nat: fix worker selection 27/31527/7
authorKlement Sekera <ksekera@cisco.com>
Wed, 3 Mar 2021 21:14:55 +0000 (22:14 +0100)
committerOle Tr�an <otroan@employees.org>
Sun, 7 Mar 2021 17:57:32 +0000 (17:57 +0000)
Use correct ports from SVR. Perform lookup of existing session for all
cases to pick any created bypasses and derive correct thread indexes.

Type: fix
Change-Id: I1e3814c9e13cd4d9b8d65f514f7e9ab42df3c22e
Signed-off-by: Klement Sekera <ksekera@cisco.com>
src/plugins/nat/nat44-ed/nat44_ed.c
src/plugins/nat/nat44-ed/nat44_ed.h
src/plugins/nat/nat44-ed/nat44_ed_api.c
src/plugins/nat/nat44-ed/nat44_ed_handoff.c
src/plugins/nat/nat44-ed/nat44_ed_in2out.c
src/plugins/nat/nat44-ed/nat44_ed_out2in.c
src/plugins/nat/nat44-ei/nat44_ei.c

index 6f2cd11..0d62e78 100644 (file)
@@ -182,9 +182,8 @@ static u32
 nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
                               u32 rx_fib_index, u8 is_output);
 
-static u32
-nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index,
-                              u8 is_output);
+static u32 nat44_ed_get_worker_in2out_cb (vlib_buffer_t *b, ip4_header_t *ip,
+                                         u32 rx_fib_index, u8 is_output);
 
 u32 nat_calc_bihash_buckets (u32 n_elts);
 
@@ -738,7 +737,8 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr,
          ip4_header_t ip = {
            .src_address = m->local_addr,
          };
-         vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index, 0));
+         vec_add1 (m->workers,
+                   sm->worker_in2out_cb (0, &ip, m->fib_index, 0));
          tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]);
        }
       else
@@ -988,10 +988,8 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
              ip4_header_t ip = {
                .src_address = locals[i].addr,
              };
-             bitmap =
-               clib_bitmap_set (bitmap,
-                                sm->worker_in2out_cb (&ip, m->fib_index, 0),
-                                1);
+             bitmap = clib_bitmap_set (
+               bitmap, sm->worker_in2out_cb (0, &ip, m->fib_index, 0), 1);
            }
        }
 
@@ -1057,9 +1055,11 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
                             sm->fib_src_low);
           if (!out2in_only)
             {
-init_nat_k(&              kv, local->addr, local->port, local->fib_index, m->proto);
-              if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
-                {
+             init_nat_k (&kv, local->addr, local->port, local->fib_index,
+                         m->proto);
+             if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv,
+                                          0))
+               {
                  nat_elog_err (sm, "static_mapping_by_local key del failed");
                  return VNET_API_ERROR_UNSPECIFIED;
                }
@@ -1070,9 +1070,9 @@ init_nat_k(&              kv, local->addr, local->port, local->fib_index, m->pro
              ip4_header_t ip = {
                .src_address = local->addr,
              };
-             tsm =
-               vec_elt_at_index (sm->per_thread_data,
-                                 sm->worker_in2out_cb (&ip, m->fib_index, 0));
+             tsm = vec_elt_at_index (
+               sm->per_thread_data,
+               sm->worker_in2out_cb (0, &ip, m->fib_index, 0));
            }
          else
            tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
@@ -1188,9 +1188,9 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
          ip4_header_t ip = {
            .src_address = local->addr,
          };
-         tsm = vec_elt_at_index (sm->per_thread_data,
-                                 sm->worker_in2out_cb (&ip, m->fib_index,
-                                                       0));
+         tsm =
+           vec_elt_at_index (sm->per_thread_data,
+                             sm->worker_in2out_cb (0, &ip, m->fib_index, 0));
        }
       else
        tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
@@ -1222,10 +1222,9 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port,
     if (sm->num_workers > 1)
       {
         ip4_header_t ip;
-        ip.src_address.as_u32 = local->addr.as_u32,
-        bitmap = clib_bitmap_set (bitmap,
-                                  sm->worker_in2out_cb (&ip, local->fib_index, 0),
-                                  1);
+       ip.src_address.as_u32 = local->addr.as_u32,
+       bitmap = clib_bitmap_set (
+         bitmap, sm->worker_in2out_cb (0, &ip, local->fib_index, 0), 1);
       }
   }
   /* *INDENT-ON* */
