Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lisa/microsoft/testsuites/core/provisioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,8 +635,10 @@ def check_sriov(self, log: Logger, node: RemoteNode) -> None:
else:
pci_nic_check = True
if pci_nic_check:
log.info(f"check_sriov: PCI nic count {len(node_nic_info.get_pci_nics())}")
assert_that(len(node_nic_info.get_pci_nics())).described_as(
f"VF count inside VM is {len(node_nic_info.get_pci_nics())}, "
f"actual sriov nic count is {sriov_count}"
pci_nics = node_nic_info.get_pci_nics_except_ib()
pci_nic_count = len(pci_nics)
log.info(f"check_sriov: PCI nic count (without IB) {pci_nic_count}")
assert_that(pci_nic_count).described_as(
f"VF count inside VM (without IB) is {pci_nic_count}, "
f"actual sriov nic count is {sriov_count}. "
).is_equal_to(sriov_count)
20 changes: 12 additions & 8 deletions lisa/microsoft/testsuites/network/common.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
from typing import Dict, List, cast
from typing import Dict, List, Tuple, cast

from assertpy import assert_that
from retry import retry
Expand Down Expand Up @@ -53,9 +53,11 @@ def initialize_nic_info(
f"inside vm, it should equal to {interface_info.ip_addr}."
).is_true()
if is_sriov:
assert_that(len(nics_info.get_device_slots())).described_as(
f"VF count inside VM is {len(set(nics_info.get_device_slots()))}, "
f"actual sriov nic count is {sriov_count}"
pci_nic_count = len(nics_info.get_pci_nics_except_ib())
assert_that(pci_nic_count).described_as(
f"Ethernet VF count inside VM (without IB) is {pci_nic_count}, "
f"actual sriov nic count is {sriov_count}. "
f"Total PCI NICs: {nics_info.get_pci_nics()}"
).is_equal_to(sriov_count)
vm_nics[node.name] = nics_info.nics

Expand All @@ -70,12 +72,14 @@ def sriov_basic_test(environment: Environment) -> None:
devices_slots = lspci.get_device_names_by_type(
constants.DEVICE_TYPE_SRIOV, force_run=True
)
if len(devices_slots) != len(set(node.nics.get_device_slots())):
ethernet_device_slots = set(node.nics.get_device_slots_except_ib())
if len(devices_slots) != len(ethernet_device_slots):
node.nics.reload()
ethernet_device_slots = set(node.nics.get_device_slots_except_ib())
assert_that(devices_slots).described_as(
"count of sriov devices listed from lspci is not expected,"
" please check the driver works properly"
).is_length(len(set(node.nics.get_device_slots())))
).is_length(len(ethernet_device_slots))

# 2. Check module of sriov network device is loaded.
for module_name in node.nics.get_used_modules(["hv_netvsc"]):
Expand Down Expand Up @@ -172,7 +176,7 @@ def _find_matching_dest_nic(
source_nic_info: NicInfo,
vm_nics: Dict[str, Dict[str, NicInfo]],
dest_node: RemoteNode,
) -> tuple[str, int]:
) -> Tuple[str, int]:
"""Find destination NIC on same subnet as source.
Returns (nic_name, skipped_count)."""
skipped_infiniband = 0
Expand All @@ -198,7 +202,7 @@ def _setup_nic_monitoring(
remove_module: bool,
turn_off_lower: bool,
source_node: RemoteNode,
) -> tuple[str, str, str, str]:
) -> Tuple[str, str, str, str]:
"""Setup NIC monitoring based on configuration.
Returns (source_nic, dest_nic, source_pci_nic, dest_pci_nic)."""
source_synthetic_nic = source_nic_info.name
Expand Down
12 changes: 10 additions & 2 deletions lisa/microsoft/testsuites/network/sriov.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Licensed under the MIT license.
import re
from pathlib import Path
from typing import Any, Dict, List, cast
from typing import Any, Dict, List, Optional, cast

