linux-cp: Fix looping netlink messages
Signal when consuming a batch of netlink messages, in order to inhibit lcp_sync from generating new netlink messages. This avoids link up/down state changess from triggering an infinite loop. Do this in the regular case of nl_route_process_msgs() and in the special case of re-synchronizing in lcp_nl_recv_dump_replies(). Type: fix Change-Id: I419d3f9aa350c119b3778b644c65165cb4cc1bef Signed-off-by: Pim van Pelt <pim@ipng.nl>
This commit is contained in:

committed by
Matthew Smith

parent
2fa69effc8
commit
2c9b128e1b
@@ -145,6 +145,22 @@ lcp_get_del_dynamic_on_link_down (void)
|
|||||||
return lcpm->del_dynamic_on_link_down;
|
return lcpm->del_dynamic_on_link_down;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
lcp_set_netlink_processing_active (u8 is_processing)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
lcpm->netlink_processing_active = (is_processing != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8
|
||||||
|
lcp_get_netlink_processing_active (void)
|
||||||
|
{
|
||||||
|
lcp_main_t *lcpm = &lcp_main;
|
||||||
|
|
||||||
|
return lcpm->netlink_processing_active;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fd.io coding-style-patch-verification: ON
|
* fd.io coding-style-patch-verification: ON
|
||||||
*
|
*
|
||||||
|
@@ -29,6 +29,8 @@ typedef struct lcp_main_s
|
|||||||
u8 del_static_on_link_down; /* Delete static routes when link goes down */
|
u8 del_static_on_link_down; /* Delete static routes when link goes down */
|
||||||
u8 del_dynamic_on_link_down; /* Delete dynamic routes when link goes down */
|
u8 del_dynamic_on_link_down; /* Delete dynamic routes when link goes down */
|
||||||
u8 test_mode; /* Set when Unit testing */
|
u8 test_mode; /* Set when Unit testing */
|
||||||
|
u8 netlink_processing_active; /* Set while a batch of Netlink messages are
|
||||||
|
being processed */
|
||||||
} lcp_main_t;
|
} lcp_main_t;
|
||||||
|
|
||||||
extern lcp_main_t lcp_main;
|
extern lcp_main_t lcp_main;
|
||||||
@@ -52,6 +54,13 @@ u8 lcp_get_del_static_on_link_down (void);
|
|||||||
void lcp_set_del_dynamic_on_link_down (u8 is_del);
|
void lcp_set_del_dynamic_on_link_down (u8 is_del);
|
||||||
u8 lcp_get_del_dynamic_on_link_down (void);
|
u8 lcp_get_del_dynamic_on_link_down (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get/Set when we're processing a batch of netlink messages.
|
||||||
|
* This is used to avoid looping messages between lcp-sync and netlink.
|
||||||
|
*/
|
||||||
|
void lcp_set_netlink_processing_active (u8 is_processing);
|
||||||
|
u8 lcp_get_netlink_processing_active (void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -37,7 +37,7 @@ lcp_itf_pair_sync_state (lcp_itf_pair_t *lip)
|
|||||||
u32 mtu;
|
u32 mtu;
|
||||||
u32 netlink_mtu;
|
u32 netlink_mtu;
|
||||||
|
|
||||||
if (!lcp_sync ())
|
if (!lcp_sync () || lcp_get_netlink_processing_active ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sw =
|
sw =
|
||||||
@@ -176,7 +176,7 @@ lcp_itf_admin_state_change (vnet_main_t *vnm, u32 sw_if_index, u32 flags)
|
|||||||
vnet_hw_interface_t *hi;
|
vnet_hw_interface_t *hi;
|
||||||
vnet_sw_interface_t *si;
|
vnet_sw_interface_t *si;
|
||||||
|
|
||||||
if (!lcp_sync ())
|
if (!lcp_sync () || lcp_get_netlink_processing_active ())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
LCP_ITF_PAIR_DBG ("admin_state_change: sw %U %u",
|
LCP_ITF_PAIR_DBG ("admin_state_change: sw %U %u",
|
||||||
@@ -223,7 +223,8 @@ lcp_itf_mtu_change (vnet_main_t *vnm, u32 sw_if_index, u32 flags)
|
|||||||
{
|
{
|
||||||
vnet_sw_interface_t *si;
|
vnet_sw_interface_t *si;
|
||||||
vnet_hw_interface_t *hi;
|
vnet_hw_interface_t *hi;
|
||||||
if (!lcp_sync ())
|
|
||||||
|
if (!lcp_sync () || lcp_get_netlink_processing_active ())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
LCP_ITF_PAIR_DBG ("mtu_change: sw %U %u", format_vnet_sw_if_index_name, vnm,
|
LCP_ITF_PAIR_DBG ("mtu_change: sw %U %u", format_vnet_sw_if_index_name, vnm,
|
||||||
@@ -271,7 +272,7 @@ lcp_itf_ip4_add_del_interface_addr (ip4_main_t *im, uword opaque,
|
|||||||
int curr_ns_fd = -1;
|
int curr_ns_fd = -1;
|
||||||
int vif_ns_fd = -1;
|
int vif_ns_fd = -1;
|
||||||
|
|
||||||
if (!lcp_sync ())
|
if (!lcp_sync () || lcp_get_netlink_processing_active ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LCP_ITF_PAIR_DBG ("ip4_addr_%s: si:%U %U/%u", is_del ? "del" : "add",
|
LCP_ITF_PAIR_DBG ("ip4_addr_%s: si:%U %U/%u", is_del ? "del" : "add",
|
||||||
@@ -320,7 +321,7 @@ lcp_itf_ip6_add_del_interface_addr (ip6_main_t *im, uword opaque,
|
|||||||
int curr_ns_fd = -1;
|
int curr_ns_fd = -1;
|
||||||
int vif_ns_fd = -1;
|
int vif_ns_fd = -1;
|
||||||
|
|
||||||
if (!lcp_sync ())
|
if (!lcp_sync () || lcp_get_netlink_processing_active ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LCP_ITF_PAIR_DBG ("ip6_addr_%s: si:%U %U/%u", is_del ? "del" : "add",
|
LCP_ITF_PAIR_DBG ("ip6_addr_%s: si:%U %U/%u", is_del ? "del" : "add",
|
||||||
|
@@ -77,6 +77,8 @@ lcp_mpls_sync_state_cb (struct mpls_main_t *mm, uword opaque, u32 sw_if_index,
|
|||||||
format_lcp_itf_pair, lip);
|
format_lcp_itf_pair, lip);
|
||||||
|
|
||||||
// If syncing is enabled, sync Linux state as well.
|
// If syncing is enabled, sync Linux state as well.
|
||||||
|
// This can happen regardless of lcp_get_netlink_processing_active(),
|
||||||
|
// provided it does not generate Netlink messages.
|
||||||
if (!lcp_sync ())
|
if (!lcp_sync ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@@ -348,6 +348,8 @@ nl_route_process_msgs (void)
|
|||||||
nl_msg_info_t *msg_info;
|
nl_msg_info_t *msg_info;
|
||||||
int err, n_msgs = 0;
|
int err, n_msgs = 0;
|
||||||
|
|
||||||
|
lcp_set_netlink_processing_active (1);
|
||||||
|
|
||||||
/* process a batch of messages. break if we hit our limit */
|
/* process a batch of messages. break if we hit our limit */
|
||||||
vec_foreach (msg_info, nm->nl_msg_queue)
|
vec_foreach (msg_info, nm->nl_msg_queue)
|
||||||
{
|
{
|
||||||
@@ -365,6 +367,8 @@ nl_route_process_msgs (void)
|
|||||||
|
|
||||||
NL_DBG ("Processed %u messages", n_msgs);
|
NL_DBG ("Processed %u messages", n_msgs);
|
||||||
|
|
||||||
|
lcp_set_netlink_processing_active (0);
|
||||||
|
|
||||||
return n_msgs;
|
return n_msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,10 +445,15 @@ lcp_nl_recv_dump_replies (nl_sock_type_t sock_type, int msg_limit,
|
|||||||
int done = 0;
|
int done = 0;
|
||||||
int n_msgs = 0;
|
int n_msgs = 0;
|
||||||
|
|
||||||
|
lcp_set_netlink_processing_active (1);
|
||||||
|
|
||||||
continue_reading:
|
continue_reading:
|
||||||
n_bytes = nl_recv (sk_route, &nla, &buf, /* creds */ NULL);
|
n_bytes = nl_recv (sk_route, &nla, &buf, /* creds */ NULL);
|
||||||
if (n_bytes <= 0)
|
if (n_bytes <= 0)
|
||||||
return n_bytes;
|
{
|
||||||
|
lcp_set_netlink_processing_active (0);
|
||||||
|
return n_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
hdr = (struct nlmsghdr *) buf;
|
hdr = (struct nlmsghdr *) buf;
|
||||||
while (nlmsg_ok (hdr, n_bytes))
|
while (nlmsg_ok (hdr, n_bytes))
|
||||||
@@ -521,6 +530,8 @@ continue_reading:
|
|||||||
goto continue_reading;
|
goto continue_reading;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
lcp_set_netlink_processing_active (0);
|
||||||
|
|
||||||
nlmsg_free (msg);
|
nlmsg_free (msg);
|
||||||
free (buf);
|
free (buf);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user