diff options
author | Neale Ranns <nranns@cisco.com> | 2016-11-21 12:25:22 +0000 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2016-11-21 14:18:09 +0000 |
commit | 8b37b8732d5f9883ab594fc0ba2b5be21c27c4fd (patch) | |
tree | 5cf5accc899d67e874fecdb14150e1bacdec211e /vnet/vnet/adj/adj_nbr.c | |
parent | c008ee186b13a1246f265372679f5a80970387b5 (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.c | 99 |
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, |