from assertpy import assert_that
from microsoft.testsuites.network.common import (
Expand Down Expand Up @@ -811,6 +811,9 @@ def verify_sriov_interrupts_change(self, environment: Environment) -> None:
client_interrupt_inspector = client_node.tools[InterruptInspector]
for _, client_nic_info in vm_nics[client_node.name].items():
if client_nic_info.is_pci_module_enabled:
# Skip InfiniBand interfaces — they use RDMA, not Ethernet SR-IOV
if client_nic_info.name and client_nic_info.name.startswith("ib"):
continue
# 2. Get initial interrupts sum per irq and cpu number on client node.
# only collect 'Completion Queue Interrupts' irqs
initial_pci_interrupts_by_irqs = (
Expand All @@ -834,8 +837,13 @@ def verify_sriov_interrupts_change(self, environment: Environment) -> None:
assert_that(len(initial_pci_interrupts_by_cpus)).described_as(
"initial cpu count of interrupts should be equal to cpu count"
).is_equal_to(client_thread_count)
matched_server_nic_info: NicInfo
matched_server_nic_info: Optional[NicInfo] = None
for _, server_nic_info in vm_nics[server_node.name].items():
# Skip NICs without IP addresses (IB, enslaved VFs, etc.)
if not server_nic_info.ip_addr:
continue
if server_nic_info.name and server_nic_info.name.startswith("ib"):
continue
if (
server_nic_info.ip_addr.rsplit(".", maxsplit=1)[0]
== client_nic_info.ip_addr.rsplit(".", maxsplit=1)[0]
Expand Down
13 changes: 9 additions & 4 deletions lisa/microsoft/testsuites/network/stress.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
from typing import Any, cast
from typing import Any, Optional, cast

from assertpy import assert_that
from microsoft.testsuites.network.common import (
Expand Down Expand Up @@ -73,15 +73,20 @@ def stress_sriov_iperf(self, environment: Environment) -> None:
client_nic_info_list = [
x
for _, x in vm_nics[client_node.name].items()
if x.ip_addr == client_node.internal_address
if x.ip_addr and x.ip_addr == client_node.internal_address
]
assert_that(client_nic_info_list).described_as(
"not found the primary network interface."
).is_not_none()
).is_not_empty()
client_nic_info = client_nic_info_list[0]
isinstance(client_nic_info, NicInfo)
matched_server_nic_info: NicInfo
matched_server_nic_info: Optional[NicInfo] = None
for _, server_nic_info in vm_nics[server_node.name].items():
# Skip InfiniBand and NICs without IP addresses
if not server_nic_info.ip_addr:
continue
if server_nic_info.name and server_nic_info.name.startswith("ib"):
continue
if (
server_nic_info.ip_addr.rsplit(".", maxsplit=1)[0]
== client_nic_info.ip_addr.rsplit(".", maxsplit=1)[0]
Expand Down
8 changes: 5 additions & 3 deletions lisa/microsoft/testsuites/performance/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,9 @@ def check_sriov_count(node: RemoteNode, sriov_count: int) -> None:
node_nic_info = node.nics
node_nic_info.reload()

assert_that(len(node_nic_info.get_pci_nics())).described_as(
f"VF count inside VM is {len(node_nic_info.get_pci_nics())},"
f"actual sriov nic count is {sriov_count}"
pci_nics = node_nic_info.get_pci_nics_except_ib()
pci_nic_count = len(pci_nics)
assert_that(pci_nic_count).described_as(
f"VF count inside VM (without IB) is {pci_nic_count}, "
f"actual sriov nic count is {sriov_count}. "
).is_equal_to(sriov_count)
33 changes: 32 additions & 1 deletion lisa/nic.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ def get_synthetic_devices(self) -> List[str]:
self._node.log.debug(f"Found synthetic devices: {synthetic_devices}")
return synthetic_devices

def get_pci_nics_except_ib(self) -> List[str]:
"""
Get NIC names for PCI-associated NICs, excluding InfiniBand (ib*)
"""
pci_nics = []
for nic in self.nics.values():
nic_name = nic.lower if nic.lower else nic.name
if nic_name and nic_name.startswith("ib"):
continue
if nic.name and nic.name.startswith("ib"):
continue
if nic.is_pci_only_nic:
pci_nics.append(nic.name)
elif nic.lower:
pci_nics.append(nic.lower)
return pci_nics

def get_pci_nics(self) -> List[str]:
pci_nics = []
for nic in self.nics.values():
Expand Down Expand Up @@ -221,6 +238,20 @@ def get_used_modules(self, exclude_module_name: List[str]) -> List[str]:
def get_device_slots(self) -> List[str]:
return [x.pci_slot for x in self.nics.values() if x.pci_slot]

def get_device_slots_except_ib(self) -> List[str]:
"""Get PCI slots for NICs, excluding InfiniBand (ib*) interfaces."""
slots = []
for nic in self.nics.values():
if not nic.pci_slot:
continue
nic_name = nic.lower if nic.lower else nic.name
if nic_name and nic_name.startswith("ib"):
continue
if nic.name and nic.name.startswith("ib"):
continue
slots.append(nic.pci_slot)
return slots

def _get_nics_driver(self) -> None:
for nic in [x.name for x in self.nics.values()]:
self.get_nic_driver(nic)
Expand Down Expand Up @@ -405,7 +436,7 @@ def _get_nic_uuid(self, nic_name: str) -> str:
readlink = self._node.tools[Readlink]
full_dev_path = readlink.get_target(f"/sys/class/net/{nic_name}/device")
uuid = os.path.basename(full_dev_path)
self._node.log.debug(f"{nic_name} UUID:{uuid}")
self._node.log.debug(f"{nic_name} UUID: {uuid}")
return uuid

def _get_nic_uuids(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion lisa/tools/lspci.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def get_pci_slot_from_device_path(self, device_path: str) -> Optional[str]:
"""
Extract PCI slot information from a device path.
"""
pci_slot = get_matched_str(device_path, PATTERN_PCI_SLOT)
pci_slot = get_matched_str(device_path, PATTERN_PCI_SLOT, first_match=False)
return pci_slot if pci_slot else None


Expand Down
Loading