bpf_trace_filter: allow pcap filtering without classifier

Type: improvement

Change-Id: I7ca860dbee0d0a24b7f00943142d8c878ed90e80
Signed-off-by: Hadi Rayan Al-Sandid <halsandi@cisco.com>
This commit is contained in:
Hadi Rayan Al-Sandid 2024-11-26 15:58:40 +01:00
parent dd02eb893b
commit fb8f51697c
5 changed files with 89 additions and 13 deletions

View File

@ -46,7 +46,7 @@ vnet_is_packet_pcaped (vnet_pcap_t *pp, vlib_buffer_t *b, u32 sw_if_index)
if (pcap_error_index != (vlib_error_t) ~0 && pcap_error_index != b->error)
return 0; /* wrong error */
if (filter_classify_table_index != ~0 &&
if (pp->pcap_filter_enable &&
pp->current_filter_function (b, filter_classify_table_index,
0 /* full classify */) != 1)
return 0; /* not matching the filter, skip */

View File

@ -2041,6 +2041,12 @@ format_vnet_pcap (u8 * s, va_list * args)
s = format (s, "drop");
printed = 1;
}
if (printed && pp->pcap_filter_enable)
{
s = format (s, "with filter");
printed = 1;
}
return s;
}
s = format (s, "unknown type %d!", type);
@ -2092,12 +2098,6 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
&& (pm->n_packets_to_capture != a->packets_to_capture))
return VNET_API_ERROR_INVALID_VALUE_2;
/* Classify filter specified, but no classify filter configured */
if ((a->rx_enable + a->tx_enable + a->drop_enable) && a->filter &&
(!cm->classify_table_index_by_sw_if_index ||
cm->classify_table_index_by_sw_if_index[0] == ~0))
return VNET_API_ERROR_NO_SUCH_LABEL;
if (a->rx_enable + a->tx_enable + a->drop_enable)
{
void *save_pcap_data;
@ -2151,11 +2151,13 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
}
pm->n_packets_to_capture = a->packets_to_capture;
pp->pcap_sw_if_index = a->sw_if_index;
if (a->filter)
if (a->filter && cm->classify_table_index_by_sw_if_index &&
cm->classify_table_index_by_sw_if_index[0] != ~0)
pp->filter_classify_table_index =
cm->classify_table_index_by_sw_if_index[0];
else
pp->filter_classify_table_index = ~0;
pp->pcap_filter_enable = a->filter;
pp->pcap_error_index = a->drop_err;
pp->pcap_rx_enable = a->rx_enable;
pp->pcap_tx_enable = a->tx_enable;
@ -2164,6 +2166,7 @@ vnet_pcap_dispatch_trace_configure (vnet_pcap_dispatch_trace_args_t * a)
}
else
{
pp->pcap_filter_enable = 0;
pp->pcap_rx_enable = 0;
pp->pcap_tx_enable = 0;
pp->pcap_drop_enable = 0;
@ -2312,10 +2315,6 @@ pcap_trace_command_fn (vlib_main_t * vm,
return clib_error_return (0,
"Max bytes per pkt must be > 32, < 9000...");
case VNET_API_ERROR_NO_SUCH_LABEL:
return clib_error_return
(0, "No classify filter configured, see 'classify filter...'");
default:
vlib_cli_output (vm, "WARNING: trace configure returned %d", rv);
break;

View File

@ -66,7 +66,7 @@ typedef struct
u8 pcap_tx_enable;
/* Trace drop pkts */
u8 pcap_drop_enable;
u8 pad1;
u8 pcap_filter_enable;
u32 max_bytes_per_pkt;
u32 pcap_sw_if_index;
pcap_main_t pcap_main;

View File

@ -1,5 +1,7 @@
from framework import VppTestCase
from asfframework import VppTestRunner
from vpp_papi_provider import CliFailedCommandError
import os
import unittest
from config import config
from scapy.layers.l2 import Ether
@ -77,6 +79,17 @@ class TestBpfTraceFilter(VppTestCase):
"Unexpected packets in the trace buffer",
)
# verify that bpf trace filter has been selected for pcap
self.vapi.cli("set pcap filter function bpf_trace_filter")
self.vapi.cli("pcap trace rx tx max 1000 intfc any filter")
# verify that packets are filtered in not captured in pcap
self.pg0.add_stream(packets)
self.pg_start()
with self.assertRaises(CliFailedCommandError):
self.vapi.cli("pcap trace rx tx off")
reply = self.vapi.cli("show bpf trace filter")
self.assertIn("(000)", reply, "Unexpected bpf filter dump")
@ -103,6 +116,29 @@ class TestBpfTraceFilter(VppTestCase):
"Unexpected packets in the trace buffer",
)
# verify that bpf trace filter has been selected for pcap
self.vapi.pcap_set_filter_function(filter_function_name="bpf_trace_filter")
reply = self.vapi.cli("show pcap filter function")
self.assertIn(
"(*) name:bpf_trace_filter",
reply,
"BPF Trace filter is not selected for Pcap",
)
# verify that packets are filtered in not captured in pcap
self.vapi.pcap_trace_on(
capture_rx=True,
capture_tx=True,
max_packets=1000,
filter=True,
sw_if_index=0,
filename="bpf_trace.pcap",
)
self.pg0.add_stream(packets)
self.pg_start()
with self.vapi.assert_negative_api_retval():
self.vapi.pcap_trace_off()
def test_bpf_trace_filter_vapi_v2(self):
"""BPF Trace filter test [VAPI v2]"""
self.vapi.bpf_trace_filter_set_v2(filter="tcp or dst port 5678")
@ -131,6 +167,30 @@ class TestBpfTraceFilter(VppTestCase):
"Unexpected packets in the trace buffer",
)
# verify that bpf trace filter has been selected for pcap
self.vapi.pcap_set_filter_function(filter_function_name="bpf_trace_filter")
reply = self.vapi.cli("show pcap filter function")
self.assertIn(
"(*) name:bpf_trace_filter",
reply,
"BPF Trace filter is not selected for Pcap",
)
# verify that packets are captured in pcap with filter
self.vapi.pcap_trace_on(
capture_rx=True,
capture_tx=True,
max_packets=1000,
filter=True,
sw_if_index=0,
filename="bpf_trace.pcap",
)
self.pg0.add_stream(packets)
self.pg_start()
self.vapi.pcap_trace_off()
self.assertTrue(os.path.exists("/tmp/bpf_trace.pcap"))
os.remove("/tmp/bpf_trace.pcap")
if __name__ == "__main__":
unittest.main(testRunner=VppTestRunner)

