From e2efecec426245163ae0abe00ca8ff368556c480 Mon Sep 17 00:00:00 2001
From: John Lo <loj@cisco.com>
Date: Wed, 23 Mar 2016 19:44:39 -0400
Subject: [PATCH] Fix L2 flood packet replication interaction with VXLAN-tunnel

The check for input sw_if_index against output sw_if_index is not correct
for the interface on the replication order after VXLAN tunnel because the
encap code overwrite packet sw_if_index[VLIB_RX] with that of the VXLAN
tunnel sw_if_index. The check should be done using sw_if_index[VLIB_RX]
saved in the packet context.

Change-Id: I175717221409977e80576e84dfe5362d1f6aed2f
Signed-off-by: John Lo <loj@cisco.com>
---
 vnet/vnet/l2/l2_flood.c | 33 ++++++++++++++++-----------------
 1 file changed, 16 insertions(+), 17 deletions(-)

diff --git a/vnet/vnet/l2/l2_flood.c b/vnet/vnet/l2/l2_flood.c
index 8a702168715..0d25f583bbb 100644
--- a/vnet/vnet/l2/l2_flood.c
+++ b/vnet/vnet/l2/l2_flood.c
@@ -131,7 +131,7 @@ l2flood_process (vlib_main_t * vm,
                  l2flood_main_t * msm,
                  u64 * counter_base,
                  vlib_buffer_t * b0,
-                 u32 sw_if_index0,
+                 u32 * sw_if_index0,
                  l2fib_entry_key_t * key0,
 		 u32 * bucket0,
                  l2fib_entry_result_t * result0,
@@ -156,7 +156,7 @@ l2flood_process (vlib_main_t * vm,
     // Find first member that passes the reflection and SHG checks
     current_member = vec_len(members) - 1;
     while ((current_member >= 0) && 
-           ((members[current_member].sw_if_index == sw_if_index0) ||
+           ((members[current_member].sw_if_index == *sw_if_index0) ||
 	    (in_shg && members[current_member].shg == in_shg))) {
       current_member--;
     }
@@ -170,7 +170,7 @@ l2flood_process (vlib_main_t * vm,
 
     if ((current_member > 0) &&
         ((current_member > 1) || 
-	 ((members[0].sw_if_index != sw_if_index0) &&
+	 ((members[0].sw_if_index != *sw_if_index0) &&
 	  (!in_shg || members[0].shg != in_shg)))) {
       // If more than one member then initiate replication
       ctx = replication_prep (vm, b0, l2flood_node.index, 1 /* l2_packet */);
@@ -179,6 +179,7 @@ l2flood_process (vlib_main_t * vm,
     }
 
   } else {
+    vnet_buffer_opaque_t *vnet_buff_op;
 
     // Do flood "recycle node" processing
 
@@ -196,9 +197,13 @@ l2flood_process (vlib_main_t * vm,
     members = (l2_flood_member_t *) ctx->feature_replicas;
     current_member = (i32)ctx->feature_counter - 1;
 
+    // Need to update input index from saved packet context
+    vnet_buff_op = (vnet_buffer_opaque_t *)ctx->vnet_buffer;
+    *sw_if_index0 = vnet_buff_op->sw_if_index[VLIB_RX];
+
     // Find next member that passes the reflection and SHG check
     while ((current_member >= 0) &&
-           ((members[current_member].sw_if_index == sw_if_index0) ||
+           ((members[current_member].sw_if_index == *sw_if_index0) ||
 	    (in_shg && members[current_member].shg == in_shg))) {
       current_member--;
     }
@@ -220,7 +225,7 @@ l2flood_process (vlib_main_t * vm,
     replication_recycle (vm, b0,
        ((current_member == 0) || /*is_last */ 
         ((current_member == 1) && 
-	 ((members[0].sw_if_index == sw_if_index0) ||
+	 ((members[0].sw_if_index == *sw_if_index0) ||
 	  (in_shg && members[0].shg == in_shg)))));
   }
 
@@ -285,7 +290,6 @@ l2flood_node_fn (vlib_main_t * vm,
 	  vlib_buffer_t * b0, * b1;
           u32 next0, next1;
           u32 sw_if_index0, sw_if_index1;
-          ethernet_header_t * h0, * h1;
           l2fib_entry_key_t key0, key1;
           l2fib_entry_result_t result0, result1;
           u32 bucket0, bucket1;
@@ -329,25 +333,21 @@ l2flood_node_fn (vlib_main_t * vm,
           sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
           sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
 
-          /* Process 2 x pkts */
-
-          h0 = vlib_buffer_get_current (b0);
-          h1 = vlib_buffer_get_current (b1);
-
             /* process 2 pkts */
             em->counters[node_counter_base_index + L2FLOOD_ERROR_L2FLOOD] += 2;
 
             l2flood_process (vm, node, msm, &em->counters[node_counter_base_index],
-                             b0, sw_if_index0, &key0, &bucket0, &result0, &next0);
+                             b0, &sw_if_index0, &key0, &bucket0, &result0, &next0);
 
             l2flood_process (vm, node, msm, &em->counters[node_counter_base_index],
-                             b1, sw_if_index1, &key1, &bucket1, &result1, &next1);
+                             b1, &sw_if_index1, &key1, &bucket1, &result1, &next1);
 
           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
             {          
               if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
                 {
                   l2flood_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
+		  ethernet_header_t * h0 = vlib_buffer_get_current (b0); 
                   t->sw_if_index = sw_if_index0;
                   t->bd_index = vnet_buffer(b0)->l2.bd_index;
                   memcpy(t->src, h0->src_address, 6);
@@ -356,6 +356,7 @@ l2flood_node_fn (vlib_main_t * vm,
               if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
                 {
                   l2flood_trace_t *t = vlib_add_trace (vm, node, b1, sizeof (*t));
+		  ethernet_header_t * h1 = vlib_buffer_get_current (b1); 
                   t->sw_if_index = sw_if_index1;
                   t->bd_index = vnet_buffer(b1)->l2.bd_index;
                   memcpy(t->src, h1->src_address, 6);
@@ -376,7 +377,6 @@ l2flood_node_fn (vlib_main_t * vm,
 	  vlib_buffer_t * b0;
           u32 next0;
           u32 sw_if_index0;
-          ethernet_header_t * h0;
           l2fib_entry_key_t key0;
           l2fib_entry_result_t result0;
           u32 bucket0;
@@ -393,18 +393,17 @@ l2flood_node_fn (vlib_main_t * vm,
 
           sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
  
-          h0 = vlib_buffer_get_current (b0);
-
           /* process 1 pkt */
           em->counters[node_counter_base_index + L2FLOOD_ERROR_L2FLOOD] += 1;
 
           l2flood_process (vm, node, msm, &em->counters[node_counter_base_index],
-                           b0, sw_if_index0, &key0, &bucket0, &result0, &next0);
+                           b0, &sw_if_index0, &key0, &bucket0, &result0, &next0);
 
           if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) &&
                             (b0->flags & VLIB_BUFFER_IS_TRACED)))
             {
               l2flood_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
+	      ethernet_header_t * h0 = vlib_buffer_get_current (b0); 
               t->sw_if_index = sw_if_index0;
               t->bd_index = vnet_buffer(b0)->l2.bd_index;
               memcpy(t->src, h0->src_address, 6);