diff options
author | Klement Sekera <ksekera@cisco.com> | 2020-12-15 18:47:05 +0100 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-01-18 08:36:26 +0000 |
commit | 4881cb4c6f0d9c6276eb7a45ed355f9fc3d729b3 (patch) | |
tree | 07959eb6fc99b88b30e6f81f4620d8d6c70110e2 /src/plugins/nat/nat44_hairpinning.c | |
parent | 4a58e49cfe03150034a65e147a2ffe8d24391b86 (diff) |
nat: deal with flows instead of sessions
This change introduces flow concept to endpoint-dependent NAT. Instead
of having a session and a plethora of special cases in code for e.g.
hairpinning, twice-nat and others, figure all this out and store it in
flow logic. Every flow has a match and a rewrite part. This unifies all
the NAT packet processing cases into one - match a flow and rewrite the
packet based on that flow. It also provides a cure for hairpinning
dilemma where one part of the flow is on one worker and another on
a different one. These cases are also sped up by not requiring
destination adress lookup every single time to be able to rewrite source
nat as this is now part of flow rewrite logic.
Type: improvement
Change-Id: Ib60c992e16792ea4d4129bc10202ebb99a73b5be
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Diffstat (limited to 'src/plugins/nat/nat44_hairpinning.c')
-rw-r--r-- | src/plugins/nat/nat44_hairpinning.c | 261 |
1 files changed, 52 insertions, 209 deletions
diff --git a/src/plugins/nat/nat44_hairpinning.c b/src/plugins/nat/nat44_hairpinning.c index 9432f554246..37dfd7827f6 100644 --- a/src/plugins/nat/nat44_hairpinning.c +++ b/src/plugins/nat/nat44_hairpinning.c @@ -94,10 +94,9 @@ is_hairpinning (snat_main_t * sm, ip4_address_t * dst_addr) #ifndef CLIB_MARCH_VARIANT int -snat_hairpinning (vlib_main_t * vm, vlib_node_runtime_t * node, - snat_main_t * sm, vlib_buffer_t * b0, ip4_header_t * ip0, - udp_header_t * udp0, tcp_header_t * tcp0, u32 proto0, - int is_ed, int do_trace) +snat_hairpinning (vlib_main_t *vm, vlib_node_runtime_t *node, snat_main_t *sm, + vlib_buffer_t *b0, ip4_header_t *ip0, udp_header_t *udp0, + tcp_header_t *tcp0, u32 proto0, int do_trace) { snat_session_t *s0 = NULL; clib_bihash_kv_8_8_t kv0, value0; @@ -128,32 +127,17 @@ snat_hairpinning (vlib_main_t * vm, vlib_node_runtime_t * node, else ti = sm->num_workers; - if (is_ed) - { - clib_bihash_kv_16_8_t ed_kv, ed_value; - init_ed_k (&ed_kv, ip0->dst_address, udp0->dst_port, - ip0->src_address, udp0->src_port, sm->outside_fib_index, - ip0->protocol); - rv = clib_bihash_search_16_8 (&sm->out2in_ed, &ed_kv, &ed_value); - ASSERT (ti == ed_value_get_thread_index (&ed_value)); - si = ed_value_get_session_index (&ed_value); - } - else - { - - init_nat_k (&kv0, ip0->dst_address, udp0->dst_port, - sm->outside_fib_index, proto0); - rv = - clib_bihash_search_8_8 (&sm->per_thread_data[ti].out2in, &kv0, - &value0); - si = value0.value; - } + init_nat_k (&kv0, ip0->dst_address, udp0->dst_port, + sm->outside_fib_index, proto0); + rv = clib_bihash_search_8_8 (&sm->per_thread_data[ti].out2in, &kv0, + &value0); if (rv) { rv = 0; goto trace; } + si = value0.value; s0 = pool_elt_at_index (sm->per_thread_data[ti].sessions, si); new_dst_addr0 = s0->in2out.addr.as_u32; new_dst_port0 = s0->in2out.port; @@ -237,9 +221,8 @@ trace: #ifndef CLIB_MARCH_VARIANT u32 -snat_icmp_hairpinning (snat_main_t * sm, - vlib_buffer_t * b0, - ip4_header_t * ip0, icmp46_header_t * icmp0, int is_ed) +snat_icmp_hairpinning (snat_main_t *sm, vlib_buffer_t *b0, ip4_header_t *ip0, + icmp46_header_t *icmp0) { clib_bihash_kv_8_8_t kv0, value0; u32 old_dst_addr0, new_dst_addr0; @@ -264,26 +247,12 @@ snat_icmp_hairpinning (snat_main_t * sm, if (protocol != NAT_PROTOCOL_TCP && protocol != NAT_PROTOCOL_UDP) return 1; - if (is_ed) - { - clib_bihash_kv_16_8_t ed_kv, ed_value; - init_ed_k (&ed_kv, ip0->dst_address, l4_header->src_port, - ip0->src_address, l4_header->dst_port, - sm->outside_fib_index, inner_ip0->protocol); - if (clib_bihash_search_16_8 (&sm->out2in_ed, &ed_kv, &ed_value)) - return 1; - ASSERT (ti == ed_value_get_thread_index (&ed_value)); - si = ed_value_get_session_index (&ed_value); - } - else - { - init_nat_k (&kv0, ip0->dst_address, l4_header->src_port, - sm->outside_fib_index, protocol); - if (clib_bihash_search_8_8 - (&sm->per_thread_data[ti].out2in, &kv0, &value0)) - return 1; - si = value0.value; - } + init_nat_k (&kv0, ip0->dst_address, l4_header->src_port, + sm->outside_fib_index, protocol); + if (clib_bihash_search_8_8 (&sm->per_thread_data[ti].out2in, &kv0, + &value0)) + return 1; + si = value0.value; s0 = pool_elt_at_index (sm->per_thread_data[ti].sessions, si); new_dst_addr0 = s0->in2out.addr.as_u32; vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index; @@ -324,36 +293,29 @@ snat_icmp_hairpinning (snat_main_t * sm, if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv0, &value0)) { - if (!is_ed) + icmp_echo_header_t *echo0 = (icmp_echo_header_t *) (icmp0 + 1); + u16 icmp_id0 = echo0->identifier; + init_nat_k (&kv0, ip0->dst_address, icmp_id0, sm->outside_fib_index, + NAT_PROTOCOL_ICMP); + if (sm->num_workers > 1) + ti = + (clib_net_to_host_u16 (icmp_id0) - 1024) / sm->port_per_thread; + else + ti = sm->num_workers; + int rv = clib_bihash_search_8_8 (&sm->per_thread_data[ti].out2in, + &kv0, &value0); + if (!rv) { - icmp_echo_header_t *echo0 = (icmp_echo_header_t *) (icmp0 + 1); - u16 icmp_id0 = echo0->identifier; - init_nat_k (&kv0, ip0->dst_address, icmp_id0, - sm->outside_fib_index, NAT_PROTOCOL_ICMP); - if (sm->num_workers > 1) - ti = - (clib_net_to_host_u16 (icmp_id0) - - 1024) / sm->port_per_thread; - else - ti = sm->num_workers; - int rv = - clib_bihash_search_8_8 (&sm->per_thread_data[ti].out2in, &kv0, - &value0); - if (!rv) - { - si = value0.value; - s0 = - pool_elt_at_index (sm->per_thread_data[ti].sessions, si); - new_dst_addr0 = s0->in2out.addr.as_u32; - vnet_buffer (b0)->sw_if_index[VLIB_TX] = - s0->in2out.fib_index; - echo0->identifier = s0->in2out.port; - sum0 = icmp0->checksum; - sum0 = ip_csum_update (sum0, icmp_id0, s0->in2out.port, - icmp_echo_header_t, identifier); - icmp0->checksum = ip_csum_fold (sum0); - goto change_addr; - } + si = value0.value; + s0 = pool_elt_at_index (sm->per_thread_data[ti].sessions, si); + new_dst_addr0 = s0->in2out.addr.as_u32; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index; + echo0->identifier = s0->in2out.port; + sum0 = icmp0->checksum; + sum0 = ip_csum_update (sum0, icmp_id0, s0->in2out.port, + icmp_echo_header_t, identifier); + icmp0->checksum = ip_csum_fold (sum0); + goto change_addr; } return 1; @@ -407,58 +369,9 @@ nat_hairpinning_sm_unknown_proto (snat_main_t * sm, } #endif -#ifndef CLIB_MARCH_VARIANT -void -nat44_ed_hairpinning_unknown_proto (snat_main_t * sm, - vlib_buffer_t * b, ip4_header_t * ip) -{ - u32 old_addr, new_addr = 0, ti = 0; - clib_bihash_kv_8_8_t kv, value; - clib_bihash_kv_16_8_t s_kv, s_value; - snat_static_mapping_t *m; - ip_csum_t sum; - snat_session_t *s; - - if (sm->num_workers > 1) - ti = sm->worker_out2in_cb (b, ip, sm->outside_fib_index, 0); - else - ti = sm->num_workers; - - old_addr = ip->dst_address.as_u32; - init_ed_k (&s_kv, ip->dst_address, 0, ip->src_address, 0, - sm->outside_fib_index, ip->protocol); - if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value)) - { - init_nat_k (&kv, ip->dst_address, 0, 0, 0); - if (clib_bihash_search_8_8 - (&sm->static_mapping_by_external, &kv, &value)) - return; - - m = pool_elt_at_index (sm->static_mappings, value.value); - if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0) - vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index; - new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32; - } - else - { - ASSERT (ti == ed_value_get_thread_index (&s_value)); - s = - pool_elt_at_index (sm->per_thread_data[ti].sessions, - ed_value_get_session_index (&s_value)); - if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0) - vnet_buffer (b)->sw_if_index[VLIB_TX] = s->in2out.fib_index; - new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32; - } - sum = ip->checksum; - sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address); - ip->checksum = ip_csum_fold (sum); -} -#endif - static inline uword -nat44_hairpinning_fn_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, int is_ed) +nat44_hairpinning_fn_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) { u32 n_left_from, *from, *to_next; nat_hairpin_next_t next_index; @@ -507,9 +420,8 @@ nat44_hairpinning_fn_inline (vlib_main_t * vm, vnet_get_config_data (&cm->config_main, &b0->current_config_index, &next0, 0); - if (snat_hairpinning - (vm, node, sm, b0, ip0, udp0, tcp0, proto0, is_ed, - 1 /* do_trace */ )) + if (snat_hairpinning (vm, node, sm, b0, ip0, udp0, tcp0, proto0, + 1 /* do_trace */)) next0 = NAT_HAIRPIN_NEXT_LOOKUP; if (next0 != NAT_HAIRPIN_NEXT_DROP) @@ -535,7 +447,7 @@ VLIB_NODE_FN (nat44_hairpinning_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return nat44_hairpinning_fn_inline (vm, node, frame, 0); + return nat44_hairpinning_fn_inline (vm, node, frame); } /* *INDENT-OFF* */ @@ -552,31 +464,9 @@ VLIB_REGISTER_NODE (nat44_hairpinning_node) = { }; /* *INDENT-ON* */ -VLIB_NODE_FN (nat44_ed_hairpinning_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return nat44_hairpinning_fn_inline (vm, node, frame, 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (nat44_ed_hairpinning_node) = { - .name = "nat44-ed-hairpinning", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - .format_trace = format_nat_hairpin_trace, - .n_next_nodes = NAT_HAIRPIN_N_NEXT, - .next_nodes = { - [NAT_HAIRPIN_NEXT_DROP] = "error-drop", - [NAT_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup", - }, -}; -/* *INDENT-ON* */ - static inline uword -snat_hairpin_dst_fn_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, int is_ed) +snat_hairpin_dst_fn_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) { u32 n_left_from, *from, *to_next; nat_hairpin_next_t next_index; @@ -625,20 +515,17 @@ snat_hairpin_dst_fn_inline (vlib_main_t * vm, tcp_header_t *tcp0 = (tcp_header_t *) udp0; snat_hairpinning (vm, node, sm, b0, ip0, udp0, tcp0, proto0, - is_ed, 1 /* do_trace */ ); + 1 /* do_trace */); } else if (proto0 == NAT_PROTOCOL_ICMP) { icmp46_header_t *icmp0 = ip4_next_header (ip0); - snat_icmp_hairpinning (sm, b0, ip0, icmp0, is_ed); + snat_icmp_hairpinning (sm, b0, ip0, icmp0); } else { - if (is_ed) - nat44_ed_hairpinning_unknown_proto (sm, b0, ip0); - else - nat_hairpinning_sm_unknown_proto (sm, b0, ip0); + nat_hairpinning_sm_unknown_proto (sm, b0, ip0); } vnet_buffer (b0)->snat.flags = SNAT_FLAG_HAIRPINNING; @@ -668,7 +555,7 @@ VLIB_NODE_FN (snat_hairpin_dst_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return snat_hairpin_dst_fn_inline (vm, node, frame, 0); + return snat_hairpin_dst_fn_inline (vm, node, frame); } /* *INDENT-OFF* */ @@ -685,31 +572,9 @@ VLIB_REGISTER_NODE (snat_hairpin_dst_node) = { }; /* *INDENT-ON* */ -VLIB_NODE_FN (nat44_ed_hairpin_dst_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return snat_hairpin_dst_fn_inline (vm, node, frame, 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (nat44_ed_hairpin_dst_node) = { - .name = "nat44-ed-hairpin-dst", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - .format_trace = format_nat_hairpin_trace, - .n_next_nodes = NAT_HAIRPIN_N_NEXT, - .next_nodes = { - [NAT_HAIRPIN_NEXT_DROP] = "error-drop", - [NAT_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup", - }, -}; -/* *INDENT-ON* */ - static inline uword -snat_hairpin_src_fn_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, int is_ed) +snat_hairpin_src_fn_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame) { u32 n_left_from, *from, *to_next; snat_hairpin_src_next_t next_index; @@ -787,7 +652,7 @@ VLIB_NODE_FN (snat_hairpin_src_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return snat_hairpin_src_fn_inline (vm, node, frame, 0); + return snat_hairpin_src_fn_inline (vm, node, frame); } /* *INDENT-OFF* */ @@ -805,28 +670,6 @@ VLIB_REGISTER_NODE (snat_hairpin_src_node) = { }; /* *INDENT-ON* */ -VLIB_NODE_FN (nat44_ed_hairpin_src_node) (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - return snat_hairpin_src_fn_inline (vm, node, frame, 1); -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (nat44_ed_hairpin_src_node) = { - .name = "nat44-ed-hairpin-src", - .vector_size = sizeof (u32), - .type = VLIB_NODE_TYPE_INTERNAL, - .n_next_nodes = SNAT_HAIRPIN_SRC_N_NEXT, - .next_nodes = { - [SNAT_HAIRPIN_SRC_NEXT_DROP] = "error-drop", - [SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT] = "nat44-ed-in2out-output", - [SNAT_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT] = "interface-output", - [SNAT_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH] = "nat44-in2out-output-worker-handoff", - }, -}; -/* *INDENT-ON* */ - /* * fd.io coding-style-patch-verification: ON * |