}
}
+uword
+unformat_vlib_error (unformat_input_t *input, va_list *args)
+{
+ vlib_main_t *vm = va_arg (*args, vlib_main_t *);
+ const vlib_error_main_t *em = &vm->error_main;
+ vlib_error_t *error_index = va_arg (*args, vlib_error_t *);
+ const vlib_node_t *node;
+ char *error_name;
+ u32 node_index;
+ vlib_error_t i;
+
+ if (!unformat (input, "%U.%s", unformat_vlib_node, vm, &node_index,
+ &error_name))
+ return 0;
+
+ node = vlib_get_node (vm, node_index);
+ for (i = 0; i < node->n_errors; i++)
+ {
+ vlib_error_t ei = node->error_heap_index + i;
+ if (strcmp (em->counters_heap[ei].name, error_name) == 0)
+ {
+ *error_index = ei;
+ vec_free (error_name);
+ return 1;
+ }
+ }
+
+ vec_free (error_name);
+ return 0;
+}
+
static char *
sev2str (enum vl_counter_severity_e s)
{
#ifndef included_vlib_error_h
#define included_vlib_error_h
+#include <vppinfra/format.h>
+
typedef u16 vlib_error_t;
enum vl_counter_severity_e
u32 n_errors, char *error_strings[],
vl_counter_t counters[]);
+unformat_function_t unformat_vlib_error;
+
#endif /* included_vlib_error_h */
/*
{
const u32 pcap_sw_if_index = pp->pcap_sw_if_index;
const u32 filter_classify_table_index = pp->filter_classify_table_index;
+ const vlib_error_t pcap_error_index = pp->pcap_error_index;
if (pcap_sw_if_index != 0)
{
return 0; /* wrong interface, skip */
}
+ if (pcap_error_index != (vlib_error_t) ~0 && pcap_error_index != b->error)
+ return 0; /* wrong error */
+
if (filter_classify_table_index != ~0 &&
vnet_is_packet_traced_inline (b, filter_classify_table_index,
0 /* full classify */) != 1)
u8 free_data;
u32 sw_if_index;
int filter;
+ vlib_error_t drop_err;
} vnet_pcap_dispatch_trace_args_t;
int vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t *);
cm->classify_table_index_by_sw_if_index[0];
else
pp->filter_classify_table_index = ~0;
+ pp->pcap_error_index = a->drop_err;
pp->pcap_rx_enable = a->rx_enable;
pp->pcap_tx_enable = a->tx_enable;
pp->pcap_drop_enable = a->drop_enable;
pp->pcap_tx_enable = 0;
pp->pcap_drop_enable = 0;
pp->filter_classify_table_index = ~0;
+ pp->pcap_error_index = ~0;
if (pm->n_packets_captured)
{
clib_error_t *error;
int filter = 0;
int free_data = 0;
u32 sw_if_index = 0; /* default: any interface */
+ vlib_error_t drop_err = ~0; /* default: any error */
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
else if (unformat (line_input, "interface %U",
unformat_vnet_sw_interface, vnm, &sw_if_index))
;
+ else if (unformat (line_input, "error %U", unformat_vlib_error, vm,
+ &drop_err))
+ ;
else if (unformat (line_input, "preallocate-data %=",
&preallocate_data, 1))
;
a->sw_if_index = sw_if_index;
a->filter = filter;
a->max_bytes_per_pkt = max_bytes_per_pkt;
+ a->drop_err = drop_err;
rv = vnet_pcap_dispatch_trace_configure (a);
* filter. The filter will only be executed if the per-interface or
* any-interface tests fail.
*
+ * - <b>error <node>.<error></b> - filter packets based on a specific error.
+ * For example: error {ip4-udp-lookup}.{No listener for dst port}
+ *
* - <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
* pcap tx capture is off...
* @cliexend
* Example of how to start a tx packet capture:
- * @cliexstart{pcap trace tx max 35 intfc GigabitEthernet0/8/0 file vppTest.pcap}
+ * @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 trace status}
u32 pcap_sw_if_index;
pcap_main_t pcap_main;
u32 filter_classify_table_index;
+ vlib_error_t pcap_error_index;
} vnet_pcap_t;
typedef struct vnet_main_t
"match l3 ip4 proto 17 l4 src_port 2345")
self.cli(
"pcap trace rx tx max 1000 intfc pg0 "
- "file vpp_test_trace_filter.pcap filter")
+ "file vpp_test_trace_filter_test_pcap.pcap filter")
# the packet we are trying to match
p = list()
for i in range(100):
self.del_pcap_filters()
# check captured pcap
- pcap = rdpcap("/tmp/vpp_test_trace_filter.pcap")
+ pcap = rdpcap("/tmp/vpp_test_trace_filter_test_pcap.pcap")
self.assertEqual(len(pcap), 9 + 17)
p_ = str(p[5])
for i in range(9):
for i in range(9, 9 + 17):
self.assertEqual(str(pcap[i]), p_)
+ def test_pcap_drop(self):
+ """ Drop Packet Capture Filter Test """
+ self.cli(
+ "pcap trace drop max 1000 "
+ "error {ip4-udp-lookup}.{No listener for dst port} "
+ "file vpp_test_trace_filter_test_pcap_drop.pcap")
+ # the packet we are trying to match
+ p = list()
+ for i in range(17):
+ # this packet should be forwarded
+ p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_hosts[0].ip4,
+ dst=self.pg1.remote_ip4) /
+ UDP(sport=2345, dport=1234) / Raw('\xa5' * 100)))
+ # this packet should be captured (no listener)
+ p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_hosts[0].ip4,
+ dst=self.pg0.local_ip4) /
+ UDP(sport=2345, dport=1234) / Raw('\xa5' * 100)))
+ # this packet will be blackholed but not captured
+ p.append((Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_hosts[0].ip4, dst="0.0.0.0") /
+ UDP(sport=2345, dport=1234) / Raw('\xa5' * 100)))
+
+ self.send_and_expect(self.pg0, p, self.pg1, n_rx=17, trace=False)
+
+ self.cli("pcap trace drop off")
+
+ # check captured pcap
+ pcap = rdpcap("/tmp/vpp_test_trace_filter_test_pcap_drop.pcap")
+ self.assertEqual(len(pcap), 17)
+
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)