misc: unify pcap rx / tx / drop trace
Use a single vnet_pcap_t in vlib_global_main, specifically to support unified tracing Update sphinx docs, doxygen tags Type: refactor Ticket: VPP-1776 Signed-off-by: Dave Barach <dave@barachs.net> Change-Id: Id15d41a596712968c0714cef1bd2cd5bc9cbdd55 (cherry picked from commit 33909777c63712ca397165cd92e7cc62208eb5c8)
This commit is contained in:

committed by
Damjan Marion

parent
2cf5b1a1ec
commit
731312df93
@ -470,25 +470,33 @@ This should be of significant value when developing new vpp graph
|
||||
nodes. If new code mispositions b->current_data, it will be completely
|
||||
obvious from looking at the dispatch trace in wireshark.
|
||||
|
||||
## pcap rx and tx tracing
|
||||
## pcap rx, tx, and drop tracing
|
||||
|
||||
vpp also supports rx and tx packet capture in pcap format, through the
|
||||
"pcap rx trace" and "pcap tx trace" debug CLI commands
|
||||
vpp also supports rx, tx, and drop packet capture in pcap format,
|
||||
through the "pcap trace" debug CLI command.
|
||||
|
||||
This command is used to start or stop a packet capture, or show
|
||||
the status of packet capture. Note that both "pcap rx trace" and
|
||||
"pcap tx trace" are implemented. The command syntax is identical,
|
||||
simply substitute rx for tx as needed.
|
||||
This command is used to start or stop a packet capture, or show the
|
||||
status of packet capture. Each of "pcap trace rx", "pcap trace tx",
|
||||
and "pcap trace drop" is implemented. Supply one or more of "rx",
|
||||
"tx", and "drop" to enable multiple simultaneous capture types.
|
||||
|
||||
These commands have the following optional parameters:
|
||||
|
||||
on|off- Used to start or stop a packet capture.
|
||||
- <b>rx</b> - trace received packets.
|
||||
|
||||
- <b>tx</b> - trace transmitted packets.
|
||||
|
||||
- <b>drop</b> - trace dropped packets.
|
||||
|
||||
- <b>max _nnnn_</b> - file size, number of packet captures. Once
|
||||
<nnnn> packets have been received, the trace buffer buffer is flushed
|
||||
to the indicated file. Defaults to 1000. Can only be updated if packet
|
||||
capture is off.
|
||||
|
||||
- <b>max-bytes-per-pkt _nnnn_</b> - maximum number of bytes to trace
|
||||
on a per-paket basis. Must be >32 and less than 9000. Default value:
|
||||
512.
|
||||
|
||||
- <b>intfc _interface_ | _any_</b> - Used to specify a given interface,
|
||||
or use '<em>any</em>' to run packet capture on all interfaces.
|
||||
'<em>any</em>' is the default if not provided. Settings from a previous
|
||||
|
@ -60,7 +60,14 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int pcap_enable;
|
||||
/* Trace RX pkts */
|
||||
u8 pcap_rx_enable;
|
||||
/* Trace TX pkts */
|
||||
u8 pcap_tx_enable;
|
||||
/* Trace drop pkts */
|
||||
u8 pcap_drop_enable;
|
||||
u8 pad1;
|
||||
u32 max_bytes_per_pkt;
|
||||
u32 pcap_sw_if_index;
|
||||
pcap_main_t pcap_main;
|
||||
u32 filter_classify_table_index;
|
||||
@ -153,7 +160,7 @@ typedef struct vlib_main_t
|
||||
u8 *pcap_buffer;
|
||||
|
||||
/* pcap rx / tx tracing */
|
||||
vnet_pcap_t pcap[VLIB_N_RX_TX];
|
||||
vnet_pcap_t pcap;
|
||||
|
||||
/* Error handling. */
|
||||
vlib_error_main_t error_main;
|
||||
|
@ -991,10 +991,11 @@ ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
}
|
||||
|
||||
/* rx pcap capture if enabled */
|
||||
if (PREDICT_FALSE (vlib_global_main.pcap[VLIB_RX].pcap_enable))
|
||||
if (PREDICT_FALSE (vlib_global_main.pcap.pcap_rx_enable))
|
||||
{
|
||||
u32 bi0;
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
vnet_pcap_t *pp = &vlib_global_main.pcap;
|
||||
|
||||
from = vlib_frame_vector_args (from_frame);
|
||||
n_left = from_frame->n_vectors;
|
||||
@ -1013,17 +1014,16 @@ ethernet_input_trace (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
(b0, vnm->classify_filter_table_indices[0],
|
||||
0 /* full classify */ );
|
||||
if (classify_filter_result)
|
||||
pcap_add_buffer (&vlib_global_main.pcap[VLIB_RX].pcap_main,
|
||||
vm, bi0, 512);
|
||||
pcap_add_buffer (&pp->pcap_main, vm, bi0,
|
||||
pp->max_bytes_per_pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vlib_global_main.pcap[VLIB_RX].pcap_sw_if_index == 0 ||
|
||||
vlib_global_main.pcap[VLIB_RX].pcap_sw_if_index
|
||||
== vnet_buffer (b0)->sw_if_index[VLIB_RX])
|
||||
if (pp->pcap_sw_if_index == 0 ||
|
||||
pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
|
||||
{
|
||||
pcap_add_buffer (&vlib_global_main.pcap[VLIB_RX].pcap_main, vm,
|
||||
bi0, 512);
|
||||
pcap_add_buffer (&pp->pcap_main, vm, bi0,
|
||||
pp->max_bytes_per_pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -843,12 +843,11 @@ typedef struct
|
||||
|
||||
vnet_hw_interface_nodes_t *deleted_hw_interface_nodes;
|
||||
|
||||
/* pcap drop tracing */
|
||||
int drop_pcap_enable;
|
||||
pcap_main_t pcap_main;
|
||||
u8 *pcap_filename;
|
||||
u32 pcap_sw_if_index;
|
||||
u32 pcap_pkts_to_capture;
|
||||
/*
|
||||
* pcap drop tracing
|
||||
* Only the drop filter hash lives here. See ../src/vlib/main.h for
|
||||
* the rest of the variables.
|
||||
*/
|
||||
uword *pcap_drop_filter_hash;
|
||||
|
||||
/* Buffer metadata format helper functions */
|
||||
@ -899,7 +898,10 @@ typedef struct
|
||||
int enable;
|
||||
int status;
|
||||
u32 packets_to_capture;
|
||||
vlib_rx_or_tx_t rxtx;
|
||||
u32 max_bytes_per_pkt;
|
||||
u8 rx_enable;
|
||||
u8 tx_enable;
|
||||
u8 drop_enable;
|
||||
u32 sw_if_index;
|
||||
int filter;
|
||||
} vnet_pcap_dispatch_trace_args_t;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -802,8 +802,10 @@ static_always_inline void vnet_interface_pcap_tx_trace
|
||||
{
|
||||
u32 n_left_from, *from;
|
||||
u32 sw_if_index;
|
||||
vnet_main_t *vnm;
|
||||
vnet_pcap_t *pp = &vlib_global_main.pcap;
|
||||
|
||||
if (PREDICT_TRUE (vlib_global_main.pcap[VLIB_TX].pcap_enable == 0))
|
||||
if (PREDICT_TRUE (pp->pcap_tx_enable == 0))
|
||||
return;
|
||||
|
||||
if (sw_if_index_from_buffer == 0)
|
||||
@ -814,7 +816,7 @@ static_always_inline void vnet_interface_pcap_tx_trace
|
||||
else
|
||||
sw_if_index = ~0;
|
||||
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
vnm = vnet_get_main ();
|
||||
n_left_from = frame->n_vectors;
|
||||
from = vlib_frame_vector_args (frame);
|
||||
|
||||
@ -833,18 +835,15 @@ static_always_inline void vnet_interface_pcap_tx_trace
|
||||
(b0, vnm->classify_filter_table_indices[0],
|
||||
0 /* full classify */ );
|
||||
if (classify_filter_result)
|
||||
pcap_add_buffer (&vlib_global_main.pcap[VLIB_TX].pcap_main, vm,
|
||||
bi0, 512);
|
||||
pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sw_if_index_from_buffer)
|
||||
sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
|
||||
|
||||
if (vlib_global_main.pcap[VLIB_TX].pcap_sw_if_index == 0 ||
|
||||
vlib_global_main.pcap[VLIB_TX].pcap_sw_if_index == sw_if_index)
|
||||
pcap_add_buffer (&vlib_global_main.pcap[VLIB_TX].pcap_main, vm, bi0,
|
||||
512);
|
||||
if (pp->pcap_sw_if_index == 0 || pp->pcap_sw_if_index == sw_if_index)
|
||||
pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1169,7 +1168,8 @@ interface_drop_punt (vlib_main_t * vm,
|
||||
|
||||
static inline void
|
||||
pcap_drop_trace (vlib_main_t * vm,
|
||||
vnet_interface_main_t * im, vlib_frame_t * f)
|
||||
vnet_interface_main_t * im,
|
||||
vnet_pcap_t * pp, vlib_frame_t * f)
|
||||
{
|
||||
u32 *from;
|
||||
u32 n_left = f->n_vectors;
|
||||
@ -1199,8 +1199,8 @@ pcap_drop_trace (vlib_main_t * vm,
|
||||
continue;
|
||||
|
||||
/* Trace all drops, or drops received on a specific interface */
|
||||
if (im->pcap_sw_if_index == 0 ||
|
||||
im->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
|
||||
if (pp->pcap_sw_if_index == 0 ||
|
||||
pp->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_RX])
|
||||
{
|
||||
save_current_data = b0->current_data;
|
||||
save_current_length = b0->current_length;
|
||||
@ -1222,7 +1222,7 @@ pcap_drop_trace (vlib_main_t * vm,
|
||||
else if (b0->current_data > 0)
|
||||
vlib_buffer_advance (b0, (word) - b0->current_data);
|
||||
|
||||
pcap_add_buffer (&im->pcap_main, vm, bi0, 512);
|
||||
pcap_add_buffer (&pp->pcap_main, vm, bi0, pp->max_bytes_per_pkt);
|
||||
|
||||
b0->current_data = save_current_data;
|
||||
b0->current_length = save_current_length;
|
||||
@ -1251,9 +1251,10 @@ VLIB_NODE_FN (interface_drop) (vlib_main_t * vm,
|
||||
vlib_frame_t * frame)
|
||||
{
|
||||
vnet_interface_main_t *im = &vnet_get_main ()->interface_main;
|
||||
vnet_pcap_t *pp = &vlib_global_main.pcap;
|
||||
|
||||
if (PREDICT_FALSE (im->drop_pcap_enable))
|
||||
pcap_drop_trace (vm, im, frame);
|
||||
if (PREDICT_FALSE (pp->pcap_drop_enable))
|
||||
pcap_drop_trace (vm, im, pp, frame);
|
||||
|
||||
return interface_drop_punt (vm, node, frame, VNET_ERROR_DISPOSITION_DROP);
|
||||
}
|
||||
@ -1416,142 +1417,6 @@ vnet_set_interface_output_node (vnet_main_t * vnm,
|
||||
}
|
||||
#endif /* CLIB_MARCH_VARIANT */
|
||||
|
||||
static clib_error_t *
|
||||
pcap_drop_trace_command_fn (vlib_main_t * vm,
|
||||
unformat_input_t * input,
|
||||
vlib_cli_command_t * cmd)
|
||||
{
|
||||
vnet_main_t *vnm = vnet_get_main ();
|
||||
vnet_interface_main_t *im = &vnm->interface_main;
|
||||
u8 *filename;
|
||||
u32 max;
|
||||
int matched = 0;
|
||||
clib_error_t *error = 0;
|
||||
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "on"))
|
||||
{
|
||||
if (im->drop_pcap_enable == 0)
|
||||
{
|
||||
if (im->pcap_filename == 0)
|
||||
im->pcap_filename = format (0, "/tmp/drop.pcap%c", 0);
|
||||
|
||||
clib_memset (&im->pcap_main, 0, sizeof (im->pcap_main));
|
||||
im->pcap_main.file_name = (char *) im->pcap_filename;
|
||||
im->pcap_main.n_packets_to_capture = PCAP_DEF_PKT_TO_CAPTURE;
|
||||
if (im->pcap_pkts_to_capture)
|
||||
im->pcap_main.n_packets_to_capture = im->pcap_pkts_to_capture;
|
||||
|
||||
im->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
|
||||
im->drop_pcap_enable = 1;
|
||||
matched = 1;
|
||||
vlib_cli_output (vm, "pcap drop capture on...");
|
||||
}
|
||||
else
|
||||
{
|
||||
vlib_cli_output (vm, "pcap drop capture already on...");
|
||||
}
|
||||
matched = 1;
|
||||
}
|
||||
else if (unformat (input, "off"))
|
||||
{
|
||||
matched = 1;
|
||||
|
||||
if (im->drop_pcap_enable)
|
||||
{
|
||||
vlib_cli_output (vm, "captured %d pkts...",
|
||||
im->pcap_main.n_packets_captured);
|
||||
if (im->pcap_main.n_packets_captured)
|
||||
{
|
||||
im->pcap_main.n_packets_to_capture =
|
||||
im->pcap_main.n_packets_captured;
|
||||
error = pcap_write (&im->pcap_main);
|
||||
if (im->pcap_main.flags & PCAP_MAIN_INIT_DONE)
|
||||
pcap_close (&im->pcap_main);
|
||||
if (error)
|
||||
clib_error_report (error);
|
||||
else
|
||||
vlib_cli_output (vm, "saved to %s...", im->pcap_filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vlib_cli_output (vm, "pcap drop capture already off...");
|
||||
}
|
||||
|
||||
im->drop_pcap_enable = 0;
|
||||
}
|
||||
else if (unformat (input, "max %d", &max))
|
||||
{
|
||||
im->pcap_pkts_to_capture = max;
|
||||
matched = 1;
|
||||
}
|
||||
|
||||
else if (unformat (input, "intfc %U",
|
||||
unformat_vnet_sw_interface, vnm,
|
||||
&im->pcap_sw_if_index))
|
||||
matched = 1;
|
||||
else if (unformat (input, "intfc any"))
|
||||
{
|
||||
im->pcap_sw_if_index = 0;
|
||||
matched = 1;
|
||||
}
|
||||
else if (unformat (input, "file %s", &filename))
|
||||
{
|
||||
u8 *chroot_filename;
|
||||
/* Brain-police user path input */
|
||||
if (strstr ((char *) filename, "..")
|
||||
|| index ((char *) filename, '/'))
|
||||
{
|
||||
vlib_cli_output (vm, "illegal characters in filename '%s'",
|
||||
filename);
|
||||
continue;
|
||||
}
|
||||
|
||||
chroot_filename = format (0, "/tmp/%s%c", filename, 0);
|
||||
vec_free (filename);
|
||||
|
||||
if (im->pcap_filename)
|
||||
vec_free (im->pcap_filename);
|
||||
im->pcap_filename = chroot_filename;
|
||||
im->pcap_main.file_name = (char *) im->pcap_filename;
|
||||
matched = 1;
|
||||
}
|
||||
else if (unformat (input, "status"))
|
||||
{
|
||||
if (im->drop_pcap_enable == 0)
|
||||
{
|
||||
vlib_cli_output (vm, "pcap drop capture is off...");
|
||||
continue;
|
||||
}
|
||||
|
||||
vlib_cli_output (vm, "pcap drop capture: %d of %d pkts...",
|
||||
im->pcap_main.n_packets_captured,
|
||||
im->pcap_main.n_packets_to_capture);
|
||||
matched = 1;
|
||||
}
|
||||
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (matched == 0)
|
||||
return clib_error_return (0, "unknown input `%U'",
|
||||
format_unformat_error, input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
VLIB_CLI_COMMAND (pcap_trace_command, static) = {
|
||||
.path = "pcap drop trace",
|
||||
.short_help =
|
||||
"pcap drop trace on off max <nn> intfc <intfc> file <name> status",
|
||||
.function = pcap_drop_trace_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
|
Reference in New Issue
Block a user