From 33909777c63712ca397165cd92e7cc62208eb5c8 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Mon, 23 Sep 2019 10:27:27 -0400 Subject: 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 Change-Id: Id15d41a596712968c0714cef1bd2cd5bc9cbdd55 --- docs/gettingstarted/developers/vnet.md | 24 +++-- src/vlib/main.h | 11 +- src/vnet/ethernet/node.c | 16 +-- src/vnet/interface.h | 16 +-- src/vnet/interface_cli.c | 185 +++++++++++++++++++++------------ src/vnet/interface_output.c | 165 +++-------------------------- 6 files changed, 177 insertions(+), 240 deletions(-) diff --git a/docs/gettingstarted/developers/vnet.md b/docs/gettingstarted/developers/vnet.md index b8f878c2cd7..826af0a90a9 100644 --- a/docs/gettingstarted/developers/vnet.md +++ b/docs/gettingstarted/developers/vnet.md @@ -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. +- rx - trace received packets. + +- tx - trace transmitted packets. + +- drop - trace dropped packets. - max _nnnn_ - file size, number of packet captures. Once 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. +- max-bytes-per-pkt _nnnn_ - maximum number of bytes to trace + on a per-paket basis. Must be >32 and less than 9000. Default value: + 512. + - intfc _interface_ | _any_ - Used to specify a given interface, or use 'any' to run packet capture on all interfaces. 'any' is the default if not provided. Settings from a previous diff --git a/src/vlib/main.h b/src/vlib/main.h index 88ce98bb405..2b50b4e4712 100644 --- a/src/vlib/main.h +++ b/src/vlib/main.h @@ -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; diff --git a/src/vnet/ethernet/node.c b/src/vnet/ethernet/node.c index fb706551719..ee14e40d881 100755 --- a/src/vnet/ethernet/node.c +++ b/src/vnet/ethernet/node.c @@ -998,10 +998,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; @@ -1020,17 +1021,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); } } } diff --git a/src/vnet/interface.h b/src/vnet/interface.h index 0c273c6c7d2..00ed1f03151 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -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; diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c index 3164f7a31f2..e6b251da17f 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -1695,52 +1695,94 @@ VLIB_CLI_COMMAND (cmd_set_if_rx_placement,static) = { }; /* *INDENT-ON* */ +static u8 * +format_vnet_pcap (u8 * s, va_list * args) +{ + vnet_pcap_t *pp = va_arg (*args, vnet_pcap_t *); + int type = va_arg (*args, int); + int printed = 0; + + if (type == 0) + { + if (pp->pcap_rx_enable) + { + s = format (s, "rx"); + printed = 1; + } + if (pp->pcap_tx_enable) + { + if (printed) + s = format (s, " and "); + s = format (s, "tx"); + printed = 1; + } + if (pp->pcap_drop_enable) + { + if (printed) + s = format (s, " and "); + s = format (s, "drop"); + printed = 1; + } + return s; + } + s = format (s, "unknown type %d!", type); + return s; +} + + int vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) { vlib_main_t *vm = vlib_get_main (); vnet_main_t *vnm = vnet_get_main (); - vlib_rx_or_tx_t rxtx = a->rxtx; - vnet_pcap_t *pp = &vm->pcap[rxtx]; + vnet_pcap_t *pp = &vm->pcap; pcap_main_t *pm = &pp->pcap_main; if (a->status) { - if (pp->pcap_enable) + if (pp->pcap_rx_enable || pp->pcap_tx_enable || pp->pcap_drop_enable) { vlib_cli_output - (vm, "pcap %s dispatch capture enabled: %d of %d pkts...", - (rxtx == VLIB_RX) ? "rx" : "tx", + (vm, "pcap %U dispatch capture enabled: %d of %d pkts...", + format_vnet_pcap, pp, 0 /* print type */ , pm->n_packets_captured, pm->n_packets_to_capture); vlib_cli_output (vm, "capture to file %s", pm->file_name); } else - vlib_cli_output (vm, "pcap %s dispatch capture disabled", - (rxtx == VLIB_RX) ? "rx" : "tx"); + vlib_cli_output (vm, "pcap dispatch capture disabled"); + return 0; } /* Consistency checks */ /* Enable w/ capture already enabled not allowed */ - if (pp->pcap_enable && a->enable) + if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable) + && (a->rx_enable + a->tx_enable + a->drop_enable)) return VNET_API_ERROR_INVALID_VALUE; /* Disable capture with capture already disabled, not interesting */ - if (pp->pcap_enable == 0 && a->enable == 0) + if (((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable) == 0) + && ((a->rx_enable + a->tx_enable + a->drop_enable == 0))) return VNET_API_ERROR_VALUE_EXIST; /* Change number of packets to capture while capturing */ - if (pp->pcap_enable && a->enable + if ((pp->pcap_rx_enable + pp->pcap_tx_enable + pp->pcap_drop_enable) + && (a->rx_enable + a->tx_enable + a->drop_enable) && (pm->n_packets_to_capture != a->packets_to_capture)) return VNET_API_ERROR_INVALID_VALUE_2; - if (a->enable && a->filter + /* Classify filter specified, but no classify filter configured */ + if ((a->rx_enable + a->tx_enable + a->drop_enable) && a->filter && (vec_len (vnm->classify_filter_table_indices) == 0)) return VNET_API_ERROR_NO_SUCH_LABEL; - if (a->enable) + if (a->rx_enable + a->tx_enable + a->drop_enable) { + /* Sanity check max bytes per pkt */ + if (a->max_bytes_per_pkt < 32 || a->max_bytes_per_pkt > 9000) + return VNET_API_ERROR_INVALID_MEMORY_SIZE; + /* Clean up from previous run, if any */ vec_free (pm->file_name); vec_free (pm->pcap_data); @@ -1751,8 +1793,18 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) clib_spinlock_init (&(pm->lock)); if (a->filename == 0) - a->filename = format (0, "/tmp/%s.pcap%c", - (rxtx == VLIB_RX) ? "rx" : "tx", 0); + { + u8 *stem = 0; + + if (a->rx_enable) + stem = format (stem, "rx"); + if (a->tx_enable) + stem = format (stem, "tx"); + if (a->drop_enable) + stem = format (stem, "drop"); + a->filename = format (0, "/tmp/%s.pcap%c", stem, 0); + vec_free (stem); + } pm->file_name = (char *) a->filename; pm->n_packets_captured = 0; @@ -1764,11 +1816,16 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) vnm->classify_filter_table_indices[0]; else pp->filter_classify_table_index = ~0; - pp->pcap_enable = 1; + pp->pcap_rx_enable = a->rx_enable; + pp->pcap_tx_enable = a->tx_enable; + pp->pcap_drop_enable = a->drop_enable; + pp->max_bytes_per_pkt = a->max_bytes_per_pkt; } else { - pp->pcap_enable = 0; + pp->pcap_rx_enable = 0; + pp->pcap_tx_enable = 0; + pp->pcap_drop_enable = 0; if (pm->n_packets_captured) { clib_error_t *error; @@ -1794,17 +1851,19 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) } static clib_error_t * -pcap_trace_command_internal (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd, vlib_rx_or_tx_t rxtx) +pcap_trace_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) { unformat_input_t _line_input, *line_input = &_line_input; vnet_pcap_dispatch_trace_args_t _a, *a = &_a; vnet_main_t *vnm = vnet_get_main (); u8 *filename = 0; u32 max = 1000; + u32 max_bytes_per_pkt = 512; int rv; - int enable = 0; + int rx_enable = 0; + int tx_enable = 0; + int drop_enable = 0; int status = 0; int filter = 0; u32 sw_if_index = 0; @@ -1815,13 +1874,16 @@ pcap_trace_command_internal (vlib_main_t * vm, while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { - if (unformat (line_input, "on %=", &enable, 1)) - ; - else if (unformat (line_input, "enable %=", &enable, 1)) - ; - else if (unformat (line_input, "off %=", &enable, 0)) - ; - else if (unformat (line_input, "disable %=", &enable, 0)) + if (unformat (line_input, "rx")) + rx_enable = 1; + else if (unformat (line_input, "tx")) + tx_enable = 1; + else if (unformat (line_input, "drop")) + drop_enable = 1; + else if (unformat (line_input, "off")) + rx_enable = tx_enable = drop_enable = 0; + else if (unformat (line_input, "max-bytes-per-pkt %u", + &max_bytes_per_pkt)) ; else if (unformat (line_input, "max %d", &max)) ; @@ -1850,12 +1912,14 @@ pcap_trace_command_internal (vlib_main_t * vm, /* no need for memset (a, 0, sizeof (*a)), set all fields here. */ a->filename = filename; - a->enable = enable; + a->rx_enable = rx_enable; + a->tx_enable = tx_enable; + a->drop_enable = drop_enable; a->status = status; a->packets_to_capture = max; - a->rxtx = rxtx; a->sw_if_index = sw_if_index; a->filter = filter; + a->max_bytes_per_pkt = max_bytes_per_pkt; rv = vnet_pcap_dispatch_trace_configure (a); @@ -1880,6 +1944,10 @@ pcap_trace_command_internal (vlib_main_t * vm, case VNET_API_ERROR_NO_SUCH_ENTRY: return clib_error_return (0, "No packets captured..."); + case VNET_API_ERROR_INVALID_MEMORY_SIZE: + return clib_error_return (0, + "Max bytes per pkt must be > 32, < 9000..."); + case VNET_API_ERROR_NO_SUCH_LABEL: return clib_error_return (0, "No classify filter configured, see 'classify filter...'"); @@ -1891,30 +1959,20 @@ pcap_trace_command_internal (vlib_main_t * vm, return 0; } -static clib_error_t * -pcap_rx_trace_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - return pcap_trace_command_internal (vm, input, cmd, VLIB_RX); -} - -static clib_error_t * -pcap_tx_trace_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - return pcap_trace_command_internal (vm, input, cmd, VLIB_TX); -} - - /*? * 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. + * the status of packet capture. * * This command has the following optional parameters: * - * - on|off - Used to start or stop a packet capture. + * + * - rx - Capture received packets + * + * - tx - Capture transmitted packets + * + * - drop - Capture dropped packets + * + * - off - Stop capturing packets, write results to the specified file * * - max - Depth of local buffer. Once 'nn' number * of packets have been received, buffer is flushed to file. Once another @@ -1922,7 +1980,10 @@ pcap_tx_trace_command_fn (vlib_main_t * vm, * to file, overwriting previous write. If not entered, value defaults * to 100. Can only be updated if packet capture is off. * - * - intfc |any - Used to specify a given interface, + * - max-bytes-per-pkt - Maximum number of bytes to capture + * for each packet. Must be >= 32, <= 9000. + * + * - intfc |any - Used to specify a given interface, * or use 'any' to run packet capture on all interfaces. * 'any' is the default if not provided. Settings from a previous * packet capture are preserved, so 'any' can be used to reset @@ -1931,8 +1992,9 @@ pcap_tx_trace_command_fn (vlib_main_t * vm, * - file - Used to specify the output filename. The file will * be placed in the '/tmp' directory, so only the filename is * supported. Directory should not be entered. If file already exists, file - * will be overwritten. If no filename is provided, '/tmp/vpe.pcap' - * will be used. Can only be updated if packet capture is off. + * will be overwritten. If no filename is provided, the file will be + * named "/tmp/rx.pcap", "/tmp/tx.pcap", "/tmp/rxandtx.pcap", etc. + * Can only be updated if packet capture is off. * * - status - Displays the current status and configured attributes * associated with a packet capture. If packet capture is in progress, @@ -1942,21 +2004,20 @@ pcap_tx_trace_command_fn (vlib_main_t * vm, * * @cliexpar * Example of how to display the status of a tx packet capture when off: - * @cliexstart{pcap tx trace status} + * @cliexstart{pcap trace status} * max is 100, for any interface to file /tmp/vpe.pcap * pcap tx capture is off... * @cliexend * Example of how to start a tx packet capture: - * @cliexstart{pcap tx trace on max 35 intfc GigabitEthernet0/8/0 file vppTest.pcap} - * pcap tx capture on... + * @cliexstart{pcap trace tx max 35 intfc GigabitEthernet0/8/0 file vppTest.pcap} * @cliexend * Example of how to display the status of a tx packet capture in progress: - * @cliexstart{pcap tx trace status} + * @cliexstart{pcap trace status} * max is 35, for interface GigabitEthernet0/8/0 to file /tmp/vppTest.pcap * pcap tx capture is on: 20 of 35 pkts... * @cliexend * Example of how to stop a tx packet capture: - * @cliexstart{vppctl pcap tx trace off} + * @cliexstart{pcap trace off} * captured 21 pkts... * saved to /tmp/vppTest.pcap... * @cliexend @@ -1964,16 +2025,10 @@ pcap_tx_trace_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (pcap_tx_trace_command, static) = { - .path = "pcap tx trace", - .short_help = - "pcap tx trace [on|off] [max ] [intfc |any] [file ] [status]", - .function = pcap_tx_trace_command_fn, -}; -VLIB_CLI_COMMAND (pcap_rx_trace_command, static) = { - .path = "pcap rx trace", + .path = "pcap trace", .short_help = - "pcap rx trace [on|off] [max ] [intfc |any] [file ] [status]", - .function = pcap_rx_trace_command_fn, + "pcap trace rx tx drop off [max ] [intfc |any] [file ] [status] [max-bytes-per-pkt ]", + .function = pcap_trace_command_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index 721236a777f..8eb2e67b1bd 100644 --- a/src/vnet/interface_output.c +++ b/src/vnet/interface_output.c @@ -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 intfc file status", - .function = pcap_drop_trace_command_fn, -}; -/* *INDENT-ON* */ - /* * fd.io coding-style-patch-verification: ON * -- cgit 1.2.3-korg