X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat44-ed%2Fnat44_ed_inlines.h;h=a13f250cd3b2f296c79ca0b091ce37805ebcb88b;hb=56c492aa0502751de2dd9d890096a82c5f04776d;hp=cb4189602490f92c8670160dbfa56814479d8701;hpb=4634d02501235d3803a17839eeaf076110abcb18;p=vpp.git diff --git a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h index cb418960249..a13f250cd3b 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h +++ b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h @@ -24,6 +24,7 @@ #include #include +#include #include always_inline void @@ -171,6 +172,26 @@ nat_get_icmp_session_lookup_values (vlib_buffer_t *b, ip4_header_t *ip0, return 0; } +always_inline int +nat44_ed_tcp_is_established (nat44_ed_tcp_state_e state) +{ + static int lookup[] = { + [NAT44_ED_TCP_STATE_CLOSED] = 0, + [NAT44_ED_TCP_STATE_SYN_I2O] = 0, + [NAT44_ED_TCP_STATE_SYN_O2I] = 0, + [NAT44_ED_TCP_STATE_ESTABLISHED] = 1, + [NAT44_ED_TCP_STATE_FIN_I2O] = 1, + [NAT44_ED_TCP_STATE_FIN_O2I] = 1, + [NAT44_ED_TCP_STATE_RST_TRANS] = 0, + [NAT44_ED_TCP_STATE_FIN_TRANS] = 0, + [NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O] = 0, + [NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I] = 0, + [NAT44_ED_TCP_N_STATE] = 0, + }; + ASSERT (state <= ARRAY_LEN (lookup)); + return lookup[state]; +} + always_inline u32 nat44_session_get_timeout (snat_main_t *sm, snat_session_t *s) { @@ -184,10 +205,10 @@ nat44_session_get_timeout (snat_main_t *sm, snat_session_t *s) return sm->timeouts.udp; case IP_PROTOCOL_TCP: { - if (s->state) - return sm->timeouts.tcp.transitory; - else + if (nat44_ed_tcp_is_established (s->tcp_state)) return sm->timeouts.tcp.established; + else + return sm->timeouts.tcp.transitory; } default: return sm->timeouts.udp; @@ -340,8 +361,7 @@ nat_lru_free_one_with_head (snat_main_t *sm, int thread_index, f64 now, sess_timeout_time = s->last_heard + (f64) nat44_session_get_timeout (sm, s); - if (now >= sess_timeout_time || - (s->tcp_closed_timestamp && now >= s->tcp_closed_timestamp)) + if (now >= sess_timeout_time) { nat44_ed_free_session_data (sm, s, thread_index, 0); nat_ed_session_delete (sm, s, thread_index, 0); @@ -701,101 +721,303 @@ is_interface_addr (snat_main_t *sm, vlib_node_runtime_t *node, } always_inline void -nat44_set_tcp_session_state_i2o (snat_main_t *sm, f64 now, snat_session_t *ses, - vlib_buffer_t *b, u32 thread_index) +nat44_ed_session_reopen (u32 thread_index, snat_session_t *s) { - snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - u8 tcp_flags = vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags; - u32 tcp_ack_number = vnet_buffer (b)->ip.reass.tcp_ack_number; - u32 tcp_seq_number = vnet_buffer (b)->ip.reass.tcp_seq_number; - if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST)) - ses->state = NAT44_SES_RST; - if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST)) - ses->state = 0; - if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) && - (ses->state & NAT44_SES_O2I_SYN)) - ses->state = 0; - if (tcp_flags & TCP_FLAG_SYN) - ses->state |= NAT44_SES_I2O_SYN; - if (tcp_flags & TCP_FLAG_FIN) - { - ses->i2o_fin_seq = clib_net_to_host_u32 (tcp_seq_number); - ses->state |= NAT44_SES_I2O_FIN; - } - if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN)) + nat_syslog_nat44_sdel (0, 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->proto, + nat44_ed_is_twice_nat_session (s)); + + nat_ipfix_logging_nat44_ses_delete ( + thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->proto, + s->in2out.port, s->out2in.port, s->in2out.fib_index); + nat_ipfix_logging_nat44_ses_create ( + thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->proto, + s->in2out.port, s->out2in.port, s->in2out.fib_index); + + nat_syslog_nat44_sadd (0, 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->proto, 0); + s->total_pkts = 0; + s->total_bytes = 0; +} + +always_inline void +nat44_ed_init_tcp_state_stable (snat_main_t *sm) +{ + /* first make sure whole table is initialised in a way where state + * is not changed, then define special cases */ + nat44_ed_tcp_state_e s; + for (s = 0; s < NAT44_ED_TCP_N_STATE; ++s) { - if (clib_net_to_host_u32 (tcp_ack_number) > ses->o2i_fin_seq) + int i; + for (i = 0; i < NAT44_ED_N_DIR; ++i) { - ses->state |= NAT44_SES_O2I_FIN_ACK; - if (nat44_is_ses_closed (ses)) - { // if session is now closed, save the timestamp - ses->tcp_closed_timestamp = now + sm->timeouts.tcp.transitory; - ses->last_lru_update = now; + int j = 0; + for (j = 0; j < NAT44_ED_TCP_N_FLAG; ++j) + { + sm->tcp_state_change_table[s][i][j] = s; } } } - // move the session to proper LRU - if (ses->state) - { - ses->lru_head_index = tsm->tcp_trans_lru_head_index; - } - else - { - ses->lru_head_index = tsm->tcp_estab_lru_head_index; - } - clib_dlist_remove (tsm->lru_pool, ses->lru_index); - clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index); + /* CLOSED and any kind of SYN -> HALF-OPEN */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_SYN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_SYN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_CLOSED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_SYN_O2I; + + /* HALF-OPEN and any kind of SYN in right direction -> ESTABLISHED */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_SYN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; + + /* ESTABLISHED and any kind of RST -> RST_TRANS */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_RST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_RST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_FINRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_FINRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_RST_TRANS; + + /* ESTABLISHED and any kind of FIN without RST -> HALF-CLOSED */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_FIN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_FIN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_ESTABLISHED][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_O2I; + + /* HALF-CLOSED and any kind of FIN -> FIN_TRANS */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_FINRST] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_FINRST] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_I2O][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_FIN_TRANS; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_O2I][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_FIN_TRANS; + + /* RST_TRANS and anything non-RST -> ESTABLISHED */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_NONE] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_NONE] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_FIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_RST_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + + /* FIN_TRANS and any kind of SYN -> HALF-REOPEN */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_I2O] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_TRANS][NAT44_ED_DIR_O2I] + [NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I; + + /* HALF-REOPEN and any kind of SYN in right direction -> ESTABLISHED */ + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O] + [NAT44_ED_DIR_O2I][NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I] + [NAT44_ED_DIR_I2O][NAT44_ED_TCP_FLAG_SYN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O] + [NAT44_ED_DIR_O2I][NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I] + [NAT44_ED_DIR_I2O][NAT44_ED_TCP_FLAG_SYNRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O] + [NAT44_ED_DIR_O2I][NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I] + [NAT44_ED_DIR_I2O][NAT44_ED_TCP_FLAG_SYNFIN] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O] + [NAT44_ED_DIR_O2I][NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; + sm->tcp_state_change_table[NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I] + [NAT44_ED_DIR_I2O][NAT44_ED_TCP_FLAG_SYNFINRST] = + NAT44_ED_TCP_STATE_ESTABLISHED; } +/* TCP state tracking according to RFC 7857 (and RFC 6146, which is referenced + * by RFC 7857). Our implementation also goes beyond by supporting creation of + * a new session while old session is in transitory timeout after seeing FIN + * packets from both sides. */ always_inline void -nat44_set_tcp_session_state_o2i (snat_main_t *sm, f64 now, snat_session_t *ses, - u8 tcp_flags, u32 tcp_ack_number, - u32 tcp_seq_number, u32 thread_index) +nat44_set_tcp_session_state (snat_main_t *sm, f64 now, snat_session_t *ses, + u8 tcp_flags, u32 thread_index, + nat44_ed_dir_e dir) { snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; - if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST)) - ses->state = NAT44_SES_RST; - if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST)) - ses->state = 0; - if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) && - (ses->state & NAT44_SES_O2I_SYN)) - ses->state = 0; - if (tcp_flags & TCP_FLAG_SYN) - ses->state |= NAT44_SES_O2I_SYN; - if (tcp_flags & TCP_FLAG_FIN) - { - ses->o2i_fin_seq = clib_net_to_host_u32 (tcp_seq_number); - ses->state |= NAT44_SES_O2I_FIN; - } - if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN)) + nat44_ed_tcp_flag_e flags = + tcp_flags & (TCP_FLAG_SYN | TCP_FLAG_FIN | TCP_FLAG_RST); + + u8 old_state = ses->tcp_state; + ses->tcp_state = sm->tcp_state_change_table[ses->tcp_state][dir][flags]; + + if (old_state != ses->tcp_state) { - if (clib_net_to_host_u32 (tcp_ack_number) > ses->i2o_fin_seq) - ses->state |= NAT44_SES_I2O_FIN_ACK; - if (nat44_is_ses_closed (ses)) - { // if session is now closed, save the timestamp - ses->tcp_closed_timestamp = now + sm->timeouts.tcp.transitory; - ses->last_lru_update = now; + if (nat44_ed_tcp_is_established (ses->tcp_state)) + { + if (NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O == old_state || + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I == old_state) + { + nat44_ed_session_reopen (thread_index, ses); + } + ses->lru_head_index = tsm->tcp_estab_lru_head_index; } + else + { + if (NAT44_ED_TCP_STATE_ESTABLISHED == old_state) + { // need to update last heard otherwise session might get + // immediately timed out if it has been idle longer than + // transitory timeout + ses->last_heard = now; + } + ses->lru_head_index = tsm->tcp_trans_lru_head_index; + } + ses->last_lru_update = now; + clib_dlist_remove (tsm->lru_pool, ses->lru_index); + clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index); } - // move the session to proper LRU - if (ses->state) - { - ses->lru_head_index = tsm->tcp_trans_lru_head_index; - } - else - { - ses->lru_head_index = tsm->tcp_estab_lru_head_index; - } - clib_dlist_remove (tsm->lru_pool, ses->lru_index); - clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index); +} + +always_inline void +nat44_set_tcp_session_state_i2o (snat_main_t *sm, f64 now, snat_session_t *ses, + u8 tcp_flags, u32 thread_index) +{ + return nat44_set_tcp_session_state (sm, now, ses, tcp_flags, thread_index, + NAT44_ED_DIR_I2O); +} + +always_inline void +nat44_set_tcp_session_state_o2i (snat_main_t *sm, f64 now, snat_session_t *ses, + u8 tcp_flags, u32 thread_index) +{ + return nat44_set_tcp_session_state (sm, now, ses, tcp_flags, thread_index, + NAT44_ED_DIR_O2I); } always_inline void nat44_session_update_counters (snat_session_t *s, f64 now, uword bytes, u32 thread_index) { - s->last_heard = now; + if (NAT44_ED_TCP_STATE_RST_TRANS != s->tcp_state && + NAT44_ED_TCP_STATE_FIN_TRANS != s->tcp_state && + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_I2O != s->tcp_state && + NAT44_ED_TCP_STATE_FIN_REOPEN_SYN_O2I != s->tcp_state) + { + s->last_heard = now; + } s->total_pkts++; s->total_bytes += bytes; }