From 56c492aa0502751de2dd9d890096a82c5f04776d Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Mon, 10 Jan 2022 21:57:27 +0000 Subject: nat: TCP state tracking based on RFC 7857/RFC 6146 Implement proper state machine based on above RFCs. ACKs to SYNs/FINs are no longer required/tracked. This is more friendly to peers and accounts for lost packets and retransmits. This change also means that all traffic is translated and forwarded while in transitory timeout, which helps delivering e.g. retransmitted FINs, FINACKs and other messages. Also support reopening a session in transitory timeout after seeing both FINs by seeing both SYNs again. This helps quick connection reestablishment if the peers want to. Type: improvement Signed-off-by: Klement Sekera Signed-off-by: Miklos Tirpak Change-Id: Ibf521c79463472db97e593bfa02b32b4a06dfd2a --- src/plugins/nat/nat44-ed/nat44_ed_out2in.c | 54 +++++++----------------------- 1 file changed, 13 insertions(+), 41 deletions(-) (limited to 'src/plugins/nat/nat44-ed/nat44_ed_out2in.c') diff --git a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c index 5ad57a17098..40a72122140 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c @@ -41,7 +41,6 @@ typedef enum NAT_ED_SP_REASON_NO_REASON, NAT_ED_SP_REASON_LOOKUP_FAILED, NAT_ED_SP_REASON_VRF_EXPIRED, - NAT_ED_SP_TCP_CLOSED, NAT_ED_SP_SESS_EXPIRED, } nat_slow_path_reason_e; @@ -57,6 +56,7 @@ typedef struct u8 is_slow_path; u8 translation_via_i2of; u8 lookup_skipped; + u8 tcp_state; nat_slow_path_reason_e slow_path_reason; } nat44_ed_out2in_trace_t; @@ -72,8 +72,6 @@ format_slow_path_reason (u8 *s, va_list *args) return format (s, "slow path because lookup failed"); case NAT_ED_SP_REASON_VRF_EXPIRED: return format (s, "slow path because vrf expired"); - case NAT_ED_SP_TCP_CLOSED: - return format (s, "slow path because tcp closed"); case NAT_ED_SP_SESS_EXPIRED: return format (s, "slow path because session expired"); } @@ -107,14 +105,19 @@ format_nat44_ed_out2in_trace (u8 * s, va_list * args) { if (t->lookup_skipped) { - s = format (s, "\n lookup skipped - cached session index used"); + s = format (s, "\n lookup skipped - cached session index used"); } else { s = format (s, "\n search key %U", format_ed_session_kvp, &t->search_key); } - s = format (s, "\n %U", format_slow_path_reason, t->slow_path_reason); + s = format (s, "\n %U", format_slow_path_reason, t->slow_path_reason); + } + if (IP_PROTOCOL_TCP == t->i2of.match.proto) + { + s = format (s, "\n TCP state: %U", format_nat44_ed_tcp_state, + t->tcp_state); } return s; @@ -645,10 +648,9 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, if (ip->protocol == IP_PROTOCOL_TCP) { - tcp_header_t *tcp = ip4_next_header (ip); - nat44_set_tcp_session_state_o2i (sm, now, s, tcp->flags, - tcp->ack_number, tcp->seq_number, - thread_index); + nat44_set_tcp_session_state_o2i ( + sm, now, s, vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags, + thread_index); } /* Accounting */ @@ -883,23 +885,6 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - if (s0->tcp_closed_timestamp) - { - if (now >= s0->tcp_closed_timestamp) - { - // session is closed, go slow path, freed in slow path - slow_path_reason = NAT_ED_SP_TCP_CLOSED; - next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; - } - else - { - // session in transitory timeout, drop - b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TCP_CLOSED]; - next[0] = NAT_NEXT_DROP; - } - goto trace0; - } - // drop if session expired u64 sess_timeout_time; sess_timeout_time = @@ -981,10 +966,6 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, nat44_set_tcp_session_state_o2i (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); break; case IP_PROTOCOL_UDP: @@ -1028,6 +1009,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of)); clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if)); t->translation_via_i2of = (&s0->i2o == f); + t->tcp_state = s0->tcp_state; } else { @@ -1170,13 +1152,6 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, s0 = pool_elt_at_index (tsm->sessions, ed_value_get_session_index (&value0)); - - if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp) - { - nat44_ed_free_session_data (sm, s0, thread_index, 0); - nat_ed_session_delete (sm, s0, thread_index, 1); - s0 = NULL; - } } if (!s0) @@ -1264,10 +1239,6 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, nat44_set_tcp_session_state_o2i (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); } else @@ -1300,6 +1271,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, t->session_index = s0 - tsm->sessions; clib_memcpy (&t->i2of, &s0->i2o, sizeof (t->i2of)); clib_memcpy (&t->o2if, &s0->o2i, sizeof (t->o2if)); + t->tcp_state = s0->tcp_state; } else { -- cgit 1.2.3-korg