Add Test Suite for VPP WireGuard 69/36169/6
authorCui,Cheng <cheng.cui@intel.com>
Thu, 19 May 2022 06:48:04 +0000 (06:48 +0000)
committerPeter Mikus <peter.mikus@protonmail.ch>
Thu, 9 Jun 2022 05:10:18 +0000 (05:10 +0000)
Signed-off-by: Cui,Cheng <cheng.cui@intel.com>
Change-Id: I71e257e5f16a887a40ff83d782a9ebdee9d05c34
Signed-off-by: Cui,Cheng <cheng.cui@intel.com>
docs/tag_documentation.rst
resources/api/vpp/supported_crcs.yaml
resources/libraries/python/WireGuardUtil.py [new file with mode: 0644]
resources/libraries/robot/wireguard/wireguard.robot [new file with mode: 0644]
tests/vpp/perf/ip4_tunnels/10ge2p1x710-ethip4udpwireguard1tnlsw-ip4base-ndrpdr.robot [new file with mode: 0644]

index e8eb647..d9861a2 100644 (file)
@@ -539,6 +539,10 @@ Encapsulation Tags
 
     All test cases with IPSEC.
 
+.. topic:: WIREGUARD
+
+    All test cases with WIREGUARD.
+
 .. topic:: SRv6
 
     All test cases with Segment routing over IPv6 dataplane.
index fc7308a..30ea8bf 100644 (file)
     vxlan_add_del_tunnel_v3_reply: '0x5383d31f'  # dev
     # vxlan_gpe_tunnel_dump / details # honeycomb
     # vxlan_tunnel_dump /details # unused L2 keyword: Get VXLAN dump
-# Please keep alphabetic order.
+    wireguard_interface_create: '0xa530137e'
+    wireguard_interface_create_reply: '0x5383d31f'
+    wireguard_peer_add: '0x9b8aad61'
+    wireguard_peer_add_reply: '0x084a0cd3'
+    # Please keep alphabetic order.
 # Use bash command "env LC_COLLATE=C sort -u" if not clear.
 
 # Hint to see the currently used command messages:
