X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fnat%2Fnat64_out2in.c;h=1c8df8a16dbbe401b3532d1d08c2d6175b7d7f52;hb=10c5ff1;hp=17513c5efb8c8da3338c2ec9ccf7c1b170bd23f6;hpb=5e52529adaa3a36402a2cc4f0f364060c5afc014;p=vpp.git diff --git a/src/plugins/nat/nat64_out2in.c b/src/plugins/nat/nat64_out2in.c index 17513c5efb8..1c8df8a16db 100644 --- a/src/plugins/nat/nat64_out2in.c +++ b/src/plugins/nat/nat64_out2in.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -133,9 +134,9 @@ nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX]; fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); - memset (&saddr, 0, sizeof (saddr)); + clib_memset (&saddr, 0, sizeof (saddr)); saddr.ip4.as_u32 = ip4->src_address.as_u32; - memset (&daddr, 0, sizeof (daddr)); + clib_memset (&daddr, 0, sizeof (daddr)); daddr.ip4.as_u32 = ip4->dst_address.as_u32; ste = @@ -159,8 +160,6 @@ nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, nat64_db_st_entry_create (db, bibe, &ip6_saddr, &saddr.ip4, sport); } - nat64_session_reset_timeout (ste, ctx->vm); - ip6->src_address.as_u64[0] = ste->in_r_addr.as_u64[0]; ip6->src_address.as_u64[1] = ste->in_r_addr.as_u64[1]; @@ -171,13 +170,19 @@ nat64_out2in_tcp_udp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, if (proto == IP_PROTOCOL_UDP) checksum = &udp->checksum; else - checksum = &tcp->checksum; + { + checksum = &tcp->checksum; + nat64_tcp_session_set_state (ste, tcp, 0); + } + csum = ip_csum_sub_even (*checksum, dport); csum = ip_csum_add_even (csum, udp->dst_port); *checksum = ip_csum_fold (csum); vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index; + nat64_session_reset_timeout (ste, ctx->vm); + return 0; } @@ -197,9 +202,9 @@ nat64_out2in_icmp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg) sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX]; fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); - memset (&saddr, 0, sizeof (saddr)); + clib_memset (&saddr, 0, sizeof (saddr)); saddr.ip4.as_u32 = ip4->src_address.as_u32; - memset (&daddr, 0, sizeof (daddr)); + clib_memset (&daddr, 0, sizeof (daddr)); daddr.ip4.as_u32 = ip4->dst_address.as_u32; if (icmp->type == ICMP6_echo_request || icmp->type == ICMP6_echo_reply) @@ -271,9 +276,9 @@ nat64_out2in_inner_icmp_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6, sw_if_index); - memset (&saddr, 0, sizeof (saddr)); + clib_memset (&saddr, 0, sizeof (saddr)); saddr.ip4.as_u32 = ip4->src_address.as_u32; - memset (&daddr, 0, sizeof (daddr)); + clib_memset (&daddr, 0, sizeof (daddr)); daddr.ip4.as_u32 = ip4->dst_address.as_u32; if (proto == IP_PROTOCOL_ICMP6) @@ -363,9 +368,9 @@ nat64_out2in_unk_proto_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, sw_if_index = vnet_buffer (ctx->b)->sw_if_index[VLIB_RX]; fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index); - memset (&saddr, 0, sizeof (saddr)); + clib_memset (&saddr, 0, sizeof (saddr)); saddr.ip4.as_u32 = ip4->src_address.as_u32; - memset (&daddr, 0, sizeof (daddr)); + clib_memset (&daddr, 0, sizeof (daddr)); daddr.ip4.as_u32 = ip4->dst_address.as_u32; ste = @@ -407,7 +412,7 @@ nat64_out2in_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 n_left_from, *from, *to_next; nat64_out2in_next_t next_index; u32 pkts_processed = 0; - u32 thread_index = vlib_get_thread_index (); + u32 thread_index = vm->thread_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -572,8 +577,6 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg) if (!bibe) return -1; - nat64_session_reset_timeout (ste, ctx->vm); - if (ctx->first_frag) { udp->dst_port = bibe->in_port; @@ -614,6 +617,7 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg) else { tcp_header_t *tcp = ip4_next_header (ip4); + nat64_tcp_session_set_state (ste, tcp, 0); checksum = &tcp->checksum; csum = ip_csum_sub_even (*checksum, bibe->out_addr.as_u32); csum = ip_csum_sub_even (csum, ste->out_r_addr.as_u32); @@ -636,6 +640,8 @@ nat64_out2in_frag_set_cb (ip4_header_t * ip4, ip6_header_t * ip6, void *arg) vnet_buffer (ctx->b)->sw_if_index[VLIB_TX] = bibe->fib_index; + nat64_session_reset_timeout (ste, ctx->vm); + return 0; } @@ -649,7 +655,7 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, u32 *fragments_to_drop = 0; u32 *fragments_to_loopback = 0; nat64_main_t *nm = &nat64_main; - u32 thread_index = vlib_get_thread_index (); + u32 thread_index = vm->thread_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; @@ -732,9 +738,9 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, { ctx0.first_frag = 1; - memset (&saddr0, 0, sizeof (saddr0)); + clib_memset (&saddr0, 0, sizeof (saddr0)); saddr0.ip4.as_u32 = ip40->src_address.as_u32; - memset (&daddr0, 0, sizeof (daddr0)); + clib_memset (&daddr0, 0, sizeof (daddr0)); daddr0.ip4.as_u32 = ip40->dst_address.as_u32; ste0 = @@ -779,7 +785,8 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0)) { - if (nat_ip4_reass_add_fragment (reass0, bi0)) + if (nat_ip4_reass_add_fragment + (reass0, bi0, &fragments_to_drop)) { b0->error = node->errors[NAT64_OUT2IN_ERROR_MAX_FRAG]; next0 = NAT64_OUT2IN_NEXT_DROP; @@ -835,17 +842,16 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, 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; } @@ -891,10 +897,26 @@ VLIB_REGISTER_NODE (nat64_out2in_reass_node) = { VLIB_NODE_FUNCTION_MULTIARCH (nat64_out2in_reass_node, nat64_out2in_reass_node_fn); +#define foreach_nat64_out2in_handoff_error \ +_(CONGESTION_DROP, "congestion drop") + +typedef enum +{ +#define _(sym,str) NAT64_OUT2IN_HANDOFF_ERROR_##sym, + foreach_nat64_out2in_handoff_error +#undef _ + NAT64_OUT2IN_HANDOFF_N_ERROR, +} nat64_out2in_handoff_error_t; + +static char *nat64_out2in_handoff_error_strings[] = { +#define _(sym,string) string, + foreach_nat64_out2in_handoff_error +#undef _ +}; + typedef struct { u32 next_worker_index; - u8 do_handoff; } nat64_out2in_handoff_trace_t; static u8 * @@ -904,10 +926,9 @@ format_nat64_out2in_handoff_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); nat64_out2in_handoff_trace_t *t = va_arg (*args, nat64_out2in_handoff_trace_t *); - char *m; - m = t->do_handoff ? "next worker" : "same worker"; - s = format (s, "NAT64-OUT2IN-HANDOFF: %s %d", m, t->next_worker_index); + s = + format (s, "NAT64-OUT2IN-HANDOFF: next-worker %d", t->next_worker_index); return s; } @@ -917,167 +938,49 @@ nat64_out2in_handoff_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { nat64_main_t *nm = &nat64_main; - vlib_thread_main_t *tm = vlib_get_thread_main (); - 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, *d = 0; - int i; - u32 n_left_to_next_worker = 0, *to_next_worker = 0; - u32 next_worker_index = 0; - u32 current_worker_index = ~0; - u32 thread_index = vlib_get_thread_index (); + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + u32 n_enq, n_left_from, *from; + u16 thread_indices[VLIB_FRAME_SIZE], *ti; u32 fq_index; - u32 to_node_index; - - fq_index = nm->fq_out2in_index; - to_node_index = nat64_out2in_node.index; - - if (PREDICT_FALSE (handoff_queue_elt_by_worker_index == 0)) - { - vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1); - - vec_validate_init_empty (congested_handoff_queue_by_worker_index, - tm->n_vlib_mains - 1, - (vlib_frame_queue_t *) (~0)); - } from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; + vlib_get_buffers (vm, from, bufs, n_left_from); + + b = bufs; + ti = thread_indices; + + fq_index = nm->fq_out2in_index; while (n_left_from > 0) { - u32 bi0; - vlib_buffer_t *b0; ip4_header_t *ip0; - u8 do_handoff; - - bi0 = from[0]; - from += 1; - n_left_from -= 1; - - b0 = vlib_get_buffer (vm, bi0); - ip0 = vlib_buffer_get_current (b0); + ip0 = vlib_buffer_get_current (b[0]); + ti[0] = nat64_get_worker_out2in (ip0); - next_worker_index = nat64_get_worker_out2in (ip0); - - if (PREDICT_FALSE (next_worker_index != thread_index)) - { - do_handoff = 1; - - if (next_worker_index != current_worker_index) - { - fq = - is_vlib_frame_queue_congested (fq_index, next_worker_index, - 30, - congested_handoff_queue_by_worker_index); - - if (fq) - { - /* if this is 1st frame */ - if (!d) - { - d = vlib_get_frame_to_node (vm, nm->error_node_index); - to_next_drop = vlib_frame_vector_args (d); - } - - to_next_drop[0] = bi0; - to_next_drop += 1; - d->n_vectors++; - goto trace0; - } - - if (hf) - hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker; - - hf = - vlib_get_worker_handoff_queue_elt (fq_index, - next_worker_index, - handoff_queue_elt_by_worker_index); - n_left_to_next_worker = VLIB_FRAME_SIZE - hf->n_vectors; - to_next_worker = &hf->buffer_index[hf->n_vectors]; - current_worker_index = next_worker_index; - } - - ASSERT (to_next_worker != 0); - - /* enqueue to correct worker thread */ - to_next_worker[0] = bi0; - to_next_worker++; - n_left_to_next_worker--; - - if (n_left_to_next_worker == 0) - { - hf->n_vectors = VLIB_FRAME_SIZE; - vlib_put_frame_queue_elt (hf); - current_worker_index = ~0; - handoff_queue_elt_by_worker_index[next_worker_index] = 0; - hf = 0; - } - } - else - { - do_handoff = 0; - /* if this is 1st frame */ - if (!f) - { - f = vlib_get_frame_to_node (vm, to_node_index); - to_next = vlib_frame_vector_args (f); - } - - to_next[0] = bi0; - to_next += 1; - f->n_vectors++; - } - - trace0: if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) + && (b[0]->flags & VLIB_BUFFER_IS_TRACED))) { nat64_out2in_handoff_trace_t *t = - vlib_add_trace (vm, node, b0, sizeof (*t)); - t->next_worker_index = next_worker_index; - t->do_handoff = do_handoff; + vlib_add_trace (vm, node, b[0], sizeof (*t)); + t->next_worker_index = ti[0]; } - } - - if (f) - vlib_put_frame_to_node (vm, to_node_index, f); - if (d) - vlib_put_frame_to_node (vm, nm->error_node_index, d); + n_left_from -= 1; + ti += 1; + b += 1; + } - if (hf) - hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker; + n_enq = + vlib_buffer_enqueue_to_thread (vm, fq_index, from, thread_indices, + frame->n_vectors, 1); - /* Ship frames to the worker nodes */ - for (i = 0; i < vec_len (handoff_queue_elt_by_worker_index); i++) - { - if (handoff_queue_elt_by_worker_index[i]) - { - hf = handoff_queue_elt_by_worker_index[i]; - /* - * It works better to let the handoff node - * rate-adapt, always ship the handoff queue element. - */ - if (1 || hf->n_vectors == hf->last_n_vectors) - { - vlib_put_frame_queue_elt (hf); - handoff_queue_elt_by_worker_index[i] = 0; - } - else - hf->last_n_vectors = hf->n_vectors; - } - congested_handoff_queue_by_worker_index[i] = - (vlib_frame_queue_t *) (~0); - } - hf = 0; - current_worker_index = ~0; + if (n_enq < frame->n_vectors) + vlib_node_increment_counter (vm, node->node_index, + NAT64_OUT2IN_HANDOFF_ERROR_CONGESTION_DROP, + frame->n_vectors - n_enq); return frame->n_vectors; } @@ -1088,6 +991,8 @@ VLIB_REGISTER_NODE (nat64_out2in_handoff_node) = { .vector_size = sizeof (u32), .format_trace = format_nat64_out2in_handoff_trace, .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = ARRAY_LEN(nat64_out2in_handoff_error_strings), + .error_strings = nat64_out2in_handoff_error_strings, .n_next_nodes = 1,