@@ -2485,12 +2484,12 @@ snat_static_mapping_match (snat_main_t * sm,
                  .src_address = local->addr,
                };
 
-               if (sm->worker_in2out_cb (&ip, m->fib_index, 0) ==
+               if (sm->worker_in2out_cb (0, &ip, m->fib_index, 0) ==
                    thread_index)
-                  {
-                    vec_add1 (tmp, i);
-                  }
-              }
+                 {
+                   vec_add1 (tmp, i);
+                 }
+              }
              ASSERT (vec_len (tmp) != 0);
            }
          else
@@ -2562,20 +2561,19 @@ end:
 }
 
 static u32
-nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index,
-                              u8 is_output)
+nat44_ed_get_worker_in2out_cb (vlib_buffer_t *b, ip4_header_t *ip,
+                              u32 rx_fib_index, u8 is_output)
 {
   snat_main_t *sm = &snat_main;
   u32 next_worker_index = sm->first_worker_index;
   u32 hash;
 
   clib_bihash_kv_16_8_t kv16, value16;
-  snat_main_per_thread_data_t *tsm;
-  udp_header_t *udp;
 
+  u32 fib_index = rx_fib_index;
   if (PREDICT_FALSE (is_output))
     {
-      u32 fib_index = sm->outside_fib_index;
+      fib_index = sm->outside_fib_index;
       nat_outside_fib_t *outside_fib;
       fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
       fib_prefix_t pfx = {
@@ -2587,8 +2585,6 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index,
        ,
       };
 
-      udp = ip4_next_header (ip);
-
       switch (vec_len (sm->outside_fibs))
        {
        case 0:
@@ -2614,24 +2610,21 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index,
             /* *INDENT-ON* */
          break;
        }
+    }
 
-      init_ed_k (&kv16, ip->src_address, udp->src_port, ip->dst_address,
-                udp->dst_port, fib_index, ip->protocol);
+  if (b)
+    {
+      init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
+                ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
+                fib_index, ip->protocol);
 
       if (PREDICT_TRUE (
            !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)))
        {
-         tsm =
-           vec_elt_at_index (sm->per_thread_data,
-                             ed_value_get_thread_index (&value16));
-         next_worker_index += tsm->thread_index;
-
-         nat_elog_debug_handoff (
-           sm, "HANDOFF IN2OUT-OUTPUT-FEATURE (session)", next_worker_index,
-           fib_index, clib_net_to_host_u32 (ip->src_address.as_u32),
-           clib_net_to_host_u32 (ip->dst_address.as_u32));
-
-         return next_worker_index;
+         next_worker_index = ed_value_get_thread_index (&value16);
+         vnet_buffer2 (b)->nat.cached_session_index =
+           ed_value_get_session_index (&value16);
+         goto out;
        }
     }
 
@@ -2643,6 +2636,7 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index,
   else
     next_worker_index += sm->workers[hash % _vec_len (sm->workers)];
 