diff --git a/resources/libraries/python/WireGuardUtil.py b/resources/libraries/python/WireGuardUtil.py
new file mode 100644 (file)
index 0000000..d8d2396
--- /dev/null
@@ -0,0 +1,278 @@
+# Copyright (c) 2022 Intel and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""WireGuard utilities library."""
+
+from ipaddress import ip_address
+from cryptography.hazmat.primitives.serialization import Encoding, \
+    PrivateFormat, PublicFormat, NoEncryption
+from cryptography.hazmat.primitives.asymmetric.x25519 import \
+    X25519PrivateKey
+
+from resources.libraries.python.InterfaceUtil import InterfaceUtil
+from resources.libraries.python.IPUtil import IPUtil
+from resources.libraries.python.PapiExecutor import PapiSocketExecutor
+
+class WireGuardUtil:
+    """This class defines the methods to set WireGuard."""
+
+    @staticmethod
+    def public_key_bytes(k):
+        """Return the public key as byte.
+
+        :param k: Generated public key.
+        :type: x25519._X25519PublicKey object
+        :returns: Public key.
+        :rtype: bytes
+        """
+        return k.public_bytes(Encoding.Raw, PublicFormat.Raw)
+
+    @staticmethod
+    def private_key_bytes(k):
+        """Return the private key as byte.
+
+        :param k: Generated private key.
+        :type: x25519._X25519PrivateKey object
+        :returns: Private key.
+        :rtype: bytes
+        """
+        return k.private_bytes(Encoding.Raw, PrivateFormat.Raw, NoEncryption())
+
+    @staticmethod
+    def generate_wireguard_privatekey_and_pubkey():
+        """Generate a pair of WireGuard Private key and Public key.
+
+        :returns: A pair of privatekey and publickey
+        :rtype: x25519._X25519PublicKey object
+        """
+        privatekey = X25519PrivateKey.generate()
+        pubkey = privatekey.public_key()
+        private_key = WireGuardUtil.private_key_bytes(privatekey)
+        public_key = WireGuardUtil.public_key_bytes(pubkey)
+        return private_key, public_key
+
+    @staticmethod
+    def vpp_wireguard_create_interface(
+            node, listen_port, wg_src, private_key):
+        """Create WireGuard interface.
+
+        :param node: VPP node to add config on.
+        :param listen_port: WireGuard interface listen port.
+        :param wg_src: WireGuard srouce IPv4.
+        :param private_key: WireGuard interface private key
+        :type node: dict
+        :type listen_port: int
+        :type wg_src: str
+        :type private_key: bytes
+        :returns: Wireguard interface sw_if_index.
+        :rtype: int
+        """
+        cmd = u"wireguard_interface_create"
+        err_msg = f"Failed to create wireguard interface" \
+            f"on host {node[u'host']}"
+        src_ip = ip_address(wg_src)
+        args = dict(
+            interface=dict(
+                port=int(listen_port),
+                src_ip=src_ip,
+                private_key=private_key,
+                generate_key=False
+            )
+        )
+        with PapiSocketExecutor(node) as papi_exec:
+            wg_sw_index = \
+                papi_exec.add(cmd, **args).get_sw_if_index(err_msg)
+            return wg_sw_index
+
+    @staticmethod
+    def vpp_wireguard_add_peer(
+            node, interface, peer_pubkey, endpoint_ip,
+            allowed_ips, n_allowed_ips, dst_port, keepalive_time):
+        """Add a peer for WireGuard interface.
+
+        :param node: VPP node to add config on.
+        :param interface: WireGuard interface sw_if_index.
+        :param peer_pubkey: Public key of wireguard interface peer.
+        :param endpoint_ip: Peer source IPv4.
+        :param allowed_ips: WireGuard interface allowed ips list.
+        :param n_allowed_ips: Number of allowed ips.
+        :param dst_port: WireGuard destination port.
+        :param keepaliva time: WireGuard persistent keepalive time.
+        :type node: dict
+        :type interface: int
+        :type peer_pubkey: bytes
+        :type endpoint_ip: str
+        :type allowed_ips: list
+        :type n_allowed_ips: int
+        :type dst_port: int
+        :type keepalive_time: int
+        """
+        endpoint_ip = ip_address(endpoint_ip)
+        wg_name = InterfaceUtil.vpp_get_interface_name(
+            node, sw_if_index=interface
+        )
+        cmd = u"wireguard_peer_add"
+        err_msg = f"Failed to add wireguard interface" \
+            f"{wg_name} peer on host {node[u'host']}"
+        args = dict(
+            peer=dict(
+                public_key=peer_pubkey,
+                port=int(dst_port),
+                endpoint=endpoint_ip,
+                sw_if_index=interface,
+                persistent_keepalive=int(keepalive_time),
+                n_allowed_ips=int(n_allowed_ips),
+                allowed_ips=allowed_ips
+            )
+        )
+        with PapiSocketExecutor(node) as papi_exec:
+            papi_exec.add(cmd, **args).get_reply(err_msg)
+
+    @staticmethod
+    def _wireguard_create_tunnel_interface_on_dut(
+            node, if1_key, if2_mac_addr, src_ip, peer_endpoint_ip,
+            peer_allowed_ips, peer_n_allowed_ips, dut_wg_ip, port,
+            keepalive_time, dut_private_key, peer_pubkey):
+        """Create WireGuard tunnel interface on one DUT node using PAPI.
+
+        :param node: VPP node as DUT to create tunnel interface.
+        :param if1_key: VPP node as DUT interface key from topology file.
+        :param if2_mac_addr: Vpp node on the other end/ TG node
+            (in case of 2-node topology) interface mac address.
+        :param src_ip: WireGuard source IPv4 address.
+        :param peer_endpoint_ip: Peer source IPv4 address.
+        :param peer_allowed_ips: WireGuard peer interface allowed ip list.
+        :param peer_n_allowed ips: Number of peer allowed ips.
+        :param dut_wg_ip: WireGuard interface ip address on DUT.
+        :param port: WireGuard interface listen port or
+            Peer interface destination port.
+        :param keepalive_time: WireGuard persistent keepalive time.
+        :param dut_private_key: WireGuard interface private key of DUT.
+        :param peer_pubkey: WireGuard Peer interface public key.
+        :type nodes: dict
+        :type if1_key: str
+        :type if2_mac_addr: str
+        :type src_ip: src
+        :type peer_endpoint_ip: src
+        :type peer_allowed_ips: list
+        :type peer_n_allowed_ips: int
+        :type dut_wg_ip: src
+        :type port: int
+        :type keepalive_time: int
+        :type dut_private_key: bytes
+        :type peer_pubkey: bytes
+        """
+        #Set IP address on VPP node interface
+        IPUtil.vpp_interface_set_ip_address(node, if1_key, src_ip, 24)
+        IPUtil.vpp_add_ip_neighbor(
+            node, if1_key, peer_endpoint_ip, if2_mac_addr
+        )
+        #Create Wireguard interface on DUT
+        dut_wg_sw_index = WireGuardUtil.vpp_wireguard_create_interface(
+            node, port, src_ip, dut_private_key
+        )
+        #Add wireguard peer
+        WireGuardUtil.vpp_wireguard_add_peer(
+            node, dut_wg_sw_index, peer_pubkey, peer_endpoint_ip,
+            peer_allowed_ips, peer_n_allowed_ips, port, keepalive_time
+        )
+        #Set wireguard interface up
+        InterfaceUtil.set_interface_state(node, dut_wg_sw_index, state=u'up')
+        #Set wireguard interface IP address
+        cmd = u'sw_interface_add_del_address'
+        args = dict(
+            sw_if_index=dut_wg_sw_index,
+            is_add=True,
+            del_all=False,
+            prefix=IPUtil.create_prefix_object(ip_address(dut_wg_ip), 24)
+        )
+        err_msg = f"Failed to set IP address on wg interface " \
+            f"on host {node[u'host']}"
+        with PapiSocketExecutor(node) as papi_exec:
+            papi_exec.add(cmd, **args).get_reply(err_msg)
+        #Set route on VPP node as DUT wg interface
+        for allowed_ip in peer_allowed_ips:
+            traffic_addr = ip_address(
+                allowed_ip[u'address'][u'un'][u'ip4']
+            )
+            prefix_len = allowed_ip[u'len']
+            IPUtil.vpp_route_add(
+                node, traffic_addr, prefix_len,
+                gateway=(traffic_addr+1).compressed,
+                interface=dut_wg_sw_index
+            )
+
+    @staticmethod
+    def vpp_wireguard_create_tunnel_interface_on_duts(
+            nodes, if1_key, if2_key, if1_ip_addr, if2_ip_addr,
+            if1_mac_addr, if2_mac_addr, wg_if1_ip_addr, wg_if2_ip_addr,
+            n_allowed_ips, port, keepalive_time, raddr_ip1, raddr_ip2):
+        """Create WireGuard tunnel interfaces between two VPP nodes.
+
+        :param nodes: VPP nodes to create tunnel interfaces.
+        :param if1_key: VPP node 1 interface key from topology file.
+        :param if2_key: VPP node 2 / TG node (in case of 2-node topology)
+        :param if1_ip_addr: VPP node 1 interface IPv4/IPv6 address.
+        :param if2_ip_addr: VPP node 2 / TG node
+            (in case of 2-node topology) interface IPv4/IPv6 address.
+        :param if1_mac_addr: VPP node1 interface mac address.
+        :param if2_mac_addr: VPP node2 interface mac address.
+        :param wg_if1_ip_addr: VPP node 1 WireGuard interface IPv4 address.
+        :param wg_if2_ip_addr: VPP node 2 WireGuard interface IPv4 address.
+        :param allowed_ips: WireGuard interface allowed ip list.
+        :param n_allowed_ips: Number of allowed ips.
+        :param port: WireGuard interface listen port or
+            Peer interface destination port.
+        :param keepalive_time: WireGuard persistent keepalive time.
+        :param raddr_ip1: Policy selector remote IPv4/IPv6 start address
+            for the first tunnel in direction node1->node2.
+        :param raddr_ip2: Policy selector remote IPv4/IPv6 start address
+            for the first tunnel in direction node2->node1.
+        :type nodes: dict
+        :type if1_key: str
+        :type if2_key: str
+        :type if1_ip_addr: str
+        :type if2_ip_addr: str
+        :type if1_mac_addr: str
+        :type if2_mac_addr: str
+        :type wg_if1_ip_addr: str
+        :type wg_if2_ip_addr: str
+        :type allowed_ips: str
+        :type n_allowed_ips: int
+        :type port: int
+        :type keepalive_time: int
+        :type raddr_ip1: str
+        :type raddr_ip2: str
+        """
+        dut1_privatekey, dut1_pubkey = \
+            WireGuardUtil.generate_wireguard_privatekey_and_pubkey()
+        dut2_privatekey, dut2_pubkey = \
+            WireGuardUtil.generate_wireguard_privatekey_and_pubkey()
+        raddr_ip1 = ip_address(raddr_ip1)
+        raddr_ip2 = ip_address(raddr_ip2)
+        dut1_allowed_ips = \
+            [IPUtil.create_prefix_object(raddr_ip2, 24),]
+        dut2_allowed_ips = \
+            [IPUtil.create_prefix_object(raddr_ip1, 24),]
+        #Configure WireGuard interface on DUT1
+        WireGuardUtil._wireguard_create_tunnel_interface_on_dut(
+            nodes[u'DUT1'], if1_key, if2_mac_addr, if1_ip_addr, if2_ip_addr,
+            dut1_allowed_ips, n_allowed_ips, wg_if1_ip_addr, port,
+            keepalive_time, dut1_privatekey, dut2_pubkey
+        )
+        #Configure WireGuard interface on DUT2
+        WireGuardUtil._wireguard_create_tunnel_interface_on_dut(
+            nodes[u'DUT2'], if2_key, if1_mac_addr, if2_ip_addr, if1_ip_addr,
+            dut2_allowed_ips, n_allowed_ips, wg_if2_ip_addr, port,
+            keepalive_time, dut2_privatekey, dut1_pubkey
+        )
diff --git a/resources/libraries/robot/wireguard/wireguard.robot b/resources/libraries/robot/wireguard/wireguard.robot
new file mode 100644 (file)
index 0000000..ca794d0
--- /dev/null
@@ -0,0 +1,58 @@
+# Copyright (c) 2022 Intel and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*** Settings ***
+| Library | String
+| Library | resources.libraries.python.InterfaceUtil
+| Library | resources.libraries.python.WireGuardUtil
+| Library | resources.libraries.python.IPUtil
+| Library | resources.libraries.python.IPv6Util
+|
+| Documentation | Wireguard keywords.
+
+*** Keywords ***
+| Generate keys for WireGuard
+| | [Documentation] | Generate a pair of keys for WireGuard
+| |
+| | ... | _NOTE:_ This KW sets following test case variable:
+| | ... | - private_key - wireguard Private key. Type: bytes
+| | ... | - pub_key - wireguard public key. Type: bytes
+| |
+| | ... | *Example:*
+| | ... | \| ${private_key} | ${pub_key} |
+| | ... | \| Generate Wireguard Privatekey and Pubkey \|
+| |
+| | ${private_key} | ${pub_key} | Generate Wireguard Privatekey and Pubkey
+| | Set Test Variable | ${private_key}
+| | Set Test Variable | ${pub_key}
+
+| Initialize WireGuard in 3-node circular topology
+| | [Documentation]
+| | ... | Set UP state on VPP interfaces in path on nodes in 3-node circular
+| | ... | topology. Get the interface MAC addresses and setup ARP on VPP
+| | ... | interfaces towards TG. Setup IPv4 addresses with /24 prefix on DUT-TG
+| | ... | links. Set routing for decrypted traffic on both DUT nodes
+| | ... | with prefix /8 and next hop of neighbour TG interface IPv4 address.
+| |
+| | VPP Interface Set IP Address
+| | ... | ${dut1} | ${DUT1_${int}1}[0] | ${dut1_if1_ip4} | 24
+| | VPP Interface Set IP Address
+| | ... | ${dut2} | ${DUT2_${int}2}[0] | ${dut2_if2_ip4} | 24
+| | VPP Add IP Neighbor
+| | ... | ${dut1} | ${DUT1_${int}1}[0] | ${tg_if1_ip4} | ${TG_pf1_mac}[0]
+| | VPP Add IP Neighbor
+| | ... | ${dut2} | ${DUT2_${int}2}[0] | ${tg_if2_ip4} | ${TG_pf2_mac}[0]
+| | Vpp Route Add | ${dut1} | ${laddr_ip4} | 8 | gateway=${tg_if1_ip4}
+| | ... | interface=${DUT1_${int}1}[0]
+| | Vpp Route Add | ${dut2} | ${raddr_ip4} | 8 | gateway=${tg_if2_ip4}
+| | ... | interface=${DUT2_${int}2}[0]
diff --git a/tests/vpp/perf/ip4_tunnels/10ge2p1x710-ethip4udpwireguard1tnlsw-ip4base-ndrpdr.robot b/tests/vpp/perf/ip4_tunnels/10ge2p1x710-ethip4udpwireguard1tnlsw-ip4base-ndrpdr.robot
new file mode 100644 (file)
index 0000000..a27e235
--- /dev/null
@@ -0,0 +1,168 @@
+# Copyright (c) 2022 Intel and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+*** Settings ***
+| Resource | resources/libraries/robot/shared/default.robot
+| Resource | resources/libraries/robot/wireguard/wireguard.robot
+|
+| Force Tags | 3_NODE_SINGLE_LINK_TOPO | PERFTEST | HW_ENV | NDRPDR | TNL_1
+| ... | IP4FWD |  NIC_Intel-X710 | WIREGUARD | DRV_VFIO_PCI
+| ... | RXQ_SIZE_0 | TXQ_SIZE_0
+| ... | ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+|
+| Suite Setup | Setup suite topology interfaces | performance
+| Suite Teardown | Tear down suite | performance
+| Test Setup | Setup test | performance
+|
+| Test Template | Local Template
+|
+| Documentation | **RFC2544: Pkt throughput IPv4 WireGuard tunnel mode.**
+| ... |
+| ... | - **[Top] Network Topologies:** TG-DUT1-DUT2-TG 3-node circular \
+| ... | topology with single links between nodes.
+| ... |
+| ... | - **[Enc] Packet Encapsulations:** Eth-IPv4 on TG-DUTn, \
+| ... | Eth-IPv4-UDP-WireGuard on DUT1-DUT2.
+| ... |
+| ... | - **[Cfg] DUT configuration:** DUT1 and DUT2 are configured with \
+| ... | single WireGuard tunnels between them. DUTs get IPv4 traffic from TG, \
+| ... | and send to another DUT, where packets are decrypted and sent back \
+| ... | to TG.
+| ... |
+| ... | - **[Ver] TG verification:** TG finds and reports throughput NDR (Non \
+| ... | Drop Rate) with zero packet loss tolerance and throughput PDR \
+| ... | (Partial Drop Rate) with non-zero packet loss tolerance (LT) \
+| ... | expressed in percentage of packets transmitted. NDR and PDR are \
+| ... | discovered for different Ethernet L2 frame sizes using MLRsearch \
+| ... | library.
+| ... | Test packets are generated by TG on \
+| ... | links to DUTs. TG traffic profile contains two L3 flow-groups \
+| ... | (flow-group per direction, number of flows per flow-group equals to \
+| ... | number of WireGuard tunnels) with all packets \
+| ... | containing Ethernet header, IPv4 header with IP protocol=61 and \
+| ... | static payload. MAC addresses are matching MAC addresses of the TG \
+| ... | node interfaces. Incrementing of IP.dst (IPv4 destination address) \
+| ... | is applied to both streams.
+| ... |
+| ... | - **[Ref] Applicable standard specifications:** RFC4303 and RFC2544.
+
+
+*** Variables ***
+| @{plugins_to_enable}= | dpdk_plugin.so | perfmon_plugin.so
+| ... | crypto_native_plugin.so | crypto_ipsecmb_plugin.so
+| ... | wireguard_plugin.so | crypto_openssl_plugin.so
+| ${crypto_type}= | ${None}
+| ${nic_name}= | Intel-X710
+| ${nic_driver}= | vfio-pci
+| ${nic_rxq_size}= | 0
+| ${nic_txq_size}= | 0
+| ${nic_pfs}= | 2
+| ${nic_vfs}= | 0
+| ${osi_layer}= | L3
+| ${overhead}= | ${60}
+| ${tg_if1_ip4}= | 192.168.10.2
+| ${dut1_if1_ip4}= | 192.168.10.1
+| ${dut1_if2_ip4}= | 200.0.0.1
+| ${dut2_if1_ip4}= | 200.0.0.2
+| ${dut2_if2_ip4}= | 192.168.20.1
+| ${tg_if2_ip4}= | 192.168.20.2
+| ${wg_if1_ip4}= | 192.168.110.1
+| ${wg_if2_ip4}= | 192.168.120.1
+| ${raddr_ip4}= | 20.0.0.0
+| ${laddr_ip4}= | 10.0.0.0
+| ${n_tunnels}= | ${1}
+| ${listen_port}= | ${51820}
+| ${keepalive_time}= | ${256}
+# Traffic profile:
+| ${traffic_profile}= | trex-stl-3n-ethip4-ip4dst${n_tunnels}
+
+*** Keywords ***
+| Local Template
+| | [Documentation]
+| | ... | - **[Cfg]** DUT runs wireguard TUNNEL. \
+| | ... | Each DUT uses ${phy_cores} physical core(s) for worker threads.
+| | ... | - **[Ver]** Measure NDR and PDR values using MLRsearch algorithm.
+| |
+| | ... | *Arguments:*
+| | ... | - frame_size - Framesize in Bytes in integer or string (IMIX_v4_1).
+| | ... | Type: integer, string
+| | ... | - phy_cores - Number of physical cores. Type: integer
+| | ... | - rxq - Number of RX queues, default value: ${None}. Type: integer
+| |
+| | [Arguments] | ${frame_size} | ${phy_cores} | ${rxq}=${None}
+| |
+| | Set Test Variable | \${frame_size}
+| |
+| | Given Set Max Rate And Jumbo
+| | And Add worker threads to all DUTs | ${phy_cores} | ${rxq}
+| | And Pre-initialize layer driver | ${nic_driver}
+| | And Apply startup configuration on all VPP DUTs
+| | When Initialize layer driver | ${nic_driver}
+| | And Initialize layer interface
+| | And Initialize WireGuard in 3-node circular topology
+| | And VPP WireGuard Create Tunnel Interface On DUTs
+| | ... | ${nodes} | ${DUT1_${int}2}[0] | ${DUT2_${int}1}[0]
+| | ... | ${dut1_if2_ip4} | ${dut2_if1_ip4} | ${DUT1_${int}2_mac}[0]
+| | ... | ${DUT2_${int}1_mac}[0] | ${wg_if1_ip4} | ${wg_if2_ip4}
+| | ... | ${n_tunnels} | ${listen_port} | ${keepalive_time}
+| | ... | ${laddr_ip4} | ${raddr_ip4}
+| | Then Find NDR and PDR intervals using optimized search
+
+*** Test Cases ***
+| 64B-1c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 64B | 1C
+| | frame_size=${64} | phy_cores=${1}
+
+| 64B-2c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 64B | 2C
+| | frame_size=${64} | phy_cores=${2}
+
+| 64B-4c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 64B | 4C
+| | frame_size=${64} | phy_cores=${4}
+
+| 1518B-1c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 1518B | 1C
+| | frame_size=${1518} | phy_cores=${1}
+
+| 1518B-2c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 1518B | 2C
+| | frame_size=${1518} | phy_cores=${2}
+
+| 1518B-4c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 1518B | 4C
+| | frame_size=${1518} | phy_cores=${4}
+
+| 9000B-1c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 9000B | 1C
+| | frame_size=${9000} | phy_cores=${1}
+
+| 9000B-2c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 9000B | 2C
+| | frame_size=${9000} | phy_cores=${2}
+
+| 9000B-4c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | 9000B | 4C
+| | frame_size=${9000} | phy_cores=${4}
+
+| IMIX-1c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | IMIX | 1C
+| | frame_size=IMIX_v4_1 | phy_cores=${1}
+
+| IMIX-2c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | IMIX | 2C
+| | frame_size=IMIX_v4_1 | phy_cores=${2}
+
+| IMIX-4c-ethip4udpwireguard1tnlsw-ip4base-ndrpdr
+| | [Tags] | IMIX | 4C
+| | frame_size=IMIX_v4_1 | phy_cores=${4}