CGN: Send ICMP error packet if user is out of sessions available 87/6487/2
authorMartin Gálik <magalik@cisco.com>
Thu, 27 Apr 2017 09:13:26 +0000 (02:13 -0700)
committerOle Trøan <otroan@employees.org>
Thu, 27 Apr 2017 12:03:46 +0000 (12:03 +0000)
Change-Id: I19a6015fde7342588cfa9c7a4f07016aa339cc72
Signed-off-by: Martin Gálik <magalik@cisco.com>
src/plugins/snat/in2out.c
test/test_snat.py

index 4970fce..f7d29c6 100644 (file)
@@ -1635,8 +1635,13 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
                 }
               if (PREDICT_FALSE(!ses0))
                 {
-                  next0 = SNAT_IN2OUT_NEXT_DROP;
-                  b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
+                  /* too many sessions for user, send ICMP error packet */
+
+                  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+                  icmp4_error_set_vnet_buffer (b0, ICMP4_destination_unreachable,
+                                               ICMP4_destination_unreachable_destination_unreachable_host,
+                                               0);
+                  next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
                   goto trace0;
                 }
             }
@@ -1780,8 +1785,13 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
                 }
               if (PREDICT_FALSE(!ses1))
                 {
-                  next1 = SNAT_IN2OUT_NEXT_DROP;
-                  b1->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
+                  /* too many sessions for user, send ICMP error packet */
+
+                  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+                  icmp4_error_set_vnet_buffer (b1, ICMP4_destination_unreachable,
+                                               ICMP4_destination_unreachable_destination_unreachable_host,
+                                               0);
+                  next1 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
                   goto trace1;
                 }
             }
@@ -1961,8 +1971,13 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
                 }
               if (PREDICT_FALSE(!ses0))
                 {
-                  next0 = SNAT_IN2OUT_NEXT_DROP;
-                  b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS];
+                  /* too many sessions for user, send ICMP error packet */
+
+                  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
+                  icmp4_error_set_vnet_buffer (b0, ICMP4_destination_unreachable,
+                                               ICMP4_destination_unreachable_destination_unreachable_host,
+                                               0);
+                  next0 = SNAT_IN2OUT_NEXT_ICMP_ERROR;
                   goto trace00;
                 }
             }
index f90d906..da9f1b0 100644 (file)
@@ -1895,12 +1895,24 @@ class TestDeterministicNAT(MethodHolder):
 
         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
-             UDP(sport=3000, dport=3000))
+             UDP(sport=3001, dport=3002))
         self.pg0.add_stream(p)
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
         capture = self.pg1.assert_nothing_captured()
 
+        # verify ICMP error packet
+        capture = self.pg0.get_capture(1)
+        p = capture[0]
+        self.assertTrue(p.haslayer(ICMP))
+        icmp = p[ICMP]
+        self.assertEqual(icmp.type, 3)
+        self.assertEqual(icmp.code, 1)
+        self.assertTrue(icmp.haslayer(IPerror))
+        inner_ip = icmp[IPerror]
+        self.assertEqual(inner_ip[UDPerror].sport, 3001)
+        self.assertEqual(inner_ip[UDPerror].dport, 3002)
+
         dms = self.vapi.snat_det_map_dump()
 
         self.assertEqual(1000, dms[0].ses_num)