NAT: fixed hairpinning for in2out translation as an output feature (VPP-976) 73/8373/1
authorMatus Fabian <matfabia@cisco.com>
Mon, 11 Sep 2017 05:17:47 +0000 (22:17 -0700)
committerMatus Fabian <matfabia@cisco.com>
Mon, 11 Sep 2017 05:17:47 +0000 (22:17 -0700)
Test whether the hairpinning flag is set only for packets from NAT inside interface.

Change-Id: I4a4fdd2084a76a70ce9dfe3e2b8332c02fa2eccd
Signed-off-by: Matus Fabian <matfabia@cisco.com>
src/plugins/nat/in2out.c
test/test_nat.py

index c51d4fb..efb3856 100644 (file)
@@ -3412,6 +3412,8 @@ snat_hairpin_src_fn (vlib_main_t * vm,
           u32 bi0;
          vlib_buffer_t * b0;
           u32 next0;
+          snat_interface_t *i;
+          u32 sw_if_index0;
 
           /* speculatively enqueue b0 to the current next frame */
          bi0 = from[0];
@@ -3422,15 +3424,25 @@ snat_hairpin_src_fn (vlib_main_t * vm,
          n_left_to_next -= 1;
 
          b0 = vlib_get_buffer (vm, bi0);
+          sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
           next0 = SNAT_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT;
 
-          if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) & SNAT_FLAG_HAIRPINNING))
-            {
-              if (PREDICT_TRUE (sm->num_workers > 1))
-                next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
-              else
-                next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
-            }
+          pool_foreach (i, sm->output_feature_interfaces,
+          ({
+            /* Only packets from NAT inside interface */
+            if ((i->is_inside == 1) && (sw_if_index0 == i->sw_if_index))
+              {
+                if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
+                                    SNAT_FLAG_HAIRPINNING))
+                  {
+                    if (PREDICT_TRUE (sm->num_workers > 1))
+                      next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH;
+                    else
+                      next0 = SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT;
+                  }
+                break;
+              }
+          }));
 
           pkts_processed += next0 != SNAT_IN2OUT_NEXT_DROP;
 
index de07019..1f2d17a 100644 (file)
@@ -2221,25 +2221,34 @@ class TestNAT44(MethodHolder):
         """ NAT44 interface output feature (in2out postrouting) """
         self.nat44_add_address(self.nat_addr)
         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
-        self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
+        self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
+        self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
                                                          is_inside=0)
 
         # in2out
-        pkts = self.create_stream_in(self.pg0, self.pg1)
+        pkts = self.create_stream_in(self.pg0, self.pg3)
         self.pg0.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
-        capture = self.pg1.get_capture(len(pkts))
+        capture = self.pg3.get_capture(len(pkts))
         self.verify_capture_out(capture)
 
         # out2in
-        pkts = self.create_stream_out(self.pg1)
-        self.pg1.add_stream(pkts)
+        pkts = self.create_stream_out(self.pg3)
+        self.pg3.add_stream(pkts)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
         capture = self.pg0.get_capture(len(pkts))
         self.verify_capture_in(capture, self.pg0)
 
+        # from non-NAT interface to NAT inside interface
+        pkts = self.create_stream_in(self.pg2, self.pg0)
+        self.pg2.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg0.get_capture(len(pkts))
+        self.verify_capture_no_translation(capture, self.pg2, self.pg0)
+
     def test_output_feature_vrf_aware(self):
         """ NAT44 interface output feature VRF aware (in2out postrouting) """
         nat_ip_vrf10 = "10.0.0.10"