bpf_trace_filter: allow pcap filtering without classifier 33/41933/5
authorHadi Rayan Al-Sandid <[email protected]>
Tue, 26 Nov 2024 14:58:40 +0000 (15:58 +0100)
committerHadi Rayan Al-Sandid <[email protected]>
Wed, 11 Dec 2024 08:58:32 +0000 (08:58 +0000)
Type: improvement

Change-Id: I7ca860dbee0d0a24b7f00943142d8c878ed90e80
Signed-off-by: Hadi Rayan Al-Sandid <[email protected]>
src/vnet/classify/pcap_classify.h
src/vnet/interface_cli.c
src/vnet/vnet.h
test/test_bpf_trace_filter.py
test/test_pcap.py

index a4ebcd1..c23267f 100644 (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 */
index c56eb97..cc214c1 100644 (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;
index 54988ae..6e436cc 100644 (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;
index 6958caa..d90088a 100644 (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)
index 1169dcc..9441808 100644 (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}"
         )