DPDK patches and discussions
 help / color / mirror / Atom feed
From: jspewock@iol.unh.edu
To: Honnappa.Nagarahalli@arm.com, juraj.linkes@pantheon.tech,
	thomas@monjalon.net, wathsala.vithanage@arm.com,
	probb@iol.unh.edu, paul.szczepanek@arm.com,
	yoan.picchi@foss.arm.com, ferruh.yigit@amd.com,
	andrew.rybchenko@oktetlabs.ru
Cc: dev@dpdk.org, Jeremy Spewock <jspewock@iol.unh.edu>
Subject: [PATCH v9 3/7] dts: add optional packet filtering to scapy sniffer
Date: Mon, 11 Mar 2024 11:44:01 -0400	[thread overview]
Message-ID: <20240311154405.13269-4-jspewock@iol.unh.edu> (raw)
In-Reply-To: <20240311154405.13269-1-jspewock@iol.unh.edu>

From: Jeremy Spewock <jspewock@iol.unh.edu>

Added the options to filter out LLDP and ARP packets when
sniffing for packets with scapy. This was done using BPF filters to
ensure that the noise these packets provide does not interfere with test
cases.

Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
---
 dts/framework/test_suite.py                   | 15 +++++++++--
 dts/framework/testbed_model/tg_node.py        | 14 ++++++++--
 .../traffic_generator/__init__.py             |  7 ++++-
 .../capturing_traffic_generator.py            | 22 ++++++++++++++-
 .../testbed_model/traffic_generator/scapy.py  | 27 +++++++++++++++++++
 5 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 1957ea7328..9c3b516002 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -23,6 +23,7 @@
 from .exception import TestCaseVerifyError
 from .logger import DTSLogger, get_dts_logger
 from .testbed_model import Port, PortLink, SutNode, TGNode
+from .testbed_model.traffic_generator import PacketFilteringConfig
 from .utils import get_packet_summaries
 
 
@@ -174,7 +175,12 @@ def configure_testbed_ipv4(self, restore: bool = False) -> None:
     def _configure_ipv4_forwarding(self, enable: bool) -> None:
         self.sut_node.configure_ipv4_forwarding(enable)
 
-    def send_packet_and_capture(self, packet: Packet, duration: float = 1) -> list[Packet]:
+    def send_packet_and_capture(
+        self,
+        packet: Packet,
+        filter_config: PacketFilteringConfig = PacketFilteringConfig(),
+        duration: float = 1,
+    ) -> list[Packet]:
         """Send and receive `packet` using the associated TG.
 
         Send `packet` through the appropriate interface and receive on the appropriate interface.
@@ -182,6 +188,7 @@ def send_packet_and_capture(self, packet: Packet, duration: float = 1) -> list[P
 
         Args:
             packet: The packet to send.
+            filter_config: The filter to use when capturing packets.
             duration: Capture traffic for this amount of time after sending `packet`.
 
         Returns:
@@ -189,7 +196,11 @@ def send_packet_and_capture(self, packet: Packet, duration: float = 1) -> list[P
         """
         packet = self._adjust_addresses(packet)
         return self.tg_node.send_packet_and_capture(
-            packet, self._tg_port_egress, self._tg_port_ingress, duration
+            packet,
+            self._tg_port_egress,
+            self._tg_port_ingress,
+            filter_config,
+            duration,
         )
 
     def get_expected_packet(self, packet: Packet) -> Packet:
diff --git a/dts/framework/testbed_model/tg_node.py b/dts/framework/testbed_model/tg_node.py
index f269d4c585..d3206e87e0 100644
--- a/dts/framework/testbed_model/tg_node.py
+++ b/dts/framework/testbed_model/tg_node.py
@@ -15,7 +15,11 @@
 
 from .node import Node
 from .port import Port
-from .traffic_generator import CapturingTrafficGenerator, create_traffic_generator
+from .traffic_generator import (
+    CapturingTrafficGenerator,
+    PacketFilteringConfig,
+    create_traffic_generator,
+)
 
 
 class TGNode(Node):
