interface: add pcap trace data preallocation 28/28128/3
authorDave Barach <[email protected]>
Wed, 5 Aug 2020 20:12:35 +0000 (16:12 -0400)
committerDave Barach <[email protected]>
Thu, 6 Aug 2020 12:03:05 +0000 (12:03 +0000)
Type: fix

Signed-off-by: Dave Barach <[email protected]>
Change-Id: I2e53fa85a0b4082666f57a3a58a09c04ae2001b5
(cherry picked from commit 586462fabcc913a5a4fa9115d4b5caf33dfdb347)

src/vnet/interface.h
src/vnet/interface_cli.c

index 7d73c5f..618eefe 100644 (file)
@@ -906,6 +906,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;
index c622a60..46c5d5e 100644 (file)
@@ -1782,15 +1782,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));
@@ -1812,6 +1822,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)
@@ -1844,6 +1862,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
@@ -1866,10 +1887,12 @@ 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;
-  u32 sw_if_index = ~0;
+  int free_data = 0;
+  u32 sw_if_index = 0;         /* default: any interface */
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -1900,7 +1923,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;
@@ -1917,6 +1949,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;
@@ -1986,6 +2020,12 @@ pcap_trace_command_fn (vlib_main_t * vm,
  * - <b>max-bytes-per-pkt <nnnn></b> - Maximum number of bytes to capture
  *   for each packet. Must be >= 32, <= 9000.
  *
+ * - <b>preallocate-data</b> - Preallocate the data buffer, to avoid
+ *   vector expansion delays during pcap capture
+ *
+ * - <b>free-data</b> - Free the data buffer. Ordinarily it's a feature
+ *   to retain the data buffer so this option is seldom used.
+ *
  * - <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
@@ -2035,7 +2075,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 <nn>] [intfc <interface>|any] [file <name>] [status] [max-bytes-per-pkt <nnnn>][filter]",
+    "pcap trace [rx] [tx] [drop] [off] [max <nn>] [intfc <interface>|any]\n"
+    "           [file <name>] [status] [max-bytes-per-pkt <nnnn>][filter]\n"
+    "           [preallocate-data][free-data]",
     .function = pcap_trace_command_fn,
 };
 /* *INDENT-ON* */