summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2019-02-18 01:54:16 -0800
committerMatus Fabian <matfabia@cisco.com>2019-02-18 01:56:18 -0800
commit684586786e98bc779e269c0d879a2a4d3f1f4bce (patch)
tree6493da7899397a8bd14b832586757570440ba386
parent830fe7370af7ac9e28e9be04b5b5712b22ad9c31 (diff)
NAT44: fix snat_get_worker_out2in_cb (VPP-1536)
Change-Id: I9c562f8e3407ca60a4412a162015fa505b7590b6 Signed-off-by: Matus Fabian <matfabia@cisco.com>
-rwxr-xr-xsrc/plugins/nat/nat.c45
-rw-r--r--src/plugins/nat/nat64.c31
-rwxr-xr-xsrc/plugins/nat/nat_reass.c54
-rw-r--r--src/plugins/nat/nat_reass.h13
4 files changed, 126 insertions, 17 deletions
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index dabb8122adf..4e9d5023b3f 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -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))
{
diff --git a/src/plugins/nat/nat64.c b/src/plugins/nat/nat64.c
index 2f665ab4cfe..126cb3cdf79 100644
--- a/src/plugins/nat/nat64.c
+++ b/src/plugins/nat/nat64.c
@@ -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))
{
diff --git a/src/plugins/nat/nat_reass.c b/src/plugins/nat/nat_reass.c
index ed827a9038b..d7f9d58fc86 100755
--- a/src/plugins/nat/nat_reass.c
+++ b/src/plugins/nat/nat_reass.c
@@ -217,6 +217,60 @@ nat_ip4_reass_find (ip4_address_t src, ip4_address_t dst, u16 frag_id,
}
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,
u32 ** bi_to_drop)
diff --git a/src/plugins/nat/nat_reass.h b/src/plugins/nat/nat_reass.h
index e58db445e6e..11f9db5a252 100644
--- a/src/plugins/nat/nat_reass.h
+++ b/src/plugins/nat/nat_reass.h
@@ -214,6 +214,19 @@ nat_reass_ip4_t *nat_ip4_reass_find (ip4_address_t src,
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.
*
* @param src Source IPv4 address.