summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2018-10-02 07:27:02 -0700
committerJohn Lo <loj@cisco.com>2018-10-10 13:55:34 +0000
commitb9fa29d513bfad0d9f18e8ed8c2da3feaa6d3bf0 (patch)
tree939c83656daca8de0ee0a5b2a292f7750e4d44ba
parent997439170aa3bb562c84e882c45331ba476e7c8e (diff)
L2-flood: no clone for 1 replication
Change-Id: If178dd38e7920f35588f5d821ff097168b078026 Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/vnet/l2/l2_flood.c128
-rw-r--r--test/test_l2_flood.py33
2 files changed, 102 insertions, 59 deletions
diff --git a/src/vnet/l2/l2_flood.c b/src/vnet/l2/l2_flood.c
index 97a4ff59da7..8908c4312d3 100644
--- a/src/vnet/l2/l2_flood.c
+++ b/src/vnet/l2/l2_flood.c
@@ -209,77 +209,87 @@ l2flood_node_fn (vlib_main_t * vm,
bi0, L2FLOOD_NEXT_DROP);
continue;
}
-
- vec_validate (msm->clones[thread_index], n_clones);
- vec_reset_length (msm->clones[thread_index]);
-
- /*
- * the header offset needs to be large enough to incorporate
- * all the L3 headers that could be touched when doing BVI
- * processing. So take the current l2 length plus 2 * IPv6
- * headers (for tunnel encap)
- */
- n_cloned = vlib_buffer_clone (vm, bi0,
- msm->clones[thread_index],
- n_clones,
- (vnet_buffer (b0)->l2.l2_len +
- sizeof (udp_header_t) +
- 2 * sizeof (ip6_header_t)));
-
- if (PREDICT_FALSE (n_cloned != n_clones))
+ else if (n_clones > 1)
{
- b0->error = node->errors[L2FLOOD_ERROR_REPL_FAIL];
- }
+ vec_validate (msm->clones[thread_index], n_clones);
+ vec_reset_length (msm->clones[thread_index]);
+
+ /*
+ * the header offset needs to be large enough to incorporate
+ * all the L3 headers that could be touched when doing BVI
+ * processing. So take the current l2 length plus 2 * IPv6
+ * headers (for tunnel encap)
+ */
+ n_cloned = vlib_buffer_clone (vm, bi0,
+ msm->clones[thread_index],
+ n_clones,
+ (vnet_buffer (b0)->l2.l2_len +
+ sizeof (udp_header_t) +
+ 2 * sizeof (ip6_header_t)));
+
+ if (PREDICT_FALSE (n_cloned != n_clones))
+ {
+ b0->error = node->errors[L2FLOOD_ERROR_REPL_FAIL];
+ }
- /*
- * for all but the last clone, these are not BVI bound
- */
- for (clone0 = 0; clone0 < n_cloned - 1; clone0++)
- {
- member = msm->members[thread_index][clone0];
- ci0 = msm->clones[thread_index][clone0];
- c0 = vlib_get_buffer (vm, ci0);
+ /*
+ * for all but the last clone, these are not BVI bound
+ */
+ for (clone0 = 0; clone0 < n_cloned - 1; clone0++)
+ {
+ member = msm->members[thread_index][clone0];
+ ci0 = msm->clones[thread_index][clone0];
+ c0 = vlib_get_buffer (vm, ci0);
- to_next[0] = ci0;
- to_next += 1;
- n_left_to_next -= 1;
+ to_next[0] = ci0;
+ to_next += 1;
+ n_left_to_next -= 1;
- if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
- (b0->flags & VLIB_BUFFER_IS_TRACED)))
- {
- ethernet_header_t *h0;
- l2flood_trace_t *t;
-
- if (c0 != b0)
- vlib_buffer_copy_trace_flag (vm, b0, ci0);
-
- t = vlib_add_trace (vm, node, c0, sizeof (*t));
- h0 = vlib_buffer_get_current (c0);
- t->sw_if_index = sw_if_index0;
- t->bd_index = vnet_buffer (c0)->l2.bd_index;
- clib_memcpy (t->src, h0->src_address, 6);
- clib_memcpy (t->dst, h0->dst_address, 6);
- }
+ if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+ (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ ethernet_header_t *h0;
+ l2flood_trace_t *t;
+
+ if (c0 != b0)
+ vlib_buffer_copy_trace_flag (vm, b0, ci0);
+
+ t = vlib_add_trace (vm, node, c0, sizeof (*t));
+ h0 = vlib_buffer_get_current (c0);
+ t->sw_if_index = sw_if_index0;
+ t->bd_index = vnet_buffer (c0)->l2.bd_index;
+ clib_memcpy (t->src, h0->src_address, 6);
+ clib_memcpy (t->dst, h0->dst_address, 6);
+ }
- /* Do normal L2 forwarding */
- vnet_buffer (c0)->sw_if_index[VLIB_TX] = member->sw_if_index;
+ /* Do normal L2 forwarding */
+ vnet_buffer (c0)->sw_if_index[VLIB_TX] =
+ member->sw_if_index;
- vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
- to_next, n_left_to_next,
- ci0, next0);
- if (PREDICT_FALSE (0 == n_left_to_next))
- {
- vlib_put_next_frame (vm, node, next_index, n_left_to_next);
- vlib_get_next_frame (vm, node, next_index,
- to_next, n_left_to_next);
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next, n_left_to_next,
+ ci0, next0);
+ if (PREDICT_FALSE (0 == n_left_to_next))
+ {
+ vlib_put_next_frame (vm, node, next_index,
+ n_left_to_next);
+ vlib_get_next_frame (vm, node, next_index, to_next,
+ n_left_to_next);
+ }
}
+ member = msm->members[thread_index][clone0];
+ ci0 = msm->clones[thread_index][clone0];
+ }
+ else
+ {
+ /* one clone */
+ ci0 = bi0;
+ member = msm->members[thread_index][0];
}
/*
* the last clone that might go to a BVI
*/
- member = msm->members[thread_index][clone0];
- ci0 = msm->clones[thread_index][clone0];
c0 = vlib_get_buffer (vm, ci0);
to_next[0] = ci0;
diff --git a/test/test_l2_flood.py b/test/test_l2_flood.py
index 50a692e57e8..8b8a3f0f960 100644
--- a/test/test_l2_flood.py
+++ b/test/test_l2_flood.py
@@ -144,6 +144,39 @@ class TestL2Flood(VppTestCase):
self.vapi.bridge_domain_add_del(1, is_add=0)
+ def test_flood_one(self):
+ """ L2 no-Flood Test """
+
+ #
+ # Create a single bridge Domain
+ #
+ self.vapi.bridge_domain_add_del(1)
+
+ #
+ # add 2 interfaces to the BD. this means a flood goes to only
+ # one member
+ #
+ for i in self.pg_interfaces[:2]:
+ self.vapi.sw_interface_set_l2_bridge(i.sw_if_index, 1, 0)
+
+ p = (Ether(dst="ff:ff:ff:ff:ff:ff",
+ src="00:00:de:ad:be:ef") /
+ IP(src="10.10.10.10", dst="1.1.1.1") /
+ UDP(sport=1234, dport=1234) /
+ Raw('\xa5' * 100))
+
+ #
+ # input on pg0 expect copies on pg1
+ #
+ self.send_and_expect(self.pg0, p*65, self.pg1)
+
+ #
+ # cleanup
+ #
+ for i in self.pg_interfaces[:2]:
+ self.vapi.sw_interface_set_l2_bridge(i.sw_if_index, 1, enable=0)
+ self.vapi.bridge_domain_add_del(1, is_add=0)
+
def test_uu_fwd(self):
""" UU Flood """