Handle multiple flows with the same client port in deterministic NAT 18/6118/4
authorJuraj Sloboda <jsloboda@cisco.com>
Wed, 5 Apr 2017 13:59:21 +0000 (15:59 +0200)
committerDamjan Marion <dmarion.lists@gmail.com>
Wed, 12 Apr 2017 17:17:18 +0000 (17:17 +0000)
Handle situation when client tries to connect to multiple hosts/ports
from the same client port. Extend matching to include remote host/port
when searching for existing session and create session for each flow
even when originating from the same client port.

Change-Id: I4f54ded930e59e7196843c6bc1d2d2386c57cd3c
Signed-off-by: Juraj Sloboda <jsloboda@cisco.com>
src/plugins/snat/in2out.c
src/plugins/snat/snat_det.h

index 1e8e144..5a2e2b7 100644 (file)
@@ -1613,11 +1613,12 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
 
           snat_det_forward(dm0, &ip0->src_address, &new_addr0, &lo_port0);
 
-          ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src);
+          key0.ext_host_addr = ip0->dst_address;
+          key0.ext_host_port = tcp0->dst;
+
+          ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src, key0);
           if (PREDICT_FALSE(!ses0))
             {
-              key0.ext_host_addr = ip0->dst_address;
-              key0.ext_host_port = tcp0->dst;
               for (i0 = 0; i0 < dm0->ports_per_host; i0++)
                 {
                   key0.out_port = clib_host_to_net_u16 (lo_port0 +
@@ -1757,11 +1758,12 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
 
           snat_det_forward(dm1, &ip1->src_address, &new_addr1, &lo_port1);
 
-          ses1 = snat_det_find_ses_by_in(dm1, &ip1->src_address, tcp1->src);
+          key1.ext_host_addr = ip1->dst_address;
+          key1.ext_host_port = tcp1->dst;
+
+          ses1 = snat_det_find_ses_by_in(dm1, &ip1->src_address, tcp1->src, key1);
           if (PREDICT_FALSE(!ses1))
             {
-              key1.ext_host_addr = ip1->dst_address;
-              key1.ext_host_port = tcp1->dst;
               for (i1 = 0; i1 < dm1->ports_per_host; i1++)
                 {
                   key1.out_port = clib_host_to_net_u16 (lo_port1 +
@@ -1937,11 +1939,12 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
 
           snat_det_forward(dm0, &ip0->src_address, &new_addr0, &lo_port0);
 
-          ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src);
+          key0.ext_host_addr = ip0->dst_address;
+          key0.ext_host_port = tcp0->dst;
+
+          ses0 = snat_det_find_ses_by_in(dm0, &ip0->src_address, tcp0->src, key0);
           if (PREDICT_FALSE(!ses0))
             {
-              key0.ext_host_addr = ip0->dst_address;
-              key0.ext_host_port = tcp0->dst;
               for (i0 = 0; i0 < dm0->ports_per_host; i0++)
                 {
                   key0.out_port = clib_host_to_net_u16 (lo_port0 +
@@ -2171,7 +2174,10 @@ u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node,
 
   snat_det_forward(dm0, &in_addr, &new_addr0, &lo_port0);
 
-  ses0 = snat_det_find_ses_by_in(dm0, &in_addr, in_port);
+  key0.ext_host_addr = ip0->dst_address;
+  key0.ext_host_port = 0;
+
+  ses0 = snat_det_find_ses_by_in(dm0, &in_addr, in_port, key0);
   if (PREDICT_FALSE(!ses0))
     {
       if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0,
@@ -2186,8 +2192,6 @@ u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node,
           next0 = SNAT_IN2OUT_NEXT_DROP;
           goto out;
         }
-      key0.ext_host_addr = ip0->dst_address;
-      key0.ext_host_port = 0;
       for (i0 = 0; i0 < dm0->ports_per_host; i0++)
         {
           key0.out_port = clib_host_to_net_u16 (lo_port0 +
index 42ce876..45e3682 100644 (file)
@@ -125,16 +125,20 @@ snat_det_get_ses_by_out (snat_det_map_t * dm, ip4_address_t * in_addr,
 }
 
 always_inline snat_det_session_t *
-snat_det_find_ses_by_in (snat_det_map_t * dm,
-                        ip4_address_t * in_addr, u16 in_port)
+snat_det_find_ses_by_in (snat_det_map_t * dm, ip4_address_t * in_addr,
+                        u16 in_port, snat_det_out_key_t out_key)
 {
+  snat_det_session_t *ses;
   u32 user_offset;
   u16 i;
 
   user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
   for (i = 0; i < SNAT_DET_SES_PER_USER; i++)
     {
-      if (dm->sessions[i + user_offset].in_port == in_port)
+      ses = &dm->sessions[i + user_offset];
+      if (ses->in_port == in_port &&
+         ses->out.ext_host_addr.as_u32 == out_key.ext_host_addr.as_u32 &&
+         ses->out.ext_host_port == out_key.ext_host_port)
        return &dm->sessions[i + user_offset];
     }