From 8563cb389a7e8d6d4e042e146c0d94b8af98ca7a Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Thu, 10 Oct 2019 17:03:57 +0000 Subject: ip: reassembly: trace ip headers over worker handoffs This change adds tracing of IP headers when doing a handoff between worker threads. This eases debugging. Type: feature Change-Id: I2195b070a364cba13a658ec1cee5154fc4c3a8b0 Signed-off-by: Klement Sekera --- src/vnet/ip/format.h | 1 + src/vnet/ip/ip6_format.c | 19 +++++++++++++++ src/vnet/ip/ip6_input.c | 21 +--------------- src/vnet/ip/reass/ip4_full_reass.c | 24 ++++++++++++++++++- src/vnet/ip/reass/ip6_full_reass.c | 49 +++++++++++++++++++++++++++++++++----- 5 files changed, 87 insertions(+), 27 deletions(-) diff --git a/src/vnet/ip/format.h b/src/vnet/ip/format.h index 7b1740dad04..952455c975a 100644 --- a/src/vnet/ip/format.h +++ b/src/vnet/ip/format.h @@ -95,6 +95,7 @@ format_function_t format_ip6_address_and_length; format_function_t format_ip6_address_and_mask; unformat_function_t unformat_ip6_header; format_function_t format_ip6_header; +format_function_t format_ip6_frag_hdr; unformat_function_t unformat_pg_ip6_header; /* Format a TCP/UDP headers. */ diff --git a/src/vnet/ip/ip6_format.c b/src/vnet/ip/ip6_format.c index 4d1793970df..5b8df239bf2 100644 --- a/src/vnet/ip/ip6_format.c +++ b/src/vnet/ip/ip6_format.c @@ -417,6 +417,25 @@ format_ip46_address (u8 * s, va_list * args) format (s, "%U", format_ip6_address, &ip46->ip6); } +u8 * +format_ip6_frag_hdr (u8 * s, va_list * args) +{ + ip6_frag_hdr_t *h = va_arg (*args, ip6_frag_hdr_t *); + u32 max_header_bytes = va_arg (*args, u32); + u32 header_bytes; + + header_bytes = sizeof (h[0]); + if (max_header_bytes != 0 && header_bytes > max_header_bytes) + return format (s, "ipv6 frag header truncated"); + + s = + format (s, + "IPV6_FRAG_HDR: next_hdr: %u, rsv: %u, frag_offset_and_more: %u, id: %u", + h->next_hdr, h->rsv, h->fragment_offset_and_more, + clib_net_to_host_u32 (h->identification)); + return s; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/ip/ip6_input.c b/src/vnet/ip/ip6_input.c index 943f6597a90..ebcfd5a9f05 100644 --- a/src/vnet/ip/ip6_input.c +++ b/src/vnet/ip/ip6_input.c @@ -247,25 +247,6 @@ VLIB_REGISTER_NODE (ip6_input_node) = { }; /* *INDENT-ON* */ -static u8 * -format_ipv6_fragmentation (u8 * s, va_list * args) -{ - ip6_frag_hdr_t *h = va_arg (*args, ip6_frag_hdr_t *); - u32 max_header_bytes = va_arg (*args, u32); - u32 header_bytes; - - header_bytes = sizeof (h[0]); - if (max_header_bytes != 0 && header_bytes > max_header_bytes) - return format (s, "ipv6 frag header truncated"); - - s = - format (s, - "fragmentation header: next_hdr: %u, rsv: %u, frag_offset_and_more: %u, id: %u", - h->next_hdr, h->rsv, h->fragment_offset_and_more, - clib_net_to_host_u32 (h->identification)); - return s; -} - static clib_error_t * ip6_init (vlib_main_t * vm) { @@ -292,7 +273,7 @@ ip6_init (vlib_main_t * vm) ip_protocol_info_t *info = vec_elt_at_index (ip_main.protocol_infos, *u); ASSERT (NULL == info->format_header); - info->format_header = format_ipv6_fragmentation; + info->format_header = format_ip6_frag_hdr; } return /* no error */ 0; } diff --git a/src/vnet/ip/reass/ip4_full_reass.c b/src/vnet/ip/reass/ip4_full_reass.c index 87a677208fb..303f23337ee 100644 --- a/src/vnet/ip/reass/ip4_full_reass.c +++ b/src/vnet/ip/reass/ip4_full_reass.c @@ -235,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; @@ -274,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, @@ -322,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; diff --git a/src/vnet/ip/reass/ip6_full_reass.c b/src/vnet/ip/reass/ip6_full_reass.c index bba11e52959..aaaf56a5d59 100644 --- a/src/vnet/ip/reass/ip6_full_reass.c +++ b/src/vnet/ip/reass/ip6_full_reass.c @@ -215,6 +215,9 @@ typedef struct u32 total_data_len; u32 thread_id; u32 thread_id_to; + bool is_after_handoff; + ip6_header_t ip6_header; + ip6_frag_hdr_t ip6_frag_header; } ip6_full_reass_trace_t; static void @@ -251,7 +254,19 @@ format_ip6_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_ip6_header, &t->ip6_header, + sizeof (t->ip6_header)); + s = + format (s, " %U\n", format_ip6_frag_hdr, &t->ip6_frag_header, + sizeof (t->ip6_frag_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, "first bi: %u, data len: %u, ip/fragment[%u, %u]", t->trace_range.first_bi, t->total_data_len, @@ -297,12 +312,33 @@ static void ip6_full_reass_add_trace (vlib_main_t * vm, vlib_node_runtime_t * node, ip6_full_reass_main_t * rm, ip6_full_reass_t * reass, u32 bi, + ip6_frag_hdr_t * ip6_frag_header, ip6_full_reass_trace_operation_e action, u32 thread_id_to) { 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; + } ip6_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->ip6_header, vlib_buffer_get_current (b), + clib_min (sizeof (t->ip6_header), b->current_length)); + if (ip6_frag_header) + { + clib_memcpy (&t->ip6_frag_header, ip6_frag_header, + sizeof (t->ip6_frag_header)); + } + else + { + clib_memset (&t->ip6_frag_header, 0, sizeof (t->ip6_frag_header)); + } + } if (reass) { t->reass_id = reass->id; @@ -434,7 +470,7 @@ ip6_full_reass_on_timeout (vlib_main_t * vm, vlib_node_runtime_t * node, if (PREDICT_FALSE (b->flags & VLIB_BUFFER_IS_TRACED)) { ip6_full_reass_add_trace (vm, node, rm, reass, reass->first_bi, - ICMP_ERROR_RT_EXCEEDED, ~0); + NULL, ICMP_ERROR_RT_EXCEEDED, ~0); } // fragment with offset zero received - send icmp message back if (b->flags & VLIB_BUFFER_NEXT_PRESENT) @@ -721,7 +757,7 @@ ip6_full_reass_finalize (vlib_main_t * vm, vlib_node_runtime_t * node, first_b->flags &= ~VLIB_BUFFER_EXT_HDR_VALID; if (PREDICT_FALSE (first_b->flags & VLIB_BUFFER_IS_TRACED)) { - ip6_full_reass_add_trace (vm, node, rm, reass, reass->first_bi, + ip6_full_reass_add_trace (vm, node, rm, reass, reass->first_bi, NULL, FINALIZE, ~0); #if 0 // following code does a hexdump of packet fragments to stdout ... @@ -889,7 +925,7 @@ ip6_full_reass_update (vlib_main_t * vm, vlib_node_runtime_t * node, // overlapping fragment - not allowed by RFC 8200 if (PREDICT_FALSE (fb->flags & VLIB_BUFFER_IS_TRACED)) { - ip6_full_reass_add_trace (vm, node, rm, reass, *bi0, + ip6_full_reass_add_trace (vm, node, rm, reass, *bi0, frag_hdr, RANGE_OVERLAP, ~0); } ip6_full_reass_drop_all (vm, node, rm, reass); @@ -906,7 +942,8 @@ check_if_done_maybe: { if (PREDICT_FALSE (fb->flags & VLIB_BUFFER_IS_TRACED)) { - ip6_full_reass_add_trace (vm, node, rm, reass, *bi0, RANGE_NEW, ~0); + ip6_full_reass_add_trace (vm, node, rm, reass, *bi0, frag_hdr, + RANGE_NEW, ~0); } } if (~0 != reass->last_packet_octet && @@ -1175,7 +1212,7 @@ ip6_full_reassembly_inline (vlib_main_t * vm, if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ip6_full_reass_add_trace (vm, node, rm, NULL, bi0, - HANDOFF, + frag_hdr, HANDOFF, vnet_buffer (b0)->ip. reass.owner_thread_index); } -- cgit 1.2.3-korg