X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat44-ed%2Fnat44_ed_out2in.c;h=5e6db63b2bffca74e2b9fbbfe9cc989c7421d977;hb=4d41f954abc2965d187bcaf165dee81c8b3fd14a;hp=90f2ec3215506bd554d494997f1883e5fee1e28f;hpb=5599fc2dae024bcf150fa4b3b4584e19419f8079;p=vpp.git diff --git a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c index 90f2ec32155..5e6db63b2bf 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_out2in.c +++ b/src/plugins/nat/nat44-ed/nat44_ed_out2in.c @@ -37,6 +37,15 @@ static char *nat_out2in_ed_error_strings[] = { #undef _ }; +typedef enum +{ + NAT_ED_SP_REASON_NO_REASON, + NAT_ED_SP_REASON_LOOKUP_FAILED, + NAT_ED_SP_REASON_VRF_EXPIRED, + NAT_ED_SP_TCP_CLOSED, + NAT_ED_SP_SESS_EXPIRED, +} nat_slow_path_reason_e; + typedef struct { u32 sw_if_index; @@ -49,8 +58,29 @@ typedef struct u8 is_slow_path; u8 translation_via_i2of; u8 lookup_skipped; + nat_slow_path_reason_e slow_path_reason; } nat44_ed_out2in_trace_t; +static u8 * +format_slow_path_reason (u8 *s, va_list *args) +{ + nat_slow_path_reason_e reason = va_arg (*args, nat_slow_path_reason_e); + switch (reason) + { + case NAT_ED_SP_REASON_NO_REASON: + return format (s, "no reason for slow path"); + case NAT_ED_SP_REASON_LOOKUP_FAILED: + return format (s, "slow path because lookup failed"); + case NAT_ED_SP_REASON_VRF_EXPIRED: + return format (s, "slow path because vrf expired"); + case NAT_ED_SP_TCP_CLOSED: + return format (s, "slow path because tcp closed"); + case NAT_ED_SP_SESS_EXPIRED: + return format (s, "slow path because session expired"); + } + return format (s, "invalid reason value"); +} + static u8 * format_nat44_ed_out2in_trace (u8 * s, va_list * args) { @@ -63,12 +93,13 @@ format_nat44_ed_out2in_trace (u8 * s, va_list * args) t->is_slow_path ? "NAT44_OUT2IN_ED_SLOW_PATH" : "NAT44_OUT2IN_ED_FAST_PATH"; - s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag, - t->sw_if_index, t->next_index, t->session_index); + s = format (s, "%s: sw_if_index %d, next index %d", tag, t->sw_if_index, + t->next_index); if (~0 != t->session_index) { - s = format (s, ", translation result '%U' via %s", - format_nat_ed_translation_error, t->translation_error, + s = format (s, ", session %d, translation result '%U' via %s", + t->session_index, format_nat_ed_translation_error, + t->translation_error, t->translation_via_i2of ? "i2of" : "o2if"); s = format (s, "\n i2of %U", format_nat_6t_flow, &t->i2of); s = format (s, "\n o2if %U", format_nat_6t_flow, &t->o2if); @@ -84,6 +115,7 @@ format_nat44_ed_out2in_trace (u8 * s, va_list * args) s = format (s, "\n search key %U", format_ed_session_kvp, &t->search_key); } + s = format (s, "\n %U", format_slow_path_reason, t->slow_path_reason); } return s; @@ -149,7 +181,7 @@ icmp_out2in_ed_slow_path (snat_main_t *sm, vlib_buffer_t *b, ip4_header_t *ip, } if (snat_static_mapping_match ( - sm, ip->dst_address, lookup_sport, rx_fib_index, + vm, sm, ip->dst_address, lookup_sport, rx_fib_index, ip_proto_to_nat_proto (ip->protocol), &sm_addr, &sm_port, &sm_fib_index, 1, &is_addr_only, 0, 0, 0, &identity_nat, &m)) { @@ -372,7 +404,6 @@ create_session_for_static_mapping_ed ( { snat_session_t *s; ip4_header_t *ip; - udp_header_t *udp; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; if (PREDICT_FALSE @@ -392,16 +423,15 @@ create_session_for_static_mapping_ed ( } ip = vlib_buffer_get_current (b); - udp = ip4_next_header (ip); s->ext_host_addr.as_u32 = ip->src_address.as_u32; - s->ext_host_port = nat_proto == NAT_PROTOCOL_ICMP ? 0 : udp->src_port; + s->ext_host_port = + nat_proto == NAT_PROTOCOL_ICMP ? 0 : vnet_buffer (b)->ip.reass.l4_src_port; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; if (lb_nat) s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING; if (lb_nat == AFFINITY_LB_NAT) s->flags |= SNAT_SESSION_FLAG_AFFINITY; - s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT; s->out2in.addr = o2i_addr; s->out2in.port = o2i_port; s->out2in.fib_index = o2i_fib_index; @@ -441,7 +471,7 @@ create_session_for_static_mapping_ed ( snat_address_t *filter = 0; // if exact address is specified use this address - if (is_exact_address (mapping)) + if (is_sm_exact_address (mapping->flags)) { snat_address_t *ap; vec_foreach (ap, sm->twice_nat_addresses) @@ -562,7 +592,7 @@ create_session_for_static_mapping_ed ( s->in2out.port, &s->ext_host_nat_addr, s->ext_host_nat_port, &s->out2in.addr, s->out2in.port, &s->ext_host_addr, s->ext_host_port, s->nat_proto, - is_twice_nat_session (s)); + nat44_ed_is_twice_nat_session (s)); per_vrf_sessions_register_session (s, thread_index); @@ -574,7 +604,6 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, ip4_header_t *ip, u32 rx_fib_index, u32 thread_index) { clib_bihash_kv_16_8_t kv, value; - udp_header_t *udp; snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index]; vlib_main_t *vm = vlib_get_main (); f64 now = vlib_time_now (vm); @@ -584,8 +613,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, if (ip->protocol == IP_PROTOCOL_ICMP) { - if (nat_get_icmp_session_lookup_values (b, ip, &lookup_saddr, - &lookup_sport, &lookup_daddr, + if (nat_get_icmp_session_lookup_values (b, ip, &lookup_daddr, + &lookup_sport, &lookup_saddr, &lookup_dport, &lookup_protocol)) return; } @@ -593,9 +622,8 @@ create_bypass_for_fwd (snat_main_t *sm, vlib_buffer_t *b, snat_session_t *s, { if (ip->protocol == IP_PROTOCOL_UDP || ip->protocol == IP_PROTOCOL_TCP) { - udp = ip4_next_header (ip); - lookup_sport = udp->dst_port; - lookup_dport = udp->src_port; + lookup_sport = vnet_buffer (b)->ip.reass.l4_dst_port; + lookup_dport = vnet_buffer (b)->ip.reass.l4_src_port; } else { @@ -725,7 +753,6 @@ nat44_ed_out2in_slowpath_unknown_proto (snat_main_t *sm, vlib_buffer_t *b, s->ext_host_addr.as_u32 = ip->src_address.as_u32; s->flags |= SNAT_SESSION_FLAG_UNKNOWN_PROTO; s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING; - s->flags |= SNAT_SESSION_FLAG_ENDPOINT_DEPENDENT; s->out2in.addr.as_u32 = ip->dst_address.as_u32; s->out2in.fib_index = rx_fib_index; s->in2out.addr.as_u32 = m->local_addr.as_u32; @@ -792,6 +819,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, snat_session_t *s0 = 0; clib_bihash_kv_16_8_t kv0, value0; nat_translation_error_e translation_error = NAT_ED_TRNSL_ERR_SUCCESS; + nat_slow_path_reason_e slow_path_reason = NAT_ED_SP_REASON_NO_REASON; nat_6t_flow_t *f = 0; nat_6t_t lookup; int lookup_skipped = 0; @@ -808,7 +836,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, vlib_prefetch_buffer_header (p2, LOAD); - CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, LOAD); + clib_prefetch_load (p2->data); } next[0] = vnet_buffer2 (b0)->nat.arc_next; @@ -893,6 +921,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, if (clib_bihash_search_16_8 (&sm->flow_hash, &kv0, &value0)) { // flow does not exist go slow path + slow_path_reason = NAT_ED_SP_REASON_LOOKUP_FAILED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } @@ -902,11 +931,14 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, ed_value_get_session_index (&value0)); skip_lookup: + ASSERT (thread_index == s0->thread_index); + if (PREDICT_FALSE (per_vrf_sessions_is_expired (s0, thread_index))) { // session is closed, go slow path nat_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); + slow_path_reason = NAT_ED_SP_REASON_VRF_EXPIRED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } @@ -916,6 +948,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, if (now >= s0->tcp_closed_timestamp) { // session is closed, go slow path, freed in slow path + slow_path_reason = NAT_ED_SP_TCP_CLOSED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; } else @@ -936,6 +969,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, // session is closed, go slow path nat_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); + slow_path_reason = NAT_ED_SP_SESS_EXPIRED; next[0] = NAT_NEXT_OUT2IN_ED_SLOW_PATH; goto trace0; } @@ -984,16 +1018,18 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, nat_free_session_data (sm, s0, thread_index, 0); nat_ed_session_delete (sm, s0, thread_index, 1); next[0] = NAT_NEXT_DROP; + b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED]; goto trace0; } } } if (NAT_ED_TRNSL_ERR_SUCCESS != - (translation_error = nat_6t_flow_buf_translate ( - sm, b0, ip0, f, proto0, 0 /* is_output_feature */))) + (translation_error = nat_6t_flow_buf_translate_o2i ( + vm, sm, b0, ip0, f, proto0, 0 /* is_output_feature */))) { next[0] = NAT_NEXT_DROP; + b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED]; goto trace0; } @@ -1044,6 +1080,7 @@ nat44_ed_out2in_fast_path_node_fn_inline (vlib_main_t * vm, t->translation_error = translation_error; clib_memcpy (&t->search_key, &kv0, sizeof (t->search_key)); t->lookup_skipped = lookup_skipped; + t->slow_path_reason = slow_path_reason; if (s0) { @@ -1143,11 +1180,14 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (!s0) next[0] = NAT_NEXT_DROP; } - if (NAT_NEXT_DROP != next[0] && + if (NAT_NEXT_DROP != next[0] && s0 && NAT_ED_TRNSL_ERR_SUCCESS != - (translation_error = nat_6t_flow_buf_translate ( - sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */))) + (translation_error = nat_6t_flow_buf_translate_o2i ( + vm, sm, b0, ip0, &s0->o2i, proto0, + 0 /* is_output_feature */))) { + next[0] = NAT_NEXT_DROP; + b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED]; goto trace0; } @@ -1164,9 +1204,12 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, if (NAT_NEXT_DROP != next[0] && s0 && NAT_ED_TRNSL_ERR_SUCCESS != - (translation_error = nat_6t_flow_buf_translate ( - sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */))) + (translation_error = nat_6t_flow_buf_translate_o2i ( + vm, sm, b0, ip0, &s0->o2i, proto0, + 0 /* is_output_feature */))) { + next[0] = NAT_NEXT_DROP; + b0->error = node->errors[NAT_OUT2IN_ED_ERROR_TRNSL_FAILED]; goto trace0; } @@ -1201,11 +1244,11 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, /* Try to match static mapping by external address and port, destination address and port in packet */ - if (snat_static_mapping_match - (sm, ip0->dst_address, - vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, - proto0, &sm_addr, &sm_port, &sm_fib_index, 1, 0, - &twice_nat0, &lb_nat0, &ip0->src_address, &identity_nat0, &m)) + if (snat_static_mapping_match ( + vm, sm, ip0->dst_address, + vnet_buffer (b0)->ip.reass.l4_dst_port, rx_fib_index0, proto0, + &sm_addr, &sm_port, &sm_fib_index, 1, 0, &twice_nat0, &lb_nat0, + &ip0->src_address, &identity_nat0, &m)) { /* * Send DHCP packets to the ipv4 stack, or we won't @@ -1274,8 +1317,8 @@ nat44_ed_out2in_slow_path_node_fn_inline (vlib_main_t * vm, } if (NAT_ED_TRNSL_ERR_SUCCESS != - (translation_error = nat_6t_flow_buf_translate ( - sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */))) + (translation_error = nat_6t_flow_buf_translate_o2i ( + vm, sm, b0, ip0, &s0->o2i, proto0, 0 /* is_output_feature */))) { next[0] = NAT_NEXT_DROP; goto trace0; @@ -1362,7 +1405,6 @@ VLIB_NODE_FN (nat44_ed_out2in_node) (vlib_main_t * vm, } } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (nat44_ed_out2in_node) = { .name = "nat44-ed-out2in", .vector_size = sizeof (u32), @@ -1373,7 +1415,6 @@ VLIB_REGISTER_NODE (nat44_ed_out2in_node) = { .error_strings = nat_out2in_ed_error_strings, .runtime_data_bytes = sizeof (snat_runtime_t), }; -/* *INDENT-ON* */ VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1382,7 +1423,6 @@ VLIB_NODE_FN (nat44_ed_out2in_slowpath_node) (vlib_main_t * vm, return nat44_ed_out2in_slow_path_node_fn_inline (vm, node, frame); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = { .name = "nat44-ed-out2in-slowpath", .vector_size = sizeof (u32), @@ -1393,7 +1433,6 @@ VLIB_REGISTER_NODE (nat44_ed_out2in_slowpath_node) = { .error_strings = nat_out2in_ed_error_strings, .runtime_data_bytes = sizeof (snat_runtime_t), }; -/* *INDENT-ON* */ static u8 * format_nat_pre_trace (u8 * s, va_list * args) @@ -1413,7 +1452,6 @@ VLIB_NODE_FN (nat_pre_out2in_node) (vlib_main_t * vm, NAT_NEXT_OUT2IN_ED_FAST_PATH); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (nat_pre_out2in_node) = { .name = "nat-pre-out2in", .vector_size = sizeof (u32), @@ -1422,7 +1460,6 @@ VLIB_REGISTER_NODE (nat_pre_out2in_node) = { .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = 0, }; -/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON