* [RFC v1 1/3] dts: add UDP tunnel command to testpmd shell
2024-07-25 16:23 [RFC v1 0/3] VXLAN-GPE test suite Dean Marx
@ 2024-07-25 16:23 ` Dean Marx
2024-07-26 20:18 ` Jeremy Spewock
2024-07-25 16:23 ` [RFC v1 2/3] dts: VXLAN gpe support test suite Dean Marx
2024-07-25 16:23 ` [RFC v1 3/3] dts: conf schema VXLAN gpe support Dean Marx
2 siblings, 1 reply; 6+ messages in thread
From: Dean Marx @ 2024-07-25 16:23 UTC (permalink / raw)
To: probb, npratte, jspewock, luca.vizzarro, yoan.picchi,
Honnappa.Nagarahalli, paul.szczepanek, juraj.linkes
Cc: dev, Dean Marx
add udp_tunnel_port command to testpmd shell class,
also ports over set verbose method from vlan suite
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/framework/remote_session/testpmd_shell.py | 51 ++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
index eda6eb320f..26114091d6 100644
--- a/dts/framework/remote_session/testpmd_shell.py
+++ b/dts/framework/remote_session/testpmd_shell.py
@@ -804,7 +804,56 @@ def show_port_stats(self, port_id: int) -> TestPmdPortStats:
return TestPmdPortStats.parse(output)
- def _close(self) -> None:
+ def set_verbose(self, level: int, verify: bool = True):
+ """Set debug verbosity level.
+
+ Args:
+ level: 0 - silent except for error
+ 1 - fully verbose except for Tx packets
+ 2 - fully verbose except for Rx packets
+ >2 - fully verbose
+ verify: If :data:`True` the command output will be scanned to verify that verbose level
+ is properly set. Defaults to :data:`True`.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and verbose level
+ is not correctly set.
+ """
+ verbose_output = self.send_command(f"set verbose {level}")
+ if verify:
+ if "Change verbose level" not in verbose_output:
+ self._logger.debug(f"Failed to set verbose level to {level}: \n{verbose_output}")
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set verbose level to {level}."
+ )
+
+ def udp_tunnel_port(
+ self, port_id: int, add: bool, udp_port: int, protocol: str, verify: bool = True
+ ):
+ """Configures a UDP tunnel on the specified port, for the specified protocol.
+
+ Args:
+ port_id: ID of the port to configure tunnel on.
+ add: If :data:`True`, adds tunnel, otherwise removes tunnel.
+ udp_port: ID of the UDP port to configure tunnel on.
+ protocol: Name of tunnelling protocol to use; options are vxlan, geneve, ecpri
+ verify: If :data:`True`, checks the output of the command to verify that
+ no errors were thrown.
+
+ Raises:
+ InteractiveCommandExecutionError: If verify is :data:`True` and command
+ output shows an error.
+ """
+ action = "add" if add else "rm"
+ cmd_output = self.send_command(
+ f"port config {port_id} udp_tunnel_port {action} {protocol} {udp_port}"
+ )
+ if verify:
+ if "Operation not supported" in cmd_output or "Bad arguments" in cmd_output:
+ self._logger.debug(f"Failed to set UDP tunnel: \n{cmd_output}")
+ raise InteractiveCommandExecutionError(f"Failed to set UDP tunnel: \n{cmd_output}")
+
+ def close(self) -> None:
"""Overrides :meth:`~.interactive_shell.close`."""
self.stop()
self.send_command("quit", "Bye...")
--
2.44.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC v1 1/3] dts: add UDP tunnel command to testpmd shell
2024-07-25 16:23 ` [RFC v1 1/3] dts: add UDP tunnel command to testpmd shell Dean Marx
@ 2024-07-26 20:18 ` Jeremy Spewock
0 siblings, 0 replies; 6+ messages in thread
From: Jeremy Spewock @ 2024-07-26 20:18 UTC (permalink / raw)
To: Dean Marx
Cc: probb, npratte, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek, juraj.linkes, dev
Hey Dean, these changes look good to me, I just had a few minor
comments/suggestions.
One thing I did notice was that the methods added here don't have
type-hints for their return-types, obviously functionally it makes no
difference since they don't return anything, but just adding the note
that says the return None is helpful for type checkers and
understanding the method at a glance.
On Thu, Jul 25, 2024 at 12:23 PM Dean Marx <dmarx@iol.unh.edu> wrote:
>
> add udp_tunnel_port command to testpmd shell class,
> also ports over set verbose method from vlan suite
>
> Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
> ---
> dts/framework/remote_session/testpmd_shell.py | 51 ++++++++++++++++++-
> 1 file changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
> index eda6eb320f..26114091d6 100644
> --- a/dts/framework/remote_session/testpmd_shell.py
> +++ b/dts/framework/remote_session/testpmd_shell.py
> @@ -804,7 +804,56 @@ def show_port_stats(self, port_id: int) -> TestPmdPortStats:
>
> return TestPmdPortStats.parse(output)
>
> - def _close(self) -> None:
It looks like this method might have been renamed by mistake in a
rebase, the name on main right now is _close. This could cause some
weird behavior in your testing since this is what the context manager
uses to close the session, but I don't think it would have any drastic
effect since the channel is still closed.
> + def set_verbose(self, level: int, verify: bool = True):
> + """Set debug verbosity level.
> +
> + Args:
> + level: 0 - silent except for error
> + 1 - fully verbose except for Tx packets
> + 2 - fully verbose except for Rx packets
> + >2 - fully verbose
> + verify: If :data:`True` the command output will be scanned to verify that verbose level
> + is properly set. Defaults to :data:`True`.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and verbose level
> + is not correctly set.
> + """
> + verbose_output = self.send_command(f"set verbose {level}")
> + if verify:
> + if "Change verbose level" not in verbose_output:
> + self._logger.debug(f"Failed to set verbose level to {level}: \n{verbose_output}")
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set verbose level to {level}."
> + )
> +
> + def udp_tunnel_port(
> + self, port_id: int, add: bool, udp_port: int, protocol: str, verify: bool = True
> + ):
> + """Configures a UDP tunnel on the specified port, for the specified protocol.
> +
> + Args:
> + port_id: ID of the port to configure tunnel on.
> + add: If :data:`True`, adds tunnel, otherwise removes tunnel.
> + udp_port: ID of the UDP port to configure tunnel on.
> + protocol: Name of tunnelling protocol to use; options are vxlan, geneve, ecpri
If there are explicit choices that this has to be like this it might
be better to put these options into an enum and then pass that in as
the parameter here. That way it is very clear from just calling the
methods what your options are.
> + verify: If :data:`True`, checks the output of the command to verify that
> + no errors were thrown.
> +
> + Raises:
> + InteractiveCommandExecutionError: If verify is :data:`True` and command
> + output shows an error.
> + """
> + action = "add" if add else "rm"
> + cmd_output = self.send_command(
> + f"port config {port_id} udp_tunnel_port {action} {protocol} {udp_port}"
> + )
> + if verify:
> + if "Operation not supported" in cmd_output or "Bad arguments" in cmd_output:
> + self._logger.debug(f"Failed to set UDP tunnel: \n{cmd_output}")
> + raise InteractiveCommandExecutionError(f"Failed to set UDP tunnel: \n{cmd_output}")
> +
> + def close(self) -> None:
> """Overrides :meth:`~.interactive_shell.close`."""
> self.stop()
> self.send_command("quit", "Bye...")
> --
> 2.44.0
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC v1 2/3] dts: VXLAN gpe support test suite
2024-07-25 16:23 [RFC v1 0/3] VXLAN-GPE test suite Dean Marx
2024-07-25 16:23 ` [RFC v1 1/3] dts: add UDP tunnel command to testpmd shell Dean Marx
@ 2024-07-25 16:23 ` Dean Marx
2024-07-26 20:18 ` Jeremy Spewock
2024-07-25 16:23 ` [RFC v1 3/3] dts: conf schema VXLAN gpe support Dean Marx
2 siblings, 1 reply; 6+ messages in thread
From: Dean Marx @ 2024-07-25 16:23 UTC (permalink / raw)
To: probb, npratte, jspewock, luca.vizzarro, yoan.picchi,
Honnappa.Nagarahalli, paul.szczepanek, juraj.linkes
Cc: dev, Dean Marx
Test suite for verifying vxlan gpe support on NIC, as well as expected
behavior while sending vxlan packets through tunnel
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/tests/TestSuite_vxlan_gpe_support.py | 77 ++++++++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 dts/tests/TestSuite_vxlan_gpe_support.py
diff --git a/dts/tests/TestSuite_vxlan_gpe_support.py b/dts/tests/TestSuite_vxlan_gpe_support.py
new file mode 100644
index 0000000000..981f878a4c
--- /dev/null
+++ b/dts/tests/TestSuite_vxlan_gpe_support.py
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2024 University of New Hampshire
+
+"""VXLAN-GPE support test suite.
+
+This suite verifies virtual extensible local area network packets
+are only received in the same state when a UDP tunnel port for VXLAN tunneling
+protocols is enabled. GPE is the Generic Protocol Extension for VXLAN,
+which is used for configuring fields in the VXLAN header through GPE tunnels.
+
+If a GPE tunnel is configured for the corresponding UDP port within a sent packet,
+that packet should be received with its VXLAN layer. If there is no GPE tunnel,
+the packet should be received without its VXLAN layer.
+
+"""
+
+from scapy.layers.inet import IP, UDP # type: ignore[import-untyped]
+from scapy.layers.l2 import Ether # type: ignore[import-untyped]
+from scapy.layers.vxlan import VXLAN # type: ignore[import-untyped]
+from scapy.packet import Raw # type: ignore[import-untyped]
+
+from framework.params.testpmd import SimpleForwardingModes
+from framework.remote_session.testpmd_shell import TestPmdShell
+from framework.test_suite import TestSuite
+
+
+class TestVxlanGpeSupport(TestSuite):
+ """DPDK VXLAN-GPE test suite.
+
+ This suite consists of one test case (Port 4790 is designated for VXLAN-GPE streams):
+ 1. VXLAN-GPE ipv4 packet detect - configures a GPE tunnel on port 4790
+ and sends packets with a matching UDP destination port. This packet
+ should be received by the traffic generator with its VXLAN layer.
+ Then, remove the GPE tunnel, send the same packet, and verify that
+ the packet is received without its VXLAN layer.
+ """
+
+ def set_up_suite(self) -> None:
+ """Set up the test suite.
+
+ Setup:
+ Verify that we have at least 2 port links in the current test run.
+ """
+ self.verify(
+ len(self._port_links) > 1,
+ "There must be at least two port links to run the scatter test suite",
+ )
+
+ def send_vxlan_packet_and_verify(self, udp_dport: int, should_receive_vxlan: bool) -> None:
+ """Generate a VXLAN GPE packet with the given UDP destination port, send and verify.
+
+ Args:
+ udp_dport: The destination UDP port to generate in the packet.
+ should_receive_vxlan: Indicates whether the packet should be
+ received by the traffic generator with its VXLAN layer.
+ """
+ packet = Ether() / IP() / UDP(dport=udp_dport) / VXLAN(flags=12) / IP() / Raw(load="xxxxx")
+ received = self.send_packet_and_capture(packet)
+ print(f"Received packets = {received}")
+ has_vxlan = any(
+ "VXLAN" in packet.summary() and "xxxxx" in str(packet.load) for packet in received
+ )
+ self.verify(
+ not (has_vxlan ^ should_receive_vxlan), "Expected packet did not match received packet."
+ )
+
+ def test_gpe_tunneling(self) -> None:
+ """Verifies expected behavior of VXLAN packets through a GPE tunnel."""
+ GPE_port = 4790
+ with TestPmdShell(node=self.sut_node) as testpmd:
+ testpmd.set_forward_mode(SimpleForwardingModes.io)
+ testpmd.set_verbose(level=1)
+ testpmd.start()
+ testpmd.udp_tunnel_port(port_id=0, add=True, udp_port=GPE_port, protocol="vxlan")
+ self.send_vxlan_packet_and_verify(udp_dport=GPE_port, should_receive_vxlan=True)
+ testpmd.udp_tunnel_port(port_id=0, add=False, udp_port=GPE_port, protocol="vxlan")
+ self.send_vxlan_packet_and_verify(udp_dport=GPE_port, should_receive_vxlan=False)
--
2.44.0
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC v1 2/3] dts: VXLAN gpe support test suite
2024-07-25 16:23 ` [RFC v1 2/3] dts: VXLAN gpe support test suite Dean Marx
@ 2024-07-26 20:18 ` Jeremy Spewock
0 siblings, 0 replies; 6+ messages in thread
From: Jeremy Spewock @ 2024-07-26 20:18 UTC (permalink / raw)
To: Dean Marx
Cc: probb, npratte, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek, juraj.linkes, dev
This all makes sense to me and looks good to me, I just had one
suggestion about verification below.
On Thu, Jul 25, 2024 at 12:23 PM Dean Marx <dmarx@iol.unh.edu> wrote:
>
> Test suite for verifying vxlan gpe support on NIC, as well as expected
> behavior while sending vxlan packets through tunnel
>
> Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
> ---
> dts/tests/TestSuite_vxlan_gpe_support.py | 77 ++++++++++++++++++++++++
> 1 file changed, 77 insertions(+)
> create mode 100644 dts/tests/TestSuite_vxlan_gpe_support.py
>
> diff --git a/dts/tests/TestSuite_vxlan_gpe_support.py b/dts/tests/TestSuite_vxlan_gpe_support.py
> new file mode 100644
> index 0000000000..981f878a4c
> --- /dev/null
> +++ b/dts/tests/TestSuite_vxlan_gpe_support.py
> @@ -0,0 +1,77 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2024 University of New Hampshire
> +
> +"""VXLAN-GPE support test suite.
> +
> +This suite verifies virtual extensible local area network packets
> +are only received in the same state when a UDP tunnel port for VXLAN tunneling
> +protocols is enabled. GPE is the Generic Protocol Extension for VXLAN,
> +which is used for configuring fields in the VXLAN header through GPE tunnels.
> +
> +If a GPE tunnel is configured for the corresponding UDP port within a sent packet,
> +that packet should be received with its VXLAN layer. If there is no GPE tunnel,
> +the packet should be received without its VXLAN layer.
> +
> +"""
> +
> +from scapy.layers.inet import IP, UDP # type: ignore[import-untyped]
> +from scapy.layers.l2 import Ether # type: ignore[import-untyped]
> +from scapy.layers.vxlan import VXLAN # type: ignore[import-untyped]
> +from scapy.packet import Raw # type: ignore[import-untyped]
> +
> +from framework.params.testpmd import SimpleForwardingModes
> +from framework.remote_session.testpmd_shell import TestPmdShell
> +from framework.test_suite import TestSuite
> +
> +
> +class TestVxlanGpeSupport(TestSuite):
> + """DPDK VXLAN-GPE test suite.
> +
> + This suite consists of one test case (Port 4790 is designated for VXLAN-GPE streams):
> + 1. VXLAN-GPE ipv4 packet detect - configures a GPE tunnel on port 4790
> + and sends packets with a matching UDP destination port. This packet
> + should be received by the traffic generator with its VXLAN layer.
> + Then, remove the GPE tunnel, send the same packet, and verify that
> + the packet is received without its VXLAN layer.
> + """
> +
> + def set_up_suite(self) -> None:
> + """Set up the test suite.
> +
> + Setup:
> + Verify that we have at least 2 port links in the current test run.
> + """
> + self.verify(
> + len(self._port_links) > 1,
> + "There must be at least two port links to run the scatter test suite",
> + )
> +
> + def send_vxlan_packet_and_verify(self, udp_dport: int, should_receive_vxlan: bool) -> None:
> + """Generate a VXLAN GPE packet with the given UDP destination port, send and verify.
> +
> + Args:
> + udp_dport: The destination UDP port to generate in the packet.
> + should_receive_vxlan: Indicates whether the packet should be
> + received by the traffic generator with its VXLAN layer.
> + """
> + packet = Ether() / IP() / UDP(dport=udp_dport) / VXLAN(flags=12) / IP() / Raw(load="xxxxx")
> + received = self.send_packet_and_capture(packet)
> + print(f"Received packets = {received}")
> + has_vxlan = any(
> + "VXLAN" in packet.summary() and "xxxxx" in str(packet.load) for packet in received
Scapy actually allows for checking if a layer exists in a packet using
the real types in a few different ways. You could use
packet.haslayer(VXLAN), or you could do basically the same as what you
have without the string comparison if you do `VXLAN in packet`. This
might end up being a little shorter and it saves you from having to
deal with the string provided from the packet summary.
> + )
> + self.verify(
> + not (has_vxlan ^ should_receive_vxlan), "Expected packet did not match received packet."
> + )
> +
> + def test_gpe_tunneling(self) -> None:
> + """Verifies expected behavior of VXLAN packets through a GPE tunnel."""
> + GPE_port = 4790
> + with TestPmdShell(node=self.sut_node) as testpmd:
> + testpmd.set_forward_mode(SimpleForwardingModes.io)
> + testpmd.set_verbose(level=1)
> + testpmd.start()
> + testpmd.udp_tunnel_port(port_id=0, add=True, udp_port=GPE_port, protocol="vxlan")
> + self.send_vxlan_packet_and_verify(udp_dport=GPE_port, should_receive_vxlan=True)
> + testpmd.udp_tunnel_port(port_id=0, add=False, udp_port=GPE_port, protocol="vxlan")
> + self.send_vxlan_packet_and_verify(udp_dport=GPE_port, should_receive_vxlan=False)
> --
> 2.44.0
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC v1 3/3] dts: conf schema VXLAN gpe support
2024-07-25 16:23 [RFC v1 0/3] VXLAN-GPE test suite Dean Marx
2024-07-25 16:23 ` [RFC v1 1/3] dts: add UDP tunnel command to testpmd shell Dean Marx
2024-07-25 16:23 ` [RFC v1 2/3] dts: VXLAN gpe support test suite Dean Marx
@ 2024-07-25 16:23 ` Dean Marx
2 siblings, 0 replies; 6+ messages in thread
From: Dean Marx @ 2024-07-25 16:23 UTC (permalink / raw)
To: probb, npratte, jspewock, luca.vizzarro, yoan.picchi,
Honnappa.Nagarahalli, paul.szczepanek, juraj.linkes
Cc: dev, Dean Marx
Configuration schema to run vxlan gpe support test suite
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/framework/config/conf_yaml_schema.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json
index f02a310bb5..06c8978103 100644
--- a/dts/framework/config/conf_yaml_schema.json
+++ b/dts/framework/config/conf_yaml_schema.json
@@ -187,7 +187,8 @@
"enum": [
"hello_world",
"os_udp",
- "pmd_buffer_scatter"
+ "pmd_buffer_scatter",
+ "vxlan_gpe_support"
]
},
"test_target": {
--
2.44.0
^ permalink raw reply [flat|nested] 6+ messages in thread