The current DTS dev systems you have access to still are:

iol-dts-tester and iol-dts-dut

with mlnx cx5 and broadcom NetXtreme-E.

Let us know if you have any further questions.

On Tue, Oct 6, 2026 at 3:56 PM Patrick Robb <[email protected]>
wrote:

> I will test this tonight.
>
> What do we have right now in terms of DTS dev systems and NICs for non-iol
> people like me. Is it still:
>
> iol-dts-tester
>
> And
>
> iol-dts-dut
>
> With mlnx cx5 and intel xl710?
>
> Just checking in.
>
> On Tue, Aug 11, 2026 at 1:04 PM Andrew Bailey <[email protected]> wrote:
>
>> Refactor current flow test suite to utilize a generator
>> method, which dynamically creates flow rules from a
>> dictionary of pattern and action fields during runtime.
>> This allows for much more extensive testing of the flow
>> API without exponential code growth.
>>
>> Signed-off-by: Andrew Bailey <[email protected]>
>> Signed-off-by: Dean Marx <[email protected]>
>> Reviewed-by: Patrick Robb <[email protected]>
>> ---
>>
>> v7:
>>  * Resolve merge conflicts.
>>  dts/tests/TestSuite_flow_offload.py | 206 ++++++++++++++++++++++++----
>>  1 file changed, 182 insertions(+), 24 deletions(-)
>>
>> diff --git a/dts/tests/TestSuite_flow_offload.py
>> b/dts/tests/TestSuite_flow_offload.py
>> index be11d09875..d1a6c2fa74 100644
>> --- a/dts/tests/TestSuite_flow_offload.py
>> +++ b/dts/tests/TestSuite_flow_offload.py
>> @@ -1,7 +1,7 @@
>>  # SPDX-License-Identifier: BSD-3-Clause
>>  # Copyright(c) 2025 University of New Hampshire
>>
>> -"""RTE Flow testing suite.
>> +"""Flow offload testing suite.
>>
>>  This suite verifies a range of flow rules built using patterns
>>  and actions from the RTE Flow API. It would be impossible to cover
>> @@ -10,7 +10,7 @@
>>
>>  """
>>
>> -from dataclasses import dataclass
>> +from dataclasses import dataclass, field
>>  from itertools import product
>>  from typing import Any, Callable, Optional
>>
>> @@ -18,6 +18,7 @@
>>  from scapy.layers.inet6 import IPv6
>>  from scapy.layers.l2 import ARP, Dot1Q, Ether
>>  from scapy.layers.sctp import SCTP
>> +from scapy.layers.vxlan import VXLAN
>>  from scapy.packet import Packet, Raw
>>
>>  from api.capabilities import NicCapability, requires_nic_capability
>> @@ -50,10 +51,16 @@ class Protocol:
>>      scapy_class: type[Packet]
>>      pattern_name: str
>>      fields: list[PatternField]
>> +    default_values: dict[str, Any] = field(default_factory=dict)
>>
>>      def build_scapy_layer(self, field_values: dict[str, Any]) -> Packet:
>> -        """Construct a Scapy layer with the given field values."""
>> -        return self.scapy_class(**field_values)
>> +        """Construct a Scapy layer with the given field values.
>> +
>> +        Default values are applied first, then overridden by any
>> +        explicit field values so test parameters always win.
>> +        """
>> +        merged = {**self.default_values, **field_values}
>> +        return self.scapy_class(**merged)
>>
>>
>>  @dataclass
>> @@ -125,6 +132,7 @@ class JumpTest:
>>
>>
>>  PROTOCOLS: dict[str, Protocol] = {
>> +    # -------------------- Base Protocols --------------------
>>      "eth": Protocol(
>>          name="eth",
>>          scapy_class=Ether,
>> @@ -215,6 +223,89 @@ class JumpTest:
>>              PatternField("op", "opcode", [1, 2]),
>>          ],
>>      ),
>> +    # -------------------- VXLAN Outer Protocols --------------------
>> +    "eth_outer": Protocol(
>> +        name="eth_outer",
>> +        scapy_class=Ether,
>> +        pattern_name="eth",
>> +        fields=[
>> +            PatternField("src", "src", ["02:00:00:00:00:00"]),
>> +            PatternField("dst", "dst", ["02:00:00:00:00:02"]),
>> +        ],
>> +    ),
>> +    "ipv4_outer": Protocol(
>> +        name="ipv4_outer",
>> +        scapy_class=IP,
>> +        pattern_name="ipv4",
>> +        fields=[
>> +            PatternField("src", "src", ["10.0.0.1"]),
>> +            PatternField("dst", "dst", ["10.0.0.2"]),
>> +            PatternField("ttl", "ttl", [64, 128]),
>> +            PatternField("tos", "tos", [0, 4]),
>> +        ],
>> +    ),
>> +    "udp_outer": Protocol(
>> +        name="udp_outer",
>> +        scapy_class=UDP,
>> +        pattern_name="udp",
>> +        fields=[],
>> +        default_values={"dport": 4789},
>> +    ),
>> +    # -------------------- VXLAN Tunnel Header --------------------
>> +    "vxlan": Protocol(
>> +        name="vxlan",
>> +        scapy_class=VXLAN,
>> +        pattern_name="vxlan",
>> +        fields=[
>> +            PatternField("vni", "vni", [42, 100]),
>> +        ],
>> +    ),
>> +    # -------------------- VXLAN Inner Protocols --------------------
>> +    "eth_inner": Protocol(
>> +        name="eth_inner",
>> +        scapy_class=Ether,
>> +        pattern_name="eth",
>> +        fields=[
>> +            PatternField("src", "src", ["02:00:00:00:00:00"]),
>> +            PatternField("dst", "dst", ["02:00:00:00:00:02"]),
>> +        ],
>> +    ),
>> +    "ipv4_inner": Protocol(
>> +        name="ipv4_inner",
>> +        scapy_class=IP,
>> +        pattern_name="ipv4",
>> +        fields=[
>> +            PatternField("src", "src", ["192.168.1.1"]),
>> +            PatternField("dst", "dst", ["192.168.1.2"]),
>> +        ],
>> +    ),
>> +    "ipv6_inner": Protocol(
>> +        name="ipv6_inner",
>> +        scapy_class=IPv6,
>> +        pattern_name="ipv6",
>> +        fields=[
>> +            PatternField("src", "src", ["2001:db8::1"]),
>> +            PatternField("dst", "dst", ["2001:db8::2"]),
>> +        ],
>> +    ),
>> +    "tcp_inner": Protocol(
>> +        name="tcp_inner",
>> +        scapy_class=TCP,
>> +        pattern_name="tcp",
>> +        fields=[
>> +            PatternField("sport", "src", [1234]),
>> +            PatternField("dport", "dst", [80]),
>> +        ],
>> +    ),
>> +    "udp_inner": Protocol(
>> +        name="udp_inner",
>> +        scapy_class=UDP,
>> +        pattern_name="udp",
>> +        fields=[
>> +            PatternField("sport", "src", [5000]),
>> +            PatternField("dport", "dst", [53]),
>> +        ],
>> +    ),
>>  }
>>
>>
>> @@ -234,6 +325,7 @@ class JumpTest:
>>  }
>>
>>  PROTOCOL_STACKS = [
>> +    # -------------------- Non-tunnel stacks --------------------
>>      [("eth", True)],
>>      [("eth", False), ("ipv4", True)],
>>      [("eth", False), ("ipv4", True), ("tcp", True)],
>> @@ -253,6 +345,66 @@ class JumpTest:
>>      [("eth", False), ("vlan", False), ("ipv6", True), ("tcp", True)],
>>      [("eth", False), ("vlan", False), ("ipv6", True), ("udp", True)],
>>      [("eth", False), ("arp", True)],
>> +    # -------------------- VXLAN tunnel stacks --------------------
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv4_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv4_inner", False),
>> +        ("tcp_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv4_inner", False),
>> +        ("udp_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv6_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv6_inner", False),
>> +        ("tcp_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +        ("ipv6_inner", False),
>> +        ("udp_inner", False),
>> +    ],
>> +    [
>> +        ("eth_outer", False),
>> +        ("ipv4_outer", True),
>> +        ("udp_outer", False),
>> +        ("vxlan", True),
>> +        ("eth_inner", False),
>> +    ],
>>  ]
>>
>>
>> @@ -304,6 +456,10 @@ def generate(
>>      ) -> list[FlowTest]:
>>          """Generate test cases for patterns matching fields across
>> multiple protocols.
>>
>> +        Pattern parts are assembled in stack order to preserve positional
>> +        correctness, which is required for tunnel encapsulations where
>> +        inner and outer layers share the same pattern_name.
>> +
>>          Args:
>>              protocol_stack: List of (protocol_name, test_fields) tuples.
>>                  If test_fields is True, iterate through field
>> combinations.
>> @@ -316,15 +472,12 @@ def generate(
>>              List of FlowTest objects ready for execution.
>>          """
>>          action_spec = self.actions[action_name]
>> -
>> -        wildcard_protocols = [name for name, test_fields in
>> protocol_stack if not test_fields]
>> -        field_test_protocols = [name for name, test_fields in
>> protocol_stack if test_fields]
>>          all_protocol_names = [name for name, _ in protocol_stack]
>> -
>> -        wildcard_pattern_parts = [self.protocols[name].pattern_name for
>> name in wildcard_protocols]
>> +        field_test_protocols = [name for name, test_fields in
>> protocol_stack if test_fields]
>>
>>          if not field_test_protocols:
>> -            pattern = " / ".join(wildcard_pattern_parts)
>> +            pattern_parts = [self.protocols[name].pattern_name for name,
>> _ in protocol_stack]
>> +            pattern = " / ".join(pattern_parts)
>>              flow_rule = FlowRule(
>>                  direction="ingress",
>>                  pattern=[pattern],
>> @@ -339,7 +492,7 @@ def generate(
>>                      packet=packet,
>>                      verification_type=action_spec.verification_type,
>>
>>  verification_params=action_spec.build_verification_params(action_value),
>> -                    description=" / ".join(wildcard_pattern_parts) + f"
>> -> {action_spec.name}",
>> +                    description=pattern + f" -> {action_spec.name}",
>>                  )
>>              ]
>>
>> @@ -354,24 +507,32 @@ def generate(
>>              max_vals = max(len(f_spec.test_parameters) for _, f_spec in
>> field_combo)
>>
>>              for i in range(max_vals):
>> -                field_pattern_parts = []
>> +                field_value_map: dict[str, tuple[Protocol, PatternField,
>> Any]] = {}
>>                  all_field_values: dict[str, dict[str, Any]] = {}
>> -                desc_parts = []
>>
>>                  for protocol_spec, field_spec in field_combo:
>>                      val = field_spec.test_parameters[i %
>> len(field_spec.test_parameters)]
>> -
>> -                    field_pattern_parts.append(
>> -                        f"{protocol_spec.pattern_name}
>> {field_spec.pattern_field} is {val}"
>> -                    )
>> +                    field_value_map[protocol_spec.name] =
>> (protocol_spec, field_spec, val)
>>
>>                      if protocol_spec.name not in all_field_values:
>>                          all_field_values[protocol_spec.name] = {}
>>                      
>> all_field_values[protocol_spec.name][field_spec.scapy_field]
>> = val
>>
>> -                    desc_parts.append(f"{protocol_spec.name
>> }[{field_spec.scapy_field}={val}]")
>> +                pattern_parts = []
>> +                desc_parts = []
>> +
>> +                for proto_name, test_fields in protocol_stack:
>> +                    proto_spec = self.protocols[proto_name]
>> +                    if test_fields and proto_name in field_value_map:
>> +                        _, f_spec, val = field_value_map[proto_name]
>> +                        pattern_parts.append(
>> +                            f"{proto_spec.pattern_name}
>> {f_spec.pattern_field} is {val}"
>> +                        )
>> +                        desc_parts.append(f"{proto_spec.name
>> }[{f_spec.scapy_field}={val}]")
>> +                    else:
>> +                        pattern_parts.append(proto_spec.pattern_name)
>>
>> -                full_pattern = " / ".join(wildcard_pattern_parts +
>> field_pattern_parts)
>> +                full_pattern = " / ".join(pattern_parts)
>>
>>                  flow_rule = FlowRule(
>>                      direction="ingress",
>> @@ -384,10 +545,7 @@ def generate(
>>                      all_protocol_names, all_field_values,
>> add_payload=True
>>                  )
>>
>> -                wildcard_desc = " / ".join(wildcard_pattern_parts)
>> -                field_desc = " / ".join(desc_parts)
>> -                full_desc = f"{wildcard_desc} / {field_desc}" if
>> wildcard_desc else field_desc
>> -
>> +                full_desc = " / ".join(desc_parts)
>>                  test_cases.append(
>>                      FlowTest(
>>                          flow_rule=flow_rule,
>> @@ -403,7 +561,7 @@ def generate(
>>
>>  @requires_nic_capability(NicCapability.FLOW_CTRL)
>>  class TestFlowOffload(TestSuite):
>> -    """Flow offload test suite.
>> +    """Flow Offload test suite.
>>
>>      This suite consists of 4 test cases:
>>      1. Queue Action: Verifies queue actions with multi-protocol patterns
>> --
>> 2.55.0
>>
>>

Reply via email to