* Re: [PATCH v1] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
@ 2026-04-10 14:35 ` Andrew Bailey
2026-05-08 14:36 ` Andrew Bailey
2026-05-08 15:07 ` Andrew Bailey
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Andrew Bailey @ 2026-04-10 14:35 UTC (permalink / raw)
To: luca.vizzarro, probb, dev; +Cc: dmarx, knimoji
[-- Attachment #1: Type: text/plain, Size: 209 bytes --]
This is an update indicating the status of this patch.
This patch is going to have another version sent to resolve a doc build
failure.
Besides that, the content of this suite is complete and pending review.
[-- Attachment #2: Type: text/html, Size: 266 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
2026-04-10 14:35 ` Andrew Bailey
@ 2026-05-08 15:07 ` Andrew Bailey
2026-05-11 15:46 ` [PATCH v2] " Andrew Bailey
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Andrew Bailey @ 2026-05-08 15:07 UTC (permalink / raw)
To: luca.vizzarro, probb, dev; +Cc: dmarx, knimoji
[-- Attachment #1: Type: text/plain, Size: 37 bytes --]
Recheck-request: github-robot: build
[-- Attachment #2: Type: text/html, Size: 58 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v2] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
2026-04-10 14:35 ` Andrew Bailey
2026-05-08 15:07 ` Andrew Bailey
@ 2026-05-11 15:46 ` Andrew Bailey
2026-07-09 1:47 ` Patrick Robb
2026-09-14 20:00 ` [PATCH v3] " Andrew Bailey
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Andrew Bailey @ 2026-05-11 15:46 UTC (permalink / raw)
To: luca.vizzarro, patrickrobb1997
Cc: dev, ahassick, lylavoie, knimoji, Andrew Bailey
Port over the IP GRE test suite from old DTS to next DTS. This test
suite covers GRE tunneling and checksum offload verification using this
protocol.
Bugzilla ID: 1480
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
doc/api/dts/tests.TestSuite_ip_gre.rst | 8 +
dts/api/testpmd/__init__.py | 23 ++
dts/tests/TestSuite_ip_gre.py | 301 +++++++++++++++++++++++++
3 files changed, 332 insertions(+)
create mode 100644 doc/api/dts/tests.TestSuite_ip_gre.rst
create mode 100644 dts/tests/TestSuite_ip_gre.py
diff --git a/doc/api/dts/tests.TestSuite_ip_gre.rst b/doc/api/dts/tests.TestSuite_ip_gre.rst
new file mode 100644
index 0000000000..e8ce01dc0b
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_ip_gre.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+ip_gre Test Suite
+=================
+
+.. automodule:: tests.TestSuite_ip_gre
+ :members:
+ :show-inheritance:
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..bb5cbd6725 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -951,6 +951,29 @@ def set_flow_control(
f"Testpmd failed to set the {flow_ctrl} in port {port}."
)
+ def set_csum_parse_tunnel(self, port: int, on: bool, verify: bool = True) -> None:
+ """Set parse tunnel on or of in testpmd for a given port.
+
+ Args:
+ port: The ID of the requested port
+ on: set parse tunnel on if `on` is :data:`True`, otherwise off
+ verify: if :data:`True`, the output of the command is scanned to verify that
+ parse tunnel was set successfully
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the command
+ fails to execute.
+
+ """
+ output = self.send_command(f"csum parse-tunnel {'on' if on else 'off'} {port}")
+ if verify and f"Parse tunnel is {'on' if on else'off'}" not in output:
+ self._logger.debug(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+
def show_port_flow_info(self, port: int) -> TestPmdPortFlowCtrl | None:
"""Show port info flow.
diff --git a/dts/tests/TestSuite_ip_gre.py b/dts/tests/TestSuite_ip_gre.py
new file mode 100644
index 0000000000..fc51eef181
--- /dev/null
+++ b/dts/tests/TestSuite_ip_gre.py
@@ -0,0 +1,301 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 University of New Hampshire
+
+"""DPDK IP GRE test suite."""
+
+from scapy.layers.inet import GRE, IP, TCP, UDP
+from scapy.layers.inet6 import IPv6
+from scapy.layers.l2 import Dot1Q, Ether
+from scapy.layers.sctp import SCTP
+from scapy.packet import Packet
+
+from api.capabilities import (
+ NicCapability,
+ requires_nic_capability,
+)
+from api.packet import send_packet_and_capture
+from api.test import verify
+from api.testpmd import TestPmd
+from api.testpmd.config import SimpleForwardingModes
+from api.testpmd.types import (
+ ChecksumOffloadOptions,
+ PacketOffloadFlag,
+ RtePTypes,
+ TestPmdVerbosePacket,
+)
+from framework.test_suite import TestSuite, func_test
+
+SRC_ID = "FF:FF:FF:FF:FF:FF"
+
+
+class TestIpGre(TestSuite):
+ """IP GRE test suite."""
+
+ def _check_for_matching_packet(
+ self, output: list[TestPmdVerbosePacket], flags: RtePTypes
+ ) -> bool:
+ """Returns :data:`True` if the packet in verbose output contains all specified flags."""
+ for packet in output:
+ if packet.src_mac == SRC_ID:
+ if flags not in packet.hw_ptype and flags not in packet.sw_ptype:
+ return False
+ return True
+
+ def _send_packet_and_verify_flags(
+ self, expected_flag: RtePTypes, packet: Packet, testpmd: TestPmd
+ ) -> None:
+ """Sends a packet to the DUT and verifies the verbose ptype flags."""
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop(verify=True))
+ valid = self._check_for_matching_packet(output=verbose_output, flags=expected_flag)
+ verify(valid, f"Packet type flag did not match the expected flag: {expected_flag}.")
+
+ def _setup_session(
+ self, testpmd: TestPmd, expected_flags: list[RtePTypes], packet_list=list[Packet]
+ ) -> None:
+ """Sets the forwarding and verbose mode of each test case interactive shell session."""
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ testpmd.set_verbose(level=1)
+ for i in range(0, len(packet_list)):
+ testpmd.start(verify=True)
+ self._send_packet_and_verify_flags(
+ expected_flag=expected_flags[i], packet=packet_list[i], testpmd=testpmd
+ )
+
+ def _send_packet_and_verify_checksum(
+ self, packet: Packet, good_L4: bool, good_IP: bool, testpmd: TestPmd
+ ) -> None:
+ """Send packet and verify verbose output matches expected output."""
+ testpmd.start()
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop())
+ is_IP = is_L4 = None
+ for testpmd_packet in verbose_output:
+ if testpmd_packet.src_mac == SRC_ID:
+ is_IP = PacketOffloadFlag.RTE_MBUF_F_RX_IP_CKSUM_GOOD in testpmd_packet.ol_flags
+ is_L4 = PacketOffloadFlag.RTE_MBUF_F_RX_L4_CKSUM_GOOD in testpmd_packet.ol_flags
+ verify(
+ is_IP is not None and is_L4 is not None,
+ "Test packet was dropped when it should have been received.",
+ )
+ verify(is_L4 == good_L4, "Layer 4 checksum flag did not match expected checksum flag.")
+ verify(is_IP == good_IP, "IP checksum flag did not match expected checksum flag.")
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip4_pkt_detect(self) -> None:
+ """GRE IP4 packet send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ self._setup_session(testpmd=testpmd, expected_flags=flags, packet_list=packets)
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip4_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and IPv4 inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ self._setup_session(testpmd=testpmd, expected_flags=flags, packet_list=packets)
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip6_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_VLAN
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ self._setup_session(testpmd=testpmd, expected_flags=flags, packet_list=packets)
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_TCP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_UDP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_SCTP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_checksum_offload(self) -> None:
+ """GRE checksum offload test.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Alter checksum of each packet.
+ * Send packets to the testpmd application.
+
+ Verify:
+ * All packets were received with the expected checksum flags.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP(chksum=0x0) / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP(chksum=0x0) / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(chksum=0x0),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(chksum=0xFFFF),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(chksum=0x0),
+ ]
+ good_l4_ip = [
+ (True, True),
+ (True, False),
+ (False, True),
+ (False, True),
+ (False, True),
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.csum)
+ testpmd.csum_set_hw(
+ layers=ChecksumOffloadOptions.ip
+ | ChecksumOffloadOptions.udp
+ | ChecksumOffloadOptions.outer_ip
+ | ChecksumOffloadOptions.sctp
+ | ChecksumOffloadOptions.tcp,
+ port_id=0,
+ )
+ testpmd.set_csum_parse_tunnel(port=0, on=True)
+ testpmd.set_verbose(1)
+ testpmd.start_all_ports()
+ testpmd.start()
+ for i in range(len(packets)):
+ self._send_packet_and_verify_checksum(
+ packets[i],
+ good_l4_ip[i][0],
+ good_l4_ip[i][1],
+ testpmd,
+ )
--
2.50.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v2] dts: add ipgre test suite
2026-05-11 15:46 ` [PATCH v2] " Andrew Bailey
@ 2026-07-09 1:47 ` Patrick Robb
0 siblings, 0 replies; 10+ messages in thread
From: Patrick Robb @ 2026-07-09 1:47 UTC (permalink / raw)
To: Andrew Bailey; +Cc: luca.vizzarro, dev, ahassick, lylavoie, knimoji
[-- Attachment #1: Type: text/plain, Size: 7621 bytes --]
On Mon, May 11, 2026 at 11:46 AM Andrew Bailey <abailey@iol.unh.edu> wrote:
> Port over the IP GRE test suite from old DTS to next DTS. This test
> suite covers GRE tunneling and checksum offload verification using this
> protocol.
>
> Bugzilla ID: 1480
>
> Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
> ---
> doc/api/dts/tests.TestSuite_ip_gre.rst | 8 +
> dts/api/testpmd/__init__.py | 23 ++
> dts/tests/TestSuite_ip_gre.py | 301 +++++++++++++++++++++++++
> 3 files changed, 332 insertions(+)
> create mode 100644 doc/api/dts/tests.TestSuite_ip_gre.rst
> create mode 100644 dts/tests/TestSuite_ip_gre.py
>
> diff --git a/doc/api/dts/tests.TestSuite_ip_gre.rst
> b/doc/api/dts/tests.TestSuite_ip_gre.rst
> new file mode 100644
> index 0000000000..e8ce01dc0b
> --- /dev/null
> +++ b/doc/api/dts/tests.TestSuite_ip_gre.rst
> @@ -0,0 +1,8 @@
> +.. SPDX-License-Identifier: BSD-3-Clause
> +
> +ip_gre Test Suite
> +=================
> +
> +.. automodule:: tests.TestSuite_ip_gre
> + :members:
> + :show-inheritance:
> diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
> index e9187440bb..bb5cbd6725 100644
> --- a/dts/api/testpmd/__init__.py
> +++ b/dts/api/testpmd/__init__.py
> @@ -951,6 +951,29 @@ def set_flow_control(
> f"Testpmd failed to set the {flow_ctrl} in port
> {port}."
> )
>
> + def set_csum_parse_tunnel(self, port: int, on: bool, verify: bool =
> True) -> None:
> + """Set parse tunnel on or of in testpmd for a given port.
>
Should be “off” not “of”
> +
> + Args:
> + port: The ID of the requested port
> + on: set parse tunnel on if `on` is :data:`True`, otherwise off
> + verify: if :data:`True`, the output of the command is scanned
> to verify that
> + parse tunnel was set successfully
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True`
> and the command
> + fails to execute.
> +
> + """
> + output = self.send_command(f"csum parse-tunnel {'on' if on else
> 'off'} {port}")
> + if verify and f"Parse tunnel is {'on' if on else'off'}" not in
> output:
>
Missing a space after "else".
> + self._logger.debug(
> + f"Testpmd failed to set csum parse-tunnel {'on' if on
> else 'off'} in port {port}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set csum parse-tunnel {'on' if on
> else 'off'} in port {port}"
> + )
> +
> def show_port_flow_info(self, port: int) -> TestPmdPortFlowCtrl |
> None:
> """Show port info flow.
>
> diff --git a/dts/tests/TestSuite_ip_gre.py b/dts/tests/TestSuite_ip_gre.py
> new file mode 100644
> index 0000000000..fc51eef181
> --- /dev/null
> +++ b/dts/tests/TestSuite_ip_gre.py
> @@ -0,0 +1,301 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2026 University of New Hampshire
> +
> +"""DPDK IP GRE test suite."""
> +
> +from scapy.layers.inet import GRE, IP, TCP, UDP
> +from scapy.layers.inet6 import IPv6
> +from scapy.layers.l2 import Dot1Q, Ether
> +from scapy.layers.sctp import SCTP
> +from scapy.packet import Packet
> +
> +from api.capabilities import (
> + NicCapability,
> + requires_nic_capability,
> +)
> +from api.packet import send_packet_and_capture
> +from api.test import verify
> +from api.testpmd import TestPmd
> +from api.testpmd.config import SimpleForwardingModes
> +from api.testpmd.types import (
> + ChecksumOffloadOptions,
> + PacketOffloadFlag,
> + RtePTypes,
> + TestPmdVerbosePacket,
> +)
> +from framework.test_suite import TestSuite, func_test
> +
> +SRC_ID = "FF:FF:FF:FF:FF:FF"
>
Why did you choose the broadcast address instead of a "normal" address?
Just want to hear your reasoning.
> +
> +
> +class TestIpGre(TestSuite):
> + """IP GRE test suite."""
> +
> + def _check_for_matching_packet(
> + self, output: list[TestPmdVerbosePacket], flags: RtePTypes
> + ) -> bool:
> + """Returns :data:`True` if the packet in verbose output contains
> all specified flags."""
> + for packet in output:
> + if packet.src_mac == SRC_ID:
> + if flags not in packet.hw_ptype and flags not in
> packet.sw_ptype:
> + return False
> + return True
> +
> + def _send_packet_and_verify_flags(
> + self, expected_flag: RtePTypes, packet: Packet, testpmd: TestPmd
> + ) -> None:
> + """Sends a packet to the DUT and verifies the verbose ptype
> flags."""
> + send_packet_and_capture(packet=packet)
> + verbose_output =
> testpmd.extract_verbose_output(testpmd.stop(verify=True))
> + valid = self._check_for_matching_packet(output=verbose_output,
> flags=expected_flag)
> + verify(valid, f"Packet type flag did not match the expected flag:
> {expected_flag}.")
Is it worth logging a packet transmission issue vs a flag setting / flag
processing issue in different ways? And re the previous 2 functions if
verbose_output is None will _check_for_matching_packet return True in
error? Just checking that this is sound.
> +
> + def _setup_session(
> + self, testpmd: TestPmd, expected_flags: list[RtePTypes],
> packet_list=list[Packet]
> + ) -> None:
> + """Sets the forwarding and verbose mode of each test case
> interactive shell session."""
> + testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
> + testpmd.set_verbose(level=1)
> + for i in range(0, len(packet_list)):
> + testpmd.start(verify=True)
> + self._send_packet_and_verify_flags(
> + expected_flag=expected_flags[i], packet=packet_list[i],
> testpmd=testpmd
> + )
>
If expected_flags and packet_list are related lists of the same length, is
it better if we use 1 list of tuples [(expected flag, packet)]?
+
> + def _send_packet_and_verify_checksum(
> + self, packet: Packet, good_L4: bool, good_IP: bool, testpmd:
> TestPmd
>
If we are going to say good_L4 can we say good_L3 or does that reduce
clarity to you? Figure we should stay consistent.
> + ) -> None:
> + """Send packet and verify verbose output matches expected
> output."""
> + testpmd.start()
> + send_packet_and_capture(packet=packet)
> + verbose_output = testpmd.extract_verbose_output(testpmd.stop())
> + is_IP = is_L4 = None
> + for testpmd_packet in verbose_output:
> + if testpmd_packet.src_mac == SRC_ID:
> + is_IP = PacketOffloadFlag.RTE_MBUF_F_RX_IP_CKSUM_GOOD in
> testpmd_packet.ol_flags
> + is_L4 = PacketOffloadFlag.RTE_MBUF_F_RX_L4_CKSUM_GOOD in
> testpmd_packet.ol_flags
>
is_IP -> good_L3_checksum? If the meaning of the is_IP variable is that
there is an IP layer, I disagree with the name because it is possible for
there to be an IP layer and a bad checksum. I do see below the verify logic
is for if the checksum is correct.
Do we have any logic here to verify we are acting on the correct packet,
given that it may not be a quiet wire?
> + verify(
> + is_IP is not None and is_L4 is not None,
> + "Test packet was dropped when it should have been received.",
>
Reviewed-by: Patrick Robb <patrickrobb1997@gmail.com>
[-- Attachment #2: Type: text/html, Size: 10362 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
` (2 preceding siblings ...)
2026-05-11 15:46 ` [PATCH v2] " Andrew Bailey
@ 2026-09-14 20:00 ` Andrew Bailey
2026-09-28 18:24 ` [PATCH v4] " Andrew Bailey
2026-09-28 19:22 ` [PATCH v5] " Andrew Bailey
5 siblings, 0 replies; 10+ messages in thread
From: Andrew Bailey @ 2026-09-14 20:00 UTC (permalink / raw)
To: dev, luca.vizzarro, patrickrobb1997
Cc: knimoji, lylavoie, dladd, Andrew Bailey
Port over the IP GRE test suite from old DTS to next DTS. This test
suite covers GRE tunneling and checksum offload verification using this
protocol.
Bugzilla ID: 1480
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
doc/api/dts/tests.TestSuite_ip_gre.rst | 8 +
dts/api/testpmd/__init__.py | 23 ++
dts/tests/TestSuite_ip_gre.py | 312 +++++++++++++++++++++++++
3 files changed, 343 insertions(+)
create mode 100644 doc/api/dts/tests.TestSuite_ip_gre.rst
create mode 100644 dts/tests/TestSuite_ip_gre.py
diff --git a/doc/api/dts/tests.TestSuite_ip_gre.rst b/doc/api/dts/tests.TestSuite_ip_gre.rst
new file mode 100644
index 0000000000..e8ce01dc0b
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_ip_gre.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+ip_gre Test Suite
+=================
+
+.. automodule:: tests.TestSuite_ip_gre
+ :members:
+ :show-inheritance:
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 7118f9470f..0466777b5f 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -957,6 +957,29 @@ def set_flow_control(
f"Testpmd failed to set the {flow_ctrl} in port {port}."
)
+ def set_csum_parse_tunnel(self, port: int, on: bool, verify: bool = True) -> None:
+ """Set parse tunnel on or off in testpmd for a given port.
+
+ Args:
+ port: The ID of the requested port
+ on: set parse tunnel on if `on` is :data:`True`, otherwise off
+ verify: if :data:`True`, the output of the command is scanned to verify that
+ parse tunnel was set successfully
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the command
+ fails to execute.
+
+ """
+ output = self.send_command(f"csum parse-tunnel {'on' if on else 'off'} {port}")
+ if verify and f"Parse tunnel is {'on' if on else 'off'}" not in output:
+ self._logger.debug(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+
def show_port_flow_info(self, port: int) -> TestPmdPortFlowCtrl | None:
"""Show port info flow.
diff --git a/dts/tests/TestSuite_ip_gre.py b/dts/tests/TestSuite_ip_gre.py
new file mode 100644
index 0000000000..be2d594931
--- /dev/null
+++ b/dts/tests/TestSuite_ip_gre.py
@@ -0,0 +1,312 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 University of New Hampshire
+
+"""DPDK IP GRE test suite."""
+
+from scapy.layers.inet import GRE, IP, TCP, UDP
+from scapy.layers.inet6 import IPv6
+from scapy.layers.l2 import Dot1Q, Ether
+from scapy.layers.sctp import SCTP
+from scapy.packet import Packet
+
+from api.capabilities import (
+ NicCapability,
+ requires_nic_capability,
+)
+from api.packet import send_packet_and_capture
+from api.test import verify
+from api.testpmd import TestPmd
+from api.testpmd.config import SimpleForwardingModes
+from api.testpmd.types import (
+ ChecksumOffloadOptions,
+ PacketOffloadFlag,
+ RtePTypes,
+ TestPmdVerbosePacket,
+)
+from framework.test_suite import TestSuite, func_test
+
+SRC_ID = "00:00:10:00:00:00"
+
+
+class TestIpGre(TestSuite):
+ """IP GRE test suite."""
+
+ def _check_for_matching_packet(
+ self, output: list[TestPmdVerbosePacket], flags: RtePTypes
+ ) -> bool:
+ """Returns :data:`True` if the packet in verbose output contains all specified flags."""
+ if output == []:
+ return False
+ for packet in output:
+ if packet.src_mac == SRC_ID and flags & (packet.hw_ptype | packet.sw_ptype) != flags:
+ return False
+ return True
+
+ def _send_packet_and_verify_flags(
+ self, expected_flag: RtePTypes, packet: Packet, testpmd: TestPmd
+ ) -> None:
+ """Sends a packet to the DUT and verifies the verbose ptype flags."""
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop(verify=True))
+ valid = self._check_for_matching_packet(output=verbose_output, flags=expected_flag)
+ verify(valid, f"Packet type flag did not match the expected flag: {expected_flag}.")
+
+ def _setup_session(
+ self, testpmd: TestPmd, expected_and_packets: tuple[list[RtePTypes], list[Packet]]
+ ) -> None:
+ """Sets the forwarding and verbose mode of each test case interactive shell session."""
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ testpmd.set_verbose(level=1)
+ expected_flags, packet_list = expected_and_packets
+
+ for expected_flag, packet in zip(expected_flags, packet_list):
+ testpmd.start(verify=True)
+ self._send_packet_and_verify_flags(
+ expected_flag=expected_flag, packet=packet, testpmd=testpmd
+ )
+
+ def _send_packet_and_verify_checksum(
+ self, packet: Packet, good_L4: bool, good_L3: bool, testpmd: TestPmd
+ ) -> None:
+ """Send packet and verify verbose output matches expected output."""
+ testpmd.start()
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop())
+ correct_L3_cksum = correct_L4 = None
+ for testpmd_packet in verbose_output:
+ if testpmd_packet.src_mac == SRC_ID:
+ correct_L3_cksum = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_IP_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ correct_L4 = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_L4_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ verify(
+ correct_L3_cksum is not None and correct_L4 is not None,
+ "Test packet was dropped when it should have been received.",
+ )
+ verify(correct_L4 == good_L4, "Layer 4 checksum flag did not match expected checksum flag.")
+ verify(
+ correct_L3_cksum == good_L3,
+ "Layer 3 checksum flag did not match expected checksum flag.",
+ )
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip4_pkt_detect(self) -> None:
+ """GRE IP4 packet send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip4_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and IPv4 inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip6_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_TCP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_UDP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_SCTP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_checksum_offload(self) -> None:
+ """GRE checksum offload test.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Alter checksum of each packet.
+ * Send packets to the testpmd application.
+
+ Verify:
+ * All packets were received with the expected checksum flags.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP(chksum=0x0) / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(chksum=0x0),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(chksum=0xFFFF),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(chksum=0x0),
+ ]
+ good_l4_l3 = [
+ (False, True),
+ (False, True),
+ (False, True),
+ (False, True),
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.csum)
+ testpmd.set_verbose(1)
+ testpmd.csum_set_hw(
+ layers=ChecksumOffloadOptions.ip
+ | ChecksumOffloadOptions.udp
+ | ChecksumOffloadOptions.sctp
+ | ChecksumOffloadOptions.outer_ip
+ | ChecksumOffloadOptions.tcp,
+ port_id=0,
+ )
+ testpmd.set_csum_parse_tunnel(port=0, on=True)
+ testpmd.start_all_ports()
+ testpmd.start()
+ for i in range(len(packets)):
+ self._send_packet_and_verify_checksum(
+ packets[i],
+ good_l4_l3[i][0],
+ good_l4_l3[i][1],
+ testpmd,
+ )
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v4] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
` (3 preceding siblings ...)
2026-09-14 20:00 ` [PATCH v3] " Andrew Bailey
@ 2026-09-28 18:24 ` Andrew Bailey
2026-09-28 19:22 ` [PATCH v5] " Andrew Bailey
5 siblings, 0 replies; 10+ messages in thread
From: Andrew Bailey @ 2026-09-28 18:24 UTC (permalink / raw)
To: dev, luca.vizzarro, patrickrobb1997
Cc: knimoji, lylavoie, dladd, Andrew Bailey
Port over the IP GRE test suite from old DTS to next DTS. This test
suite covers GRE tunneling and checksum offload verification using this
protocol.
Bugzilla ID: 1480
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
doc/api/dts/tests.TestSuite_ip_gre.rst | 8 +
dts/api/testpmd/__init__.py | 23 ++
dts/tests/TestSuite_ip_gre.py | 313 +++++++++++++++++++++++++
3 files changed, 344 insertions(+)
create mode 100644 doc/api/dts/tests.TestSuite_ip_gre.rst
create mode 100644 dts/tests/TestSuite_ip_gre.py
diff --git a/doc/api/dts/tests.TestSuite_ip_gre.rst b/doc/api/dts/tests.TestSuite_ip_gre.rst
new file mode 100644
index 0000000000..e8ce01dc0b
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_ip_gre.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+ip_gre Test Suite
+=================
+
+.. automodule:: tests.TestSuite_ip_gre
+ :members:
+ :show-inheritance:
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 7118f9470f..0466777b5f 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -957,6 +957,29 @@ def set_flow_control(
f"Testpmd failed to set the {flow_ctrl} in port {port}."
)
+ def set_csum_parse_tunnel(self, port: int, on: bool, verify: bool = True) -> None:
+ """Set parse tunnel on or off in testpmd for a given port.
+
+ Args:
+ port: The ID of the requested port
+ on: set parse tunnel on if `on` is :data:`True`, otherwise off
+ verify: if :data:`True`, the output of the command is scanned to verify that
+ parse tunnel was set successfully
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the command
+ fails to execute.
+
+ """
+ output = self.send_command(f"csum parse-tunnel {'on' if on else 'off'} {port}")
+ if verify and f"Parse tunnel is {'on' if on else 'off'}" not in output:
+ self._logger.debug(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+
def show_port_flow_info(self, port: int) -> TestPmdPortFlowCtrl | None:
"""Show port info flow.
diff --git a/dts/tests/TestSuite_ip_gre.py b/dts/tests/TestSuite_ip_gre.py
new file mode 100644
index 0000000000..984f48a0be
--- /dev/null
+++ b/dts/tests/TestSuite_ip_gre.py
@@ -0,0 +1,313 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 University of New Hampshire
+
+"""DPDK IP GRE test suite."""
+
+from scapy.layers.inet import GRE, IP, TCP, UDP
+from scapy.layers.inet6 import IPv6
+from scapy.layers.l2 import Dot1Q, Ether
+from scapy.layers.sctp import SCTP
+from scapy.packet import Packet
+
+from api.capabilities import (
+ NicCapability,
+ requires_nic_capability,
+)
+from api.packet import send_packet_and_capture
+from api.test import verify
+from api.testpmd import TestPmd
+from api.testpmd.config import SimpleForwardingModes
+from api.testpmd.types import (
+ ChecksumOffloadOptions,
+ PacketOffloadFlag,
+ RtePTypes,
+ TestPmdVerbosePacket,
+)
+from framework.test_suite import TestSuite, func_test
+
+SRC_ID = "00:00:10:00:00:00"
+
+
+class TestIpGre(TestSuite):
+ """IP GRE test suite."""
+
+ def _check_for_matching_packet(
+ self, output: list[TestPmdVerbosePacket], flags: RtePTypes
+ ) -> bool:
+ """Returns :data:`True` if the packet in verbose output contains all specified flags."""
+ for packet in output:
+ if packet.src_mac == SRC_ID and flags & (packet.hw_ptype | packet.sw_ptype) != flags:
+ return False
+ elif packet.src_mac == SRC_ID:
+ return True
+
+ return False
+
+ def _send_packet_and_verify_flags(
+ self, expected_flag: RtePTypes, packet: Packet, testpmd: TestPmd
+ ) -> None:
+ """Sends a packet to the DUT and verifies the verbose ptype flags."""
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop(verify=True))
+ valid = self._check_for_matching_packet(output=verbose_output, flags=expected_flag)
+ verify(valid, f"Packet type flag did not match the expected flag: {expected_flag}.")
+
+ def _setup_session(
+ self, testpmd: TestPmd, expected_and_packets: tuple[list[RtePTypes], list[Packet]]
+ ) -> None:
+ """Sets the forwarding and verbose mode of each test case interactive shell session."""
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ testpmd.set_verbose(level=1)
+ expected_flags, packet_list = expected_and_packets
+
+ for expected_flag, packet in zip(expected_flags, packet_list):
+ testpmd.start(verify=True)
+ self._send_packet_and_verify_flags(
+ expected_flag=expected_flag, packet=packet, testpmd=testpmd
+ )
+
+ def _send_packet_and_verify_checksum(
+ self, packet: Packet, good_L4: bool, good_L3: bool, testpmd: TestPmd
+ ) -> None:
+ """Send packet and verify verbose output matches expected output."""
+ testpmd.start()
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop())
+ correct_L3_cksum = correct_L4 = None
+ for testpmd_packet in verbose_output:
+ if testpmd_packet.src_mac == SRC_ID:
+ correct_L3_cksum = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_IP_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ correct_L4 = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_L4_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ verify(
+ correct_L3_cksum is not None and correct_L4 is not None,
+ "Test packet was dropped when it should have been received.",
+ )
+ verify(correct_L4 == good_L4, "Layer 4 checksum flag did not match expected checksum flag.")
+ verify(
+ correct_L3_cksum == good_L3,
+ "Layer 3 checksum flag did not match expected checksum flag.",
+ )
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip4_pkt_detect(self) -> None:
+ """GRE IP4 packet send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip4_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and IPv4 inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip6_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_TCP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_UDP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_SCTP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_checksum_offload(self) -> None:
+ """GRE checksum offload test.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Alter checksum of each packet.
+ * Send packets to the testpmd application.
+
+ Verify:
+ * All packets were received with the expected checksum flags.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP(chksum=0x0) / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(chksum=0x0),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(chksum=0xFFFF),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(chksum=0x0),
+ ]
+ good_l4_l3 = [
+ (False, True),
+ (False, True),
+ (False, True),
+ (False, True),
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.csum)
+ testpmd.set_verbose(1)
+ testpmd.csum_set_hw(
+ layers=ChecksumOffloadOptions.ip
+ | ChecksumOffloadOptions.udp
+ | ChecksumOffloadOptions.sctp
+ | ChecksumOffloadOptions.outer_ip
+ | ChecksumOffloadOptions.tcp,
+ port_id=0,
+ )
+ testpmd.set_csum_parse_tunnel(port=0, on=True)
+ testpmd.start_all_ports()
+ testpmd.start()
+ for i in range(len(packets)):
+ self._send_packet_and_verify_checksum(
+ packets[i],
+ good_l4_l3[i][0],
+ good_l4_l3[i][1],
+ testpmd,
+ )
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v5] dts: add ipgre test suite
2026-03-27 18:02 [PATCH v1] dts: add ipgre test suite Andrew Bailey
` (4 preceding siblings ...)
2026-09-28 18:24 ` [PATCH v4] " Andrew Bailey
@ 2026-09-28 19:22 ` Andrew Bailey
2026-09-28 19:49 ` Andrew Bailey
5 siblings, 1 reply; 10+ messages in thread
From: Andrew Bailey @ 2026-09-28 19:22 UTC (permalink / raw)
To: dev, luca.vizzarro, patrickrobb1997
Cc: knimoji, lylavoie, dladd, Andrew Bailey
Port over the IP GRE test suite from old DTS to next DTS. This test
suite covers GRE tunneling and checksum offload verification using this
protocol.
Bugzilla ID: 1480
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
doc/api/dts/tests.TestSuite_ip_gre.rst | 8 +
dts/api/testpmd/__init__.py | 23 ++
dts/tests/TestSuite_ip_gre.py | 310 +++++++++++++++++++++++++
3 files changed, 341 insertions(+)
create mode 100644 doc/api/dts/tests.TestSuite_ip_gre.rst
create mode 100644 dts/tests/TestSuite_ip_gre.py
diff --git a/doc/api/dts/tests.TestSuite_ip_gre.rst b/doc/api/dts/tests.TestSuite_ip_gre.rst
new file mode 100644
index 0000000000..e8ce01dc0b
--- /dev/null
+++ b/doc/api/dts/tests.TestSuite_ip_gre.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+ip_gre Test Suite
+=================
+
+.. automodule:: tests.TestSuite_ip_gre
+ :members:
+ :show-inheritance:
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 7118f9470f..0466777b5f 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -957,6 +957,29 @@ def set_flow_control(
f"Testpmd failed to set the {flow_ctrl} in port {port}."
)
+ def set_csum_parse_tunnel(self, port: int, on: bool, verify: bool = True) -> None:
+ """Set parse tunnel on or off in testpmd for a given port.
+
+ Args:
+ port: The ID of the requested port
+ on: set parse tunnel on if `on` is :data:`True`, otherwise off
+ verify: if :data:`True`, the output of the command is scanned to verify that
+ parse tunnel was set successfully
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the command
+ fails to execute.
+
+ """
+ output = self.send_command(f"csum parse-tunnel {'on' if on else 'off'} {port}")
+ if verify and f"Parse tunnel is {'on' if on else 'off'}" not in output:
+ self._logger.debug(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set csum parse-tunnel {'on' if on else 'off'} in port {port}"
+ )
+
def show_port_flow_info(self, port: int) -> TestPmdPortFlowCtrl | None:
"""Show port info flow.
diff --git a/dts/tests/TestSuite_ip_gre.py b/dts/tests/TestSuite_ip_gre.py
new file mode 100644
index 0000000000..c113b25130
--- /dev/null
+++ b/dts/tests/TestSuite_ip_gre.py
@@ -0,0 +1,310 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 University of New Hampshire
+
+"""DPDK IP GRE test suite."""
+
+from scapy.layers.inet import GRE, IP, TCP, UDP
+from scapy.layers.inet6 import IPv6
+from scapy.layers.l2 import Dot1Q, Ether
+from scapy.layers.sctp import SCTP
+from scapy.packet import Packet
+
+from api.capabilities import (
+ NicCapability,
+ requires_nic_capability,
+)
+from api.packet import send_packet_and_capture
+from api.test import verify
+from api.testpmd import TestPmd
+from api.testpmd.config import SimpleForwardingModes
+from api.testpmd.types import (
+ ChecksumOffloadOptions,
+ PacketOffloadFlag,
+ RtePTypes,
+ TestPmdVerbosePacket,
+)
+from framework.test_suite import TestSuite, func_test
+
+SRC_ID = "00:00:10:00:00:00"
+
+
+class TestIpGre(TestSuite):
+ """IP GRE test suite."""
+
+ def _check_for_matching_packet(
+ self, output: list[TestPmdVerbosePacket], flags: RtePTypes
+ ) -> bool:
+ """Returns :data:`True` if the packet in verbose output contains all specified flags."""
+ for packet in output:
+ if packet.src_mac == SRC_ID and flags & (packet.hw_ptype | packet.sw_ptype) == flags:
+ return True
+ return False
+
+ def _send_packet_and_verify_flags(
+ self, expected_flag: RtePTypes, packet: Packet, testpmd: TestPmd
+ ) -> None:
+ """Sends a packet to the DUT and verifies the verbose ptype flags."""
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop(verify=True))
+ valid = self._check_for_matching_packet(output=verbose_output, flags=expected_flag)
+ verify(valid, f"Packet type flag did not match the expected flag: {expected_flag}.")
+
+ def _setup_session(
+ self, testpmd: TestPmd, expected_and_packets: tuple[list[RtePTypes], list[Packet]]
+ ) -> None:
+ """Sets the forwarding and verbose mode of each test case interactive shell session."""
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ testpmd.set_verbose(level=1)
+ expected_flags, packet_list = expected_and_packets
+
+ for expected_flag, packet in zip(expected_flags, packet_list):
+ testpmd.start(verify=True)
+ self._send_packet_and_verify_flags(
+ expected_flag=expected_flag, packet=packet, testpmd=testpmd
+ )
+
+ def _send_packet_and_verify_checksum(
+ self, packet: Packet, good_L4: bool, good_L3: bool, testpmd: TestPmd
+ ) -> None:
+ """Send packet and verify verbose output matches expected output."""
+ testpmd.start()
+ send_packet_and_capture(packet=packet)
+ verbose_output = testpmd.extract_verbose_output(testpmd.stop())
+ correct_L3_cksum = correct_L4 = None
+ for testpmd_packet in verbose_output:
+ if testpmd_packet.src_mac == SRC_ID:
+ correct_L3_cksum = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_IP_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ correct_L4 = (
+ PacketOffloadFlag.RTE_MBUF_F_RX_L4_CKSUM_GOOD in testpmd_packet.ol_flags
+ )
+ verify(
+ correct_L3_cksum is not None and correct_L4 is not None,
+ "Test packet was dropped when it should have been received.",
+ )
+ verify(correct_L4 == good_L4, "Layer 4 checksum flag did not match expected checksum flag.")
+ verify(
+ correct_L3_cksum == good_L3,
+ "Layer 3 checksum flag did not match expected checksum flag.",
+ )
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip4_pkt_detect(self) -> None:
+ """GRE IP4 packet send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IP() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV4
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip4_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and IPv4 inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IP() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IP() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV4
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_ip6_outer_ip6_inner_pkt_detect(self) -> None:
+ """GRE IPv6 outer and inner send and detect.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Send them to the testpmd application.
+
+ Verify:
+ * All packets were received.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / IPv6() / GRE() / IPv6() / SCTP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / UDP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / TCP(),
+ Ether(src=SRC_ID) / Dot1Q() / IPv6() / GRE() / IPv6() / SCTP(),
+ ]
+ flags = [
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_UDP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_TCP,
+ RtePTypes.L2_ETHER_QINQ
+ | RtePTypes.L3_IPV6
+ | RtePTypes.TUNNEL_GRE
+ | RtePTypes.INNER_L3_IPV6
+ | RtePTypes.INNER_L4_SCTP,
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
+ self._setup_session(testpmd=testpmd, expected_and_packets=(flags, packets))
+
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_IPV4_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_TCP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_UDP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_SCTP_CKSUM)
+ @requires_nic_capability(NicCapability.PORT_TX_OFFLOAD_GRE_TNL_TSO)
+ @func_test
+ def gre_checksum_offload(self) -> None:
+ """GRE checksum offload test.
+
+ Steps:
+ * Craft packets using GRE tunneling.
+ * Alter checksum of each packet.
+ * Send packets to the testpmd application.
+
+ Verify:
+ * All packets were received with the expected checksum flags.
+ """
+ packets = [
+ Ether(src=SRC_ID) / IP(chksum=0x0) / GRE() / IP() / TCP(),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / TCP(chksum=0x0),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / UDP(chksum=0xFFFF),
+ Ether(src=SRC_ID) / IP() / GRE() / IP() / SCTP(chksum=0x0),
+ ]
+ good_l4_l3 = [
+ (False, True),
+ (False, True),
+ (False, True),
+ (False, True),
+ ]
+ with TestPmd() as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.csum)
+ testpmd.set_verbose(1)
+ testpmd.csum_set_hw(
+ layers=ChecksumOffloadOptions.ip
+ | ChecksumOffloadOptions.udp
+ | ChecksumOffloadOptions.sctp
+ | ChecksumOffloadOptions.outer_ip
+ | ChecksumOffloadOptions.tcp,
+ port_id=0,
+ )
+ testpmd.set_csum_parse_tunnel(port=0, on=True)
+ testpmd.start_all_ports()
+ testpmd.start()
+ for i in range(len(packets)):
+ self._send_packet_and_verify_checksum(
+ packets[i],
+ good_l4_l3[i][0],
+ good_l4_l3[i][1],
+ testpmd,
+ )
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread