+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;
+ 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);
+
+ if (is_fwd_bypass_session (s))
+ {
+ if (snat_is_unk_proto_session (s))
+ {
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
+ }
+ else
+ {
+ 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;
+ 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)))
+ nat_elog_warn ("in2out_ed key del failed");
+ return;
+ }
+
+ /* session lookup tables */
+ if (is_affinity_sessions (s))
+ nat_affinity_unlock (s->ext_host_addr, s->out2in.addr,
+ s->in2out.protocol, s->out2in.port);
+ l_addr = &s->out2in.addr;
+ r_addr = &s->ext_host_addr;
+ fib_index = s->out2in.fib_index;
+ if (snat_is_unk_proto_session (s))
+ {
+ proto = s->in2out.port;
+ r_port = 0;
+ l_port = 0;
+ }
+ else
+ {
+ proto = snat_proto_to_ip_proto (s->in2out.protocol);
+ l_port = s->out2in.port;
+ r_port = s->ext_host_port;
+ }
+ 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");
+
+ l_addr = &s->in2out.addr;
+ fib_index = s->in2out.fib_index;
+
+ if (!snat_is_unk_proto_session (s))
+ l_port = s->in2out.port;
+
+ if (is_twice_nat_session (s))
+ {
+ r_addr = &s->ext_host_nat_addr;
+ r_port = s->ext_host_nat_port;
+ }
+ 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");
+
+ if (!is_ha)
+ {
+ nat_syslog_nat44_sdel (s->user_index, s->in2out.fib_index,
+ &s->in2out.addr, s->in2out.port,
+ &s->ext_host_nat_addr, s->ext_host_nat_port,
+ &s->out2in.addr, s->out2in.port,
+ &s->ext_host_addr, s->ext_host_port,
+ s->in2out.protocol, is_twice_nat_session (s));
+ }
+
+ if (snat_is_unk_proto_session (s))
+ return;
+
+ // is this correct ?
+ if (!is_ha)
+ {
+ snat_ipfix_logging_nat44_ses_delete (thread_index,
+ s->in2out.addr.as_u32,
+ s->out2in.addr.as_u32,
+ s->in2out.protocol,
+ s->in2out.port,
+ s->out2in.port,
+ s->in2out.fib_index);
+ nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
+ s->ext_host_port, s->out2in.protocol, s->out2in.fib_index,
+ thread_index);
+ }
+
+ /* Twice NAT address and port for external host */
+ if (is_twice_nat_session (s))
+ {
+ key.protocol = s->in2out.protocol;
+ key.port = s->ext_host_nat_port;
+ key.addr.as_u32 = s->ext_host_nat_addr.as_u32;
+ snat_free_outside_address_and_port (sm->twice_nat_addresses,
+ thread_index, &key);
+ }
+
+ if (snat_is_session_static (s))
+ return;
+
+ // should be called for every dynamic session
+ snat_free_outside_address_and_port (sm->addresses, thread_index,
+ &s->out2in);
+}
+
+