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
committed by
Florin Coras
parent
9c4b5b28b1
commit
7bee773e71
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
95
src/vnet/util/trajectory.c
Normal file
95
src/vnet/util/trajectory.c
Normal 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:
|
||||
*/
|
Reference in New Issue
Block a user