dpdk: cli to check for buffer leakage
Use buffer pre_data and existing buffer trace trajectory code to find out dpdk buffer leakages. Change-Id: I26a5d8bd2f23d01cb6070ffc3ddcc6d3d863b575 Signed-off-by: Florin Coras <fcoras@cisco.com>
This commit is contained in:
committed by
Dave Barach
parent
3e233678f1
commit
2f9b0c05fc
@@ -340,7 +340,7 @@ vlib_buffer_free_inline (vlib_main_t * vm,
|
||||
vlib_buffer_t *b;
|
||||
|
||||
b = vlib_get_buffer (vm, buffers[i]);
|
||||
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
|
||||
fl = vlib_buffer_get_buffer_free_list (vm, b, &fi);
|
||||
|
||||
/* The only current use of this callback: multicast recycle */
|
||||
@@ -493,6 +493,67 @@ buffer_state_validation_init (vlib_main_t * vm)
|
||||
VLIB_INIT_FUNCTION (buffer_state_validation_init);
|
||||
#endif
|
||||
|
||||
#if CLI_DEBUG
|
||||
struct dpdk_validate_buf_result
|
||||
{
|
||||
u32 invalid;
|
||||
u32 uninitialized;
|
||||
};
|
||||
|
||||
#define DPDK_TRAJECTORY_POISON 31
|
||||
|
||||
static void
|
||||
dpdk_buffer_validate_trajectory (struct rte_mempool *mp, void *opaque,
|
||||
void *obj, unsigned obj_idx)
|
||||
{
|
||||
vlib_buffer_t *b;
|
||||
struct dpdk_validate_buf_result *counter = opaque;
|
||||
b = vlib_buffer_from_rte_mbuf ((struct rte_mbuf *) obj);
|
||||
if (b->pre_data[0] != 0)
|
||||
{
|
||||
if (b->pre_data[0] == DPDK_TRAJECTORY_POISON)
|
||||
counter->uninitialized++;
|
||||
else
|
||||
counter->invalid++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dpdk_buffer_validate_trajectory_all (u32 * uninitialized)
|
||||
{
|
||||
dpdk_main_t *dm = &dpdk_main;
|
||||
struct dpdk_validate_buf_result counter = { 0 };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vec_len (dm->pktmbuf_pools); i++)
|
||||
rte_mempool_obj_iter (dm->pktmbuf_pools[i],
|
||||
dpdk_buffer_validate_trajectory, &counter);
|
||||
if (uninitialized)
|
||||
*uninitialized = counter.uninitialized;
|
||||
return counter.invalid;
|
||||
}
|
||||
|
||||
static void
|
||||
dpdk_buffer_poison_trajectory (struct rte_mempool *mp, void *opaque,
|
||||
void *obj, unsigned obj_idx)
|
||||
{
|
||||
vlib_buffer_t *b;
|
||||
b = vlib_buffer_from_rte_mbuf ((struct rte_mbuf *) obj);
|
||||
b->pre_data[0] = DPDK_TRAJECTORY_POISON;
|
||||
}
|
||||
|
||||
void
|
||||
dpdk_buffer_poison_trajectory_all (void)
|
||||
{
|
||||
dpdk_main_t *dm = &dpdk_main;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < vec_len (dm->pktmbuf_pools); i++)
|
||||
rte_mempool_obj_iter (dm->pktmbuf_pools[i], dpdk_buffer_poison_trajectory,
|
||||
0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_BUFFER_REGISTER_CALLBACKS (dpdk, static) = {
|
||||
.vlib_buffer_alloc_cb = &dpdk_buffer_alloc,
|
||||
|
||||
@@ -1885,6 +1885,59 @@ VLIB_CLI_COMMAND (show_vpe_version_command, static) = {
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#if CLI_DEBUG
|
||||
|
||||
static clib_error_t *
|
||||
dpdk_validate_buffers_fn (vlib_main_t * vm, unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd_arg)
|
||||
{
|
||||
u32 n_invalid_bufs = 0, uninitialized = 0;
|
||||
u32 is_poison = 0, is_test = 0;
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "poison"))
|
||||
is_poison = 1;
|
||||
else if (unformat (input, "trajectory"))
|
||||
is_test = 1;
|
||||
else
|
||||
return clib_error_return (0, "unknown input `%U'",
|
||||
format_unformat_error, input);
|
||||
}
|
||||
|
||||
if (VLIB_BUFFER_TRACE_TRAJECTORY == 0)
|
||||
{
|
||||
vlib_cli_output (vm, "Trajectory not enabled. Recompile with "
|
||||
"VLIB_BUFFER_TRACE_TRAJECTORY 1");
|
||||
return 0;
|
||||
}
|
||||
if (is_poison)
|
||||
{
|
||||
dpdk_buffer_poison_trajectory_all ();
|
||||
}
|
||||
if (is_test)
|
||||
{
|
||||
n_invalid_bufs = dpdk_buffer_validate_trajectory_all (&uninitialized);
|
||||
if (!n_invalid_bufs)
|
||||
vlib_cli_output (vm, "All buffers are valid %d uninitialized",
|
||||
uninitialized);
|
||||
else
|
||||
vlib_cli_output (vm, "Found %d invalid buffers and %d uninitialized",
|
||||
n_invalid_bufs, uninitialized);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (test_dpdk_buffers_command, static) =
|
||||
{
|
||||
.path = "test dpdk buffers",
|
||||
.short_help = "test dpdk buffers [poison] [trajectory]",
|
||||
.function = dpdk_validate_buffers_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
#endif
|
||||
|
||||
clib_error_t *
|
||||
dpdk_cli_init (vlib_main_t * vm)
|
||||
{
|
||||
|
||||
@@ -462,6 +462,11 @@ dpdk_interface_tx (vlib_main_t * vm,
|
||||
|
||||
or_flags = b0->flags | b1->flags | b2->flags | b3->flags;
|
||||
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b2);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b3);
|
||||
|
||||
if (or_flags & VLIB_BUFFER_NEXT_PRESENT)
|
||||
{
|
||||
dpdk_validate_rte_mbuf (vm, b0, 1);
|
||||
@@ -556,6 +561,7 @@ dpdk_interface_tx (vlib_main_t * vm,
|
||||
from++;
|
||||
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
|
||||
|
||||
dpdk_validate_rte_mbuf (vm, b0, 1);
|
||||
|
||||
|
||||
@@ -467,6 +467,11 @@ admin_up_down_process (vlib_main_t * vm,
|
||||
clib_error_t *dpdk_buffer_pool_create (vlib_main_t * vm, unsigned num_mbufs,
|
||||
unsigned socket_id);
|
||||
|
||||
#if CLI_DEBUG
|
||||
int dpdk_buffer_validate_trajectory_all (u32 * uninitialized);
|
||||
void dpdk_buffer_poison_trajectory_all (void);
|
||||
#endif
|
||||
|
||||
#endif /* __included_dpdk_h__ */
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -686,7 +686,7 @@ vlib_buffer_free_inline (vlib_main_t * vm,
|
||||
u32 bi = buffers[i];
|
||||
|
||||
b = vlib_get_buffer (vm, bi);
|
||||
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b);
|
||||
fl = vlib_buffer_get_buffer_free_list (vm, b, &fi);
|
||||
|
||||
/* The only current use of this callback: multicast recycle */
|
||||
|
||||
@@ -2131,6 +2131,7 @@ ip4_arp_inline (vlib_main_t * vm,
|
||||
|
||||
vlib_buffer_copy_trace_flag (vm, p0, bi0);
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
|
||||
vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
|
||||
|
||||
vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
|
||||
|
||||
@@ -439,14 +439,16 @@ tcp_init_mss (tcp_connection_t * tc)
|
||||
always_inline int
|
||||
tcp_alloc_tx_buffers (tcp_main_t * tm, u8 thread_index, u32 n_free_buffers)
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
u32 current_length = vec_len (tm->tx_buffers[thread_index]);
|
||||
u32 n_allocated;
|
||||
|
||||
vec_validate (tm->tx_buffers[thread_index],
|
||||
current_length + n_free_buffers - 1);
|
||||
_vec_len (tm->tx_buffers[thread_index]) = current_length
|
||||
+ vlib_buffer_alloc (vlib_get_main (),
|
||||
&tm->tx_buffers[thread_index][current_length],
|
||||
n_free_buffers);
|
||||
n_allocated =
|
||||
vlib_buffer_alloc (vm, &tm->tx_buffers[thread_index][current_length],
|
||||
n_free_buffers);
|
||||
_vec_len (tm->tx_buffers[thread_index]) = current_length + n_allocated;
|
||||
/* buffer shortage, report failure */
|
||||
if (vec_len (tm->tx_buffers[thread_index]) == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user