From: Steven Luong Date: Thu, 10 Oct 2019 18:36:41 +0000 (-0700) Subject: bonding: graph node running after bond-input in feature arc may crash X-Git-Tag: v20.05-rc0~610 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=71e5b4710258376873c62428cb4a81b2a650fc26 bonding: graph node running after bond-input in feature arc may crash In bond RX quad loop, when all packets within the frame have the same incoming interface, we cannot skip calling bond_update_next because that function calls vnet_feature_next() to update the b->current_config_index. The next node needs the correct b->current_config_index to work with. Type: fix Signed-off-by: Steven Luong Change-Id: I3d8b3d4e0f95490f406fae7638f0c43c301ce664 --- diff --git a/src/vnet/bonding/node.c b/src/vnet/bonding/node.c index ce5aefab2fd..9f6579cda89 100644 --- a/src/vnet/bonding/node.c +++ b/src/vnet/bonding/node.c @@ -142,11 +142,13 @@ bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node, slave_if_t *sif; bond_if_t *bif; + *next_index = BOND_INPUT_NEXT_DROP; + *error = 0; + if (PREDICT_TRUE (*last_slave_sw_if_index == slave_sw_if_index)) - return; + goto next; *last_slave_sw_if_index = slave_sw_if_index; - *next_index = BOND_INPUT_NEXT_DROP; sif = bond_get_slave_by_sw_if_index (slave_sw_if_index); ASSERT (sif); @@ -163,10 +165,24 @@ bond_update_next (vlib_main_t * vm, vlib_node_runtime_t * node, } *bond_sw_if_index = bif->sw_if_index; - *error = 0; + +next: vnet_feature_next (next_index, b); } +static_always_inline void +bond_update_next_x4 (vlib_buffer_t * b0, vlib_buffer_t * b1, + vlib_buffer_t * b2, vlib_buffer_t * b3) +{ + u32 tmp0, tmp1, tmp2, tmp3; + + tmp0 = tmp1 = tmp2 = tmp3 = BOND_INPUT_NEXT_DROP; + vnet_feature_next (&tmp0, b0); + vnet_feature_next (&tmp1, b1); + vnet_feature_next (&tmp2, b2); + vnet_feature_next (&tmp3, b3); +} + VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -223,6 +239,22 @@ VLIB_NODE_FN (bond_input_node) (vlib_main_t * vm, if (PREDICT_TRUE (x == 0)) { + /* + * Optimize to call update_next only if there is a feature arc + * after bond-input. Test feature count greater than 1 because + * bond-input itself is a feature arc for this slave interface. + */ + ASSERT ((vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[1])->feature_arc_index) && + (vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[2])->feature_arc_index) && + (vnet_buffer (b[0])->feature_arc_index == + vnet_buffer (b[3])->feature_arc_index)); + if (PREDICT_FALSE (vnet_get_feature_count + (vnet_buffer (b[0])->feature_arc_index, + last_slave_sw_if_index) > 1)) + bond_update_next_x4 (b[0], b[1], b[2], b[3]); + next[0] = next[1] = next[2] = next[3] = next_index; if (next_index == BOND_INPUT_NEXT_DROP) { diff --git a/src/vnet/feature/feature.h b/src/vnet/feature/feature.h index 2d1569b8cec..6e3401897f4 100644 --- a/src/vnet/feature/feature.h +++ b/src/vnet/feature/feature.h @@ -219,6 +219,13 @@ vnet_feature_enable_disable (const char *arc_name, const char *node_name, void *feature_config, u32 n_feature_config_bytes); +static_always_inline u32 +vnet_get_feature_count (u8 arc, u32 sw_if_index) +{ + vnet_feature_main_t *fm = &feature_main; + return (fm->feature_count_by_sw_if_index[arc][sw_if_index]); +} + static inline vnet_feature_config_main_t * vnet_get_feature_arc_config_main (u8 arc_index) {