Skip to content

Commit

Permalink
vrrp: fix vmac creation issue due to race condition
Browse files Browse the repository at this point in the history
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 indirectly by sub-functions of
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 <[email protected]>
  • Loading branch information
louis-6wind committed Feb 23, 2024
1 parent 566f44b commit 0624ca4
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 0 deletions.
2 changes: 2 additions & 0 deletions keepalived/core/keepalived_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions keepalived/include/vrrp_if.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_
Expand Down
12 changes: 12 additions & 0 deletions keepalived/vrrp/vrrp_if.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 0624ca4

Please sign in to comment.