View File

@ -75,11 +75,13 @@ class TestPcap(VppTestCase):
"pa en",
"pcap dispatch trace off",
"pcap trace rx tx max 1000 intfc any",
"pcap trace status",
"pa en",
"pcap trace status",
"pcap trace rx tx off",
"classify filter pcap mask l3 ip4 src match l3 ip4 src 11.22.33.44",
"pcap trace rx tx max 1000 intfc any file filt.pcap filter",
"pcap trace status",
"show cla t verbose 2",
"show cla t verbose",
"show cla t",
@ -123,6 +125,21 @@ class TestPcap(VppTestCase):
self.pg_send(self.pg0, pkt * 10)
self.vapi.pcap_trace_off()
# Launching trace with filter & no classifier table specified
# should result in no packet capture
self.vapi.pcap_trace_on(
capture_rx=True,
capture_tx=True,
max_packets=1000,
filter=True,
sw_if_index=0,
filename="trace_any_invalid_filter.pcap",
)
self.pg_send(self.pg0, pkt * 10)
with self.vapi.assert_negative_api_retval():
self.vapi.pcap_trace_off()
self.assertFalse(os.path.exists("/tmp/trace_any_invalid_filter.pcap"))
self.vapi.cli(
f"classify filter pcap mask l3 ip4 src match l3 ip4 src {self.pg0.local_ip4}"
)