From: Klement Sekera Date: Wed, 15 Apr 2020 13:37:18 +0000 (+0200) Subject: nat: ignore user hash in ED NAT X-Git-Tag: v20.09-rc0~138 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=d9e18aac39827b576dda5ee456e17694988f5ac6 nat: ignore user hash in ED NAT With port overloading, port is no longer a scarce resource and there is no need to limit connections per internal IP. This saves one hash insert in slow path. Type: improvement Change-Id: I8a7a9713ac855fa99fa1617ec684f757cf6e09ae Signed-off-by: Klement Sekera --- diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c index ca1d0cd56ca..95f80a4ff2b 100644 --- a/src/plugins/nat/in2out_ed.c +++ b/src/plugins/nat/in2out_ed.c @@ -152,7 +152,7 @@ nat44_i2o_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) snat_free_outside_address_and_port (sm->addresses, ctx->thread_index, &s->out2in); delete: - nat44_delete_session (sm, s, ctx->thread_index); + nat44_ed_delete_session (sm, s, ctx->thread_index, 1); return 1; } @@ -281,9 +281,8 @@ slow_path_ed (snat_main_t * sm, vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now) { snat_session_t *s = NULL; - snat_user_t *u = NULL; snat_session_key_t key0, key1; - lb_nat_type_t lb = 0, is_sm = 0; + lb_nat_type_t lb = 0; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key; u32 proto = ip_proto_to_snat_proto (key->proto); @@ -333,16 +332,7 @@ slow_path_ed (snat_main_t * sm, if (snat_static_mapping_match (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat)) { - u = - nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index); - if (!u) - { - nat_elog_warn ("create NAT user failed"); - b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER]; - goto drop; - } - - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { nat_elog_warn ("create NAT session failed"); @@ -396,20 +386,9 @@ slow_path_ed (snat_main_t * sm, *sessionp = s; return next; } - is_sm = 1; - u = - nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index); - if (!u) - { - nat_elog_warn ("create NAT user failed"); - b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER]; - goto drop; - } - - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { - nat44_delete_user_with_no_session (sm, u, thread_index); nat_elog_warn ("create NAT session failed"); b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED]; goto drop; @@ -453,7 +432,6 @@ slow_path_ed (snat_main_t * sm, out2in_ed_inserted = true; } - user_session_increment (sm, u, is_sm); if (lb) s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT; @@ -506,10 +484,6 @@ drop: nat_free_session_data (sm, s, thread_index, 0); nat44_ed_delete_session (sm, s, thread_index, 1); } - if (u) - { - nat44_delete_user_with_no_session (sm, u, thread_index); - } return NAT_NEXT_DROP; } @@ -630,7 +604,7 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip, if (nat44_is_ses_closed (s)) { nat_free_session_data (sm, s, thread_index, 0); - nat44_delete_session (sm, s, thread_index); + nat44_ed_delete_session (sm, s, thread_index, 1); } else s->flags |= SNAT_SESSION_FLAG_OUTPUT_FEATURE; @@ -782,10 +756,7 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, snat_static_mapping_t *m; u32 old_addr, new_addr = 0; ip_csum_t sum; - snat_user_t *u; - dlist_elt_t *head, *elt; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - u32 elt_index, head_index, ses_index; snat_session_t *s; u32 outside_fib_index = sm->outside_fib_index; int i; @@ -845,15 +816,6 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, return 0; } - u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index, - thread_index); - if (!u) - { - b->error = node->errors[NAT_IN2OUT_ED_ERROR_CANNOT_CREATE_USER]; - nat_elog_warn ("create NAT user failed"); - return 0; - } - make_sm_kv (&kv, &ip->src_address, 0, rx_fib_index, 0); /* Try to find static mapping first */ @@ -864,41 +826,23 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, is_sm = 1; goto create_ses; } - /* Fallback to 3-tuple key */ else { - /* Choose same out address as for TCP/UDP session to same destination */ - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; - if (PREDICT_FALSE (elt_index == ~0)) - ses_index = ~0; - else - { - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - } - - while (ses_index != ~0) - { - s = pool_elt_at_index (tsm->sessions, ses_index); - elt_index = elt->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - - if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32) - { - new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32; - - make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, - ip->protocol, outside_fib_index, 0, 0); - if (clib_bihash_search_16_8 - (&tsm->out2in_ed, &s_kv, &s_value)) - goto create_ses; - - break; - } - } + /* *INDENT-OFF* */ + pool_foreach (s, tsm->sessions, { + if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32) + { + new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32; + + make_ed_kv (&s_kv, &s->out2in.addr, &ip->dst_address, ip->protocol, + outside_fib_index, 0, 0); + if (clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value)) + goto create_ses; + + break; + } + }); + /* *INDENT-ON* */ for (i = 0; i < vec_len (sm->addresses); i++) { @@ -915,11 +859,10 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, } create_ses: - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { b->error = node->errors[NAT_IN2OUT_ED_ERROR_MAX_USER_SESS_EXCEEDED]; - nat44_delete_user_with_no_session (sm, u, thread_index); nat_elog_warn ("create NAT session failed"); return 0; } @@ -934,7 +877,6 @@ nat44_ed_in2out_unknown_proto (snat_main_t * sm, s->in2out.port = s->out2in.port = ip->protocol; if (is_sm) s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; - user_session_increment (sm, u, is_sm); /* Add to lookup tables */ make_ed_kv (&s_kv, &s->in2out.addr, &ip->dst_address, ip->protocol, @@ -1111,7 +1053,7 @@ nat44_ed_in2out_fast_path_node_fn_inline (vlib_main_t * vm, if (now >= sess_timeout_time) { nat_free_session_data (sm, s0, thread_index, 0); - nat44_delete_session (sm, s0, thread_index); + nat44_ed_delete_session (sm, s0, thread_index, 1); // session is closed, go slow path next0 = def_slow; goto trace0; @@ -1372,7 +1314,7 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm, if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp) { nat_free_session_data (sm, s0, thread_index, 0); - nat44_delete_session (sm, s0, thread_index); + nat44_ed_delete_session (sm, s0, thread_index, 1); s0 = NULL; } } diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index d27887e80e6..b0c30d636af 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -623,64 +623,21 @@ nat_global_lru_free_one (snat_main_t * sm, int thread_index, f64 now) } snat_session_t * -nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, - f64 now) +nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, f64 now) { - snat_session_t *s = NULL; + snat_session_t *s; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - dlist_elt_t *oldest_elt; - u64 sess_timeout_time; - u32 oldest_index; - - // no sessions - if (PREDICT_FALSE (!(u->nsessions) && !(u->nstaticsessions))) - goto alloc_new; - - // no free sessions - if (PREDICT_FALSE - ((u->nsessions + u->nstaticsessions) >= sm->max_translations_per_user)) - { - nat_elog_addr (SNAT_LOG_WARNING, "[warn] max translations per user", - clib_net_to_host_u32 (u->addr.as_u32)); - snat_ipfix_logging_max_entries_per_user (thread_index, - sm->max_translations_per_user, - u->addr.as_u32); - return 0; - } + nat_global_lru_free_one (sm, thread_index, now); - /* first try to reuse an expired session from this ip */ - oldest_index = - clib_dlist_remove_head (tsm->list_pool, - u->sessions_per_user_list_head_index); - oldest_elt = pool_elt_at_index (tsm->list_pool, oldest_index); - s = pool_elt_at_index (tsm->sessions, oldest_elt->value); + pool_get (tsm->sessions, s); + clib_memset (s, 0, sizeof (*s)); - sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s); - if (now >= sess_timeout_time || - (s->tcp_close_timestamp && now >= s->tcp_close_timestamp)) - { - // reuse old session - clib_dlist_addtail (tsm->list_pool, - u->sessions_per_user_list_head_index, oldest_index); - s = nat44_session_reuse_old (sm, u, s, thread_index, now); - s->last_lru_update = now; - } - else - { - clib_dlist_addhead (tsm->list_pool, - u->sessions_per_user_list_head_index, oldest_index); - s = NULL; - } + nat44_global_lru_insert (tsm, s, now); -alloc_new: - if (!s) - { - nat_global_lru_free_one (sm, thread_index, now); - s = nat44_session_alloc_new (tsm, u, now); - vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, - pool_elts (tsm->sessions)); - } + s->ha_last_refreshed = now; + vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, + pool_elts (tsm->sessions)); return s; } @@ -839,6 +796,105 @@ get_thread_idx_by_port (u16 e_port) return thread_idx; } +void +snat_static_mapping_del_sessions (snat_main_t * sm, + snat_main_per_thread_data_t * tsm, + snat_user_key_t u_key, int addr_only, + ip4_address_t e_addr, u16 e_port) +{ + clib_bihash_kv_8_8_t kv, value; + kv.key = u_key.as_u64; + u64 user_index; + dlist_elt_t *head, *elt; + snat_user_t *u; + snat_session_t *s; + u32 elt_index, head_index, ses_index; + if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) + { + user_index = value.value; + u = pool_elt_at_index (tsm->users, user_index); + if (u->nstaticsessions) + { + head_index = u->sessions_per_user_list_head_index; + head = pool_elt_at_index (tsm->list_pool, head_index); + elt_index = head->next; + elt = pool_elt_at_index (tsm->list_pool, elt_index); + ses_index = elt->value; + while (ses_index != ~0) + { + s = pool_elt_at_index (tsm->sessions, ses_index); + elt = pool_elt_at_index (tsm->list_pool, elt->next); + ses_index = elt->value; + + if (!addr_only) + { + if ((s->out2in.addr.as_u32 != e_addr.as_u32) || + (clib_net_to_host_u16 (s->out2in.port) != e_port)) + continue; + } + + if (is_lb_session (s)) + continue; + + if (!snat_is_session_static (s)) + continue; + + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_delete_session (sm, s, tsm - sm->per_thread_data); + + if (!addr_only) + break; + } + } + } +} + +void +snat_ed_static_mapping_del_sessions (snat_main_t * sm, + snat_main_per_thread_data_t * tsm, + ip4_address_t l_addr, + u16 l_port, + u8 protocol, + u32 fib_index, int addr_only, + ip4_address_t e_addr, u16 e_port) +{ + snat_session_t *s; + u32 *indexes_to_free = NULL; + /* *INDENT-OFF* */ + pool_foreach (s, tsm->sessions, { + if (s->in2out.fib_index != fib_index || + s->in2out.addr.as_u32 != l_addr.as_u32) + { + continue; + } + if (!addr_only) + { + if ((s->out2in.addr.as_u32 != e_addr.as_u32) || + (clib_net_to_host_u16 (s->out2in.port) != e_port) || + clib_net_to_host_u16 (s->in2out.port) != l_port || + s->in2out.protocol != protocol) + continue; + } + + if (is_lb_session (s)) + continue; + if (!snat_is_session_static (s)) + continue; + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + vec_add1 (indexes_to_free, s - tsm->sessions); + if (!addr_only) + break; + }); + /* *INDENT-ON* */ + u32 *ses_index; + vec_foreach (ses_index, indexes_to_free) + { + s = pool_elt_at_index (tsm->sessions, *ses_index); + nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1); + } + vec_free (indexes_to_free); +} + int snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, u16 l_port, u16 e_port, u32 vrf_id, int addr_only, @@ -1243,48 +1299,20 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, if (!(sm->static_mapping_only) || (sm->static_mapping_only && sm->static_mapping_connection_tracking)) { - u_key.addr = m->local_addr; - u_key.fib_index = fib_index; - kv.key = u_key.as_u64; - if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) + if (sm->endpoint_dependent) { - user_index = value.value; - u = pool_elt_at_index (tsm->users, user_index); - if (u->nstaticsessions) - { - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - while (ses_index != ~0) - { - s = pool_elt_at_index (tsm->sessions, ses_index); - elt = pool_elt_at_index (tsm->list_pool, elt->next); - ses_index = elt->value; - - if (!addr_only) - { - if ((s->out2in.addr.as_u32 != e_addr.as_u32) || - (clib_net_to_host_u16 (s->out2in.port) != - e_port)) - continue; - } - - if (is_lb_session (s)) - continue; - - if (!snat_is_session_static (s)) - continue; - - nat_free_session_data (sm, s, - tsm - sm->per_thread_data, 0); - nat44_delete_session (sm, s, tsm - sm->per_thread_data); - - if (!addr_only && !sm->endpoint_dependent) - break; - } - } + snat_ed_static_mapping_del_sessions (sm, tsm, m->local_addr, + m->local_port, m->proto, + fib_index, addr_only, + e_addr, e_port); + } + else + { + u_key.addr = m->local_addr; + u_key.fib_index = fib_index; + kv.key = u_key.as_u64; + snat_static_mapping_del_sessions (sm, tsm, u_key, addr_only, + e_addr, e_port); } } @@ -1344,12 +1372,8 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, snat_address_t *a = 0; int i; nat44_lb_addr_port_t *local; - u32 elt_index, head_index, ses_index; snat_main_per_thread_data_t *tsm; - snat_user_key_t u_key; - snat_user_t *u; snat_session_t *s; - dlist_elt_t *head, *elt; uword *bitmap = 0; if (!sm->endpoint_dependent) @@ -1562,37 +1586,17 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); /* Delete sessions */ - u_key.addr = local->addr; - u_key.fib_index = local->fib_index; - kv.key = u_key.as_u64; - if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) - { - u = pool_elt_at_index (tsm->users, value.value); - if (u->nstaticsessions) - { - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - while (ses_index != ~0) - { - s = pool_elt_at_index (tsm->sessions, ses_index); - elt = pool_elt_at_index (tsm->list_pool, elt->next); - ses_index = elt->value; - - if (!(is_lb_session (s))) - continue; - - if ((s->in2out.addr.as_u32 != local->addr.as_u32) || - (clib_net_to_host_u16 (s->in2out.port) != local->port)) - continue; - - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); - nat44_delete_session (sm, s, tsm - sm->per_thread_data); - } - } - } + pool_foreach (s, tsm->sessions, { + if (!(is_lb_session (s))) + continue; + + if ((s->in2out.addr.as_u32 != local->addr.as_u32) || + (clib_net_to_host_u16 (s->in2out.port) != local->port)) + continue; + + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1); + }); })); /* *INDENT-ON* */ if (m->affinity) @@ -1619,11 +1623,8 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port, clib_bihash_kv_8_8_t kv, value; nat44_lb_addr_port_t *local, *prev_local, *match_local = 0; snat_main_per_thread_data_t *tsm; - snat_user_key_t u_key; - snat_user_t *u; snat_session_t *s; - dlist_elt_t *head, *elt; - u32 elt_index, head_index, ses_index, *locals = 0; + u32 *locals = 0; uword *bitmap = 0; int i; @@ -1716,38 +1717,19 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port, tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); /* Delete sessions */ - u_key.addr = match_local->addr; - u_key.fib_index = match_local->fib_index; - kv.key = u_key.as_u64; - if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) - { - u = pool_elt_at_index (tsm->users, value.value); - if (u->nstaticsessions) - { - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - while (ses_index != ~0) - { - s = pool_elt_at_index (tsm->sessions, ses_index); - elt = pool_elt_at_index (tsm->list_pool, elt->next); - ses_index = elt->value; - - if (!(is_lb_session (s))) - continue; + /* *INDENT-OFF* */ + pool_foreach (s, tsm->sessions, { + if (!(is_lb_session (s))) + continue; - if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) || - (clib_net_to_host_u16 (s->in2out.port) != - match_local->port)) - continue; + if ((s->in2out.addr.as_u32 != match_local->addr.as_u32) || + (clib_net_to_host_u16 (s->in2out.port) != match_local->port)) + continue; - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); - nat44_delete_session (sm, s, tsm - sm->per_thread_data); - } - } - } + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1); + }); + /* *INDENT-ON* */ pool_put (m->locals, match_local); } @@ -1858,11 +1840,19 @@ snat_del_address (snat_main_t * sm, ip4_address_t addr, u8 delete_sm, } })); - vec_foreach (ses_index, ses_to_be_removed) - { - ses = pool_elt_at_index (tsm->sessions, ses_index[0]); - nat44_delete_session (sm, ses, tsm - sm->per_thread_data); - } + if (sm->endpoint_dependent){ + vec_foreach (ses_index, ses_to_be_removed) + { + ses = pool_elt_at_index (tsm->sessions, ses_index[0]); + nat44_ed_delete_session (sm, ses, tsm - sm->per_thread_data, 1); + } + }else{ + vec_foreach (ses_index, ses_to_be_removed) + { + ses = pool_elt_at_index (tsm->sessions, ses_index[0]); + nat44_delete_session (sm, ses, tsm - sm->per_thread_data); + } + } vec_free (ses_to_be_removed); } @@ -3722,7 +3712,6 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port, { snat_main_t *sm = &snat_main; snat_session_key_t key; - snat_user_t *u; snat_session_t *s; clib_bihash_kv_16_8_t kv; f64 now = vlib_time_now (sm->vlib_main); @@ -3759,11 +3748,7 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port, return; } - u = nat_user_get_or_create (sm, in_addr, fib_index, thread_index); - if (!u) - return; - - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) return; @@ -3776,7 +3761,6 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port, s->ext_host_nat_addr.as_u32 = ehn_addr->as_u32; s->ext_host_nat_port = ehn_port; } - user_session_increment (sm, u, snat_is_session_static (s)); switch (vec_len (sm->outside_fibs)) { case 0: @@ -4460,7 +4444,7 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port, return VNET_API_ERROR_UNSPECIFIED; s = pool_elt_at_index (tsm->sessions, value.value); nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); - nat44_delete_session (sm, s, tsm - sm->per_thread_data); + nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1); return 0; } diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h index 0fc174d2a91..98c18c06635 100644 --- a/src/plugins/nat/nat.h +++ b/src/plugins/nat/nat.h @@ -1317,13 +1317,12 @@ snat_session_t *nat_session_alloc_or_recycle (snat_main_t * sm, /** * @brief Allocate NAT endpoint-dependent session * - * @param u NAT user * @param thread_index thread index * * @return session data structure on success otherwise zero value */ -snat_session_t *nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, - u32 thread_index, f64 now); +snat_session_t *nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, + f64 now); /** * @brief Set address and port assignment algorithm for MAP-E CE diff --git a/src/plugins/nat/nat44/inlines.h b/src/plugins/nat/nat44/inlines.h index 541770ad102..3c88e15c05e 100644 --- a/src/plugins/nat/nat44/inlines.h +++ b/src/plugins/nat/nat44/inlines.h @@ -53,6 +53,19 @@ nat44_session_reuse_old (snat_main_t * sm, snat_user_t * u, return s; } +static_always_inline void +nat44_global_lru_insert (snat_main_per_thread_data_t * tsm, + snat_session_t * s, f64 now) +{ + dlist_elt_t *lru_list_elt; + pool_get (tsm->global_lru_pool, lru_list_elt); + s->global_lru_index = lru_list_elt - tsm->global_lru_pool; + clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index, + s->global_lru_index); + lru_list_elt->value = s - tsm->sessions; + s->last_lru_update = now; +} + static_always_inline snat_session_t * nat44_session_alloc_new (snat_main_per_thread_data_t * tsm, snat_user_t * u, f64 now) @@ -75,14 +88,7 @@ nat44_session_alloc_new (snat_main_per_thread_data_t * tsm, snat_user_t * u, s->per_user_list_head_index, per_user_translation_list_elt - tsm->list_pool); - dlist_elt_t *lru_list_elt; - pool_get (tsm->global_lru_pool, lru_list_elt); - s->global_lru_index = lru_list_elt - tsm->global_lru_pool; - clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index, - s->global_lru_index); - lru_list_elt->value = s - tsm->sessions; - s->last_lru_update = now; - + nat44_global_lru_insert (tsm, s, now); s->ha_last_refreshed = now; return s; } diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index 863f2cbea9f..a54a4790a20 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -1678,26 +1678,40 @@ vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t * sm->worker_in2out_cb (&ip, ukey.fib_index, 0)); else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); - if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value)) - return; - u = pool_elt_at_index (tsm->users, value.value); - if (!u->nsessions && !u->nstaticsessions) - return; - - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - session_index = elt->value; - while (session_index != ~0) + if (!sm->endpoint_dependent) { - s = pool_elt_at_index (tsm->sessions, session_index); - - send_nat44_user_session_details (s, reg, mp->context); - - elt_index = elt->next; + if (clib_bihash_search_8_8 (&tsm->user_hash, &key, &value)) + return; + u = pool_elt_at_index (tsm->users, value.value); + if (!u->nsessions && !u->nstaticsessions) + return; + + head_index = u->sessions_per_user_list_head_index; + head = pool_elt_at_index (tsm->list_pool, head_index); + elt_index = head->next; elt = pool_elt_at_index (tsm->list_pool, elt_index); session_index = elt->value; + while (session_index != ~0) + { + s = pool_elt_at_index (tsm->sessions, session_index); + + send_nat44_user_session_details (s, reg, mp->context); + + elt_index = elt->next; + elt = pool_elt_at_index (tsm->list_pool, elt_index); + session_index = elt->value; + } + } + else + { + /* *INDENT-OFF* */ + pool_foreach (s, tsm->sessions, { + if (s->in2out.addr.as_u32 == ukey.addr.as_u32) + { + send_nat44_user_session_details (s, reg, mp->context); + } + }); + /* *INDENT-ON* */ } } @@ -2012,12 +2026,21 @@ static void vec_add1 (ses_to_be_removed, s - tsm->sessions); } })); - vec_foreach (ses_index, ses_to_be_removed) - { - s = pool_elt_at_index(tsm->sessions, ses_index[0]); - nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); - nat44_delete_session (sm, s, tsm - sm->per_thread_data); - } + if(sm->endpoint_dependent){ + vec_foreach (ses_index, ses_to_be_removed) + { + s = pool_elt_at_index(tsm->sessions, ses_index[0]); + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_ed_delete_session (sm, s, tsm - sm->per_thread_data, 1); + } + }else{ + vec_foreach (ses_index, ses_to_be_removed) + { + s = pool_elt_at_index(tsm->sessions, ses_index[0]); + nat_free_session_data (sm, s, tsm - sm->per_thread_data, 0); + nat44_delete_session (sm, s, tsm - sm->per_thread_data); + } + } vec_free (ses_to_be_removed); } /* *INDENT-ON* */ diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h index 01b43591ccd..daf501dcef3 100644 --- a/src/plugins/nat/nat_inlines.h +++ b/src/plugins/nat/nat_inlines.h @@ -286,9 +286,8 @@ nat44_delete_user_with_no_session (snat_main_t * sm, snat_user_t * u, } always_inline void -nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses, - u32 thread_index, int global_lru_delete - /* delete from global LRU list */ ) +nat44_delete_session (snat_main_t * sm, snat_session_t * ses, + u32 thread_index) { snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, thread_index); @@ -302,10 +301,7 @@ nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses, clib_dlist_remove (tsm->list_pool, ses->per_user_index); pool_put_index (tsm->list_pool, ses->per_user_index); - if (global_lru_delete) - { - clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index); - } + clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index); pool_put_index (tsm->global_lru_pool, ses->global_lru_index); pool_put (tsm->sessions, ses); vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, @@ -324,20 +320,23 @@ nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses, } } -always_inline void -nat44_delete_session (snat_main_t * sm, snat_session_t * ses, - u32 thread_index) -{ - return nat44_delete_session_internal (sm, ses, thread_index, 1); -} - always_inline void nat44_ed_delete_session (snat_main_t * sm, snat_session_t * ses, u32 thread_index, int global_lru_delete /* delete from global LRU list */ ) { - return nat44_delete_session_internal (sm, ses, thread_index, - global_lru_delete); + snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, + thread_index); + + if (global_lru_delete) + { + clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index); + } + pool_put_index (tsm->global_lru_pool, ses->global_lru_index); + pool_put (tsm->sessions, ses); + vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, + pool_elts (tsm->sessions)); + } /** \brief Set TCP session state. @@ -455,10 +454,13 @@ nat44_session_update_lru (snat_main_t * sm, snat_session_t * s, /* don't update too often - timeout is in a magnitude of seconds anyway */ if (s->last_heard > s->last_lru_update + 1) { - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s->per_user_list_head_index, s->per_user_index); + if (!sm->endpoint_dependent) + { + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, + s->per_user_index); + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, + s->per_user_list_head_index, s->per_user_index); + } clib_dlist_remove (sm->per_thread_data[thread_index].global_lru_pool, s->global_lru_index); diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c index e5adef45fc8..560dc0d89d4 100644 --- a/src/plugins/nat/out2in_ed.c +++ b/src/plugins/nat/out2in_ed.c @@ -176,7 +176,7 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) snat_free_outside_address_and_port (sm->addresses, ctx->thread_index, &s->out2in); delete: - nat44_delete_session (sm, s, ctx->thread_index); + nat44_ed_delete_session (sm, s, ctx->thread_index, 1); return 1; } @@ -195,7 +195,6 @@ create_session_for_static_mapping_ed (snat_main_t * sm, lb_nat_type_t lb_nat, f64 now) { snat_session_t *s; - snat_user_t *u; ip4_header_t *ip; udp_header_t *udp; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; @@ -210,19 +209,10 @@ create_session_for_static_mapping_ed (snat_main_t * sm, return 0; } - u = nat_user_get_or_create (sm, &l_key.addr, l_key.fib_index, thread_index); - if (!u) - { - b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_SESSIONS_EXCEEDED]; - nat_elog_warn ("create NAT user failed"); - return 0; - } - - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED]; - nat44_delete_user_with_no_session (sm, u, thread_index); nat_elog_warn ("create NAT session failed"); return 0; } @@ -241,7 +231,6 @@ create_session_for_static_mapping_ed (snat_main_t * sm, s->out2in = e_key; s->in2out = l_key; s->in2out.protocol = s->out2in.protocol; - user_session_increment (sm, u, 1); /* Add to lookup tables */ make_ed_kv (&kv, &e_key.addr, &s->ext_host_addr, ip->protocol, @@ -264,7 +253,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, tsm->snat_thread_index)) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS]; - nat44_delete_session (sm, s, thread_index); + nat44_ed_delete_session (sm, s, thread_index, 1); if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0)) nat_elog_notice ("out2in-ed key del failed"); return 0; @@ -331,7 +320,6 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, nat_ed_ses_key_t key; clib_bihash_kv_16_8_t kv, value; udp_header_t *udp; - snat_user_t *u; snat_session_t *s = 0; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; f64 now = vlib_time_now (sm->vlib_main); @@ -372,18 +360,9 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, if (PREDICT_FALSE (nat44_maximum_sessions_exceeded (sm, thread_index))) return; - u = nat_user_get_or_create (sm, &ip->dst_address, sm->inside_fib_index, - thread_index); - if (!u) - { - nat_elog_warn ("create NAT user failed"); - return; - } - - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { - nat44_delete_user_with_no_session (sm, u, thread_index); nat_elog_warn ("create NAT session failed"); return; } @@ -403,7 +382,6 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, } s->out2in.fib_index = 0; s->in2out = s->out2in; - user_session_increment (sm, u, 0); kv.value = s - tsm->sessions; if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1)) @@ -579,7 +557,6 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, ip_csum_t sum; snat_session_t *s; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - snat_user_t *u; old_addr = ip->dst_address.as_u32; @@ -612,21 +589,11 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32; - u = nat_user_get_or_create (sm, &m->local_addr, m->fib_index, - thread_index); - if (!u) - { - b->error = node->errors[NAT_OUT2IN_ED_ERROR_CANNOT_CREATE_USER]; - nat_elog_warn ("create NAT user failed"); - return 0; - } - /* Create a new session */ - s = nat_ed_session_alloc (sm, u, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now); if (!s) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED]; - nat44_delete_user_with_no_session (sm, u, thread_index); nat_elog_warn ("create NAT session failed"); return 0; } @@ -640,7 +607,6 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, s->in2out.addr.as_u32 = new_addr; s->in2out.fib_index = m->fib_index; s->in2out.port = s->out2in.port = ip->protocol; - user_session_increment (sm, u, 1); /* Add to lookup tables */ s_kv.value = s - tsm->sessions; @@ -791,7 +757,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, { // session is closed, go slow path nat_free_session_data (sm, s0, thread_index, 0); - nat44_delete_session (sm, s0, thread_index); + nat44_ed_delete_session (sm, s0, thread_index, 1); next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } @@ -1053,7 +1019,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp) { nat_free_session_data (sm, s0, thread_index, 0); - nat44_delete_session (sm, s0, thread_index); + nat44_ed_delete_session (sm, s0, thread_index, 1); s0 = NULL; } } diff --git a/src/plugins/nat/test/test_nat.py b/src/plugins/nat/test/test_nat.py index 31eb7cb3b3c..214daf8a43a 100644 --- a/src/plugins/nat/test/test_nat.py +++ b/src/plugins/nat/test/test_nat.py @@ -4510,8 +4510,6 @@ class TestNAT44EndpointDependent(MethodHolder): '/err/nat44-ed-out2in/good out2in packets processed') self.assertEqual(err - totaln, 3) - users = self.statistics.get_counter('/nat44/total-users') - self.assertEqual(users[0][0], 1) sessions = self.statistics.get_counter('/nat44/total-sessions') self.assertEqual(sessions[0][0], 3) @@ -4607,8 +4605,6 @@ class TestNAT44EndpointDependent(MethodHolder): '/err/nat44-ed-out2in/good out2in packets processed') self.assertEqual(err - totaln, 3) - users = self.statistics.get_counter('/nat44/total-users') - self.assertEqual(users[0][0], 1) sessions = self.statistics.get_counter('/nat44/total-sessions') self.assertEqual(sessions[0][0], 3) @@ -6817,13 +6813,6 @@ class TestNAT44EndpointDependent(MethodHolder): self.pg_start() self.pg1.get_capture(1) - nsessions = 0 - users = self.vapi.nat44_user_dump() - self.assertEqual(len(users), 1) - self.assertEqual(str(users[0].ip_address), - self.pg0.remote_ip4) - self.assertEqual(users[0].nsessions, 1) - def test_syslog_sess(self): """ Test syslog session creation and deletion """ self.vapi.syslog_set_filter(