aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nat/out2in_ed.c
diff options
context:
space:
mode:
authorKlement Sekera <ksekera@cisco.com>2020-03-10 12:32:54 +0100
committerOle Trøan <otroan@employees.org>2020-03-26 14:56:09 +0000
commit1c2ac860ed9a80dac539af6408d70f7dfd2c238e (patch)
tree5f418adb4fe3f43d104379179fc2885fc5b64f6a /src/plugins/nat/out2in_ed.c
parent65c30ceb92dd79c7b00e8c31119db98d473dbfbb (diff)
nat: transitory timeout for TCP CLOSED state
Wait transitory timeout seconds before moving internal state of TCP session to CLOSED state per RFC 7857. This patch implements this functionality for endpoint-dependent NAT. Type: improvement Signed-off-by: Klement Sekera <ksekera@cisco.com> Change-Id: I4491d831cd9edf63fae520a516cdbe590bac85db
Diffstat (limited to 'src/plugins/nat/out2in_ed.c')
-rw-r--r--src/plugins/nat/out2in_ed.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c
index fbb7d069dbb..69436145a67 100644
--- a/src/plugins/nat/out2in_ed.c
+++ b/src/plugins/nat/out2in_ed.c
@@ -414,7 +414,8 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip,
{
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;
}
@@ -682,6 +683,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
u32 tcp_packets = 0, udp_packets = 0, icmp_packets = 0, other_packets =
0, fragments = 0;
+ u32 tcp_closed_drops = 0;
stats_node_index = sm->ed_out2in_node_index;
@@ -766,6 +768,23 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
}
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];
+ ++tcp_closed_drops;
+ next0 = NAT_NEXT_DROP;
+ }
+ goto trace0;
+ }
+
// drop if session expired
u64 sess_timeout_time;
sess_timeout_time = s0->last_heard +
@@ -827,7 +846,8 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm,
}
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;
@@ -1029,7 +1049,20 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
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 */
@@ -1108,10 +1141,6 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
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;
@@ -1158,7 +1187,8 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm,
}
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;