X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat.c;h=7cb0b53368c9ed4d441b52f02a31e904de2c4995;hb=6bb080f1e;hp=5fc3eefe106622e47e5a9fc9431c3b7f17a16f3d;hpb=248ce43c6d79b79597e28f19615e83d2bb0a9276;p=vpp.git diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c index 5fc3eefe106..7cb0b53368c 100755 --- a/src/plugins/nat/nat.c +++ b/src/plugins/nat/nat.c @@ -199,7 +199,10 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, { snat_session_key_t key; clib_bihash_kv_8_8_t kv; - nat_ed_ses_key_t ed_key; + u8 proto; + u16 r_port, l_port; + ip4_address_t *l_addr, *r_addr; + u32 fib_index = 0; clib_bihash_kv_16_8_t ed_kv; snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, thread_index); @@ -208,21 +211,20 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, { if (snat_is_unk_proto_session (s)) { - ed_key.proto = s->in2out.port; - ed_key.r_port = 0; - ed_key.l_port = 0; + make_ed_kv (&s->in2out.addr, &s->ext_host_addr, s->in2out.port, 0, + 0, 0, ~0ULL, &ed_kv); } else { - ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol); - ed_key.l_port = s->in2out.port; - ed_key.r_port = s->ext_host_port; + proto = snat_proto_to_ip_proto (s->in2out.protocol); + l_port = s->in2out.port; + r_port = s->ext_host_port; + l_addr = &s->in2out.addr; + r_addr = &s->ext_host_addr; + proto = snat_proto_to_ip_proto (s->in2out.protocol); + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); } - ed_key.l_addr = s->in2out.addr; - ed_key.r_addr = s->ext_host_addr; - ed_key.fib_index = 0; - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)) nat_elog_warn ("in2out_ed key del failed"); return; @@ -234,36 +236,36 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, if (is_affinity_sessions (s)) nat_affinity_unlock (s->ext_host_addr, s->out2in.addr, s->in2out.protocol, s->out2in.port); - ed_key.l_addr = s->out2in.addr; - ed_key.r_addr = s->ext_host_addr; - ed_key.fib_index = s->out2in.fib_index; + l_addr = &s->out2in.addr; + r_addr = &s->ext_host_addr; + fib_index = s->out2in.fib_index; if (snat_is_unk_proto_session (s)) { - ed_key.proto = s->in2out.port; - ed_key.r_port = 0; - ed_key.l_port = 0; + proto = s->in2out.port; + r_port = 0; + l_port = 0; } else { - ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol); - ed_key.l_port = s->out2in.port; - ed_key.r_port = s->ext_host_port; + proto = snat_proto_to_ip_proto (s->in2out.protocol); + l_port = s->out2in.port; + r_port = s->ext_host_port; } - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0)) nat_elog_warn ("out2in_ed key del failed"); - ed_key.l_addr = s->in2out.addr; - ed_key.fib_index = s->in2out.fib_index; + l_addr = &s->in2out.addr; + fib_index = s->in2out.fib_index; if (!snat_is_unk_proto_session (s)) - ed_key.l_port = s->in2out.port; + l_port = s->in2out.port; if (is_twice_nat_session (s)) { - ed_key.r_addr = s->ext_host_nat_addr; - ed_key.r_port = s->ext_host_nat_port; + r_addr = &s->ext_host_nat_addr; + r_port = s->ext_host_nat_port; } - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)) nat_elog_warn ("in2out_ed key del failed"); @@ -323,26 +325,39 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, if (snat_is_session_static (s)) return; - ed_bihash_kv_t bihash_key; - clib_memset (&bihash_key, 0, sizeof (bihash_key)); - bihash_key.k.dst_address = s->ext_host_addr.as_u32; - bihash_key.k.dst_port = s->ext_host_port; - bihash_key.k.src_address = s->out2in.addr.as_u32; - bihash_key.k.src_port = s->out2in.port; - bihash_key.k.protocol = s->out2in.protocol; - clib_bihash_add_del_16_8 (&sm->ed_ext_ports, &bihash_key.kv, - 0 /* is_add */ ); - snat_free_outside_address_and_port (sm->addresses, thread_index, &s->out2in); } +int +nat44_set_session_limit (u32 session_limit, u32 vrf_id) +{ + snat_main_t *sm = &snat_main; + u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id); + u32 len = vec_len (sm->max_translations_per_fib); + + if (len <= fib_index) + { + vec_validate (sm->max_translations_per_fib, fib_index + 1); + + for (; len < vec_len (sm->max_translations_per_fib); len++) + sm->max_translations_per_fib[len] = sm->max_translations; + } + + sm->max_translations_per_fib[fib_index] = session_limit; + return 0; +} + + void nat44_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index, u8 is_ha) { snat_session_key_t key; - nat_ed_ses_key_t ed_key; + u8 proto; + u16 r_port, l_port; + ip4_address_t *l_addr, *r_addr; + u32 fib_index; clib_bihash_kv_16_8_t ed_kv; snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, thread_index); @@ -351,22 +366,22 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s, { if (snat_is_unk_proto_session (s)) { - ed_key.proto = s->in2out.port; - ed_key.r_port = 0; - ed_key.l_port = 0; + proto = s->in2out.port; + r_port = 0; + l_port = 0; } else { - ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol); - ed_key.l_port = s->in2out.port; - ed_key.r_port = s->ext_host_port; + proto = snat_proto_to_ip_proto (s->in2out.protocol); + l_port = s->in2out.port; + r_port = s->ext_host_port; } - ed_key.l_addr = s->in2out.addr; - ed_key.r_addr = s->ext_host_addr; - ed_key.fib_index = 0; - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; + l_addr = &s->in2out.addr; + r_addr = &s->ext_host_addr; + fib_index = 0; + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))) @@ -378,41 +393,40 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s, if (is_affinity_sessions (s)) nat_affinity_unlock (s->ext_host_addr, s->out2in.addr, s->in2out.protocol, s->out2in.port); - ed_key.l_addr = s->out2in.addr; - ed_key.r_addr = s->ext_host_addr; - ed_key.fib_index = s->out2in.fib_index; + l_addr = &s->out2in.addr; + r_addr = &s->ext_host_addr; + fib_index = s->out2in.fib_index; if (snat_is_unk_proto_session (s)) { - ed_key.proto = s->in2out.port; - ed_key.r_port = 0; - ed_key.l_port = 0; + proto = s->in2out.port; + r_port = 0; + l_port = 0; } else { - ed_key.proto = snat_proto_to_ip_proto (s->in2out.protocol); - ed_key.l_port = s->out2in.port; - ed_key.r_port = s->ext_host_port; + proto = snat_proto_to_ip_proto (s->in2out.protocol); + l_port = s->out2in.port; + r_port = s->ext_host_port; } - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &ed_kv, 0))) nat_elog_warn ("out2in_ed key del failed"); - ed_key.l_addr = s->in2out.addr; - ed_key.fib_index = s->in2out.fib_index; + l_addr = &s->in2out.addr; + fib_index = s->in2out.fib_index; if (!snat_is_unk_proto_session (s)) - ed_key.l_port = s->in2out.port; + l_port = s->in2out.port; if (is_twice_nat_session (s)) { - ed_key.r_addr = s->ext_host_nat_addr; - ed_key.r_port = s->ext_host_nat_port; + r_addr = &s->ext_host_nat_addr; + r_port = s->ext_host_nat_port; } - - ed_kv.key[0] = ed_key.as_u64[0]; - ed_kv.key[1] = ed_key.as_u64[1]; + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + &ed_kv); if (PREDICT_FALSE (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))) nat_elog_warn ("in2out_ed key del failed"); @@ -458,16 +472,6 @@ nat44_free_session_data (snat_main_t * sm, snat_session_t * s, if (snat_is_session_static (s)) return; - ed_bihash_kv_t bihash_key; - clib_memset (&bihash_key, 0, sizeof (bihash_key)); - bihash_key.k.dst_address = s->ext_host_addr.as_u32; - bihash_key.k.dst_port = s->ext_host_port; - bihash_key.k.src_address = s->out2in.addr.as_u32; - bihash_key.k.src_port = s->out2in.port; - bihash_key.k.protocol = s->out2in.protocol; - clib_bihash_add_del_16_8 (&sm->ed_ext_ports, &bihash_key.kv, - 0 /* is_add */ ); - // should be called for every dynamic session snat_free_outside_address_and_port (sm->addresses, thread_index, &s->out2in); @@ -495,8 +499,6 @@ nat_user_get_or_create (snat_main_t * sm, ip4_address_t * addr, u32 fib_index, pool_get (tsm->users, u); clib_memset (u, 0, sizeof (*u)); - u->min_session_timeout = 0; - u->addr.as_u32 = addr->as_u32; u->fib_index = fib_index; @@ -593,6 +595,14 @@ nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u, s->per_user_list_head_index, per_user_translation_list_elt - tsm->list_pool); + dlist_elt_t *global_lru_list_elt; + pool_get (tsm->global_lru_pool, global_lru_list_elt); + global_lru_list_elt->value = s - tsm->sessions; + s->global_lru_index = global_lru_list_elt - tsm->global_lru_pool; + clib_dlist_addtail (tsm->global_lru_pool, tsm->global_lru_head_index, + s->global_lru_index); + s->last_lru_update = now; + s->user_index = u - tsm->users; vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, pool_elts (tsm->sessions)); @@ -603,61 +613,55 @@ nat_session_alloc_or_recycle (snat_main_t * sm, snat_user_t * u, return s; } -snat_session_t * -nat_ed_session_alloc (snat_main_t * sm, snat_user_t * u, u32 thread_index, - f64 now) +int +nat_global_lru_free_one (snat_main_t * sm, int thread_index, f64 now) { - snat_session_t *s; - snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - + snat_session_t *s = NULL; 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)) + snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; + oldest_index = clib_dlist_remove_head (tsm->global_lru_pool, + tsm->global_lru_head_index); + if (~0 != oldest_index) { - if (nat44_max_translations_per_user_cleanup (u, thread_index, now)) - goto alloc_new; - - 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; + oldest_elt = pool_elt_at_index (tsm->global_lru_pool, oldest_index); + s = pool_elt_at_index (tsm->sessions, oldest_elt->value); + + 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)) + { + nat_free_session_data (sm, s, thread_index, 0); + nat44_ed_delete_session (sm, s, thread_index, 0); + return 1; + } + else + { + clib_dlist_addhead (tsm->global_lru_pool, + tsm->global_lru_head_index, oldest_index); + } } + return 0; +} - 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); +snat_session_t * +nat_ed_session_alloc (snat_main_t * sm, u32 thread_index, f64 now) +{ + snat_session_t *s; + snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - 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); - } - else - { - // alloc new session - clib_dlist_addhead (tsm->list_pool, - u->sessions_per_user_list_head_index, oldest_index); - alloc_new: - s = nat44_session_alloc_new (tsm, u, now); - vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, - pool_elts (tsm->sessions)); - } + nat_global_lru_free_one (sm, thread_index, now); + + pool_get (tsm->sessions, s); + clib_memset (s, 0, sizeof (*s)); + + nat44_global_lru_insert (tsm, s, now); + + s->ha_last_refreshed = now; + vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, + pool_elts (tsm->sessions)); return s; } @@ -816,6 +820,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, @@ -1220,48 +1323,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); } } @@ -1321,12 +1396,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) @@ -1539,37 +1610,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) @@ -1596,11 +1647,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; @@ -1693,38 +1741,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); } @@ -1835,11 +1864,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); } @@ -2474,6 +2511,46 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses, snat_session_key_t * k, u16 port_per_thread, u32 snat_thread_index); +void +test_ed_make_split () +{ + ip4_address_t l_addr; + l_addr.as_u8[0] = 1; + l_addr.as_u8[1] = 1; + l_addr.as_u8[2] = 1; + l_addr.as_u8[3] = 1; + ip4_address_t r_addr; + r_addr.as_u8[0] = 2; + r_addr.as_u8[1] = 2; + r_addr.as_u8[2] = 2; + r_addr.as_u8[3] = 2; + u16 l_port = 40001; + u16 r_port = 40301; + u8 proto = 9; + u32 fib_index = 9000001; + u64 value = ~0ULL; + clib_bihash_kv_16_8_t kv; + make_ed_kv (&l_addr, &r_addr, proto, fib_index, l_port, r_port, value, &kv); + ip4_address_t l_addr2; + ip4_address_t r_addr2; + clib_memset (&l_addr2, 0, sizeof (l_addr2)); + clib_memset (&r_addr2, 0, sizeof (r_addr2)); + u16 l_port2 = 0; + u16 r_port2 = 0; + u8 proto2 = 0; + u32 fib_index2 = 0; + split_ed_kv (&kv, &l_addr2, &r_addr2, &proto2, &fib_index2, &l_port2, + &r_port2); + u64 value2 = kv.value; + ASSERT (l_addr.as_u32 == l_addr2.as_u32); + ASSERT (r_addr.as_u32 == r_addr2.as_u32); + ASSERT (l_port == l_port2); + ASSERT (r_port == r_port2); + ASSERT (proto == proto2); + ASSERT (fib_index == fib_index2); + ASSERT (value == value2); +} + static clib_error_t * snat_init (vlib_main_t * vm) { @@ -2643,6 +2720,7 @@ snat_init (vlib_main_t * vm) FIB_SOURCE_PRIORITY_LOW, FIB_SOURCE_BH_SIMPLE); + test_ed_make_split (); return error; } @@ -3146,16 +3224,18 @@ u8 * format_ed_session_kvp (u8 * s, va_list * args) { clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *); - nat_ed_ses_key_t k; - k.as_u64[0] = v->key[0]; - k.as_u64[1] = v->key[1]; + u8 proto; + u16 r_port, l_port; + ip4_address_t l_addr, r_addr; + u32 fib_index; + split_ed_kv (v, &l_addr, &r_addr, &proto, &fib_index, &l_port, &r_port); s = format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu", - format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port), - format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port), - format_ip_protocol, k.proto, k.fib_index, v->value); + format_ip4_address, &l_addr, clib_net_to_host_u16 (l_port), + format_ip4_address, &r_addr, clib_net_to_host_u16 (r_port), + format_ip_protocol, proto, fib_index, v->value); return s; } @@ -3327,8 +3407,9 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index, break; } - make_ed_kv (&kv16, &ip->src_address, &ip->dst_address, - ip->protocol, fib_index, udp->src_port, udp->dst_port); + make_ed_kv (&ip->src_address, &ip->dst_address, + ip->protocol, fib_index, udp->src_port, udp->dst_port, + ~0ULL, &kv16); /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) @@ -3397,8 +3478,9 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, { udp = ip4_next_header (ip); - make_ed_kv (&kv16, &ip->dst_address, &ip->src_address, - ip->protocol, rx_fib_index, udp->dst_port, udp->src_port); + make_ed_kv (&ip->dst_address, &ip->src_address, + ip->protocol, rx_fib_index, udp->dst_port, udp->src_port, + ~0ULL, &kv16); /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) @@ -3418,15 +3500,8 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, } else if (proto == SNAT_PROTOCOL_ICMP) { - nat_ed_ses_key_t key; - - if (!get_icmp_o2i_ed_key (b, ip, &key)) + if (!get_icmp_o2i_ed_key (b, ip, rx_fib_index, ~0ULL, 0, 0, 0, &kv16)) { - - key.fib_index = rx_fib_index; - kv16.key[0] = key.as_u64[0]; - kv16.key[1] = key.as_u64[1]; - /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) { @@ -3699,7 +3774,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); @@ -3736,11 +3810,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; @@ -3753,7 +3823,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: @@ -3789,14 +3858,14 @@ nat_ha_sadd_ed_cb (ip4_address_t * in_addr, u16 in_port, key.fib_index = fib_index; s->in2out = key; - make_ed_kv (&kv, in_addr, &s->ext_host_nat_addr, + make_ed_kv (in_addr, &s->ext_host_nat_addr, snat_proto_to_ip_proto (proto), fib_index, in_port, - s->ext_host_nat_port); + s->ext_host_nat_port, s - tsm->sessions, &kv); if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &kv, 1)) nat_elog_warn ("in2out key add failed"); - make_ed_kv (&kv, out_addr, eh_addr, snat_proto_to_ip_proto (proto), - s->out2in.fib_index, out_port, eh_port); + make_ed_kv (out_addr, eh_addr, snat_proto_to_ip_proto (proto), + s->out2in.fib_index, out_port, eh_port, s - tsm->sessions, &kv); if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 1)) nat_elog_warn ("out2in key add failed"); } @@ -3807,7 +3876,6 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port, u32 fib_index, u32 ti) { snat_main_t *sm = &snat_main; - nat_ed_ses_key_t key; clib_bihash_kv_16_8_t kv, value; u32 thread_index; snat_session_t *s; @@ -3822,14 +3890,8 @@ nat_ha_sdel_ed_cb (ip4_address_t * out_addr, u16 out_port, thread_index = sm->num_workers; tsm = vec_elt_at_index (sm->per_thread_data, thread_index); - key.l_addr.as_u32 = out_addr->as_u32; - key.l_port = out_port; - key.r_addr.as_u32 = eh_addr->as_u32; - key.r_port = eh_port; - key.proto = proto; - key.fib_index = fib_index; - kv.key[0] = key.as_u64[0]; - kv.key[1] = key.as_u64[1]; + make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL, + &kv); if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value)) return; @@ -3845,21 +3907,14 @@ nat_ha_sref_ed_cb (ip4_address_t * out_addr, u16 out_port, u32 thread_index) { snat_main_t *sm = &snat_main; - nat_ed_ses_key_t key; clib_bihash_kv_16_8_t kv, value; snat_session_t *s; snat_main_per_thread_data_t *tsm; tsm = vec_elt_at_index (sm->per_thread_data, thread_index); - key.l_addr.as_u32 = out_addr->as_u32; - key.l_port = out_port; - key.r_addr.as_u32 = eh_addr->as_u32; - key.r_port = eh_port; - key.proto = proto; - key.fib_index = fib_index; - kv.key[0] = key.as_u64[0]; - kv.key[1] = key.as_u64[1]; + make_ed_kv (out_addr, eh_addr, proto, fib_index, out_port, eh_port, ~0ULL, + &kv); if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value)) return; @@ -3877,18 +3932,18 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) snat_main_per_thread_data_t *tsm; u32 static_mapping_buckets = 1024; - u32 static_mapping_memory_size = 64 << 20; + uword static_mapping_memory_size = 64 << 20; u32 nat64_bib_buckets = 1024; u32 nat64_bib_memory_size = 128 << 20; u32 nat64_st_buckets = 2048; - u32 nat64_st_memory_size = 256 << 20; + uword nat64_st_memory_size = 256 << 20; u32 user_buckets = 128; - u32 user_memory_size = 64 << 20; + uword user_memory_size = 64 << 20; u32 translation_buckets = 1024; - u32 translation_memory_size = 128 << 20; + uword translation_memory_size = 128 << 20; u32 max_translations_per_user = ~0; @@ -3985,16 +4040,15 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) sm->tcp_established_timeout = tcp_established_timeout; sm->icmp_timeout = icmp_timeout; - sm->min_timeout = nat44_minimal_timeout (sm); - sm->user_buckets = user_buckets; sm->user_memory_size = user_memory_size; sm->translation_buckets = translation_buckets; sm->translation_memory_size = translation_memory_size; - /* do not exceed load factor 10 */ sm->max_translations = 10 * translation_buckets; + vec_add1 (sm->max_translations_per_fib, sm->max_translations); + sm->max_translations_per_user = max_translations_per_user == ~0 ? sm->max_translations : max_translations_per_user; @@ -4067,14 +4121,15 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) /* *INDENT-OFF* */ vec_foreach (tsm, sm->per_thread_data) { - tsm->min_session_timeout = 0; - - tsm->cleared = 0; - tsm->cleanup_runs = 0; - tsm->cleanup_timeout = 0; - pool_alloc (tsm->sessions, sm->max_translations); pool_alloc (tsm->list_pool, sm->max_translations); + pool_alloc (tsm->global_lru_pool, sm->max_translations); + + dlist_elt_t *head; + pool_get (tsm->global_lru_pool, head); + tsm->global_lru_head_index = head - tsm->global_lru_pool; + clib_dlist_init (tsm->global_lru_pool, + tsm->global_lru_head_index); if (sm->endpoint_dependent) { @@ -4089,9 +4144,6 @@ snat_config (vlib_main_t * vm, unformat_input_t * input) translation_memory_size); clib_bihash_set_kvp_format_fn_16_8 (&tsm->out2in_ed, format_ed_session_kvp); - clib_bihash_init_16_8 - (&sm->ed_ext_ports, "ed-nat-5-tuple-port-overload-hash", - translation_buckets, translation_memory_size); } else { @@ -4408,7 +4460,6 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port, { ip4_header_t ip; clib_bihash_16_8_t *t; - nat_ed_ses_key_t key; clib_bihash_kv_16_8_t kv, value; u32 fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id); snat_session_t *s; @@ -4426,22 +4477,18 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port, tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); t = is_in ? &tsm->in2out_ed : &tsm->out2in_ed; - key.l_addr.as_u32 = addr->as_u32; - key.r_addr.as_u32 = eh_addr->as_u32; - key.l_port = clib_host_to_net_u16 (port); - key.r_port = clib_host_to_net_u16 (eh_port); - key.proto = proto; - key.fib_index = fib_index; - kv.key[0] = key.as_u64[0]; - kv.key[1] = key.as_u64[1]; + make_ed_kv (addr, eh_addr, proto, fib_index, clib_host_to_net_u16 (port), + clib_host_to_net_u16 (eh_port), ~0ULL, &kv); if (clib_bihash_search_16_8 (t, &kv, &value)) - return VNET_API_ERROR_NO_SUCH_ENTRY; + { + return VNET_API_ERROR_NO_SUCH_ENTRY; + } if (pool_is_free_index (tsm->sessions, value.value)) 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; }