aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/adj/adj_nbr.c
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2016-11-21 12:25:22 +0000
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-21 14:18:09 +0000
commit8b37b8732d5f9883ab594fc0ba2b5be21c27c4fd (patch)
tree5cf5accc899d67e874fecdb14150e1bacdec211e /vnet/vnet/adj/adj_nbr.c
parentc008ee186b13a1246f265372679f5a80970387b5 (diff)
Convergence Improvements
addressing convergence times when interface is shut. 1) prioritise the registered callback handlers. Add FIB convergence handler as high priority 2) hook the FIB convergence call-back into HW link down. 3) don't schedule a walk of a FIB node if it has no children 4) Checks at fib_path_t to prevent unnecessary walks, that it prevent the same information propagting the graph multiple times. Change-Id: I406966b50f31d77c221821b8649776d66655194c Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'vnet/vnet/adj/adj_nbr.c')
-rw-r--r--vnet/vnet/adj/adj_nbr.c99
1 files changed, 87 insertions, 12 deletions
diff --git a/vnet/vnet/adj/adj_nbr.c b/vnet/vnet/adj/adj_nbr.c
index 4245990585e..1a78ecbc49f 100644
--- a/vnet/vnet/adj/adj_nbr.c
+++ b/vnet/vnet/adj/adj_nbr.c
@@ -604,30 +604,47 @@ adj_nbr_walk_nh (u32 sw_if_index,
}
/**
+ * Flags associated with the interface state walks
+ */
+typedef enum adj_nbr_interface_flags_t_
+{
+ ADJ_NBR_INTERFACE_UP = (1 << 0),
+} adj_nbr_interface_flags_t;
+
+/**
* Context for the state change walk of the DB
*/
typedef struct adj_nbr_interface_state_change_ctx_t_
{
/**
- * Flags passed from the vnet notifiy function
+ * Flags on the interface
*/
- int flags;
+ adj_nbr_interface_flags_t flags;
} adj_nbr_interface_state_change_ctx_t;
static adj_walk_rc_t
adj_nbr_interface_state_change_one (adj_index_t ai,
- void *arg)
+ void *arg)
{
/*
* Back walk the graph to inform the forwarding entries
- * that this interface state has changed.
+ * that this interface state has changed. Do this synchronously
+ * since this is the walk that provides convergence
*/
adj_nbr_interface_state_change_ctx_t *ctx = arg;
fib_node_back_walk_ctx_t bw_ctx = {
- .fnbw_reason = (ctx->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ?
- FIB_NODE_BW_REASON_FLAG_INTERFACE_UP :
- FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN),
+ .fnbw_reason = ((ctx->flags & ADJ_NBR_INTERFACE_UP) ?
+ FIB_NODE_BW_REASON_FLAG_INTERFACE_UP :
+ FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN),
+ /*
+ * the force sync applies only as far as the first fib_entry.
+ * And it's the fib_entry's we need to converge away from
+ * the adjacencies on the now down link
+ */
+ .fnbw_flags = (!(ctx->flags & ADJ_NBR_INTERFACE_UP) ?
+ FIB_NODE_BW_FLAG_FORCE_SYNC :
+ 0),
};
fib_walk_sync(FIB_NODE_TYPE_ADJ, ai, &bw_ctx);
@@ -635,10 +652,13 @@ adj_nbr_interface_state_change_one (adj_index_t ai,
return (ADJ_WALK_RC_CONTINUE);
}
+/**
+ * @brief Registered function for SW interface state changes
+ */
static clib_error_t *
-adj_nbr_interface_state_change (vnet_main_t * vnm,
- u32 sw_if_index,
- u32 flags)
+adj_nbr_sw_interface_state_change (vnet_main_t * vnm,
+ u32 sw_if_index,
+ u32 flags)
{
fib_protocol_t proto;
@@ -648,7 +668,9 @@ adj_nbr_interface_state_change (vnet_main_t * vnm,
for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
{
adj_nbr_interface_state_change_ctx_t ctx = {
- .flags = flags,
+ .flags = ((flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) ?
+ ADJ_NBR_INTERFACE_UP :
+ 0),
};
adj_nbr_walk(sw_if_index, proto,
@@ -659,7 +681,60 @@ adj_nbr_interface_state_change (vnet_main_t * vnm,
return (NULL);
}
-VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_nbr_interface_state_change);
+VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION_PRIO(
+ adj_nbr_sw_interface_state_change,
+ VNET_ITF_FUNC_PRIORITY_HIGH);
+
+/**
+ * @brief Invoked on each SW interface of a HW interface when the
+ * HW interface state changes
+ */
+static void
+adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm,
+ u32 sw_if_index,
+ void *arg)
+{
+ adj_nbr_interface_state_change_ctx_t *ctx = arg;
+ fib_protocol_t proto;
+
+ /*
+ * walk each adj on the interface and trigger a walk from that adj
+ */
+ for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++)
+ {
+ adj_nbr_walk(sw_if_index, proto,
+ adj_nbr_interface_state_change_one,
+ ctx);
+ }
+}
+
+/**
+ * @brief Registered callback for HW interface state changes
+ */
+static clib_error_t *
+adj_nbr_hw_interface_state_change (vnet_main_t * vnm,
+ u32 hw_if_index,
+ u32 flags)
+{
+ /*
+ * walk SW interface on the HW
+ */
+ adj_nbr_interface_state_change_ctx_t ctx = {
+ .flags = ((flags & VNET_HW_INTERFACE_FLAG_LINK_UP) ?
+ ADJ_NBR_INTERFACE_UP :
+ 0),
+ };
+
+ vnet_hw_interface_walk_sw(vnm, hw_if_index,
+ adj_nbr_hw_sw_interface_state_change,
+ &ctx);
+
+ return (NULL);
+}
+
+VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION_PRIO(
+ adj_nbr_hw_interface_state_change,
+ VNET_ITF_FUNC_PRIORITY_HIGH);
static adj_walk_rc_t
adj_nbr_interface_delete_one (adj_index_t ai,