From b9fa29d513bfad0d9f18e8ed8c2da3feaa6d3bf0 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 2 Oct 2018 07:27:02 -0700 Subject: [PATCH] L2-flood: no clone for 1 replication Change-Id: If178dd38e7920f35588f5d821ff097168b078026 Signed-off-by: Neale Ranns --- src/vnet/l2/l2_flood.c | 128 ++++++++++++++++++++++++++----------------------- test/test_l2_flood.py | 33 +++++++++++++ 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 """ -- 2.16.6