X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fin2out.c;h=c724553e36b969afca67a1ebe6f9e7b944a264d9;hb=refs%2Fchanges%2F65%2F12765%2F3;hp=5d6969f57899b7dae3c1298635537146884c15e6;hpb=2aad876be8d5b1754976dc29a401a4bbf4a2c76d;p=vpp.git diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index 5d6969f5789..c724553e36b 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -127,7 +128,8 @@ _(NO_TRANSLATION, "No translation") \ _(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \ _(DROP_FRAGMENT, "Drop fragment") \ _(MAX_REASS, "Maximum reassemblies exceeded") \ -_(MAX_FRAG, "Maximum fragments per reassembly exceeded") +_(MAX_FRAG, "Maximum fragments per reassembly exceeded")\ +_(FQ_CONGESTED, "Handoff frame queue congested") typedef enum { #define _(sym,str) SNAT_IN2OUT_ERROR_##sym, @@ -239,7 +241,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,11 +256,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; @@ -266,9 +271,27 @@ 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; } @@ -289,11 +312,13 @@ 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))) { b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED]; nat_ipfix_logging_max_sessions(sm->max_translations); + nat_log_notice ("maximum sessions exceeded"); return SNAT_IN2OUT_NEXT_DROP; } @@ -311,12 +336,12 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, thread_index); if (!u) { - clib_warning ("create NAT user failed"); + nat_log_warn ("create NAT user failed"); return SNAT_IN2OUT_NEXT_DROP; } /* 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, @@ -328,22 +353,20 @@ 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) { - clib_warning ("create NAT session failed"); + nat_log_warn ("create NAT session failed"); 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; @@ -358,14 +381,14 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0, kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].in2out, &kv0, 1 /* is_add */)) - clib_warning ("in2out key add failed"); + nat_log_notice ("in2out key add failed"); kv0.key = s->out2in.as_u64; kv0.value = s - sm->per_thread_data[thread_index].sessions; if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0, 1 /* is_add */)) - clib_warning ("out2in key add failed"); + nat_log_notice ("out2in key add failed"); /* log NAT event */ snat_ipfix_logging_nat44_ses_create(s->in2out.addr.as_u32, @@ -470,11 +493,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; + f64 now = vlib_time_now (sm->vlib_main); if (!sm->forwarding_enabled) return 0; @@ -505,7 +531,25 @@ 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)) + { + if (ip->protocol == IP_PROTOCOL_TCP) + { + tcp_header_t *tcp = ip4_next_header(ip); + if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index)) + return 1; + } + /* Per-user LRU list maintenance */ + nat44_session_update_lru (sm, s, thread_index); + /* Accounting */ + nat44_session_update_counters (s, now, 0); + return 1; + } + else + return 0; + } return 0; } @@ -561,7 +605,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; @@ -683,7 +727,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))) @@ -773,6 +817,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; @@ -879,7 +926,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; @@ -980,7 +1027,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; @@ -1035,15 +1082,10 @@ static inline u32 icmp_in2out_slow_path (snat_main_t *sm, if (vnet_buffer(b0)->sw_if_index[VLIB_TX] == 0) snat_icmp_hairpinning(sm, b0, ip0, icmp0); /* Accounting */ - s0->last_heard = now; - s0->total_pkts++; - s0->total_bytes += vlib_buffer_length_in_chain (sm->vlib_main, b0); + nat44_session_update_counters (s0, now, + vlib_buffer_length_in_chain (sm->vlib_main, b0)); /* Per-user LRU list maintenance */ - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s0->per_user_list_head_index, - s0->per_user_index); + nat44_session_update_lru (sm, s0, thread_index); } return next0; } @@ -1135,7 +1177,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]; @@ -1150,6 +1192,7 @@ snat_in2out_unknown_proto (snat_main_t *sm, { b->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED]; nat_ipfix_logging_max_sessions(sm->max_translations); + nat_log_notice ("maximum sessions exceeded"); return 0; } @@ -1157,7 +1200,7 @@ snat_in2out_unknown_proto (snat_main_t *sm, thread_index); if (!u) { - clib_warning ("create NAT user failed"); + nat_log_warn ("create NAT user failed"); return 0; } @@ -1179,34 +1222,37 @@ snat_in2out_unknown_proto (snat_main_t *sm, else { /* Choose same out address as for TCP/UDP session to same destination */ - if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value)) + head_index = u->sessions_per_user_list_head_index; + head = pool_elt_at_index (tsm->list_pool, head_index); + elt_index = head->next; + if (PREDICT_FALSE (elt_index == ~0)) + ses_index = ~0; + else + { + elt = pool_elt_at_index (tsm->list_pool, elt_index); + ses_index = elt->value; + } + + while (ses_index != ~0) { - head_index = u->sessions_per_user_list_head_index; - head = pool_elt_at_index (tsm->list_pool, head_index); - elt_index = head->next; + s = pool_elt_at_index (tsm->sessions, ses_index); + elt_index = elt->next; elt = pool_elt_at_index (tsm->list_pool, elt_index); ses_index = elt->value; - while (ses_index != ~0) - { - s = pool_elt_at_index (tsm->sessions, ses_index); - elt_index = elt->next; - elt = pool_elt_at_index (tsm->list_pool, elt_index); - ses_index = elt->value; - if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32) - { - new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32; - address_index = s->outside_address_index; + if (s->ext_host_addr.as_u32 == ip->dst_address.as_u32) + { + new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32; + address_index = s->outside_address_index; - key.fib_index = sm->outside_fib_index; - key.l_addr.as_u32 = new_addr; - s_kv.key[0] = key.as_u64[0]; - s_kv.key[1] = key.as_u64[1]; - if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value)) - break; + key.fib_index = sm->outside_fib_index; + key.l_addr.as_u32 = new_addr; + s_kv.key[0] = key.as_u64[0]; + s_kv.key[1] = key.as_u64[1]; + if (clib_bihash_search_16_8 (&sm->out2in_ed, &s_kv, &s_value)) + break; - goto create_ses; - } + goto create_ses; } } key.fib_index = sm->outside_fib_index; @@ -1229,12 +1275,13 @@ create_ses: s = nat_session_alloc_or_recycle (sm, u, thread_index); if (!s) { - clib_warning ("create NAT session failed"); + nat_log_warn ("create NAT session failed"); return 0; } 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; @@ -1242,14 +1289,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; @@ -1260,14 +1301,14 @@ create_ses: s_kv.key[1] = key.as_u64[1]; s_kv.value = s - tsm->sessions; if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1)) - clib_warning ("in2out key add failed"); + nat_log_notice ("in2out key add failed"); key.l_addr.as_u32 = new_addr; key.fib_index = sm->outside_fib_index; s_kv.key[0] = key.as_u64[0]; s_kv.key[1] = key.as_u64[1]; if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1)) - clib_warning ("out2in key add failed"); + nat_log_notice ("out2in key add failed"); } /* Update IP checksum */ @@ -1276,13 +1317,9 @@ create_ses: ip->checksum = ip_csum_fold (sum); /* Accounting */ - s->last_heard = now; - s->total_pkts++; - s->total_bytes += vlib_buffer_length_in_chain (vm, b); + nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b)); /* 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); + nat44_session_update_lru (sm, s, thread_index); /* Hairpinning */ if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0) @@ -1316,6 +1353,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; @@ -1330,9 +1368,18 @@ 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)) + { + if (ip->protocol == IP_PROTOCOL_TCP) + { + if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index)) + return 0; + } + /* Per-user LRU list maintenance */ + nat44_session_update_lru (sm, s, thread_index); + return 0; + } } else { @@ -1340,6 +1387,7 @@ snat_in2out_lb (snat_main_t *sm, { b->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED]; nat_ipfix_logging_max_sessions(sm->max_translations); + nat_log_notice ("maximum sessions exceeded"); return 0; } @@ -1347,37 +1395,40 @@ 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, thread_index); if (!u) { - clib_warning ("create NAT user failed"); + nat_log_warn ("create NAT user failed"); return 0; } s = nat_session_alloc_or_recycle (sm, u, thread_index); if (!s) { - clib_warning ("create NAT session failed"); + nat_log_warn ("create NAT session failed"); return 0; } s->ext_host_addr.as_u32 = ip->dst_address.as_u32; + s->ext_host_port = udp->dst_port; 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; if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1)) - clib_warning ("in2out-ed key add failed"); + nat_log_notice ("in2out-ed key add failed"); key.l_addr = e_key.addr; key.fib_index = e_key.fib_index; @@ -1385,7 +1436,7 @@ snat_in2out_lb (snat_main_t *sm, s_kv.key[0] = key.as_u64[0]; s_kv.key[1] = key.as_u64[1]; if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1)) - clib_warning ("out2in-ed key add failed"); + nat_log_notice ("out2in-ed key add failed"); } new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32; @@ -1398,6 +1449,9 @@ snat_in2out_lb (snat_main_t *sm, s->ext_host_addr.as_u32, ip4_header_t, dst_address); ip->checksum = ip_csum_fold (sum); + if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0) + vnet_buffer(b)->sw_if_index[VLIB_TX] = sm->outside_fib_index; + if (PREDICT_TRUE(proto == SNAT_PROTOCOL_TCP)) { old_port = tcp->src_port; @@ -1418,6 +1472,8 @@ snat_in2out_lb (snat_main_t *sm, ip->dst_address.as_u32 = s->ext_host_addr.as_u32; } tcp->checksum = ip_csum_fold(sum); + if (nat44_set_tcp_session_state_i2o (sm, s, tcp, thread_index)) + return s; } else { @@ -1430,17 +1486,11 @@ snat_in2out_lb (snat_main_t *sm, udp->checksum = 0; } - if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0) - vnet_buffer(b)->sw_if_index[VLIB_TX] = sm->outside_fib_index; - /* Accounting */ - s->last_heard = now; - s->total_pkts++; - s->total_bytes += vlib_buffer_length_in_chain (vm, b); + nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b)); /* 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); + nat44_session_update_lru (sm, s, thread_index); + return s; } @@ -1569,7 +1619,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; } @@ -1601,7 +1651,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 @@ -1685,15 +1735,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } /* Accounting */ - s0->last_heard = now; - s0->total_pkts++; - s0->total_bytes += vlib_buffer_length_in_chain (vm, b0); + nat44_session_update_counters (s0, now, + vlib_buffer_length_in_chain (vm, b0)); /* Per-user LRU list maintenance */ - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s0->per_user_list_head_index, - s0->per_user_index); + nat44_session_update_lru (sm, s0, thread_index); trace00: if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) @@ -1761,7 +1806,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; } @@ -1793,8 +1838,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, udp1->src_port, thread_index))) - goto trace00; + ip1, proto1, udp1->src_port, udp1->dst_port, thread_index, sw_if_index1))) + goto trace01; } else { @@ -1877,15 +1922,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } /* Accounting */ - s1->last_heard = now; - s1->total_pkts++; - s1->total_bytes += vlib_buffer_length_in_chain (vm, b1); + nat44_session_update_counters (s1, now, + vlib_buffer_length_in_chain (vm, b1)); /* Per-user LRU list maintenance */ - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s1->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s1->per_user_list_head_index, - s1->per_user_index); + nat44_session_update_lru (sm, s1, thread_index); trace01: if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) @@ -1989,7 +2029,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; } @@ -2021,7 +2061,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 @@ -2106,15 +2146,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm, } /* Accounting */ - s0->last_heard = now; - s0->total_pkts++; - s0->total_bytes += vlib_buffer_length_in_chain (vm, b0); + nat44_session_update_counters (s0, now, + vlib_buffer_length_in_chain (vm, b0)); /* Per-user LRU list maintenance */ - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s0->per_user_list_head_index, - s0->per_user_index); + nat44_session_update_lru (sm, s0, thread_index); trace0: if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) @@ -2403,7 +2438,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; @@ -2552,6 +2587,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm, { next0 = SNAT_IN2OUT_NEXT_DROP; b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_REASS]; + nat_log_notice ("maximum reassemblies exceeded"); goto trace0; } @@ -2592,6 +2628,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm, if (nat_ip4_reass_add_fragment (reass0, bi0)) { b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_FRAG]; + nat_log_notice ("maximum fragments per reassembly exceeded"); next0 = SNAT_IN2OUT_NEXT_DROP; goto trace0; } @@ -2643,15 +2680,10 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm, s0->ext_host_port, proto0); /* Accounting */ - s0->last_heard = now; - s0->total_pkts++; - s0->total_bytes += vlib_buffer_length_in_chain (vm, b0); + nat44_session_update_counters (s0, now, + vlib_buffer_length_in_chain (vm, b0)); /* Per-user LRU list maintenance */ - clib_dlist_remove (sm->per_thread_data[thread_index].list_pool, - s0->per_user_index); - clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool, - s0->per_user_list_head_index, - s0->per_user_index); + nat44_session_update_lru (sm, s0, thread_index); trace0: if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE) @@ -2845,8 +2877,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm, dm0 = snat_det_map_by_user(sm, &ip0->src_address); if (PREDICT_FALSE(!dm0)) { - clib_warning("no match for internal host %U", - format_ip4_address, &ip0->src_address); + nat_log_info ("no match for internal host %U", + format_ip4_address, &ip0->src_address); next0 = SNAT_IN2OUT_NEXT_DROP; b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION]; goto trace0; @@ -2995,8 +3027,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm, dm1 = snat_det_map_by_user(sm, &ip1->src_address); if (PREDICT_FALSE(!dm1)) { - clib_warning("no match for internal host %U", - format_ip4_address, &ip0->src_address); + nat_log_info ("no match for internal host %U", + format_ip4_address, &ip0->src_address); next1 = SNAT_IN2OUT_NEXT_DROP; b1->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION]; goto trace1; @@ -3181,8 +3213,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm, dm0 = snat_det_map_by_user(sm, &ip0->src_address); if (PREDICT_FALSE(!dm0)) { - clib_warning("no match for internal host %U", - format_ip4_address, &ip0->src_address); + nat_log_info ("no match for internal host %U", + format_ip4_address, &ip0->src_address); next0 = SNAT_IN2OUT_NEXT_DROP; b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION]; goto trace00; @@ -3414,8 +3446,8 @@ u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node, dm0 = snat_det_map_by_user(sm, &in_addr); if (PREDICT_FALSE(!dm0)) { - clib_warning("no match for internal host %U", - format_ip4_address, &in_addr); + nat_log_info ("no match for internal host %U", + format_ip4_address, &in_addr); if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0, IP_PROTOCOL_ICMP, rx_fib_index0))) { @@ -3506,11 +3538,12 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, { snat_main_t *sm = &snat_main; vlib_thread_main_t *tm = vlib_get_thread_main (); - u32 n_left_from, *from, *to_next = 0; + u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0; static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index; static __thread vlib_frame_queue_t **congested_handoff_queue_by_worker_index = 0; vlib_frame_queue_elt_t *hf = 0; + vlib_frame_queue_t *fq; vlib_frame_t *f = 0; int i; u32 n_left_to_next_worker = 0, *to_next_worker = 0; @@ -3519,6 +3552,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, u32 thread_index = vlib_get_thread_index (); u32 fq_index; u32 to_node_index; + vlib_frame_t *d = 0; ASSERT (vec_len (sm->workers)); @@ -3538,7 +3572,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1); vec_validate_init_empty (congested_handoff_queue_by_worker_index, - sm->first_worker_index + sm->num_workers - 1, + tm->n_vlib_mains - 1, (vlib_frame_queue_t *) (~0)); } @@ -3573,6 +3607,26 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, if (next_worker_index != current_worker_index) { + fq = is_vlib_frame_queue_congested ( + fq_index, next_worker_index, NAT_FQ_NELTS - 2, + congested_handoff_queue_by_worker_index); + + if (fq) + { + /* if this is 1st frame */ + if (!d) + { + d = vlib_get_frame_to_node (vm, sm->error_node_index); + to_next_drop = vlib_frame_vector_args (d); + } + + to_next_drop[0] = bi0; + to_next_drop += 1; + d->n_vectors++; + b0->error = node->errors[SNAT_IN2OUT_ERROR_FQ_CONGESTED]; + goto trace0; + } + if (hf) hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker; @@ -3614,6 +3668,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, f->n_vectors++; } +trace0: if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) { @@ -3627,6 +3682,9 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm, if (f) vlib_put_frame_to_node (vm, to_node_index, f); + if (d) + vlib_put_frame_to_node (vm, sm->error_node_index, d); + if (hf) hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker; @@ -3671,6 +3729,9 @@ VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node) = { .format_trace = format_snat_in2out_worker_handoff_trace, .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(snat_in2out_error_strings), + .error_strings = snat_in2out_error_strings, + .n_next_nodes = 1, .next_nodes = { @@ -4012,7 +4073,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;