diff options
-rwxr-xr-x | src/plugins/nat/in2out.c | 33 | ||||
-rwxr-xr-x | src/plugins/nat/out2in.c | 52 |
2 files changed, 78 insertions, 7 deletions
diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index f81efb7bdeb..f731b81b74b 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -251,11 +251,14 @@ snat_not_translate (snat_main_t * sm, vlib_node_runtime_t *node, static inline int nat_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip0, - u32 proto0, u16 src_port, u32 thread_index) + u32 proto0, u16 src_port, u16 dst_port, + u32 thread_index, u32 sw_if_index) { snat_session_key_t key0; clib_bihash_kv_8_8_t kv0, value0; + snat_interface_t *i; + /* src NAT check */ key0.addr = ip0->src_address; key0.port = src_port; key0.protocol = proto0; @@ -263,8 +266,26 @@ nat_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip0, kv0.key = key0.as_u64; if (!clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0, - &value0)) + &value0)) + return 1; + + /* dst NAT check */ + key0.addr = ip0->dst_address; + key0.port = dst_port; + key0.protocol = proto0; + key0.fib_index = sm->inside_fib_index; + kv0.key = key0.as_u64; + if (!clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].in2out, &kv0, + &value0)) + { + /* hairpinning */ + pool_foreach (i, sm->output_feature_interfaces, + ({ + if ((nat_interface_is_inside(i)) && (sw_if_index == i->sw_if_index)) + return 0; + })); return 1; + } return 0; } @@ -556,7 +577,7 @@ u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, if (vnet_buffer(b0)->sw_if_index[VLIB_TX] != ~0) { if (PREDICT_FALSE(nat_not_translate_output_feature(sm, - ip0, SNAT_PROTOCOL_ICMP, key0.port, thread_index))) + ip0, SNAT_PROTOCOL_ICMP, key0.port, key0.port, thread_index, sw_if_index0))) { dont_translate = 1; goto out; @@ -1591,7 +1612,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, if (is_output_feature) { if (PREDICT_FALSE(nat_not_translate_output_feature(sm, - ip0, proto0, udp0->src_port, thread_index))) + ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0))) goto trace00; } else @@ -1783,7 +1804,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, if (is_output_feature) { if (PREDICT_FALSE(nat_not_translate_output_feature(sm, - ip1, proto1, udp1->src_port, thread_index))) + ip1, proto1, udp1->src_port, udp1->dst_port, thread_index, sw_if_index1))) goto trace01; } else @@ -2011,7 +2032,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, if (is_output_feature) { if (PREDICT_FALSE(nat_not_translate_output_feature(sm, - ip0, proto0, udp0->src_port, thread_index))) + ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0))) goto trace0; } else diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c index 142c5ddb175..1f1afd4fae3 100755 --- a/src/plugins/nat/out2in.c +++ b/src/plugins/nat/out2in.c @@ -133,6 +133,7 @@ typedef enum { SNAT_OUT2IN_NEXT_LOOKUP, SNAT_OUT2IN_NEXT_ICMP_ERROR, SNAT_OUT2IN_NEXT_REASS, + SNAT_OUT2IN_NEXT_IN2OUT, SNAT_OUT2IN_N_NEXT, } snat_out2in_next_t; @@ -311,6 +312,26 @@ icmp_get_ed_key(ip4_header_t *ip0, nat_ed_ses_key_t *p_key0) return 0; } +static int +next_src_nat (snat_main_t * sm, ip4_header_t * ip, u32 proto, u16 src_port, + u32 thread_index) +{ + snat_session_key_t key; + clib_bihash_kv_8_8_t kv, value; + + key.addr = ip->src_address; + key.port = src_port; + key.protocol = proto; + key.fib_index = sm->inside_fib_index; + kv.key = key.as_u64; + + if (!clib_bihash_search_8_8 (&sm->per_thread_data[thread_index].in2out, &kv, + &value)) + return 1; + + return 0; +} + static void create_bypass_for_fwd(snat_main_t * sm, ip4_header_t * ip) { @@ -419,8 +440,13 @@ u32 icmp_match_out2in_slow(snat_main_t *sm, vlib_node_runtime_t *node, } else { - create_bypass_for_fwd(sm, ip0); dont_translate = 1; + if (next_src_nat(sm, ip0, key0.protocol, key0.port, thread_index)) + { + next0 = SNAT_OUT2IN_NEXT_IN2OUT; + goto out; + } + create_bypass_for_fwd(sm, ip0); goto out; } } @@ -1155,6 +1181,11 @@ snat_out2in_node_fn (vlib_main_t * vm, } else { + if (next_src_nat(sm, ip0, proto0, udp0->src_port, thread_index)) + { + next0 = SNAT_OUT2IN_NEXT_IN2OUT; + goto trace0; + } create_bypass_for_fwd(sm, ip0); goto trace0; } @@ -1322,6 +1353,11 @@ snat_out2in_node_fn (vlib_main_t * vm, } else { + if (next_src_nat(sm, ip1, proto1, udp1->src_port, thread_index)) + { + next1 = SNAT_OUT2IN_NEXT_IN2OUT; + goto trace1; + } create_bypass_for_fwd(sm, ip1); goto trace1; } @@ -1525,6 +1561,11 @@ snat_out2in_node_fn (vlib_main_t * vm, } else { + if (next_src_nat(sm, ip0, proto0, udp0->src_port, thread_index)) + { + next0 = SNAT_OUT2IN_NEXT_IN2OUT; + goto trace00; + } create_bypass_for_fwd(sm, ip0); goto trace00; } @@ -1652,6 +1693,7 @@ VLIB_REGISTER_NODE (snat_out2in_node) = { [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup", [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error", [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass", + [SNAT_OUT2IN_NEXT_IN2OUT] = "nat44-in2out", }, }; VLIB_NODE_FUNCTION_MULTIARCH (snat_out2in_node, snat_out2in_node_fn); @@ -1768,6 +1810,11 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm, } else { + if (next_src_nat(sm, ip0, proto0, udp0->src_port, thread_index)) + { + next0 = SNAT_OUT2IN_NEXT_IN2OUT; + goto trace0; + } create_bypass_for_fwd(sm, ip0); goto trace0; } @@ -1939,6 +1986,7 @@ VLIB_REGISTER_NODE (nat44_out2in_reass_node) = { [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup", [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error", [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass", + [SNAT_OUT2IN_NEXT_IN2OUT] = "nat44-in2out", }, }; VLIB_NODE_FUNCTION_MULTIARCH (nat44_out2in_reass_node, @@ -2428,6 +2476,7 @@ VLIB_REGISTER_NODE (snat_det_out2in_node) = { [SNAT_OUT2IN_NEXT_LOOKUP] = "ip4-lookup", [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error", [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass", + [SNAT_OUT2IN_NEXT_IN2OUT] = "nat44-in2out", }, }; VLIB_NODE_FUNCTION_MULTIARCH (snat_det_out2in_node, snat_det_out2in_node_fn); @@ -2921,6 +2970,7 @@ VLIB_REGISTER_NODE (snat_out2in_fast_node) = { [SNAT_OUT2IN_NEXT_DROP] = "error-drop", [SNAT_OUT2IN_NEXT_ICMP_ERROR] = "ip4-icmp-error", [SNAT_OUT2IN_NEXT_REASS] = "nat44-out2in-reass", + [SNAT_OUT2IN_NEXT_IN2OUT] = "nat44-in2out", }, }; VLIB_NODE_FUNCTION_MULTIARCH (snat_out2in_fast_node, snat_out2in_fast_node_fn); |