From 7bee773e71b81a1e13a656030b0f7edae99c5e92 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Wed, 18 Oct 2017 18:48:11 -0400 Subject: [PATCH] VPP-1024: rewrite buffer trajectory tracer Use a proper u16 * vector to capture node indices, since vpp w/ plugins now exceeds 255 graph nodes Change-Id: Ic48cad676fa3a6116413ddf08c083dd9660783f1 Signed-off-by: Dave Barach --- src/vlib/buffer.h | 9 ++++- src/vlib/main.c | 59 +++++++++------------------- src/vnet.am | 3 +- src/vnet/buffer.h | 17 +++++++++ src/vnet/interface.c | 15 +++++--- src/vnet/unix/gdb_funcs.c | 13 +++++++ src/vnet/util/trajectory.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 161 insertions(+), 50 deletions(-) create mode 100644 src/vnet/util/trajectory.c diff --git a/src/vlib/buffer.h b/src/vlib/buffer.h index e47dbc6d4fd..e5c1d21397b 100644 --- a/src/vlib/buffer.h +++ b/src/vlib/buffer.h @@ -142,7 +142,8 @@ typedef struct /**< Only valid for first buffer in chain. Current length plus total length given here give total number of bytes in buffer chain. */ - u32 opaque2[13]; /**< More opaque data, currently unused */ + u32 align_pad; /**< available */ + u32 opaque2[12]; /**< More opaque data, see ../vnet/vnet/buffer.h */ /***** end of second cache line */ CLIB_CACHE_LINE_ALIGN_MARK (cacheline2); @@ -512,7 +513,11 @@ serialize_vlib_buffer_n_bytes (serialize_main_t * m) #define VLIB_BUFFER_TRACE_TRAJECTORY 0 #if VLIB_BUFFER_TRACE_TRAJECTORY > 0 -#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) (b)->pre_data[0]=0 +extern void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 index); +extern void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b); +extern void vlib_buffer_trace_trajectory_init (vlib_buffer_t * b); +#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) \ + vlib_buffer_trace_trajectory_init (b); #else #define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b) #endif /* VLIB_BUFFER_TRACE_TRAJECTORY */ diff --git a/src/vlib/main.c b/src/vlib/main.c index 7875f62ad37..fd9937fe3e6 100644 --- a/src/vlib/main.c +++ b/src/vlib/main.c @@ -884,52 +884,32 @@ vlib_elog_main_loop_event (vlib_main_t * vm, /* data to log */ n_vectors); } +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 +void (*vlib_buffer_trace_trajectory_cb) (vlib_buffer_t * b, u32 node_index); +void (*vlib_buffer_trace_trajectory_init_cb) (vlib_buffer_t * b); + void -vlib_dump_context_trace (vlib_main_t * vm, u32 bi) +vlib_buffer_trace_trajectory_init (vlib_buffer_t * b) { - vlib_node_main_t *vnm = &vm->node_main; - vlib_buffer_t *b; - u8 i, n; - - if (VLIB_BUFFER_TRACE_TRAJECTORY) + if (PREDICT_TRUE (vlib_buffer_trace_trajectory_init_cb != 0)) { - b = vlib_get_buffer (vm, bi); - n = b->pre_data[0]; - - fformat (stderr, "Context trace for bi %d b 0x%llx, visited %d\n", - bi, b, n); - - if (n == 0 || n > 20) - { - fformat (stderr, "n is unreasonable\n"); - return; - } - - - for (i = 0; i < n; i++) - { - u32 node_index; - - node_index = b->pre_data[i + 1]; + (*vlib_buffer_trace_trajectory_init_cb) (b); + } +} - if (node_index > vec_len (vnm->nodes)) - { - fformat (stderr, "Skip bogus node index %d\n", node_index); - continue; - } +#endif - fformat (stderr, "%v (%d)\n", vnm->nodes[node_index]->name, - node_index); - } - } - else +static inline void +add_trajectory_trace (vlib_buffer_t * b, u32 node_index) +{ +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 + if (PREDICT_TRUE (vlib_buffer_trace_trajectory_cb != 0)) { - fformat (stderr, - "in vlib/buffers.h, #define VLIB_BUFFER_TRACE_TRAJECTORY 1\n"); + (*vlib_buffer_trace_trajectory_cb) (b, node_index); } +#endif } - static_always_inline u64 dispatch_node (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -995,15 +975,12 @@ dispatch_node (vlib_main_t * vm, if (VLIB_BUFFER_TRACE_TRAJECTORY && frame) { int i; - int log_index; u32 *from; from = vlib_frame_vector_args (frame); for (i = 0; i < frame->n_vectors; i++) { vlib_buffer_t *b = vlib_get_buffer (vm, from[i]); - ASSERT (b->pre_data[0] < 32); - log_index = b->pre_data[0]++ + 1; - b->pre_data[log_index] = node->node_index; + add_trajectory_trace (b, node->node_index); } n = node->function (vm, node, frame); } diff --git a/src/vnet.am b/src/vnet.am index 97964c5132e..d76441fcc79 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -1094,7 +1094,8 @@ nobase_include_HEADERS += \ ######################################## libvnet_la_SOURCES += \ - vnet/util/radix.c + vnet/util/radix.c \ + vnet/util/trajectory.c ######################################## # Plugin client library diff --git a/src/vnet/buffer.h b/src/vnet/buffer.h index 7567b875248..045328816cd 100644 --- a/src/vnet/buffer.h +++ b/src/vnet/buffer.h @@ -317,9 +317,26 @@ typedef struct { union { +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 + /* buffer trajectory tracing */ + struct + { + u16 *trajectory_trace; + }; +#endif + u32 unused[12]; }; } vnet_buffer_opaque2_t; +#define vnet_buffer2(b) ((vnet_buffer_opaque2_t *) (b)->opaque2) + +/* + * The opaque2 field of the vlib_buffer_t is intepreted as a + * vnet_buffer_opaque2_t. Hence it should be big enough to accommodate one. + */ +STATIC_ASSERT (sizeof (vnet_buffer_opaque2_t) <= + STRUCT_SIZE_OF (vlib_buffer_t, opaque2), + "VNET buffer opaque2 meta-data too large for vlib_buffer"); #endif /* included_vnet_buffer_h */ diff --git a/src/vnet/interface.c b/src/vnet/interface.c index 159ce8c6494..eb5d3d0fced 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -1170,6 +1170,7 @@ vnet_interface_init (vlib_main_t * vm) vnet_interface_main_t *im = &vnm->interface_main; vlib_buffer_t *b = 0; vnet_buffer_opaque_t *o = 0; + clib_error_t *error; /* * Keep people from shooting themselves in the foot. @@ -1250,15 +1251,17 @@ vnet_interface_init (vlib_main_t * vm) } } - { - clib_error_t *error; + if ((error = vlib_call_init_function (vm, vnet_interface_cli_init))) + return error; - if ((error = vlib_call_init_function (vm, vnet_interface_cli_init))) - return error; + vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword)); +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 + if ((error = vlib_call_init_function (vm, trajectory_trace_init))) return error; - } - vnm->interface_tag_by_sw_if_index = hash_create (0, sizeof (uword)); +#endif + + return 0; } VLIB_INIT_FUNCTION (vnet_interface_init); diff --git a/src/vnet/unix/gdb_funcs.c b/src/vnet/unix/gdb_funcs.c index 32e22d924ba..40d0d663472 100644 --- a/src/vnet/unix/gdb_funcs.c +++ b/src/vnet/unix/gdb_funcs.c @@ -190,6 +190,8 @@ show_gdb_command_fn (vlib_main_t * vm, vlib_cli_command_t * cmd) { vlib_cli_output (vm, "vl(p) returns vec_len(p)"); + vlib_cli_output (vm, "vb(b) returns vnet_buffer(b) [opaque]"); + vlib_cli_output (vm, "vb2(b) returns vnet_buffer2(b) [opaque2]"); vlib_cli_output (vm, "pe(p) returns pool_elts(p)"); vlib_cli_output (vm, "pifi(p, i) returns pool_is_free_index(p, i)"); vlib_cli_output (vm, "gdb_show_errors(0|1) dumps error counters"); @@ -217,6 +219,17 @@ vnet_buffer_opaque_t *vb (void *vb_arg) return rv; } +vnet_buffer_opaque2_t *vb2 (void *vb_arg) +{ + vlib_buffer_t *b = (vlib_buffer_t *)vb_arg; + vnet_buffer_opaque2_t *rv; + + rv = vnet_buffer2(b); + + return rv; +} + + /* Cafeteria plan, maybe you don't want these functions */ clib_error_t * gdb_func_init (vlib_main_t * vm) { return 0; } diff --git a/src/vnet/util/trajectory.c b/src/vnet/util/trajectory.c new file mode 100644 index 00000000000..24b51254ecd --- /dev/null +++ b/src/vnet/util/trajectory.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \file + * Buffer trace trajectory utilities + */ + +#include + +/** + * Dump a trajectory trace, reasonably easy to call from gdb + */ +void +vnet_dump_trajectory_trace (vlib_main_t * vm, u32 bi) +{ +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 + vlib_node_main_t *vnm = &vm->node_main; + vlib_buffer_t *b; + u16 *trace; + u8 i; + + b = vlib_get_buffer (vm, bi); + + trace = vnet_buffer2 (b)->trajectory_trace; + + fformat (stderr, "Context trace for bi %d b 0x%llx, visited %d\n", + bi, b, vec_len (trace)); + + for (i = 0; i < vec_len (trace); i++) + { + u32 node_index; + + node_index = trace[i]; + + if (node_index > vec_len (vnm->nodes)) + { + fformat (stderr, "Skip bogus node index %d\n", node_index); + continue; + } + + fformat (stderr, "%v (%d)\n", vnm->nodes[node_index]->name, node_index); + } +#else + fformat (stderr, "in vlib/buffers.h, " + "#define VLIB_BUFFER_TRACE_TRAJECTORY 1\n"); + +#endif +} + +#if VLIB_BUFFER_TRACE_TRAJECTORY > 0 + +void +init_trajectory_trace (vlib_buffer_t * b) +{ + vec_validate (vnet_buffer2 (b)->trajectory_trace, 7); + _vec_len (vnet_buffer2 (b)->trajectory_trace) = 0; +} + +void +add_trajectory_trace (vlib_buffer_t * b, u32 node_index) +{ + vec_add1 (vnet_buffer2 (b)->trajectory_trace, (u16) node_index); +} + +static clib_error_t * +trajectory_trace_init (vlib_main_t * vm) +{ + vlib_buffer_trace_trajectory_cb = add_trajectory_trace; + vlib_buffer_trace_trajectory_init_cb = init_trajectory_trace; + return 0; +} + +VLIB_INIT_FUNCTION (trajectory_trace_init); + +#endif + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- 2.16.6