X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fip%2Freass%2Fip4_full_reass.c;h=b1d8a56fb933fe6ecdcd8dba75802cdd5c20c261;hb=a877cf9f3980f9721246887f67b22b6591cb873f;hp=18ac4d1b1b01694ee05cd49bf03846a7b558c205;hpb=de34c35fc73226943538149fae9dbc5cfbdc6e75;p=vpp.git diff --git a/src/vnet/ip/reass/ip4_full_reass.c b/src/vnet/ip/reass/ip4_full_reass.c index 18ac4d1b1b0..b1d8a56fb93 100644 --- a/src/vnet/ip/reass/ip4_full_reass.c +++ b/src/vnet/ip/reass/ip4_full_reass.c @@ -185,6 +185,8 @@ typedef struct u32 fq_index; u32 fq_feature_index; + // reference count for enabling/disabling feature - per interface + u32 *feature_use_refcount_per_intf; } ip4_full_reass_main_t; extern ip4_full_reass_main_t ip4_full_reass_main; @@ -233,6 +235,8 @@ typedef struct u32 fragment_first; u32 fragment_last; u32 total_data_len; + bool is_after_handoff; + ip4_header_t ip4_header; } ip4_full_reass_trace_t; extern vlib_node_registration_t ip4_full_reass_node; @@ -272,7 +276,16 @@ format_ip4_full_reass_trace (u8 * s, va_list * args) u32 indent = 0; if (~0 != t->reass_id) { - s = format (s, "reass id: %u, op id: %u, ", t->reass_id, t->op_id); + if (t->is_after_handoff) + { + s = + format (s, "%U\n", format_ip4_header, &t->ip4_header, + sizeof (t->ip4_header)); + indent = 2; + } + s = + format (s, "%Ureass id: %u, op id: %u, ", format_white_space, indent, + t->reass_id, t->op_id); indent = format_get_indent (s); s = format (s, @@ -320,7 +333,18 @@ ip4_full_reass_add_trace (vlib_main_t * vm, vlib_node_runtime_t * node, { vlib_buffer_t *b = vlib_get_buffer (vm, bi); vnet_buffer_opaque_t *vnb = vnet_buffer (b); + bool is_after_handoff = false; + if (vlib_buffer_get_trace_thread (b) != vm->thread_index) + { + is_after_handoff = true; + } ip4_full_reass_trace_t *t = vlib_add_trace (vm, node, b, sizeof (t[0])); + t->is_after_handoff = is_after_handoff; + if (t->is_after_handoff) + { + clib_memcpy (&t->ip4_header, vlib_buffer_get_current (b), + clib_min (sizeof (t->ip4_header), b->current_length)); + } if (reass) { t->reass_id = reass->id; @@ -1040,11 +1064,12 @@ ip4_full_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node, reass->data_len == reass->last_packet_octet + 1) { *handoff_thread_idx = reass->sendout_thread_index; + int handoff = + reass->memory_owner_thread_index != reass->sendout_thread_index; rc = ip4_full_reass_finalize (vm, node, rm, rt, reass, bi0, next0, error0, is_custom_app); - if (IP4_REASS_RC_OK == rc - && reass->memory_owner_thread_index != reass->sendout_thread_index) + if (IP4_REASS_RC_OK == rc && handoff) { rc = IP4_REASS_RC_HANDOFF; } @@ -1199,13 +1224,17 @@ ip4_full_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, packet_enqueue: - b0->error = node->errors[error0]; if (bi0 != ~0) { to_next[0] = bi0; to_next += 1; n_left_to_next -= 1; + + /* bi0 might have been updated by reass_finalize, reload */ + b0 = vlib_get_buffer (vm, bi0); + b0->error = node->errors[error0]; + if (next0 == IP4_FULL_REASS_NEXT_HANDOFF) { if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -1218,7 +1247,6 @@ ip4_full_reass_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else if (is_feature && IP4_ERROR_NONE == error0) { - b0 = vlib_get_buffer (vm, bi0); vnet_feature_next (&next0, b0); } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, @@ -1337,7 +1365,7 @@ typedef struct } ip4_rehash_cb_ctx; #ifndef CLIB_MARCH_VARIANT -static void +static int ip4_rehash_cb (clib_bihash_kv_16_8_t * kv, void *_ctx) { ip4_rehash_cb_ctx *ctx = _ctx; @@ -1345,6 +1373,7 @@ ip4_rehash_cb (clib_bihash_kv_16_8_t * kv, void *_ctx) { ctx->failure = 1; } + return (BIHASH_WALK_CONTINUE); } static void @@ -1447,6 +1476,7 @@ ip4_full_reass_init_function (vlib_main_t * vm) rm->fq_feature_index = vlib_frame_queue_main_init (ip4_full_reass_node_feature.index, 0); + rm->feature_use_refcount_per_intf = NULL; return error; } @@ -1624,11 +1654,17 @@ show_ip4_reass (vlib_main_t * vm, clib_spinlock_unlock (&rt->lock); } vlib_cli_output (vm, "---------------------"); - vlib_cli_output (vm, "Current IP4 reassemblies count: %lu\n", + vlib_cli_output (vm, "Current full IP4 reassemblies count: %lu\n", (long unsigned) sum_reass_n); vlib_cli_output (vm, - "Maximum configured concurrent IP4 reassemblies per worker-thread: %lu\n", + "Maximum configured concurrent full IP4 reassemblies per worker-thread: %lu\n", (long unsigned) rm->max_reass_n); + vlib_cli_output (vm, + "Maximum configured full IP4 reassembly timeout: %lums\n", + (long unsigned) rm->timeout_ms); + vlib_cli_output (vm, + "Maximum configured full IP4 reassembly expire walk interval: %lums\n", + (long unsigned) rm->expire_walk_interval_ms); return 0; } @@ -1792,6 +1828,35 @@ VLIB_REGISTER_NODE (ip4_full_reass_feature_handoff_node) = { }; /* *INDENT-ON* */ +#ifndef CLIB_MARCH_VARIANT +int +ip4_full_reass_enable_disable_with_refcnt (u32 sw_if_index, int is_enable) +{ + ip4_full_reass_main_t *rm = &ip4_full_reass_main; + vec_validate (rm->feature_use_refcount_per_intf, sw_if_index); + if (is_enable) + { + if (!rm->feature_use_refcount_per_intf[sw_if_index]) + { + ++rm->feature_use_refcount_per_intf[sw_if_index]; + return vnet_feature_enable_disable ("ip4-unicast", + "ip4-full-reassembly-feature", + sw_if_index, 1, 0, 0); + } + ++rm->feature_use_refcount_per_intf[sw_if_index]; + } + else + { + --rm->feature_use_refcount_per_intf[sw_if_index]; + if (!rm->feature_use_refcount_per_intf[sw_if_index]) + return vnet_feature_enable_disable ("ip4-unicast", + "ip4-full-reassembly-feature", + sw_if_index, 0, 0, 0); + } + return -1; +} +#endif + /* * fd.io coding-style-patch-verification: ON *