diff options
Diffstat (limited to 'src/vnet/ip/reass/ip4_sv_reass.c')
-rw-r--r-- | src/vnet/ip/reass/ip4_sv_reass.c | 486 |
1 files changed, 312 insertions, 174 deletions
diff --git a/src/vnet/ip/reass/ip4_sv_reass.c b/src/vnet/ip/reass/ip4_sv_reass.c index cd5e19b65d3..7c3c2fff217 100644 --- a/src/vnet/ip/reass/ip4_sv_reass.c +++ b/src/vnet/ip/reass/ip4_sv_reass.c @@ -48,7 +48,7 @@ typedef struct { struct { - u32 xx_id; + u32 fib_index; ip4_address_t src; ip4_address_t dst; u16 frag_id; @@ -150,6 +150,7 @@ typedef struct /** Worker handoff */ u32 fq_index; u32 fq_feature_index; + u32 fq_custom_context_index; // reference count for enabling/disabling feature - per interface u32 *feature_use_refcount_per_intf; @@ -189,6 +190,7 @@ typedef struct u8 ip_proto; u16 l4_src_port; u16 l4_dst_port; + int l4_layer_truncated; } ip4_sv_reass_trace_t; extern vlib_node_registration_t ip4_sv_reass_node; @@ -225,6 +227,10 @@ format_ip4_sv_reass_trace (u8 * s, va_list * args) s = format (s, "[not-fragmented]"); break; } + if (t->l4_layer_truncated) + { + s = format (s, " [l4-layer-truncated]"); + } return s; } @@ -232,7 +238,8 @@ static void ip4_sv_reass_add_trace (vlib_main_t *vm, vlib_node_runtime_t *node, ip4_sv_reass_t *reass, u32 bi, ip4_sv_reass_trace_operation_e action, u32 ip_proto, - u16 l4_src_port, u16 l4_dst_port) + u16 l4_src_port, u16 l4_dst_port, + int l4_layer_truncated) { vlib_buffer_t *b = vlib_get_buffer (vm, bi); if (pool_is_free_index @@ -253,6 +260,7 @@ ip4_sv_reass_add_trace (vlib_main_t *vm, vlib_node_runtime_t *node, t->ip_proto = ip_proto; t->l4_src_port = l4_src_port; t->l4_dst_port = l4_dst_port; + t->l4_layer_truncated = l4_layer_truncated; #if 0 static u8 *s = NULL; s = format (s, "%U", format_ip4_sv_reass_trace, NULL, NULL, t); @@ -314,6 +322,8 @@ ip4_sv_reass_find_or_create (vlib_main_t * vm, ip4_sv_reass_main_t * rm, ip4_sv_reass_t *reass = NULL; f64 now = vlib_time_now (vm); +again: + if (!clib_bihash_search_16_8 (&rm->hash, &kv->kv, &kv->kv)) { if (vm->thread_index != kv->v.thread_index) @@ -368,10 +378,14 @@ ip4_sv_reass_find_or_create (vlib_main_t * vm, ip4_sv_reass_main_t * rm, kv->v.thread_index = vm->thread_index; reass->last_heard = now; - if (clib_bihash_add_del_16_8 (&rm->hash, &kv->kv, 1)) + int rv = clib_bihash_add_del_16_8 (&rm->hash, &kv->kv, 2); + if (rv) { ip4_sv_reass_free (vm, rm, rt, reass); reass = NULL; + // if other worker created a context already work with the other copy + if (-2 == rv) + goto again; } return reass; @@ -407,9 +421,10 @@ ip4_sv_reass_update (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - ip4_sv_reass_add_trace (vm, node, reass, bi0, REASS_FINISH, - reass->ip_proto, reass->l4_src_port, - reass->l4_dst_port); + ip4_sv_reass_add_trace ( + vm, node, reass, bi0, REASS_FINISH, reass->ip_proto, + reass->l4_src_port, reass->l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } } vec_add1 (reass->cached_buffers, bi0); @@ -417,8 +432,9 @@ ip4_sv_reass_update (vlib_main_t *vm, vlib_node_runtime_t *node, { if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - ip4_sv_reass_add_trace (vm, node, reass, bi0, REASS_FRAGMENT_CACHE, - ~0, ~0, ~0); + ip4_sv_reass_add_trace ( + vm, node, reass, bi0, REASS_FRAGMENT_CACHE, ~0, ~0, ~0, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } if (vec_len (reass->cached_buffers) > rm->max_reass_len) { @@ -428,15 +444,33 @@ ip4_sv_reass_update (vlib_main_t *vm, vlib_node_runtime_t *node, return rc; } +always_inline int +l4_layer_truncated (ip4_header_t *ip) +{ + static const int l4_layer_length[256] = { + [IP_PROTOCOL_TCP] = sizeof (tcp_header_t), + [IP_PROTOCOL_UDP] = sizeof (udp_header_t), + [IP_PROTOCOL_ICMP] = sizeof (icmp46_header_t), + }; + + return ((u8 *) ip + ip4_header_bytes (ip) + l4_layer_length[ip->protocol] > + (u8 *) ip + clib_net_to_host_u16 (ip->length)); +} + always_inline uword -ip4_sv_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * frame, bool is_feature, - bool is_output_feature, bool is_custom) +ip4_sv_reass_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, bool is_feature, + bool is_output_feature, bool is_custom, + bool with_custom_context) { u32 *from = vlib_frame_vector_args (frame); - u32 n_left_from, n_left_to_next, *to_next, next_index; + u32 n_left_from, n_left_to_next, *to_next, *to_next_aux, next_index; ip4_sv_reass_main_t *rm = &ip4_sv_reass_main; ip4_sv_reass_per_thread_t *rt = &rm->per_thread_data[vm->thread_index]; + u32 *context; + if (with_custom_context) + context = vlib_frame_aux_args (frame); + clib_spinlock_lock (&rt->lock); n_left_from = frame->n_vectors; @@ -482,6 +516,7 @@ ip4_sv_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, (is_output_feature ? 1 : 0) * vnet_buffer (b1)-> ip.save_rewrite_length); + if (PREDICT_FALSE (ip4_get_fragment_more (ip0) || ip4_get_fragment_offset (ip0)) || (ip4_get_fragment_more (ip1) || ip4_get_fragment_offset (ip1))) @@ -506,29 +541,40 @@ ip4_sv_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } vnet_buffer (b0)->ip.reass.is_non_first_fragment = 0; vnet_buffer (b0)->ip.reass.ip_proto = ip0->protocol; - if (IP_PROTOCOL_TCP == ip0->protocol) + if (l4_layer_truncated (ip0)) { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((tcp_header_t *) (ip0 + 1))->flags; - vnet_buffer (b0)->ip.reass.tcp_ack_number = - ((tcp_header_t *) (ip0 + 1))->ack_number; - vnet_buffer (b0)->ip.reass.tcp_seq_number = - ((tcp_header_t *) (ip0 + 1))->seq_number; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 1; + vnet_buffer (b0)->ip.reass.l4_src_port = 0; + vnet_buffer (b0)->ip.reass.l4_dst_port = 0; } - else if (IP_PROTOCOL_ICMP == ip0->protocol) + else { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((icmp46_header_t *) (ip0 + 1))->type; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 0; + if (IP_PROTOCOL_TCP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((tcp_header_t *) (ip0 + 1))->flags; + vnet_buffer (b0)->ip.reass.tcp_ack_number = + ((tcp_header_t *) (ip0 + 1))->ack_number; + vnet_buffer (b0)->ip.reass.tcp_seq_number = + ((tcp_header_t *) (ip0 + 1))->seq_number; + } + else if (IP_PROTOCOL_ICMP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((icmp46_header_t *) (ip0 + 1))->type; + } + vnet_buffer (b0)->ip.reass.l4_src_port = ip4_get_port (ip0, 1); + vnet_buffer (b0)->ip.reass.l4_dst_port = ip4_get_port (ip0, 0); } - vnet_buffer (b0)->ip.reass.l4_src_port = ip4_get_port (ip0, 1); - vnet_buffer (b0)->ip.reass.l4_dst_port = ip4_get_port (ip0, 0); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - ip4_sv_reass_add_trace (vm, node, NULL, from[(b - 2) - bufs], - REASS_PASSTHROUGH, - vnet_buffer (b0)->ip.reass.ip_proto, - vnet_buffer (b0)->ip.reass.l4_src_port, - vnet_buffer (b0)->ip.reass.l4_dst_port); + ip4_sv_reass_add_trace ( + vm, node, NULL, from[(b - 2) - bufs], REASS_PASSTHROUGH, + vnet_buffer (b0)->ip.reass.ip_proto, + vnet_buffer (b0)->ip.reass.l4_src_port, + vnet_buffer (b0)->ip.reass.l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } if (is_feature) { @@ -541,35 +587,48 @@ ip4_sv_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } vnet_buffer (b1)->ip.reass.is_non_first_fragment = 0; vnet_buffer (b1)->ip.reass.ip_proto = ip1->protocol; - if (IP_PROTOCOL_TCP == ip1->protocol) + if (l4_layer_truncated (ip1)) { - vnet_buffer (b1)->ip.reass.icmp_type_or_tcp_flags = - ((tcp_header_t *) (ip1 + 1))->flags; - vnet_buffer (b1)->ip.reass.tcp_ack_number = - ((tcp_header_t *) (ip1 + 1))->ack_number; - vnet_buffer (b1)->ip.reass.tcp_seq_number = - ((tcp_header_t *) (ip1 + 1))->seq_number; + vnet_buffer (b1)->ip.reass.l4_layer_truncated = 1; + vnet_buffer (b1)->ip.reass.l4_src_port = 0; + vnet_buffer (b1)->ip.reass.l4_dst_port = 0; } - else if (IP_PROTOCOL_ICMP == ip1->protocol) + else { - vnet_buffer (b1)->ip.reass.icmp_type_or_tcp_flags = - ((icmp46_header_t *) (ip1 + 1))->type; + vnet_buffer (b1)->ip.reass.l4_layer_truncated = 0; + if (IP_PROTOCOL_TCP == ip1->protocol) + { + vnet_buffer (b1)->ip.reass.icmp_type_or_tcp_flags = + ((tcp_header_t *) (ip1 + 1))->flags; + vnet_buffer (b1)->ip.reass.tcp_ack_number = + ((tcp_header_t *) (ip1 + 1))->ack_number; + vnet_buffer (b1)->ip.reass.tcp_seq_number = + ((tcp_header_t *) (ip1 + 1))->seq_number; + } + else if (IP_PROTOCOL_ICMP == ip1->protocol) + { + vnet_buffer (b1)->ip.reass.icmp_type_or_tcp_flags = + ((icmp46_header_t *) (ip1 + 1))->type; + } + vnet_buffer (b1)->ip.reass.l4_src_port = ip4_get_port (ip1, 1); + vnet_buffer (b1)->ip.reass.l4_dst_port = ip4_get_port (ip1, 0); } - vnet_buffer (b1)->ip.reass.l4_src_port = ip4_get_port (ip1, 1); - vnet_buffer (b1)->ip.reass.l4_dst_port = ip4_get_port (ip1, 0); if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED)) { - ip4_sv_reass_add_trace (vm, node, NULL, from[(b - 1) - bufs], - REASS_PASSTHROUGH, - vnet_buffer (b1)->ip.reass.ip_proto, - vnet_buffer (b1)->ip.reass.l4_src_port, - vnet_buffer (b1)->ip.reass.l4_dst_port); + ip4_sv_reass_add_trace ( + vm, node, NULL, from[(b - 1) - bufs], REASS_PASSTHROUGH, + vnet_buffer (b1)->ip.reass.ip_proto, + vnet_buffer (b1)->ip.reass.l4_src_port, + vnet_buffer (b1)->ip.reass.l4_dst_port, + vnet_buffer (b1)->ip.reass.l4_layer_truncated); } n_left_from -= 2; next[0] = next0; next[1] = next1; next += 2; + if (with_custom_context) + context += 2; } while (n_left_from > 0) @@ -608,34 +667,45 @@ ip4_sv_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } vnet_buffer (b0)->ip.reass.is_non_first_fragment = 0; vnet_buffer (b0)->ip.reass.ip_proto = ip0->protocol; - if (IP_PROTOCOL_TCP == ip0->protocol) + if (l4_layer_truncated (ip0)) { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((tcp_header_t *) (ip0 + 1))->flags; - vnet_buffer (b0)->ip.reass.tcp_ack_number = - ((tcp_header_t *) (ip0 + 1))->ack_number; - vnet_buffer (b0)->ip.reass.tcp_seq_number = - ((tcp_header_t *) (ip0 + 1))->seq_number; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 1; } - else if (IP_PROTOCOL_ICMP == ip0->protocol) + else { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((icmp46_header_t *) (ip0 + 1))->type; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 0; + if (IP_PROTOCOL_TCP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((tcp_header_t *) (ip0 + 1))->flags; + vnet_buffer (b0)->ip.reass.tcp_ack_number = + ((tcp_header_t *) (ip0 + 1))->ack_number; + vnet_buffer (b0)->ip.reass.tcp_seq_number = + ((tcp_header_t *) (ip0 + 1))->seq_number; + } + else if (IP_PROTOCOL_ICMP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((icmp46_header_t *) (ip0 + 1))->type; + } + vnet_buffer (b0)->ip.reass.l4_src_port = ip4_get_port (ip0, 1); + vnet_buffer (b0)->ip.reass.l4_dst_port = ip4_get_port (ip0, 0); } - vnet_buffer (b0)->ip.reass.l4_src_port = ip4_get_port (ip0, 1); - vnet_buffer (b0)->ip.reass.l4_dst_port = ip4_get_port (ip0, 0); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { - ip4_sv_reass_add_trace (vm, node, NULL, from[(b - 1) - bufs], - REASS_PASSTHROUGH, - vnet_buffer (b0)->ip.reass.ip_proto, - vnet_buffer (b0)->ip.reass.l4_src_port, - vnet_buffer (b0)->ip.reass.l4_dst_port); + ip4_sv_reass_add_trace ( + vm, node, NULL, from[(b - 1) - bufs], REASS_PASSTHROUGH, + vnet_buffer (b0)->ip.reass.ip_proto, + vnet_buffer (b0)->ip.reass.l4_src_port, + vnet_buffer (b0)->ip.reass.l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } n_left_from -= 1; next[0] = next0; next += 1; + if (with_custom_context) + context += 1; } vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts, @@ -649,7 +719,11 @@ slow_path: while (n_left_from > 0) { - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + if (with_custom_context) + vlib_get_next_frame_with_aux_safe (vm, node, next_index, to_next, + to_next_aux, n_left_to_next); + else + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); while (n_left_from > 0 && n_left_to_next > 0) { @@ -657,6 +731,7 @@ slow_path: vlib_buffer_t *b0; u32 next0; u32 error0 = IP4_ERROR_NONE; + u8 forward_context = 0; bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); @@ -679,29 +754,42 @@ slow_path: } vnet_buffer (b0)->ip.reass.is_non_first_fragment = 0; vnet_buffer (b0)->ip.reass.ip_proto = ip0->protocol; - if (IP_PROTOCOL_TCP == ip0->protocol) + if (l4_layer_truncated (ip0)) { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((tcp_header_t *) (ip0 + 1))->flags; - vnet_buffer (b0)->ip.reass.tcp_ack_number = - ((tcp_header_t *) (ip0 + 1))->ack_number; - vnet_buffer (b0)->ip.reass.tcp_seq_number = - ((tcp_header_t *) (ip0 + 1))->seq_number; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 1; + vnet_buffer (b0)->ip.reass.l4_src_port = 0; + vnet_buffer (b0)->ip.reass.l4_dst_port = 0; } - else if (IP_PROTOCOL_ICMP == ip0->protocol) + else { - vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = - ((icmp46_header_t *) (ip0 + 1))->type; + vnet_buffer (b0)->ip.reass.l4_layer_truncated = 0; + if (IP_PROTOCOL_TCP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((tcp_header_t *) (ip0 + 1))->flags; + vnet_buffer (b0)->ip.reass.tcp_ack_number = + ((tcp_header_t *) (ip0 + 1))->ack_number; + vnet_buffer (b0)->ip.reass.tcp_seq_number = + ((tcp_header_t *) (ip0 + 1))->seq_number; + } + else if (IP_PROTOCOL_ICMP == ip0->protocol) + { + vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags = + ((icmp46_header_t *) (ip0 + 1))->type; + } + vnet_buffer (b0)->ip.reass.l4_src_port = + ip4_get_port (ip0, 1); + vnet_buffer (b0)->ip.reass.l4_dst_port = + ip4_get_port (ip0, 0); } - vnet_buffer (b0)->ip.reass.l4_src_port = ip4_get_port (ip0, 1); - vnet_buffer (b0)->ip.reass.l4_dst_port = ip4_get_port (ip0, 0); if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ip4_sv_reass_add_trace ( vm, node, NULL, bi0, REASS_PASSTHROUGH, vnet_buffer (b0)->ip.reass.ip_proto, vnet_buffer (b0)->ip.reass.l4_src_port, - vnet_buffer (b0)->ip.reass.l4_dst_port); + vnet_buffer (b0)->ip.reass.l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } goto packet_enqueue; } @@ -719,13 +807,17 @@ slow_path: ip4_sv_reass_kv_t kv; u8 do_handoff = 0; - kv.k.as_u64[0] = - (u64) vec_elt (ip4_main.fib_index_by_sw_if_index, - vnet_buffer (b0)->sw_if_index[VLIB_RX]) | - (u64) ip0->src_address.as_u32 << 32; - kv.k.as_u64[1] = - (u64) ip0->dst_address. - as_u32 | (u64) ip0->fragment_id << 32 | (u64) ip0->protocol << 48; + if (with_custom_context) + kv.k.as_u64[0] = (u64) *context | (u64) ip0->src_address.as_u32 + << 32; + else + kv.k.as_u64[0] = + (u64) vec_elt (ip4_main.fib_index_by_sw_if_index, + vnet_buffer (b0)->sw_if_index[VLIB_RX]) | + (u64) ip0->src_address.as_u32 << 32; + kv.k.as_u64[1] = (u64) ip0->dst_address.as_u32 | + (u64) ip0->fragment_id << 32 | + (u64) ip0->protocol << 48; ip4_sv_reass_t *reass = ip4_sv_reass_find_or_create (vm, rm, rt, &kv, &do_handoff); @@ -735,6 +827,8 @@ slow_path: next0 = IP4_SV_REASSEMBLY_NEXT_HANDOFF; vnet_buffer (b0)->ip.reass.owner_thread_index = kv.v.thread_index; + if (with_custom_context) + forward_context = 1; goto packet_enqueue; } @@ -771,31 +865,32 @@ slow_path: { ip4_sv_reass_add_trace ( vm, node, reass, bi0, REASS_FRAGMENT_FORWARD, - reass->ip_proto, reass->l4_src_port, reass->l4_dst_port); + reass->ip_proto, reass->l4_src_port, reass->l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } goto packet_enqueue; } ip4_sv_reass_rc_t rc = ip4_sv_reass_update (vm, node, rm, ip0, reass, bi0); + u32 counter = ~0; switch (rc) { case IP4_SV_REASS_RC_OK: /* nothing to do here */ break; case IP4_SV_REASS_RC_TOO_MANY_FRAGMENTS: - vlib_node_increment_counter (vm, node->node_index, - IP4_ERROR_REASS_FRAGMENT_CHAIN_TOO_LONG, - 1); - ip4_sv_reass_free (vm, rm, rt, reass); - goto next_packet; + counter = IP4_ERROR_REASS_FRAGMENT_CHAIN_TOO_LONG; break; case IP4_SV_REASS_RC_UNSUPP_IP_PROTO: - vlib_node_increment_counter (vm, node->node_index, - IP4_ERROR_REASS_UNSUPP_IP_PROT, 1); + counter = IP4_ERROR_REASS_UNSUPP_IP_PROT; + break; + } + if (~0 != counter) + { + vlib_node_increment_counter (vm, node->node_index, counter, 1); ip4_sv_reass_free (vm, rm, rt, reass); goto next_packet; - break; } if (reass->is_complete) { @@ -843,13 +938,15 @@ slow_path: { ip4_sv_reass_add_trace ( vm, node, reass, bi0, REASS_FRAGMENT_FORWARD, - reass->ip_proto, reass->l4_src_port, reass->l4_dst_port); + reass->ip_proto, reass->l4_src_port, reass->l4_dst_port, + vnet_buffer (b0)->ip.reass.l4_layer_truncated); } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); } - _vec_len (reass->cached_buffers) = 0; // buffers are owned by frame now + vec_set_len (reass->cached_buffers, + 0); // buffers are owned by frame now } goto next_packet; @@ -862,13 +959,26 @@ slow_path: b0 = vlib_get_buffer (vm, bi0); vnet_feature_next (&next0, b0); } - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, next0); + if (with_custom_context && forward_context) + { + if (to_next_aux) + { + to_next_aux[0] = *context; + to_next_aux += 1; + } + vlib_validate_buffer_enqueue_with_aux_x1 ( + vm, node, next_index, to_next, to_next_aux, n_left_to_next, + bi0, *context, next0); + } + else + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); next_packet: from += 1; n_left_from -= 1; + if (with_custom_context) + context += 1; } vlib_put_next_frame (vm, node, next_index, n_left_to_next); @@ -879,28 +989,21 @@ done: return frame->n_vectors; } -static char *ip4_sv_reass_error_strings[] = { -#define _(sym, string) string, - foreach_ip4_error -#undef _ -}; - VLIB_NODE_FN (ip4_sv_reass_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_inline (vm, node, frame, false /* is_feature */ , - false /* is_output_feature */ , - false /* is_custom */ ); + return ip4_sv_reass_inline ( + vm, node, frame, false /* is_feature */, false /* is_output_feature */, + false /* is_custom */, false /* with_custom_context */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_node) = { .name = "ip4-sv-reassembly", .vector_size = sizeof (u32), .format_trace = format_ip4_sv_reass_trace, - .n_errors = ARRAY_LEN (ip4_sv_reass_error_strings), - .error_strings = ip4_sv_reass_error_strings, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, .n_next_nodes = IP4_SV_REASSEMBLY_N_NEXT, .next_nodes = { @@ -910,24 +1013,22 @@ VLIB_REGISTER_NODE (ip4_sv_reass_node) = { }, }; -/* *INDENT-ON* */ VLIB_NODE_FN (ip4_sv_reass_node_feature) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_inline (vm, node, frame, true /* is_feature */ , - false /* is_output_feature */ , - false /* is_custom */ ); + return ip4_sv_reass_inline ( + vm, node, frame, true /* is_feature */, false /* is_output_feature */, + false /* is_custom */, false /* with_custom_context */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_node_feature) = { .name = "ip4-sv-reassembly-feature", .vector_size = sizeof (u32), .format_trace = format_ip4_sv_reass_trace, - .n_errors = ARRAY_LEN (ip4_sv_reass_error_strings), - .error_strings = ip4_sv_reass_error_strings, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, .n_next_nodes = IP4_SV_REASSEMBLY_N_NEXT, .next_nodes = { @@ -936,34 +1037,30 @@ VLIB_REGISTER_NODE (ip4_sv_reass_node_feature) = { [IP4_SV_REASSEMBLY_NEXT_HANDOFF] = "ip4-sv-reass-feature-hoff", }, }; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VNET_FEATURE_INIT (ip4_sv_reass_feature) = { .arc_name = "ip4-unicast", .node_name = "ip4-sv-reassembly-feature", .runs_before = VNET_FEATURES ("ip4-lookup"), .runs_after = 0, }; -/* *INDENT-ON* */ VLIB_NODE_FN (ip4_sv_reass_node_output_feature) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_inline (vm, node, frame, true /* is_feature */ , - true /* is_output_feature */ , - false /* is_custom */ ); + return ip4_sv_reass_inline ( + vm, node, frame, true /* is_feature */, true /* is_output_feature */, + false /* is_custom */, false /* with_custom_context */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_node_output_feature) = { .name = "ip4-sv-reassembly-output-feature", .vector_size = sizeof (u32), .format_trace = format_ip4_sv_reass_trace, - .n_errors = ARRAY_LEN (ip4_sv_reass_error_strings), - .error_strings = ip4_sv_reass_error_strings, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, .n_next_nodes = IP4_SV_REASSEMBLY_N_NEXT, .next_nodes = { @@ -972,24 +1069,20 @@ VLIB_REGISTER_NODE (ip4_sv_reass_node_output_feature) = { [IP4_SV_REASSEMBLY_NEXT_HANDOFF] = "ip4-sv-reass-feature-hoff", }, }; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VNET_FEATURE_INIT (ip4_sv_reass_output_feature) = { .arc_name = "ip4-output", .node_name = "ip4-sv-reassembly-output-feature", .runs_before = 0, .runs_after = 0, }; -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_custom_node) = { .name = "ip4-sv-reassembly-custom-next", .vector_size = sizeof (u32), .format_trace = format_ip4_sv_reass_trace, - .n_errors = ARRAY_LEN (ip4_sv_reass_error_strings), - .error_strings = ip4_sv_reass_error_strings, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, .n_next_nodes = IP4_SV_REASSEMBLY_N_NEXT, .next_nodes = { @@ -999,15 +1092,39 @@ VLIB_REGISTER_NODE (ip4_sv_reass_custom_node) = { }, }; -/* *INDENT-ON* */ VLIB_NODE_FN (ip4_sv_reass_custom_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_inline (vm, node, frame, false /* is_feature */ , - false /* is_output_feature */ , - true /* is_custom */ ); + return ip4_sv_reass_inline ( + vm, node, frame, false /* is_feature */, false /* is_output_feature */, + true /* is_custom */, false /* with_custom_context */); +} + +VLIB_REGISTER_NODE (ip4_sv_reass_custom_context_node) = { + .name = "ip4-sv-reassembly-custom-context", + .vector_size = sizeof (u32), + .aux_size = sizeof(u32), + .format_trace = format_ip4_sv_reass_trace, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, + .n_next_nodes = IP4_SV_REASSEMBLY_N_NEXT, + .next_nodes = + { + [IP4_SV_REASSEMBLY_NEXT_INPUT] = "ip4-input", + [IP4_SV_REASSEMBLY_NEXT_DROP] = "ip4-drop", + [IP4_SV_REASSEMBLY_NEXT_HANDOFF] = "ip4-sv-reassembly-custom-context-handoff", + + }, +}; + +VLIB_NODE_FN (ip4_sv_reass_custom_context_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + return ip4_sv_reass_inline ( + vm, node, frame, false /* is_feature */, false /* is_output_feature */, + true /* is_custom */, true /* with_custom_context */); } #ifndef CLIB_MARCH_VARIANT @@ -1152,6 +1269,8 @@ ip4_sv_reass_init_function (vlib_main_t * vm) rm->fq_index = vlib_frame_queue_main_init (ip4_sv_reass_node.index, 0); rm->fq_feature_index = vlib_frame_queue_main_init (ip4_sv_reass_node_feature.index, 0); + rm->fq_custom_context_index = + vlib_frame_queue_main_init (ip4_sv_reass_custom_context_node.index, 0); rm->feature_use_refcount_per_intf = NULL; rm->output_feature_use_refcount_per_intf = NULL; @@ -1204,7 +1323,6 @@ ip4_sv_reass_walk_expired (vlib_main_t *vm, clib_spinlock_lock (&rt->lock); vec_reset_length (pool_indexes_to_free); - /* *INDENT-OFF* */ pool_foreach_index (index, rt->pool) { reass = pool_elt_at_index (rt->pool, index); if (now > reass->last_heard + rm->timeout) @@ -1212,15 +1330,12 @@ ip4_sv_reass_walk_expired (vlib_main_t *vm, vec_add1 (pool_indexes_to_free, index); } } - /* *INDENT-ON* */ int *i; - /* *INDENT-OFF* */ vec_foreach (i, pool_indexes_to_free) { ip4_sv_reass_t *reass = pool_elt_at_index (rt->pool, i[0]); ip4_sv_reass_free (vm, rm, rt, reass); } - /* *INDENT-ON* */ clib_spinlock_unlock (&rt->lock); } @@ -1228,33 +1343,29 @@ ip4_sv_reass_walk_expired (vlib_main_t *vm, vec_free (pool_indexes_to_free); if (event_data) { - _vec_len (event_data) = 0; + vec_set_len (event_data, 0); } } return 0; } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_expire_node) = { - .function = ip4_sv_reass_walk_expired, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "ip4-sv-reassembly-expire-walk", - .format_trace = format_ip4_sv_reass_trace, - .n_errors = ARRAY_LEN (ip4_sv_reass_error_strings), - .error_strings = ip4_sv_reass_error_strings, - + .function = ip4_sv_reass_walk_expired, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "ip4-sv-reassembly-expire-walk", + .format_trace = format_ip4_sv_reass_trace, + .n_errors = IP4_N_ERROR, + .error_counters = ip4_error_counters, }; -/* *INDENT-ON* */ static u8 * format_ip4_sv_reass_key (u8 * s, va_list * args) { ip4_sv_reass_key_t *key = va_arg (*args, ip4_sv_reass_key_t *); s = - format (s, - "xx_id: %u, src: %U, dst: %U, frag_id: %u, proto: %u", - key->xx_id, format_ip4_address, &key->src, format_ip4_address, + format (s, "fib_index: %u, src: %U, dst: %U, frag_id: %u, proto: %u", + key->fib_index, format_ip4_address, &key->src, format_ip4_address, &key->dst, clib_net_to_host_u16 (key->frag_id), key->proto); return s; } @@ -1313,11 +1424,9 @@ show_ip4_reass (vlib_main_t * vm, clib_spinlock_lock (&rt->lock); if (details) { - /* *INDENT-OFF* */ pool_foreach (reass, rt->pool) { vlib_cli_output (vm, "%U", format_ip4_sv_reass, vm, reass); } - /* *INDENT-ON* */ } sum_reass_n += rt->reass_n; clib_spinlock_unlock (&rt->lock); @@ -1341,13 +1450,11 @@ show_ip4_reass (vlib_main_t * vm, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_ip4_sv_reass_cmd, static) = { .path = "show ip4-sv-reassembly", .short_help = "show ip4-sv-reassembly [details]", .function = show_ip4_reass, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT vnet_api_error_t @@ -1398,25 +1505,30 @@ format_ip4_sv_reass_handoff_trace (u8 * s, va_list * args) } always_inline uword -ip4_sv_reass_handoff_node_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, bool is_feature) +ip4_sv_reass_handoff_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, bool is_feature, + bool is_custom_context) { ip4_sv_reass_main_t *rm = &ip4_sv_reass_main; vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; - u32 n_enq, n_left_from, *from; + u32 n_enq, n_left_from, *from, *context; u16 thread_indices[VLIB_FRAME_SIZE], *ti; u32 fq_index; from = vlib_frame_vector_args (frame); + if (is_custom_context) + context = vlib_frame_aux_args (frame); + n_left_from = frame->n_vectors; vlib_get_buffers (vm, from, bufs, n_left_from); b = bufs; ti = thread_indices; - fq_index = (is_feature) ? rm->fq_feature_index : rm->fq_index; + fq_index = (is_feature) ? rm->fq_feature_index : + (is_custom_context ? rm->fq_custom_context_index : + rm->fq_index); while (n_left_from > 0) { @@ -1435,8 +1547,12 @@ ip4_sv_reass_handoff_node_inline (vlib_main_t * vm, ti += 1; b += 1; } - n_enq = vlib_buffer_enqueue_to_thread (vm, node, fq_index, from, - thread_indices, frame->n_vectors, 1); + if (is_custom_context) + n_enq = vlib_buffer_enqueue_to_thread_with_aux ( + vm, node, fq_index, from, context, thread_indices, frame->n_vectors, 1); + else + n_enq = vlib_buffer_enqueue_to_thread ( + vm, node, fq_index, from, thread_indices, frame->n_vectors, 1); if (n_enq < frame->n_vectors) vlib_node_increment_counter (vm, node->node_index, @@ -1449,12 +1565,11 @@ VLIB_NODE_FN (ip4_sv_reass_handoff_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_handoff_node_inline (vm, node, frame, - false /* is_feature */ ); + return ip4_sv_reass_handoff_node_inline ( + vm, node, frame, false /* is_feature */, false /* is_custom_context */); } -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_handoff_node) = { .name = "ip4-sv-reassembly-handoff", .vector_size = sizeof (u32), @@ -1468,22 +1583,39 @@ VLIB_REGISTER_NODE (ip4_sv_reass_handoff_node) = { [0] = "error-drop", }, }; -/* *INDENT-ON* */ +VLIB_NODE_FN (ip4_sv_reass_custom_context_handoff_node) +(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) +{ + return ip4_sv_reass_handoff_node_inline ( + vm, node, frame, false /* is_feature */, true /* is_custom_context */); +} + +VLIB_REGISTER_NODE (ip4_sv_reass_custom_context_handoff_node) = { + .name = "ip4-sv-reassembly-custom-context-handoff", + .vector_size = sizeof (u32), + .aux_size = sizeof (u32), + .n_errors = ARRAY_LEN(ip4_sv_reass_handoff_error_strings), + .error_strings = ip4_sv_reass_handoff_error_strings, + .format_trace = format_ip4_sv_reass_handoff_trace, + + .n_next_nodes = 1, + + .next_nodes = { + [0] = "error-drop", + }, +}; -/* *INDENT-OFF* */ VLIB_NODE_FN (ip4_sv_reass_feature_handoff_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { - return ip4_sv_reass_handoff_node_inline (vm, node, frame, - true /* is_feature */ ); + return ip4_sv_reass_handoff_node_inline ( + vm, node, frame, true /* is_feature */, false /* is_custom_context */); } -/* *INDENT-ON* */ -/* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_sv_reass_feature_handoff_node) = { .name = "ip4-sv-reass-feature-hoff", .vector_size = sizeof (u32), @@ -1497,7 +1629,6 @@ VLIB_REGISTER_NODE (ip4_sv_reass_feature_handoff_node) = { [0] = "error-drop", }, }; -/* *INDENT-ON* */ #ifndef CLIB_MARCH_VARIANT int @@ -1535,6 +1666,13 @@ ip4_sv_reass_custom_register_next_node (uword node_index) node_index); } +uword +ip4_sv_reass_custom_context_register_next_node (uword node_index) +{ + return vlib_node_add_next ( + vlib_get_main (), ip4_sv_reass_custom_context_node.index, node_index); +} + int ip4_sv_reass_output_enable_disable_with_refcnt (u32 sw_if_index, int is_enable) |