X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fout2in_ed.c;h=5d759fbfad596ddce9cf9d7e0f9738d77941ed00;hb=4496243cc9c9f5a64483923e1f158cab74aca18a;hp=667d33e6266be02d1f0043b7480b0e4d9794adf9;hpb=71f62a52a2abaeb8b4fc8c70fde501fa7400417c;p=vpp.git diff --git a/src/plugins/nat/out2in_ed.c b/src/plugins/nat/out2in_ed.c index 667d33e6266..5d759fbfad5 100644 --- a/src/plugins/nat/out2in_ed.c +++ b/src/plugins/nat/out2in_ed.c @@ -31,6 +31,7 @@ #include #include #include +#include static char *nat_out2in_ed_error_strings[] = { #define _(sym,string) string, @@ -122,7 +123,7 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) } else { - proto = snat_proto_to_ip_proto (s->in2out.protocol); + proto = nat_proto_to_ip_proto (s->in2out.protocol); l_port = s->in2out.port; r_port = s->ext_host_port; } @@ -131,7 +132,7 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) r_addr = &s->ext_host_nat_addr; r_port = s->ext_host_nat_port; } - make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0ULL, + make_ed_kv (l_addr, r_addr, proto, fib_index, l_port, r_port, ~0, ~0, &ed_kv); if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &ed_kv, 0)) nat_elog_warn ("in2out_ed key del failed"); @@ -181,7 +182,7 @@ nat44_o2i_ed_is_idle_session_cb (clib_bihash_kv_16_8_t * kv, void *arg) snat_free_outside_address_and_port (sm->addresses, ctx->thread_index, &s->out2in); delete: - nat44_ed_delete_session (sm, s, ctx->thread_index, 1); + nat_ed_session_delete (sm, s, ctx->thread_index, 1); return 1; } @@ -216,7 +217,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, return 0; } - s = nat_ed_session_alloc (sm, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now, e_key.protocol); if (!s) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED]; @@ -228,7 +229,7 @@ create_session_for_static_mapping_ed (snat_main_t * sm, udp = ip4_next_header (ip); s->ext_host_addr.as_u32 = ip->src_address.as_u32; - s->ext_host_port = e_key.protocol == SNAT_PROTOCOL_ICMP ? 0 : udp->src_port; + s->ext_host_port = e_key.protocol == NAT_PROTOCOL_ICMP ? 0 : udp->src_port; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; if (lb_nat) s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; @@ -241,11 +242,11 @@ create_session_for_static_mapping_ed (snat_main_t * sm, /* Add to lookup tables */ make_ed_kv (&e_key.addr, &s->ext_host_addr, ip->protocol, - e_key.fib_index, e_key.port, s->ext_host_port, + e_key.fib_index, e_key.port, s->ext_host_port, thread_index, s - tsm->sessions, &kv); ctx.now = now; ctx.thread_index = thread_index; - if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->out2in_ed, &kv, + if (clib_bihash_add_or_overwrite_stale_16_8 (&sm->out2in_ed, &kv, nat44_o2i_ed_is_idle_session_cb, &ctx)) nat_elog_notice ("out2in-ed key add failed"); @@ -260,8 +261,8 @@ create_session_for_static_mapping_ed (snat_main_t * sm, tsm->snat_thread_index)) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_OUT_OF_PORTS]; - nat44_ed_delete_session (sm, s, thread_index, 1); - if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &kv, 0)) + nat_ed_session_delete (sm, s, thread_index, 1); + if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &kv, 0)) nat_elog_notice ("out2in-ed key del failed"); return 0; } @@ -270,12 +271,12 @@ create_session_for_static_mapping_ed (snat_main_t * sm, s->flags |= SNAT_SESSION_FLAG_TWICE_NAT; make_ed_kv (&l_key.addr, &s->ext_host_nat_addr, ip->protocol, l_key.fib_index, l_key.port, s->ext_host_nat_port, - s - tsm->sessions, &kv); + thread_index, s - tsm->sessions, &kv); } else { make_ed_kv (&l_key.addr, &s->ext_host_addr, ip->protocol, - l_key.fib_index, l_key.port, s->ext_host_port, + l_key.fib_index, l_key.port, s->ext_host_port, thread_index, s - tsm->sessions, &kv); } if (clib_bihash_add_or_overwrite_stale_16_8 (&tsm->in2out_ed, &kv, @@ -314,7 +315,7 @@ next_src_nat (snat_main_t * sm, ip4_header_t * ip, u16 src_port, snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; make_ed_kv (&ip->src_address, &ip->dst_address, ip->protocol, - rx_fib_index, src_port, dst_port, ~0ULL, &kv); + rx_fib_index, src_port, dst_port, ~0, ~0, &kv); if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value)) return 1; @@ -336,7 +337,7 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, if (ip->protocol == IP_PROTOCOL_ICMP) { if (get_icmp_o2i_ed_key - (b, ip, rx_fib_index, ~0ULL, 0, &l_port, &r_port, &kv)) + (b, ip, rx_fib_index, ~0, ~0, 0, &l_port, &r_port, &kv)) return; } else @@ -353,12 +354,15 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, r_port = 0; } make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol, - rx_fib_index, l_port, r_port, ~0ULL, &kv); + rx_fib_index, l_port, r_port, ~0, ~0, &kv); } if (!clib_bihash_search_16_8 (&tsm->in2out_ed, &kv, &value)) { - s = pool_elt_at_index (tsm->sessions, value.value); + ASSERT (thread_index == ed_value_get_thread_index (&value)); + s = + pool_elt_at_index (tsm->sessions, + ed_value_get_session_index (&value)); } else { @@ -369,14 +373,14 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, (sm, rx_fib_index, thread_index))) return; - s = nat_ed_session_alloc (sm, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol); if (!s) { nat_elog_warn ("create NAT session failed"); return; } - proto = ip_proto_to_snat_proto (ip->protocol); + proto = ip_proto_to_nat_proto (ip->protocol); s->ext_host_addr = ip->src_address; s->ext_host_port = r_port; @@ -384,7 +388,7 @@ create_bypass_for_fwd (snat_main_t * sm, vlib_buffer_t * b, ip4_header_t * ip, s->out2in.addr = ip->dst_address; s->out2in.port = l_port; s->out2in.protocol = proto; - if (proto == ~0) + if (proto == NAT_PROTOCOL_OTHER) { s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; s->out2in.port = ip->protocol; @@ -444,19 +448,19 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node, rx_fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); if (get_icmp_o2i_ed_key - (b, ip, rx_fib_index, ~0ULL, p_proto, &l_port, &r_port, &kv)) + (b, ip, rx_fib_index, ~0, ~0, p_proto, &l_port, &r_port, &kv)) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_UNSUPPORTED_PROTOCOL]; next = NAT_NEXT_DROP; goto out; } - if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value)) + if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv, &value)) { /* Try to match static mapping */ e_key.addr = ip->dst_address; e_key.port = l_port; - e_key.protocol = ip_proto_to_snat_proto (ip->protocol); + e_key.protocol = ip_proto_to_nat_proto (ip->protocol); e_key.fib_index = rx_fib_index; if (snat_static_mapping_match (sm, e_key, &l_key, 1, &is_addr_only, 0, 0, 0, &identity_nat)) @@ -534,7 +538,10 @@ icmp_match_out2in_ed (snat_main_t * sm, vlib_node_runtime_t * node, goto out; } - s = pool_elt_at_index (tsm->sessions, value.value); + ASSERT (thread_index == ed_value_get_thread_index (&value)); + s = + pool_elt_at_index (tsm->sessions, + ed_value_get_session_index (&value)); } out: if (s) @@ -566,11 +573,14 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, old_addr = ip->dst_address.as_u32; make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol, rx_fib_index, - 0, 0, ~0ULL, &s_kv); + 0, 0, ~0, ~0, &s_kv); - if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &s_kv, &s_value)) + if (!clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value)) { - s = pool_elt_at_index (tsm->sessions, s_value.value); + ASSERT (thread_index == ed_value_get_thread_index (&s_value)); + s = + pool_elt_at_index (tsm->sessions, + ed_value_get_session_index (&s_value)); new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32; } else @@ -597,7 +607,7 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32; /* Create a new session */ - s = nat_ed_session_alloc (sm, thread_index, now); + s = nat_ed_session_alloc (sm, thread_index, now, ip->protocol); if (!s) { b->error = node->errors[NAT_OUT2IN_ED_ERROR_MAX_USER_SESS_EXCEEDED]; @@ -617,11 +627,11 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, /* Add to lookup tables */ s_kv.value = s - tsm->sessions; - if (clib_bihash_add_del_16_8 (&tsm->out2in_ed, &s_kv, 1)) + if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1)) nat_elog_notice ("out2in key add failed"); make_ed_kv (&ip->dst_address, &ip->src_address, ip->protocol, - m->fib_index, 0, 0, s - tsm->sessions, &s_kv); + m->fib_index, 0, 0, thread_index, s - tsm->sessions, &s_kv); if (clib_bihash_add_del_16_8 (&tsm->in2out_ed, &s_kv, 1)) nat_elog_notice ("in2out key add failed"); } @@ -645,7 +655,8 @@ nat44_ed_out2in_unknown_proto (snat_main_t * sm, static inline uword nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_frame_t * frame, + int is_multi_worker) { u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index; nat_next_t next_index; @@ -713,15 +724,15 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, udp0 = ip4_next_header (ip0); tcp0 = (tcp_header_t *) udp0; - proto0 = ip_proto_to_snat_proto (ip0->protocol); + proto0 = ip_proto_to_nat_proto (ip0->protocol); - if (PREDICT_FALSE (proto0 == ~0)) + if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER)) { next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } - if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) { next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; @@ -730,18 +741,48 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, make_ed_kv (&ip0->dst_address, &ip0->src_address, ip0->protocol, rx_fib_index0, vnet_buffer (b0)->ip.reass.l4_dst_port, - vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0); + vnet_buffer (b0)->ip.reass.l4_src_port, ~0, ~0, &kv0); + + /* there is a stashed index in vnet_buffer2 from handoff node, + * see if we can use it */ + if (is_multi_worker && PREDICT_TRUE + (!pool_is_free_index + (tsm->sessions, + vnet_buffer2 (b0)->nat.ed_out2in_nat_session_index))) + { + s0 = pool_elt_at_index (tsm->sessions, + vnet_buffer2 (b0)-> + nat.ed_out2in_nat_session_index); + if (PREDICT_TRUE + (s0->out2in.addr.as_u32 == ip0->dst_address.as_u32 + && s0->out2in.port == + vnet_buffer (b0)->ip.reass.l4_dst_port + && s0->out2in.protocol == + ip_proto_to_nat_proto (ip0->protocol) + && s0->out2in.fib_index == rx_fib_index0 + && s0->ext_host_addr.as_u32 == ip0->src_address.as_u32 + && s0->ext_host_port == + vnet_buffer (b0)->ip.reass.l4_src_port)) + { + /* yes, this is the droid we're looking for */ + goto skip_lookup; + } + } - if (clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0)) + if (clib_bihash_search_16_8 (&sm->out2in_ed, &kv0, &value0)) { next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } - s0 = pool_elt_at_index (tsm->sessions, value0.value); + ASSERT (thread_index == ed_value_get_thread_index (&value0)); + s0 = + pool_elt_at_index (tsm->sessions, + ed_value_get_session_index (&value0)); - if (s0->tcp_close_timestamp) + skip_lookup: + if (s0->tcp_closed_timestamp) { - if (now >= s0->tcp_close_timestamp) + if (now >= s0->tcp_closed_timestamp) { // session is closed, go slow path next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; @@ -763,7 +804,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, { // session is closed, go slow path nat_free_session_data (sm, s0, thread_index, 0); - nat44_ed_delete_session (sm, s0, thread_index, 1); + nat_ed_session_delete (sm, s0, thread_index, 1); next0 = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } @@ -784,7 +825,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port; - if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP)) + if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP)) { if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment) { @@ -918,7 +959,6 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, u32 n_left_from, *from, *to_next, pkts_processed = 0, stats_node_index; nat_next_t next_index; snat_main_t *sm = &snat_main; - // HERE f64 now = vlib_time_now (vm); u32 thread_index = vm->thread_index; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; @@ -988,9 +1028,9 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, udp0 = ip4_next_header (ip0); tcp0 = (tcp_header_t *) udp0; icmp0 = (icmp46_header_t *) udp0; - proto0 = ip_proto_to_snat_proto (ip0->protocol); + proto0 = ip_proto_to_nat_proto (ip0->protocol); - if (PREDICT_FALSE (proto0 == ~0)) + if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER)) { s0 = nat44_ed_out2in_unknown_proto (sm, b0, ip0, rx_fib_index0, @@ -1004,7 +1044,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, goto trace0; } - if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_ICMP)) + if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP)) { next0 = icmp_out2in_ed_slow_path (sm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, @@ -1016,17 +1056,20 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, make_ed_kv (&ip0->dst_address, &ip0->src_address, ip0->protocol, rx_fib_index0, vnet_buffer (b0)->ip.reass.l4_dst_port, - vnet_buffer (b0)->ip.reass.l4_src_port, ~0ULL, &kv0); + vnet_buffer (b0)->ip.reass.l4_src_port, ~0, ~0, &kv0); s0 = NULL; - if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv0, &value0)) + if (!clib_bihash_search_16_8 (&sm->out2in_ed, &kv0, &value0)) { - s0 = pool_elt_at_index (tsm->sessions, value0.value); + ASSERT (thread_index == ed_value_get_thread_index (&value0)); + s0 = + pool_elt_at_index (tsm->sessions, + ed_value_get_session_index (&value0)); - if (s0->tcp_close_timestamp && now >= s0->tcp_close_timestamp) + if (s0->tcp_closed_timestamp && now >= s0->tcp_closed_timestamp) { nat_free_session_data (sm, s0, thread_index, 0); - nat44_ed_delete_session (sm, s0, thread_index, 1); + nat_ed_session_delete (sm, s0, thread_index, 1); s0 = NULL; } } @@ -1049,7 +1092,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, * Send DHCP packets to the ipv4 stack, or we won't * be able to use dhcp client on the outside interface */ - if (PREDICT_FALSE (proto0 == SNAT_PROTOCOL_UDP + if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_UDP && (vnet_buffer (b0)->ip. reass.l4_dst_port == clib_host_to_net_u16 @@ -1074,7 +1117,6 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, next0 = NAT_NEXT_IN2OUT_ED_FAST_PATH; goto trace0; } - // TEST: if (sm->num_workers > 1) create_bypass_for_fwd_worker (sm, b0, ip0, rx_fib_index0); @@ -1088,7 +1130,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (PREDICT_FALSE (identity_nat0)) goto trace0; - if ((proto0 == SNAT_PROTOCOL_TCP) + if ((proto0 == NAT_PROTOCOL_TCP) && !tcp_flags_is_init (vnet_buffer (b0)->ip. reass.icmp_type_or_tcp_flags)) { @@ -1126,7 +1168,7 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, old_port0 = vnet_buffer (b0)->ip.reass.l4_dst_port; - if (PREDICT_TRUE (proto0 == SNAT_PROTOCOL_TCP)) + if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP)) { if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment) { @@ -1256,7 +1298,14 @@ VLIB_NODE_FN (nat44_ed_out2in_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame); + if (snat_main.num_workers > 1) + { + return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 1); + } + else + { + return nat44_ed_out2in_fast_path_node_fn_inline (vm, node, frame, 0); + } } /* *INDENT-OFF* */ @@ -1298,7 +1347,8 @@ format_nat_pre_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); nat_pre_trace_t *t = va_arg (*args, nat_pre_trace_t *); - return format (s, "out2in next_index %d", t->next_index); + return format (s, "out2in next_index %d arc_next_index %d", t->next_index, + t->arc_next_index); } VLIB_NODE_FN (nat_pre_out2in_node) (vlib_main_t * vm,