aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Barach <dbarach@cisco.com>2018-05-25 17:36:05 -0400
committerDave Barach <dbarach@cisco.com>2018-05-25 17:36:44 -0400
commitc6f186b23d00685b3e9f132ba79a5cb44f0a44c0 (patch)
treecddcc7b7831e61f0f5d7b008a7ca1ae80e14f280
parentc65770deebf63d34cc09c6aa3af7c86b3affb4b8 (diff)
Add interface rx pcap tracing
Should cost at most 1 clock per frame when not enabled. Add "pcap rx trace..." debug CLI, refactored "pcap tx trace" debug CLI to avoid duplicating code. Change-Id: I19ac75d1cf94a6a24c98facbf0753381d37963ea Signed-off-by: Dave Barach <dbarach@cisco.com>
-rw-r--r--src/plugins/dpdk/device/cli.c152
-rw-r--r--src/plugins/dpdk/device/device.c9
-rw-r--r--src/plugins/dpdk/device/dpdk.h15
-rw-r--r--src/plugins/dpdk/device/node.c44
-rw-r--r--src/vnet/unix/pcap.h28
5 files changed, 167 insertions, 81 deletions
diff --git a/src/plugins/dpdk/device/cli.c b/src/plugins/dpdk/device/cli.c
index 08bf0c94b53..151a6f4e9c8 100644
--- a/src/plugins/dpdk/device/cli.c
+++ b/src/plugins/dpdk/device/cli.c
@@ -88,9 +88,10 @@ done:
return error;
}
-static clib_error_t *
-pcap_trace_command_fn (vlib_main_t * vm,
- unformat_input_t * input, vlib_cli_command_t * cmd)
+static inline clib_error_t *
+pcap_trace_command_internal (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd, int rx_tx)
{
#define PCAP_DEF_PKT_TO_CAPTURE (100)
@@ -111,7 +112,7 @@ pcap_trace_command_fn (vlib_main_t * vm,
{
if (unformat (line_input, "on"))
{
- if (dm->tx_pcap_enable == 0)
+ if (dm->pcap[rx_tx].pcap_enable == 0)
{
enabled = 1;
}
@@ -124,22 +125,24 @@ pcap_trace_command_fn (vlib_main_t * vm,
}
else if (unformat (line_input, "off"))
{
- if (dm->tx_pcap_enable)
+ if (dm->pcap[rx_tx].pcap_enable)
{
- vlib_cli_output (vm, "captured %d pkts...",
- dm->pcap_main.n_packets_captured + 1);
- if (dm->pcap_main.n_packets_captured)
+ vlib_cli_output
+ (vm, "captured %d pkts...",
+ dm->pcap[rx_tx].pcap_main.n_packets_captured);
+ if (dm->pcap[rx_tx].pcap_main.n_packets_captured)
{
- dm->pcap_main.n_packets_to_capture =
- dm->pcap_main.n_packets_captured;
- error = pcap_write (&dm->pcap_main);
+ dm->pcap[rx_tx].pcap_main.n_packets_to_capture =
+ dm->pcap[rx_tx].pcap_main.n_packets_captured;
+ error = pcap_write (&dm->pcap[rx_tx].pcap_main);
if (error)
clib_error_report (error);
else
- vlib_cli_output (vm, "saved to %s...", dm->pcap_filename);
+ vlib_cli_output (vm, "saved to %s...",
+ dm->pcap[rx_tx].pcap_filename);
}
- dm->tx_pcap_enable = 0;
+ dm->pcap[rx_tx].pcap_enable = 0;
}
else
{
@@ -150,29 +153,31 @@ pcap_trace_command_fn (vlib_main_t * vm,
}
else if (unformat (line_input, "max %d", &max))
{
- if (dm->tx_pcap_enable)
+ if (dm->pcap[rx_tx].pcap_enable)
{
- vlib_cli_output (vm,
- "can't change max value while pcap tx capture active...");
+ vlib_cli_output
+ (vm,
+ "can't change max value while pcap tx capture active...");
errorFlag = 1;
break;
}
+ dm->pcap[rx_tx].pcap_main.n_packets_to_capture = max;
}
else if (unformat (line_input, "intfc %U",
unformat_vnet_sw_interface, dm->vnet_main,
- &dm->pcap_sw_if_index))
+ &dm->pcap[rx_tx].pcap_sw_if_index))
;
else if (unformat (line_input, "intfc any"))
{
- dm->pcap_sw_if_index = 0;
+ dm->pcap[rx_tx].pcap_sw_if_index = 0;
}
else if (unformat (line_input, "file %s", &filename))
{
- if (dm->tx_pcap_enable)
+ if (dm->pcap[rx_tx].pcap_enable)
{
- vlib_cli_output (vm,
- "can't change file while pcap tx capture active...");
+ vlib_cli_output
+ (vm, "can't change file while pcap tx capture active...");
errorFlag = 1;
break;
}
@@ -183,8 +188,7 @@ pcap_trace_command_fn (vlib_main_t * vm,
{
vlib_cli_output (vm, "illegal characters in filename '%s'",
filename);
- vlib_cli_output (vm,
- "Hint: Only filename, do not enter directory structure.");
+ vlib_cli_output (vm, "Hint: .. and / are not allowed.");
vec_free (filename);
errorFlag = 1;
break;
@@ -195,38 +199,41 @@ pcap_trace_command_fn (vlib_main_t * vm,
}
else if (unformat (line_input, "status"))
{
- if (dm->pcap_sw_if_index == 0)
+ if (dm->pcap[rx_tx].pcap_sw_if_index == 0)
{
- vlib_cli_output (vm, "max is %d for any interface to file %s",
- dm->
- pcap_pkts_to_capture ? dm->pcap_pkts_to_capture
- : PCAP_DEF_PKT_TO_CAPTURE,
- dm->
- pcap_filename ? dm->pcap_filename : (u8 *)
- "/tmp/vpe.pcap");
+ vlib_cli_output
+ (vm, "max is %d for any interface to file %s",
+ dm->pcap_pkts_to_capture ?
+ dm->pcap[rx_tx].pcap_pkts_to_capture
+ : PCAP_DEF_PKT_TO_CAPTURE,
+ dm->pcap_filename ?
+ dm->pcap[rx_tx].pcap_filename : (u8 *) "/tmp/vpe.pcap");
}
else
{
vlib_cli_output (vm, "max is %d for interface %U to file %s",
- dm->
- pcap_pkts_to_capture ? dm->pcap_pkts_to_capture
+ dm->pcap[rx_tx].pcap_pkts_to_capture
+ ? dm->pcap_pkts_to_capture
: PCAP_DEF_PKT_TO_CAPTURE,
format_vnet_sw_if_index_name, dm->vnet_main,
dm->pcap_sw_if_index,
- dm->
- pcap_filename ? dm->pcap_filename : (u8 *)
+ dm->pcap[rx_tx].pcap_filename
+ ? dm->pcap[rx_tx].pcap_filename : (u8 *)
"/tmp/vpe.pcap");
}
- if (dm->tx_pcap_enable == 0)
+ if (dm->pcap[rx_tx].pcap_enable == 0)
{
- vlib_cli_output (vm, "pcap tx capture is off...");
+ vlib_cli_output (vm, "pcap %s capture is off...",
+ (rx_tx == VLIB_RX) ? "rx" : "tx");
}
else
{
- vlib_cli_output (vm, "pcap tx capture is on: %d of %d pkts...",
- dm->pcap_main.n_packets_captured,
- dm->pcap_main.n_packets_to_capture);
+ vlib_cli_output (vm, "pcap %s capture is on: %d of %d pkts...",
+ (rx_tx == VLIB_RX) ? "rx" : "tx",
+ dm->pcap[rx_tx].pcap_main.n_packets_captured,
+ dm->pcap[rx_tx].
+ pcap_main.n_packets_to_capture);
}
break;
}
@@ -247,42 +254,62 @@ pcap_trace_command_fn (vlib_main_t * vm,
/* Since no error, save configured values. */
if (chroot_filename)
{
- if (dm->pcap_filename)
- vec_free (dm->pcap_filename);
+ if (dm->pcap[rx_tx].pcap_filename)
+ vec_free (dm->pcap[rx_tx].pcap_filename);
vec_add1 (chroot_filename, 0);
- dm->pcap_filename = chroot_filename;
+ dm->pcap[rx_tx].pcap_filename = chroot_filename;
}
if (max)
- dm->pcap_pkts_to_capture = max;
+ dm->pcap[rx_tx].pcap_pkts_to_capture = max;
if (enabled)
{
- if (dm->pcap_filename == 0)
- dm->pcap_filename = format (0, "/tmp/vpe.pcap%c", 0);
-
- memset (&dm->pcap_main, 0, sizeof (dm->pcap_main));
- dm->pcap_main.file_name = (char *) dm->pcap_filename;
- dm->pcap_main.n_packets_to_capture = PCAP_DEF_PKT_TO_CAPTURE;
- if (dm->pcap_pkts_to_capture)
- dm->pcap_main.n_packets_to_capture = dm->pcap_pkts_to_capture;
-
- dm->pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
- dm->tx_pcap_enable = 1;
+ if (dm->pcap[rx_tx].pcap_filename == 0)
+ dm->pcap[rx_tx].pcap_filename = format (0, "/tmp/vpe.pcap%c", 0);
+
+ memset (&dm->pcap[rx_tx].pcap_main, 0,
+ sizeof (dm->pcap[rx_tx].pcap_main));
+ dm->pcap[rx_tx].pcap_main.file_name =
+ (char *) dm->pcap[rx_tx].pcap_filename;
+ dm->pcap[rx_tx].pcap_main.n_packets_to_capture
+ = PCAP_DEF_PKT_TO_CAPTURE;
+ if (dm->pcap[rx_tx].pcap_pkts_to_capture)
+ dm->pcap[rx_tx].pcap_main.n_packets_to_capture
+ = dm->pcap[rx_tx].pcap_pkts_to_capture;
+
+ dm->pcap[rx_tx].pcap_main.packet_type = PCAP_PACKET_TYPE_ethernet;
+ dm->pcap[rx_tx].pcap_enable = 1;
vlib_cli_output (vm, "pcap tx capture on...");
}
}
else if (chroot_filename)
vec_free (chroot_filename);
-
return error;
}
+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.
+ * 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 has the following optional parameters:
*
@@ -334,11 +361,18 @@ pcap_trace_command_fn (vlib_main_t * vm,
* @cliexend
?*/
/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (pcap_trace_command, static) = {
+
+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_trace_command_fn,
+ .function = pcap_tx_trace_command_fn,
+};
+VLIB_CLI_COMMAND (pcap_rx_trace_command, static) = {
+ .path = "pcap rx trace",
+ .short_help =
+ "pcap rx trace [on|off] [max <nn>] [intfc <interface>|any] [file <name>] [status]",
+ .function = pcap_rx_trace_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c
index 0ac798fa704..5409fe4f50e 100644
--- a/src/plugins/dpdk/device/device.c
+++ b/src/plugins/dpdk/device/device.c
@@ -351,16 +351,17 @@ CLIB_MULTIARCH_FN (dpdk_interface_tx) (vlib_main_t * vm,
ASSERT (n_packets <= VLIB_FRAME_SIZE);
/* TX PCAP tracing */
- if (PREDICT_FALSE (dm->tx_pcap_enable))
+ if (PREDICT_FALSE (dm->pcap[VLIB_TX].pcap_enable))
{
n_left = n_packets;
while (n_left > 0)
{
u32 bi0 = from[0];
vlib_buffer_t *b0 = vlib_get_buffer (vm, bi0);
- if (dm->pcap_sw_if_index == 0 ||
- dm->pcap_sw_if_index == vnet_buffer (b0)->sw_if_index[VLIB_TX])
- pcap_add_buffer (&dm->pcap_main, vm, bi0, 512);
+ if (dm->pcap[VLIB_TX].pcap_sw_if_index == 0 ||
+ dm->pcap[VLIB_TX].pcap_sw_if_index
+ == vnet_buffer (b0)->sw_if_index[VLIB_TX])
+ pcap_add_buffer (&dm->pcap[VLIB_TX].pcap_main, vm, bi0, 512);
from++;
n_left--;
}
diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h
index eed1126da74..c60312e804b 100644
--- a/src/plugins/dpdk/device/dpdk.h
+++ b/src/plugins/dpdk/device/dpdk.h
@@ -380,6 +380,15 @@ typedef struct
typedef struct
{
+ int pcap_enable;
+ pcap_main_t pcap_main;
+ u8 *pcap_filename;
+ u32 pcap_sw_if_index;
+ u32 pcap_pkts_to_capture;
+} dpdk_pcap_t;
+
+typedef struct
+{
/* Devices */
dpdk_device_t *devices;
@@ -392,8 +401,10 @@ typedef struct
/* buffer flags template, configurable to enable/disable tcp / udp cksum */
u32 buffer_flags_template;
- /* pcap tracing [only works if (CLIB_DEBUG > 0)] */
- int tx_pcap_enable;
+ /* pcap tracing */
+ dpdk_pcap_t pcap[VLIB_N_RX_TX];
+
+ int pcap_enable;
pcap_main_t pcap_main;
u8 *pcap_filename;
u32 pcap_sw_if_index;
diff --git a/src/plugins/dpdk/device/node.c b/src/plugins/dpdk/device/node.c
index a1acc1f0d1e..daccf733372 100644
--- a/src/plugins/dpdk/device/node.c
+++ b/src/plugins/dpdk/device/node.c
@@ -553,7 +553,7 @@ dpdk_device_input (vlib_main_t * vm, dpdk_main_t * dm, dpdk_device_t * xd,
n_rx_packets);
/* packet trace if enabled */
- if ((n_trace = vlib_get_trace_count (vm, node)))
+ if (PREDICT_FALSE ((n_trace = vlib_get_trace_count (vm, node))))
{
n_left = n_rx_packets;
buffers = ptd->buffers;
@@ -584,6 +584,48 @@ dpdk_device_input (vlib_main_t * vm, dpdk_main_t * dm, dpdk_device_t * xd,
vlib_set_trace_count (vm, node, n_trace);
}
+ /* rx pcap capture if enabled */
+ if (PREDICT_FALSE (dm->pcap[VLIB_RX].pcap_enable))
+ {
+ u32 bi0;
+ n_left = n_rx_packets;
+ buffers = ptd->buffers;
+ while (n_left)
+ {
+ bi0 = buffers[0];
+ b0 = vlib_get_buffer (vm, bi0);
+ buffers++;
+
+ if (dm->pcap[VLIB_RX].pcap_sw_if_index == 0 ||
+ dm->pcap[VLIB_RX].pcap_sw_if_index
+ == vnet_buffer (b0)->sw_if_index[VLIB_RX])
+ {
+ struct rte_mbuf *mb;
+ i16 data_start;
+ i32 temp_advance;
+
+ /*
+ * Note: current_data will have advanced
+ * when we skip ethernet input.
+ * Temporarily back up to the original DMA
+ * target, so we capture a valid ethernet frame
+ */
+ mb = rte_mbuf_from_vlib_buffer (b0);
+
+ /* Figure out the original data_start */
+ data_start = (mb->buf_addr + mb->data_off) - (void *) b0->data;
+ /* Back up that far */
+ temp_advance = b0->current_data - data_start;
+ vlib_buffer_advance (b0, -temp_advance);
+ /* Trace the packet */
+ pcap_add_buffer (&dm->pcap[VLIB_RX].pcap_main, vm, bi0, 512);
+ /* and advance again */
+ vlib_buffer_advance (b0, temp_advance);
+ }
+ n_left--;
+ }
+ }
+
vlib_increment_combined_counter
(vnet_get_main ()->interface_main.combined_sw_if_counters
+ VNET_INTERFACE_COUNTER_RX, thread_index, xd->sw_if_index,
diff --git a/src/vnet/unix/pcap.h b/src/vnet/unix/pcap.h
index 7d55db37979..1ab1531cfa3 100644
--- a/src/vnet/unix/pcap.h
+++ b/src/vnet/unix/pcap.h
@@ -211,23 +211,21 @@ pcap_add_buffer (pcap_main_t * pm,
f64 time_now = vlib_time_now (vm);
void *d;
- d = pcap_add_packet (pm, time_now, n_left, n);
- while (1)
+ if (PREDICT_TRUE (pm->n_packets_captured < pm->n_packets_to_capture))
{
- u32 copy_length = clib_min ((u32) n_left, b->current_length);
- clib_memcpy (d, b->data + b->current_data, copy_length);
- n_left -= b->current_length;
- if (n_left <= 0)
- break;
- d += b->current_length;
- ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
- b = vlib_get_buffer (vm, b->next_buffer);
+ d = pcap_add_packet (pm, time_now, n_left, n);
+ while (1)
+ {
+ u32 copy_length = clib_min ((u32) n_left, b->current_length);
+ clib_memcpy (d, b->data + b->current_data, copy_length);
+ n_left -= b->current_length;
+ if (n_left <= 0)
+ break;
+ d += b->current_length;
+ ASSERT (b->flags & VLIB_BUFFER_NEXT_PRESENT);
+ b = vlib_get_buffer (vm, b->next_buffer);
+ }
}
-
- /** Flush output vector. */
- if (vec_len (pm->pcap_data) >= 64 * 1024
- || pm->n_packets_captured >= pm->n_packets_to_capture)
- pcap_write (pm);
}
#endif /* included_vnet_pcap_h */