X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat_inlines.h;h=e5f2d96b33f7d841ebce2d7cf99ebb8773a5c60f;hb=ba5f9bc7534bcf58225b0658993728b1f4d47a67;hp=2f68ed4a70082872adb96877059b30748b7007d5;hpb=9a6dc8a9376e7270331255861b3ead1045b40c6d;p=vpp.git diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h index 2f68ed4a700..e5f2d96b33f 100644 --- a/src/plugins/nat/nat_inlines.h +++ b/src/plugins/nat/nat_inlines.h @@ -171,9 +171,9 @@ snat_proto_to_ip_proto (snat_protocol_t snat_proto) } static_always_inline u8 -icmp_is_error_message (icmp46_header_t * icmp) +icmp_type_is_error_message (u8 icmp_type) { - switch (icmp->type) + switch (icmp_type) { case ICMP4_destination_unreachable: case ICMP4_time_exceeded: @@ -286,8 +286,9 @@ nat44_delete_user_with_no_session (snat_main_t * sm, snat_user_t * u, } always_inline void -nat44_delete_session (snat_main_t * sm, snat_session_t * ses, - u32 thread_index) +nat44_delete_session_internal (snat_main_t * sm, snat_session_t * ses, + u32 thread_index, int global_lru_delete + /* delete from global LRU list */ ) { snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data, thread_index); @@ -301,6 +302,11 @@ nat44_delete_session (snat_main_t * sm, snat_session_t * ses, clib_dlist_remove (tsm->list_pool, ses->per_user_index); pool_put_index (tsm->list_pool, ses->per_user_index); + if (global_lru_delete) + { + clib_dlist_remove (tsm->global_lru_pool, ses->global_lru_index); + } + pool_put_index (tsm->global_lru_pool, ses->global_lru_index); pool_put (tsm->sessions, ses); vlib_set_simple_counter (&sm->total_sessions, thread_index, 0, pool_elts (tsm->sessions)); @@ -318,70 +324,89 @@ nat44_delete_session (snat_main_t * sm, snat_session_t * ses, } } +always_inline void +nat44_delete_session (snat_main_t * sm, snat_session_t * ses, + u32 thread_index) +{ + return nat44_delete_session_internal (sm, ses, thread_index, 1); +} + +always_inline void +nat44_ed_delete_session (snat_main_t * sm, snat_session_t * ses, + u32 thread_index, int global_lru_delete + /* delete from global LRU list */ ) +{ + return nat44_delete_session_internal (sm, ses, thread_index, + global_lru_delete); +} + /** \brief Set TCP session state. @return 1 if session was closed, otherwise 0 */ always_inline int -nat44_set_tcp_session_state_i2o (snat_main_t * sm, snat_session_t * ses, - tcp_header_t * tcp, u32 thread_index) +nat44_set_tcp_session_state_i2o (snat_main_t * sm, f64 now, + snat_session_t * ses, vlib_buffer_t * b, + u32 thread_index) { - if ((ses->state == 0) && (tcp->flags & TCP_FLAG_RST)) + 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)) + 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) && + 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) + if (tcp_flags & TCP_FLAG_SYN) ses->state |= NAT44_SES_I2O_SYN; - if (tcp->flags & TCP_FLAG_FIN) + if (tcp_flags & TCP_FLAG_FIN) { - ses->i2o_fin_seq = clib_net_to_host_u32 (tcp->seq_number); + 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)) - { - if (clib_net_to_host_u32 (tcp->ack_number) > ses->o2i_fin_seq) - ses->state |= NAT44_SES_O2I_FIN_ACK; - } - if (nat44_is_ses_closed (ses) - && !(ses->flags & SNAT_SESSION_FLAG_OUTPUT_FEATURE)) + if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN)) { - nat_free_session_data (sm, ses, thread_index, 0); - nat44_delete_session (sm, ses, thread_index); - return 1; + if (clib_net_to_host_u32 (tcp_ack_number) > ses->o2i_fin_seq) + { + ses->state |= NAT44_SES_O2I_FIN_ACK; + if (nat44_is_ses_closed (ses)) + { // if session is now closed, save the timestamp + ses->tcp_close_timestamp = now + sm->tcp_transitory_timeout; + } + } } return 0; } always_inline int -nat44_set_tcp_session_state_o2i (snat_main_t * sm, snat_session_t * ses, - tcp_header_t * tcp, u32 thread_index) +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) { - if ((ses->state == 0) && (tcp->flags & TCP_FLAG_RST)) + 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)) + 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) && + 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) + if (tcp_flags & TCP_FLAG_SYN) ses->state |= NAT44_SES_O2I_SYN; - if (tcp->flags & TCP_FLAG_FIN) + if (tcp_flags & TCP_FLAG_FIN) { - ses->o2i_fin_seq = clib_net_to_host_u32 (tcp->seq_number); + 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)) + if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN)) { - if (clib_net_to_host_u32 (tcp->ack_number) > ses->i2o_fin_seq) + 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)) - { - nat_free_session_data (sm, ses, thread_index, 0); - nat44_delete_session (sm, ses, thread_index); - return 1; + if (nat44_is_ses_closed (ses)) + { // if session is now closed, save the timestamp + ses->tcp_close_timestamp = now + sm->tcp_transitory_timeout; + } } return 0; } @@ -427,10 +452,22 @@ always_inline void nat44_session_update_lru (snat_main_t * sm, snat_session_t * s, u32 thread_index) { - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s->per_user_list_head_index, s->per_user_index); + /* don't update too often - timeout is in a magnitude of seconds anyway */ + if (s->last_heard > s->last_lru_update + 1) + { + clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, + s->per_user_index); + clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, + s->per_user_list_head_index, s->per_user_index); + + clib_dlist_remove (sm->per_thread_data[thread_index].global_lru_pool, + s->global_lru_index); + clib_dlist_addtail (sm->per_thread_data[thread_index].global_lru_pool, + sm-> + per_thread_data[thread_index].global_lru_head_index, + s->global_lru_index); + s->last_lru_update = s->last_heard; + } } always_inline void @@ -466,7 +503,8 @@ make_sm_kv (clib_bihash_kv_8_8_t * kv, ip4_address_t * addr, u8 proto, } static_always_inline int -get_icmp_i2o_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0) +get_icmp_i2o_ed_key (vlib_buffer_t * b, ip4_header_t * ip0, + nat_ed_ses_key_t * p_key0) { icmp46_header_t *icmp0; nat_ed_ses_key_t key0; @@ -478,12 +516,13 @@ get_icmp_i2o_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0) icmp0 = (icmp46_header_t *) ip4_next_header (ip0); echo0 = (icmp_echo_header_t *) (icmp0 + 1); - if (!icmp_is_error_message (icmp0)) + if (!icmp_type_is_error_message + (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)) { key0.proto = IP_PROTOCOL_ICMP; key0.l_addr = ip0->src_address; key0.r_addr = ip0->dst_address; - key0.l_port = echo0->identifier; + key0.l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst? key0.r_port = 0; } else @@ -516,7 +555,8 @@ get_icmp_i2o_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0) static_always_inline int -get_icmp_o2i_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0) +get_icmp_o2i_ed_key (vlib_buffer_t * b, ip4_header_t * ip0, + nat_ed_ses_key_t * p_key0) { icmp46_header_t *icmp0; nat_ed_ses_key_t key0; @@ -528,12 +568,13 @@ get_icmp_o2i_ed_key (ip4_header_t * ip0, nat_ed_ses_key_t * p_key0) icmp0 = (icmp46_header_t *) ip4_next_header (ip0); echo0 = (icmp_echo_header_t *) (icmp0 + 1); - if (!icmp_is_error_message (icmp0)) + if (!icmp_type_is_error_message + (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags)) { key0.proto = IP_PROTOCOL_ICMP; key0.l_addr = ip0->dst_address; key0.r_addr = ip0->src_address; - key0.l_port = echo0->identifier; + key0.l_port = vnet_buffer (b)->ip.reass.l4_src_port; // TODO should this be src or dst? key0.r_port = 0; } else @@ -684,6 +725,15 @@ snat_not_translate_fast (snat_main_t * sm, vlib_node_runtime_t * node, return 1; } +static inline void +increment_v4_address (ip4_address_t * a) +{ + u32 v; + + v = clib_net_to_host_u32 (a->as_u32) + 1; + a->as_u32 = clib_host_to_net_u32 (v); +} + #endif /* __included_nat_inlines_h__ */ /*