Next node frame over-flow after replication 14/5014/2
authorNeale Ranns <nranns@cisco.com>
Fri, 3 Feb 2017 12:34:01 +0000 (04:34 -0800)
committerDamjan Marion <dmarion.lists@gmail.com>
Fri, 3 Feb 2017 14:32:36 +0000 (14:32 +0000)
Change-Id: I25077dd0739787de4f7512e5a70a62e8c34c28e4
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/vnet/dpo/replicate_dpo.c
test/test_ip_mcast.py

index 8bad75e..c779516 100644 (file)
@@ -664,6 +664,20 @@ replicate_inline (vlib_main_t * vm,
             /* ship copies to the rest of the buckets */
             for (bucket = 1; bucket < rep0->rep_n_buckets; bucket++)
             {
+                /*
+                 * After the enqueue of the first buffer, and of all subsequent
+                 * buffers in this loop, it is possible that we over-flow the
+                 * frame of the to-next node. When this happens we need to 'put'
+                 * that full frame to the node and get a fresh empty one.
+                 * Note that these are macros with side effects that change
+                 * to_next & n_left_to_next
+                 */
+                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);
+                }
+
                 /* Make a copy */
                 c0 = vlib_buffer_copy(vm, b0);
                 ci0 = vlib_get_buffer_index(vm, c0);
@@ -676,9 +690,9 @@ replicate_inline (vlib_main_t * vm,
                 next0 = dpo0->dpoi_next_node;
                 vnet_buffer (c0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
 
-                if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+                if (PREDICT_FALSE(c0->flags & VLIB_BUFFER_IS_TRACED))
                 {
-                    replicate_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
+                    replicate_trace_t *t = vlib_add_trace (vm, node, c0, sizeof (*t));
                     t->rep_index = repi0;
                     t->dpo = *dpo0;
                 }
index 028853d..9b668e4 100644 (file)
@@ -29,6 +29,14 @@ class MRouteEntryFlags:
     MFIB_ENTRY_FLAG_CONNECTED = 4
     MFIB_ENTRY_FLAG_INHERIT_ACCEPT = 8
 
+#
+# The number of packets sent is set to 90 so that when we replicate more than 3
+# times, which we do for some entries, we will generate more than 256 packets
+# to the next node in the VLIB graph. Thus we are testing the code's correctness
+# handling this over-flow
+#
+N_PKTS_IN_STREAM = 90
+
 
 class TestIPMcast(VppTestCase):
     """ IP Multicast Test Case """
@@ -49,7 +57,7 @@ class TestIPMcast(VppTestCase):
 
     def create_stream_ip4(self, src_if, src_ip, dst_ip):
         pkts = []
-        for i in range(0, 65):
+        for i in range(0, N_PKTS_IN_STREAM):
             info = self.create_packet_info(src_if, src_if)
             payload = self.info_to_payload(info)
             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
@@ -62,7 +70,7 @@ class TestIPMcast(VppTestCase):
 
     def create_stream_ip6(self, src_if, src_ip, dst_ip):
         pkts = []
-        for i in range(0, 65):
+        for i in range(0, N_PKTS_IN_STREAM):
             info = self.create_packet_info(src_if, src_if)
             payload = self.info_to_payload(info)
             p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
@@ -82,7 +90,7 @@ class TestIPMcast(VppTestCase):
         return capture
 
     def verify_capture_ip4(self, src_if, sent):
-        rxd = self.pg1.get_capture(65)
+        rxd = self.pg1.get_capture(N_PKTS_IN_STREAM)
 
         try:
             capture = self.verify_filter(rxd, sent)
@@ -112,7 +120,7 @@ class TestIPMcast(VppTestCase):
             raise
 
     def verify_capture_ip6(self, src_if, sent):
-        capture = self.pg1.get_capture(65)
+        capture = self.pg1.get_capture(N_PKTS_IN_STREAM)
 
         self.assertEqual(len(capture), len(sent))