X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fout2in_ed.c;h=5b70b0c672aea09a30bc78c07c689671c5e83c8d;hb=ba5f9bc7534bcf58225b0658993728b1f4d47a67;hp=420b7b7a8630be00740f94aff405d140f7234cf5;hpb=a73f2d6f53c224668bd6bbea1a980ee4313c794f;p=vpp.git diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c index 420b7b7a863..5b70b0c672a 100644 --- a/src/plugins/nat/out2in_ed.c +++ b/src/plugins/nat/out2in_ed.c @@ -131,6 +131,16 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) 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; @@ -213,6 +223,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, 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; } @@ -220,6 +231,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, 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; @@ -412,7 +424,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; } @@ -613,6 +626,7 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, thread_index); if (!u) { + b->error = node->errors[NAT_OUT2IN_ED_ERROR_CANNOT_CREATE_USER]; nat_elog_warn ("create NAT user failed"); return 0; } @@ -621,6 +635,7 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, 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; @@ -762,17 +777,32 @@ 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]; + 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; } // @@ -822,7 +852,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; @@ -1001,13 +1032,13 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, 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)) @@ -1024,7 +1055,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 */ @@ -1103,10 +1147,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; @@ -1153,7 +1193,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;