summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorSteven Luong <sluong@cisco.com>2019-10-10 11:36:41 -0700
committerDamjan Marion <dmarion@me.com>2019-10-16 18:39:14 +0000
commit71e5b4710258376873c62428cb4a81b2a650fc26 (patch)
treef26d0653980e915b0ab7560ca1bb6416c119d2e8 /src/vnet
parent94e4dea15ac704a40617fe8bcfcce74e2d890856 (diff)
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 <sluong@cisco.com> Change-Id: I3d8b3d4e0f95490f406fae7638f0c43c301ce664
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/bonding/node.c38
-rw-r--r--src/vnet/feature/feature.h7
2 files changed, 42 insertions, 3 deletions
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)
{