diff options
author | Dave Barach <dave@barachs.net> | 2019-09-23 10:27:27 -0400 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-09-25 22:19:59 +0000 |
commit | 731312df93534d9695b2d22fc9071a860868f87d (patch) | |
tree | 76e30dfd15a341170cb886dabb0f8d5d58f31e37 | |
parent | 2cf5b1a1ec8d959f1355974822deba35d6bfb04b (diff) |
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)
-rw-r--r-- | docs/gettingstarted/developers/vnet.md | 24 | ||||
-rw-r--r-- | src/vlib/main.h | 11 | ||||
-rwxr-xr-x | src/vnet/ethernet/node.c | 16 | ||||
-rw-r--r-- | src/vnet/interface.h | 16 | ||||
-rw-r--r-- | src/vnet/interface_cli.c | 184 | ||||
-rw-r--r-- | src/vnet/interface_output.c | 165 |
6 files changed, 177 insertions, 239 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. +- <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 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 cfbad8b8cc0..272475938a9 100755 --- a/src/vnet/ethernet/node.c +++ b/src/vnet/ethernet/node.c @@ -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); } } } 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 4ad0cb025bd..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,29 +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: * - * - <b>on|off</b> - Used to start or stop a packet capture. + * + * - <b>rx</b> - Capture received packets + * + * - <b>tx</b> - Capture transmitted packets + * + * - <b>drop</b> - Capture dropped packets + * + * - <b>off</b> - Stop capturing packets, write results to the specified file * * - <b>max <nn></b> - Depth of local buffer. Once '<em>nn</em>' number * of packets have been received, buffer is flushed to file. Once another @@ -1921,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. * - * - <b>intfc <interface>|any</b> - Used to specify a given interface, + * - <b>max-bytes-per-pkt <nnnn></b> - Maximum number of bytes to capture + * for each packet. Must be >= 32, <= 9000. + * + * - <b>intfc <interface-name>|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 * packet capture are preserved, so '<em>any</em>' can be used to reset @@ -1930,8 +1992,9 @@ pcap_tx_trace_command_fn (vlib_main_t * vm, * - <b>file <name></b> - Used to specify the output filename. The file will * be placed in the '<em>/tmp</em>' 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, '<em>/tmp/vpe.pcap</em>' - * 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. * * - <b>status</b> - Displays the current status and configured attributes * associated with a packet capture. If packet capture is in progress, @@ -1941,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 @@ -1963,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 <nn>] [intfc <interface>|any] [file <name>] [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 <nn>] [intfc <interface>|any] [file <name>] [status]", - .function = pcap_rx_trace_command_fn, + "pcap trace rx tx drop off [max <nn>] [intfc <interface>|any] [file <name>] [status] [max-bytes-per-pkt <nnnn>]", + .function = pcap_trace_command_fn, }; /* *INDENT-ON* */ diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index 5d3d53e5ad8..6a11f16918c 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 <nn> intfc <intfc> file <name> status", - .function = pcap_drop_trace_command_fn, -}; -/* *INDENT-ON* */ - /* * fd.io coding-style-patch-verification: ON * |