[PATCH v5 2/2] dts: add VF configuration and workflow
Patrick Robb
probb at iol.unh.edu
Thu Mar 13 04:36:11 CET 2025
This patch adds an additional test run config option for
selecting physical functions or virtual functions for the
testrun. If virtual function is selected, it adds a workflow
for creating the virtual functions during test run setup.
Bugzilla ID: 1500
Signed-off-by: Jeremy Spewock <jspewock at iol.unh.edu>
Signed-off-by: Patrick Robb <probb at iol.unh.edu>
---
dts/framework/config/test_run.py | 2 ++
dts/framework/remote_session/dpdk.py | 11 +++++++++--
dts/framework/test_run.py | 7 ++++++-
dts/framework/testbed_model/node.py | 5 +++++
dts/framework/testbed_model/port.py | 16 ++++++++++++++++
dts/test_run.example.yaml | 1 +
6 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 06fe28143c..2298960f48 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -464,6 +464,8 @@ class TestRunConfiguration(FrozenModel):
perf: bool
#: Whether to run functional tests.
func: bool
+ #: Whether to run the testing with virtual functions instead of physical functions
+ virtual_functions_testrun: bool
#: Whether to skip smoke tests.
skip_smoke_tests: bool = False
#: The names of test suites and/or test cases to execute.
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 8d9f3b8948..b0445caded 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -415,12 +415,19 @@ def __init__(
self._ports_bound_to_dpdk = False
self._kill_session = None
- def setup(self, ports: Iterable[Port]):
+ def setup(self, ports: Iterable[Port], vf_ports: bool):
"""Set up the DPDK runtime on the target node."""
if self.build:
self.build.setup()
self._prepare_devbind_script()
- self.bind_ports_to_driver(ports)
+
+ if not vf_ports:
+ # for PF test, bind PFs to the DPDK driver
+ self.bind_ports_to_driver(ports)
+ else:
+ # for VF test, leave PFs bound to kernel driver. Bind each PF's VFs to the DPDK driver
+ for port in ports:
+ self.bind_ports_to_driver(port.virtual_functions)
def teardown(self, ports: Iterable[Port]) -> None:
"""Reset DPDK variables and bind port driver to the OS driver."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index f9cfe5e908..9fe30113c2 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -202,6 +202,9 @@ def __init__(
for link in self.config.port_topology
)
+ if self.config.virtual_functions_testrun:
+ sut_node.set_vfs()
+
dpdk_build_env = DPDKBuildEnvironment(config.dpdk.build, sut_node)
dpdk_runtime_env = DPDKRuntimeEnvironment(config.dpdk, sut_node, dpdk_build_env)
traffic_generator = create_traffic_generator(config.traffic_generator, tg_node)
@@ -344,7 +347,9 @@ def next(self) -> State | None:
test_run.ctx.sut_node.setup()
test_run.ctx.tg_node.setup()
- test_run.ctx.dpdk.setup(test_run.ctx.topology.sut_ports)
+ test_run.ctx.dpdk.setup(
+ test_run.ctx.topology.sut_ports, test_run.config.virtual_functions_testrun
+ )
test_run.ctx.tg.setup(test_run.ctx.topology.tg_ports)
self.result.ports = test_run.ctx.topology.sut_ports + test_run.ctx.topology.tg_ports
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index e6737cd173..ac4f44550b 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -185,6 +185,11 @@ def close(self) -> None:
for session in self._other_sessions:
session.close()
+ def set_vfs(self):
+ """Iterate through node ports and create VFs."""
+ for port in self.ports:
+ port.set_vfs()
+
def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger) -> OSSession:
"""Factory for OS-aware sessions.
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py
index f638120eeb..e47ee7948e 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/framework/testbed_model/port.py
@@ -26,6 +26,7 @@ class Port:
mac_address: The MAC address of the port.
logical_name: The logical name of the port.
bound_for_dpdk: :data:`True` if the port is bound to the driver for DPDK.
+ virtual_functions: The list of virtual functions on the port.
"""
node: Final["Node"]
@@ -33,6 +34,7 @@ class Port:
mac_address: Final[str]
logical_name: Final[str]
bound_for_dpdk: bool
+ virtual_functions: list["Port"]
def __init__(self, node: "Node", config: PortConfig):
"""Initialize the port from `node` and `config`.
@@ -45,6 +47,7 @@ def __init__(self, node: "Node", config: PortConfig):
self.config = config
self.logical_name, self.mac_address = node.main_session.get_port_info(config.pci)
self.bound_for_dpdk = False
+ self.virtual_functions = []
@property
def name(self) -> str:
@@ -64,6 +67,19 @@ def configure_mtu(self, mtu: int):
"""
return self.node.main_session.configure_port_mtu(mtu, self)
+ def set_vfs(self):
+ """Create virtual functions for the port."""
+ self.node.main_session.create_vfs(self)
+ addr_list = self.node.main_session.get_pci_addr_of_vfs(self)
+ for addr in addr_list:
+ vf_port_config = PortConfig(
+ name=f"{self.name}-vf-{addr}",
+ pci=addr,
+ os_driver_for_dpdk=self.config.os_driver_for_dpdk,
+ os_driver=self.config.os_driver,
+ )
+ self.virtual_functions.append(Port(self.node, vf_port_config))
+
def to_dict(self) -> dict[str, Any]:
"""Convert to a dictionary."""
return {
diff --git a/dts/test_run.example.yaml b/dts/test_run.example.yaml
index 330a31bb18..16d15dc568 100644
--- a/dts/test_run.example.yaml
+++ b/dts/test_run.example.yaml
@@ -27,6 +27,7 @@ traffic_generator:
type: SCAPY
perf: false # disable performance testing
func: true # enable functional testing
+virtual_functions_testrun: false # testsuites are run from physical functions if set to false, and virtual functions if set to true
skip_smoke_tests: false # optional
# by removing the `test_suites` field, this test run will run every test suite available
test_suites: # the following test suites will be run in their entirety
--
2.48.1
More information about the dev
mailing list