diff options
author | Benoît Ganne <bganne@cisco.com> | 2021-03-03 17:37:25 +0100 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2021-04-22 11:12:59 +0000 |
commit | 5cfe45211ac7977ab9bf07b817fe9a5d00226eb3 (patch) | |
tree | 1154a67367b5cbd8343ecdc48518746bdcc8642a | |
parent | d06e2eb1a1d570367b4076772ac66bc95e3a7bd8 (diff) |
misc: add filter for specific error for pcap trace
Type: feature
Change-Id: I325257454df1cc22833fa6a1dedd4739d4d5a558
Signed-off-by: Benoît Ganne <bganne@cisco.com>
-rw-r--r-- | src/vlib/error.c | 31 | ||||
-rw-r--r-- | src/vlib/error.h | 4 | ||||
-rw-r--r-- | src/vnet/classify/pcap_classify.h | 4 | ||||
-rw-r--r-- | src/vnet/interface.h | 1 | ||||
-rw-r--r-- | src/vnet/interface_cli.c | 13 | ||||
-rw-r--r-- | src/vnet/vnet.h | 1 | ||||
-rw-r--r-- | test/test_trace_filter.py | 36 |
7 files changed, 87 insertions, 3 deletions
diff --git a/src/vlib/error.c b/src/vlib/error.c index 99664c618a9..1a84e7e6801 100644 --- a/src/vlib/error.c +++ b/src/vlib/error.c @@ -210,6 +210,37 @@ vlib_register_errors (vlib_main_t * vm, } } +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) { diff --git a/src/vlib/error.h b/src/vlib/error.h index 11757e05f67..2bffc6b9367 100644 --- a/src/vlib/error.h +++ b/src/vlib/error.h @@ -40,6 +40,8 @@ #ifndef included_vlib_error_h #define included_vlib_error_h +#include <vppinfra/format.h> + typedef u16 vlib_error_t; enum vl_counter_severity_e @@ -75,6 +77,8 @@ void vlib_register_errors (struct vlib_main_t *vm, u32 n_errors, char *error_strings[], vl_counter_t counters[]); +unformat_function_t unformat_vlib_error; + #endif /* included_vlib_error_h */ /* diff --git a/src/vnet/classify/pcap_classify.h b/src/vnet/classify/pcap_classify.h index 1f1c38fd6e6..e079816f62c 100644 --- a/src/vnet/classify/pcap_classify.h +++ b/src/vnet/classify/pcap_classify.h @@ -33,6 +33,7 @@ vnet_is_packet_pcaped (vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index) { 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) { @@ -42,6 +43,9 @@ vnet_is_packet_pcaped (vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index) 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) diff --git a/src/vnet/interface.h b/src/vnet/interface.h index b36d02c32bf..9d2f2a1c81d 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -1039,6 +1039,7 @@ typedef struct 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 *); diff --git a/src/vnet/interface_cli.c b/src/vnet/interface_cli.c index 9ade975937e..6dadbb8e8d3 100644 --- a/src/vnet/interface_cli.c +++ b/src/vnet/interface_cli.c @@ -2034,6 +2034,7 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) 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; @@ -2045,6 +2046,7 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a) 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; @@ -2091,6 +2093,7 @@ pcap_trace_command_fn (vlib_main_t * vm, 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)) @@ -2124,6 +2127,9 @@ pcap_trace_command_fn (vlib_main_t * vm, 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)) ; @@ -2155,6 +2161,7 @@ pcap_trace_command_fn (vlib_main_t * vm, 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); @@ -2235,6 +2242,9 @@ pcap_trace_command_fn (vlib_main_t * vm, * 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 @@ -2255,7 +2265,8 @@ pcap_trace_command_fn (vlib_main_t * vm, * 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} diff --git a/src/vnet/vnet.h b/src/vnet/vnet.h index 1deaff66375..24afe633af2 100644 --- a/src/vnet/vnet.h +++ b/src/vnet/vnet.h @@ -70,6 +70,7 @@ typedef struct 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 diff --git a/test/test_trace_filter.py b/test/test_trace_filter.py index 8869b3255d3..fd250ac17c7 100644 --- a/test/test_trace_filter.py +++ b/test/test_trace_filter.py @@ -174,7 +174,7 @@ class TestTracefilter(VppTestCase): "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): @@ -198,7 +198,7 @@ class TestTracefilter(VppTestCase): 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): @@ -207,6 +207,38 @@ class TestTracefilter(VppTestCase): 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) |