Skip to content
Open
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
53 changes: 35 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,21 @@ 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(
server_interface_ip = server_comm_ip
client_interface_ip = client_node.nics.get_internal_ipv4_address()
assert_that(server_interface_ip).described_as(
"Server Node: internal address is not set"
).is_not_empty()
assert_that(client_node.internal_address).described_as(
assert_that(client_interface_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

cpu = client_node.tools[Lscpu]
thread_count = cpu.get_thread_count()
Expand All @@ -326,10 +334,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 +389,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 +548,7 @@ def perf_ntttcp( # noqa: C901
ip=(
lagscope_server_ip
if lagscope_server_ip is not None
else server.internal_address
else server_comm_address
),
no_debug_log=True,
)
Expand All @@ -545,9 +558,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 +573,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 +593,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 +792,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"

Expand Down Expand Up @@ -831,7 +846,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 +920,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
27 changes: 27 additions & 0 deletions lisa/nic.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,33 @@ 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 when it is a valid IPv4. On a dual-stack
# (use_ipv6) environment it is IPv6, and some node types (e.g.
# LocalNode) don't define internal_address at all -- in both cases fall
# back to the primary NIC's internal IPv4, since tools that bind/connect
# over IPv4 only (ntttcp/lagscope/netperf/sockperf) need an IPv4 target.
address: str = getattr(self._node, "internal_address", "") or ""
try:
is_ipv4 = ipaddress.ip_address(address).version == 4
except ValueError:
is_ipv4 = False
if is_ipv4:
return address
ipv4_address: str = self.get_primary_nic().ip_addr
if not ipv4_address:
raise LisaException(
f"internal address '{address}' is not a usable IPv4 and the "
f"primary NIC '{self.get_primary_nic().name}' has no IPv4 "
f"address to fall back to."
)
Comment on lines +291 to +297
self._node.log.debug(
f"internal address '{address}' is not IPv4; using the node's "
f"internal IPv4 {ipv4_address} instead."
)
return ipv4_address

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