Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
54 changes: 36 additions & 18 deletions lisa/microsoft/testsuites/performance/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,16 @@ def perf_tcp_latency(test_result: TestResult) -> List[NetworkLatencyPerformanceM
server = cast(RemoteNode, environment.nodes[1])
client_lagscope = client.tools[Lagscope]
server_lagscope = server.tools[Lagscope]
# lagscope builds IPv4-style CLI args (-s<ip>/-r<ip>) with no IPv6 bracket
# handling. On dual-stack (use_ipv6) environments server.internal_address is
# IPv6, so resolve the server's internal IPv4 to bind/connect over instead.
server_comm_address = server.nics.get_internal_ipv4_address()
try:
for lagscope in [client_lagscope, server_lagscope]:
lagscope.set_busy_poll()
server_lagscope.run_as_server_async(ip=server.internal_address)
server_lagscope.run_as_server_async(ip=server_comm_address)
latency_perf_messages = client_lagscope.create_latency_performance_messages(
client_lagscope.run_as_client(server_ip=server.internal_address),
client_lagscope.run_as_client(server_ip=server_comm_address),
inspect.stack()[1][3],
test_result,
)
Expand Down Expand Up @@ -303,17 +307,22 @@ def perf_tcp_pps(
]
)

# netperf builds IPv4-style CLI args with no IPv6 bracket handling. On a
# dual-stack (use_ipv6) environment internal_address is IPv6, so resolve
# the internal IPv4 to bind/target instead.
server_comm_ip = server_node.nics.get_internal_ipv4_address()
server_interface_ip: str = ""
client_interface_ip: str = ""
if use_internal_address:
assert_that(server_node.internal_address).described_as(
assert_that(server_comm_ip).described_as(
"Server Node: internal address is not set"
).is_not_empty()
assert_that(client_node.internal_address).described_as(
client_comm_ip = client_node.nics.get_internal_ipv4_address()
assert_that(client_comm_ip).described_as(
"Client Node: internal address is not set"
).is_not_empty()
server_interface_ip = server_node.internal_address
client_interface_ip = client_node.internal_address
server_interface_ip = server_comm_ip
client_interface_ip = client_comm_ip

cpu = client_node.tools[Lscpu]
thread_count = cpu.get_thread_count()
Expand All @@ -326,10 +335,10 @@ def perf_tcp_pps(
for port in ports:
server_netperf.run_as_server(port, interface_ip=server_interface_ip)
for port in ports:
# Use server.internal_address as target since netperf client needs
# Use the server's internal IPv4 as target since netperf client needs
# the server's IP (which may differ from the interface it binds to)
client_netperf.run_as_client_async(
server_ip=server_node.internal_address,
server_ip=server_comm_ip,
core_count=thread_count,
port=port,
interface_ip=client_interface_ip,
Expand Down Expand Up @@ -381,6 +390,11 @@ def perf_ntttcp( # noqa: C901
# if it's not filled, assume it's called by case directly.
test_case_name = inspect.stack()[1][3]

# ntttcp and lagscope run over IPv4. On dual-stack (use_ipv6) environments
# server.internal_address is IPv6, so resolve the server's internal IPv4 to
# use as the ntttcp/lagscope target.
server_comm_address = server.nics.get_internal_ipv4_address()

Comment thread
LiliDeng marked this conversation as resolved.
if connections is None:
if udp_mode:
connections = NTTTCP_UDP_CONCURRENCY
Expand Down Expand Up @@ -535,7 +549,7 @@ def perf_ntttcp( # noqa: C901
ip=(
lagscope_server_ip
Comment thread
LiliDeng marked this conversation as resolved.
if lagscope_server_ip is not None
else server.internal_address
else server_comm_address
),
no_debug_log=True,
)
Expand All @@ -545,9 +559,7 @@ def perf_ntttcp( # noqa: C901
server_result = server_ntttcp.run_as_server_async(
server_nic_name,
server_ip=(
server.internal_address
if isinstance(server.os, BSD)
else ""
server_comm_address if isinstance(server.os, BSD) else ""
),
ports_count=num_threads_p,
buffer_size=buffer_size,
Expand All @@ -562,7 +574,7 @@ def perf_ntttcp( # noqa: C901
# Start lagscope client to measure latency during the
# ntttcp test
client_lagscope_process = client_lagscope.run_as_client_async(
server_ip=server.internal_address,
server_ip=server_comm_address,
ping_count=0,
run_time_seconds=(
run_time_seconds
Expand All @@ -582,7 +594,7 @@ def perf_ntttcp( # noqa: C901
# Use daemon mode to run in background, then monitor process
client_ntttcp_result = client_ntttcp.run_as_client(
client_nic_name,
server.internal_address,
server_comm_address,
buffer_size=buffer_size,
threads_count=num_threads_n,
ports_count=num_threads_p,
Expand Down Expand Up @@ -781,11 +793,15 @@ def perf_iperf(
)
test_case_name = inspect.stack()[1][3]
iperf3_messages_list: List[Any] = []
# iperf3 is invoked with ip_version="4"; on a dual-stack (use_ipv6)
# environment internal_address is IPv6, so resolve the server's internal
# IPv4 to use as the client target / bind interface.
server_comm_ip = server.nics.get_internal_ipv4_address()
server_interface_ip = ""
client_interface_ip = ""
if run_with_internal_address:
server_interface_ip = server.internal_address
client_interface_ip = client.internal_address
server_interface_ip = server_comm_ip
client_interface_ip = client.nics.get_internal_ipv4_address()
assert server_interface_ip, "Server Node: internal address is not set"
assert client_interface_ip, "Client Node: internal address is not set"
Comment thread
LiliDeng marked this conversation as resolved.

Expand Down Expand Up @@ -831,7 +847,7 @@ def perf_iperf(
current_client_iperf_instances += 1
client_iperf3_process_list.append(
client_iperf3.run_as_client_async(
server.internal_address,
server_comm_ip,
output_json=True,
report_periodic=1,
report_unit="g",
Expand Down Expand Up @@ -905,7 +921,9 @@ def perf_sockperf(
"sockperf: Warmup stage",
timeout=30,
)
client_output = client.tools[Sockperf].run_client(mode, server.internal_address)
client_output = client.tools[Sockperf].run_client(
mode, server.nics.get_internal_ipv4_address()
)
client.tools[Sockperf].create_latency_performance_message(
client_output, test_case_name, test_result
)
Expand Down
31 changes: 30 additions & 1 deletion lisa/nic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from collections import OrderedDict
from dataclasses import dataclass
from pathlib import PurePosixPath
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast

from assertpy import assert_that
from retry import retry
Expand All @@ -18,6 +18,7 @@

if TYPE_CHECKING:
from lisa import Node
from lisa.node import RemoteNode

Comment thread
LiliDeng marked this conversation as resolved.

class NicInfo:
Expand Down Expand Up @@ -274,6 +275,34 @@ def get_nic_names(self) -> List[str]:
def get_primary_nic(self) -> NicInfo:
return self.get_nic_by_index(0)

def get_internal_ipv4_address(self) -> str:
# Return an IPv4 address usable for intra-VM communication. Prefer the
# node's internal_address, but on a dual-stack (use_ipv6) environment
# that address is IPv6 -- tools that bind/connect over IPv4 only (e.g.
# ntttcp/lagscope) cannot use it. The node still has an internal IPv4
# on its primary (SRIOV) NIC, so fall back to that. IPv4-only
# deployments are unaffected: internal_address is already IPv4 and is
# returned unchanged.
address: str = cast("RemoteNode", self._node).internal_address
try:
is_ipv6 = ipaddress.ip_address(address).version == 6
except ValueError:
is_ipv6 = False
if not is_ipv6:
return address
ipv4_address: str = self.get_primary_nic().ip_addr
if not ipv4_address:
raise LisaException(
f"internal address {address} is IPv6 but the primary NIC "
f"'{self.get_primary_nic().name}' has no IPv4 address to fall "
f"back to."
)
Comment on lines +291 to +297
self._node.log.debug(
f"internal address {address} is IPv6; using the node's internal "
f"IPv4 {ipv4_address} instead."
)
return ipv4_address
Comment thread
LiliDeng marked this conversation as resolved.
Outdated

def get_secondary_nic(self) -> NicInfo:
# get a nic which isn't servicing the SSH connection with lisa.
# will assert if none is present.
Expand Down
Loading