NAT44: fix snat_get_worker_out2in_cb (VPP-1536) 39/17639/1
authorMatus Fabian <matfabia@cisco.com>
Mon, 18 Feb 2019 09:54:16 +0000 (01:54 -0800)
committerMatus Fabian <matfabia@cisco.com>
Mon, 18 Feb 2019 09:56:18 +0000 (01:56 -0800)
Change-Id: I9c562f8e3407ca60a4412a162015fa505b7590b6
Signed-off-by: Matus Fabian <matfabia@cisco.com>
src/plugins/nat/nat.c
src/plugins/nat/nat64.c
src/plugins/nat/nat_reass.c
src/plugins/nat/nat_reass.h

index dabb812..4e9d502 100755 (executable)
@@ -2862,20 +2862,47 @@ snat_get_worker_out2in_cb (ip4_header_t * ip0, u32 rx_fib_index0)
       if (PREDICT_FALSE (nat_reass_is_drop_frag (0)))
        return vlib_get_thread_index ();
 
-      if (PREDICT_TRUE (!ip4_is_first_fragment (ip0)))
-       {
-         nat_reass_ip4_t *reass;
+      nat_reass_ip4_t *reass;
+      reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
+                                 ip0->fragment_id, ip0->protocol);
 
-         reass = nat_ip4_reass_find (ip0->src_address, ip0->dst_address,
-                                     ip0->fragment_id, ip0->protocol);
+      if (reass && (reass->thread_index != (u32) ~ 0))
+       return reass->thread_index;
 
-         if (reass && (reass->thread_index != (u32) ~ 0))
-           return reass->thread_index;
-         else
-           return vlib_get_thread_index ();
+      if (ip4_is_first_fragment (ip0))
+       {
+         reass =
+           nat_ip4_reass_create (ip0->src_address, ip0->dst_address,
+                                 ip0->fragment_id, ip0->protocol);
+         if (!reass)
+           goto no_reass;
+
+         if (PREDICT_FALSE (pool_elts (sm->static_mappings)))
+           {
+             m_key.addr = ip0->dst_address;
+             m_key.port = clib_net_to_host_u16 (port);
+             m_key.protocol = proto;
+             m_key.fib_index = rx_fib_index0;
+             kv.key = m_key.as_u64;
+             if (!clib_bihash_search_8_8
+                 (&sm->static_mapping_by_external, &kv, &value))
+               {
+                 m = pool_elt_at_index (sm->static_mappings, value.value);
+                 reass->thread_index = m->workers[0];
+                 return reass->thread_index;
+               }
+           }
+         reass->thread_index = sm->first_worker_index;
+         reass->thread_index +=
+           sm->workers[(clib_net_to_host_u16 (port) - 1024) /
+                       sm->port_per_thread];
+         return reass->thread_index;
        }
+      else
+       return vlib_get_thread_index ();
     }
 
