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 <dave@barachs.net>
This commit is contained in:
Dave Barach
2017-10-18 18:48:11 -04:00
committed by Florin Coras
parent 9c4b5b28b1
commit 7bee773e71
7 changed files with 164 additions and 53 deletions

View File

@ -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 */

View File

@ -884,51 +884,31 @@ 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];
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");
(*vlib_buffer_trace_trajectory_init_cb) (b);
}
}
#endif
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))
{
(*vlib_buffer_trace_trajectory_cb) (b, node_index);
}
#endif
}
static_always_inline u64
dispatch_node (vlib_main_t * vm,
@ -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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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;
#endif
return 0;
}
VLIB_INIT_FUNCTION (vnet_interface_init);

View File

@ -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; }

View File

@ -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 <vnet/vnet.h>
/**
* 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:
*/