Skip to content

Commit e15daca

Browse files
sreejithsreekumaranmssonicbld
authored andcommitted
Full Mesh Traffic Sanity verification (sonic-net#11968)
* Added testcase to run traffic in full mesh from all src to all dst port pair. After all src inject traffic to a given dst, queue counters are verified for any drop * Removed the unwanted Try block Fixed a bug in longest prefix match in conditional_mark Added conditional mark to skip if not ptf64 topo * Made adding static routes a pytest fixture * Added fixture to configure ip on ptf interfaces while using PTF64 topo * Changed to skip for all platforms except Cisco * flake8 issues reported from changes in PR 9896
1 parent 7468fce commit e15daca

5 files changed

Lines changed: 371 additions & 9 deletions

File tree

tests/common/plugins/conditional_mark/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ def find_longest_matches(nodeid, conditions):
419419
for condition in conditions:
420420
# condition is a dict which has only one item, so we use condition.keys()[0] to get its key.
421421
if nodeid.startswith(list(condition.keys())[0]):
422-
length = len(condition)
422+
length = len(list(condition.keys())[0])
423423
if length > max_length:
424424
max_length = length
425425
longest_matches = []

tests/common/plugins/conditional_mark/tests_mark_conditions.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,12 @@ qos/test_qos_sai.py::TestQosSai::testQosSaiDwrrWeightChange:
12841284
conditions:
12851285
- "asic_type in ['mellanox']"
12861286

1287+
qos/test_qos_sai.py::TestQosSai::testQosSaiFullMeshTrafficSanity:
1288+
skip:
1289+
reason: "Unsupported platform or testbed type."
1290+
conditions:
1291+
- "asic_type not in ['cisco-8000'] or topo_name not in ['ptf64']"
1292+
12871293
qos/test_qos_sai.py::TestQosSai::testQosSaiHeadroomPoolSize:
12881294
skip:
12891295
reason: "Headroom pool size not supported."

tests/qos/qos_sai_base.py

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,13 +132,17 @@ def runPtfTest(self, ptfhost, testCase='', testParams={}, relax=False, pdb=False
132132
"""
133133
custom_options = " --disable-ipv6 --disable-vxlan --disable-geneve" \
134134
" --disable-erspan --disable-mpls --disable-nvgre"
135+
# Append a suffix to the logfile name if log_suffix is present in testParams
136+
log_suffix = testParams.get("log_suffix", "")
137+
logfile_suffix = "_{0}".format(log_suffix) if log_suffix else ""
138+
135139
ptf_runner(
136140
ptfhost,
137141
"saitests",
138142
testCase,
139143
platform_dir="ptftests",
140144
params=testParams,
141-
log_file="/tmp/{0}.log".format(testCase),
145+
log_file="/tmp/{0}{1}.log".format(testCase, logfile_suffix), # Include suffix in the logfile name,
142146
qlen=10000,
143147
is_python3=True,
144148
relax=relax,
@@ -812,9 +816,32 @@ def __buildPortSpeeds(self, config_facts):
812816
port_speeds[attr['speed']].append(etp)
813817
return port_speeds
814818

819+
@pytest.fixture(scope='class', autouse=False)
820+
def configure_ip_on_ptf_intfs(self, ptfhost, get_src_dst_asic_and_duts, tbinfo):
821+
src_dut = get_src_dst_asic_and_duts['src_dut']
822+
src_mgFacts = src_dut.get_extended_minigraph_facts(tbinfo)
823+
topo = tbinfo["topo"]["name"]
824+
825+
# if PTF64 and is Cisco, set ip IP address on eth interfaces of the ptf"
826+
if topo == 'ptf64' and is_cisco_device(src_dut):
827+
minigraph_ip_interfaces = src_mgFacts['minigraph_interfaces']
828+
for entry in minigraph_ip_interfaces:
829+
ptfhost.shell("ip addr add {}/31 dev eth{}".format(
830+
entry['peer_addr'], src_mgFacts["minigraph_ptf_indices"][entry['attachto']])
831+
)
832+
yield
833+
for entry in minigraph_ip_interfaces:
834+
ptfhost.shell("ip addr del {}/31 dev eth{}".format(
835+
entry['peer_addr'], src_mgFacts["minigraph_ptf_indices"][entry['attachto']])
836+
)
837+
return
838+
else:
839+
yield
840+
return
841+
815842
@pytest.fixture(scope='class', autouse=True)
816843
def dutConfig(
817-
self, request, duthosts, get_src_dst_asic_and_duts,
844+
self, request, duthosts, configure_ip_on_ptf_intfs, get_src_dst_asic_and_duts,
818845
lower_tor_host, tbinfo, dualtor_ports_for_duts, dut_qos_maps): # noqa F811
819846
"""
820847
Build DUT host config pertaining to QoS SAI tests
@@ -934,7 +961,7 @@ def dutConfig(
934961
testPortIds[src_dut_index][src_asic_index] = sorted(
935962
list(testPortIps[src_dut_index][src_asic_index].keys()))
936963

937-
elif topo in self.SUPPORTED_T1_TOPOS:
964+
elif topo in self.SUPPORTED_T1_TOPOS or (topo in self.SUPPORTED_PTF_TOPOS and is_cisco_device(src_dut)):
938965
# T1 is supported only for 'single_asic' or 'single_dut_multi_asic'.
939966
# So use src_dut as the dut
940967
use_separated_upkink_dscp_tc_map = separated_dscp_to_tc_map_on_uplink(dut_qos_maps)
@@ -2380,6 +2407,67 @@ def populate_arp_entries(
23802407
ptfhost, testCase=saiQosTest, testParams=testParams
23812408
)
23822409

2410+
@pytest.fixture(scope="function", autouse=False)
2411+
def set_static_route_ptf64(self, dutConfig, get_src_dst_asic_and_duts, dutTestParams, enum_frontend_asic_index):
2412+
def generate_ip_address(base_ip, new_first_octet):
2413+
octets = base_ip.split('.')
2414+
if len(octets) != 4:
2415+
raise ValueError("Invalid IP address format")
2416+
octets[0] = str(new_first_octet)
2417+
octets[2] = octets[3]
2418+
octets[3] = '1'
2419+
return '.'.join(octets)
2420+
2421+
def combine_ips(src_ips, dst_ips, new_first_octet):
2422+
combined_ips_map = {}
2423+
2424+
for key, src_info in src_ips.items():
2425+
src_ip = src_info['peer_addr']
2426+
new_ip = generate_ip_address(src_ip, new_first_octet)
2427+
combined_ips_map[key] = {'original_ip': src_ip, 'generated_ip': new_ip}
2428+
2429+
for key, dst_info in dst_ips.items():
2430+
dst_ip = dst_info['peer_addr']
2431+
new_ip = generate_ip_address(dst_ip, new_first_octet)
2432+
combined_ips_map[key] = {'original_ip': dst_ip, 'generated_ip': new_ip}
2433+
2434+
return combined_ips_map
2435+
2436+
def configRoutePrefix(add_route):
2437+
action = "add" if add_route else "del"
2438+
for port, entry in combined_ips_map.items():
2439+
if enum_frontend_asic_index is None:
2440+
src_asic.shell("config route {} prefix {}.0/24 nexthop {}".format(
2441+
action, '.'.join(entry['generated_ip'].split('.')[:3]), entry['original_ip']))
2442+
else:
2443+
src_asic.shell("ip netns exec asic{} config route {} prefix {}.0/24 nexthop {}".format(
2444+
enum_frontend_asic_index,
2445+
action, '.'.join(entry['generated_ip'].split('.')[:3]),
2446+
entry['original_ip'])
2447+
)
2448+
2449+
if dutTestParams["basicParams"]["sonic_asic_type"] != "cisco-8000":
2450+
pytest.skip("Traffic sanity test is not supported")
2451+
2452+
if dutTestParams["topo"] != "ptf64":
2453+
pytest.skip("Test not supported in {} topology. Use ptf64 topo".format(dutTestParams["topo"]))
2454+
2455+
src_dut_index = get_src_dst_asic_and_duts['src_dut_index']
2456+
dst_dut_index = get_src_dst_asic_and_duts['dst_dut_index']
2457+
src_asic_index = get_src_dst_asic_and_duts['src_asic_index']
2458+
dst_asic_index = get_src_dst_asic_and_duts['dst_asic_index']
2459+
src_asic = get_src_dst_asic_and_duts['src_asic']
2460+
2461+
src_testPortIps = dutConfig["testPortIps"][src_dut_index][src_asic_index]
2462+
dst_testPortIps = dutConfig["testPortIps"][dst_dut_index][dst_asic_index]
2463+
2464+
new_first_octet = 100
2465+
combined_ips_map = combine_ips(src_testPortIps, dst_testPortIps, new_first_octet)
2466+
2467+
configRoutePrefix(True)
2468+
yield combined_ips_map
2469+
configRoutePrefix(False)
2470+
23832471
@pytest.fixture(scope="function", autouse=False)
23842472
def skip_longlink(self, dutQosConfig):
23852473
portSpeedCableLength = dutQosConfig["portSpeedCableLength"]

tests/qos/test_qos_sai.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,3 +2262,89 @@ def testQosSaiLossyQueueVoqMultiSrc(
22622262
ptfhost, testCase="sai_qos_tests.LossyQueueVoqMultiSrcTest",
22632263
testParams=testParams
22642264
)
2265+
2266+
def testQosSaiFullMeshTrafficSanity(
2267+
self, ptfhost, dutTestParams, dutConfig, dutQosConfig,
2268+
get_src_dst_asic_and_duts, dut_qos_maps, # noqa F811
2269+
set_static_route_ptf64
2270+
):
2271+
"""
2272+
Test QoS SAI traffic sanity
2273+
Args:
2274+
ptfhost (AnsibleHost): Packet Test Framework (PTF)
2275+
dutTestParams (Fixture, dict): DUT host test params
2276+
dutConfig (Fixture, dict): Map of DUT config containing dut interfaces, test port IDs, test port IPs,
2277+
and test ports
2278+
dutQosConfig (Fixture, dict): Map containing DUT host QoS configuration
2279+
Returns:
2280+
None
2281+
Raises:
2282+
RunAnsibleModuleFail if ptf test fails
2283+
"""
2284+
# Execution with a specific set of dst port
2285+
def run_test_for_dst_port(start, end):
2286+
test_params = dict()
2287+
test_params.update(dutTestParams["basicParams"])
2288+
test_params.update({
2289+
"testbed_type": dutTestParams["topo"],
2290+
"all_src_port_id_to_ip": all_src_port_id_to_ip,
2291+
"all_src_port_id_to_name": all_src_port_id_to_name,
2292+
"all_dst_port_id_to_ip": {port_id: all_dst_port_id_to_ip[port_id] for port_id in range(start, end)},
2293+
"all_dst_port_id_to_name": {port_id: all_dst_port_id_to_name[port_id] for port_id in range(start, end)},
2294+
"dscp_to_q_map": dscp_to_q_map,
2295+
# Add a log_suffix to have separate log and pcap file name
2296+
"log_suffix": "_".join([str(port_id) for port_id in range(start, end)]),
2297+
"hwsku": dutTestParams['hwsku']
2298+
})
2299+
2300+
self.runPtfTest(ptfhost, testCase="sai_qos_tests.FullMeshTrafficSanity", testParams=test_params)
2301+
2302+
src_dut_index = get_src_dst_asic_and_duts['src_dut_index']
2303+
dst_dut_index = get_src_dst_asic_and_duts['dst_dut_index']
2304+
src_asic_index = get_src_dst_asic_and_duts['src_asic_index']
2305+
dst_asic_index = get_src_dst_asic_and_duts['dst_asic_index']
2306+
2307+
src_testPortIps = dutConfig["testPortIps"][src_dut_index][src_asic_index]
2308+
dst_testPortIps = dutConfig["testPortIps"][dst_dut_index][dst_asic_index]
2309+
2310+
# Fetch all port IDs and IPs
2311+
all_src_port_id_to_ip = {port_id: src_testPortIps[port_id]['peer_addr'] for port_id in src_testPortIps.keys()}
2312+
2313+
all_src_port_id_to_name = {
2314+
port_id: dutConfig["dutInterfaces"][port_id]
2315+
for port_id in all_src_port_id_to_ip.keys()
2316+
}
2317+
2318+
all_dst_port_id_to_ip = {
2319+
port_id: set_static_route_ptf64[port_id]['generated_ip']
2320+
for port_id in dst_testPortIps.keys()
2321+
}
2322+
2323+
all_dst_port_id_to_name = {
2324+
port_id: dutConfig["dutInterfaces"][port_id]
2325+
for port_id in all_dst_port_id_to_ip.keys()
2326+
}
2327+
2328+
try:
2329+
tc_to_q_map = dut_qos_maps['tc_to_queue_map']['AZURE']
2330+
tc_to_dscp_map = {v: k for k, v in dut_qos_maps['dscp_to_tc_map']['AZURE'].items()}
2331+
except KeyError:
2332+
pytest.skip(
2333+
"Need both TC_TO_PRIORITY_GROUP_MAP and DSCP_TO_TC_MAP"
2334+
"and key AZURE to run this test.")
2335+
2336+
dscp_to_q_map = {tc_to_dscp_map[tc]: tc_to_q_map[tc] for tc in tc_to_dscp_map if tc != 7}
2337+
2338+
# Define the number of splits
2339+
# for the dst port list
2340+
num_splits = 4
2341+
2342+
# Get all keys and sort them
2343+
all_keys = sorted(all_dst_port_id_to_ip.keys())
2344+
2345+
# Calculate the split points
2346+
split_points = [all_keys[i * len(all_keys) // num_splits] for i in range(1, num_splits)]
2347+
2348+
# Execute with one set of dst port at a time, avoids ptf run getting timed out
2349+
for start, end in zip([0] + split_points, split_points + [len(all_keys)]):
2350+
run_test_for_dst_port(start, end)

0 commit comments

Comments
 (0)