X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fin2out.c;h=786b6c6887b025d7fddbabc7e0e35b3ca8b5d5be;hb=1e5c07d379a092f4829e7081aa962d013b31fdfc;hp=f009ce47d78088be8c959a0795b16b85abca5765;hpb=9691cf2d082727fb2f88e85050068dc6fd761bcd;p=vpp.git diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index f009ce47d78..786b6c6887b 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -239,7 +239,7 @@ snat_not_translate (snat_main_t * sm, vlib_node_runtime_t *node, &value0)) { /* or is static mappings */ - if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0)) + if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0, 0)) return 0; } else @@ -254,22 +254,42 @@ 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, u32 thread_index) + u32 proto0, u16 src_port, u16 dst_port, + u32 thread_index, u32 sw_if_index) { - udp_header_t * udp0 = ip4_next_header (ip0); 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 = udp0->src_port; + key0.port = src_port; key0.protocol = proto0; key0.fib_index = sm->outside_fib_index; 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; } @@ -290,6 +310,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, u32 outside_fib_index; uword * p; udp_header_t * udp0 = ip4_next_header (ip0); + u8 is_sm = 0; if (PREDICT_FALSE (maximum_sessions_exceeded(sm, thread_index))) { @@ -317,7 +338,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, } /* First try to match static mapping by local address and port */ - if (snat_static_mapping_match (sm, *key0, &key1, 0, 0, 0)) + if (snat_static_mapping_match (sm, *key0, &key1, 0, 0, 0, 0)) { /* Try to create dynamic translation */ if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index0, @@ -329,12 +350,9 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, b0->error = node->errors[SNAT_IN2OUT_ERROR_OUT_OF_PORTS]; return SNAT_IN2OUT_NEXT_DROP; } - u->nsessions++; } else - { - u->nstaticsessions++; - } + is_sm = 1; s = nat_session_alloc_or_recycle (sm, u, thread_index); if (!s) @@ -343,8 +361,9 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, return SNAT_IN2OUT_NEXT_DROP; } - if (address_index == ~0) + if (is_sm) s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; + user_session_increment (sm, u, is_sm); s->outside_address_index = address_index; s->in2out = *key0; s->out2in = key1; @@ -471,11 +490,14 @@ icmp_get_ed_key(ip4_header_t *ip0, nat_ed_ses_key_t *p_key0) } static inline int -nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip) +nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip, + u32 thread_index) { nat_ed_ses_key_t key; clib_bihash_kv_16_8_t kv, value; udp_header_t *udp; + snat_session_t *s = 0; + snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; if (!sm->forwarding_enabled) return 0; @@ -506,7 +528,19 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip) kv.key[1] = key.as_u64[1]; if (!clib_bihash_search_16_8 (&sm->in2out_ed, &kv, &value)) - return value.value == ~0ULL; + { + s = pool_elt_at_index (sm->per_thread_data[thread_index].sessions, value.value); + if (is_fwd_bypass_session (s)) + { + /* Per-user LRU list maintenance */ + clib_dlist_remove (tsm->list_pool, s->per_user_index); + clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index, + s->per_user_index); + return 1; + } + else + return 0; + } return 0; } @@ -562,7 +596,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, IP_PROTOCOL_ICMP, thread_index))) + ip0, SNAT_PROTOCOL_ICMP, key0.port, key0.port, thread_index, sw_if_index0))) { dont_translate = 1; goto out; @@ -571,7 +605,7 @@ u32 icmp_match_in2out_slow(snat_main_t *sm, vlib_node_runtime_t *node, else { if (PREDICT_FALSE(snat_not_translate(sm, node, sw_if_index0, - ip0, IP_PROTOCOL_ICMP, rx_fib_index0, thread_index))) + ip0, SNAT_PROTOCOL_ICMP, rx_fib_index0, thread_index))) { dont_translate = 1; goto out; @@ -684,7 +718,7 @@ u32 icmp_match_in2out_fast(snat_main_t *sm, vlib_node_runtime_t *node, } key0.fib_index = rx_fib_index0; - if (snat_static_mapping_match(sm, key0, &sm0, 0, &is_addr_only, 0)) + if (snat_static_mapping_match(sm, key0, &sm0, 0, &is_addr_only, 0, 0)) { if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0, IP_PROTOCOL_ICMP, rx_fib_index0))) @@ -774,6 +808,9 @@ static inline u32 icmp_in2out (snat_main_t *sm, src_address /* changed member */); ip0->checksum = ip_csum_fold (sum0); + if (icmp0->checksum == 0) + icmp0->checksum = 0xffff; + if (!icmp_is_error_message (icmp0)) { new_id0 = sm0.port; @@ -880,7 +917,7 @@ snat_hairpinning (snat_main_t *sm, kv0.key = key0.as_u64; /* Check if destination is static mappings */ - if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0)) + if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0, 0)) { new_dst_addr0 = sm0.addr.as_u32; new_dst_port0 = sm0.port; @@ -981,7 +1018,7 @@ snat_icmp_hairpinning (snat_main_t *sm, &value0)) { /* or static mappings */ - if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0)) + if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0, 0)) { new_dst_addr0 = sm0.addr.as_u32; vnet_buffer(b0)->sw_if_index[VLIB_TX] = sm0.fib_index; @@ -1136,7 +1173,7 @@ snat_in2out_unknown_proto (snat_main_t *sm, key.fib_index = rx_fib_index; key.proto = ip->protocol; key.l_port = 0; - key.l_port = 0; + key.r_port = 0; s_kv.key[0] = key.as_u64[0]; s_kv.key[1] = key.as_u64[1]; @@ -1236,6 +1273,7 @@ create_ses: s->ext_host_addr.as_u32 = ip->dst_address.as_u32; s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; + s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT; s->outside_address_index = address_index; s->out2in.addr.as_u32 = new_addr; s->out2in.fib_index = sm->outside_fib_index; @@ -1243,14 +1281,8 @@ create_ses: s->in2out.fib_index = rx_fib_index; s->in2out.port = s->out2in.port = ip->protocol; if (is_sm) - { - u->nstaticsessions++; - s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; - } - else - { - u->nsessions++; - } + s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; + user_session_increment (sm, u, is_sm); /* Add to lookup tables */ key.l_addr.as_u32 = old_addr; @@ -1317,6 +1349,7 @@ snat_in2out_lb (snat_main_t *sm, u32 proto = ip_proto_to_snat_proto (ip->protocol); snat_session_key_t e_key, l_key; snat_user_t *u; + u8 lb; old_addr = ip->src_address.as_u32; @@ -1331,9 +1364,9 @@ snat_in2out_lb (snat_main_t *sm, if (!clib_bihash_search_16_8 (&sm->in2out_ed, &s_kv, &s_value)) { - if (s_value.value == ~0ULL) - return 0; s = pool_elt_at_index (tsm->sessions, s_value.value); + if (is_fwd_bypass_session (s)) + return 0; } else { @@ -1348,7 +1381,7 @@ snat_in2out_lb (snat_main_t *sm, l_key.port = udp->src_port; l_key.protocol = proto; l_key.fib_index = rx_fib_index; - if (snat_static_mapping_match(sm, l_key, &e_key, 0, 0, 0)) + if (snat_static_mapping_match(sm, l_key, &e_key, 0, 0, 0, &lb)) return 0; u = nat_user_get_or_create (sm, &ip->src_address, rx_fib_index, @@ -1368,12 +1401,14 @@ snat_in2out_lb (snat_main_t *sm, s->ext_host_addr.as_u32 = ip->dst_address.as_u32; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; - s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; + if (lb) + s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; + s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT; s->outside_address_index = ~0; s->in2out = l_key; s->out2in = e_key; s->out2in.protocol = l_key.protocol; - u->nstaticsessions++; + user_session_increment (sm, u, 1 /* static */); /* Add to lookup tables */ s_kv.value = s - tsm->sessions; @@ -1570,7 +1605,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { if (is_output_feature) { - if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip0))) + if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip0, thread_index))) goto trace00; } @@ -1602,7 +1637,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, thread_index))) + ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0))) goto trace00; } else @@ -1762,7 +1797,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { if (is_output_feature) { - if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip1))) + if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip1, thread_index))) goto trace01; } @@ -1794,8 +1829,8 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, if (is_output_feature) { if (PREDICT_FALSE(nat_not_translate_output_feature(sm, - ip1, proto1, thread_index))) - goto trace00; + ip1, proto1, udp1->src_port, udp1->dst_port, thread_index, sw_if_index1))) + goto trace01; } else { @@ -1990,7 +2025,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, { if (is_output_feature) { - if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip0))) + if (PREDICT_FALSE(nat_not_translate_output_feature_fwd(sm, ip0, thread_index))) goto trace0; } @@ -2022,7 +2057,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, thread_index))) + ip0, proto0, udp0->src_port, udp0->dst_port, thread_index, sw_if_index0))) goto trace0; } else @@ -2404,7 +2439,7 @@ nat44_reass_hairpinning (snat_main_t *sm, udp0 = ip4_next_header (ip0); /* Check if destination is static mappings */ - if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0)) + if (!snat_static_mapping_match(sm, key0, &sm0, 1, 0, 0, 0)) { new_dst_addr0 = sm0.addr.as_u32; new_dst_port0 = sm0.port; @@ -4013,7 +4048,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm, key0.port = udp0->src_port; key0.fib_index = rx_fib_index0; - if (snat_static_mapping_match(sm, key0, &sm0, 0, 0, 0)) + if (snat_static_mapping_match(sm, key0, &sm0, 0, 0, 0, 0)) { b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION]; next0= SNAT_IN2OUT_NEXT_DROP;