* [PATCH v1 1/8] dts: move test suite module from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 2/8] dts: move testbed model " Dean Marx
` (7 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/capabilities.py | 6 +++---
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 7 +++----
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/context.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/testbed_model/capability.py | 6 +++---
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
35 files changed, 45 insertions(+), 46 deletions(-)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..8569cacbd2 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..fc2be931fe 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 69ce26040a..f107b1cd2c 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -30,12 +30,11 @@
from typing_extensions import Self
from framework.config.common import FrozenModel
+from framework.exception import ConfigurationError, InternalError
+from framework.logger import DTSLogger, get_dts_logger
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-
-from .exception import ConfigurationError, InternalError
-from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
+from framework.utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..6f4f9d82f8 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..75737418a8 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..86745ab56b 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -16,8 +16,8 @@
from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..037ae6c9fb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
@@ -113,7 +114,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from framework.testbed_model.capability import (
Capability,
get_supported_capabilities,
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..39f6f3c0df 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..05bfe951fd 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,8 +11,8 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.port import Port
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..3f046ad87e 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -30,9 +30,9 @@
CryptodevResults,
)
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from framework.context import get_ctx
from framework.exception import SkippedTestException
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..e0ef1f447a 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -37,10 +37,10 @@
)
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..44fee58775 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -18,10 +18,10 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from framework.context import filter_cores
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..98c12459f6 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -25,9 +25,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..d37796954d 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,11 +36,11 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreList
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..8777d446cd 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -22,6 +22,7 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -30,7 +31,6 @@
TestPmdVerbosePacket,
)
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..3d74decb11 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -23,6 +23,7 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
from framework.exception import (
@@ -30,7 +31,6 @@
SkippedTestException,
TestCaseVerifyError,
)
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..38ed2234cd 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,10 +19,10 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
from framework.utils import REGEX_FOR_PCI_ADDRESS
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..263a915745 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,9 +18,9 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..fd1fc476cc 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,9 +12,9 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.capability import requires
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 2/8] dts: move testbed model from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
2026-04-23 17:03 ` [PATCH v1 1/8] dts: move test suite module " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 3/8] dts: move exception module " Dean Marx
` (6 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 ++++----
dts/api/packet.py | 14 +++++++-------
dts/api/test_suite.py | 4 ++--
dts/{framework => api}/testbed_model/__init__.py | 0
.../testbed_model/capability.py | 12 ++++++------
dts/{framework => api}/testbed_model/cpu.py | 4 ++--
.../testbed_model/linux_session.py | 6 +++---
dts/{framework => api}/testbed_model/node.py | 2 +-
.../testbed_model/os_session.py | 8 ++++----
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 +++---
dts/{framework => api}/testbed_model/topology.py | 6 +++---
.../testbed_model/traffic_generator/__init__.py | 4 ++--
.../capturing_traffic_generator.py | 4 ++--
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++++++-------
.../traffic_generator/traffic_generator.py | 8 ++++----
.../testbed_model/traffic_generator/trex.py | 16 ++++++++--------
.../testbed_model/virtual_device.py | 0
dts/framework/config/node.py | 16 ++++++++--------
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 10 +++++-----
dts/framework/params/eal.py | 6 +++---
dts/framework/params/types.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 8 ++++----
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 2 +-
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 16 ++++++++--------
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 8 ++++----
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 +++---
39 files changed, 109 insertions(+), 109 deletions(-)
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (99%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..025c87bbfa 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,10 +47,10 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 8569cacbd2..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/packet.py b/dts/api/packet.py
index fc2be931fe..d30d455485 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -28,14 +28,14 @@
from scapy.packet import Packet, Padding, raw
from api.test import fail, log_debug
-from framework.context import get_ctx
-from framework.exception import InternalError
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from framework.context import get_ctx
+from framework.exception import InternalError
from framework.utils import get_packet_summaries
@@ -82,10 +82,10 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
+ from framework.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index f107b1cd2c..ebb07a9cae 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from framework.config.common import FrozenModel
from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from framework.utils import to_pascal_case
if TYPE_CHECKING:
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 98%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 39f6f3c0df..95583261d8 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -64,11 +64,11 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.test_suite import TestCase
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 6e2ecca080..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -24,12 +24,12 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index ee943462c2..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -18,13 +18,13 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
)
-from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
+from api.testbed_model.port import PortInfo
+from api.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 99%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 2c267afed1..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 98%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/api/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 99%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
index dec952685a..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/api/testbed_model/posix_session.py
@@ -16,15 +16,15 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 98%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 34862c4d2e..5b8fe03836 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -18,9 +18,9 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.exception import ConfigurationError, InternalError
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 95%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index fca251f534..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -14,13 +14,13 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
-from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
+from api.testbed_model.port import Port
+from api.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index c6e9006205..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -25,16 +25,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 91%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 96%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 22cd20dea9..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..63062a31b5 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -21,7 +21,7 @@
@unique
class OS(StrEnum):
- r"""The supported operating systems of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported operating systems of :class:`~api.testbed_model.node.Node`\s."""
#:
linux = auto()
@@ -32,7 +32,7 @@ class OS(StrEnum):
class HugepageConfiguration(FrozenModel):
- r"""The hugepage configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The hugepage configuration of :class:`~api.testbed_model.node.Node`\s."""
#: The number of hugepages to allocate.
number_of: int
@@ -41,7 +41,7 @@ class HugepageConfiguration(FrozenModel):
class PortConfig(FrozenModel):
- r"""The port configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The port configuration of :class:`~api.testbed_model.node.Node`\s."""
#: An identifier for the port. May contain letters, digits, underscores, hyphens and spaces.
name: str = Field(pattern=REGEX_FOR_IDENTIFIER)
@@ -54,17 +54,17 @@ class PortConfig(FrozenModel):
class NodeConfiguration(FrozenModel):
- r"""The configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The configuration of :class:`~api.testbed_model.node.Node`\s."""
- #: The name of the :class:`~framework.testbed_model.node.Node`.
+ #: The name of the :class:`~api.testbed_model.node.Node`.
name: str = Field(pattern=REGEX_FOR_IDENTIFIER)
- #: The hostname of the :class:`~framework.testbed_model.node.Node`. Can also be an IP address.
+ #: The hostname of the :class:`~api.testbed_model.node.Node`. Can also be an IP address.
hostname: str
- #: The name of the user used to connect to the :class:`~framework.testbed_model.node.Node`.
+ #: The name of the user used to connect to the :class:`~api.testbed_model.node.Node`.
user: str
#: The password of the user. The use of passwords is heavily discouraged, please use SSH keys.
password: str | None = None
- #: The operating system of the :class:`~framework.testbed_model.node.Node`.
+ #: The operating system of the :class:`~api.testbed_model.node.Node`.
os: OS
#: An optional hugepage configuration.
hugepages: HugepageConfiguration | None = Field(None, alias="hugepages_2mb")
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 75737418a8..2c16a712eb 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -38,7 +38,7 @@
@unique
class Compiler(StrEnum):
- r"""The supported compilers of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported compilers of :class:`~api.testbed_model.node.Node`\s."""
#:
gcc = auto()
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 86745ab56b..618eb3dda7 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,18 +8,18 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.test_suite import TestCase, TestSuite
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..4181c20e43 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
+from api.testbed_model.node import Node
from framework.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..c955f4def2 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,10 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -29,10 +33,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import MesonArgs, TarCompressionFormat
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..ac89ec0459 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,13 +10,13 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
+from api.testbed_model.cpu import LogicalCoreList
from framework.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..23d05fbdff 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,6 +29,7 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.testbed_model.node import Node
from framework.context import get_ctx
from framework.exception import (
InteractiveCommandExecutionError,
@@ -38,7 +39,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..0e245a515b 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,10 +12,10 @@
import sys
import textwrap
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.exception import ConfigurationError
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..e2efff8681 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,9 +35,9 @@
)
from typing_extensions import OrderedDict
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
from .exception import DTSError, ErrorSeverity, InternalError
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 037ae6c9fb..14c04d1ce0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -107,6 +107,14 @@
from typing import ClassVar, Protocol, Union
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
@@ -114,14 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 05bfe951fd..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -12,8 +12,8 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 3f046ad87e..83ce94d4df 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,9 +31,9 @@
)
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
+from api.testbed_model.virtual_device import VirtualDevice
from framework.context import get_ctx
from framework.exception import SkippedTestException
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 44fee58775..63f771d594 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,10 +19,10 @@
send_packets_and_capture,
)
from api.test_suite import TestSuite, func_test
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from framework.context import filter_cores
-from framework.testbed_model.cpu import LogicalCoreCount
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index d37796954d..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -37,14 +37,14 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 38ed2234cd..157dec7585 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,10 +20,10 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.testbed_model.linux_session import LinuxSession
from framework.utils import REGEX_FOR_PCI_ADDRESS
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 263a915745..0696933053 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -19,9 +19,9 @@
send_packets_and_capture,
)
from api.test_suite import TestSuite, func_test
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index fd1fc476cc..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -13,11 +13,11 @@
from api.packet import send_packets_and_capture
from api.test import log, verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 3/8] dts: move exception module from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
2026-04-23 17:03 ` [PATCH v1 1/8] dts: move test suite module " Dean Marx
2026-04-23 17:03 ` [PATCH v1 2/8] dts: move testbed model " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 4/8] dts: move utils " Dean Marx
` (5 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/test_suite.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 6 +++---
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
24 files changed, 31 insertions(+), 32 deletions(-)
rename dts/{framework => api}/exception.py (100%)
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 025c87bbfa..02d807241f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,8 +47,8 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
+from api.exception import InternalError
from api.testbed_model.node import Node, NodeIdentifier, get_node
-from framework.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index d30d455485..2bf31aa753 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,6 +27,7 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -35,7 +36,6 @@
PerformanceTrafficStats,
)
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.utils import get_packet_summaries
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index ebb07a9cae..be13485f9b 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -29,10 +29,10 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from api.testbed_model.capability import TestProtocol
from api.testbed_model.topology import Topology
from framework.config.common import FrozenModel
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.utils import to_pascal_case
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 6f4f9d82f8..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 2c16a712eb..1b051fbadf 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 618eb3dda7..7ed4cc5665 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,10 +8,10 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
+from api.exception import InternalError
from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
from api.testbed_model.node import Node
from api.testbed_model.topology import Topology
-from framework.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c955f4def2..91173e0796 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -29,7 +30,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 23d05fbdff..15743949e7 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,13 +29,13 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from api.testbed_model.node import Node
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.testbed_model.node import Node
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 0e245a515b..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,9 +12,9 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from api.testbed_model.node import Node
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from .config import Configuration, load_config
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index e2efff8681..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 14c04d1ce0..9972d26b04 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
@@ -117,7 +118,6 @@
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 83ce94d4df..fb6fda3bac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,11 +29,11 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
from framework.context import get_ctx
-from framework.exception import SkippedTestException
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index e0ef1f447a..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,12 +35,12 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index 98c12459f6..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,11 +23,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 8777d446cd..dae90ee2d5 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, func_test
@@ -30,7 +31,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 3d74decb11..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,16 +21,16 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
+from api.exception import (
+ InteractiveCommandExecutionError,
+ SkippedTestException,
+ TestCaseVerifyError,
+)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.exception import (
- InteractiveCommandExecutionError,
- SkippedTestException,
- TestCaseVerifyError,
-)
@dataclass
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 4/8] dts: move utils from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 3/8] dts: move exception module " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 5/8] dts: move context " Dean Marx
` (4 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/test_suite.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
13 files changed, 12 insertions(+), 12 deletions(-)
rename dts/{framework => api}/utils.py (100%)
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 2bf31aa753..2be00ad48a 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -35,8 +35,8 @@
from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
from framework.context import get_ctx
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index be13485f9b..7feb35a9f8 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -32,9 +32,9 @@
from api.exception import ConfigurationError, InternalError
from api.testbed_model.capability import TestProtocol
from api.testbed_model.topology import Topology
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.logger import DTSLogger, get_dts_logger
-from framework.utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 63062a31b5..d7122d13d8 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 1b051fbadf..10901c740d 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 91173e0796..1a4fec8ec9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -18,6 +18,7 @@
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
from api.testbed_model.virtual_device import VirtualDevice
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 63f771d594..0b0b7bc931 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -22,8 +22,8 @@
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index dae90ee2d5..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -31,7 +31,7 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.utils import StrEnum
+from api.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 157dec7585..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -22,9 +22,9 @@
from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 0696933053..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -22,7 +22,7 @@
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.utils import generate_random_packets
+from api.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 5/8] dts: move context from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 4/8] dts: move utils " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 6/8] dts: move params directory " Dean Marx
` (3 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/test_suite.py | 4 ++--
dts/api/testbed_model/node.py | 2 +-
dts/api/testbed_model/topology.py | 14 +++++++-------
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
16 files changed, 23 insertions(+), 23 deletions(-)
rename dts/{framework => api}/context.py (100%)
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 02d807241f..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 2be00ad48a..393fee542b 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -36,7 +36,7 @@
PerformanceTrafficStats,
)
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
def send_packet_and_capture(
@@ -85,7 +85,7 @@ def send_packets_and_capture(
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
- from framework.context import get_ctx
+ from api.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index 7feb35a9f8..0822f9bfe5 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -37,7 +37,7 @@
from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -91,7 +91,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/api/testbed_model/topology.py b/dts/api/testbed_model/topology.py
index 5b8fe03836..11593d64d5 100644
--- a/dts/api/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 4181c20e43..955a7ccdba 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,7 +31,7 @@
from typing_extensions import Self
from api.testbed_model.node import Node
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 1a4fec8ec9..68897bfefe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -30,7 +30,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index ac89ec0459..947f60f75c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,7 +11,7 @@
from pathlib import PurePath
from api.testbed_model.cpu import LogicalCoreList
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 15743949e7..6aebef3f45 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,7 +35,7 @@
InteractiveSSHTimeoutError,
)
from api.testbed_model.node import Node
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 9972d26b04..914bf9491d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -117,7 +117,7 @@
from api.testbed_model.topology import PortLink, Topology
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fb6fda3bac..67ebbc64c2 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -33,7 +33,7 @@
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.context import get_ctx
+from api.context import get_ctx
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 0b0b7bc931..f4833340a6 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -23,7 +23,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 6/8] dts: move params directory from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 5/8] dts: move context " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 7/8] dts: separate Linux session into interface and logic Dean Marx
` (2 subsequent siblings)
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/cryptodev/__init__.py | 4 ++--
dts/api/cryptodev/config.py | 4 ++--
dts/api/packet.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 2 +-
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 4 ++--
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 6 +++---
dts/framework/remote_session/dpdk.py | 4 ++--
dts/framework/remote_session/dpdk_shell.py | 4 ++--
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
18 files changed, 28 insertions(+), 28 deletions(-)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (99%)
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,11 +24,10 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 393fee542b..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,6 +27,7 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
@@ -36,7 +37,6 @@
PerformanceTrafficStats,
)
from api.utils import get_packet_summaries
-from api.context import get_ctx
def send_packet_and_capture(
@@ -82,10 +82,10 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
+ from api.context import get_ctx
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
- from api.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 99%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..55a0e546c1 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -32,6 +32,7 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.params import Switch, YesNoSwitch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.port import Port
from api.testbed_model.virtual_device import VirtualDevice
@@ -56,7 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..e9cd822bac 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,7 +32,9 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
+from api.params.types import TestPmdParamsDict
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,8 +57,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
-from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 955a7ccdba..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
-from api.testbed_model.node import Node
from api.context import get_ctx
-from framework.params import Params
-from framework.params.eal import EalParams
+from api.params import Params
+from api.params.eal import EalParams
+from api.testbed_model.node import Node
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 68897bfefe..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,9 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -30,9 +32,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 947f60f75c..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,9 +10,9 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from api.testbed_model.cpu import LogicalCoreList
from api.context import get_ctx
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.testbed_model.cpu import LogicalCoreList
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 6aebef3f45..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,15 +29,15 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 914bf9491d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
@@ -117,7 +118,6 @@
from api.testbed_model.topology import PortLink, Topology
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 67ebbc64c2..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -33,7 +34,6 @@
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from api.context import get_ctx
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index f4833340a6..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,6 +13,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
@@ -23,7 +24,6 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 7/8] dts: separate Linux session into interface and logic
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 6/8] dts: move params directory " Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 17:03 ` [PATCH v1 8/8] dts: update API rst files for doc build Dean Marx
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 34498 bytes --]
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/api/testbed_model/linux_session.py | 366 +-----------------------
dts/api/testbed_model/node.py | 11 +-
dts/api/testbed_model/os_session.py | 16 ++
dts/framework/linux_session.py | 375 +++++++++++++++++++++++++
4 files changed, 414 insertions(+), 354 deletions(-)
create mode 100644 dts/framework/linux_session.py
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..da3da4461c 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -2,366 +2,26 @@
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
-"""Linux OS translator.
+"""Linux OS session interface.
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
-from pathlib import PurePath
-from typing import TypedDict
+from abc import ABC, abstractmethod
-from typing_extensions import NotRequired
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations.
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
+ API consumers should type-hint against this class when they need access
+ to Linux-only capabilities beyond the base :class:`~.os_session.OSSession` contract.
"""
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
-
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
-
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
-
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
- def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
-
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
-
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
-
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
- """
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
-
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Enable or disable IPv4 forwarding on the node.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ enable: True to enable forwarding, False to disable.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..3cab51855d 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -25,7 +25,6 @@
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
@@ -201,16 +200,26 @@ def close(self) -> None:
def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger) -> OSSession:
"""Factory for OS-aware sessions.
+ Creates a concrete :class:`~.os_session.OSSession` implementation appropriate for the
+ operating system specified in `node_config`. The concrete session classes live in the
+ framework package and are imported lazily to avoid circular dependencies between the
+ API and framework layers.
+
Args:
node_config: The test run configuration of the node to connect to.
name: The name of the session.
logger: The logger instance this session will use.
+ Returns:
+ An OS-aware session connected to the node.
+
Raises:
ConfigurationError: If the node's OS is unsupported.
"""
match node_config.os:
case OS.linux:
+ from framework.linux_session import LinuxSession
+
return LinuxSession(node_config, name, logger)
case _:
raise ConfigurationError(f"Unsupported OS {node_config.os}")
diff --git a/dts/api/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
index b1e0538ac9..618a5bc45c 100644
--- a/dts/api/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -166,6 +166,22 @@ def close(self) -> None:
"""Close the underlying remote session."""
self.remote_session.close()
+ @property
+ @abstractmethod
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Must be set up during environment initialization before access.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
+
@staticmethod
@abstractmethod
def _get_privileged_command(command: str) -> str:
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..54c6370d53
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,375 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS session implementation.
+
+Translates OS-unaware calls into Linux-specific commands and utilities.
+Implements the :class:`~api.linux_session.LinuxSession` contract for Linux distributions,
+building on :class:`~.posix_session.PosixSession` for POSIX-compliant operations.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """Linux-specific implementation of the OS session interface.
+
+ Inherits POSIX-compliant operations from
+ :class:`~.posix_session.PosixSession` and implements the
+ :class:`~api.linux_session.LinuxSession` contract. All backend logic —
+ ``lshw`` caching, hugepage sysfs interaction, VFIO module loading,
+ SR-IOV management — lives here in the framework.
+ """
+
+ _devbind_script_path: PurePath | None
+
+ def __init__(self, *args, **kwargs) -> None:
+ """Overrides :meth:`~.os_session.OSSession.__init__`."""
+ self._devbind_script_path = None
+ super().__init__(*args, **kwargs)
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ @property
+ def devbind_script_path(self) -> PurePath:
+ """Overrides :attr:`~.os_session.OSSession.devbind_script_path`.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ if self._devbind_script_path is None:
+ raise InternalError("Accessed devbind script path before setup.")
+ return self._devbind_script_path
+
+ @devbind_script_path.setter
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
+ self._devbind_script_path = value
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ @property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ """Cached lshw network info, fetched on first access."""
+ if not hasattr(self, "_lshw_net_cache"):
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ self._lshw_net_cache: list[LshwOutput] = json.loads(output.stdout)
+ return self._lshw_net_cache
+
+ def _refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info.
+
+ Called internally after operations that change port/driver state.
+ """
+ if hasattr(self, "_lshw_net_cache"):
+ del self._lshw_net_cache
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`."""
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+ self._refresh_lshw()
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+ self._refresh_lshw()
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self._refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self._refresh_lshw()
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+ self._refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Implements :meth:`~api.linux_session.LinuxSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v1 8/8] dts: update API rst files for doc build
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (6 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 7/8] dts: separate Linux session into interface and logic Dean Marx
@ 2026-04-23 17:03 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
8 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 17:03 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Appropriately rename/update the framework rst files
which have been moved to the API in this series.
Resolve circular dependency issues in api/params/types
and api/testpmd.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...{framework.context.rst => api.context.rst} | 2 +-
...mework.exception.rst => api.exception.rst} | 2 +-
...work.params.eal.rst => api.params.eal.rst} | 2 +-
.../{framework.params.rst => api.params.rst} | 6 ++--
....params.types.rst => api.params.types.rst} | 2 +-
...work.test_suite.rst => api.test_suite.rst} | 2 +-
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
.../{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 8 ++++++
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 15 +++++-----
dts/api/params/types.py | 8 ++++--
dts/api/testpmd/__init__.py | 7 ++++-
27 files changed, 93 insertions(+), 75 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
create mode 100644 doc/api/dts/framework.linux_session.rst
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..5cb2d04db1
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+linux\_session - Linux Remote Session
+=====================================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..bdb8462622 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,9 +16,9 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
@@ -29,14 +29,15 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ framework.linux_session
+ api.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
- framework.utils
- framework.exception
+ api.utils
+ api.exception
Indices and tables
@@ -44,4 +45,4 @@ Indices and tables
* :ref:`genindex`
* :ref:`modindex`
-* :ref:`search`
+* :ref:`search`
\ No newline at end of file
diff --git a/dts/api/params/types.py b/dts/api/params/types.py
index 55a0e546c1..280c87ec92 100644
--- a/dts/api/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -32,7 +34,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
-from api.params import Switch, YesNoSwitch
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.port import Port
from api.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9cd822bac..09974048e7 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -34,7 +37,9 @@
from api.capabilities import LinkTopology, NicCapability
from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
-from api.params.types import TestPmdParamsDict
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 0/7] dts: move test suite imports from framework to API
2026-04-23 17:03 ` [PATCH v1 0/8] dts: move test suite imports from framework to API Dean Marx
` (7 preceding siblings ...)
2026-04-23 17:03 ` [PATCH v1 8/8] dts: update API rst files for doc build Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 1/7] dts: move test suite module " Dean Marx
` (7 more replies)
8 siblings, 8 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
This series moves various modules from the framework directory
to the API based on which are being imported by test suites.
These include:
- test_suite
- testbed_model
- exception
- utils
- context
- params
This eliminates all test suite framework imports except for
the remote_session imports in packet_capture, as well
as the settings/config imports in smoke_tests. I believe these
imports, and what to do with them, should be a topic of discussion
in future DTS meetings, as I don't believe they should reside in the
API, even if they are being imported in test suites.
In addition to these changes, I've split the linux_session module
into an interface in api/testbed_model/linux_session and an
implementation in framework/linux_session. This way, users
can still import linux session if necessary, without exposing
the backend implementation.
---
v2:
* Integrated rst updates with corresponding commits for build testing
Dean Marx (7):
dts: move test suite module from framework to API
dts: move testbed model from framework to API
dts: move exception module from framework to API
dts: move utils from framework to API
dts: move context from framework to API
dts: move params directory from framework to API
dts: separate Linux session into interface and logic
--
2.52.0
^ permalink raw reply [flat|nested] 81+ messages in thread* [PATCH v2 1/7] dts: move test suite module from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 2/7] dts: move testbed model " Dean Marx
` (6 subsequent siblings)
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.test_suite.rst => api.test_suite.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/capabilities.py | 6 +++---
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 7 +++----
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/context.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/testbed_model/capability.py | 6 +++---
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
37 files changed, 47 insertions(+), 48 deletions(-)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..b9338d6b11 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -29,7 +29,7 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ api.test_suite
framework.test_result
framework.settings
framework.context
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..8569cacbd2 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..fc2be931fe 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 69ce26040a..f107b1cd2c 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -30,12 +30,11 @@
from typing_extensions import Self
from framework.config.common import FrozenModel
+from framework.exception import ConfigurationError, InternalError
+from framework.logger import DTSLogger, get_dts_logger
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-
-from .exception import ConfigurationError, InternalError
-from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
+from framework.utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..6f4f9d82f8 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..75737418a8 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..86745ab56b 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -16,8 +16,8 @@
from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..037ae6c9fb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
@@ -113,7 +114,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from framework.testbed_model.capability import (
Capability,
get_supported_capabilities,
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..39f6f3c0df 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from framework.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..05bfe951fd 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,8 +11,8 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.port import Port
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..3f046ad87e 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -30,9 +30,9 @@
CryptodevResults,
)
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from framework.context import get_ctx
from framework.exception import SkippedTestException
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..e0ef1f447a 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -37,10 +37,10 @@
)
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..44fee58775 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -18,10 +18,10 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from framework.context import filter_cores
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..98c12459f6 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -25,9 +25,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..d37796954d 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,11 +36,11 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreList
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..8777d446cd 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -22,6 +22,7 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -30,7 +31,6 @@
TestPmdVerbosePacket,
)
from framework.exception import InteractiveCommandExecutionError
-from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..3d74decb11 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -23,6 +23,7 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
from framework.exception import (
@@ -30,7 +31,6 @@
SkippedTestException,
TestCaseVerifyError,
)
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..38ed2234cd 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,10 +19,10 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
from framework.utils import REGEX_FOR_PCI_ADDRESS
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..263a915745 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,9 +18,9 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..fd1fc476cc 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,9 +12,9 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
from framework.testbed_model.capability import requires
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 2/7] dts: move testbed model from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-23 19:04 ` [PATCH v2 1/7] dts: move test suite module " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 3/7] dts: move exception module " Dean Marx
` (5 subsequent siblings)
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 +++---
dts/api/packet.py | 14 +++++-----
dts/api/test_suite.py | 4 +--
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 12 ++++----
dts/{framework => api}/testbed_model/cpu.py | 4 +--
.../testbed_model/linux_session.py | 6 ++--
dts/{framework => api}/testbed_model/node.py | 2 +-
.../testbed_model/os_session.py | 8 +++---
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 ++--
.../testbed_model/topology.py | 6 ++--
.../traffic_generator/__init__.py | 4 +--
.../capturing_traffic_generator.py | 4 +--
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++++-----
.../traffic_generator/traffic_generator.py | 8 +++---
.../testbed_model/traffic_generator/trex.py | 16 +++++------
.../testbed_model/virtual_device.py | 0
dts/framework/config/node.py | 16 +++++------
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 10 +++----
dts/framework/params/eal.py | 6 ++--
dts/framework/params/types.py | 6 ++--
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 8 +++---
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 2 +-
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 16 +++++------
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 8 +++---
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 ++--
55 files changed, 165 insertions(+), 165 deletions(-)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (99%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index b9338d6b11..527cc8ce53 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,7 +16,7 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
framework.params
framework.config
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..025c87bbfa 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,10 +47,10 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 8569cacbd2..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/packet.py b/dts/api/packet.py
index fc2be931fe..d30d455485 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -28,14 +28,14 @@
from scapy.packet import Packet, Padding, raw
from api.test import fail, log_debug
-from framework.context import get_ctx
-from framework.exception import InternalError
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from framework.context import get_ctx
+from framework.exception import InternalError
from framework.utils import get_packet_summaries
@@ -82,10 +82,10 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
+ from framework.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index f107b1cd2c..ebb07a9cae 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from framework.config.common import FrozenModel
from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from framework.utils import to_pascal_case
if TYPE_CHECKING:
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 98%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 39f6f3c0df..95583261d8 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from api.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -64,11 +64,11 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.test_suite import TestCase
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 6e2ecca080..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -24,12 +24,12 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index ee943462c2..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -18,13 +18,13 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
)
-from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
+from api.testbed_model.port import PortInfo
+from api.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 99%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 2c267afed1..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 98%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/api/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 99%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
index dec952685a..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/api/testbed_model/posix_session.py
@@ -16,15 +16,15 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 98%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 34862c4d2e..5b8fe03836 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -18,9 +18,9 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.exception import ConfigurationError, InternalError
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 95%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index fca251f534..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -14,13 +14,13 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
-from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
+from api.testbed_model.port import Port
+from api.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index c6e9006205..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -25,16 +25,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 91%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 96%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 22cd20dea9..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..63062a31b5 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -21,7 +21,7 @@
@unique
class OS(StrEnum):
- r"""The supported operating systems of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported operating systems of :class:`~api.testbed_model.node.Node`\s."""
#:
linux = auto()
@@ -32,7 +32,7 @@ class OS(StrEnum):
class HugepageConfiguration(FrozenModel):
- r"""The hugepage configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The hugepage configuration of :class:`~api.testbed_model.node.Node`\s."""
#: The number of hugepages to allocate.
number_of: int
@@ -41,7 +41,7 @@ class HugepageConfiguration(FrozenModel):
class PortConfig(FrozenModel):
- r"""The port configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The port configuration of :class:`~api.testbed_model.node.Node`\s."""
#: An identifier for the port. May contain letters, digits, underscores, hyphens and spaces.
name: str = Field(pattern=REGEX_FOR_IDENTIFIER)
@@ -54,17 +54,17 @@ class PortConfig(FrozenModel):
class NodeConfiguration(FrozenModel):
- r"""The configuration of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The configuration of :class:`~api.testbed_model.node.Node`\s."""
- #: The name of the :class:`~framework.testbed_model.node.Node`.
+ #: The name of the :class:`~api.testbed_model.node.Node`.
name: str = Field(pattern=REGEX_FOR_IDENTIFIER)
- #: The hostname of the :class:`~framework.testbed_model.node.Node`. Can also be an IP address.
+ #: The hostname of the :class:`~api.testbed_model.node.Node`. Can also be an IP address.
hostname: str
- #: The name of the user used to connect to the :class:`~framework.testbed_model.node.Node`.
+ #: The name of the user used to connect to the :class:`~api.testbed_model.node.Node`.
user: str
#: The password of the user. The use of passwords is heavily discouraged, please use SSH keys.
password: str | None = None
- #: The operating system of the :class:`~framework.testbed_model.node.Node`.
+ #: The operating system of the :class:`~api.testbed_model.node.Node`.
os: OS
#: An optional hugepage configuration.
hugepages: HugepageConfiguration | None = Field(None, alias="hugepages_2mb")
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 75737418a8..2c16a712eb 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -38,7 +38,7 @@
@unique
class Compiler(StrEnum):
- r"""The supported compilers of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported compilers of :class:`~api.testbed_model.node.Node`\s."""
#:
gcc = auto()
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 86745ab56b..618eb3dda7 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,18 +8,18 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.test_suite import TestCase, TestSuite
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..4181c20e43 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
+from api.testbed_model.node import Node
from framework.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..c955f4def2 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,10 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -29,10 +33,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import MesonArgs, TarCompressionFormat
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..ac89ec0459 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,13 +10,13 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
+from api.testbed_model.cpu import LogicalCoreList
from framework.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..23d05fbdff 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,6 +29,7 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.testbed_model.node import Node
from framework.context import get_ctx
from framework.exception import (
InteractiveCommandExecutionError,
@@ -38,7 +39,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..0e245a515b 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,10 +12,10 @@
import sys
import textwrap
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.exception import ConfigurationError
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..e2efff8681 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,9 +35,9 @@
)
from typing_extensions import OrderedDict
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
from .exception import DTSError, ErrorSeverity, InternalError
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 037ae6c9fb..14c04d1ce0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -107,6 +107,14 @@
from typing import ClassVar, Protocol, Union
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
@@ -114,14 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 05bfe951fd..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -12,8 +12,8 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 3f046ad87e..83ce94d4df 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,9 +31,9 @@
)
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
+from api.testbed_model.virtual_device import VirtualDevice
from framework.context import get_ctx
from framework.exception import SkippedTestException
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 44fee58775..63f771d594 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,10 +19,10 @@
send_packets_and_capture,
)
from api.test_suite import TestSuite, func_test
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from framework.context import filter_cores
-from framework.testbed_model.cpu import LogicalCoreCount
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index d37796954d..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -37,14 +37,14 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 38ed2234cd..157dec7585 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,10 +20,10 @@
)
from api.test import verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.testbed_model.linux_session import LinuxSession
from framework.utils import REGEX_FOR_PCI_ADDRESS
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 263a915745..0696933053 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -19,9 +19,9 @@
send_packets_and_capture,
)
from api.test_suite import TestSuite, func_test
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.testbed_model.virtual_device import VirtualDevice
from framework.utils import generate_random_packets
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index fd1fc476cc..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -13,11 +13,11 @@
from api.packet import send_packets_and_capture
from api.test import log, verify
from api.test_suite import TestSuite, func_test
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 3/7] dts: move exception module from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-23 19:04 ` [PATCH v2 1/7] dts: move test suite module " Dean Marx
2026-04-23 19:04 ` [PATCH v2 2/7] dts: move testbed model " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 4/7] dts: move utils " Dean Marx
` (4 subsequent siblings)
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.exception.rst => api.exception.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/test_suite.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 6 +++---
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
26 files changed, 33 insertions(+), 34 deletions(-)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename dts/{framework => api}/exception.py (100%)
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 527cc8ce53..3b9ffab4ce 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -36,7 +36,7 @@ Modules
framework.logger
framework.parser
framework.utils
- framework.exception
+ api.exception
Indices and tables
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 025c87bbfa..02d807241f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,8 +47,8 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
+from api.exception import InternalError
from api.testbed_model.node import Node, NodeIdentifier, get_node
-from framework.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index d30d455485..2bf31aa753 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,6 +27,7 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -35,7 +36,6 @@
PerformanceTrafficStats,
)
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.utils import get_packet_summaries
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index ebb07a9cae..be13485f9b 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -29,10 +29,10 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from api.testbed_model.capability import TestProtocol
from api.testbed_model.topology import Topology
from framework.config.common import FrozenModel
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.utils import to_pascal_case
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 6f4f9d82f8..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 2c16a712eb..1b051fbadf 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 618eb3dda7..7ed4cc5665 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,10 +8,10 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
+from api.exception import InternalError
from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
from api.testbed_model.node import Node
from api.testbed_model.topology import Topology
-from framework.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c955f4def2..91173e0796 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -29,7 +30,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 23d05fbdff..15743949e7 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,13 +29,13 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from api.testbed_model.node import Node
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.testbed_model.node import Node
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 0e245a515b..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,9 +12,9 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from api.testbed_model.node import Node
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from .config import Configuration, load_config
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index e2efff8681..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 14c04d1ce0..9972d26b04 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
@@ -117,7 +118,6 @@
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 83ce94d4df..fb6fda3bac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,11 +29,11 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
from framework.context import get_ctx
-from framework.exception import SkippedTestException
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index e0ef1f447a..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,12 +35,12 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index 98c12459f6..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,11 +23,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 8777d446cd..dae90ee2d5 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, func_test
@@ -30,7 +31,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 3d74decb11..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,16 +21,16 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
+from api.exception import (
+ InteractiveCommandExecutionError,
+ SkippedTestException,
+ TestCaseVerifyError,
+)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.exception import (
- InteractiveCommandExecutionError,
- SkippedTestException,
- TestCaseVerifyError,
-)
@dataclass
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 4/7] dts: move utils from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-23 19:04 ` [PATCH v2 3/7] dts: move exception module " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 5/7] dts: move context " Dean Marx
` (3 subsequent siblings)
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/test_suite.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
15 files changed, 14 insertions(+), 14 deletions(-)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
rename dts/{framework => api}/utils.py (100%)
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 3b9ffab4ce..ced42ac241 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -35,7 +35,7 @@ Modules
framework.context
framework.logger
framework.parser
- framework.utils
+ api.utils
api.exception
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 2bf31aa753..2be00ad48a 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -35,8 +35,8 @@
from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
from framework.context import get_ctx
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index be13485f9b..7feb35a9f8 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -32,9 +32,9 @@
from api.exception import ConfigurationError, InternalError
from api.testbed_model.capability import TestProtocol
from api.testbed_model.topology import Topology
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.logger import DTSLogger, get_dts_logger
-from framework.utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 63062a31b5..d7122d13d8 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 1b051fbadf..10901c740d 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 91173e0796..1a4fec8ec9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -18,6 +18,7 @@
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
from api.testbed_model.virtual_device import VirtualDevice
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 63f771d594..0b0b7bc931 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -22,8 +22,8 @@
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index dae90ee2d5..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -31,7 +31,7 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.utils import StrEnum
+from api.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 157dec7585..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -22,9 +22,9 @@
from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 0696933053..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -22,7 +22,7 @@
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
-from framework.utils import generate_random_packets
+from api.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 5/7] dts: move context from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-23 19:04 ` [PATCH v2 4/7] dts: move utils " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 6/7] dts: move params directory " Dean Marx
` (2 subsequent siblings)
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.context.rst => api.context.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/test_suite.py | 4 ++--
dts/api/testbed_model/node.py | 2 +-
dts/api/testbed_model/topology.py | 14 +++++++-------
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
18 files changed, 25 insertions(+), 25 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename dts/{framework => api}/context.py (100%)
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index ced42ac241..7c282bbba1 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -32,7 +32,7 @@ Modules
api.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
api.utils
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 02d807241f..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 2be00ad48a..393fee542b 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -36,7 +36,7 @@
PerformanceTrafficStats,
)
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
def send_packet_and_capture(
@@ -85,7 +85,7 @@ def send_packets_and_capture(
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
- from framework.context import get_ctx
+ from api.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/test_suite.py b/dts/api/test_suite.py
index 7feb35a9f8..0822f9bfe5 100644
--- a/dts/api/test_suite.py
+++ b/dts/api/test_suite.py
@@ -37,7 +37,7 @@
from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -91,7 +91,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/api/testbed_model/topology.py b/dts/api/testbed_model/topology.py
index 5b8fe03836..11593d64d5 100644
--- a/dts/api/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 4181c20e43..955a7ccdba 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,7 +31,7 @@
from typing_extensions import Self
from api.testbed_model.node import Node
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 1a4fec8ec9..68897bfefe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -30,7 +30,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index ac89ec0459..947f60f75c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,7 +11,7 @@
from pathlib import PurePath
from api.testbed_model.cpu import LogicalCoreList
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 15743949e7..6aebef3f45 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,7 +35,7 @@
InteractiveSSHTimeoutError,
)
from api.testbed_model.node import Node
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 9972d26b04..914bf9491d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -117,7 +117,7 @@
from api.testbed_model.topology import PortLink, Topology
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fb6fda3bac..67ebbc64c2 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -33,7 +33,7 @@
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.context import get_ctx
+from api.context import get_ctx
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 0b0b7bc931..f4833340a6 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -23,7 +23,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 6/7] dts: move params directory from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-23 19:04 ` [PATCH v2 5/7] dts: move context " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-23 19:04 ` [PATCH v2 7/7] dts: separate Linux session into interface and logic Dean Marx
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.params.eal.rst => api.params.eal.rst} | 2 +-
doc/api/dts/{framework.params.rst => api.params.rst} | 6 +++---
.../{framework.params.types.rst => api.params.types.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/__init__.py | 4 ++--
dts/api/cryptodev/config.py | 4 ++--
dts/api/packet.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 8 ++++++--
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 9 +++++++--
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 6 +++---
dts/framework/remote_session/dpdk.py | 4 ++--
dts/framework/remote_session/dpdk_shell.py | 4 ++--
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
22 files changed, 44 insertions(+), 35 deletions(-)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (97%)
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 7c282bbba1..e89e782ac0 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -18,7 +18,7 @@ Packages
api
api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,11 +24,10 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 393fee542b..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,6 +27,7 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
@@ -36,7 +37,6 @@
PerformanceTrafficStats,
)
from api.utils import get_packet_summaries
-from api.context import get_ctx
def send_packet_and_capture(
@@ -82,10 +82,10 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
+ from api.context import get_ctx
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
- from api.context import get_ctx
assert isinstance(
get_ctx().func_tg, CapturingTrafficGenerator
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 97%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..280c87ec92 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -32,6 +34,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.port import Port
from api.testbed_model.virtual_device import VirtualDevice
@@ -56,7 +61,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..09974048e7 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -32,7 +35,11 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,8 +62,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
-from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 955a7ccdba..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
-from api.testbed_model.node import Node
from api.context import get_ctx
-from framework.params import Params
-from framework.params.eal import EalParams
+from api.params import Params
+from api.params.eal import EalParams
+from api.testbed_model.node import Node
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 68897bfefe..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,9 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -30,9 +32,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 947f60f75c..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,9 +10,9 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from api.testbed_model.cpu import LogicalCoreList
from api.context import get_ctx
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.testbed_model.cpu import LogicalCoreList
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index 6aebef3f45..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,15 +29,15 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 914bf9491d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,6 +106,7 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
@@ -117,7 +118,6 @@
from api.testbed_model.topology import PortLink, Topology
from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 67ebbc64c2..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -33,7 +34,6 @@
from api.test import verify
from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from api.context import get_ctx
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index f4833340a6..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,6 +13,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
@@ -23,7 +24,6 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v2 7/7] dts: separate Linux session into interface and logic
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-23 19:04 ` [PATCH v2 6/7] dts: move params directory " Dean Marx
@ 2026-04-23 19:04 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
7 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-23 19:04 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 36200 bytes --]
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...st => api.testbed_model.linux_session.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 8 +
doc/api/dts/index.rst | 1 +
dts/api/testbed_model/linux_session.py | 366 +----------------
dts/api/testbed_model/node.py | 11 +-
dts/api/testbed_model/os_session.py | 16 +
dts/framework/linux_session.py | 375 ++++++++++++++++++
7 files changed, 424 insertions(+), 355 deletions(-)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
create mode 100644 doc/api/dts/framework.linux_session.rst
create mode 100644 dts/framework/linux_session.py
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..5cb2d04db1
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+linux\_session - Linux Remote Session
+=====================================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index e89e782ac0..0dbc18b75c 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -37,6 +37,7 @@ Modules
framework.parser
api.utils
api.exception
+ framework.linux_session
Indices and tables
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..da3da4461c 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -2,366 +2,26 @@
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
-"""Linux OS translator.
+"""Linux OS session interface.
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
-from pathlib import PurePath
-from typing import TypedDict
+from abc import ABC, abstractmethod
-from typing_extensions import NotRequired
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations.
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
+ API consumers should type-hint against this class when they need access
+ to Linux-only capabilities beyond the base :class:`~.os_session.OSSession` contract.
"""
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
-
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
-
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
-
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
- def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
-
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
-
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
-
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
- """
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
-
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Enable or disable IPv4 forwarding on the node.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ enable: True to enable forwarding, False to disable.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..3cab51855d 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -25,7 +25,6 @@
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
@@ -201,16 +200,26 @@ def close(self) -> None:
def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger) -> OSSession:
"""Factory for OS-aware sessions.
+ Creates a concrete :class:`~.os_session.OSSession` implementation appropriate for the
+ operating system specified in `node_config`. The concrete session classes live in the
+ framework package and are imported lazily to avoid circular dependencies between the
+ API and framework layers.
+
Args:
node_config: The test run configuration of the node to connect to.
name: The name of the session.
logger: The logger instance this session will use.
+ Returns:
+ An OS-aware session connected to the node.
+
Raises:
ConfigurationError: If the node's OS is unsupported.
"""
match node_config.os:
case OS.linux:
+ from framework.linux_session import LinuxSession
+
return LinuxSession(node_config, name, logger)
case _:
raise ConfigurationError(f"Unsupported OS {node_config.os}")
diff --git a/dts/api/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
index b1e0538ac9..618a5bc45c 100644
--- a/dts/api/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -166,6 +166,22 @@ def close(self) -> None:
"""Close the underlying remote session."""
self.remote_session.close()
+ @property
+ @abstractmethod
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Must be set up during environment initialization before access.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
+
@staticmethod
@abstractmethod
def _get_privileged_command(command: str) -> str:
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..54c6370d53
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,375 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS session implementation.
+
+Translates OS-unaware calls into Linux-specific commands and utilities.
+Implements the :class:`~api.linux_session.LinuxSession` contract for Linux distributions,
+building on :class:`~.posix_session.PosixSession` for POSIX-compliant operations.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """Linux-specific implementation of the OS session interface.
+
+ Inherits POSIX-compliant operations from
+ :class:`~.posix_session.PosixSession` and implements the
+ :class:`~api.linux_session.LinuxSession` contract. All backend logic —
+ ``lshw`` caching, hugepage sysfs interaction, VFIO module loading,
+ SR-IOV management — lives here in the framework.
+ """
+
+ _devbind_script_path: PurePath | None
+
+ def __init__(self, *args, **kwargs) -> None:
+ """Overrides :meth:`~.os_session.OSSession.__init__`."""
+ self._devbind_script_path = None
+ super().__init__(*args, **kwargs)
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ @property
+ def devbind_script_path(self) -> PurePath:
+ """Overrides :attr:`~.os_session.OSSession.devbind_script_path`.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ if self._devbind_script_path is None:
+ raise InternalError("Accessed devbind script path before setup.")
+ return self._devbind_script_path
+
+ @devbind_script_path.setter
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
+ self._devbind_script_path = value
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ @property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ """Cached lshw network info, fetched on first access."""
+ if not hasattr(self, "_lshw_net_cache"):
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ self._lshw_net_cache: list[LshwOutput] = json.loads(output.stdout)
+ return self._lshw_net_cache
+
+ def _refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info.
+
+ Called internally after operations that change port/driver state.
+ """
+ if hasattr(self, "_lshw_net_cache"):
+ del self._lshw_net_cache
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`."""
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+ self._refresh_lshw()
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+ self._refresh_lshw()
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self._refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self._refresh_lshw()
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+ self._refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Implements :meth:`~api.linux_session.LinuxSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 0/7] dts: move test suite imports from framework to API
2026-04-23 19:04 ` [PATCH v2 0/7] dts: move test suite imports from framework to API Dean Marx
` (6 preceding siblings ...)
2026-04-23 19:04 ` [PATCH v2 7/7] dts: separate Linux session into interface and logic Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 1/7] dts: move exception module " Dean Marx
` (9 more replies)
7 siblings, 10 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
This series moves various modules from the framework directory
to the API based on which are being imported by test suites.
These include:
- test_suite
- testbed_model
- exception
- utils
- context
- params
This eliminates all test suite framework imports except for
the remote_session imports in packet_capture, as well
as the settings/config imports in smoke_tests. I believe these
imports, and what to do with them, should be a topic of discussion
in future DTS meetings, as I don't believe they should reside in the
API, even if they are being imported in test suites.
In addition to these changes, I've split the linux_session module
into an interface in api/testbed_model/linux_session and an
implementation in framework/linux_session. This way, users
can still import linux session if necessary, without exposing
the backend implementation.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
v2:
* Integrated rst updates with corresponding commits for build testing
v3:
* Fixed commit ordering to resolve import inconsistency
* Updated Linux Session interface with test suite methods
Dean Marx (7):
dts: move exception module from framework to API
dts: move utils from framework to API
dts: move context from framework to API
dts: move testbed model from framework to API
dts: move test suite module from framework to API
dts: move params directory from framework to API
dts: separate Linux session into interface and logic
...{framework.context.rst => api.context.rst} | 2 +-
...mework.exception.rst => api.exception.rst} | 2 +-
...work.params.eal.rst => api.params.eal.rst} | 2 +-
.../{framework.params.rst => api.params.rst} | 6 +--
....params.types.rst => api.params.types.rst} | 2 +-
...work.test_suite.rst => api.test_suite.rst} | 2 +-
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 ++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
.../{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 6 +++
doc/api/dts/framework.testbed_model.rst | 28 -------------
...mework.testbed_model.traffic_generator.rst | 16 --------
doc/api/dts/index.rst | 13 +++---
dts/api/artifact.py | 6 +--
dts/api/capabilities.py | 14 +++----
dts/{framework => api}/context.py | 14 +++----
dts/api/cryptodev/__init__.py | 6 +--
dts/api/cryptodev/config.py | 6 +--
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 18 ++++----
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 8 ++--
dts/{framework => api}/params/types.py | 14 ++++---
dts/api/test.py | 4 +-
dts/{framework => api}/test_suite.py | 15 ++++---
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 18 ++++----
dts/{framework => api}/testbed_model/cpu.py | 4 +-
dts/api/testbed_model/linux_session.py | 41 +++++++++++++++++++
dts/{framework => api}/testbed_model/node.py | 6 +--
.../testbed_model/os_session.py | 8 ++--
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 +--
.../testbed_model/topology.py | 20 ++++-----
.../traffic_generator/__init__.py | 4 +-
.../capturing_traffic_generator.py | 4 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++----
.../traffic_generator/traffic_generator.py | 8 ++--
.../testbed_model/traffic_generator/trex.py | 16 ++++----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 11 +++--
dts/api/testpmd/config.py | 6 +--
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 2 +-
dts/framework/config/__init__.py | 6 +--
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 12 +++---
.../{testbed_model => }/linux_session.py | 15 ++++---
dts/framework/parser.py | 2 +-
dts/framework/remote_session/blocking_app.py | 8 ++--
dts/framework/remote_session/dpdk.py | 16 ++++----
dts/framework/remote_session/dpdk_shell.py | 6 +--
.../interactive_remote_session.py | 2 +-
.../remote_session/interactive_shell.py | 8 ++--
.../remote_session/remote_session.py | 4 +-
dts/framework/runner.py | 4 +-
dts/framework/test_result.py | 5 +--
dts/framework/test_run.py | 24 +++++------
dts/tests/TestSuite_blocklist.py | 4 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 8 ++--
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 4 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 8 ++--
dts/tests/TestSuite_mac_filter.py | 4 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 12 +++---
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
dts/tests/TestSuite_pmd_rss.py | 6 +--
dts/tests/TestSuite_port_control.py | 2 +-
...stSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 12 +++---
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
.../TestSuite_single_core_forward_perf.py | 4 +-
dts/tests/TestSuite_smoke_tests.py | 6 +--
dts/tests/TestSuite_softnic.py | 6 +--
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 8 ++--
dts/tests/TestSuite_vlan.py | 2 +-
98 files changed, 353 insertions(+), 299 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
create mode 100644 doc/api/dts/framework.linux_session.rst
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/context.py (90%)
rename dts/{framework => api}/exception.py (100%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (89%)
rename dts/{framework => api}/params/types.py (94%)
rename dts/{framework => api}/test_suite.py (98%)
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
create mode 100644 dts/api/testbed_model/linux_session.py
rename dts/{framework => api}/testbed_model/node.py (98%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (96%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
rename dts/{framework => api}/utils.py (99%)
rename dts/framework/{testbed_model => }/linux_session.py (97%)
--
2.52.0
^ permalink raw reply [flat|nested] 81+ messages in thread* [PATCH v3 1/7] dts: move exception module from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 2/7] dts: move utils " Dean Marx
` (8 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.exception.rst => api.exception.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/capability.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/port.py | 2 +-
dts/framework/testbed_model/posix_session.py | 2 +-
dts/framework/testbed_model/topology.py | 2 +-
.../testbed_model/traffic_generator/__init__.py | 2 +-
dts/framework/testbed_model/traffic_generator/scapy.py | 2 +-
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
34 files changed, 40 insertions(+), 41 deletions(-)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename dts/{framework => api}/exception.py (100%)
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..01f630e7cd 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -36,7 +36,7 @@ Modules
framework.logger
framework.parser
framework.utils
- framework.exception
+ api.exception
Indices and tables
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..7d04c7ab49 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,7 +47,7 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
from framework.testbed_model.node import Node, NodeIdentifier, get_node
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..cabb39a8dd 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,9 +27,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..566dc7c4a2 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..62aaba033a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..7e61c85998 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,7 +8,7 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..d803a9e4bd 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -25,7 +26,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..fdd074be3a 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,12 +29,12 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..a0d8039a04 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,8 +12,8 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from framework.testbed_model.node import Node
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..3cecb928ca 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
from framework.testbed_model.os_session import OSSessionInfo
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..bbaf4f1fdf 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,9 +106,9 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 69ce26040a..e06fdd28b9 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-from .exception import ConfigurationError, InternalError
from .logger import DTSLogger, get_dts_logger
from .utils import to_pascal_case
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..001b65994c 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -64,7 +64,7 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
from framework.logger import get_dts_logger
from framework.testbed_model.node import Node
from framework.testbed_model.port import DriverKind
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index ee943462c2..88b6da1ae6 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -18,7 +18,7 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/framework/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index dec952685a..db2c3c0c40 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -16,7 +16,7 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
from framework.settings import SETTINGS
from framework.utils import (
MesonArgs,
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 34862c4d2e..805a762c19 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -18,7 +18,7 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
+from api.exception import ConfigurationError, InternalError
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.node import Node, NodeIdentifier
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index fca251f534..324b5e88f3 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -14,12 +14,12 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index c6e9006205..e983443548 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -25,9 +25,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
from framework.testbed_model.node import Node
from framework.testbed_model.port import Port
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..f36b48a153 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,9 +29,9 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from framework.context import get_ctx
-from framework.exception import SkippedTestException
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..b62efa2b42 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,11 +35,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..b44822d31c 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,10 +23,10 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..1e5a6860be 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.testpmd import TestPmd
@@ -29,7 +30,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..7e50a075ac 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,15 +21,15 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
-from api.packet import send_packet_and_capture
-from api.test import fail, log, verify
-from api.testpmd import TestPmd
-from api.testpmd.types import FlowRule
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
SkippedTestException,
TestCaseVerifyError,
)
+from api.packet import send_packet_and_capture
+from api.test import fail, log, verify
+from api.testpmd import TestPmd
+from api.testpmd.types import FlowRule
from framework.test_suite import TestSuite, func_test
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 2/7] dts: move utils from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-24 17:01 ` [PATCH v3 1/7] dts: move exception module " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 3/7] dts: move context " Dean Marx
` (7 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/cpu.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/os_session.py | 2 +-
dts/framework/testbed_model/posix_session.py | 4 ++--
.../traffic_generator/capturing_traffic_generator.py | 2 +-
.../testbed_model/traffic_generator/traffic_generator.py | 2 +-
dts/framework/testbed_model/traffic_generator/trex.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
22 files changed, 22 insertions(+), 22 deletions(-)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
rename dts/{framework => api}/utils.py (100%)
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 01f630e7cd..783270f6e9 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -35,7 +35,7 @@ Modules
framework.context
framework.logger
framework.parser
- framework.utils
+ api.utils
api.exception
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index cabb39a8dd..b7a9bb28bf 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -29,6 +29,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
+from api.utils import get_packet_summaries
from framework.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -36,7 +37,6 @@
from framework.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..28f23389a7 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 62aaba033a..977067f42a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index d803a9e4bd..69b47b823b 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -14,6 +14,7 @@
from typing import ClassVar, Final
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.testbed_model.node import Node
from framework.testbed_model.os_session import OSSession
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index e06fdd28b9..426c98fdf6 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index 6e2ecca080..52ef196f84 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -24,7 +24,7 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 88b6da1ae6..69b0923744 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.utils import expand_range
from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index 2c267afed1..7bb339fab2 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index db2c3c0c40..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -17,14 +17,14 @@
from pathlib import Path, PurePath, PurePosixPath
from api.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..2804d64990 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.utils import get_packet_summaries
from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..fedce77fdf 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/framework/testbed_model/traffic_generator/trex.py
index 22cd20dea9..2064703fcc 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/framework/testbed_model/traffic_generator/trex.py
@@ -11,6 +11,7 @@
from scapy.packet import Packet
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
@@ -23,7 +24,6 @@
PerformanceTrafficGenerator,
PerformanceTrafficStats,
)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..1e99b82b8c 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -20,10 +20,10 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 1e5a6860be..4df273e3e1 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -30,8 +30,8 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
+from api.utils import StrEnum
from framework.test_suite import BaseConfig, TestSuite, func_test
-from framework.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..fce83604a6 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,11 +20,11 @@
)
from api.test import verify
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..c57a12c932 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -20,9 +20,9 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
+from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 3/7] dts: move context from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-24 17:01 ` [PATCH v3 1/7] dts: move exception module " Dean Marx
2026-04-24 17:01 ` [PATCH v3 2/7] dts: move utils " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 4/7] dts: move testbed model " Dean Marx
` (6 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.context.rst => api.context.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/test_suite.py | 4 ++--
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/topology.py | 14 +++++++-------
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
18 files changed, 25 insertions(+), 25 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename dts/{framework => api}/context.py (100%)
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 783270f6e9..98269d6e80 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -32,7 +32,7 @@ Modules
framework.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
api.utils
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 7d04c7ab49..f3dd07de56 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index b7a9bb28bf..59f26da833 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -30,7 +30,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
@@ -82,7 +82,7 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..07db6dfeb0 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,7 +30,7 @@
from typing_extensions import Self
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 69b47b823b..9f7cd60dfe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -26,7 +26,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..a8f169787c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,7 +10,7 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index fdd074be3a..d138727c85 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -34,7 +34,7 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index bbaf4f1fdf..605a916ebb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,7 +108,7 @@
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 426c98fdf6..6066f7a77a 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -38,7 +38,7 @@
from .logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -92,7 +92,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 805a762c19..5b6ff2add5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index f36b48a153..39784cbcac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,7 +31,7 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 1e99b82b8c..c018efb1f7 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -21,7 +21,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 4/7] dts: move testbed model from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-24 17:01 ` [PATCH v3 3/7] dts: move context " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 5/7] dts: move test suite module " Dean Marx
` (5 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 +++---
dts/api/context.py | 10 +++----
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 12 ++++----
dts/api/test.py | 2 +-
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 10 +++----
dts/{framework => api}/testbed_model/cpu.py | 2 +-
.../testbed_model/linux_session.py | 2 +-
dts/{framework => api}/testbed_model/node.py | 0
.../testbed_model/os_session.py | 6 ++--
dts/{framework => api}/testbed_model/port.py | 0
.../testbed_model/posix_session.py | 0
.../testbed_model/topology.py | 4 +--
.../traffic_generator/__init__.py | 2 +-
.../capturing_traffic_generator.py | 2 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 12 ++++----
.../traffic_generator/traffic_generator.py | 6 ++--
.../testbed_model/traffic_generator/trex.py | 14 +++++-----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 2 +-
dts/framework/params/eal.py | 6 ++--
dts/framework/params/types.py | 6 ++--
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 10 +++----
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 4 +--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 18 ++++++------
dts/framework/test_suite.py | 4 +--
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 4 +--
dts/tests/TestSuite_l2fwd.py | 4 +--
dts/tests/TestSuite_packet_capture.py | 8 +++---
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 ++--
57 files changed, 148 insertions(+), 148 deletions(-)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (99%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (100%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (100%)
rename dts/{framework => api}/testbed_model/posix_session.py (100%)
rename dts/{framework => api}/testbed_model/topology.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (97%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (94%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (97%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 98269d6e80..f47e4af3f2 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,7 +16,7 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
framework.params
framework.config
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index f3dd07de56..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -48,9 +48,9 @@
from typing_extensions import Buffer
from api.exception import InternalError
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..04fc20738b 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/context.py b/dts/api/context.py
index 7e61c85998..13a2ad6c39 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -9,17 +9,17 @@
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
from api.exception import InternalError
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.test_suite import TestCase, TestSuite
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..1ba8e0d977 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,7 +24,6 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 59f26da833..bf90961c26 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,16 +27,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
-from api.utils import get_packet_summaries
-from api.context import get_ctx
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
def send_packet_and_capture(
@@ -83,7 +83,7 @@ def send_packets_and_capture(
A list of received packets.
"""
from api.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 99%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 001b65994c..4e4e976be5 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -65,10 +65,10 @@ def test_scatter_mbuf_2048(self):
from api.capabilities import LinkTopology, NicCapability
from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.testpmd import TestPmd
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 52ef196f84..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -29,7 +29,7 @@
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index 69b0923744..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.testbed_model.port import PortInfo
from api.utils import expand_range
-from framework.testbed_model.port import PortInfo
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 100%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 7bb339fab2..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 100%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 100%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 99%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 5b6ff2add5..11593d64d5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -19,8 +19,8 @@
from api.capabilities import LinkTopology
from api.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index 324b5e88f3..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -15,12 +15,12 @@
"""
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 99%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 2804d64990..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.testbed_model.port import Port
from api.utils import get_packet_summaries
-from framework.testbed_model.port import Port
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index e983443548..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -26,15 +26,15 @@
from scapy.packet import Packet
from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 94%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index fedce77fdf..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 2064703fcc..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..9f47a15433 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
@@ -55,7 +56,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 07db6dfeb0..84db3974b1 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,11 +31,11 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 9f7cd60dfe..713a564d25 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,12 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
@@ -26,14 +31,9 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index a8f169787c..b807f9bdae 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,12 +11,12 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.testbed_model.cpu import LogicalCoreList
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index d138727c85..ec539bad95 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,16 +29,16 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index a0d8039a04..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -13,9 +13,9 @@
import textwrap
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 3cecb928ca..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -36,9 +36,9 @@
from typing_extensions import OrderedDict
from api.exception import DTSError, ErrorSeverity, InternalError
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
class Result(IntEnum):
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 605a916ebb..790fbf997d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,22 +106,22 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 6066f7a77a..786cfc7bff 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..97e03b8fb7 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 39784cbcac..fc4b3cb308 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -31,9 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from api.context import get_ctx
+from api.testbed_model.virtual_device import VirtualDevice
from framework.test_suite import BaseConfig, TestSuite, crypto_test
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index c018efb1f7..5650366c36 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,17 +13,17 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreCount
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..042b7019aa 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,15 +36,15 @@
send_packets_and_capture,
)
from api.test import verify
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index fce83604a6..656e2e4bb7 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.linux_session import LinuxSession
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index c57a12c932..91a6d4eb9f 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.virtual_device import VirtualDevice
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..c649aac197 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 5/7] dts: move test suite module from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-24 17:01 ` [PATCH v3 4/7] dts: move testbed model " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 6/7] dts: move params directory " Dean Marx
` (4 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.test_suite.rst => api.test_suite.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/capabilities.py | 6 +++---
dts/api/context.py | 2 +-
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 3 +--
dts/api/testbed_model/capability.py | 6 +++---
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
37 files changed, 45 insertions(+), 46 deletions(-)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index f47e4af3f2..7c282bbba1 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -29,7 +29,7 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ api.test_suite
framework.test_result
framework.settings
api.context
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 04fc20738b..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/context.py b/dts/api/context.py
index 13a2ad6c39..7ed4cc5665 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -16,10 +16,10 @@
from framework.settings import SETTINGS
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from api.testbed_model.capability import TestProtocol
from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
P = ParamSpec("P")
diff --git a/dts/api/packet.py b/dts/api/packet.py
index bf90961c26..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 786cfc7bff..0822f9bfe5 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -34,8 +34,7 @@
from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-
-from .logger import DTSLogger, get_dts_logger
+from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
from api.context import Context
diff --git a/dts/api/testbed_model/capability.py b/dts/api/testbed_model/capability.py
index 4e4e976be5..95583261d8 100644
--- a/dts/api/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.logger import get_dts_logger
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 566dc7c4a2..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 977067f42a..81e3dba79b 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 790fbf997d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,6 +108,7 @@
from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
get_supported_capabilities,
@@ -121,7 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 97e03b8fb7..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fc4b3cb308..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -32,8 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index b62efa2b42..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -38,9 +38,9 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 5650366c36..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,11 +19,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index b44822d31c..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -26,8 +26,8 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 042b7019aa..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,6 +36,7 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -44,7 +45,6 @@
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 4df273e3e1..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -23,6 +23,7 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -31,7 +32,6 @@
TestPmdVerbosePacket,
)
from api.utils import StrEnum
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 7e50a075ac..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 656e2e4bb7..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 91a6d4eb9f..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index c649aac197..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import requires
from api.testbed_model.linux_session import LinuxSession
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestVirtioFwd(TestSuite):
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 6/7] dts: move params directory from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-24 17:01 ` [PATCH v3 5/7] dts: move test suite module " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-24 17:01 ` [PATCH v3 7/7] dts: separate Linux session into interface and logic Dean Marx
` (3 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.params.eal.rst => api.params.eal.rst} | 2 +-
doc/api/dts/{framework.params.rst => api.params.rst} | 6 +++---
.../{framework.params.types.rst => api.params.types.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/api/cryptodev/config.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 8 ++++++--
dts/api/testpmd/__init__.py | 7 ++++++-
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 4 ++--
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
17 files changed, 32 insertions(+), 23 deletions(-)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (97%)
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 7c282bbba1..e89e782ac0 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -18,7 +18,7 @@ Packages
api
api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 1ba8e0d977..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -27,7 +27,7 @@
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 97%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..2c215cfe54 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -56,7 +58,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9f47a15433..85ebe2ea65 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -56,7 +59,9 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.params.types import TestPmdParamsDict
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 84db3974b1..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,9 +31,9 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.params import Params
+from api.params.eal import EalParams
from api.testbed_model.node import Node
-from framework.params import Params
-from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 713a564d25..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -15,6 +15,7 @@
from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -32,7 +33,6 @@
RemoteDPDKTreeLocation,
)
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index b807f9bdae..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,8 +11,8 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCoreList
-from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index ec539bad95..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,9 +35,9 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v3 7/7] dts: separate Linux session into interface and logic
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-24 17:01 ` [PATCH v3 6/7] dts: move params directory " Dean Marx
@ 2026-04-24 17:01 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 subsequent siblings)
9 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-24 17:01 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/framework.linux_session.rst | 6 +
doc/api/dts/index.rst | 1 +
dts/api/testbed_model/linux_session.py | 372 ++----------------------
dts/api/testbed_model/node.py | 2 +-
dts/framework/linux_session.py | 366 +++++++++++++++++++++++
5 files changed, 397 insertions(+), 350 deletions(-)
create mode 100644 doc/api/dts/framework.linux_session.rst
create mode 100644 dts/framework/linux_session.py
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..0bbbe36eb7
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,6 @@
+framework.linux\_session
+========================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index e89e782ac0..0dbc18b75c 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -37,6 +37,7 @@ Modules
framework.parser
api.utils
api.exception
+ framework.linux_session
Indices and tables
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..5bcbf1ce97 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -1,367 +1,41 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
+"""Linux OS session interface.
-"""Linux OS translator.
-
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
+from abc import ABC, abstractmethod
from pathlib import PurePath
-from typing import TypedDict
-
-from typing_extensions import NotRequired
-
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
-
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
- """
-
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations."""
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
+ @property
+ @abstractmethod
def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
+ """The path to the devbind script."""
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+ @abstractmethod
+ def set_interface_link_up(self, name: str) -> None:
+ """Set the link status of an interface to up.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface.
"""
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def delete_interface(self, name: str) -> None:
+ """Delete a virtual interface.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface to delete.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..ae9886e531 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -22,10 +22,10 @@
OS,
NodeConfiguration,
)
+from framework.linux_session import LinuxSession
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..e5320b7fc4
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,366 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS translator.
+
+Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
+compliant with POSIX standards, so this module only implements the parts that aren't.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from functools import cached_property
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """The implementation of non-Posix compliant parts of Linux."""
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ # when forcing numa, we need to clear existing hugepages regardless
+ # of size, so they can be moved to the first numa node
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ # the file doesn't exist, meaning the node doesn't support numa
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ # the system supports numa if self._numa_nodes is non-empty and there are more
+ # than one numa node (in the latter case it may actually support numa, but
+ # there's no reason to do any numa specific configuration)
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ # clear non-numa hugepages
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
+
+ The :attr:`~.devbind_script_path` property must be setup in order to call this method.
+ """
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+
+ del self._lshw_net_info
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+
+ del self._lshw_net_info
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ @cached_property
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Needs to be manually assigned first in order to be used.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ raise InternalError("Accessed devbind script path before setup.")
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~os_session.OSSession,load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self.refresh_lshw()
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+
+ self.refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self.refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ @cached_property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ return json.loads(output.stdout)
+
+ def refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info."""
+ if "_lshw_net_info" in self.__dict__:
+ del self.__dict__["_lshw_net_info"]
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 0/7] dts: move test suite imports from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (6 preceding siblings ...)
2026-04-24 17:01 ` [PATCH v3 7/7] dts: separate Linux session into interface and logic Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
` (6 more replies)
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
9 siblings, 7 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
This series moves various modules from the framework directory
to the API based on which are being imported by test suites.
These include:
- test_suite
- testbed_model
- exception
- utils
- context
- params
This eliminates all test suite framework imports except for
the remote_session imports in packet_capture, as well
as the settings/config imports in smoke_tests. I believe these
imports, and what to do with them, should be a topic of discussion
in future DTS meetings, as I don't believe they should reside in the
API, even if they are being imported in test suites.
In addition to these changes, I've split the linux_session module
into an interface in api/testbed_model/linux_session and an
implementation in framework/linux_session. This way, users
can still import linux session if necessary, without exposing
the backend implementation.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
v2:
* Integrated rst updates with corresponding commits for build testing
v3:
* Fixed commit ordering to resolve import inconsistency
* Updated Linux Session interface with test suite methods
v4:
* Added missing SPDX tag to framework.linux_session.rst
* Added lazy linux session import in node.py to
resolve circular import issue
Dean Marx (7):
dts: move exception module from framework to API
dts: move utils from framework to API
dts: move context from framework to API
dts: move testbed model from framework to API
dts: move test suite module from framework to API
dts: move params directory from framework to API
dts: separate Linux session into interface and logic
...{framework.context.rst => api.context.rst} | 2 +-
...mework.exception.rst => api.exception.rst} | 2 +-
...work.params.eal.rst => api.params.eal.rst} | 2 +-
.../{framework.params.rst => api.params.rst} | 6 +--
....params.types.rst => api.params.types.rst} | 2 +-
...work.test_suite.rst => api.test_suite.rst} | 2 +-
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 ++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
.../{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 8 ++++
doc/api/dts/framework.testbed_model.rst | 28 -------------
...mework.testbed_model.traffic_generator.rst | 16 --------
doc/api/dts/index.rst | 13 +++---
dts/api/artifact.py | 6 +--
dts/api/capabilities.py | 14 +++----
dts/{framework => api}/context.py | 14 +++----
dts/api/cryptodev/__init__.py | 6 +--
dts/api/cryptodev/config.py | 6 +--
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 18 ++++----
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 8 ++--
dts/{framework => api}/params/types.py | 14 ++++---
dts/api/test.py | 4 +-
dts/{framework => api}/test_suite.py | 15 ++++---
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 18 ++++----
dts/{framework => api}/testbed_model/cpu.py | 4 +-
dts/api/testbed_model/linux_session.py | 41 +++++++++++++++++++
dts/{framework => api}/testbed_model/node.py | 12 +++---
.../testbed_model/os_session.py | 8 ++--
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 +--
.../testbed_model/topology.py | 20 ++++-----
.../traffic_generator/__init__.py | 4 +-
.../capturing_traffic_generator.py | 4 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++----
.../traffic_generator/traffic_generator.py | 8 ++--
.../testbed_model/traffic_generator/trex.py | 16 ++++----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 11 +++--
dts/api/testpmd/config.py | 6 +--
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 2 +-
dts/framework/config/__init__.py | 6 +--
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 12 +++---
.../{testbed_model => }/linux_session.py | 15 ++++---
dts/framework/parser.py | 2 +-
dts/framework/remote_session/blocking_app.py | 8 ++--
dts/framework/remote_session/dpdk.py | 16 ++++----
dts/framework/remote_session/dpdk_shell.py | 6 +--
.../interactive_remote_session.py | 2 +-
.../remote_session/interactive_shell.py | 8 ++--
.../remote_session/remote_session.py | 4 +-
dts/framework/runner.py | 4 +-
dts/framework/test_result.py | 5 +--
dts/framework/test_run.py | 24 +++++------
dts/tests/TestSuite_blocklist.py | 4 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 8 ++--
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 4 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 8 ++--
dts/tests/TestSuite_mac_filter.py | 4 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 12 +++---
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
dts/tests/TestSuite_pmd_rss.py | 6 +--
dts/tests/TestSuite_port_control.py | 2 +-
...stSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 12 +++---
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
.../TestSuite_single_core_forward_perf.py | 4 +-
dts/tests/TestSuite_smoke_tests.py | 6 +--
dts/tests/TestSuite_softnic.py | 6 +--
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 8 ++--
dts/tests/TestSuite_vlan.py | 2 +-
98 files changed, 359 insertions(+), 301 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
create mode 100644 doc/api/dts/framework.linux_session.rst
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/context.py (90%)
rename dts/{framework => api}/exception.py (100%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (89%)
rename dts/{framework => api}/params/types.py (94%)
rename dts/{framework => api}/test_suite.py (98%)
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
create mode 100644 dts/api/testbed_model/linux_session.py
rename dts/{framework => api}/testbed_model/node.py (96%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (96%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
rename dts/{framework => api}/utils.py (99%)
rename dts/framework/{testbed_model => }/linux_session.py (97%)
--
2.52.0
^ permalink raw reply [flat|nested] 81+ messages in thread* [PATCH v4 1/7] dts: move exception module from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 2/7] dts: move utils " Dean Marx
` (5 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.exception.rst => api.exception.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/capability.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/port.py | 2 +-
dts/framework/testbed_model/posix_session.py | 2 +-
dts/framework/testbed_model/topology.py | 2 +-
.../testbed_model/traffic_generator/__init__.py | 2 +-
dts/framework/testbed_model/traffic_generator/scapy.py | 2 +-
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
34 files changed, 40 insertions(+), 41 deletions(-)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename dts/{framework => api}/exception.py (100%)
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..01f630e7cd 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -36,7 +36,7 @@ Modules
framework.logger
framework.parser
framework.utils
- framework.exception
+ api.exception
Indices and tables
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..7d04c7ab49 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,7 +47,7 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
from framework.testbed_model.node import Node, NodeIdentifier, get_node
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..cabb39a8dd 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,9 +27,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..566dc7c4a2 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..62aaba033a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..7e61c85998 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,7 +8,7 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..d803a9e4bd 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -25,7 +26,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..fdd074be3a 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,12 +29,12 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..a0d8039a04 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,8 +12,8 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from framework.testbed_model.node import Node
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..3cecb928ca 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
from framework.testbed_model.os_session import OSSessionInfo
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..bbaf4f1fdf 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,9 +106,9 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 69ce26040a..e06fdd28b9 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-from .exception import ConfigurationError, InternalError
from .logger import DTSLogger, get_dts_logger
from .utils import to_pascal_case
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..001b65994c 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -64,7 +64,7 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
from framework.logger import get_dts_logger
from framework.testbed_model.node import Node
from framework.testbed_model.port import DriverKind
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index ee943462c2..88b6da1ae6 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -18,7 +18,7 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/framework/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index dec952685a..db2c3c0c40 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -16,7 +16,7 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
from framework.settings import SETTINGS
from framework.utils import (
MesonArgs,
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 34862c4d2e..805a762c19 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -18,7 +18,7 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
+from api.exception import ConfigurationError, InternalError
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.node import Node, NodeIdentifier
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index fca251f534..324b5e88f3 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -14,12 +14,12 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index c6e9006205..e983443548 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -25,9 +25,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
from framework.testbed_model.node import Node
from framework.testbed_model.port import Port
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..f36b48a153 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,9 +29,9 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from framework.context import get_ctx
-from framework.exception import SkippedTestException
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..b62efa2b42 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,11 +35,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..b44822d31c 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,10 +23,10 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..1e5a6860be 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.testpmd import TestPmd
@@ -29,7 +30,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..7e50a075ac 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,15 +21,15 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
-from api.packet import send_packet_and_capture
-from api.test import fail, log, verify
-from api.testpmd import TestPmd
-from api.testpmd.types import FlowRule
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
SkippedTestException,
TestCaseVerifyError,
)
+from api.packet import send_packet_and_capture
+from api.test import fail, log, verify
+from api.testpmd import TestPmd
+from api.testpmd.types import FlowRule
from framework.test_suite import TestSuite, func_test
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 2/7] dts: move utils from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-28 18:08 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 3/7] dts: move context " Dean Marx
` (4 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/cpu.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/os_session.py | 2 +-
dts/framework/testbed_model/posix_session.py | 4 ++--
.../traffic_generator/capturing_traffic_generator.py | 2 +-
.../testbed_model/traffic_generator/traffic_generator.py | 2 +-
dts/framework/testbed_model/traffic_generator/trex.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
22 files changed, 22 insertions(+), 22 deletions(-)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
rename dts/{framework => api}/utils.py (100%)
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 01f630e7cd..783270f6e9 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -35,7 +35,7 @@ Modules
framework.context
framework.logger
framework.parser
- framework.utils
+ api.utils
api.exception
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index cabb39a8dd..b7a9bb28bf 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -29,6 +29,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
+from api.utils import get_packet_summaries
from framework.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -36,7 +37,6 @@
from framework.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..28f23389a7 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 62aaba033a..977067f42a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index d803a9e4bd..69b47b823b 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -14,6 +14,7 @@
from typing import ClassVar, Final
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.testbed_model.node import Node
from framework.testbed_model.os_session import OSSession
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index e06fdd28b9..426c98fdf6 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index 6e2ecca080..52ef196f84 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -24,7 +24,7 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 88b6da1ae6..69b0923744 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.utils import expand_range
from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index 2c267afed1..7bb339fab2 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index db2c3c0c40..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -17,14 +17,14 @@
from pathlib import Path, PurePath, PurePosixPath
from api.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..2804d64990 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.utils import get_packet_summaries
from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..fedce77fdf 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/framework/testbed_model/traffic_generator/trex.py
index 22cd20dea9..2064703fcc 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/framework/testbed_model/traffic_generator/trex.py
@@ -11,6 +11,7 @@
from scapy.packet import Packet
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
@@ -23,7 +24,6 @@
PerformanceTrafficGenerator,
PerformanceTrafficStats,
)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..1e99b82b8c 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -20,10 +20,10 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 1e5a6860be..4df273e3e1 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -30,8 +30,8 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
+from api.utils import StrEnum
from framework.test_suite import BaseConfig, TestSuite, func_test
-from framework.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..fce83604a6 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,11 +20,11 @@
)
from api.test import verify
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..c57a12c932 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -20,9 +20,9 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
+from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 3/7] dts: move context from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-28 18:08 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
2026-04-28 18:08 ` [PATCH v4 2/7] dts: move utils " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
` (3 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.context.rst => api.context.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/test_suite.py | 4 ++--
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/topology.py | 14 +++++++-------
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
18 files changed, 25 insertions(+), 25 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename dts/{framework => api}/context.py (100%)
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 783270f6e9..98269d6e80 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -32,7 +32,7 @@ Modules
framework.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
api.utils
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 7d04c7ab49..f3dd07de56 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index b7a9bb28bf..59f26da833 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -30,7 +30,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
@@ -82,7 +82,7 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..07db6dfeb0 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,7 +30,7 @@
from typing_extensions import Self
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 69b47b823b..9f7cd60dfe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -26,7 +26,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..a8f169787c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,7 +10,7 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index fdd074be3a..d138727c85 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -34,7 +34,7 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index bbaf4f1fdf..605a916ebb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,7 +108,7 @@
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 426c98fdf6..6066f7a77a 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -38,7 +38,7 @@
from .logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -92,7 +92,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 805a762c19..5b6ff2add5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index f36b48a153..39784cbcac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,7 +31,7 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 1e99b82b8c..c018efb1f7 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -21,7 +21,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 4/7] dts: move testbed model from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-28 18:08 ` [PATCH v4 3/7] dts: move context " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
` (2 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 +++---
dts/api/context.py | 10 +++----
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 12 ++++----
dts/api/test.py | 2 +-
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 10 +++----
dts/{framework => api}/testbed_model/cpu.py | 2 +-
.../testbed_model/linux_session.py | 2 +-
dts/{framework => api}/testbed_model/node.py | 0
.../testbed_model/os_session.py | 6 ++--
dts/{framework => api}/testbed_model/port.py | 0
.../testbed_model/posix_session.py | 0
.../testbed_model/topology.py | 4 +--
.../traffic_generator/__init__.py | 2 +-
.../capturing_traffic_generator.py | 2 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 12 ++++----
.../traffic_generator/traffic_generator.py | 6 ++--
.../testbed_model/traffic_generator/trex.py | 14 +++++-----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 2 +-
dts/framework/params/eal.py | 6 ++--
dts/framework/params/types.py | 6 ++--
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 10 +++----
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 4 +--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 18 ++++++------
dts/framework/test_suite.py | 4 +--
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 4 +--
dts/tests/TestSuite_l2fwd.py | 4 +--
dts/tests/TestSuite_packet_capture.py | 8 +++---
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 ++--
57 files changed, 148 insertions(+), 148 deletions(-)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (99%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (100%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (100%)
rename dts/{framework => api}/testbed_model/posix_session.py (100%)
rename dts/{framework => api}/testbed_model/topology.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (97%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (94%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (97%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 98269d6e80..f47e4af3f2 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,7 +16,7 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
framework.params
framework.config
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index f3dd07de56..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -48,9 +48,9 @@
from typing_extensions import Buffer
from api.exception import InternalError
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..04fc20738b 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/context.py b/dts/api/context.py
index 7e61c85998..13a2ad6c39 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -9,17 +9,17 @@
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
from api.exception import InternalError
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.test_suite import TestCase, TestSuite
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..1ba8e0d977 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,7 +24,6 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 59f26da833..bf90961c26 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,16 +27,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
-from api.utils import get_packet_summaries
-from api.context import get_ctx
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
def send_packet_and_capture(
@@ -83,7 +83,7 @@ def send_packets_and_capture(
A list of received packets.
"""
from api.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 99%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 001b65994c..4e4e976be5 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -65,10 +65,10 @@ def test_scatter_mbuf_2048(self):
from api.capabilities import LinkTopology, NicCapability
from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.testpmd import TestPmd
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 52ef196f84..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -29,7 +29,7 @@
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index 69b0923744..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.testbed_model.port import PortInfo
from api.utils import expand_range
-from framework.testbed_model.port import PortInfo
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 100%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 7bb339fab2..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 100%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 100%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 99%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 5b6ff2add5..11593d64d5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -19,8 +19,8 @@
from api.capabilities import LinkTopology
from api.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index 324b5e88f3..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -15,12 +15,12 @@
"""
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 99%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 2804d64990..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.testbed_model.port import Port
from api.utils import get_packet_summaries
-from framework.testbed_model.port import Port
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index e983443548..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -26,15 +26,15 @@
from scapy.packet import Packet
from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 94%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index fedce77fdf..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 2064703fcc..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..9f47a15433 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
@@ -55,7 +56,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 07db6dfeb0..84db3974b1 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,11 +31,11 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 9f7cd60dfe..713a564d25 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,12 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
@@ -26,14 +31,9 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index a8f169787c..b807f9bdae 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,12 +11,12 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.testbed_model.cpu import LogicalCoreList
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index d138727c85..ec539bad95 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,16 +29,16 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index a0d8039a04..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -13,9 +13,9 @@
import textwrap
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 3cecb928ca..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -36,9 +36,9 @@
from typing_extensions import OrderedDict
from api.exception import DTSError, ErrorSeverity, InternalError
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
class Result(IntEnum):
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 605a916ebb..790fbf997d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,22 +106,22 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 6066f7a77a..786cfc7bff 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..97e03b8fb7 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 39784cbcac..fc4b3cb308 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -31,9 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from api.context import get_ctx
+from api.testbed_model.virtual_device import VirtualDevice
from framework.test_suite import BaseConfig, TestSuite, crypto_test
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index c018efb1f7..5650366c36 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,17 +13,17 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreCount
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..042b7019aa 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,15 +36,15 @@
send_packets_and_capture,
)
from api.test import verify
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index fce83604a6..656e2e4bb7 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.linux_session import LinuxSession
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index c57a12c932..91a6d4eb9f 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.virtual_device import VirtualDevice
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..c649aac197 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 5/7] dts: move test suite module from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-28 18:08 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
2026-04-28 18:08 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.test_suite.rst => api.test_suite.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/capabilities.py | 6 +++---
dts/api/context.py | 2 +-
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 3 +--
dts/api/testbed_model/capability.py | 6 +++---
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
37 files changed, 45 insertions(+), 46 deletions(-)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index f47e4af3f2..7c282bbba1 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -29,7 +29,7 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ api.test_suite
framework.test_result
framework.settings
api.context
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 04fc20738b..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/context.py b/dts/api/context.py
index 13a2ad6c39..7ed4cc5665 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -16,10 +16,10 @@
from framework.settings import SETTINGS
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from api.testbed_model.capability import TestProtocol
from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
P = ParamSpec("P")
diff --git a/dts/api/packet.py b/dts/api/packet.py
index bf90961c26..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 786cfc7bff..0822f9bfe5 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -34,8 +34,7 @@
from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-
-from .logger import DTSLogger, get_dts_logger
+from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
from api.context import Context
diff --git a/dts/api/testbed_model/capability.py b/dts/api/testbed_model/capability.py
index 4e4e976be5..95583261d8 100644
--- a/dts/api/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.logger import get_dts_logger
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 566dc7c4a2..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 977067f42a..81e3dba79b 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 790fbf997d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,6 +108,7 @@
from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
get_supported_capabilities,
@@ -121,7 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 97e03b8fb7..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fc4b3cb308..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -32,8 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index b62efa2b42..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -38,9 +38,9 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 5650366c36..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,11 +19,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index b44822d31c..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -26,8 +26,8 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 042b7019aa..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,6 +36,7 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -44,7 +45,6 @@
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 4df273e3e1..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -23,6 +23,7 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -31,7 +32,6 @@
TestPmdVerbosePacket,
)
from api.utils import StrEnum
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 7e50a075ac..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 656e2e4bb7..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 91a6d4eb9f..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index c649aac197..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import requires
from api.testbed_model.linux_session import LinuxSession
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestVirtioFwd(TestSuite):
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 6/7] dts: move params directory from framework to API
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-28 18:08 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
2026-04-28 18:08 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.params.eal.rst => api.params.eal.rst} | 2 +-
doc/api/dts/{framework.params.rst => api.params.rst} | 6 +++---
.../{framework.params.types.rst => api.params.types.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/api/cryptodev/config.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 8 ++++++--
dts/api/testpmd/__init__.py | 7 ++++++-
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 4 ++--
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
17 files changed, 32 insertions(+), 23 deletions(-)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (97%)
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 7c282bbba1..e89e782ac0 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -18,7 +18,7 @@ Packages
api
api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 1ba8e0d977..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -27,7 +27,7 @@
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 97%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..2c215cfe54 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -56,7 +58,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9f47a15433..85ebe2ea65 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -56,7 +59,9 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.params.types import TestPmdParamsDict
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 84db3974b1..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,9 +31,9 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.params import Params
+from api.params.eal import EalParams
from api.testbed_model.node import Node
-from framework.params import Params
-from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 713a564d25..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -15,6 +15,7 @@
from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -32,7 +33,6 @@
RemoteDPDKTreeLocation,
)
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index b807f9bdae..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,8 +11,8 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCoreList
-from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index ec539bad95..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,9 +35,9 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 7/7] dts: separate Linux session into interface and logic
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-28 18:08 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
@ 2026-04-28 18:08 ` Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-28 18:08 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/framework.linux_session.rst | 8 +
doc/api/dts/index.rst | 1 +
dts/api/testbed_model/linux_session.py | 372 ++----------------------
dts/api/testbed_model/node.py | 8 +-
dts/framework/linux_session.py | 366 +++++++++++++++++++++++
5 files changed, 403 insertions(+), 352 deletions(-)
create mode 100644 doc/api/dts/framework.linux_session.rst
create mode 100644 dts/framework/linux_session.py
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..9de2e1484d
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+framework.linux\_session
+========================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index e89e782ac0..0dbc18b75c 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -37,6 +37,7 @@ Modules
framework.parser
api.utils
api.exception
+ framework.linux_session
Indices and tables
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..5bcbf1ce97 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -1,367 +1,41 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
+"""Linux OS session interface.
-"""Linux OS translator.
-
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
+from abc import ABC, abstractmethod
from pathlib import PurePath
-from typing import TypedDict
-
-from typing_extensions import NotRequired
-
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
-
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
- """
-
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations."""
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
+ @property
+ @abstractmethod
def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
+ """The path to the devbind script."""
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+ @abstractmethod
+ def set_interface_link_up(self, name: str) -> None:
+ """Set the link status of an interface to up.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface.
"""
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def delete_interface(self, name: str) -> None:
+ """Delete a virtual interface.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface to delete.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..51abbd098b 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -15,17 +15,19 @@
from functools import cached_property
from pathlib import PurePath
-from typing import Literal, TypeAlias
+from typing import TYPE_CHECKING, Literal, TypeAlias
from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
+
+if TYPE_CHECKING:
+ from framework.linux_session import LinuxSession
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
@@ -211,7 +213,7 @@ def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger)
"""
match node_config.os:
case OS.linux:
- return LinuxSession(node_config, name, logger)
+ return "LinuxSession"(node_config, name, logger)
case _:
raise ConfigurationError(f"Unsupported OS {node_config.os}")
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..e5320b7fc4
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,366 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS translator.
+
+Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
+compliant with POSIX standards, so this module only implements the parts that aren't.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from functools import cached_property
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """The implementation of non-Posix compliant parts of Linux."""
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ # when forcing numa, we need to clear existing hugepages regardless
+ # of size, so they can be moved to the first numa node
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ # the file doesn't exist, meaning the node doesn't support numa
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ # the system supports numa if self._numa_nodes is non-empty and there are more
+ # than one numa node (in the latter case it may actually support numa, but
+ # there's no reason to do any numa specific configuration)
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ # clear non-numa hugepages
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
+
+ The :attr:`~.devbind_script_path` property must be setup in order to call this method.
+ """
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+
+ del self._lshw_net_info
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+
+ del self._lshw_net_info
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ @cached_property
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Needs to be manually assigned first in order to be used.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ raise InternalError("Accessed devbind script path before setup.")
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~os_session.OSSession,load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self.refresh_lshw()
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+
+ self.refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self.refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ @cached_property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ return json.loads(output.stdout)
+
+ def refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info."""
+ if "_lshw_net_info" in self.__dict__:
+ del self.__dict__["_lshw_net_info"]
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread
* [PATCH v4 0/7] dts: move test suite imports from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (7 preceding siblings ...)
2026-04-28 18:08 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
` (6 more replies)
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
9 siblings, 7 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
This series moves various modules from the framework directory
to the API based on which are being imported by test suites.
These include:
- test_suite
- testbed_model
- exception
- utils
- context
- params
This eliminates all test suite framework imports except for
the remote_session imports in packet_capture, as well
as the settings/config imports in smoke_tests. I believe these
imports, and what to do with them, should be a topic of discussion
in future DTS meetings, as I don't believe they should reside in the
API, even if they are being imported in test suites.
In addition to these changes, I've split the linux_session module
into an interface in api/testbed_model/linux_session and an
implementation in framework/linux_session. This way, users
can still import linux session if necessary, without exposing
the backend implementation.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
v2:
* Integrated rst updates with corresponding commits for build testing
v3:
* Fixed commit ordering to resolve import inconsistency
* Updated Linux Session interface with test suite methods
v4:
* Added missing SPDX tag to framework.linux_session.rst
Dean Marx (7):
dts: move exception module from framework to API
dts: move utils from framework to API
dts: move context from framework to API
dts: move testbed model from framework to API
dts: move test suite module from framework to API
dts: move params directory from framework to API
dts: separate Linux session into interface and logic
...{framework.context.rst => api.context.rst} | 2 +-
...mework.exception.rst => api.exception.rst} | 2 +-
...work.params.eal.rst => api.params.eal.rst} | 2 +-
.../{framework.params.rst => api.params.rst} | 6 +--
....params.types.rst => api.params.types.rst} | 2 +-
...work.test_suite.rst => api.test_suite.rst} | 2 +-
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 ++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
.../{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 8 ++++
doc/api/dts/framework.testbed_model.rst | 28 -------------
...mework.testbed_model.traffic_generator.rst | 16 --------
doc/api/dts/index.rst | 13 +++---
dts/api/artifact.py | 6 +--
dts/api/capabilities.py | 14 +++----
dts/{framework => api}/context.py | 14 +++----
dts/api/cryptodev/__init__.py | 6 +--
dts/api/cryptodev/config.py | 6 +--
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 18 ++++----
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 8 ++--
dts/{framework => api}/params/types.py | 14 ++++---
dts/api/test.py | 4 +-
dts/{framework => api}/test_suite.py | 15 ++++---
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 18 ++++----
dts/{framework => api}/testbed_model/cpu.py | 4 +-
dts/api/testbed_model/linux_session.py | 41 +++++++++++++++++++
dts/{framework => api}/testbed_model/node.py | 12 +++---
.../testbed_model/os_session.py | 8 ++--
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 +--
.../testbed_model/topology.py | 20 ++++-----
.../traffic_generator/__init__.py | 4 +-
.../capturing_traffic_generator.py | 4 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++----
.../traffic_generator/traffic_generator.py | 8 ++--
.../testbed_model/traffic_generator/trex.py | 16 ++++----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 11 +++--
dts/api/testpmd/config.py | 6 +--
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 2 +-
dts/framework/config/__init__.py | 6 +--
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 12 +++---
.../{testbed_model => }/linux_session.py | 15 ++++---
dts/framework/parser.py | 2 +-
dts/framework/remote_session/blocking_app.py | 8 ++--
dts/framework/remote_session/dpdk.py | 16 ++++----
dts/framework/remote_session/dpdk_shell.py | 6 +--
.../interactive_remote_session.py | 2 +-
.../remote_session/interactive_shell.py | 8 ++--
.../remote_session/remote_session.py | 4 +-
dts/framework/runner.py | 4 +-
dts/framework/test_result.py | 5 +--
dts/framework/test_run.py | 24 +++++------
dts/tests/TestSuite_blocklist.py | 4 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 8 ++--
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 4 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 8 ++--
dts/tests/TestSuite_mac_filter.py | 4 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 12 +++---
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
dts/tests/TestSuite_pmd_rss.py | 6 +--
dts/tests/TestSuite_port_control.py | 2 +-
...stSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 12 +++---
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
.../TestSuite_single_core_forward_perf.py | 4 +-
dts/tests/TestSuite_smoke_tests.py | 6 +--
dts/tests/TestSuite_softnic.py | 6 +--
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 8 ++--
dts/tests/TestSuite_vlan.py | 2 +-
98 files changed, 359 insertions(+), 301 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
create mode 100644 doc/api/dts/framework.linux_session.rst
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/context.py (90%)
rename dts/{framework => api}/exception.py (100%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (89%)
rename dts/{framework => api}/params/types.py (94%)
rename dts/{framework => api}/test_suite.py (98%)
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
create mode 100644 dts/api/testbed_model/linux_session.py
rename dts/{framework => api}/testbed_model/node.py (96%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (96%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
rename dts/{framework => api}/utils.py (99%)
rename dts/framework/{testbed_model => }/linux_session.py (97%)
--
2.52.0
^ permalink raw reply [flat|nested] 81+ messages in thread* [PATCH v4 1/7] dts: move exception module from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 2/7] dts: move utils " Dean Marx
` (5 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.exception.rst => api.exception.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/capability.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/port.py | 2 +-
dts/framework/testbed_model/posix_session.py | 2 +-
dts/framework/testbed_model/topology.py | 2 +-
.../testbed_model/traffic_generator/__init__.py | 2 +-
dts/framework/testbed_model/traffic_generator/scapy.py | 2 +-
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
34 files changed, 40 insertions(+), 41 deletions(-)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename dts/{framework => api}/exception.py (100%)
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..01f630e7cd 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -36,7 +36,7 @@ Modules
framework.logger
framework.parser
framework.utils
- framework.exception
+ api.exception
Indices and tables
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..7d04c7ab49 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,7 +47,7 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
from framework.testbed_model.node import Node, NodeIdentifier, get_node
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..cabb39a8dd 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,9 +27,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..566dc7c4a2 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..62aaba033a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..7e61c85998 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,7 +8,7 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..d803a9e4bd 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -25,7 +26,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..fdd074be3a 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,12 +29,12 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..a0d8039a04 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,8 +12,8 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from framework.testbed_model.node import Node
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..3cecb928ca 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
from framework.testbed_model.os_session import OSSessionInfo
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..bbaf4f1fdf 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,9 +106,9 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 69ce26040a..e06fdd28b9 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-from .exception import ConfigurationError, InternalError
from .logger import DTSLogger, get_dts_logger
from .utils import to_pascal_case
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..001b65994c 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -64,7 +64,7 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
from framework.logger import get_dts_logger
from framework.testbed_model.node import Node
from framework.testbed_model.port import DriverKind
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index ee943462c2..88b6da1ae6 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -18,7 +18,7 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/framework/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index dec952685a..db2c3c0c40 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -16,7 +16,7 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
from framework.settings import SETTINGS
from framework.utils import (
MesonArgs,
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 34862c4d2e..805a762c19 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -18,7 +18,7 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
+from api.exception import ConfigurationError, InternalError
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.node import Node, NodeIdentifier
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index fca251f534..324b5e88f3 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -14,12 +14,12 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index c6e9006205..e983443548 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -25,9 +25,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
from framework.testbed_model.node import Node
from framework.testbed_model.port import Port
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..f36b48a153 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,9 +29,9 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from framework.context import get_ctx
-from framework.exception import SkippedTestException
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..b62efa2b42 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,11 +35,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..b44822d31c 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,10 +23,10 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..1e5a6860be 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.testpmd import TestPmd
@@ -29,7 +30,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..7e50a075ac 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,15 +21,15 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
-from api.packet import send_packet_and_capture
-from api.test import fail, log, verify
-from api.testpmd import TestPmd
-from api.testpmd.types import FlowRule
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
SkippedTestException,
TestCaseVerifyError,
)
+from api.packet import send_packet_and_capture
+from api.test import fail, log, verify
+from api.testpmd import TestPmd
+from api.testpmd.types import FlowRule
from framework.test_suite import TestSuite, func_test
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 2/7] dts: move utils from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-30 21:09 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 3/7] dts: move context " Dean Marx
` (4 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/cpu.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/os_session.py | 2 +-
dts/framework/testbed_model/posix_session.py | 4 ++--
.../traffic_generator/capturing_traffic_generator.py | 2 +-
.../testbed_model/traffic_generator/traffic_generator.py | 2 +-
dts/framework/testbed_model/traffic_generator/trex.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
22 files changed, 22 insertions(+), 22 deletions(-)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
rename dts/{framework => api}/utils.py (100%)
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 01f630e7cd..783270f6e9 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -35,7 +35,7 @@ Modules
framework.context
framework.logger
framework.parser
- framework.utils
+ api.utils
api.exception
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index cabb39a8dd..b7a9bb28bf 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -29,6 +29,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
+from api.utils import get_packet_summaries
from framework.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -36,7 +37,6 @@
from framework.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..28f23389a7 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 62aaba033a..977067f42a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index d803a9e4bd..69b47b823b 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -14,6 +14,7 @@
from typing import ClassVar, Final
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.testbed_model.node import Node
from framework.testbed_model.os_session import OSSession
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index e06fdd28b9..426c98fdf6 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index 6e2ecca080..52ef196f84 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -24,7 +24,7 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 88b6da1ae6..69b0923744 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.utils import expand_range
from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index 2c267afed1..7bb339fab2 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index db2c3c0c40..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -17,14 +17,14 @@
from pathlib import Path, PurePath, PurePosixPath
from api.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..2804d64990 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.utils import get_packet_summaries
from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..fedce77fdf 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/framework/testbed_model/traffic_generator/trex.py
index 22cd20dea9..2064703fcc 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/framework/testbed_model/traffic_generator/trex.py
@@ -11,6 +11,7 @@
from scapy.packet import Packet
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
@@ -23,7 +24,6 @@
PerformanceTrafficGenerator,
PerformanceTrafficStats,
)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..1e99b82b8c 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -20,10 +20,10 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 1e5a6860be..4df273e3e1 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -30,8 +30,8 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
+from api.utils import StrEnum
from framework.test_suite import BaseConfig, TestSuite, func_test
-from framework.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..fce83604a6 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,11 +20,11 @@
)
from api.test import verify
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..c57a12c932 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -20,9 +20,9 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
+from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 3/7] dts: move context from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-30 21:09 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
2026-04-30 21:09 ` [PATCH v4 2/7] dts: move utils " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
` (3 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.context.rst => api.context.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/test_suite.py | 4 ++--
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/topology.py | 14 +++++++-------
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
18 files changed, 25 insertions(+), 25 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename dts/{framework => api}/context.py (100%)
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 783270f6e9..98269d6e80 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -32,7 +32,7 @@ Modules
framework.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
api.utils
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 7d04c7ab49..f3dd07de56 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index b7a9bb28bf..59f26da833 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -30,7 +30,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
@@ -82,7 +82,7 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..07db6dfeb0 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,7 +30,7 @@
from typing_extensions import Self
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 69b47b823b..9f7cd60dfe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -26,7 +26,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..a8f169787c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,7 +10,7 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index fdd074be3a..d138727c85 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -34,7 +34,7 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index bbaf4f1fdf..605a916ebb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,7 +108,7 @@
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 426c98fdf6..6066f7a77a 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -38,7 +38,7 @@
from .logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -92,7 +92,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 805a762c19..5b6ff2add5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index f36b48a153..39784cbcac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,7 +31,7 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 1e99b82b8c..c018efb1f7 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -21,7 +21,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 4/7] dts: move testbed model from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-30 21:09 ` [PATCH v4 3/7] dts: move context " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
` (2 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 +++---
dts/api/context.py | 10 +++----
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 12 ++++----
dts/api/test.py | 2 +-
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 10 +++----
dts/{framework => api}/testbed_model/cpu.py | 2 +-
.../testbed_model/linux_session.py | 2 +-
dts/{framework => api}/testbed_model/node.py | 0
.../testbed_model/os_session.py | 6 ++--
dts/{framework => api}/testbed_model/port.py | 0
.../testbed_model/posix_session.py | 0
.../testbed_model/topology.py | 4 +--
.../traffic_generator/__init__.py | 2 +-
.../capturing_traffic_generator.py | 2 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 12 ++++----
.../traffic_generator/traffic_generator.py | 6 ++--
.../testbed_model/traffic_generator/trex.py | 14 +++++-----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 2 +-
dts/framework/params/eal.py | 6 ++--
dts/framework/params/types.py | 6 ++--
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 10 +++----
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 4 +--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 18 ++++++------
dts/framework/test_suite.py | 4 +--
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 4 +--
dts/tests/TestSuite_l2fwd.py | 4 +--
dts/tests/TestSuite_packet_capture.py | 8 +++---
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 ++--
57 files changed, 148 insertions(+), 148 deletions(-)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (99%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (100%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (100%)
rename dts/{framework => api}/testbed_model/posix_session.py (100%)
rename dts/{framework => api}/testbed_model/topology.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (97%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (94%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (97%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 98269d6e80..f47e4af3f2 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,7 +16,7 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
framework.params
framework.config
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index f3dd07de56..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -48,9 +48,9 @@
from typing_extensions import Buffer
from api.exception import InternalError
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..04fc20738b 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/context.py b/dts/api/context.py
index 7e61c85998..13a2ad6c39 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -9,17 +9,17 @@
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
from api.exception import InternalError
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.test_suite import TestCase, TestSuite
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..1ba8e0d977 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,7 +24,6 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 59f26da833..bf90961c26 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,16 +27,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
-from api.utils import get_packet_summaries
-from api.context import get_ctx
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
def send_packet_and_capture(
@@ -83,7 +83,7 @@ def send_packets_and_capture(
A list of received packets.
"""
from api.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 99%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 001b65994c..4e4e976be5 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -65,10 +65,10 @@ def test_scatter_mbuf_2048(self):
from api.capabilities import LinkTopology, NicCapability
from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.testpmd import TestPmd
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 52ef196f84..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -29,7 +29,7 @@
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index 69b0923744..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.testbed_model.port import PortInfo
from api.utils import expand_range
-from framework.testbed_model.port import PortInfo
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 100%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 7bb339fab2..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 100%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 100%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 99%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 5b6ff2add5..11593d64d5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -19,8 +19,8 @@
from api.capabilities import LinkTopology
from api.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index 324b5e88f3..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -15,12 +15,12 @@
"""
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 99%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 2804d64990..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.testbed_model.port import Port
from api.utils import get_packet_summaries
-from framework.testbed_model.port import Port
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index e983443548..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -26,15 +26,15 @@
from scapy.packet import Packet
from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 94%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index fedce77fdf..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 2064703fcc..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..9f47a15433 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
@@ -55,7 +56,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 07db6dfeb0..84db3974b1 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,11 +31,11 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 9f7cd60dfe..713a564d25 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,12 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
@@ -26,14 +31,9 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index a8f169787c..b807f9bdae 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,12 +11,12 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.testbed_model.cpu import LogicalCoreList
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index d138727c85..ec539bad95 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,16 +29,16 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index a0d8039a04..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -13,9 +13,9 @@
import textwrap
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 3cecb928ca..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -36,9 +36,9 @@
from typing_extensions import OrderedDict
from api.exception import DTSError, ErrorSeverity, InternalError
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
class Result(IntEnum):
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 605a916ebb..790fbf997d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,22 +106,22 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 6066f7a77a..786cfc7bff 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..97e03b8fb7 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 39784cbcac..fc4b3cb308 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -31,9 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from api.context import get_ctx
+from api.testbed_model.virtual_device import VirtualDevice
from framework.test_suite import BaseConfig, TestSuite, crypto_test
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index c018efb1f7..5650366c36 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,17 +13,17 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreCount
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..042b7019aa 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,15 +36,15 @@
send_packets_and_capture,
)
from api.test import verify
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index fce83604a6..656e2e4bb7 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.linux_session import LinuxSession
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index c57a12c932..91a6d4eb9f 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.virtual_device import VirtualDevice
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..c649aac197 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 5/7] dts: move test suite module from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-30 21:09 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
2026-04-30 21:09 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.test_suite.rst => api.test_suite.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/capabilities.py | 6 +++---
dts/api/context.py | 2 +-
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 3 +--
dts/api/testbed_model/capability.py | 6 +++---
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
37 files changed, 45 insertions(+), 46 deletions(-)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index f47e4af3f2..7c282bbba1 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -29,7 +29,7 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ api.test_suite
framework.test_result
framework.settings
api.context
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 04fc20738b..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/context.py b/dts/api/context.py
index 13a2ad6c39..7ed4cc5665 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -16,10 +16,10 @@
from framework.settings import SETTINGS
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from api.testbed_model.capability import TestProtocol
from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
P = ParamSpec("P")
diff --git a/dts/api/packet.py b/dts/api/packet.py
index bf90961c26..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 786cfc7bff..0822f9bfe5 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -34,8 +34,7 @@
from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-
-from .logger import DTSLogger, get_dts_logger
+from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
from api.context import Context
diff --git a/dts/api/testbed_model/capability.py b/dts/api/testbed_model/capability.py
index 4e4e976be5..95583261d8 100644
--- a/dts/api/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.logger import get_dts_logger
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 566dc7c4a2..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 977067f42a..81e3dba79b 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 790fbf997d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,6 +108,7 @@
from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
get_supported_capabilities,
@@ -121,7 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 97e03b8fb7..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fc4b3cb308..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -32,8 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index b62efa2b42..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -38,9 +38,9 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 5650366c36..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,11 +19,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index b44822d31c..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -26,8 +26,8 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 042b7019aa..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,6 +36,7 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -44,7 +45,6 @@
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 4df273e3e1..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -23,6 +23,7 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -31,7 +32,6 @@
TestPmdVerbosePacket,
)
from api.utils import StrEnum
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 7e50a075ac..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 656e2e4bb7..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 91a6d4eb9f..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index c649aac197..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import requires
from api.testbed_model.linux_session import LinuxSession
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestVirtioFwd(TestSuite):
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 6/7] dts: move params directory from framework to API
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-30 21:09 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
2026-04-30 21:09 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.params.eal.rst => api.params.eal.rst} | 2 +-
doc/api/dts/{framework.params.rst => api.params.rst} | 6 +++---
.../{framework.params.types.rst => api.params.types.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/api/cryptodev/config.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 8 ++++++--
dts/api/testpmd/__init__.py | 7 ++++++-
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 4 ++--
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
17 files changed, 32 insertions(+), 23 deletions(-)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (97%)
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 7c282bbba1..e89e782ac0 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -18,7 +18,7 @@ Packages
api
api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 1ba8e0d977..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -27,7 +27,7 @@
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 97%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..2c215cfe54 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -56,7 +58,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9f47a15433..85ebe2ea65 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -56,7 +59,9 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.params.types import TestPmdParamsDict
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 84db3974b1..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,9 +31,9 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.params import Params
+from api.params.eal import EalParams
from api.testbed_model.node import Node
-from framework.params import Params
-from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 713a564d25..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -15,6 +15,7 @@
from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -32,7 +33,6 @@
RemoteDPDKTreeLocation,
)
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index b807f9bdae..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,8 +11,8 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCoreList
-from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index ec539bad95..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,9 +35,9 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 7/7] dts: separate Linux session into interface and logic
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-30 21:09 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
@ 2026-04-30 21:09 ` Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 21:09 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/framework.linux_session.rst | 8 +
doc/api/dts/index.rst | 1 +
dts/api/testbed_model/linux_session.py | 372 ++----------------------
dts/api/testbed_model/node.py | 8 +-
dts/framework/linux_session.py | 366 +++++++++++++++++++++++
5 files changed, 403 insertions(+), 352 deletions(-)
create mode 100644 doc/api/dts/framework.linux_session.rst
create mode 100644 dts/framework/linux_session.py
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..9de2e1484d
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+framework.linux\_session
+========================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index e89e782ac0..0dbc18b75c 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -37,6 +37,7 @@ Modules
framework.parser
api.utils
api.exception
+ framework.linux_session
Indices and tables
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..5bcbf1ce97 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -1,367 +1,41 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
+"""Linux OS session interface.
-"""Linux OS translator.
-
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
+from abc import ABC, abstractmethod
from pathlib import PurePath
-from typing import TypedDict
-
-from typing_extensions import NotRequired
-
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
-
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
- """
-
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations."""
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
+ @property
+ @abstractmethod
def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
+ """The path to the devbind script."""
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+ @abstractmethod
+ def set_interface_link_up(self, name: str) -> None:
+ """Set the link status of an interface to up.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface.
"""
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def delete_interface(self, name: str) -> None:
+ """Delete a virtual interface.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface to delete.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..51abbd098b 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -15,17 +15,19 @@
from functools import cached_property
from pathlib import PurePath
-from typing import Literal, TypeAlias
+from typing import TYPE_CHECKING, Literal, TypeAlias
from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
+
+if TYPE_CHECKING:
+ from framework.linux_session import LinuxSession
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
@@ -211,7 +213,7 @@ def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger)
"""
match node_config.os:
case OS.linux:
- return LinuxSession(node_config, name, logger)
+ return "LinuxSession"(node_config, name, logger)
case _:
raise ConfigurationError(f"Unsupported OS {node_config.os}")
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..e5320b7fc4
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,366 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS translator.
+
+Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
+compliant with POSIX standards, so this module only implements the parts that aren't.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from functools import cached_property
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """The implementation of non-Posix compliant parts of Linux."""
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ # when forcing numa, we need to clear existing hugepages regardless
+ # of size, so they can be moved to the first numa node
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ # the file doesn't exist, meaning the node doesn't support numa
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ # the system supports numa if self._numa_nodes is non-empty and there are more
+ # than one numa node (in the latter case it may actually support numa, but
+ # there's no reason to do any numa specific configuration)
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ # clear non-numa hugepages
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
+
+ The :attr:`~.devbind_script_path` property must be setup in order to call this method.
+ """
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+
+ del self._lshw_net_info
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+
+ del self._lshw_net_info
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ @cached_property
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Needs to be manually assigned first in order to be used.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ raise InternalError("Accessed devbind script path before setup.")
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~os_session.OSSession,load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self.refresh_lshw()
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+
+ self.refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self.refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ @cached_property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ return json.loads(output.stdout)
+
+ def refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info."""
+ if "_lshw_net_info" in self.__dict__:
+ del self.__dict__["_lshw_net_info"]
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread
* [PATCH v4 0/7] dts: move test suite imports from framework to API
2026-04-24 17:01 ` [PATCH v3 0/7] dts: move test suite imports from framework to API Dean Marx
` (8 preceding siblings ...)
2026-04-30 21:09 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
` (6 more replies)
9 siblings, 7 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
This series moves various modules from the framework directory
to the API based on which are being imported by test suites.
These include:
- test_suite
- testbed_model
- exception
- utils
- context
- params
This eliminates all test suite framework imports except for
the remote_session imports in packet_capture, as well
as the settings/config imports in smoke_tests. I believe these
imports, and what to do with them, should be a topic of discussion
in future DTS meetings, as I don't believe they should reside in the
API, even if they are being imported in test suites.
In addition to these changes, I've split the linux_session module
into an interface in api/testbed_model/linux_session and an
implementation in framework/linux_session. This way, users
can still import linux session if necessary, without exposing
the backend implementation.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
v2:
* Integrated rst updates with corresponding commits for build testing
v3:
* Fixed commit ordering to resolve import inconsistency
* Updated Linux Session interface with test suite methods
v4:
* Added missing SPDX tag to framework.linux_session.rst
Dean Marx (7):
dts: move exception module from framework to API
dts: move utils from framework to API
dts: move context from framework to API
dts: move testbed model from framework to API
dts: move test suite module from framework to API
dts: move params directory from framework to API
dts: separate Linux session into interface and logic
...{framework.context.rst => api.context.rst} | 2 +-
...mework.exception.rst => api.exception.rst} | 2 +-
...work.params.eal.rst => api.params.eal.rst} | 2 +-
.../{framework.params.rst => api.params.rst} | 6 +--
....params.types.rst => api.params.types.rst} | 2 +-
...work.test_suite.rst => api.test_suite.rst} | 2 +-
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 ++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
.../{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/framework.linux_session.rst | 8 ++++
doc/api/dts/framework.testbed_model.rst | 28 -------------
...mework.testbed_model.traffic_generator.rst | 16 --------
doc/api/dts/index.rst | 13 +++---
dts/api/artifact.py | 6 +--
dts/api/capabilities.py | 14 +++----
dts/{framework => api}/context.py | 14 +++----
dts/api/cryptodev/__init__.py | 6 +--
dts/api/cryptodev/config.py | 6 +--
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 18 ++++----
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 8 ++--
dts/{framework => api}/params/types.py | 14 ++++---
dts/api/test.py | 4 +-
dts/{framework => api}/test_suite.py | 15 ++++---
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 18 ++++----
dts/{framework => api}/testbed_model/cpu.py | 4 +-
dts/api/testbed_model/linux_session.py | 41 +++++++++++++++++++
dts/{framework => api}/testbed_model/node.py | 10 +++--
.../testbed_model/os_session.py | 8 ++--
dts/{framework => api}/testbed_model/port.py | 2 +-
.../testbed_model/posix_session.py | 6 +--
.../testbed_model/topology.py | 20 ++++-----
.../traffic_generator/__init__.py | 4 +-
.../capturing_traffic_generator.py | 4 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 14 +++----
.../traffic_generator/traffic_generator.py | 8 ++--
.../testbed_model/traffic_generator/trex.py | 16 ++++----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 11 +++--
dts/api/testpmd/config.py | 6 +--
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 2 +-
dts/framework/config/__init__.py | 6 +--
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 12 +++---
.../{testbed_model => }/linux_session.py | 15 ++++---
dts/framework/parser.py | 2 +-
dts/framework/remote_session/blocking_app.py | 8 ++--
dts/framework/remote_session/dpdk.py | 16 ++++----
dts/framework/remote_session/dpdk_shell.py | 6 +--
.../interactive_remote_session.py | 2 +-
.../remote_session/interactive_shell.py | 8 ++--
.../remote_session/remote_session.py | 4 +-
dts/framework/runner.py | 4 +-
dts/framework/test_result.py | 5 +--
dts/framework/test_run.py | 24 +++++------
dts/tests/TestSuite_blocklist.py | 4 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 8 ++--
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 4 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 8 ++--
dts/tests/TestSuite_mac_filter.py | 4 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 12 +++---
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
dts/tests/TestSuite_pmd_rss.py | 6 +--
dts/tests/TestSuite_port_control.py | 2 +-
...stSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 12 +++---
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
.../TestSuite_single_core_forward_perf.py | 4 +-
dts/tests/TestSuite_smoke_tests.py | 6 +--
dts/tests/TestSuite_softnic.py | 6 +--
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 8 ++--
dts/tests/TestSuite_vlan.py | 2 +-
98 files changed, 358 insertions(+), 300 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
create mode 100644 doc/api/dts/framework.linux_session.rst
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/context.py (90%)
rename dts/{framework => api}/exception.py (100%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (89%)
rename dts/{framework => api}/params/types.py (94%)
rename dts/{framework => api}/test_suite.py (98%)
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (98%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
create mode 100644 dts/api/testbed_model/linux_session.py
rename dts/{framework => api}/testbed_model/node.py (97%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (98%)
rename dts/{framework => api}/testbed_model/posix_session.py (99%)
rename dts/{framework => api}/testbed_model/topology.py (96%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (95%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (91%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (96%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
rename dts/{framework => api}/utils.py (99%)
rename dts/framework/{testbed_model => }/linux_session.py (97%)
--
2.52.0
^ permalink raw reply [flat|nested] 81+ messages in thread* [PATCH v4 1/7] dts: move exception module from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 2/7] dts: move utils " Dean Marx
` (5 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites currently import the exception module
from the framework in order to catch certain errors during
test execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.exception.rst => api.exception.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/{framework => api}/exception.py | 0
dts/api/packet.py | 2 +-
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/config/__init__.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/context.py | 2 +-
dts/framework/parser.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
.../remote_session/interactive_remote_session.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 4 ++--
dts/framework/remote_session/remote_session.py | 4 ++--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 3 +--
dts/framework/test_run.py | 4 ++--
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/capability.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/port.py | 2 +-
dts/framework/testbed_model/posix_session.py | 2 +-
dts/framework/testbed_model/topology.py | 2 +-
.../testbed_model/traffic_generator/__init__.py | 2 +-
dts/framework/testbed_model/traffic_generator/scapy.py | 2 +-
dts/framework/utils.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
| 2 +-
dts/tests/TestSuite_rte_flow.py | 10 +++++-----
34 files changed, 40 insertions(+), 41 deletions(-)
rename doc/api/dts/{framework.exception.rst => api.exception.rst} (77%)
rename dts/{framework => api}/exception.py (100%)
diff --git a/doc/api/dts/framework.exception.rst b/doc/api/dts/api.exception.rst
similarity index 77%
rename from doc/api/dts/framework.exception.rst
rename to doc/api/dts/api.exception.rst
index efb47dc5ae..8e6bff5ee7 100644
--- a/doc/api/dts/framework.exception.rst
+++ b/doc/api/dts/api.exception.rst
@@ -3,6 +3,6 @@
exception - Exceptions
======================
-.. automodule:: framework.exception
+.. automodule:: api.exception
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index c719297c11..01f630e7cd 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -36,7 +36,7 @@ Modules
framework.logger
framework.parser
framework.utils
- framework.exception
+ api.exception
Indices and tables
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 24a2b05063..7d04c7ab49 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -47,7 +47,7 @@
from paramiko import SFTPClient, SFTPFile
from typing_extensions import Buffer
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
from framework.testbed_model.node import Node, NodeIdentifier, get_node
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index a4fafc3713..c6a220dced 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -22,8 +22,8 @@
ThroughputResults,
VerifyResults,
)
+from api.exception import RemoteCommandExecutionError, SkippedTestException
from framework.context import get_ctx
-from framework.exception import RemoteCommandExecutionError, SkippedTestException
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/framework/exception.py b/dts/api/exception.py
similarity index 100%
rename from dts/framework/exception.py
rename to dts/api/exception.py
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 094a1b7a9d..cabb39a8dd 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,9 +27,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.exception import InternalError
from api.test import fail, log_debug
from framework.context import get_ctx
-from framework.exception import InternalError
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index e17babe0ca..9cad9a9495 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.context import get_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index e9187440bb..9498d723d5 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
ChecksumOffloadOptions,
@@ -55,7 +56,6 @@
VLANOffloadFlag,
)
from framework.context import get_ctx
-from framework.exception import InteractiveCommandExecutionError, InternalError
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index d2f0138e4a..566dc7c4a2 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -35,7 +35,7 @@
from pydantic import Field, TypeAdapter, ValidationError, model_validator
from typing_extensions import Self
-from framework.exception import ConfigurationError
+from api.exception import ConfigurationError
from .common import FrozenModel, ValidationContext
from .node import NodeConfiguration
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 76e24d1785..62aaba033a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -27,7 +27,7 @@
)
from typing_extensions import TYPE_CHECKING, Self
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 8f1021dc96..7e61c85998 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -8,7 +8,7 @@
from dataclasses import MISSING, dataclass, field, fields
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
-from framework.exception import InternalError
+from api.exception import InternalError
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
diff --git a/dts/framework/parser.py b/dts/framework/parser.py
index 3075c36857..ebf470ad30 100644
--- a/dts/framework/parser.py
+++ b/dts/framework/parser.py
@@ -15,7 +15,7 @@
from typing_extensions import Self
-from framework.exception import InternalError
+from api.exception import InternalError
class ParserFn(TypedDict):
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index c3575cfcaf..d803a9e4bd 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,6 +13,7 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.exception import ConfigurationError, RemoteFileNotFoundError
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -25,7 +26,6 @@
RemoteDPDKTreeLocation,
)
from framework.context import get_ctx
-from framework.exception import ConfigurationError, RemoteFileNotFoundError
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/interactive_remote_session.py b/dts/framework/remote_session/interactive_remote_session.py
index c8156b4345..04f45e0df8 100644
--- a/dts/framework/remote_session/interactive_remote_session.py
+++ b/dts/framework/remote_session/interactive_remote_session.py
@@ -15,8 +15,8 @@
SSHException,
)
+from api.exception import SSHConnectionError
from framework.config.node import NodeConfiguration
-from framework.exception import SSHConnectionError
from framework.logger import DTSLogger
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index a65cbce209..fdd074be3a 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,12 +29,12 @@
from paramiko import Channel, channel
from typing_extensions import Self
-from framework.context import get_ctx
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from framework.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/remote_session/remote_session.py b/dts/framework/remote_session/remote_session.py
index 158325bb7f..f49966070f 100644
--- a/dts/framework/remote_session/remote_session.py
+++ b/dts/framework/remote_session/remote_session.py
@@ -24,13 +24,13 @@
SSHException,
)
-from framework.config.node import NodeConfiguration
-from framework.exception import (
+from api.exception import (
RemoteCommandExecutionError,
SSHConnectionError,
SSHSessionDeadError,
SSHTimeoutError,
)
+from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.settings import SETTINGS
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 6ea4749ff4..a0d8039a04 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -12,8 +12,8 @@
import sys
import textwrap
+from api.exception import ConfigurationError
from framework.config.common import ValidationContext
-from framework.exception import ConfigurationError
from framework.test_run import TestRun
from framework.testbed_model.node import Node
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 21faa55dc1..3cecb928ca 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -35,12 +35,11 @@
)
from typing_extensions import OrderedDict
+from api.exception import DTSError, ErrorSeverity, InternalError
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
from framework.testbed_model.os_session import OSSessionInfo
-from .exception import DTSError, ErrorSeverity, InternalError
-
class Result(IntEnum):
"""The possible states that a setup, a teardown or a test case may end up in."""
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 94dc6023a7..bbaf4f1fdf 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,9 +106,9 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
from framework.context import Context, init_ctx
-from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
@@ -136,7 +136,7 @@ class TestRun:
If an error occurs, the current stage is aborted, the error is recorded, everything in
the inner stages is marked as blocked and the run continues in the next iteration
of the same stage. The return code is the highest `severity` of all
- :class:`~.framework.exception.DTSError`\s.
+ :class:`~.api.exception.DTSError`\s.
Example:
An error occurs in a test suite setup. The current test suite is aborted,
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 69ce26040a..e06fdd28b9 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -29,11 +29,11 @@
from scapy.packet import Packet
from typing_extensions import Self
+from api.exception import ConfigurationError, InternalError
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
-from .exception import ConfigurationError, InternalError
from .logger import DTSLogger, get_dts_logger
from .utils import to_pascal_case
diff --git a/dts/framework/testbed_model/capability.py b/dts/framework/testbed_model/capability.py
index 960370fc72..001b65994c 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/framework/testbed_model/capability.py
@@ -64,7 +64,7 @@ def test_scatter_mbuf_2048(self):
from typing_extensions import Self
from api.capabilities import LinkTopology, NicCapability
-from framework.exception import ConfigurationError, InternalError, SkippedTestException
+from api.exception import ConfigurationError, InternalError, SkippedTestException
from framework.logger import get_dts_logger
from framework.testbed_model.node import Node
from framework.testbed_model.port import DriverKind
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index ee943462c2..88b6da1ae6 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -18,7 +18,7 @@
from typing_extensions import NotRequired
-from framework.exception import (
+from api.exception import (
ConfigurationError,
InternalError,
RemoteCommandExecutionError,
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 67a96ef4e5..4f42bf6aeb 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -17,11 +17,11 @@
from pathlib import PurePath
from typing import Literal, TypeAlias
+from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
-from framework.exception import ConfigurationError, InternalError
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py
index d81bc4cda0..aea3e59c25 100644
--- a/dts/framework/testbed_model/port.py
+++ b/dts/framework/testbed_model/port.py
@@ -12,8 +12,8 @@
from functools import cached_property
from typing import TYPE_CHECKING, Any, Final, Literal, NamedTuple
+from api.exception import InternalError
from framework.config.node import PortConfig
-from framework.exception import InternalError
if TYPE_CHECKING:
from .node import Node
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index dec952685a..db2c3c0c40 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -16,7 +16,7 @@
from collections.abc import Iterable
from pathlib import Path, PurePath, PurePosixPath
-from framework.exception import DPDKBuildError, RemoteCommandExecutionError
+from api.exception import DPDKBuildError, RemoteCommandExecutionError
from framework.settings import SETTINGS
from framework.utils import (
MesonArgs,
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 34862c4d2e..805a762c19 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -18,7 +18,7 @@
from typing_extensions import Self
from api.capabilities import LinkTopology
-from framework.exception import ConfigurationError, InternalError
+from api.exception import ConfigurationError, InternalError
from framework.testbed_model.linux_session import LinuxSession
from framework.testbed_model.node import Node, NodeIdentifier
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/framework/testbed_model/traffic_generator/__init__.py
index fca251f534..324b5e88f3 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/framework/testbed_model/traffic_generator/__init__.py
@@ -14,12 +14,12 @@
and a capturing traffic generator is required.
"""
+from api.exception import ConfigurationError
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.exception import ConfigurationError
from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/framework/testbed_model/traffic_generator/scapy.py
index c6e9006205..e983443548 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/framework/testbed_model/traffic_generator/scapy.py
@@ -25,9 +25,9 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet
+from api.exception import InteractiveSSHSessionDeadError, InternalError
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
-from framework.exception import InteractiveSSHSessionDeadError, InternalError
from framework.remote_session.python_shell import PythonShell
from framework.testbed_model.node import Node
from framework.testbed_model.port import Port
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
index 9917ffbfaa..28e344871a 100644
--- a/dts/framework/utils.py
+++ b/dts/framework/utils.py
@@ -26,7 +26,7 @@
from scapy.layers.inet import IP, TCP, UDP, Ether
from scapy.packet import Packet
-from .exception import InternalError
+from api.exception import InternalError
REGEX_FOR_PCI_ADDRESS: str = r"[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}"
_REGEX_FOR_COLON_OR_HYPHEN_SEP_MAC: str = r"(?:[\da-fA-F]{2}[:-]){5}[\da-fA-F]{2}"
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index af0a5680ab..f36b48a153 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -29,9 +29,9 @@
from api.cryptodev.types import (
CryptodevResults,
)
+from api.exception import SkippedTestException
from api.test import verify
from framework.context import get_ctx
-from framework.exception import SkippedTestException
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index 5ac85bee7d..b62efa2b42 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -35,11 +35,11 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index a7e24b37d5..b44822d31c 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -23,10 +23,10 @@
NicCapability,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
from api.testpmd import TestPmd
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import TestSuite, func_test
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index f6adf262c3..1e5a6860be 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -20,6 +20,7 @@
requires_link_topology,
requires_nic_capability,
)
+from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
from api.testpmd import TestPmd
@@ -29,7 +30,6 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
-from framework.exception import InteractiveCommandExecutionError
from framework.test_suite import BaseConfig, TestSuite, func_test
from framework.utils import StrEnum
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 6255e4c36d..7e50a075ac 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -21,15 +21,15 @@
from scapy.packet import Packet, Raw
from api.capabilities import NicCapability, requires_nic_capability
-from api.packet import send_packet_and_capture
-from api.test import fail, log, verify
-from api.testpmd import TestPmd
-from api.testpmd.types import FlowRule
-from framework.exception import (
+from api.exception import (
InteractiveCommandExecutionError,
SkippedTestException,
TestCaseVerifyError,
)
+from api.packet import send_packet_and_capture
+from api.test import fail, log, verify
+from api.testpmd import TestPmd
+from api.testpmd.types import FlowRule
from framework.test_suite import TestSuite, func_test
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 2/7] dts: move utils from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-30 22:06 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 3/7] dts: move context " Dean Marx
` (4 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The utils module is used to generate a set of random
packets in certain test suites. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/{framework.utils.rst => api.utils.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/config.py | 2 +-
dts/api/packet.py | 2 +-
dts/api/testpmd/config.py | 2 +-
dts/api/testpmd/types.py | 2 +-
dts/{framework => api}/utils.py | 0
dts/framework/config/node.py | 2 +-
dts/framework/config/test_run.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/test_suite.py | 2 +-
dts/framework/testbed_model/cpu.py | 2 +-
dts/framework/testbed_model/linux_session.py | 2 +-
dts/framework/testbed_model/os_session.py | 2 +-
dts/framework/testbed_model/posix_session.py | 4 ++--
.../traffic_generator/capturing_traffic_generator.py | 2 +-
.../testbed_model/traffic_generator/traffic_generator.py | 2 +-
dts/framework/testbed_model/traffic_generator/trex.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
| 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
22 files changed, 22 insertions(+), 22 deletions(-)
rename doc/api/dts/{framework.utils.rst => api.utils.rst} (80%)
rename dts/{framework => api}/utils.py (100%)
diff --git a/doc/api/dts/framework.utils.rst b/doc/api/dts/api.utils.rst
similarity index 80%
rename from doc/api/dts/framework.utils.rst
rename to doc/api/dts/api.utils.rst
index cc06d4c3c3..0b4baff1b5 100644
--- a/doc/api/dts/framework.utils.rst
+++ b/doc/api/dts/api.utils.rst
@@ -3,6 +3,6 @@
utils - Various Utilities
=========================
-.. automodule:: framework.utils
+.. automodule:: api.utils
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 01f630e7cd..783270f6e9 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -35,7 +35,7 @@ Modules
framework.context
framework.logger
framework.parser
- framework.utils
+ api.utils
api.exception
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index 69ff7aa59a..a88e70d45c 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.utils import StrEnum
from framework.params import Params, Switch
from framework.params.eal import EalParams
-from framework.utils import StrEnum
Silent = Literal[""]
diff --git a/dts/api/packet.py b/dts/api/packet.py
index cabb39a8dd..b7a9bb28bf 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -29,6 +29,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
+from api.utils import get_packet_summaries
from framework.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -36,7 +37,6 @@
from framework.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
-from framework.utils import get_packet_summaries
def send_packet_and_capture(
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index e71a3e1ef0..8b688834ee 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,6 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
+from api.utils import StrEnum
from framework.params import (
Params,
Switch,
@@ -24,7 +25,6 @@
str_from_flag_value,
)
from framework.params.eal import EalParams
-from framework.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py
index 0d322aece2..5c847b4bd6 100644
--- a/dts/api/testpmd/types.py
+++ b/dts/api/testpmd/types.py
@@ -15,8 +15,8 @@
from typing_extensions import Self
+from api.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
from framework.parser import ParserFn, TextParser
-from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum
RxTxLiteralSwitch = Literal["rx", "tx"]
diff --git a/dts/framework/utils.py b/dts/api/utils.py
similarity index 100%
rename from dts/framework/utils.py
rename to dts/api/utils.py
diff --git a/dts/framework/config/node.py b/dts/framework/config/node.py
index 792290f11f..28f23389a7 100644
--- a/dts/framework/config/node.py
+++ b/dts/framework/config/node.py
@@ -14,7 +14,7 @@
from pydantic import Field, model_validator
from typing_extensions import Self
-from framework.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
+from api.utils import REGEX_FOR_IDENTIFIER, REGEX_FOR_PCI_ADDRESS, StrEnum
from .common import FrozenModel
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 62aaba033a..977067f42a 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -28,7 +28,7 @@
from typing_extensions import TYPE_CHECKING, Self
from api.exception import InternalError
-from framework.utils import REGEX_FOR_PORT_LINK, StrEnum
+from api.utils import REGEX_FOR_PORT_LINK, StrEnum
from .common import FrozenModel, load_fields_from_settings
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index d803a9e4bd..69b47b823b 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -14,6 +14,7 @@
from typing import ClassVar, Final
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
DPDKBuildOptionsConfiguration,
@@ -33,7 +34,6 @@
from framework.testbed_model.node import Node
from framework.testbed_model.os_session import OSSession
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import MesonArgs, TarCompressionFormat
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index e06fdd28b9..426c98fdf6 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,12 +30,12 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.utils import to_pascal_case
from framework.config.common import FrozenModel
from framework.testbed_model.capability import TestProtocol
from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
-from .utils import to_pascal_case
if TYPE_CHECKING:
from framework.context import Context
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index 6e2ecca080..52ef196f84 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -24,7 +24,7 @@
from dataclasses import dataclass
from enum import auto, unique
-from framework.utils import StrEnum, expand_range
+from api.utils import StrEnum, expand_range
@unique
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 88b6da1ae6..69b0923744 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.utils import expand_range
from framework.testbed_model.port import PortInfo
-from framework.utils import expand_range
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index 2c267afed1..7bb339fab2 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -29,12 +29,12 @@
from enum import Flag, auto
from pathlib import Path, PurePath, PurePosixPath
+from api.utils import MesonArgs, TarCompressionFormat
from framework.config.node import NodeConfiguration
from framework.logger import DTSLogger
from framework.remote_session.interactive_remote_session import InteractiveRemoteSession
from framework.remote_session.remote_session import CommandResult, RemoteSession
from framework.settings import SETTINGS
-from framework.utils import MesonArgs, TarCompressionFormat
from .cpu import Architecture, LogicalCore
from .port import Port, PortInfo
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/framework/testbed_model/posix_session.py
index db2c3c0c40..61c634dad1 100644
--- a/dts/framework/testbed_model/posix_session.py
+++ b/dts/framework/testbed_model/posix_session.py
@@ -17,14 +17,14 @@
from pathlib import Path, PurePath, PurePosixPath
from api.exception import DPDKBuildError, RemoteCommandExecutionError
-from framework.settings import SETTINGS
-from framework.utils import (
+from api.utils import (
MesonArgs,
TarCompressionFormat,
convert_to_list_of_string,
create_tarball,
extract_tarball,
)
+from framework.settings import SETTINGS
from .cpu import Architecture
from .os_session import FilePermissions, OSSession, OSSessionInfo
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
index 7655751d7e..2804d64990 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.utils import get_packet_summaries
from framework.testbed_model.port import Port
-from framework.utils import get_packet_summaries
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
index cdda5a7c08..fedce77fdf 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/framework/testbed_model/traffic_generator/traffic_generator.py
@@ -25,7 +25,7 @@ class TrafficGenerator(ABC):
Exposes the common public methods of all traffic generators and defines private methods
that must implement the traffic generation logic in subclasses. This class also extends from
- :class:`framework.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
+ :class:`api.utils.MultiInheritanceBaseClass` to allow subclasses the ability to inherit
from multiple classes to fulfil the traffic generating functionality without breaking
single inheritance.
"""
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/framework/testbed_model/traffic_generator/trex.py
index 22cd20dea9..2064703fcc 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/framework/testbed_model/traffic_generator/trex.py
@@ -11,6 +11,7 @@
from scapy.packet import Packet
+from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
@@ -23,7 +24,6 @@
PerformanceTrafficGenerator,
PerformanceTrafficStats,
)
-from framework.utils import StrEnum
@dataclass(slots=True)
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 596b892730..1e99b82b8c 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -20,10 +20,10 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
+from api.utils import generate_random_packets
from framework.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 1e5a6860be..4df273e3e1 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -30,8 +30,8 @@
RSSOffloadTypesFlag,
TestPmdVerbosePacket,
)
+from api.utils import StrEnum
from framework.test_suite import BaseConfig, TestSuite, func_test
-from framework.utils import StrEnum
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 271ad4301c..fce83604a6 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -20,11 +20,11 @@
)
from api.test import verify
from api.testpmd import TestPmd
+from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.linux_session import LinuxSession
-from framework.utils import REGEX_FOR_PCI_ADDRESS
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index fa91f7ee2f..c57a12c932 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -20,9 +20,9 @@
)
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
+from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.virtual_device import VirtualDevice
-from framework.utils import generate_random_packets
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 3/7] dts: move context from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
2026-04-30 22:06 ` [PATCH v4 1/7] dts: move exception module " Dean Marx
2026-04-30 22:06 ` [PATCH v4 2/7] dts: move utils " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
` (3 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
A couple test suites import and get the run context
during execution. Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.context.rst => api.context.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/{framework => api}/context.py | 0
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 4 ++--
dts/api/test.py | 2 +-
dts/api/testpmd/__init__.py | 2 +-
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/framework/test_run.py | 2 +-
dts/framework/test_suite.py | 4 ++--
dts/framework/testbed_model/node.py | 2 +-
dts/framework/testbed_model/topology.py | 14 +++++++-------
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
18 files changed, 25 insertions(+), 25 deletions(-)
rename doc/api/dts/{framework.context.rst => api.context.rst} (80%)
rename dts/{framework => api}/context.py (100%)
diff --git a/doc/api/dts/framework.context.rst b/doc/api/dts/api.context.rst
similarity index 80%
rename from doc/api/dts/framework.context.rst
rename to doc/api/dts/api.context.rst
index 925c160360..65b4ab9a47 100644
--- a/doc/api/dts/framework.context.rst
+++ b/doc/api/dts/api.context.rst
@@ -3,6 +3,6 @@
context - DTS execution context
===============================
-.. automodule:: framework.context
+.. automodule:: api.context
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 783270f6e9..98269d6e80 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -32,7 +32,7 @@ Modules
framework.test_suite
framework.test_result
framework.settings
- framework.context
+ api.context
framework.logger
framework.parser
api.utils
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index 7d04c7ab49..f3dd07de56 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -86,7 +86,7 @@ def make_file_path(
path /= custom_path
else:
- from framework.context import get_ctx
+ from api.context import get_ctx
try:
ctx = get_ctx()
diff --git a/dts/framework/context.py b/dts/api/context.py
similarity index 100%
rename from dts/framework/context.py
rename to dts/api/context.py
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index c6a220dced..67dcb02130 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -23,7 +23,7 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index b7a9bb28bf..59f26da833 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -30,7 +30,7 @@
from api.exception import InternalError
from api.test import fail, log_debug
from api.utils import get_packet_summaries
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
@@ -82,7 +82,7 @@ def send_packets_and_capture(
Returns:
A list of received packets.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index 9cad9a9495..a1f2326075 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -11,7 +11,7 @@
from api.artifact import Artifact
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9498d723d5..a528663c21 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -55,7 +55,7 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index c3b02dcc62..07db6dfeb0 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -30,7 +30,7 @@
from typing_extensions import Self
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 69b47b823b..9f7cd60dfe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -26,7 +26,7 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index 269c2cada4..a8f169787c 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -10,7 +10,7 @@
from abc import ABC, abstractmethod
from pathlib import PurePath
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index fdd074be3a..d138727c85 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -34,7 +34,7 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index bbaf4f1fdf..605a916ebb 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,7 +108,7 @@
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.config.test_run import TestRunConfiguration
-from framework.context import Context, init_ctx
+from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 426c98fdf6..6066f7a77a 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -38,7 +38,7 @@
from .logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
- from framework.context import Context
+ from api.context import Context
class BaseConfig(FrozenModel):
@@ -92,7 +92,7 @@ def __init__(self, config: BaseConfig) -> None:
Args:
config: The test suite configuration.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self.config = config
self._ctx = get_ctx()
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index 4f42bf6aeb..40dd7f0666 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -242,7 +242,7 @@ def get_node(node_identifier: NodeIdentifier) -> Node | None:
if node_identifier == "local":
return None
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
if node_identifier == "sut":
diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py
index 805a762c19..5b6ff2add5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/framework/testbed_model/topology.py
@@ -96,7 +96,7 @@ def node_and_ports_from_id(self, node_identifier: NodeIdentifier) -> tuple[Node,
Raises:
InternalError: If the given `node_identifier` is invalid.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
match node_identifier:
@@ -180,7 +180,7 @@ def instantiate_crypto_ports(self) -> None:
Raises:
InternalError: If crypto virtual functions could not be created on a port.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
for port in ctx.sut_node.cryptodevs:
@@ -206,7 +206,7 @@ def instantiate_vf_ports(self) -> None:
Raises:
InternalError: If virtual function creation fails.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -235,7 +235,7 @@ def instantiate_vf_ports(self) -> None:
def delete_vf_ports(self) -> None:
"""Delete virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -246,7 +246,7 @@ def delete_vf_ports(self) -> None:
def delete_crypto_vf_ports(self) -> None:
"""Delete crypto virtual functions from the SUT node during test run teardown."""
- from framework.context import get_ctx
+ from api.context import get_ctx
ctx = get_ctx()
@@ -259,7 +259,7 @@ def bind_cryptodevs(self, driver: DriverKind):
Args:
driver: The driver to bind the crypto functions
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
self._bind_ports_to_drivers(get_ctx().sut_node, self.crypto_vf_ports, driver)
@@ -318,7 +318,7 @@ def _prepare_devbind_script(self) -> None:
Raises:
InternalError: If dpdk-devbind.py could not be found.
"""
- from framework.context import get_ctx
+ from api.context import get_ctx
local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
valid_script_path = local_script_path.exists()
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index f36b48a153..39784cbcac 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -31,7 +31,7 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from framework.context import get_ctx
+from api.context import get_ctx
from framework.test_suite import BaseConfig, TestSuite, crypto_test
from framework.testbed_model.virtual_device import VirtualDevice
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 1e99b82b8c..c018efb1f7 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -21,7 +21,7 @@
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.context import filter_cores
+from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
from framework.testbed_model.cpu import LogicalCoreCount
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 4/7] dts: move testbed model from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (2 preceding siblings ...)
2026-04-30 22:06 ` [PATCH v4 3/7] dts: move context " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
` (2 subsequent siblings)
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Multiple test suites import modules from testbed model
in the framework. Move this directory to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
...y.rst => api.testbed_model.capability.rst} | 2 +-
...odel.cpu.rst => api.testbed_model.cpu.rst} | 2 +-
...st => api.testbed_model.linux_session.rst} | 2 +-
...el.node.rst => api.testbed_model.node.rst} | 2 +-
...n.rst => api.testbed_model.os_session.rst} | 2 +-
...el.port.rst => api.testbed_model.port.rst} | 2 +-
...st => api.testbed_model.posix_session.rst} | 2 +-
doc/api/dts/api.testbed_model.rst | 28 +++++++++++++++++++
...ogy.rst => api.testbed_model.topology.rst} | 2 +-
...generator.capturing_traffic_generator.rst} | 2 +-
.../api.testbed_model.traffic_generator.rst | 16 +++++++++++
...testbed_model.traffic_generator.scapy.rst} | 2 +-
...l.traffic_generator.traffic_generator.rst} | 2 +-
...t => api.testbed_model.virtual_device.rst} | 2 +-
doc/api/dts/framework.testbed_model.rst | 28 -------------------
...mework.testbed_model.traffic_generator.rst | 16 -----------
doc/api/dts/index.rst | 2 +-
dts/api/artifact.py | 2 +-
dts/api/capabilities.py | 8 +++---
dts/api/context.py | 10 +++----
dts/api/cryptodev/__init__.py | 2 +-
dts/api/packet.py | 12 ++++----
dts/api/test.py | 2 +-
.../testbed_model/__init__.py | 0
.../testbed_model/capability.py | 10 +++----
dts/{framework => api}/testbed_model/cpu.py | 2 +-
.../testbed_model/linux_session.py | 2 +-
dts/{framework => api}/testbed_model/node.py | 0
.../testbed_model/os_session.py | 6 ++--
dts/{framework => api}/testbed_model/port.py | 0
.../testbed_model/posix_session.py | 0
.../testbed_model/topology.py | 4 +--
.../traffic_generator/__init__.py | 2 +-
.../capturing_traffic_generator.py | 2 +-
.../performance_traffic_generator.py | 0
.../testbed_model/traffic_generator/scapy.py | 12 ++++----
.../traffic_generator/traffic_generator.py | 6 ++--
.../testbed_model/traffic_generator/trex.py | 14 +++++-----
.../testbed_model/virtual_device.py | 0
dts/api/testpmd/__init__.py | 2 +-
dts/framework/params/eal.py | 6 ++--
dts/framework/params/types.py | 6 ++--
dts/framework/remote_session/blocking_app.py | 2 +-
dts/framework/remote_session/dpdk.py | 10 +++----
dts/framework/remote_session/dpdk_shell.py | 2 +-
.../remote_session/interactive_shell.py | 4 +--
dts/framework/runner.py | 2 +-
dts/framework/test_result.py | 2 +-
dts/framework/test_run.py | 18 ++++++------
dts/framework/test_suite.py | 4 +--
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 4 +--
dts/tests/TestSuite_l2fwd.py | 4 +--
dts/tests/TestSuite_packet_capture.py | 8 +++---
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 6 ++--
57 files changed, 148 insertions(+), 148 deletions(-)
rename doc/api/dts/{framework.testbed_model.capability.rst => api.testbed_model.capability.rst} (74%)
rename doc/api/dts/{framework.testbed_model.cpu.rst => api.testbed_model.cpu.rst} (78%)
rename doc/api/dts/{framework.testbed_model.linux_session.rst => api.testbed_model.linux_session.rst} (74%)
rename doc/api/dts/{framework.testbed_model.node.rst => api.testbed_model.node.rst} (71%)
rename doc/api/dts/{framework.testbed_model.os_session.rst => api.testbed_model.os_session.rst} (76%)
rename doc/api/dts/{framework.testbed_model.port.rst => api.testbed_model.port.rst} (77%)
rename doc/api/dts/{framework.testbed_model.posix_session.rst => api.testbed_model.posix_session.rst} (74%)
create mode 100644 doc/api/dts/api.testbed_model.rst
rename doc/api/dts/{framework.testbed_model.topology.rst => api.testbed_model.topology.rst} (73%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.capturing_traffic_generator.rst => api.testbed_model.traffic_generator.capturing_traffic_generator.rst} (68%)
create mode 100644 doc/api/dts/api.testbed_model.traffic_generator.rst
rename doc/api/dts/{framework.testbed_model.traffic_generator.scapy.rst => api.testbed_model.traffic_generator.scapy.rst} (70%)
rename doc/api/dts/{framework.testbed_model.traffic_generator.traffic_generator.rst => api.testbed_model.traffic_generator.traffic_generator.rst} (65%)
rename doc/api/dts/{framework.testbed_model.virtual_device.rst => api.testbed_model.virtual_device.rst} (72%)
delete mode 100644 doc/api/dts/framework.testbed_model.rst
delete mode 100644 doc/api/dts/framework.testbed_model.traffic_generator.rst
rename dts/{framework => api}/testbed_model/__init__.py (100%)
rename dts/{framework => api}/testbed_model/capability.py (99%)
rename dts/{framework => api}/testbed_model/cpu.py (99%)
rename dts/{framework => api}/testbed_model/linux_session.py (99%)
rename dts/{framework => api}/testbed_model/node.py (100%)
rename dts/{framework => api}/testbed_model/os_session.py (99%)
rename dts/{framework => api}/testbed_model/port.py (100%)
rename dts/{framework => api}/testbed_model/posix_session.py (100%)
rename dts/{framework => api}/testbed_model/topology.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/__init__.py (97%)
rename dts/{framework => api}/testbed_model/traffic_generator/capturing_traffic_generator.py (99%)
rename dts/{framework => api}/testbed_model/traffic_generator/performance_traffic_generator.py (100%)
rename dts/{framework => api}/testbed_model/traffic_generator/scapy.py (98%)
rename dts/{framework => api}/testbed_model/traffic_generator/traffic_generator.py (94%)
rename dts/{framework => api}/testbed_model/traffic_generator/trex.py (97%)
rename dts/{framework => api}/testbed_model/virtual_device.py (100%)
diff --git a/doc/api/dts/framework.testbed_model.capability.rst b/doc/api/dts/api.testbed_model.capability.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.capability.rst
rename to doc/api/dts/api.testbed_model.capability.rst
index fab91cad83..88e396dddb 100644
--- a/doc/api/dts/framework.testbed_model.capability.rst
+++ b/doc/api/dts/api.testbed_model.capability.rst
@@ -3,6 +3,6 @@
capability - Testbed Capabilities
=================================
-.. automodule:: framework.testbed_model.capability
+.. automodule:: api.testbed_model.capability
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.cpu.rst b/doc/api/dts/api.testbed_model.cpu.rst
similarity index 78%
rename from doc/api/dts/framework.testbed_model.cpu.rst
rename to doc/api/dts/api.testbed_model.cpu.rst
index 997f2a9795..dbbb29480a 100644
--- a/doc/api/dts/framework.testbed_model.cpu.rst
+++ b/doc/api/dts/api.testbed_model.cpu.rst
@@ -3,6 +3,6 @@
cpu - CPU Representation and Utilities
======================================
-.. automodule:: framework.testbed_model.cpu
+.. automodule:: api.testbed_model.cpu
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.linux_session.rst b/doc/api/dts/api.testbed_model.linux_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.linux_session.rst
rename to doc/api/dts/api.testbed_model.linux_session.rst
index 7567816199..cfe79d8bca 100644
--- a/doc/api/dts/framework.testbed_model.linux_session.rst
+++ b/doc/api/dts/api.testbed_model.linux_session.rst
@@ -3,6 +3,6 @@
linux\_session - Linux Remote Session
=====================================
-.. automodule:: framework.testbed_model.linux_session
+.. automodule:: api.testbed_model.linux_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.node.rst b/doc/api/dts/api.testbed_model.node.rst
similarity index 71%
rename from doc/api/dts/framework.testbed_model.node.rst
rename to doc/api/dts/api.testbed_model.node.rst
index 23c6c46a00..15f522e5f7 100644
--- a/doc/api/dts/framework.testbed_model.node.rst
+++ b/doc/api/dts/api.testbed_model.node.rst
@@ -3,6 +3,6 @@
node - Base Node
================
-.. automodule:: framework.testbed_model.node
+.. automodule:: api.testbed_model.node
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.os_session.rst b/doc/api/dts/api.testbed_model.os_session.rst
similarity index 76%
rename from doc/api/dts/framework.testbed_model.os_session.rst
rename to doc/api/dts/api.testbed_model.os_session.rst
index ecfb352311..e7e3f9894f 100644
--- a/doc/api/dts/framework.testbed_model.os_session.rst
+++ b/doc/api/dts/api.testbed_model.os_session.rst
@@ -3,6 +3,6 @@
os\_session - OS-aware Remote Session ABC
=========================================
-.. automodule:: framework.testbed_model.os_session
+.. automodule:: api.testbed_model.os_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.port.rst b/doc/api/dts/api.testbed_model.port.rst
similarity index 77%
rename from doc/api/dts/framework.testbed_model.port.rst
rename to doc/api/dts/api.testbed_model.port.rst
index fdb7ca8a1d..d64501aef0 100644
--- a/doc/api/dts/framework.testbed_model.port.rst
+++ b/doc/api/dts/api.testbed_model.port.rst
@@ -3,7 +3,7 @@
port - NIC Port Representation
==============================
-.. automodule:: framework.testbed_model.port
+.. automodule:: api.testbed_model.port
:members:
:show-inheritance:
:noindex:
diff --git a/doc/api/dts/framework.testbed_model.posix_session.rst b/doc/api/dts/api.testbed_model.posix_session.rst
similarity index 74%
rename from doc/api/dts/framework.testbed_model.posix_session.rst
rename to doc/api/dts/api.testbed_model.posix_session.rst
index e65585fd85..9f0e9ff18d 100644
--- a/doc/api/dts/framework.testbed_model.posix_session.rst
+++ b/doc/api/dts/api.testbed_model.posix_session.rst
@@ -3,6 +3,6 @@
posix\_session - Posix Remote Session
=====================================
-.. automodule:: framework.testbed_model.posix_session
+.. automodule:: api.testbed_model.posix_session
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.rst b/doc/api/dts/api.testbed_model.rst
new file mode 100644
index 0000000000..5e2e5189b2
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+testbed\_model - Testbed Modelling Package
+==========================================
+
+.. automodule:: api.testbed_model
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ api.testbed_model.traffic_generator
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.os_session
+ api.testbed_model.linux_session
+ api.testbed_model.posix_session
+ api.testbed_model.node
+ api.testbed_model.capability
+ api.testbed_model.cpu
+ api.testbed_model.port
+ api.testbed_model.topology
+ api.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.topology.rst b/doc/api/dts/api.testbed_model.topology.rst
similarity index 73%
rename from doc/api/dts/framework.testbed_model.topology.rst
rename to doc/api/dts/api.testbed_model.topology.rst
index 496f2a895f..bb63fe38dc 100644
--- a/doc/api/dts/framework.testbed_model.topology.rst
+++ b/doc/api/dts/api.testbed_model.topology.rst
@@ -3,6 +3,6 @@
topology - Testbed Topology
===========================
-.. automodule:: framework.testbed_model.topology
+.. automodule:: api.testbed_model.topology
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
similarity index 68%
rename from doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
index 29fa834042..cfe03201a7 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.capturing_traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.capturing_traffic_generator.rst
@@ -3,6 +3,6 @@
capturing\_traffic\_generator - Base Capturing TG ABC
=====================================================
-.. automodule:: framework.testbed_model.traffic_generator.capturing_traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.capturing_traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/api.testbed_model.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.rst
new file mode 100644
index 0000000000..311bdcf6b9
--- /dev/null
+++ b/doc/api/dts/api.testbed_model.traffic_generator.rst
@@ -0,0 +1,16 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+traffic\_generator Subpackage
+=============================
+
+.. automodule:: api.testbed_model.traffic_generator
+ :members:
+ :show-inheritance:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 1
+
+ api.testbed_model.traffic_generator.traffic_generator
+ api.testbed_model.traffic_generator.capturing_traffic_generator
+ api.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
similarity index 70%
rename from doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
index df78ac9514..949bb66632 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.scapy.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.scapy.rst
@@ -3,6 +3,6 @@
scapy - Capturing Traffic Generator
===================================
-.. automodule:: framework.testbed_model.traffic_generator.scapy
+.. automodule:: api.testbed_model.traffic_generator.scapy
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
similarity index 65%
rename from doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
rename to doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
index bfec728dee..1045e534b5 100644
--- a/doc/api/dts/framework.testbed_model.traffic_generator.traffic_generator.rst
+++ b/doc/api/dts/api.testbed_model.traffic_generator.traffic_generator.rst
@@ -3,6 +3,6 @@
traffic\_generator - Base TG ABC
================================
-.. automodule:: framework.testbed_model.traffic_generator.traffic_generator
+.. automodule:: api.testbed_model.traffic_generator.traffic_generator
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.virtual_device.rst b/doc/api/dts/api.testbed_model.virtual_device.rst
similarity index 72%
rename from doc/api/dts/framework.testbed_model.virtual_device.rst
rename to doc/api/dts/api.testbed_model.virtual_device.rst
index a6b0420e75..97adc895f6 100644
--- a/doc/api/dts/framework.testbed_model.virtual_device.rst
+++ b/doc/api/dts/api.testbed_model.virtual_device.rst
@@ -3,6 +3,6 @@
virtual\_device - Virtual Devices
=================================
-.. automodule:: framework.testbed_model.virtual_device
+.. automodule:: api.testbed_model.virtual_device
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.testbed_model.rst b/doc/api/dts/framework.testbed_model.rst
deleted file mode 100644
index f283178f6a..0000000000
--- a/doc/api/dts/framework.testbed_model.rst
+++ /dev/null
@@ -1,28 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-testbed\_model - Testbed Modelling Package
-==========================================
-
-.. automodule:: framework.testbed_model
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 2
-
- framework.testbed_model.traffic_generator
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.os_session
- framework.testbed_model.linux_session
- framework.testbed_model.posix_session
- framework.testbed_model.node
- framework.testbed_model.capability
- framework.testbed_model.cpu
- framework.testbed_model.port
- framework.testbed_model.topology
- framework.testbed_model.virtual_device
diff --git a/doc/api/dts/framework.testbed_model.traffic_generator.rst b/doc/api/dts/framework.testbed_model.traffic_generator.rst
deleted file mode 100644
index 24c250ee3a..0000000000
--- a/doc/api/dts/framework.testbed_model.traffic_generator.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-.. SPDX-License-Identifier: BSD-3-Clause
-
-traffic\_generator Subpackage
-=============================
-
-.. automodule:: framework.testbed_model.traffic_generator
- :members:
- :show-inheritance:
-
-.. toctree::
- :hidden:
- :maxdepth: 1
-
- framework.testbed_model.traffic_generator.traffic_generator
- framework.testbed_model.traffic_generator.capturing_traffic_generator
- framework.testbed_model.traffic_generator.scapy
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 98269d6e80..f47e4af3f2 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -16,7 +16,7 @@ Packages
tests
api
- framework.testbed_model
+ api.testbed_model
framework.remote_session
framework.params
framework.config
diff --git a/dts/api/artifact.py b/dts/api/artifact.py
index f3dd07de56..74a8ac667f 100644
--- a/dts/api/artifact.py
+++ b/dts/api/artifact.py
@@ -48,9 +48,9 @@
from typing_extensions import Buffer
from api.exception import InternalError
+from api.testbed_model.node import Node, NodeIdentifier, get_node
from framework.logger import DTSLogger, get_dts_logger
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node, NodeIdentifier, get_node
TextMode: TypeAlias = (
Literal["r", "r+", "w", "w+", "a", "a+", "x", "x+"]
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 09bc538523..04fc20738b 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -23,7 +23,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires_link_topology
+ from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -34,7 +34,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires_nic_capability
+ from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -235,7 +235,7 @@ def requires_link_topology(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import TopologyCapability
+ from api.testbed_model.capability import TopologyCapability
def add_required_topology(
test_case_or_suite: type["TestProtocol"],
@@ -258,7 +258,7 @@ def requires_nic_capability(
Returns:
The decorated test case or test suite.
"""
- from framework.testbed_model.capability import DecoratedNicCapability
+ from api.testbed_model.capability import DecoratedNicCapability
def add_required_capability(
test_case_or_suite: type["TestProtocol"],
diff --git a/dts/api/context.py b/dts/api/context.py
index 7e61c85998..13a2ad6c39 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -9,17 +9,17 @@
from typing import TYPE_CHECKING, Any, Optional, ParamSpec, Union
from api.exception import InternalError
+from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
+from api.testbed_model.node import Node
+from api.testbed_model.topology import Topology
from framework.remote_session.shell_pool import ShellPool
from framework.settings import SETTINGS
-from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
+ from api.testbed_model.capability import TestProtocol
+ from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.test_suite import TestCase, TestSuite
- from framework.testbed_model.capability import TestProtocol
- from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 67dcb02130..1ba8e0d977 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -14,6 +14,7 @@
from typing_extensions import Unpack
+from api.context import get_ctx
from api.cryptodev.config import CryptoPmdParams, TestType
from api.cryptodev.types import (
CryptodevResults,
@@ -23,7 +24,6 @@
VerifyResults,
)
from api.exception import RemoteCommandExecutionError, SkippedTestException
-from api.context import get_ctx
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
diff --git a/dts/api/packet.py b/dts/api/packet.py
index 59f26da833..bf90961c26 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -27,16 +27,16 @@
from scapy.layers.l2 import Ether
from scapy.packet import Packet, Padding, raw
+from api.context import get_ctx
from api.exception import InternalError
from api.test import fail, log_debug
-from api.utils import get_packet_summaries
-from api.context import get_ctx
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
)
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficStats,
)
+from api.utils import get_packet_summaries
def send_packet_and_capture(
@@ -83,7 +83,7 @@ def send_packets_and_capture(
A list of received packets.
"""
from api.context import get_ctx
- from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
+ from api.testbed_model.traffic_generator.capturing_traffic_generator import (
CapturingTrafficGenerator,
)
@@ -340,7 +340,7 @@ def assess_performance_by_packet(
Returns:
Performance statistics of the generated test.
"""
- from framework.testbed_model.traffic_generator.performance_traffic_generator import (
+ from api.testbed_model.traffic_generator.performance_traffic_generator import (
PerformanceTrafficGenerator,
)
diff --git a/dts/api/test.py b/dts/api/test.py
index a1f2326075..03846639ad 100644
--- a/dts/api/test.py
+++ b/dts/api/test.py
@@ -10,8 +10,8 @@
from datetime import datetime
from api.artifact import Artifact
-from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from api.context import get_ctx
+from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger
diff --git a/dts/framework/testbed_model/__init__.py b/dts/api/testbed_model/__init__.py
similarity index 100%
rename from dts/framework/testbed_model/__init__.py
rename to dts/api/testbed_model/__init__.py
diff --git a/dts/framework/testbed_model/capability.py b/dts/api/testbed_model/capability.py
similarity index 99%
rename from dts/framework/testbed_model/capability.py
rename to dts/api/testbed_model/capability.py
index 001b65994c..4e4e976be5 100644
--- a/dts/framework/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -26,7 +26,7 @@
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import LinkTopology, requires
+ from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@func_test
@@ -37,7 +37,7 @@ def hello_world_single_core(self):
.. code:: python
from framework.test_suite import TestSuite, func_test
- from framework.testbed_model.capability import NicCapability, requires
+ from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
# other test cases may not require it
@@ -65,10 +65,10 @@ def test_scatter_mbuf_2048(self):
from api.capabilities import LinkTopology, NicCapability
from api.exception import ConfigurationError, InternalError, SkippedTestException
+from api.testbed_model.node import Node
+from api.testbed_model.port import DriverKind
+from api.testbed_model.topology import Topology
from framework.logger import get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import DriverKind
-from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
from api.testpmd import TestPmd
diff --git a/dts/framework/testbed_model/cpu.py b/dts/api/testbed_model/cpu.py
similarity index 99%
rename from dts/framework/testbed_model/cpu.py
rename to dts/api/testbed_model/cpu.py
index 52ef196f84..ee754f5844 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/api/testbed_model/cpu.py
@@ -29,7 +29,7 @@
@unique
class Architecture(StrEnum):
- r"""The supported architectures of :class:`~framework.testbed_model.node.Node`\s."""
+ r"""The supported architectures of :class:`~api.testbed_model.node.Node`\s."""
#:
i686 = auto()
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
similarity index 99%
rename from dts/framework/testbed_model/linux_session.py
rename to dts/api/testbed_model/linux_session.py
index 69b0923744..7307b2abe2 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -23,8 +23,8 @@
InternalError,
RemoteCommandExecutionError,
)
+from api.testbed_model.port import PortInfo
from api.utils import expand_range
-from framework.testbed_model.port import PortInfo
from .cpu import LogicalCore
from .port import Port
diff --git a/dts/framework/testbed_model/node.py b/dts/api/testbed_model/node.py
similarity index 100%
rename from dts/framework/testbed_model/node.py
rename to dts/api/testbed_model/node.py
diff --git a/dts/framework/testbed_model/os_session.py b/dts/api/testbed_model/os_session.py
similarity index 99%
rename from dts/framework/testbed_model/os_session.py
rename to dts/api/testbed_model/os_session.py
index 7bb339fab2..b1e0538ac9 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/api/testbed_model/os_session.py
@@ -73,11 +73,11 @@ class OSSessionInfo:
Attributes:
os_name: The name of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
os_version: The version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
kernel_version: The kernel version of the running operating system of
- the :class:`~framework.testbed_model.node.Node`.
+ the :class:`~api.testbed_model.node.Node`.
"""
os_name: str
diff --git a/dts/framework/testbed_model/port.py b/dts/api/testbed_model/port.py
similarity index 100%
rename from dts/framework/testbed_model/port.py
rename to dts/api/testbed_model/port.py
diff --git a/dts/framework/testbed_model/posix_session.py b/dts/api/testbed_model/posix_session.py
similarity index 100%
rename from dts/framework/testbed_model/posix_session.py
rename to dts/api/testbed_model/posix_session.py
diff --git a/dts/framework/testbed_model/topology.py b/dts/api/testbed_model/topology.py
similarity index 99%
rename from dts/framework/testbed_model/topology.py
rename to dts/api/testbed_model/topology.py
index 5b6ff2add5..11593d64d5 100644
--- a/dts/framework/testbed_model/topology.py
+++ b/dts/api/testbed_model/topology.py
@@ -19,8 +19,8 @@
from api.capabilities import LinkTopology
from api.exception import ConfigurationError, InternalError
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.node import Node, NodeIdentifier
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.node import Node, NodeIdentifier
from .port import DriverKind, Port, PortConfig
diff --git a/dts/framework/testbed_model/traffic_generator/__init__.py b/dts/api/testbed_model/traffic_generator/__init__.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/__init__.py
rename to dts/api/testbed_model/traffic_generator/__init__.py
index 324b5e88f3..11fa25448a 100644
--- a/dts/framework/testbed_model/traffic_generator/__init__.py
+++ b/dts/api/testbed_model/traffic_generator/__init__.py
@@ -15,12 +15,12 @@
"""
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.test_run import (
ScapyTrafficGeneratorConfig,
TrafficGeneratorConfig,
TrexTrafficGeneratorConfig,
)
-from framework.testbed_model.node import Node
from .scapy import ScapyTrafficGenerator
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
similarity index 99%
rename from dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
index 2804d64990..db274e5e82 100644
--- a/dts/framework/testbed_model/traffic_generator/capturing_traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/capturing_traffic_generator.py
@@ -17,8 +17,8 @@
from scapy.packet import Packet
from api.artifact import Artifact
+from api.testbed_model.port import Port
from api.utils import get_packet_summaries
-from framework.testbed_model.port import Port
from .traffic_generator import TrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py b/dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
similarity index 100%
rename from dts/framework/testbed_model/traffic_generator/performance_traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/performance_traffic_generator.py
diff --git a/dts/framework/testbed_model/traffic_generator/scapy.py b/dts/api/testbed_model/traffic_generator/scapy.py
similarity index 98%
rename from dts/framework/testbed_model/traffic_generator/scapy.py
rename to dts/api/testbed_model/traffic_generator/scapy.py
index e983443548..215c57f93d 100644
--- a/dts/framework/testbed_model/traffic_generator/scapy.py
+++ b/dts/api/testbed_model/traffic_generator/scapy.py
@@ -26,15 +26,15 @@
from scapy.packet import Packet
from api.exception import InteractiveSSHSessionDeadError, InternalError
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from framework.config.node import OS
from framework.config.test_run import ScapyTrafficGeneratorConfig
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
from .capturing_traffic_generator import CapturingTrafficGenerator
diff --git a/dts/framework/testbed_model/traffic_generator/traffic_generator.py b/dts/api/testbed_model/traffic_generator/traffic_generator.py
similarity index 94%
rename from dts/framework/testbed_model/traffic_generator/traffic_generator.py
rename to dts/api/testbed_model/traffic_generator/traffic_generator.py
index fedce77fdf..5fd68e5144 100644
--- a/dts/framework/testbed_model/traffic_generator/traffic_generator.py
+++ b/dts/api/testbed_model/traffic_generator/traffic_generator.py
@@ -13,11 +13,11 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node
+from api.testbed_model.port import Port
+from api.testbed_model.topology import Topology
from framework.config.test_run import TrafficGeneratorConfig
from framework.logger import DTSLogger, get_dts_logger
-from framework.testbed_model.node import Node
-from framework.testbed_model.port import Port
-from framework.testbed_model.topology import Topology
class TrafficGenerator(ABC):
diff --git a/dts/framework/testbed_model/traffic_generator/trex.py b/dts/api/testbed_model/traffic_generator/trex.py
similarity index 97%
rename from dts/framework/testbed_model/traffic_generator/trex.py
rename to dts/api/testbed_model/traffic_generator/trex.py
index 2064703fcc..d97ed934c9 100644
--- a/dts/framework/testbed_model/traffic_generator/trex.py
+++ b/dts/api/testbed_model/traffic_generator/trex.py
@@ -11,19 +11,19 @@
from scapy.packet import Packet
+from api.testbed_model.node import Node, create_session
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.topology import Topology
+from api.testbed_model.traffic_generator.performance_traffic_generator import (
+ PerformanceTrafficGenerator,
+ PerformanceTrafficStats,
+)
from api.utils import StrEnum
from framework.config.node import OS, NodeConfiguration
from framework.config.test_run import TrexTrafficGeneratorConfig
from framework.parser import TextParser
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.python_shell import PythonShell
-from framework.testbed_model.node import Node, create_session
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.topology import Topology
-from framework.testbed_model.traffic_generator.performance_traffic_generator import (
- PerformanceTrafficGenerator,
- PerformanceTrafficStats,
-)
@dataclass(slots=True)
diff --git a/dts/framework/testbed_model/virtual_device.py b/dts/api/testbed_model/virtual_device.py
similarity index 100%
rename from dts/framework/testbed_model/virtual_device.py
rename to dts/api/testbed_model/virtual_device.py
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index a528663c21..9f47a15433 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -32,6 +32,7 @@
from typing_extensions import Unpack
from api.capabilities import LinkTopology, NicCapability
+from api.context import get_ctx
from api.exception import InteractiveCommandExecutionError, InternalError
from api.testpmd.config import PortTopology, SimpleForwardingModes, TestPmdParams
from api.testpmd.types import (
@@ -55,7 +56,6 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from api.context import get_ctx
from framework.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
diff --git a/dts/framework/params/eal.py b/dts/framework/params/eal.py
index e84a20f02f..86bfd3fcc6 100644
--- a/dts/framework/params/eal.py
+++ b/dts/framework/params/eal.py
@@ -6,12 +6,12 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.virtual_device import VirtualDevice
from framework.params import Params, Switch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.virtual_device import VirtualDevice
if TYPE_CHECKING:
- from framework.testbed_model.port import Port
+ from api.testbed_model.port import Port
def _port_to_pci(port: "Port") -> str:
diff --git a/dts/framework/params/types.py b/dts/framework/params/types.py
index 3c7650474c..f2fa69f8b8 100644
--- a/dts/framework/params/types.py
+++ b/dts/framework/params/types.py
@@ -32,6 +32,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TestType,
TLSVersion,
)
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.port import Port
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd.config import (
AnonMempoolAllocationMode,
EthPeer,
@@ -54,9 +57,6 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TxUDPPortPair,
)
from framework.params import Switch, YesNoSwitch
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.port import Port
-from framework.testbed_model.virtual_device import VirtualDevice
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 07db6dfeb0..84db3974b1 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,11 +31,11 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.params import Params
from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
-from framework.testbed_model.node import Node
P = TypeVar("P", bound=Params)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 9f7cd60dfe..713a564d25 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -13,7 +13,12 @@
from pathlib import Path, PurePath
from typing import ClassVar, Final
+from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
+from api.testbed_model.node import Node
+from api.testbed_model.os_session import OSSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.utils import MesonArgs, TarCompressionFormat
from framework.config.test_run import (
DPDKBuildConfiguration,
@@ -26,14 +31,9 @@
RemoteDPDKTarballLocation,
RemoteDPDKTreeLocation,
)
-from api.context import get_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
-from framework.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
-from framework.testbed_model.node import Node
-from framework.testbed_model.os_session import OSSession
-from framework.testbed_model.virtual_device import VirtualDevice
@dataclass(slots=True, frozen=True)
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index a8f169787c..b807f9bdae 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,12 +11,12 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.testbed_model.cpu import LogicalCoreList
from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
)
-from framework.testbed_model.cpu import LogicalCoreList
def compute_eal_params(
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index d138727c85..ec539bad95 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -29,16 +29,16 @@
from paramiko import Channel, channel
from typing_extensions import Self
+from api.context import get_ctx
from api.exception import (
InteractiveCommandExecutionError,
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
-from api.context import get_ctx
+from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
from framework.params import Params
from framework.settings import SETTINGS
-from framework.testbed_model.node import Node
P = ParamSpec("P")
T = TypeVar("T", bound="InteractiveShell")
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index a0d8039a04..29be7b80fe 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -13,9 +13,9 @@
import textwrap
from api.exception import ConfigurationError
+from api.testbed_model.node import Node
from framework.config.common import ValidationContext
from framework.test_run import TestRun
-from framework.testbed_model.node import Node
from .config import Configuration, load_config
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/framework/test_result.py b/dts/framework/test_result.py
index 3cecb928ca..5f945163ce 100644
--- a/dts/framework/test_result.py
+++ b/dts/framework/test_result.py
@@ -36,9 +36,9 @@
from typing_extensions import OrderedDict
from api.exception import DTSError, ErrorSeverity, InternalError
+from api.testbed_model.os_session import OSSessionInfo
from framework.remote_session.dpdk import DPDKBuildInfo
from framework.settings import SETTINGS
-from framework.testbed_model.os_session import OSSessionInfo
class Result(IntEnum):
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 605a916ebb..790fbf997d 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -106,22 +106,22 @@
from types import MethodType
from typing import ClassVar, Protocol, Union
+from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.testbed_model.capability import (
+ Capability,
+ get_supported_capabilities,
+ test_if_supported,
+)
+from api.testbed_model.node import Node
+from api.testbed_model.topology import PortLink, Topology
+from api.testbed_model.traffic_generator import create_traffic_generator
from framework.config.test_run import TestRunConfiguration
-from api.context import Context, init_ctx
from framework.logger import DTSLogger, get_dts_logger
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
-from framework.testbed_model.capability import (
- Capability,
- get_supported_capabilities,
- test_if_supported,
-)
-from framework.testbed_model.node import Node
-from framework.testbed_model.topology import PortLink, Topology
-from framework.testbed_model.traffic_generator import create_traffic_generator
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py
index 6066f7a77a..786cfc7bff 100644
--- a/dts/framework/test_suite.py
+++ b/dts/framework/test_suite.py
@@ -30,10 +30,10 @@
from typing_extensions import Self
from api.exception import ConfigurationError, InternalError
+from api.testbed_model.capability import TestProtocol
+from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-from framework.testbed_model.capability import TestProtocol
-from framework.testbed_model.topology import Topology
from .logger import DTSLogger, get_dts_logger
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index c57231de22..97e03b8fb7 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.port import Port
from api.testpmd import TestPmd
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.port import Port
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index 39784cbcac..fc4b3cb308 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -13,6 +13,7 @@
LinkTopology,
requires_link_topology,
)
+from api.context import get_ctx
from api.cryptodev import Cryptodev
from api.cryptodev.config import (
AeadAlgName,
@@ -31,9 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
-from api.context import get_ctx
+from api.testbed_model.virtual_device import VirtualDevice
from framework.test_suite import BaseConfig, TestSuite, crypto_test
-from framework.testbed_model.virtual_device import VirtualDevice
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index c018efb1f7..5650366c36 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -13,17 +13,17 @@
requires_link_topology,
requires_nic_capability,
)
+from api.context import filter_cores
from api.packet import (
get_expected_packets,
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from api.context import filter_cores
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreCount
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 4bd15e2401..042b7019aa 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,15 +36,15 @@
send_packets_and_capture,
)
from api.test import verify
+from api.testbed_model.cpu import LogicalCoreList
+from api.testbed_model.traffic_generator.capturing_traffic_generator import (
+ PacketFilteringConfig,
+)
from api.testpmd import TestPmd
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.cpu import LogicalCoreList
-from framework.testbed_model.traffic_generator.capturing_traffic_generator import (
- PacketFilteringConfig,
-)
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index fce83604a6..656e2e4bb7 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.linux_session import LinuxSession
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index c57a12c932..91a6d4eb9f 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.virtual_device import VirtualDevice
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index bdecdb76fd..c649aac197 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.testbed_model.capability import requires
+from api.testbed_model.linux_session import LinuxSession
+from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
from framework.test_suite import TestSuite, func_test
-from framework.testbed_model.capability import requires
-from framework.testbed_model.linux_session import LinuxSession
-from framework.testbed_model.virtual_device import VirtualDevice
class TestVirtioFwd(TestSuite):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 5/7] dts: move test suite module from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (3 preceding siblings ...)
2026-04-30 22:06 ` [PATCH v4 4/7] dts: move testbed model " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
2026-04-30 22:06 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Currently, each test suite imports the TestSuite class
from the DTS framework to use as a base class.
However, the goal for 26.07 is to move all test suite
imports to the API module. Moves and updates the test_suite
file to the API directory, and updates all files that import
test_suite to reflect this change.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.test_suite.rst => api.test_suite.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/capabilities.py | 6 +++---
dts/api/context.py | 2 +-
dts/api/packet.py | 2 +-
dts/{framework => api}/test_suite.py | 3 +--
dts/api/testbed_model/capability.py | 6 +++---
dts/framework/config/__init__.py | 4 ++--
dts/framework/config/test_run.py | 8 ++++----
dts/framework/test_run.py | 2 +-
dts/tests/TestSuite_blocklist.py | 2 +-
dts/tests/TestSuite_checksum_offload.py | 2 +-
dts/tests/TestSuite_cryptodev_throughput.py | 2 +-
dts/tests/TestSuite_dual_vlan.py | 2 +-
dts/tests/TestSuite_dynamic_config.py | 2 +-
dts/tests/TestSuite_dynamic_queue_conf.py | 2 +-
dts/tests/TestSuite_hello_world.py | 2 +-
dts/tests/TestSuite_l2fwd.py | 2 +-
dts/tests/TestSuite_mac_filter.py | 2 +-
dts/tests/TestSuite_mtu.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +-
| 2 +-
dts/tests/TestSuite_port_control.py | 2 +-
dts/tests/TestSuite_port_restart_config_persistency.py | 2 +-
dts/tests/TestSuite_port_stats.py | 2 +-
dts/tests/TestSuite_promisc_support.py | 2 +-
dts/tests/TestSuite_qinq.py | 2 +-
dts/tests/TestSuite_queue_start_stop.py | 2 +-
dts/tests/TestSuite_rte_flow.py | 2 +-
dts/tests/TestSuite_rx_tx_offload.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
dts/tests/TestSuite_smoke_tests.py | 2 +-
dts/tests/TestSuite_softnic.py | 2 +-
dts/tests/TestSuite_uni_pkt.py | 2 +-
dts/tests/TestSuite_virtio_fwd.py | 2 +-
dts/tests/TestSuite_vlan.py | 2 +-
37 files changed, 45 insertions(+), 46 deletions(-)
rename doc/api/dts/{framework.test_suite.rst => api.test_suite.rst} (81%)
rename dts/{framework => api}/test_suite.py (99%)
diff --git a/doc/api/dts/framework.test_suite.rst b/doc/api/dts/api.test_suite.rst
similarity index 81%
rename from doc/api/dts/framework.test_suite.rst
rename to doc/api/dts/api.test_suite.rst
index 9517f51a4a..4acb7b103a 100644
--- a/doc/api/dts/framework.test_suite.rst
+++ b/doc/api/dts/api.test_suite.rst
@@ -3,6 +3,6 @@
test\_suite - Common Test Suite Features
========================================
-.. automodule:: framework.test_suite
+.. automodule:: api.test_suite
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index f47e4af3f2..7c282bbba1 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -29,7 +29,7 @@ Modules
framework.runner
framework.test_run
- framework.test_suite
+ api.test_suite
framework.test_result
framework.settings
api.context
diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py
index 04fc20738b..a4d6b2b424 100644
--- a/dts/api/capabilities.py
+++ b/dts/api/capabilities.py
@@ -22,7 +22,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires_link_topology
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -33,7 +33,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires_nic_capability
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -47,7 +47,7 @@ def test_scatter_mbuf_2048(self):
from typing import TYPE_CHECKING, Callable
if TYPE_CHECKING:
- from framework.test_suite import TestProtocol
+ from api.test_suite import TestProtocol
class LinkTopology(IntEnum):
diff --git a/dts/api/context.py b/dts/api/context.py
index 13a2ad6c39..7ed4cc5665 100644
--- a/dts/api/context.py
+++ b/dts/api/context.py
@@ -16,10 +16,10 @@
from framework.settings import SETTINGS
if TYPE_CHECKING:
+ from api.test_suite import TestCase, TestSuite
from api.testbed_model.capability import TestProtocol
from api.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
- from framework.test_suite import TestCase, TestSuite
P = ParamSpec("P")
diff --git a/dts/api/packet.py b/dts/api/packet.py
index bf90961c26..873b8f0324 100644
--- a/dts/api/packet.py
+++ b/dts/api/packet.py
@@ -175,7 +175,7 @@ def adjust_addresses(packets: list[Packet], expected: bool = False) -> list[Pack
Raises:
InternalError: If no tests are running.
"""
- from framework.test_suite import TestSuite
+ from api.test_suite import TestSuite
if get_ctx().local.current_test_suite is None:
raise InternalError("No current test suite, tests aren't running?")
diff --git a/dts/framework/test_suite.py b/dts/api/test_suite.py
similarity index 99%
rename from dts/framework/test_suite.py
rename to dts/api/test_suite.py
index 786cfc7bff..0822f9bfe5 100644
--- a/dts/framework/test_suite.py
+++ b/dts/api/test_suite.py
@@ -34,8 +34,7 @@
from api.testbed_model.topology import Topology
from api.utils import to_pascal_case
from framework.config.common import FrozenModel
-
-from .logger import DTSLogger, get_dts_logger
+from framework.logger import DTSLogger, get_dts_logger
if TYPE_CHECKING:
from api.context import Context
diff --git a/dts/api/testbed_model/capability.py b/dts/api/testbed_model/capability.py
index 4e4e976be5..95583261d8 100644
--- a/dts/api/testbed_model/capability.py
+++ b/dts/api/testbed_model/capability.py
@@ -25,7 +25,7 @@
Examples:
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import LinkTopology, requires
# The whole test suite (each test case within) doesn't require any links.
@requires_link_topology(LinkTopology.NO_LINK)
@@ -36,7 +36,7 @@ def hello_world_single_core(self):
.. code:: python
- from framework.test_suite import TestSuite, func_test
+ from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import NicCapability, requires
class TestPmdBufferScatter(TestSuite):
# only the test case requires the SCATTERED_RX_ENABLED capability
@@ -71,8 +71,8 @@ def test_scatter_mbuf_2048(self):
from framework.logger import get_dts_logger
if TYPE_CHECKING:
+ from api.test_suite import TestCase
from api.testpmd import TestPmd
- from framework.test_suite import TestCase
P = ParamSpec("P")
TestPmdMethod = Callable[Concatenate["TestPmd", P], Any]
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 566dc7c4a2..3a3580aaf7 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -43,7 +43,7 @@
# Import only if type checking or building docs, to prevent circular imports.
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig
+ from api.test_suite import BaseConfig
NodesConfig = Annotated[list[NodeConfiguration], Field(min_length=1)]
@@ -182,7 +182,7 @@ def load_config(ctx: ValidationContext) -> Configuration:
nodes = _load_and_parse_model(ctx["settings"].nodes_config_path, NodesConfig, ctx)
try:
- from framework.test_suite import BaseConfig as BaseConfig
+ from api.test_suite import BaseConfig as BaseConfig
Configuration.model_rebuild()
return Configuration.model_validate(
diff --git a/dts/framework/config/test_run.py b/dts/framework/config/test_run.py
index 977067f42a..81e3dba79b 100644
--- a/dts/framework/config/test_run.py
+++ b/dts/framework/config/test_run.py
@@ -33,7 +33,7 @@
from .common import FrozenModel, load_fields_from_settings
if TYPE_CHECKING:
- from framework.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
+ from api.test_suite import BaseConfig, TestCase, TestSuite, TestSuiteSpec
@unique
@@ -230,7 +230,7 @@ class TestSuiteConfig(FrozenModel):
@cached_property
def test_suite_spec(self) -> "TestSuiteSpec":
"""The specification of the requested test suite."""
- from framework.test_suite import find_by_name
+ from api.test_suite import find_by_name
test_suite_spec = find_by_name(self.test_suite_name)
assert (
@@ -280,7 +280,7 @@ def fetch_all_test_suites() -> list[TestSuiteConfig]:
This function does not include the smoke tests.
"""
- from framework.test_suite import AVAILABLE_TEST_SUITES
+ from api.test_suite import AVAILABLE_TEST_SUITES
return [
TestSuiteConfig(test_suite=test_suite.name)
@@ -506,7 +506,7 @@ def filter_tests(
self, tests_config: dict[str, "BaseConfig"]
) -> Iterable[tuple[type["TestSuite"], "BaseConfig", deque[type["TestCase"]]]]:
"""Filter test suites and cases selected for execution."""
- from framework.test_suite import TestCaseType
+ from api.test_suite import TestCaseType
test_suites = [TestSuiteConfig(test_suite="smoke_tests")]
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 790fbf997d..c133fbecb0 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -108,6 +108,7 @@
from api.context import Context, init_ctx
from api.exception import InternalError, SkippedTestException, TestCaseVerifyError
+from api.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
from api.testbed_model.capability import (
Capability,
get_supported_capabilities,
@@ -121,7 +122,6 @@
from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
-from framework.test_suite import BaseConfig, TestCase, TestCaseType, TestSuite
TestScenario = tuple[type[TestSuite], BaseConfig, deque[type[TestCase]]]
diff --git a/dts/tests/TestSuite_blocklist.py b/dts/tests/TestSuite_blocklist.py
index 97e03b8fb7..31e69c0de9 100644
--- a/dts/tests/TestSuite_blocklist.py
+++ b/dts/tests/TestSuite_blocklist.py
@@ -11,9 +11,9 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.port import Port
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestBlocklist(TestSuite):
diff --git a/dts/tests/TestSuite_checksum_offload.py b/dts/tests/TestSuite_checksum_offload.py
index 90ca798e56..a2ea13991b 100644
--- a/dts/tests/TestSuite_checksum_offload.py
+++ b/dts/tests/TestSuite_checksum_offload.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import ChecksumOffloadOptions, PacketOffloadFlag
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM)
diff --git a/dts/tests/TestSuite_cryptodev_throughput.py b/dts/tests/TestSuite_cryptodev_throughput.py
index fc4b3cb308..d2a6cbab94 100644
--- a/dts/tests/TestSuite_cryptodev_throughput.py
+++ b/dts/tests/TestSuite_cryptodev_throughput.py
@@ -32,8 +32,8 @@
)
from api.exception import SkippedTestException
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, crypto_test
from api.testbed_model.virtual_device import VirtualDevice
-from framework.test_suite import BaseConfig, TestSuite, crypto_test
config_list: list[dict[str, int | float | str]] = [
{"buff_size": 64, "Gbps": 1.00},
diff --git a/dts/tests/TestSuite_dual_vlan.py b/dts/tests/TestSuite_dual_vlan.py
index 1b77dd2b47..f3347a6d52 100644
--- a/dts/tests/TestSuite_dual_vlan.py
+++ b/dts/tests/TestSuite_dual_vlan.py
@@ -21,9 +21,9 @@
from api.capabilities import LinkTopology, requires_link_topology
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestDualVlan(TestSuite):
diff --git a/dts/tests/TestSuite_dynamic_config.py b/dts/tests/TestSuite_dynamic_config.py
index 7204ec4f73..b9e2c30da1 100644
--- a/dts/tests/TestSuite_dynamic_config.py
+++ b/dts/tests/TestSuite_dynamic_config.py
@@ -27,9 +27,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_dynamic_queue_conf.py b/dts/tests/TestSuite_dynamic_queue_conf.py
index b62efa2b42..24584c7d60 100644
--- a/dts/tests/TestSuite_dynamic_queue_conf.py
+++ b/dts/tests/TestSuite_dynamic_queue_conf.py
@@ -38,9 +38,9 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
def setup_and_teardown_test(
diff --git a/dts/tests/TestSuite_hello_world.py b/dts/tests/TestSuite_hello_world.py
index bf1a93c782..cd62eb8f3e 100644
--- a/dts/tests/TestSuite_hello_world.py
+++ b/dts/tests/TestSuite_hello_world.py
@@ -9,8 +9,8 @@
"""
from api.test import log
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_l2fwd.py b/dts/tests/TestSuite_l2fwd.py
index 5650366c36..f237821a04 100644
--- a/dts/tests/TestSuite_l2fwd.py
+++ b/dts/tests/TestSuite_l2fwd.py
@@ -19,11 +19,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreCount
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer, SimpleForwardingModes
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mac_filter.py b/dts/tests/TestSuite_mac_filter.py
index b44822d31c..eb1413f336 100644
--- a/dts/tests/TestSuite_mac_filter.py
+++ b/dts/tests/TestSuite_mac_filter.py
@@ -26,8 +26,8 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packet_and_capture
from api.test import fail, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_mtu.py b/dts/tests/TestSuite_mtu.py
index 8355495d33..c264db299e 100644
--- a/dts/tests/TestSuite_mtu.py
+++ b/dts/tests/TestSuite_mtu.py
@@ -23,8 +23,8 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
STANDARD_FRAME = 1518 # --max-pkt-len will subtract l2 information at a minimum of 18 bytes.
JUMBO_FRAME = 9018
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index 042b7019aa..fd5cef5268 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -36,6 +36,7 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.traffic_generator.capturing_traffic_generator import (
PacketFilteringConfig,
@@ -44,7 +45,6 @@
from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.test_suite import TestSuite, func_test
@dataclass(kw_only=True)
diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py
index 96da67ee7d..6c7f6d79fe 100644
--- a/dts/tests/TestSuite_pmd_buffer_scatter.py
+++ b/dts/tests/TestSuite_pmd_buffer_scatter.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
--git a/dts/tests/TestSuite_pmd_rss.py b/dts/tests/TestSuite_pmd_rss.py
index 4df273e3e1..162e08ccbc 100644
--- a/dts/tests/TestSuite_pmd_rss.py
+++ b/dts/tests/TestSuite_pmd_rss.py
@@ -23,6 +23,7 @@
from api.exception import InteractiveCommandExecutionError
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import BaseConfig, TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import (
@@ -31,7 +32,6 @@
TestPmdVerbosePacket,
)
from api.utils import StrEnum
-from framework.test_suite import BaseConfig, TestSuite, func_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_port_control.py b/dts/tests/TestSuite_port_control.py
index 6be47838d0..5b960cb3a3 100644
--- a/dts/tests/TestSuite_port_control.py
+++ b/dts/tests/TestSuite_port_control.py
@@ -18,9 +18,9 @@
)
from api.packet import send_packets_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_port_restart_config_persistency.py b/dts/tests/TestSuite_port_restart_config_persistency.py
index 4ea22b6d70..88df35d33c 100644
--- a/dts/tests/TestSuite_port_restart_config_persistency.py
+++ b/dts/tests/TestSuite_port_restart_config_persistency.py
@@ -14,9 +14,9 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import TestPmdPortFlowCtrl
-from framework.test_suite import TestSuite, func_test
ALTERNATIVE_MTU: int = 800
STANDARD_MTU: int = 1500
diff --git a/dts/tests/TestSuite_port_stats.py b/dts/tests/TestSuite_port_stats.py
index 3dc045f847..0328c6718c 100644
--- a/dts/tests/TestSuite_port_stats.py
+++ b/dts/tests/TestSuite_port_stats.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_promisc_support.py b/dts/tests/TestSuite_promisc_support.py
index a0c65dc662..c59c8c6078 100644
--- a/dts/tests/TestSuite_promisc_support.py
+++ b/dts/tests/TestSuite_promisc_support.py
@@ -21,8 +21,8 @@
send_packets_and_capture,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_qinq.py b/dts/tests/TestSuite_qinq.py
index 505d71dbc8..5dde37d4db 100644
--- a/dts/tests/TestSuite_qinq.py
+++ b/dts/tests/TestSuite_qinq.py
@@ -18,8 +18,8 @@
from api.capabilities import NicCapability, requires_nic_capability
from api.packet import send_packet_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
-from framework.test_suite import TestSuite, func_test
class TestQinq(TestSuite):
diff --git a/dts/tests/TestSuite_queue_start_stop.py b/dts/tests/TestSuite_queue_start_stop.py
index e9048d4245..6935f395c1 100644
--- a/dts/tests/TestSuite_queue_start_stop.py
+++ b/dts/tests/TestSuite_queue_start_stop.py
@@ -24,9 +24,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.TWO_LINKS)
diff --git a/dts/tests/TestSuite_rte_flow.py b/dts/tests/TestSuite_rte_flow.py
index 7e50a075ac..8c5c59edec 100644
--- a/dts/tests/TestSuite_rte_flow.py
+++ b/dts/tests/TestSuite_rte_flow.py
@@ -28,9 +28,9 @@
)
from api.packet import send_packet_and_capture
from api.test import fail, log, verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import FlowRule
-from framework.test_suite import TestSuite, func_test
@dataclass
diff --git a/dts/tests/TestSuite_rx_tx_offload.py b/dts/tests/TestSuite_rx_tx_offload.py
index b0da627d3c..c8d24baaae 100644
--- a/dts/tests/TestSuite_rx_tx_offload.py
+++ b/dts/tests/TestSuite_rx_tx_offload.py
@@ -13,12 +13,12 @@
requires_nic_capability,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.types import (
OffloadConfiguration,
RxTxLiteralSwitch,
)
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.ONE_LINK)
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index 1e7ab7b036..f1eb435759 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -22,10 +22,10 @@
)
from api.packet import assess_performance_by_packet
from api.test import verify, write_performance_json
+from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
from framework.params.types import TestPmdParamsDict
-from framework.test_suite import BaseConfig, TestSuite, perf_test
class Config(BaseConfig):
diff --git a/dts/tests/TestSuite_smoke_tests.py b/dts/tests/TestSuite_smoke_tests.py
index 656e2e4bb7..b3eb325fc0 100644
--- a/dts/tests/TestSuite_smoke_tests.py
+++ b/dts/tests/TestSuite_smoke_tests.py
@@ -19,12 +19,12 @@
requires_link_topology,
)
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.linux_session import LinuxSession
from api.testpmd import TestPmd
from api.utils import REGEX_FOR_PCI_ADDRESS
from framework.config.node import PortConfig
from framework.settings import SETTINGS
-from framework.test_suite import TestSuite, func_test
@requires_link_topology(LinkTopology.NO_LINK)
diff --git a/dts/tests/TestSuite_softnic.py b/dts/tests/TestSuite_softnic.py
index 91a6d4eb9f..05a6d3aa18 100644
--- a/dts/tests/TestSuite_softnic.py
+++ b/dts/tests/TestSuite_softnic.py
@@ -18,11 +18,11 @@
match_all_packets,
send_packets_and_capture,
)
+from api.test_suite import TestSuite, func_test
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import EthPeer
from api.utils import generate_random_packets
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PHYSICAL_FUNCTION)
diff --git a/dts/tests/TestSuite_uni_pkt.py b/dts/tests/TestSuite_uni_pkt.py
index 222276ce67..d83185d1b2 100644
--- a/dts/tests/TestSuite_uni_pkt.py
+++ b/dts/tests/TestSuite_uni_pkt.py
@@ -25,10 +25,10 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
from api.testpmd.types import RtePTypes, TestPmdVerbosePacket
-from framework.test_suite import TestSuite, func_test
class TestUniPkt(TestSuite):
diff --git a/dts/tests/TestSuite_virtio_fwd.py b/dts/tests/TestSuite_virtio_fwd.py
index c649aac197..2c10478df3 100644
--- a/dts/tests/TestSuite_virtio_fwd.py
+++ b/dts/tests/TestSuite_virtio_fwd.py
@@ -12,12 +12,12 @@
from api.capabilities import LinkTopology
from api.packet import send_packets_and_capture
from api.test import log, verify
+from api.test_suite import TestSuite, func_test
from api.testbed_model.capability import requires
from api.testbed_model.linux_session import LinuxSession
from api.testbed_model.virtual_device import VirtualDevice
from api.testpmd import TestPmd
from api.testpmd.config import PortTopology, SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
class TestVirtioFwd(TestSuite):
diff --git a/dts/tests/TestSuite_vlan.py b/dts/tests/TestSuite_vlan.py
index 898673fc86..975e87b128 100644
--- a/dts/tests/TestSuite_vlan.py
+++ b/dts/tests/TestSuite_vlan.py
@@ -23,9 +23,9 @@
)
from api.packet import send_packet_and_capture
from api.test import verify
+from api.test_suite import TestSuite, func_test
from api.testpmd import TestPmd
from api.testpmd.config import SimpleForwardingModes
-from framework.test_suite import TestSuite, func_test
@requires_nic_capability(NicCapability.PORT_RX_OFFLOAD_VLAN_FILTER)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 6/7] dts: move params directory from framework to API
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (4 preceding siblings ...)
2026-04-30 22:06 ` [PATCH v4 5/7] dts: move test suite module " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
2026-04-30 22:06 ` [PATCH v4 7/7] dts: separate Linux session into interface and logic Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
The params directory is imported in test suites such as
packet capture to use as a base class for dumpcap.
Move this to the API.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
.../dts/{framework.params.eal.rst => api.params.eal.rst} | 2 +-
doc/api/dts/{framework.params.rst => api.params.rst} | 6 +++---
.../{framework.params.types.rst => api.params.types.rst} | 2 +-
doc/api/dts/index.rst | 2 +-
dts/api/cryptodev/__init__.py | 2 +-
dts/api/cryptodev/config.py | 4 ++--
dts/{framework => api}/params/__init__.py | 0
dts/{framework => api}/params/eal.py | 2 +-
dts/{framework => api}/params/types.py | 8 ++++++--
dts/api/testpmd/__init__.py | 7 ++++++-
dts/api/testpmd/config.py | 6 +++---
dts/framework/remote_session/blocking_app.py | 4 ++--
dts/framework/remote_session/dpdk.py | 2 +-
dts/framework/remote_session/dpdk_shell.py | 2 +-
dts/framework/remote_session/interactive_shell.py | 2 +-
dts/tests/TestSuite_packet_capture.py | 2 +-
dts/tests/TestSuite_single_core_forward_perf.py | 2 +-
17 files changed, 32 insertions(+), 23 deletions(-)
rename doc/api/dts/{framework.params.eal.rst => api.params.eal.rst} (79%)
rename doc/api/dts/{framework.params.rst => api.params.rst} (71%)
rename doc/api/dts/{framework.params.types.rst => api.params.types.rst} (80%)
rename dts/{framework => api}/params/__init__.py (100%)
rename dts/{framework => api}/params/eal.py (97%)
rename dts/{framework => api}/params/types.py (97%)
diff --git a/doc/api/dts/framework.params.eal.rst b/doc/api/dts/api.params.eal.rst
similarity index 79%
rename from doc/api/dts/framework.params.eal.rst
rename to doc/api/dts/api.params.eal.rst
index 6999b00233..4531cb1fe1 100644
--- a/doc/api/dts/framework.params.eal.rst
+++ b/doc/api/dts/api.params.eal.rst
@@ -3,6 +3,6 @@
eal - EAL Parameters Modelling
==============================
-.. automodule:: framework.params.eal
+.. automodule:: api.params.eal
:members:
:show-inheritance:
diff --git a/doc/api/dts/framework.params.rst b/doc/api/dts/api.params.rst
similarity index 71%
rename from doc/api/dts/framework.params.rst
rename to doc/api/dts/api.params.rst
index d8c6af9667..3ea7f9215e 100644
--- a/doc/api/dts/framework.params.rst
+++ b/doc/api/dts/api.params.rst
@@ -3,7 +3,7 @@
params - Command Line Parameters Modelling
==========================================
-.. automodule:: framework.params
+.. automodule:: api.params
:members:
:show-inheritance:
@@ -11,5 +11,5 @@ params - Command Line Parameters Modelling
:hidden:
:maxdepth: 1
- framework.params.eal
- framework.params.types
+ api.params.eal
+ api.params.types
diff --git a/doc/api/dts/framework.params.types.rst b/doc/api/dts/api.params.types.rst
similarity index 80%
rename from doc/api/dts/framework.params.types.rst
rename to doc/api/dts/api.params.types.rst
index 6d609038be..4754b3a665 100644
--- a/doc/api/dts/framework.params.types.rst
+++ b/doc/api/dts/api.params.types.rst
@@ -3,6 +3,6 @@
params.types - Parameters Modelling Types
=========================================
-.. automodule:: framework.params.types
+.. automodule:: api.params.types
:members:
:show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index 7c282bbba1..e89e782ac0 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -18,7 +18,7 @@ Packages
api
api.testbed_model
framework.remote_session
- framework.params
+ api.params
framework.config
Modules
diff --git a/dts/api/cryptodev/__init__.py b/dts/api/cryptodev/__init__.py
index 1ba8e0d977..bbfe3622c2 100644
--- a/dts/api/cryptodev/__init__.py
+++ b/dts/api/cryptodev/__init__.py
@@ -27,7 +27,7 @@
from framework.remote_session.dpdk_shell import compute_eal_params
if TYPE_CHECKING:
- from framework.params.types import CryptoPmdParamsDict
+ from api.params.types import CryptoPmdParamsDict
from pathlib import PurePath
diff --git a/dts/api/cryptodev/config.py b/dts/api/cryptodev/config.py
index a88e70d45c..3420c2fe91 100644
--- a/dts/api/cryptodev/config.py
+++ b/dts/api/cryptodev/config.py
@@ -6,9 +6,9 @@
from enum import auto
from typing import Literal
+from api.params import Params, Switch
+from api.params.eal import EalParams
from api.utils import StrEnum
-from framework.params import Params, Switch
-from framework.params.eal import EalParams
Silent = Literal[""]
diff --git a/dts/framework/params/__init__.py b/dts/api/params/__init__.py
similarity index 100%
rename from dts/framework/params/__init__.py
rename to dts/api/params/__init__.py
diff --git a/dts/framework/params/eal.py b/dts/api/params/eal.py
similarity index 97%
rename from dts/framework/params/eal.py
rename to dts/api/params/eal.py
index 86bfd3fcc6..64fa45ae12 100644
--- a/dts/framework/params/eal.py
+++ b/dts/api/params/eal.py
@@ -6,9 +6,9 @@
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Literal
+from api.params import Params, Switch
from api.testbed_model.cpu import LogicalCoreList
from api.testbed_model.virtual_device import VirtualDevice
-from framework.params import Params, Switch
if TYPE_CHECKING:
from api.testbed_model.port import Port
diff --git a/dts/framework/params/types.py b/dts/api/params/types.py
similarity index 97%
rename from dts/framework/params/types.py
rename to dts/api/params/types.py
index f2fa69f8b8..2c215cfe54 100644
--- a/dts/framework/params/types.py
+++ b/dts/api/params/types.py
@@ -12,8 +12,10 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
params = TestPmdParams(**kwargs)
"""
+from __future__ import annotations
+
from pathlib import PurePath
-from typing import TypedDict
+from typing import TYPE_CHECKING, TypedDict
from api.cryptodev.config import (
AeadAlgName,
@@ -56,7 +58,9 @@ def create_testpmd(**kwargs: Unpack[TestPmdParamsDict]):
TXRingParams,
TxUDPPortPair,
)
-from framework.params import Switch, YesNoSwitch
+
+if TYPE_CHECKING:
+ from api.params import Switch, YesNoSwitch
class EalParamsDict(TypedDict, total=False):
diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py
index 9f47a15433..85ebe2ea65 100644
--- a/dts/api/testpmd/__init__.py
+++ b/dts/api/testpmd/__init__.py
@@ -14,6 +14,8 @@
testpmd.close()
"""
+from __future__ import annotations
+
import functools
import re
import time
@@ -21,6 +23,7 @@
from enum import Flag
from pathlib import PurePath
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
ClassVar,
@@ -56,7 +59,9 @@
TxOffloadConfiguration,
VLANOffloadFlag,
)
-from framework.params.types import TestPmdParamsDict
+
+if TYPE_CHECKING:
+ from api.params.types import TestPmdParamsDict
from framework.remote_session.dpdk_shell import DPDKShell
from framework.remote_session.interactive_shell import only_active
from framework.settings import SETTINGS
diff --git a/dts/api/testpmd/config.py b/dts/api/testpmd/config.py
index 8b688834ee..96fe5e79fb 100644
--- a/dts/api/testpmd/config.py
+++ b/dts/api/testpmd/config.py
@@ -13,8 +13,7 @@
from pathlib import PurePath
from typing import Literal, NamedTuple
-from api.utils import StrEnum
-from framework.params import (
+from api.params import (
Params,
Switch,
YesNoSwitch,
@@ -24,7 +23,8 @@
modify_str,
str_from_flag_value,
)
-from framework.params.eal import EalParams
+from api.params.eal import EalParams
+from api.utils import StrEnum
class PortTopology(StrEnum):
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
index 84db3974b1..537d937eca 100644
--- a/dts/framework/remote_session/blocking_app.py
+++ b/dts/framework/remote_session/blocking_app.py
@@ -31,9 +31,9 @@
from typing_extensions import Self
from api.context import get_ctx
+from api.params import Params
+from api.params.eal import EalParams
from api.testbed_model.node import Node
-from framework.params import Params
-from framework.params.eal import EalParams
from framework.remote_session.dpdk_shell import compute_eal_params
from framework.remote_session.interactive_shell import InteractiveShell
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 713a564d25..afdf7526d9 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -15,6 +15,7 @@
from api.context import get_ctx
from api.exception import ConfigurationError, RemoteFileNotFoundError
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
from api.testbed_model.node import Node
from api.testbed_model.os_session import OSSession
@@ -32,7 +33,6 @@
RemoteDPDKTreeLocation,
)
from framework.logger import DTSLogger, get_dts_logger
-from framework.params.eal import EalParams
from framework.remote_session.remote_session import CommandResult
diff --git a/dts/framework/remote_session/dpdk_shell.py b/dts/framework/remote_session/dpdk_shell.py
index b807f9bdae..61cc4687f3 100644
--- a/dts/framework/remote_session/dpdk_shell.py
+++ b/dts/framework/remote_session/dpdk_shell.py
@@ -11,8 +11,8 @@
from pathlib import PurePath
from api.context import get_ctx
+from api.params.eal import EalParams
from api.testbed_model.cpu import LogicalCoreList
-from framework.params.eal import EalParams
from framework.remote_session.interactive_shell import (
InteractiveShell,
only_active,
diff --git a/dts/framework/remote_session/interactive_shell.py b/dts/framework/remote_session/interactive_shell.py
index ec539bad95..f7f0669eea 100644
--- a/dts/framework/remote_session/interactive_shell.py
+++ b/dts/framework/remote_session/interactive_shell.py
@@ -35,9 +35,9 @@
InteractiveSSHSessionDeadError,
InteractiveSSHTimeoutError,
)
+from api.params import Params
from api.testbed_model.node import Node
from framework.logger import DTSLogger, get_dts_logger
-from framework.params import Params
from framework.settings import SETTINGS
P = ParamSpec("P")
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index fd5cef5268..ba67c9e1c6 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -35,6 +35,7 @@
match_all_packets,
send_packets_and_capture,
)
+from api.params import Params
from api.test import verify
from api.test_suite import TestSuite, func_test
from api.testbed_model.cpu import LogicalCoreList
@@ -42,7 +43,6 @@
PacketFilteringConfig,
)
from api.testpmd import TestPmd
-from framework.params import Params
from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
diff --git a/dts/tests/TestSuite_single_core_forward_perf.py b/dts/tests/TestSuite_single_core_forward_perf.py
index f1eb435759..24f2cebf17 100644
--- a/dts/tests/TestSuite_single_core_forward_perf.py
+++ b/dts/tests/TestSuite_single_core_forward_perf.py
@@ -21,11 +21,11 @@
requires_link_topology,
)
from api.packet import assess_performance_by_packet
+from api.params.types import TestPmdParamsDict
from api.test import verify, write_performance_json
from api.test_suite import BaseConfig, TestSuite, perf_test
from api.testpmd import TestPmd
from api.testpmd.config import RXRingParams, TXRingParams
-from framework.params.types import TestPmdParamsDict
class Config(BaseConfig):
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread* [PATCH v4 7/7] dts: separate Linux session into interface and logic
2026-04-30 22:06 ` [PATCH v4 0/7] dts: move test suite imports from framework to API Dean Marx
` (5 preceding siblings ...)
2026-04-30 22:06 ` [PATCH v4 6/7] dts: move params directory " Dean Marx
@ 2026-04-30 22:06 ` Dean Marx
6 siblings, 0 replies; 81+ messages in thread
From: Dean Marx @ 2026-04-30 22:06 UTC (permalink / raw)
To: patrickrobb1997, luca.vizzarro, yoan.picchi, Honnappa.Nagarahalli,
paul.szczepanek
Cc: dev, Dean Marx
Separate Linux session into an interface for the API,
and a logical module in the framework.
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
doc/api/dts/framework.linux_session.rst | 8 +
doc/api/dts/index.rst | 1 +
dts/api/testbed_model/linux_session.py | 372 ++----------------------
dts/api/testbed_model/node.py | 6 +-
dts/framework/linux_session.py | 366 +++++++++++++++++++++++
5 files changed, 402 insertions(+), 351 deletions(-)
create mode 100644 doc/api/dts/framework.linux_session.rst
create mode 100644 dts/framework/linux_session.py
diff --git a/doc/api/dts/framework.linux_session.rst b/doc/api/dts/framework.linux_session.rst
new file mode 100644
index 0000000000..9de2e1484d
--- /dev/null
+++ b/doc/api/dts/framework.linux_session.rst
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+framework.linux\_session
+========================
+
+.. automodule:: framework.linux_session
+ :members:
+ :show-inheritance:
diff --git a/doc/api/dts/index.rst b/doc/api/dts/index.rst
index e89e782ac0..0dbc18b75c 100644
--- a/doc/api/dts/index.rst
+++ b/doc/api/dts/index.rst
@@ -37,6 +37,7 @@ Modules
framework.parser
api.utils
api.exception
+ framework.linux_session
Indices and tables
diff --git a/dts/api/testbed_model/linux_session.py b/dts/api/testbed_model/linux_session.py
index 7307b2abe2..5bcbf1ce97 100644
--- a/dts/api/testbed_model/linux_session.py
+++ b/dts/api/testbed_model/linux_session.py
@@ -1,367 +1,41 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright(c) 2023 PANTHEON.tech s.r.o.
# Copyright(c) 2023 University of New Hampshire
+"""Linux OS session interface.
-"""Linux OS translator.
-
-Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
-compliant with POSIX standards, so this module only implements the parts that aren't.
-This intermediate module implements the common parts of mostly POSIX compliant distributions.
+Extends the base :class:`~.os_session.OSSession` with methods specific to Linux nodes.
+The concrete implementation containing all backend logic lives in the framework package.
"""
-import json
-import re
-from collections.abc import Iterable
-from functools import cached_property
+from abc import ABC, abstractmethod
from pathlib import PurePath
-from typing import TypedDict
-
-from typing_extensions import NotRequired
-
-from api.exception import (
- ConfigurationError,
- InternalError,
- RemoteCommandExecutionError,
-)
-from api.testbed_model.port import PortInfo
-from api.utils import expand_range
-
-from .cpu import LogicalCore
-from .port import Port
-from .posix_session import PosixSession
-
-
-class LshwConfigurationOutput(TypedDict):
- """The relevant parts of ``lshw``'s ``configuration`` section."""
-
- #:
- driver: str
- #:
- link: str
-
-
-class LshwOutput(TypedDict):
- """A model of the relevant information from ``lshw``'s json output.
-
- Example:
- ::
-
- {
- ...
- "businfo" : "pci@0000:08:00.0",
- "logicalname" : "enp8s0",
- "version" : "00",
- "serial" : "52:54:00:59:e1:ac",
- ...
- "configuration" : {
- ...
- "link" : "yes",
- ...
- },
- ...
- """
-
- #:
- businfo: str
- #:
- logicalname: NotRequired[str]
- #:
- serial: NotRequired[str]
- #:
- configuration: LshwConfigurationOutput
-
-
-class LinuxSession(PosixSession):
- """The implementation of non-Posix compliant parts of Linux."""
-
- @staticmethod
- def _get_privileged_command(command: str) -> str:
- command = command.replace(r"'", r"\'")
- return f"sudo -- sh -c '{command}'"
- def get_remote_cpus(self) -> list[LogicalCore]:
- """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
- cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
- lcores = []
- for cpu_line in cpu_info.splitlines():
- lcore, core, socket, node = map(int, cpu_line.split(","))
- lcores.append(LogicalCore(lcore, core, socket, node))
- return lcores
-
- def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
- """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
- return dpdk_prefix
-
- def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
-
- Raises:
- ConfigurationError: If the given `hugepage_size` is not supported by the OS.
- """
- self._logger.info("Getting Hugepage information.")
- if (
- f"hugepages-{hugepage_size}kB"
- not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
- ):
- raise ConfigurationError("hugepage size not supported by operating system")
- hugepages_total = self._get_hugepages_total(hugepage_size)
- self._numa_nodes = self._get_numa_nodes()
-
- if force_first_numa or hugepages_total < number_of:
- # when forcing numa, we need to clear existing hugepages regardless
- # of size, so they can be moved to the first numa node
- self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
- else:
- self._logger.info("Hugepages already configured.")
- self._mount_huge_pages()
-
- def _get_hugepages_total(self, hugepage_size: int) -> int:
- hugepages_total = self.send_command(
- f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
- ).stdout
- return int(hugepages_total)
-
- def _get_numa_nodes(self) -> list[int]:
- try:
- numa_count = self.send_command(
- "cat /sys/devices/system/node/online", verify=True
- ).stdout
- numa_range = expand_range(numa_count)
- except RemoteCommandExecutionError:
- # the file doesn't exist, meaning the node doesn't support numa
- numa_range = []
- return numa_range
-
- def _mount_huge_pages(self) -> None:
- self._logger.info("Re-mounting Hugepages.")
- hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
- self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
- result = self.send_command(hugapge_fs_cmd)
- if result.stdout == "":
- remote_mount_path = "/mnt/huge"
- self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
- self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
-
- def _supports_numa(self) -> bool:
- # the system supports numa if self._numa_nodes is non-empty and there are more
- # than one numa node (in the latter case it may actually support numa, but
- # there's no reason to do any numa specific configuration)
- return len(self._numa_nodes) > 1
-
- def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
- self._logger.info("Configuring Hugepages.")
- hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
- if force_first_numa and self._supports_numa():
- # clear non-numa hugepages
- self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
- hugepage_config_path = (
- f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
- f"/hugepages-{size}kB/nr_hugepages"
- )
-
- self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
-
- def get_port_info(self, pci_address: str) -> PortInfo:
- """Overrides :meth:`~.os_session.OSSession.get_port_info`.
-
- Raises:
- ConfigurationError: If the port could not be found.
- """
- bus_info = f"pci@{pci_address}"
- port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
- if port is None:
- raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
- logical_name = port.get("logicalname", "")
- mac_address = port.get("serial", "")
+class LinuxSession(ABC):
+ """Abstract interface for Linux-specific OS session operations."""
- configuration = port.get("configuration", {})
- driver = configuration.get("driver", "")
- is_link_up = configuration.get("link", "down") == "up"
-
- return PortInfo(mac_address, logical_name, driver, is_link_up)
-
- def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
-
- The :attr:`~.devbind_script_path` property must be setup in order to call this method.
- """
- ports_pci_addrs = " ".join(port.pci for port in ports)
-
- self.send_command(
- f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
- privileged=True,
- verify=True,
- )
-
- del self._lshw_net_info
-
- def bring_up_link(self, ports: Iterable[Port]) -> None:
- """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
- for port in ports:
- self.send_command(
- f"ip link set dev {port.logical_name} up", privileged=True, verify=True
- )
-
- del self._lshw_net_info
-
- def set_interface_link_up(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
- self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
-
- def delete_interface(self, name: str) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
- self.send_command(f"ip link delete {name}", privileged=True)
-
- @cached_property
+ @property
+ @abstractmethod
def devbind_script_path(self) -> PurePath:
- """The path to the dpdk-devbind.py script on the node.
-
- Needs to be manually assigned first in order to be used.
+ """The path to the devbind script."""
- Raises:
- InternalError: If accessed before environment setup.
- """
- raise InternalError("Accessed devbind script path before setup.")
-
- def load_vfio(self, pf_port: Port) -> None:
- """Overrides :meth:`~os_session.OSSession,load_vfio`."""
- cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
- device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
- if device and device.group(1) in ["37c8", "0435", "19e2"]:
- self.send_command(
- "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
- privileged=True,
- )
- self.send_command(
- "modprobe -r vfio_virqfd; modprobe -r vfio",
- privileged=True,
- )
- self.send_command(
- "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
- )
- self.send_command(
- "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
- privileged=True,
- )
- else:
- self.send_command("modprobe vfio-pci")
- self.refresh_lshw()
+ @devbind_script_path.setter
+ @abstractmethod
+ def devbind_script_path(self, value: PurePath) -> None:
+ """Set the devbind script path after environment setup."""
- def create_crypto_vfs(self, pf_port: list[Port]) -> None:
- """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+ @abstractmethod
+ def set_interface_link_up(self, name: str) -> None:
+ """Set the link status of an interface to up.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface.
"""
- for port in pf_port:
- self.delete_crypto_vfs(port)
- for port in pf_port:
- sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
- )
- self.send_command(
- f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
- )
-
- self.refresh_lshw()
- def create_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+ @abstractmethod
+ def delete_interface(self, name: str) -> None:
+ """Delete a virtual interface.
- Raises:
- InternalError: If there are existing VFs which have to be deleted.
+ Args:
+ name: The name of the interface to delete.
"""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if 0 < curr_num_vfs:
- raise InternalError("There are existing VFs on the port which must be deleted.")
- if curr_num_vfs == 0:
- self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
- self.refresh_lshw()
-
- def delete_crypto_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
- self.send_command(
- f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
- privileged=True,
- )
- self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
-
- def delete_vfs(self, pf_port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(
- self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
- )
- if curr_num_vfs == 0:
- self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
- else:
- self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
-
- def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- f"readlink {sys_bus_path}/virtfn*",
- privileged=True,
- )
- return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
- return []
-
- def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
- """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
- sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
- curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
- if curr_num_vfs > 0:
- pci_addrs = self.send_command(
- 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
- + f"{sys_bus_path}/virtfn*/uevent",
- privileged=True,
- )
- return pci_addrs.stdout.splitlines()
- else:
- return []
-
- @cached_property
- def _lshw_net_info(self) -> list[LshwOutput]:
- output = self.send_command("lshw -quiet -json -C network", verify=True)
- return json.loads(output.stdout)
-
- def refresh_lshw(self) -> None:
- """Force refresh of cached lshw network info."""
- if "_lshw_net_info" in self.__dict__:
- del self.__dict__["_lshw_net_info"]
- _ = self._lshw_net_info
-
- def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
- if attr_value:
- setattr(port, attr_name, attr_value)
- self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
- else:
- self._logger.warning(
- f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
- )
-
- def configure_port_mtu(self, mtu: int, port: Port) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
- self.send_command(
- f"ip link set dev {port.logical_name} mtu {mtu}",
- privileged=True,
- verify=True,
- )
-
- def configure_ipv4_forwarding(self, enable: bool) -> None:
- """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
- state = 1 if enable else 0
- self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
diff --git a/dts/api/testbed_model/node.py b/dts/api/testbed_model/node.py
index 40dd7f0666..ca634655e6 100644
--- a/dts/api/testbed_model/node.py
+++ b/dts/api/testbed_model/node.py
@@ -15,17 +15,19 @@
from functools import cached_property
from pathlib import PurePath
-from typing import Literal, TypeAlias
+from typing import TYPE_CHECKING, Literal, TypeAlias
from api.exception import ConfigurationError, InternalError
from framework.config.node import (
OS,
NodeConfiguration,
)
+
+if TYPE_CHECKING:
+ from framework.linux_session import LinuxSession
from framework.logger import DTSLogger, get_dts_logger
from .cpu import Architecture, LogicalCore
-from .linux_session import LinuxSession
from .os_session import OSSession, OSSessionInfo
from .port import Port
diff --git a/dts/framework/linux_session.py b/dts/framework/linux_session.py
new file mode 100644
index 0000000000..e5320b7fc4
--- /dev/null
+++ b/dts/framework/linux_session.py
@@ -0,0 +1,366 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 PANTHEON.tech s.r.o.
+# Copyright(c) 2023 University of New Hampshire
+
+"""Linux OS translator.
+
+Translate OS-unaware calls into Linux calls/utilities. Most of Linux distributions are mostly
+compliant with POSIX standards, so this module only implements the parts that aren't.
+This intermediate module implements the common parts of mostly POSIX compliant distributions.
+"""
+
+import json
+import re
+from collections.abc import Iterable
+from functools import cached_property
+from pathlib import PurePath
+from typing import TypedDict
+
+from typing_extensions import NotRequired
+
+from api.exception import (
+ ConfigurationError,
+ InternalError,
+ RemoteCommandExecutionError,
+)
+from api.testbed_model.cpu import LogicalCore
+from api.testbed_model.linux_session import LinuxSession as LinuxSessionBase
+from api.testbed_model.port import Port, PortInfo
+from api.testbed_model.posix_session import PosixSession
+from api.utils import expand_range
+
+
+class LshwConfigurationOutput(TypedDict):
+ """The relevant parts of ``lshw``'s ``configuration`` section."""
+
+ #:
+ driver: str
+ #:
+ link: str
+
+
+class LshwOutput(TypedDict):
+ """A model of the relevant information from ``lshw``'s json output.
+
+ Example:
+ ::
+
+ {
+ ...
+ "businfo" : "pci@0000:08:00.0",
+ "logicalname" : "enp8s0",
+ "version" : "00",
+ "serial" : "52:54:00:59:e1:ac",
+ ...
+ "configuration" : {
+ ...
+ "link" : "yes",
+ ...
+ },
+ ...
+ """
+
+ #:
+ businfo: str
+ #:
+ logicalname: NotRequired[str]
+ #:
+ serial: NotRequired[str]
+ #:
+ configuration: LshwConfigurationOutput
+
+
+class LinuxSession(PosixSession, LinuxSessionBase):
+ """The implementation of non-Posix compliant parts of Linux."""
+
+ @staticmethod
+ def _get_privileged_command(command: str) -> str:
+ command = command.replace(r"'", r"\'")
+ return f"sudo -- sh -c '{command}'"
+
+ def get_remote_cpus(self) -> list[LogicalCore]:
+ """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
+ cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
+ lcores = []
+ for cpu_line in cpu_info.splitlines():
+ lcore, core, socket, node = map(int, cpu_line.split(","))
+ lcores.append(LogicalCore(lcore, core, socket, node))
+ return lcores
+
+ def get_dpdk_file_prefix(self, dpdk_prefix: str) -> str:
+ """Overrides :meth:`~.os_session.OSSession.get_dpdk_file_prefix`."""
+ return dpdk_prefix
+
+ def setup_hugepages(self, number_of: int, hugepage_size: int, force_first_numa: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.setup_hugepages`.
+
+ Raises:
+ ConfigurationError: If the given `hugepage_size` is not supported by the OS.
+ """
+ self._logger.info("Getting Hugepage information.")
+ if (
+ f"hugepages-{hugepage_size}kB"
+ not in self.send_command("ls /sys/kernel/mm/hugepages").stdout
+ ):
+ raise ConfigurationError("hugepage size not supported by operating system")
+ hugepages_total = self._get_hugepages_total(hugepage_size)
+ self._numa_nodes = self._get_numa_nodes()
+
+ if force_first_numa or hugepages_total < number_of:
+ # when forcing numa, we need to clear existing hugepages regardless
+ # of size, so they can be moved to the first numa node
+ self._configure_huge_pages(number_of, hugepage_size, force_first_numa)
+ else:
+ self._logger.info("Hugepages already configured.")
+ self._mount_huge_pages()
+
+ def _get_hugepages_total(self, hugepage_size: int) -> int:
+ hugepages_total = self.send_command(
+ f"cat /sys/kernel/mm/hugepages/hugepages-{hugepage_size}kB/nr_hugepages"
+ ).stdout
+ return int(hugepages_total)
+
+ def _get_numa_nodes(self) -> list[int]:
+ try:
+ numa_count = self.send_command(
+ "cat /sys/devices/system/node/online", verify=True
+ ).stdout
+ numa_range = expand_range(numa_count)
+ except RemoteCommandExecutionError:
+ # the file doesn't exist, meaning the node doesn't support numa
+ numa_range = []
+ return numa_range
+
+ def _mount_huge_pages(self) -> None:
+ self._logger.info("Re-mounting Hugepages.")
+ hugapge_fs_cmd = "awk '/hugetlbfs/ { print $2 }' /proc/mounts"
+ self.send_command(f"umount $({hugapge_fs_cmd})", privileged=True)
+ result = self.send_command(hugapge_fs_cmd)
+ if result.stdout == "":
+ remote_mount_path = "/mnt/huge"
+ self.send_command(f"mkdir -p {remote_mount_path}", privileged=True)
+ self.send_command(f"mount -t hugetlbfs nodev {remote_mount_path}", privileged=True)
+
+ def _supports_numa(self) -> bool:
+ # the system supports numa if self._numa_nodes is non-empty and there are more
+ # than one numa node (in the latter case it may actually support numa, but
+ # there's no reason to do any numa specific configuration)
+ return len(self._numa_nodes) > 1
+
+ def _configure_huge_pages(self, number_of: int, size: int, force_first_numa: bool) -> None:
+ self._logger.info("Configuring Hugepages.")
+ hugepage_config_path = f"/sys/kernel/mm/hugepages/hugepages-{size}kB/nr_hugepages"
+ if force_first_numa and self._supports_numa():
+ # clear non-numa hugepages
+ self.send_command(f"echo 0 | tee {hugepage_config_path}", privileged=True)
+ hugepage_config_path = (
+ f"/sys/devices/system/node/node{self._numa_nodes[0]}/hugepages"
+ f"/hugepages-{size}kB/nr_hugepages"
+ )
+
+ self.send_command(f"echo {number_of} | tee {hugepage_config_path}", privileged=True)
+
+ def get_port_info(self, pci_address: str) -> PortInfo:
+ """Overrides :meth:`~.os_session.OSSession.get_port_info`.
+
+ Raises:
+ ConfigurationError: If the port could not be found.
+ """
+ bus_info = f"pci@{pci_address}"
+ port = next(port for port in self._lshw_net_info if port.get("businfo") == bus_info)
+ if port is None:
+ raise ConfigurationError(f"Port {pci_address} could not be found on the node.")
+
+ logical_name = port.get("logicalname", "")
+ mac_address = port.get("serial", "")
+
+ configuration = port.get("configuration", {})
+ driver = configuration.get("driver", "")
+ is_link_up = configuration.get("link", "down") == "up"
+
+ return PortInfo(mac_address, logical_name, driver, is_link_up)
+
+ def bind_ports_to_driver(self, ports: list[Port], driver_name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bind_ports_to_driver`.
+
+ The :attr:`~.devbind_script_path` property must be setup in order to call this method.
+ """
+ ports_pci_addrs = " ".join(port.pci for port in ports)
+
+ self.send_command(
+ f"{self.devbind_script_path} -b {driver_name} --force {ports_pci_addrs}",
+ privileged=True,
+ verify=True,
+ )
+
+ del self._lshw_net_info
+
+ def bring_up_link(self, ports: Iterable[Port]) -> None:
+ """Overrides :meth:`~.os_session.OSSession.bring_up_link`."""
+ for port in ports:
+ self.send_command(
+ f"ip link set dev {port.logical_name} up", privileged=True, verify=True
+ )
+
+ del self._lshw_net_info
+
+ def set_interface_link_up(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.set_interface_link_up`."""
+ self.send_command(f"ip link set dev {name} up", privileged=True, verify=True)
+
+ def delete_interface(self, name: str) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_interface`."""
+ self.send_command(f"ip link delete {name}", privileged=True)
+
+ @cached_property
+ def devbind_script_path(self) -> PurePath:
+ """The path to the dpdk-devbind.py script on the node.
+
+ Needs to be manually assigned first in order to be used.
+
+ Raises:
+ InternalError: If accessed before environment setup.
+ """
+ raise InternalError("Accessed devbind script path before setup.")
+
+ def load_vfio(self, pf_port: Port) -> None:
+ """Overrides :meth:`~os_session.OSSession,load_vfio`."""
+ cmd_result = self.send_command(f"lspci -nn -s {pf_port.pci}")
+ device = re.search(r":([0-9a-fA-F]{4})\]", cmd_result.stdout)
+ if device and device.group(1) in ["37c8", "0435", "19e2"]:
+ self.send_command(
+ "modprobe -r vfio_iommu_type1; modprobe -r vfio_pci",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe -r vfio_virqfd; modprobe -r vfio",
+ privileged=True,
+ )
+ self.send_command(
+ "modprobe vfio-pci disable_denylist=1 enable_sriov=1", privileged=True
+ )
+ self.send_command(
+ "echo 1 | tee /sys/module/vfio/parameters/enable_unsafe_noiommu_mode",
+ privileged=True,
+ )
+ else:
+ self.send_command("modprobe vfio-pci")
+ self.refresh_lshw()
+
+ def create_crypto_vfs(self, pf_port: list[Port]) -> None:
+ """Overrides :meth:`~os_session.OSSession.create_crypto_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ for port in pf_port:
+ self.delete_crypto_vfs(port)
+ for port in pf_port:
+ sys_bus_path = f"/sys/bus/pci/devices/{port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+ )
+ self.send_command(
+ f"echo {num_vfs} | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True
+ )
+
+ self.refresh_lshw()
+
+ def create_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+ Raises:
+ InternalError: If there are existing VFs which have to be deleted.
+ """
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if 0 < curr_num_vfs:
+ raise InternalError("There are existing VFs on the port which must be deleted.")
+ if curr_num_vfs == 0:
+ self.send_command(f"echo 1 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+ self.refresh_lshw()
+
+ def delete_crypto_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_crypto_vfs`."""
+ self.send_command(
+ f"echo 1 | sudo tee /sys/bus/pci/devices/{pf_port.pci}/remove".replace(":", "\\:"),
+ privileged=True,
+ )
+ self.send_command("echo 1 | sudo tee /sys/bus/pci/rescan", privileged=True)
+
+ def delete_vfs(self, pf_port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.delete_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(
+ self.send_command(f"cat {sys_bus_path}/sriov_numvfs", privileged=True).stdout
+ )
+ if curr_num_vfs == 0:
+ self._logger.debug(f"No VFs found on port {pf_port.pci}, skipping deletion")
+ else:
+ self.send_command(f"echo 0 | sudo tee {sys_bus_path}/sriov_numvfs", privileged=True)
+
+ def get_pci_addr_of_crypto_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_crypto_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ f"readlink {sys_bus_path}/virtfn*",
+ privileged=True,
+ )
+ return [pci.replace("../", "") for pci in pci_addrs.stdout.splitlines()]
+ return []
+
+ def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+ """Overrides :meth:`~.os_session.OSSession.get_pci_addr_of_vfs`."""
+ sys_bus_path = f"/sys/bus/pci/devices/{pf_port.pci}".replace(":", "\\:")
+ curr_num_vfs = int(self.send_command(f"cat {sys_bus_path}/sriov_numvfs").stdout)
+ if curr_num_vfs > 0:
+ pci_addrs = self.send_command(
+ 'awk -F "PCI_SLOT_NAME=" "/PCI_SLOT_NAME=/ {print \\$2}" '
+ + f"{sys_bus_path}/virtfn*/uevent",
+ privileged=True,
+ )
+ return pci_addrs.stdout.splitlines()
+ else:
+ return []
+
+ @cached_property
+ def _lshw_net_info(self) -> list[LshwOutput]:
+ output = self.send_command("lshw -quiet -json -C network", verify=True)
+ return json.loads(output.stdout)
+
+ def refresh_lshw(self) -> None:
+ """Force refresh of cached lshw network info."""
+ if "_lshw_net_info" in self.__dict__:
+ del self.__dict__["_lshw_net_info"]
+ _ = self._lshw_net_info
+
+ def _update_port_attr(self, port: Port, attr_value: str | None, attr_name: str) -> None:
+ if attr_value:
+ setattr(port, attr_name, attr_value)
+ self._logger.debug(f"Found '{attr_name}' of port {port.pci}: '{attr_value}'.")
+ else:
+ self._logger.warning(
+ f"Attempted to get '{attr_name}' of port {port.pci}, but it doesn't exist."
+ )
+
+ def configure_port_mtu(self, mtu: int, port: Port) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_port_mtu`."""
+ self.send_command(
+ f"ip link set dev {port.logical_name} mtu {mtu}",
+ privileged=True,
+ verify=True,
+ )
+
+ def configure_ipv4_forwarding(self, enable: bool) -> None:
+ """Overrides :meth:`~.os_session.OSSession.configure_ipv4_forwarding`."""
+ state = 1 if enable else 0
+ self.send_command(f"sysctl -w net.ipv4.ip_forward={state}", privileged=True)
--
2.52.0
^ permalink raw reply related [flat|nested] 81+ messages in thread