From 76401c5767ecdf701f4c77beee0b721c485321d5 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Wed, 3 Mar 2021 22:14:55 +0100 Subject: nat: fix worker selection Use correct ports from SVR. Perform lookup of existing session for all cases to pick any created bypasses and derive correct thread indexes. Type: fix Change-Id: I1e3814c9e13cd4d9b8d65f514f7e9ab42df3c22e Signed-off-by: Klement Sekera --- src/plugins/nat/nat44-ed/nat44_ed.c | 98 ++++++++++++++--------------- src/plugins/nat/nat44-ed/nat44_ed.h | 9 +-- src/plugins/nat/nat44-ed/nat44_ed_api.c | 5 +- src/plugins/nat/nat44-ed/nat44_ed_handoff.c | 10 +-- src/plugins/nat/nat44-ed/nat44_ed_in2out.c | 27 ++++---- src/plugins/nat/nat44-ed/nat44_ed_out2in.c | 11 ++-- src/plugins/nat/nat44-ei/nat44_ei.c | 2 +- 7 files changed, 73 insertions(+), 89 deletions(-) diff --git a/src/plugins/nat/nat44-ed/nat44_ed.c b/src/plugins/nat/nat44-ed/nat44_ed.c index 6f2cd11e695..0d62e788ec1 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.c +++ b/src/plugins/nat/nat44-ed/nat44_ed.c @@ -182,9 +182,8 @@ static u32 nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, u32 rx_fib_index, u8 is_output); -static u32 -nat44_ed_get_worker_in2out_cb (ip4_header_t * ip, u32 rx_fib_index, - u8 is_output); +static u32 nat44_ed_get_worker_in2out_cb (vlib_buffer_t *b, ip4_header_t *ip, + u32 rx_fib_index, u8 is_output); u32 nat_calc_bihash_buckets (u32 n_elts); @@ -738,7 +737,8 @@ snat_add_static_mapping (ip4_address_t l_addr, ip4_address_t e_addr, ip4_header_t ip = { .src_address = m->local_addr, }; - vec_add1 (m->workers, sm->worker_in2out_cb (&ip, m->fib_index, 0)); + vec_add1 (m->workers, + sm->worker_in2out_cb (0, &ip, m->fib_index, 0)); tsm = vec_elt_at_index (sm->per_thread_data, m->workers[0]); } else @@ -988,10 +988,8 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, ip4_header_t ip = { .src_address = locals[i].addr, }; - bitmap = - clib_bitmap_set (bitmap, - sm->worker_in2out_cb (&ip, m->fib_index, 0), - 1); + bitmap = clib_bitmap_set ( + bitmap, sm->worker_in2out_cb (0, &ip, m->fib_index, 0), 1); } } @@ -1057,9 +1055,11 @@ nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port, sm->fib_src_low); if (!out2in_only) { -init_nat_k(& kv, local->addr, local->port, local->fib_index, m->proto); - if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0)) - { + init_nat_k (&kv, local->addr, local->port, local->fib_index, + m->proto); + if (clib_bihash_add_del_8_8 (&sm->static_mapping_by_local, &kv, + 0)) + { nat_elog_err (sm, "static_mapping_by_local key del failed"); return VNET_API_ERROR_UNSPECIFIED; } @@ -1070,9 +1070,9 @@ init_nat_k(& kv, local->addr, local->port, local->fib_index, m->pro ip4_header_t ip = { .src_address = local->addr, }; - tsm = - vec_elt_at_index (sm->per_thread_data, - sm->worker_in2out_cb (&ip, m->fib_index, 0)); + tsm = vec_elt_at_index ( + sm->per_thread_data, + sm->worker_in2out_cb (0, &ip, m->fib_index, 0)); } else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); @@ -1188,9 +1188,9 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port, ip4_header_t ip = { .src_address = local->addr, }; - tsm = vec_elt_at_index (sm->per_thread_data, - sm->worker_in2out_cb (&ip, m->fib_index, - 0)); + tsm = + vec_elt_at_index (sm->per_thread_data, + sm->worker_in2out_cb (0, &ip, m->fib_index, 0)); } else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); @@ -1222,10 +1222,9 @@ nat44_lb_static_mapping_add_del_local (ip4_address_t e_addr, u16 e_port, if (sm->num_workers > 1) { ip4_header_t ip; - ip.src_address.as_u32 = local->addr.as_u32, - bitmap = clib_bitmap_set (bitmap, - sm->worker_in2out_cb (&ip, local->fib_index, 0), - 1); + ip.src_address.as_u32 = local->addr.as_u32, + bitmap = clib_bitmap_set ( + bitmap, sm->worker_in2out_cb (0, &ip, local->fib_index, 0), 1); } } /* *INDENT-ON* */ @@ -2485,12 +2484,12 @@ snat_static_mapping_match (snat_main_t * sm, .src_address = local->addr, }; - if (sm->worker_in2out_cb (&ip, m->fib_index, 0) == + if (sm->worker_in2out_cb (0, &ip, m->fib_index, 0) == thread_index) - { - vec_add1 (tmp, i); - } - } + { + vec_add1 (tmp, i); + } + } ASSERT (vec_len (tmp) != 0); } else @@ -2562,20 +2561,19 @@ end: } static u32 -nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index, - u8 is_output) +nat44_ed_get_worker_in2out_cb (vlib_buffer_t *b, ip4_header_t *ip, + u32 rx_fib_index, u8 is_output) { snat_main_t *sm = &snat_main; u32 next_worker_index = sm->first_worker_index; u32 hash; clib_bihash_kv_16_8_t kv16, value16; - snat_main_per_thread_data_t *tsm; - udp_header_t *udp; + u32 fib_index = rx_fib_index; if (PREDICT_FALSE (is_output)) { - u32 fib_index = sm->outside_fib_index; + fib_index = sm->outside_fib_index; nat_outside_fib_t *outside_fib; fib_node_index_t fei = FIB_NODE_INDEX_INVALID; fib_prefix_t pfx = { @@ -2587,8 +2585,6 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index, , }; - udp = ip4_next_header (ip); - switch (vec_len (sm->outside_fibs)) { case 0: @@ -2614,24 +2610,21 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index, /* *INDENT-ON* */ break; } + } - init_ed_k (&kv16, ip->src_address, udp->src_port, ip->dst_address, - udp->dst_port, fib_index, ip->protocol); + if (b) + { + init_ed_k (&kv16, ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, + ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, + fib_index, ip->protocol); if (PREDICT_TRUE ( !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))) { - tsm = - vec_elt_at_index (sm->per_thread_data, - ed_value_get_thread_index (&value16)); - next_worker_index += tsm->thread_index; - - nat_elog_debug_handoff ( - sm, "HANDOFF IN2OUT-OUTPUT-FEATURE (session)", next_worker_index, - fib_index, clib_net_to_host_u32 (ip->src_address.as_u32), - clib_net_to_host_u32 (ip->dst_address.as_u32)); - - return next_worker_index; + next_worker_index = ed_value_get_thread_index (&value16); + vnet_buffer2 (b)->nat.cached_session_index = + ed_value_get_session_index (&value16); + goto out; } } @@ -2643,6 +2636,7 @@ nat44_ed_get_worker_in2out_cb (ip4_header_t *ip, u32 rx_fib_index, else next_worker_index += sm->workers[hash % _vec_len (sm->workers)]; +out: if (PREDICT_TRUE (!is_output)) { nat_elog_debug_handoff (sm, "HANDOFF IN2OUT", next_worker_index, @@ -2682,8 +2676,9 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, { udp = ip4_next_header (ip); - init_ed_k (&kv16, ip->dst_address, udp->dst_port, ip->src_address, - udp->src_port, rx_fib_index, ip->protocol); + init_ed_k (&kv16, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, + ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, + rx_fib_index, ip->protocol); if (PREDICT_TRUE ( !clib_bihash_search_16_8 (&sm->flow_hash, &kv16, &value16))) @@ -2750,7 +2745,7 @@ nat44_ed_get_worker_out2in_cb (vlib_buffer_t * b, ip4_header_t * ip, } udp = ip4_next_header (ip); - port = udp->dst_port; + port = vnet_buffer (b)->ip.reass.l4_dst_port; if (PREDICT_FALSE (ip->protocol == IP_PROTOCOL_ICMP)) { @@ -3220,9 +3215,8 @@ nat44_del_ed_session (snat_main_t * sm, ip4_address_t * addr, u16 port, ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32; if (sm->num_workers > 1) - tsm = - vec_elt_at_index (sm->per_thread_data, - sm->worker_in2out_cb (&ip, fib_index, 0)); + tsm = vec_elt_at_index (sm->per_thread_data, + sm->worker_in2out_cb (0, &ip, fib_index, 0)); else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h index 902e5e34b14..c6bccd9f492 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.h +++ b/src/plugins/nat/nat44-ed/nat44_ed.h @@ -190,7 +190,6 @@ typedef enum #define NAT_STATIC_MAPPING_FLAG_LB 8 #define NAT_STATIC_MAPPING_FLAG_EXACT_ADDRESS 16 -/* *INDENT-OFF* */ typedef CLIB_PACKED(struct { // number of sessions in this vrf @@ -202,7 +201,6 @@ typedef CLIB_PACKED(struct // is this vrf expired u8 expired; }) per_vrf_sessions_t; -/* *INDENT-ON* */ typedef union { @@ -287,7 +285,6 @@ nat_6t_flow_icmp_id_rewrite_set (nat_6t_flow_t *f, u16 id) f->rewrite.icmp_id = id; } -/* *INDENT-OFF* */ typedef CLIB_PACKED(struct { /* Outside network tuple */ @@ -348,20 +345,17 @@ typedef CLIB_PACKED(struct u32 per_vrf_sessions_index; }) snat_session_t; -/* *INDENT-ON* */ typedef struct { ip4_address_t addr; u32 fib_index; -/* *INDENT-OFF* */ #define _(N, i, n, s) \ u32 busy_##n##_ports; \ u32 * busy_##n##_ports_per_thread; \ u32 busy_##n##_port_refcounts[65535]; foreach_nat_protocol #undef _ -/* *INDENT-ON* */ } snat_address_t; typedef struct @@ -496,7 +490,8 @@ typedef struct struct snat_main_s; /* Return worker thread index for given packet */ -typedef u32 (snat_get_worker_in2out_function_t) (ip4_header_t * ip, +typedef u32 (snat_get_worker_in2out_function_t) (vlib_buffer_t *b, + ip4_header_t *ip, u32 rx_fib_index, u8 is_output); diff --git a/src/plugins/nat/nat44-ed/nat44_ed_api.c b/src/plugins/nat/nat44-ed/nat44_ed_api.c index c6c505e0daf..3089f68950f 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_api.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_api.c @@ -1529,9 +1529,8 @@ vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t * ip.src_address.as_u32 = ukey.addr.as_u32; ukey.fib_index = fib_table_find (FIB_PROTOCOL_IP4, ntohl (mp->vrf_id)); if (sm->num_workers > 1) - tsm = - vec_elt_at_index (sm->per_thread_data, - sm->worker_in2out_cb (&ip, ukey.fib_index, 0)); + tsm = vec_elt_at_index (sm->per_thread_data, + sm->worker_in2out_cb (0, &ip, ukey.fib_index, 0)); else tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers); diff --git a/src/plugins/nat/nat44-ed/nat44_ed_handoff.c b/src/plugins/nat/nat44-ed/nat44_ed_handoff.c index 6715ce2f2c4..e286df93a6e 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_handoff.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_handoff.c @@ -157,10 +157,10 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm, if (is_in2out) { - ti[0] = sm->worker_in2out_cb (ip0, rx_fib_index0, is_output); - ti[1] = sm->worker_in2out_cb (ip1, rx_fib_index1, is_output); - ti[2] = sm->worker_in2out_cb (ip2, rx_fib_index2, is_output); - ti[3] = sm->worker_in2out_cb (ip3, rx_fib_index3, is_output); + ti[0] = sm->worker_in2out_cb (b[0], ip0, rx_fib_index0, is_output); + ti[1] = sm->worker_in2out_cb (b[1], ip1, rx_fib_index1, is_output); + ti[2] = sm->worker_in2out_cb (b[2], ip2, rx_fib_index2, is_output); + ti[3] = sm->worker_in2out_cb (b[3], ip3, rx_fib_index3, is_output); } else { @@ -218,7 +218,7 @@ nat44_worker_handoff_fn_inline (vlib_main_t * vm, if (is_in2out) { - ti[0] = sm->worker_in2out_cb (ip0, rx_fib_index0, is_output); + ti[0] = sm->worker_in2out_cb (b[0], ip0, rx_fib_index0, is_output); } else { diff --git a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c index 59355e49ccd..885851c46b6 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_in2out.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_in2out.c @@ -554,15 +554,15 @@ error: } static_always_inline int -nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node, - u32 sw_if_index, ip4_header_t * ip, u32 proto, - u32 rx_fib_index, u32 thread_index) +nat44_ed_not_translate (snat_main_t *sm, vlib_node_runtime_t *node, + u32 sw_if_index, vlib_buffer_t *b, ip4_header_t *ip, + u32 proto, u32 rx_fib_index, u32 thread_index) { - udp_header_t *udp = ip4_next_header (ip); clib_bihash_kv_16_8_t kv, value; - init_ed_k (&kv, ip->dst_address, udp->dst_port, ip->src_address, - udp->src_port, sm->outside_fib_index, ip->protocol); + init_ed_k (&kv, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, + ip->src_address, vnet_buffer (b)->ip.reass.l4_src_port, + sm->outside_fib_index, ip->protocol); /* NAT packet aimed at external address if has active sessions */ if (clib_bihash_search_16_8 (&sm->flow_hash, &kv, &value)) @@ -571,10 +571,10 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node, ip4_address_t placeholder_addr; u16 placeholder_port; u32 placeholder_fib_index; - if (!snat_static_mapping_match - (sm, ip->dst_address, udp->dst_port, sm->outside_fib_index, proto, - &placeholder_addr, &placeholder_port, &placeholder_fib_index, 1, 0, - 0, 0, 0, 0, 0)) + if (!snat_static_mapping_match ( + sm, ip->dst_address, vnet_buffer (b)->ip.reass.l4_dst_port, + sm->outside_fib_index, proto, &placeholder_addr, &placeholder_port, + &placeholder_fib_index, 1, 0, 0, 0, 0, 0, 0)) return 0; } else @@ -742,7 +742,7 @@ icmp_in2out_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, } else { - if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index, ip, + if (PREDICT_FALSE (nat44_ed_not_translate (sm, node, sw_if_index, b, ip, NAT_PROTOCOL_ICMP, rx_fib_index, thread_index))) { @@ -1373,9 +1373,8 @@ nat44_ed_in2out_slow_path_node_fn_inline (vlib_main_t * vm, } else { - if (PREDICT_FALSE - (nat44_ed_not_translate - (sm, node, sw_if_index0, ip0, proto0, rx_fib_index0, + if (PREDICT_FALSE (nat44_ed_not_translate ( + sm, node, sw_if_index0, b0, ip0, proto0, rx_fib_index0, thread_index))) goto trace0; } diff --git a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c index 90f2ec32155..d3fd50953e0 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c @@ -372,7 +372,6 @@ create_session_for_static_mapping_ed ( { snat_session_t *s; ip4_header_t *ip; - udp_header_t *udp; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; if (PREDICT_FALSE @@ -392,10 +391,10 @@ create_session_for_static_mapping_ed ( } ip = vlib_buffer_get_current (b); - udp = ip4_next_header (ip); s->ext_host_addr.as_u32 = ip->src_address.as_u32; - s->ext_host_port = nat_proto == NAT_PROTOCOL_ICMP ? 0 : udp->src_port; + s->ext_host_port = + nat_proto == NAT_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; if (lb_nat) s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; @@ -574,7 +573,6 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index) { clib_bihash_kv_16_8_t kv, value; - udp_header_t *udp; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; vlib_main_t *vm = vlib_get_main (); f64 now = vlib_time_now (vm); @@ -593,9 +591,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, { if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP) { - udp = ip4_next_header (ip); - lookup_sport = udp->dst_port; - lookup_dport = udp->src_port; + lookup_sport = vnet_buffer (b)->ip.reass.l4_dst_port; + lookup_dport = vnet_buffer (b)->ip.reass.l4_src_port; } else { diff --git a/src/plugins/nat/nat44-ei/nat44_ei.c b/src/plugins/nat/nat44-ei/nat44_ei.c index d361060a42e..67757015b1d 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.c +++ b/src/plugins/nat/nat44-ei/nat44_ei.c @@ -1407,7 +1407,7 @@ nat44_ei_get_out2in_worker_index (vlib_buffer_t *b, ip4_header_t *ip0, proto = ip_proto_to_nat_proto (ip0->protocol); udp = ip4_next_header (ip0); - port = udp->dst_port; + port = vnet_buffer (b)->ip.reass.l4_dst_port; /* unknown protocol */ if (PREDICT_FALSE (proto == NAT_PROTOCOL_OTHER)) -- cgit 1.2.3-korg