@@ -53,6 +57,7 @@ def send_packet_and_capture(
         packet: Packet,
         send_port: Port,
         receive_port: Port,
+        filter_config: PacketFilteringConfig = PacketFilteringConfig(),
         duration: float = 1,
     ) -> list[Packet]:
         """Send `packet`, return received traffic.
@@ -65,13 +70,18 @@ def send_packet_and_capture(
             packet: The packet to send.
             send_port: The egress port on the TG node.
             receive_port: The ingress port in the TG node.
+            filter_config: The filter to use when capturing packets.
             duration: Capture traffic for this amount of time after sending `packet`.
 
         Returns:
              A list of received packets. May be empty if no packets are captured.
         """
         return self.traffic_generator.send_packet_and_capture(
-            packet, send_port, receive_port, duration
+            packet,
+            send_port,
+            receive_port,
+            filter_config,
+            duration,
         )
 
     def close(self) -> None:
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index 11e2bd7d97..0eaf0355cd 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -14,11 +14,16 @@
 and a capturing traffic generator is required.
 """
 
+# pylama:ignore=W0611
+
 from framework.config import ScapyTrafficGeneratorConfig, TrafficGeneratorType
 from framework.exception import ConfigurationError
 from framework.testbed_model.node import Node
 
-from .capturing_traffic_generator import CapturingTrafficGenerator
+from .capturing_traffic_generator import (
+    CapturingTrafficGenerator,
+    PacketFilteringConfig,
+)
 from .scapy import ScapyTrafficGenerator
 
 
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index 0246590333..e5a1560e90 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -11,6 +11,7 @@
 
 import uuid
 from abc import abstractmethod
+from dataclasses import dataclass
 
 import scapy.utils  # type: ignore[import]
 from scapy.packet import Packet  # type: ignore[import]
@@ -26,6 +27,19 @@ def _get_default_capture_name() -> str:
     return str(uuid.uuid4())
 
 
+@dataclass(slots=True, frozen=True)
+class PacketFilteringConfig:
+    """The supported filtering options for :class:`CapturingTrafficGenerator`.
+
+    Attributes:
+        no_lldp: If :data:`True`, LLDP packets will be filtered out when capturing.
+        no_arp: If :data:`True`, ARP packets will be filtered out when capturing.
+    """
+
+    no_lldp: bool = True
+    no_arp: bool = True
+
+
 class CapturingTrafficGenerator(TrafficGenerator):
     """Capture packets after sending traffic.
 
@@ -54,6 +68,7 @@ def send_packet_and_capture(
         packet: Packet,
         send_port: Port,
         receive_port: Port,
+        filter_config: PacketFilteringConfig,
         duration: float,
         capture_name: str = _get_default_capture_name(),
     ) -> list[Packet]:
