X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fin2out_ed.c;h=f3999f00129de58c42e6ef7ccb5b9b8dca0aa318;hb=6c01dceea5c612373453db7f1ccda589a2cd782e;hp=adf0ff30948987dc458047c77826f334100638be;hpb=37a3a2a08f72310a3f7e898a9b44af7751f2cc9c;p=vpp.git diff --git a/src/plugins/nat/in2out_ed.c b/src/plugins/nat/in2out_ed.c index adf0ff30948..f3999f00129 100644 --- a/src/plugins/nat/in2out_ed.c +++ b/src/plugins/nat/in2out_ed.c @@ -37,7 +37,8 @@ _(BAD_ICMP_TYPE, "unsupported ICMP type") \ _(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")\ +_(NON_SYN, "non-SYN packet try to create session") typedef enum { @@ -256,7 +257,7 @@ slow_path_ed (snat_main_t * sm, snat_session_t ** sessionp, vlib_node_runtime_t * node, u32 next, u32 thread_index, f64 now) { - snat_session_t *s; + snat_session_t *s = 0; snat_user_t *u; snat_session_key_t key0, key1; lb_nat_type_t lb = 0, is_sm = 0; @@ -265,6 +266,7 @@ slow_path_ed (snat_main_t * sm, u32 proto = ip_proto_to_snat_proto (key->proto); nat_outside_fib_t *outside_fib; fib_node_index_t fei = FIB_NODE_INDEX_INVALID; + u8 identity_nat; fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP4, .fp_len = 32, @@ -288,7 +290,8 @@ slow_path_ed (snat_main_t * sm, key0.fib_index = rx_fib_index; key1.fib_index = sm->outside_fib_index; /* First try to match static mapping by local address and port */ - if (snat_static_mapping_match (sm, key0, &key1, 0, 0, 0, &lb, 0)) + if (snat_static_mapping_match + (sm, key0, &key1, 0, 0, 0, &lb, 0, &identity_nat)) { /* Try to create dynamic translation */ if (snat_alloc_outside_address_and_port (sm->addresses, rx_fib_index, @@ -302,7 +305,15 @@ slow_path_ed (snat_main_t * sm, } } else - is_sm = 1; + { + if (PREDICT_FALSE (identity_nat)) + { + *sessionp = s; + return next; + } + + is_sm = 1; + } u = nat_user_get_or_create (sm, &key->l_addr, rx_fib_index, thread_index); if (!u) @@ -413,7 +424,7 @@ nat44_ed_not_translate (snat_main_t * sm, vlib_node_runtime_t * node, key0.protocol = proto; key0.fib_index = sm->outside_fib_index; /* or is static mappings */ - if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0)) + if (!snat_static_mapping_match (sm, key0, &key1, 1, 0, 0, 0, 0, 0)) return 0; } else @@ -503,7 +514,19 @@ nat44_ed_not_translate_output_feature (snat_main_t * sm, ip4_header_t * ip, make_ed_kv (&kv, &ip->src_address, &ip->dst_address, proto, tx_fib_index, src_port, dst_port); if (!clib_bihash_search_16_8 (&tsm->out2in_ed, &kv, &value)) - return 1; + { + s = pool_elt_at_index (tsm->sessions, value.value); + if (nat44_is_ses_closed (s)) + { + nat_log_debug ("TCP close connection %U", format_snat_session, + &sm->per_thread_data[thread_index], s); + nat_free_session_data (sm, s, thread_index); + nat44_delete_session (sm, s, thread_index); + } + else + s->flags |= SNAT_SESSION_FLAG_OUTPUT_FEATURE; + return 1; + } /* dst NAT check */ make_ed_kv (&kv, &ip->dst_address, &ip->src_address, proto, rx_fib_index, @@ -607,6 +630,12 @@ icmp_match_in2out_ed (snat_main_t * sm, vlib_node_runtime_t * node, if (PREDICT_FALSE (next == NAT_IN2OUT_ED_NEXT_DROP)) goto out; + + if (!s) + { + dont_translate = 1; + goto out; + } } else { @@ -1005,12 +1034,22 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, goto trace00; } + if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0)) + { + b0->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN]; + next0 = NAT_IN2OUT_ED_NEXT_DROP; + goto trace00; + } + next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node, next0, thread_index, now); if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP)) goto trace00; + + if (PREDICT_FALSE (!s0)) + goto trace00; } else { @@ -1206,12 +1245,22 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, goto trace01; } + if ((proto1 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp1)) + { + b1->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN]; + next1 = NAT_IN2OUT_ED_NEXT_DROP; + goto trace01; + } + next1 = slow_path_ed (sm, b1, rx_fib_index1, &kv1, &s1, node, next1, thread_index, now); if (PREDICT_FALSE (next1 == NAT_IN2OUT_ED_NEXT_DROP)) goto trace01; + + if (PREDICT_FALSE (!s1)) + goto trace01; } else { @@ -1436,12 +1485,22 @@ nat44_ed_in2out_node_fn_inline (vlib_main_t * vm, goto trace0; } + if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0)) + { + b0->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN]; + next0 = NAT_IN2OUT_ED_NEXT_DROP; + goto trace0; + } + next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node, next0, thread_index, now); if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP)) goto trace0; + + if (PREDICT_FALSE (!s0)) + goto trace0; } else { @@ -1833,12 +1892,25 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm, } } + if ((proto0 == SNAT_PROTOCOL_TCP) && !tcp_is_init (tcp0)) + { + b0->error = node->errors[NAT_IN2OUT_ED_ERROR_NON_SYN]; + next0 = NAT_IN2OUT_ED_NEXT_DROP; + goto trace0; + } + next0 = slow_path_ed (sm, b0, rx_fib_index0, &kv0, &s0, node, next0, thread_index, now); if (PREDICT_FALSE (next0 == NAT_IN2OUT_ED_NEXT_DROP)) goto trace0; + if (PREDICT_FALSE (!s0)) + { + reass0->flags |= NAT_REASS_FLAG_ED_DONT_TRANSLATE; + goto trace0; + } + reass0->sess_index = s0 - per_thread_data->sessions; } else @@ -1929,11 +2001,8 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm, } /* Hairpinning */ - if (PREDICT_TRUE (proto0 != SNAT_PROTOCOL_ICMP)) - nat44_reass_hairpinning (sm, b0, ip0, s0->out2in.port, - s0->ext_host_port, proto0, 1); - else - snat_icmp_hairpinning (sm, b0, ip0, icmp0, 1); + nat44_reass_hairpinning (sm, b0, ip0, s0->out2in.port, + s0->ext_host_port, proto0, 1); /* Accounting */ nat44_session_update_counters (s0, now, @@ -1974,17 +2043,16 @@ nat44_ed_in2out_reass_node_fn_inline (vlib_main_t * vm, u32 len = vec_len (fragments_to_loopback); if (len <= VLIB_FRAME_SIZE) { - clib_memcpy (from, fragments_to_loopback, - sizeof (u32) * len); + clib_memcpy_fast (from, fragments_to_loopback, + sizeof (u32) * len); n_left_from = len; vec_reset_length (fragments_to_loopback); } else { - clib_memcpy (from, - fragments_to_loopback + (len - - VLIB_FRAME_SIZE), - sizeof (u32) * VLIB_FRAME_SIZE); + clib_memcpy_fast (from, fragments_to_loopback + + (len - VLIB_FRAME_SIZE), + sizeof (u32) * VLIB_FRAME_SIZE); n_left_from = VLIB_FRAME_SIZE; _vec_len (fragments_to_loopback) = len - VLIB_FRAME_SIZE; }