+out:
   if (PREDICT_TRUE (!is_output))
     {
       nat_elog_debug_handoff (sm, "HANDOFF IN2OUT", next_worker_index,
@@ -2682,8 +2676,9 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
     {
       udp = ip4_next_header (ip);
 
-      init_ed_k (&kv16, ip->dst_address, udp->dst_port, ip->src_address,
-                udp->src_port, rx_fib_index, ip->protocol);
+      init_ed_k (&kv16, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
+                ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
+                rx_fib_index, ip->protocol);
 
       if (PREDICT_TRUE (
            !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16)))
@@ -2750,7 +2745,7 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip,
     }
 
   udp = ip4_next_header (ip);
-  port = udp->dst_port;
+  port = vnet_buffer (b)->ip.reass.l4_dst_port;
 
   if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP))
     {
@@ -3220,9 +3215,8 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port,
 
   ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
   if (sm->num_workers > 1)
-    tsm =
-      vec_elt_at_index (sm->per_thread_data,
-                       sm->worker_in2out_cb (&ip, fib_index, 0));
+    tsm = vec_elt_at_index (sm->per_thread_data,
+                           sm->worker_in2out_cb (0, &ip, fib_index, 0));
   else
     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
index 902e5e3..c6bccd9 100644 (file)
@@ -190,7 +190,6 @@ typedef enum
 #define NAT_STATIC_MAPPING_FLAG_LB             8
 #define NAT_STATIC_MAPPING_FLAG_EXACT_ADDRESS  16
 
-/* *INDENT-OFF* */
 typedef CLIB_PACKED(struct
 {
   // number of sessions in this vrf
@@ -202,7 +201,6 @@ typedef CLIB_PACKED(struct
   // is this vrf expired
   u8 expired;
 }) per_vrf_sessions_t;
-/* *INDENT-ON* */
 
 typedef union
 {
@@ -287,7 +285,6 @@ nat_6t_flow_icmp_id_rewrite_set (nat_6t_flow_t *f, u16 id)
   f->rewrite.icmp_id = id;
 }
 
-/* *INDENT-OFF* */
 typedef CLIB_PACKED(struct
 {
   /* Outside network tuple */
@@ -348,20 +345,17 @@ typedef CLIB_PACKED(struct
   u32 per_vrf_sessions_index;
 
 }) snat_session_t;
-/* *INDENT-ON* */
 
 typedef struct
 {
   ip4_address_t addr;
   u32 fib_index;
-/* *INDENT-OFF* */
 #define _(N, i, n, s) \
   u32 busy_##n##_ports; \
   u32 * busy_##n##_ports_per_thread; \
   u32 busy_##n##_port_refcounts[65535];
   foreach_nat_protocol
 #undef _
-/* *INDENT-ON* */
 } snat_address_t;
 
 typedef struct
@@ -496,7 +490,8 @@ typedef struct
 struct snat_main_s;
 
 /* Return worker thread index for given packet */
-typedef u32 (snat_get_worker_in2out_function_t) (ip4_header_t * ip,
+typedef u32 (snat_get_worker_in2out_function_t) (vlib_buffer_t *b,
+                                                ip4_header_t *ip,
                                                 u32 rx_fib_index,
                                                 u8 is_output);
 
index c6c505e..3089f68 100644 (file)
@@ -1529,9 +1529,8 @@ vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t *
   ip.src_address.as_u32 = ukey.addr.as_u32;
   ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id));
   if (sm->num_workers > 1)
-    tsm =
-      vec_elt_at_index (sm->per_thread_data,
-                       sm->worker_in2out_cb (&ip, ukey.fib_index, 0));
+    tsm = vec_elt_at_index (sm->per_thread_data,
+                           sm->worker_in2out_cb (0, &ip, ukey.fib_index, 0));
   else
     tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
 
index 6715ce2..e286df9 100644 (file)
@@ -157,10 +157,10 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm,
 
       if (is_in2out)
        {
-         ti[0] = sm->worker_in2out_cb (ip0, rx_fib_index0, is_output);
-         ti[1] = sm->worker_in2out_cb (ip1, rx_fib_index1, is_output);
-         ti[2] = sm->worker_in2out_cb (ip2, rx_fib_index2, is_output);
-         ti[3] = sm->worker_in2out_cb (ip3, rx_fib_index3, is_output);
+         ti[0] = sm->worker_in2out_cb (b[0], ip0, rx_fib_index0, is_output);
+         ti[1] = sm->worker_in2out_cb (b[1], ip1, rx_fib_index1, is_output);
+         ti[2] = sm->worker_in2out_cb (b[2], ip2, rx_fib_index2, is_output);
+         ti[3] = sm->worker_in2out_cb (b[3], ip3, rx_fib_index3, is_output);
        }
       else
        {
@@ -218,7 +218,7 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm,
 
       if (is_in2out)
        {
-         ti[0] = sm->worker_in2out_cb (ip0, rx_fib_index0, is_output);
+         ti[0] = sm->worker_in2out_cb (b[0], ip0, rx_fib_index0, is_output);
        }
       else
        {
index 59355e4..885851c 100644 (file)
@@ -554,15 +554,15 @@ error:
 }
 
 static_always_inline int
-nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
-                       u32 sw_if_index, ip4_header_t * ip, u32 proto,
-                       u32 rx_fib_index, u32 thread_index)
+nat44_ed_not_translate (snat_main_t *sm, vlib_node_runtime_t *node,
+                       u32 sw_if_index, vlib_buffer_t *b, ip4_header_t *ip,
+                       u32 proto, u32 rx_fib_index, u32 thread_index)
 {
-  udp_header_t *udp = ip4_next_header (ip);
   clib_bihash_kv_16_8_t kv, value;
 
-  init_ed_k (&kv, ip->dst_address, udp->dst_port, ip->src_address,
-            udp->src_port, sm->outside_fib_index, ip->protocol);
+  init_ed_k (&kv, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
+            ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port,
+            sm->outside_fib_index, ip->protocol);
 
   /* NAT packet aimed at external address if has active sessions */
   if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value))
@@ -571,10 +571,10 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node,
       ip4_address_t placeholder_addr;
       u16 placeholder_port;
       u32 placeholder_fib_index;
-      if (!snat_static_mapping_match
-         (sm, ip->dst_address, udp->dst_port, sm->outside_fib_index, proto,
-          &placeholder_addr, &placeholder_port, &placeholder_fib_index, 1, 0,
-          0, 0, 0, 0, 0))
+      if (!snat_static_mapping_match (
+           sm, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port,
+           sm->outside_fib_index, proto, &placeholder_addr, &placeholder_port,
+           &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0))
        return 0;
     }
   else