+no_reass:
   /* unknown protocol */
   if (PREDICT_FALSE (proto == ~0))
     {
index 2f665ab..126cb3c 100644 (file)
@@ -138,20 +138,35 @@ nat64_get_worker_out2in (ip4_header_t * ip)
       if (PREDICT_FALSE (nat_reass_is_drop_frag (0)))
        return vlib_get_thread_index ();
 
-      if (PREDICT_TRUE (!ip4_is_first_fragment (ip)))
-       {
-         nat_reass_ip4_t *reass;
+      nat_reass_ip4_t *reass;
+      reass = nat_ip4_reass_find (ip->src_address, ip->dst_address,
+                                 ip->fragment_id, ip->protocol);
 
-         reass = nat_ip4_reass_find (ip->src_address, ip->dst_address,
-                                     ip->fragment_id, ip->protocol);
+      if (reass && (reass->thread_index != (u32) ~ 0))
+       return reass->thread_index;
 
-         if (reass && (reass->thread_index != (u32) ~ 0))
-           return reass->thread_index;
+      if (ip4_is_first_fragment (ip))
+       {
+         reass =
+           nat_ip4_reass_create (ip->src_address, ip->dst_address,
+                                 ip->fragment_id, ip->protocol);
+         if (!reass)
+           goto no_reass;
+
+         port = clib_net_to_host_u16 (port);
+         if (port > 1024)
+           reass->thread_index =
+             nm->sm->first_worker_index +
+             ((port - 1024) / sm->port_per_thread);
          else
-           return vlib_get_thread_index ();
+           reass->thread_index = vlib_get_thread_index ();
+         return reass->thread_index;
        }
+      else
+       return vlib_get_thread_index ();
     }
 
+no_reass:
   /* unknown protocol */
   if (PREDICT_FALSE (proto == ~0))
     {
index ed827a9..d7f9d58 100755 (executable)
@@ -216,6 +216,60 @@ nat_ip4_reass_find (ip4_address_t src, ip4_address_t dst, u16 frag_id,
   return reass;
 }
 
+nat_reass_ip4_t *
+nat_ip4_reass_create (ip4_address_t src, ip4_address_t dst, u16 frag_id,
+                     u8 proto)
+{
+  nat_reass_main_t *srm = &nat_reass_main;
+  nat_reass_ip4_t *reass = 0;
+  dlist_elt_t *elt, *per_reass_list_head_elt;
+  u32 elt_index;
+  f64 now = vlib_time_now (srm->vlib_main);
+  nat_reass_ip4_key_t k;
+  clib_bihash_kv_16_8_t kv;
+
+  clib_spinlock_lock_if_init (&srm->ip4_reass_lock);
+
+  if (srm->ip4_reass_n >= srm->ip4_max_reass)
+    {
+      nat_log_warn ("no free resassembly slot");
+      goto unlock;
+    }
+
+  pool_get (srm->ip4_reass_pool, reass);
+  pool_get (srm->ip4_reass_lru_list_pool, elt);
+  reass->lru_list_index = elt_index = elt - srm->ip4_reass_lru_list_pool;
+  clib_dlist_init (srm->ip4_reass_lru_list_pool, elt_index);
+  elt->value = reass - srm->ip4_reass_pool;
+  clib_dlist_addtail (srm->ip4_reass_lru_list_pool,
+                     srm->ip4_reass_head_index, elt_index);
+  pool_get (srm->ip4_frags_list_pool, per_reass_list_head_elt);
+  reass->frags_per_reass_list_head_index =
+    per_reass_list_head_elt - srm->ip4_frags_list_pool;
+  clib_dlist_init (srm->ip4_frags_list_pool,
+                  reass->frags_per_reass_list_head_index);
+  srm->ip4_reass_n++;
+  k.src.as_u32 = src.as_u32;
+  k.dst.as_u32 = dst.as_u32;
+  k.frag_id = frag_id;
+  k.proto = proto;
+  reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
+  reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
+  kv.value = reass - srm->ip4_reass_pool;
+  reass->sess_index = (u32) ~ 0;
+  reass->thread_index = (u32) ~ 0;
+  reass->last_heard = now;
+  reass->frag_n = 0;
+  reass->flags = 0;
+  reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
+  if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
+    nat_log_warn ("ip4_reass_hash add key failed");
+
+unlock:
+  clib_spinlock_unlock_if_init (&srm->ip4_reass_lock);
+  return reass;
+}
+
 nat_reass_ip4_t *
 nat_ip4_reass_find_or_create (ip4_address_t src, ip4_address_t dst,
                              u16 frag_id, u8 proto, u8 reset_timeout,
index e58db44..11f9db5 100644 (file)
@@ -213,6 +213,19 @@ nat_reass_ip4_t *nat_ip4_reass_find (ip4_address_t src,
                                     ip4_address_t dst,
                                     u16 frag_id, u8 proto);
 
+/**
+ * @brief Create reassembly.
+ *
+ * @param src Source IPv4 address.
+ * @param dst Destination IPv4 address.
+ * @param frag_id Fragment ID.
+ * @param proto L4 protocol.
+ *
+ * @returns Reassembly data or 0 on failure.
+ */
+nat_reass_ip4_t *nat_ip4_reass_create (ip4_address_t src, ip4_address_t dst,
+                                      u16 frag_id, u8 proto);
+
 /**
  * @brief Find or create reassembly.
  *