@@ -68,6 +83,7 @@ def send_packet_and_capture(
             packet: The packet to send.
             send_port: The egress port on the TG node.
             receive_port: The ingress port in the TG node.
+            filter_config: Filters to apply when capturing packets.
             duration: Capture traffic for this amount of time after sending the packet.
             capture_name: The name of the .pcap file where to store the capture.
 
@@ -75,7 +91,7 @@ def send_packet_and_capture(
              The received packets. May be empty if no packets are captured.
         """
         return self.send_packets_and_capture(
-            [packet], send_port, receive_port, duration, capture_name
+            [packet], send_port, receive_port, filter_config, duration, capture_name
         )
 
     def send_packets_and_capture(
@@ -83,6 +99,7 @@ def send_packets_and_capture(
         packets: list[Packet],
         send_port: Port,
         receive_port: Port,
+        filter_config: PacketFilteringConfig,
         duration: float,
         capture_name: str = _get_default_capture_name(),
     ) -> list[Packet]:
@@ -99,6 +116,7 @@ def send_packets_and_capture(
             packets: The packets to send.
             send_port: The egress port on the TG node.
             receive_port: The ingress port in the TG node.
+            filter_config: Filters to apply when capturing packets.
             duration: Capture traffic for this amount of time after sending the packets.
             capture_name: The name of the .pcap file where to store the capture.
 
@@ -113,6 +131,7 @@ def send_packets_and_capture(
             packets,
             send_port,
             receive_port,
+            filter_config,
             duration,
         )
 
@@ -126,6 +145,7 @@ def _send_packets_and_capture(
         packets: list[Packet],
         send_port: Port,
         receive_port: Port,
+        filter_config: PacketFilteringConfig,
         duration: float,
     ) -> list[Packet]:
         """The implementation of :method:`send_packets_and_capture`.
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index 5b60f66237..df3069d516 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -32,6 +32,7 @@
 
 from .capturing_traffic_generator import (
     CapturingTrafficGenerator,
+    PacketFilteringConfig,
     _get_default_capture_name,
 )
 
@@ -69,6 +70,7 @@ def scapy_send_packets_and_capture(
     send_iface: str,
     recv_iface: str,
     duration: float,
+    sniff_filter: str,
 ) -> list[bytes]:
     """The RPC function to send and capture packets.
 
@@ -90,6 +92,7 @@ def scapy_send_packets_and_capture(
         iface=recv_iface,
         store=True,
         started_callback=lambda *args: scapy.all.sendp(scapy_packets, iface=send_iface),
+        filter=sniff_filter,
     )
     sniffer.start()
     time.sleep(duration)
@@ -260,11 +263,34 @@ def _send_packets(self, packets: list[Packet], port: Port) -> None:
         packets = [packet.build() for packet in packets]
         self.rpc_server_proxy.scapy_send_packets(packets, port.logical_name)
 
+    def _create_packet_filter(self, filter_config: PacketFilteringConfig) -> str:
+        """Combines filter settings from `filter_config` into a BPF that scapy can use.
+
+        Scapy allows for the use of Berkeley Packet Filters (BPFs) to filter what packets are
+        collected based on various attributes of the packet.
+
+        Args:
+            filter_config: Config class that specifies which filters should be applied.
+
+        Returns:
+            A string representing the combination of BPF filters to be passed to scapy. For
+            example:
+
+            "ether[12:2] != 0x88cc && ether[12:2] != 0x0806"
+        """
+        bpf_filter = []
+        if filter_config.no_arp:
+            bpf_filter.append("ether[12:2] != 0x0806")
+        if filter_config.no_lldp:
+            bpf_filter.append("ether[12:2] != 0x88cc")
+        return " && ".join(bpf_filter)
+
     def _send_packets_and_capture(
         self,
         packets: list[Packet],
         send_port: Port,
         receive_port: Port,
+        filter_config: PacketFilteringConfig,
         duration: float,
         capture_name: str = _get_default_capture_name(),
     ) -> list[Packet]:
@@ -277,6 +303,7 @@ def _send_packets_and_capture(
             send_port.logical_name,
             receive_port.logical_name,
             duration,
+            self._create_packet_filter(filter_config),
         )  # type: ignore[assignment]
 
         scapy_packets = [Ether(packet.data) for packet in xmlrpc_packets]
-- 
2.43.2


  parent reply	other threads:[~2024-03-11 15:45 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-18 18:12 [PATCH v4 0/7] dts: Port scatter suite over jspewock
2023-12-18 18:12 ` [PATCH v4 1/7] dts: add required methods to testpmd_shell jspewock
2023-12-19 16:45   ` Juraj Linkeš
2023-12-21 19:37     ` Jeremy Spewock
2024-01-03 11:10       ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 2/7] dts: allow passing parameters into interactive apps jspewock
2023-12-19 16:50   ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 3/7] dts: add optional packet filtering to scapy sniffer jspewock
2023-12-19 16:54   ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 4/7] dts: add pci addresses to EAL parameters jspewock
2023-12-19 16:55   ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 5/7] dts: allow configuring MTU of ports jspewock
2023-12-19 16:58   ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 6/7] dts: add scatter to the yaml schema jspewock
2023-12-19 16:59   ` Juraj Linkeš
2023-12-18 18:12 ` [PATCH v4 7/7] dts: add scatter test suite jspewock
2023-12-19 17:29   ` Juraj Linkeš
2023-12-21 21:47     ` Jeremy Spewock
2024-01-03 11:14       ` Juraj Linkeš
2024-01-03 22:12 ` [PATCH v5 0/7] dts: Port scatter suite over jspewock
2024-01-03 22:12   ` [PATCH v5 1/7] dts: add startup verification and forwarding modes to testpmd shell jspewock
2024-01-03 22:12   ` [PATCH v5 2/7] dts: limit EAL parameters to DPDK apps and add parameters to all apps jspewock
2024-01-03 22:12   ` [PATCH v5 3/7] dts: add optional packet filtering to scapy sniffer jspewock
2024-01-03 22:12   ` [PATCH v5 4/7] dts: add pci addresses to EAL parameters jspewock
2024-01-03 22:12   ` [PATCH v5 5/7] dts: allow configuring MTU of ports jspewock
2024-01-03 22:12   ` [PATCH v5 6/7] dts: add scatter to the yaml schema jspewock
2024-01-03 22:12   ` [PATCH v5 7/7] dts: add pmd_buffer_scatter test suite jspewock
2024-01-03 22:31   ` [PATCH v6 0/7] dts: Port scatter suite over jspewock
2024-01-03 22:32     ` [PATCH v6 1/7] dts: add startup verification and forwarding modes to testpmd shell jspewock
2024-01-08 11:34       ` Juraj Linkeš
2024-01-08 16:36         ` Jeremy Spewock
2024-01-09 11:54           ` Juraj Linkeš
2024-01-09 14:31             ` Jeremy Spewock
2024-01-03 22:32     ` [PATCH v6 2/7] dts: limit EAL parameters to DPDK apps and add parameters to all apps jspewock
2024-01-08 11:52       ` Juraj Linkeš
2024-01-08 16:37         ` Jeremy Spewock
2024-01-03 22:32     ` [PATCH v6 3/7] dts: add optional packet filtering to scapy sniffer jspewock
2024-01-08 12:01       ` Juraj Linkeš
2024-01-08 16:39         ` Jeremy Spewock
2024-01-08 16:40           ` Jeremy Spewock
2024-01-03 22:32     ` [PATCH v6 4/7] dts: add pci addresses to EAL parameters jspewock
2024-01-08 14:59       ` Juraj Linkeš
2024-01-03 22:32     ` [PATCH v6 5/7] dts: allow configuring MTU of ports jspewock
2024-01-08 15:00       ` Juraj Linkeš
2024-01-03 22:32     ` [PATCH v6 6/7] dts: add scatter to the yaml schema jspewock
2024-01-08 15:01       ` Juraj Linkeš
2024-01-03 22:32     ` [PATCH v6 7/7] dts: add pmd_buffer_scatter test suite jspewock
2024-01-08 15:47       ` Juraj Linkeš
2024-01-08 16:53         ` Jeremy Spewock
2024-01-09 15:36     ` [PATCH v7 0/7] dts: Port scatter suite over jspewock
2024-01-09 15:36       ` [PATCH v7 1/7] dts: add startup verification and forwarding modes to testpmd shell jspewock
2024-01-10 13:18         ` Juraj Linkeš
2024-01-10 14:09           ` Jeremy Spewock
2024-01-09 15:36       ` [PATCH v7 2/7] dts: limit EAL parameters to DPDK apps and add parameters to all apps jspewock
2024-01-09 15:36       ` [PATCH v7 3/7] dts: add optional packet filtering to scapy sniffer jspewock
2024-01-09 15:36       ` [PATCH v7 4/7] dts: add pci addresses to EAL parameters jspewock
2024-01-09 15:36       ` [PATCH v7 5/7] dts: allow configuring MTU of ports jspewock
2024-01-09 15:36       ` [PATCH v7 6/7] dts: add scatter to the yaml schema jspewock
2024-01-09 15:36       ` [PATCH v7 7/7] dts: add pmd_buffer_scatter test suite jspewock
2024-01-10 13:16         ` Juraj Linkeš
2024-01-10 14:09           ` Jeremy Spewock
2024-01-10 13:22       ` [PATCH v7 0/7] dts: Port scatter suite over Juraj Linkeš
2024-01-10 14:42       ` [PATCH v8 " jspewock
2024-01-10 14:42         ` [PATCH v8 1/7] dts: add startup verification and forwarding modes to testpmd shell jspewock
2024-01-10 14:42         ` [PATCH v8 2/7] dts: limit EAL parameters to DPDK apps and add parameters to all apps jspewock
2024-01-10 14:42         ` [PATCH v8 3/7] dts: add optional packet filtering to scapy sniffer jspewock
2024-01-10 14:42         ` [PATCH v8 4/7] dts: add pci addresses to EAL parameters jspewock
2024-01-10 14:42         ` [PATCH v8 5/7] dts: allow configuring MTU of ports jspewock
2024-01-10 14:42         ` [PATCH v8 6/7] dts: add scatter to the yaml schema jspewock
2024-01-10 14:42         ` [PATCH v8 7/7] dts: add pmd_buffer_scatter test suite jspewock
2024-01-11 10:07         ` [PATCH v8 0/7] dts: Port scatter suite over Juraj Linkeš
2024-02-21  3:34         ` Patrick Robb
2024-03-07 15:00         ` Thomas Monjalon
2024-03-11 14:15           ` Jeremy Spewock
2024-03-11 15:43         ` [PATCH v9 " jspewock
2024-03-11 15:43           ` [PATCH v9 1/7] dts: add startup verification and forwarding modes to testpmd shell jspewock
2024-03-11 15:44           ` [PATCH v9 2/7] dts: limit EAL parameters to DPDK apps and add parameters to all apps jspewock
2024-03-11 15:44           ` jspewock [this message]
2024-03-11 15:44           ` [PATCH v9 4/7] dts: add pci addresses to EAL parameters jspewock
2024-03-11 15:44           ` [PATCH v9 5/7] dts: allow configuring MTU of ports jspewock
2024-03-11 15:44           ` [PATCH v9 6/7] dts: add scatter to the yaml schema jspewock
2024-03-11 15:44           ` [PATCH v9 7/7] dts: add pmd_buffer_scatter test suite jspewock
2024-03-15 17:41           ` [PATCH v9 0/7] dts: Port scatter suite over Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240311154405.13269-4-jspewock@iol.unh.edu \
    --to=jspewock@iol.unh.edu \
    --cc=Honnappa.Nagarahalli@arm.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=juraj.linkes@pantheon.tech \
    --cc=paul.szczepanek@arm.com \
    --cc=probb@iol.unh.edu \
    --cc=thomas@monjalon.net \
    --cc=wathsala.vithanage@arm.com \
    --cc=yoan.picchi@foss.arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).