From 684586786e98bc779e269c0d879a2a4d3f1f4bce Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Mon, 18 Feb 2019 01:54:16 -0800 Subject: [PATCH] NAT44: fix snat_get_worker_out2in_cb (VPP-1536) Change-Id: I9c562f8e3407ca60a4412a162015fa505b7590b6 Signed-off-by: Matus Fabian --- src/plugins/nat/nat.c | 45 +++++++++++++++++++++++++++++-------- src/plugins/nat/nat64.c | 31 +++++++++++++++++++------- src/plugins/nat/nat_reass.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ src/plugins/nat/nat_reass.h | 13 +++++++++++ 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 @@ -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, 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 @@ -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. * -- 2.16.6