From 4850a6b12feddf6576d3fd55f18663de8a896ed9 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Thu, 22 Feb 2024 14:19:49 +0100 Subject: [PATCH] vrrp: fix vmac creation issue due a race condition The VMAC interface sometimes does not reappear when its associated link interface is quickly re-added after being deleted, a situation caused by a race condition. This problem manifests during the operations of cleanup_lost_interface() This function checks for VMAC interfaces on top of the removed link interface. It deletes these VMAC interfaces if they are present. Subsequently, Netlink is invoked to refresh the information of all interfaces, and this is followed by the cleaning of the link interface data in memory. The problem occurs when Netlink, queried within cleanup_lost_interface(), detects that the link interface has reappeared. Although the interface data in memory is updated accordingly, cleanup_lost_interface() unconditionally clears this refreshed information. As a result, the data regarding the link interface is lost, preventing the re-creation of its associated VMAC interfaces. Fix the VMAC creation issue by adding a 'cleaning flag' that is set at the start of the cleanup process. This flag says whether to proceed with the interface data cleanup. If the interface is refreshed during the Netlink polling, the flag is unset, thereby preventing the subsequent clearing of the updated interface information. Signed-off-by: Louis Scalbert --- keepalived/core/keepalived_netlink.c | 2 ++ keepalived/include/vrrp_if.h | 1 + keepalived/vrrp/vrrp_if.c | 12 ++++++++++++ 3 files changed, 15 insertions(+) diff --git a/keepalived/core/keepalived_netlink.c b/keepalived/core/keepalived_netlink.c index 0f95cbfb3c..3582dee043 100644 --- a/keepalived/core/keepalived_netlink.c +++ b/keepalived/core/keepalived_netlink.c @@ -1978,6 +1978,8 @@ netlink_if_link_populate(interface_t *ifp, struct rtattr *tb[], struct ifinfomsg #endif /* _HAVE_VRF_ */ ifp->rp_filter = UINT_MAX; /* We have not read it yet */ + + ifp->cleaning = false; #endif /* _HAVE_VRRP_VMAC_ */ ifp->ifi_flags = ifi->ifi_flags; diff --git a/keepalived/include/vrrp_if.h b/keepalived/include/vrrp_if.h index 0ee5bb7576..248b09cfc6 100644 --- a/keepalived/include/vrrp_if.h +++ b/keepalived/include/vrrp_if.h @@ -161,6 +161,7 @@ typedef struct _interface { otherwise the physical interface */ bool is_ours; /* keepalived created the interface */ bool deleting; /* Set when we are deleting the interface */ + bool cleaning; /* Set when we are cleaning the interface */ bool seen_interface; /* The interface has existed at some point since we started */ bool changeable_type; /* The interface type or underlying interface can be changed */ #ifdef _HAVE_VRF_ diff --git a/keepalived/vrrp/vrrp_if.c b/keepalived/vrrp/vrrp_if.c index f9bde8dbae..60befa04d6 100644 --- a/keepalived/vrrp/vrrp_if.c +++ b/keepalived/vrrp/vrrp_if.c @@ -1394,6 +1394,11 @@ cleanup_lost_interface(interface_t *ifp) tracking_obj_t *top; vrrp_t *vrrp; +#ifdef _HAVE_VRRP_VMAC_ + ifp->cleaning = true; +#endif /* _HAVE_VRRP_VMAC_ */ + + list_for_each_entry(top, &ifp->tracking_vrrp, e_list) { vrrp = top->obj.vrrp; @@ -1476,12 +1481,19 @@ cleanup_lost_interface(interface_t *ifp) interface_down(ifp); +#ifdef _HAVE_VRRP_VMAC_ + if (!ifp->cleaning) + /* interface has been refreshed. Do not clean */ + return; +#endif /* _HAVE_VRRP_VMAC_ */ + ifp->ifindex = 0; ifp->ifi_flags = 0; ifp->seen_up = false; #ifdef _HAVE_VRRP_VMAC_ if (!ifp->is_ours) ifp->base_ifp = ifp; + ifp->cleaning = false; #endif #ifdef _HAVE_VRF_ ifp->vrf_master_ifp = NULL;