if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0))
nat_elog_warn ("in2out_ed key del failed");
+ 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 */ );
+
if (snat_is_unk_proto_session (s))
goto delete;
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);
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;
{
tcp_header_t *tcp = ip4_next_header (ip);
if (nat44_set_tcp_session_state_o2i
- (sm, s, tcp->flags, tcp->ack_number, tcp->seq_number, thread_index))
+ (sm, now, s, tcp->flags, tcp->ack_number, tcp->seq_number,
+ thread_index))
return;
}
thread_index);
if (!u)
{
+ b->error = node->errors[NAT_OUT2IN_ED_ERROR_CANNOT_CREATE_USER];
nat_elog_warn ("create NAT user failed");
return 0;
}
s = nat_ed_session_alloc (sm, u, 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;
}
s0 = pool_elt_at_index (tsm->sessions, value0.value);
+ if (s0->tcp_close_timestamp)
+ {
+ if (now >= s0->tcp_close_timestamp)
+ {
+ // session is closed, go slow path
+ next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
+ }
+ else
+ {
+ // session in transitory timeout, drop
+ b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TCP_CLOSED];
+ next0 = NAT_NEXT_DROP;
+ }
+ goto trace0;
+ }
+
// drop if session expired
u64 sess_timeout_time;
sess_timeout_time = s0->last_heard +
(f64) nat44_session_get_timeout (sm, s0);
if (now >= sess_timeout_time)
{
- // delete session
+ // session is closed, go slow path
nat_free_session_data (sm, s0, thread_index, 0);
nat44_delete_session (sm, s0, thread_index);
-
- next0 = NAT_NEXT_DROP;
+ next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH;
goto trace0;
}
//
}
tcp_packets++;
if (nat44_set_tcp_session_state_o2i
- (sm, s0, vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
+ (sm, now, s0,
+ vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
vnet_buffer (b0)->ip.reass.tcp_ack_number,
vnet_buffer (b0)->ip.reass.tcp_seq_number, thread_index))
goto trace0;
s0 =
nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0,
thread_index, now, vm, node);
- other_packets++;
if (!sm->forwarding_enabled)
{
if (!s0)
next0 = NAT_NEXT_DROP;
- goto trace0;
}
+ other_packets++;
+ goto trace0;
}
if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP))
vnet_buffer (b0)->ip.reass.l4_dst_port,
vnet_buffer (b0)->ip.reass.l4_src_port);
- if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
+ s0 = NULL;
+ if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0))
+ {
+ s0 = pool_elt_at_index (tsm->sessions, value0.value);
+
+ 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);
+ s0 = NULL;
+ }
+ }
+
+ if (!s0)
{
/* Try to match static mapping by external address and port,
destination address and port in packet */
goto trace0;
}
}
- else
- {
- s0 = pool_elt_at_index (tsm->sessions, value0.value);
- }
old_addr0 = ip0->dst_address.as_u32;
new_addr0 = ip0->dst_address.as_u32 = s0->in2out.addr.as_u32;
}
tcp_packets++;
if (nat44_set_tcp_session_state_o2i
- (sm, s0, vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
+ (sm, now, s0,
+ vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags,
vnet_buffer (b0)->ip.reass.tcp_ack_number,
vnet_buffer (b0)->ip.reass.tcp_seq_number, thread_index))
goto trace0;