From d62b58eee9f283ad1bf16390d487252d0b18c93e Mon Sep 17 00:00:00 2001 From: Lili Deng Date: Thu, 16 Jul 2026 15:41:26 +0800 Subject: [PATCH] perf(ntttcp): run ntttcp/lagscope over internal IPv4 on dual-stack ntttcp and lagscope bind/connect over IPv4 only. On use_ipv6 (dual-stack) environments server.internal_address is the IPv6 private address, so lagscope fails with 'no port opened for lagscope server' and every ntttcp perf attempt fails. Resolve the server's internal IPv4 from its primary NIC and use it as the ntttcp/lagscope target, so perf runs succeed even when the VMs are deployed with IPv6. IPv4-only deployments are unaffected (internal_address is already IPv4). --- .../testsuites/performance/common.py | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/lisa/microsoft/testsuites/performance/common.py b/lisa/microsoft/testsuites/performance/common.py index 1680ee475d..5edb6c03c8 100644 --- a/lisa/microsoft/testsuites/performance/common.py +++ b/lisa/microsoft/testsuites/performance/common.py @@ -1,6 +1,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. import inspect +import ipaddress import pathlib import time from functools import partial @@ -344,6 +345,28 @@ def perf_tcp_pps( notifier.notify(pps_message) +def _get_ntttcp_ipv4_address(node: RemoteNode) -> str: + # ntttcp and lagscope bind/connect over IPv4 only. When the environment is + # deployed dual-stack (use_ipv6), node.internal_address is the IPv6 private + # address, which makes lagscope fail to open its listening port. The node + # still has an internal IPv4 on the same (SRIOV) NIC, so run the perf tools + # over that IPv4 address instead. IPv4-only deployments are unaffected: the + # address is already IPv4 and is returned unchanged. + address = 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 = node.nics.get_primary_nic().ip_addr + node.log.debug( + f"internal address {address} is IPv6; ntttcp/lagscope will use the " + f"node's internal IPv4 {ipv4_address} instead." + ) + return ipv4_address + + def perf_ntttcp( # noqa: C901 test_result: TestResult, server: Optional[RemoteNode] = None, @@ -381,6 +404,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 = _get_ntttcp_ipv4_address(server) + if connections is None: if udp_mode: connections = NTTTCP_UDP_CONCURRENCY @@ -535,7 +563,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, ) @@ -545,9 +573,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, @@ -562,7 +588,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 @@ -582,7 +608,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,