From 586462fabcc913a5a4fa9115d4b5caf33dfdb347 Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Wed, 5 Aug 2020 16:12:35 -0400 Subject: interface: add pcap trace data preallocation Type: improvement Signed-off-by: Dave Barach Change-Id: I2e53fa85a0b4082666f57a3a58a09c04ae2001b5 --- src/vnet/interface.h | 2 ++ src/vnet/interface_cli.c | 50 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/vnet/interface.h b/src/vnet/interface.h index 5f4fd065756..f9081442338 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -924,6 +924,8 @@ typedef struct u8 rx_enable; u8 tx_enable; u8 drop_enable; + u8 preallocate_data; + u8 free_data; 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 c62a9858e8c..531710fd5ad 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -1973,15 +1973,25 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) if (a->rx_enable + a->tx_enable + a->drop_enable) { + void *save_pcap_data; + /* 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); + vec_reset_length (pm->pcap_data); + + /* Throw away the data buffer? */ + if (a->free_data) + vec_free (pm->pcap_data); + + save_pcap_data = pm->pcap_data; + memset (pm, 0, sizeof (*pm)); + pm->pcap_data = save_pcap_data; + vec_validate_aligned (vnet_trace_dummy, 2048, CLIB_CACHE_LINE_BYTES); if (pm->lock == 0) clib_spinlock_init (&(pm->lock)); @@ -2003,6 +2013,14 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) pm->file_name = (char *) a->filename; pm->n_packets_captured = 0; pm->packet_type = PCAP_PACKET_TYPE_ethernet; + /* Preallocate the data vector? */ + if (a->preallocate_data) + { + vec_validate + (pm->pcap_data, a->packets_to_capture + * ((sizeof (pcap_packet_header_t) + a->max_bytes_per_pkt))); + vec_reset_length (pm->pcap_data); + } pm->n_packets_to_capture = a->packets_to_capture; pp->pcap_sw_if_index = a->sw_if_index; if (a->filter) @@ -2035,6 +2053,9 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) clib_error_report (error); return VNET_API_ERROR_SYSCALL_ERROR_1; } + vec_free (pm->file_name); + if (a->free_data) + vec_free (pm->pcap_data); return 0; } else @@ -2057,9 +2078,11 @@ pcap_trace_command_fn (vlib_main_t * vm, int rv; int rx_enable = 0; int tx_enable = 0; + int preallocate_data = 0; int drop_enable = 0; int status = 0; int filter = 0; + int free_data = 0; u32 sw_if_index = 0; /* default: any interface */ /* Get a line of input. */ @@ -2091,7 +2114,16 @@ pcap_trace_command_fn (vlib_main_t * vm, else if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface, vnm, &sw_if_index)) ; - else if (unformat (line_input, "intfc any")) + else if (unformat (line_input, "interface %U", + unformat_vnet_sw_interface, vnm, &sw_if_index)) + ; + else if (unformat (line_input, "preallocate-data %=", + &preallocate_data, 1)) + ; + else if (unformat (line_input, "free-data %=", &free_data, 1)) + ; + else if (unformat (line_input, "intfc any") + || unformat (line_input, "interface any")) sw_if_index = 0; else if (unformat (line_input, "filter")) filter = 1; @@ -2108,6 +2140,8 @@ pcap_trace_command_fn (vlib_main_t * vm, a->filename = filename; a->rx_enable = rx_enable; a->tx_enable = tx_enable; + a->preallocate_data = preallocate_data; + a->free_data = free_data; a->drop_enable = drop_enable; a->status = status; a->packets_to_capture = max; @@ -2177,6 +2211,12 @@ pcap_trace_command_fn (vlib_main_t * vm, * - max-bytes-per-pkt - Maximum number of bytes to capture * for each packet. Must be >= 32, <= 9000. * + * - preallocate-data - Preallocate the data buffer, to avoid + * vector expansion delays during pcap capture + * + * - free-data - Free the data buffer. Ordinarily it's a feature + * to retain the data buffer so this option is seldom used. + * * - 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 @@ -2226,7 +2266,9 @@ pcap_trace_command_fn (vlib_main_t * vm, VLIB_CLI_COMMAND (pcap_tx_trace_command, static) = { .path = "pcap trace", .short_help = - "pcap trace rx tx drop off [max ] [intfc |any] [file ] [status] [max-bytes-per-pkt ][filter]", + "pcap trace [rx] [tx] [drop] [off] [max ] [intfc |any]\n" + " [file ] [status] [max-bytes-per-pkt ][filter]\n" + " [preallocate-data][free-data]", .function = pcap_trace_command_fn, }; /* *INDENT-ON* */ -- cgit 1.2.3-korg