L2-flood: no clone for 1 replication 00/15100/3
authorNeale Ranns <nranns@cisco.com>
Tue, 2 Oct 2018 14:27:02 +0000 (07:27 -0700)
committerJohn Lo <loj@cisco.com>
Wed, 10 Oct 2018 13:55:34 +0000 (13:55 +0000)
Change-Id: If178dd38e7920f35588f5d821ff097168b078026
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet/l2/l2_flood.c
test/test_l2_flood.py

index 97a4ff5..8908c43 100644 (file)
@@ -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;
index 50a692e..8b8a3f0 100644 (file)
@@ -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 """