@@ -742,7 +742,7 @@ icmp_in2out_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip,
     }
   else
     {
-      if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index, ip,
+      if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index, b, ip,
                                                 NAT_PROTOCOL_ICMP,
                                                 rx_fib_index, thread_index)))
        {
@@ -1373,9 +1373,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm,
            }
          else
            {
-             if (PREDICT_FALSE
-                 (nat44_ed_not_translate
-                  (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
+             if (PREDICT_FALSE (nat44_ed_not_translate (
+                   sm, node, sw_if_index0, b0, ip0, proto0, rx_fib_index0,
                    thread_index)))
                goto trace0;
            }
index 90f2ec3..d3fd509 100644 (file)
@@ -372,7 +372,6 @@ create_session_for_static_mapping_ed (
 {
   snat_session_t *s;
   ip4_header_t *ip;
-  udp_header_t *udp;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
 
   if (PREDICT_FALSE
@@ -392,10 +391,10 @@ create_session_for_static_mapping_ed (
     }
 
   ip = vlib_buffer_get_current (b);
-  udp = ip4_next_header (ip);
 
   s->ext_host_addr.as_u32 = ip->src_address.as_u32;
-  s->ext_host_port = nat_proto == NAT_PROTOCOL_ICMP ? 0 : udp->src_port;
+  s->ext_host_port =
+    nat_proto == NAT_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port;
   s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
   if (lb_nat)
     s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
@@ -574,7 +573,6 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s,
                       ip4_header_t *ip, u32 rx_fib_index, u32 thread_index)
 {
   clib_bihash_kv_16_8_t kv, value;
-  udp_header_t *udp;
   snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
   vlib_main_t *vm = vlib_get_main ();
   f64 now = vlib_time_now (vm);
@@ -593,9 +591,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s,
     {
       if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP)
        {
-         udp = ip4_next_header (ip);
-         lookup_sport = udp->dst_port;
-         lookup_dport = udp->src_port;
+         lookup_sport = vnet_buffer (b)->ip.reass.l4_dst_port;
+         lookup_dport = vnet_buffer (b)->ip.reass.l4_src_port;
        }
       else
        {
index d361060..6775701 100644 (file)
@@ -1407,7 +1407,7 @@ nat44_ei_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip0,
 
   proto = ip_proto_to_nat_proto (ip0->protocol);
   udp = ip4_next_header (ip0);
-  port = udp->dst_port;
+  port = vnet_buffer (b)->ip.reass.l4_dst_port;
 
   /* unknown protocol */
   if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER))