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:
Dave Barach
2019-09-23 10:27:27 -04:00
committed by Damjan Marion
parent 2cf5b1a1ec
commit 731312df93
6 changed files with 177 additions and 239 deletions

View File

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

View File

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

View File

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

View File

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

View File

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