[v5,1/2] dts: add OS abstractions for creating virtual functions

Message ID 20250313033611.1896695-2-probb@iol.unh.edu (mailing list archive)
State New
Delegated to: Paul Szczepanek
Headers
Series dts: add VFs to the framework |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation warning apply patch failure

Commit Message

Patrick Robb March 13, 2025, 3:36 a.m. UTC
Virtual functions are created in different ways per operating system.
Accordingly, we have abstracted the functions for managing virtual
functions into different classes per OS. This patch adds stubs
for creating virtual functions and gathering virtual function info.

Bugzilla ID: 1500

Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu>
Signed-off-by: Patrick Robb <probb@iol.unh.edu>
---
 dts/framework/testbed_model/linux_session.py | 37 +++++++++++++++++++-
 dts/framework/testbed_model/os_session.py    | 27 ++++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)
  

Comments

Patrick Robb March 13, 2025, 12:53 p.m. UTC | #1
On Wed, Mar 12, 2025 at 11:40 PM Patrick Robb <probb@iol.unh.edu> wrote:

>
> +    def create_vfs(self, pf_port: Port) -> None:
> +        """Overrides :meth:`~.os_session.OSSession.create_vfs`.
> +
> +        Raises:
> +            InternalError: If the number of VFs is greater than 0 but
> less than the
> +            maximum for `pf_port`.
> +        """
> +        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)
> +        max_num_vfs = int(
> +            self.send_command(f"cat {sys_bus_path}/sriov_totalvfs",
> privileged=True).stdout
> +        )
> +        if 0 < curr_num_vfs < max_num_vfs:
> +            raise InternalError("There are existing VFs on the port which
> must be deleted.")
>

Maybe in this situation we should just delete all VFs, and then create the
new set of VFs.
  

Patch

diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index 7c2b110c99..35cc7f6852 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -16,7 +16,11 @@ 
 
 from typing_extensions import NotRequired
 
-from framework.exception import ConfigurationError, RemoteCommandExecutionError
+from framework.exception import (
+    ConfigurationError,
+    InternalError,
+    RemoteCommandExecutionError,
+)
 from framework.utils import expand_range
 
 from .cpu import LogicalCore
@@ -183,6 +187,37 @@  def bring_up_link(self, ports: Iterable[Port]) -> None:
                 f"ip link set dev {port.logical_name} up", privileged=True, verify=True
             )
 
+    def create_vfs(self, pf_port: Port) -> None:
+        """Overrides :meth:`~.os_session.OSSession.create_vfs`.
+
+        Raises:
+            InternalError: If the number of VFs is greater than 0 but less than the
+            maximum for `pf_port`.
+        """
+        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)
+        max_num_vfs = int(
+            self.send_command(f"cat {sys_bus_path}/sriov_totalvfs", privileged=True).stdout
+        )
+        if 0 < curr_num_vfs < max_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 {max_num_vfs} > {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 []
+
     @cached_property
     def _lshw_net_info(self) -> list[LshwOutput]:
         output = self.send_command("lshw -quiet -json -C network", verify=True)
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index 354c607357..a4ad9940b2 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -554,3 +554,30 @@  def configure_port_mtu(self, mtu: int, port: Port) -> None:
             mtu: Desired MTU value.
             port: Port to set `mtu` on.
         """
+
+    @abstractmethod
+    def create_vfs(self, pf_port: Port) -> None:
+        """Creates virtual functions for `pf_port`.
+
+        Checks how many virtual functions (VFs) `pf_port` supports, and creates that
+        number of VFs on the port.
+
+        Args:
+            pf_port: The port to create virtual functions on.
+
+        Raises:
+            InternalError: If the number of VFs is greater than 0 but less than the
+            maximum for `pf_port`.
+        """
+
+    @abstractmethod
+    def get_pci_addr_of_vfs(self, pf_port: Port) -> list[str]:
+        """Find the PCI addresses of all virtual functions (VFs) on the port `pf_port`.
+
+        Args:
+            pf_port: The port to find the VFs on.
+
+        Returns:
+            A list containing all of the PCI addresses of the VFs on the port. If the port has no
+            VFs then the list will be empty.
+        """