Skip to content

Commit 58b8b03

Browse files
authored
Disable Cisco VOQ WD for dualtor QOS, improve PG test debuggability (sonic-net#20502) (sonic-net#20870)
Double commit sonic-net#20502 Disable VOQ WD during test_tunnel_qos_remap.py Commonize some aspects of the VOQ WD disabling from QOS SAI to avoid major code duplication. Improve performance of test for cisco by reducing unnecessary 8-second per loop wait time to 1 second. (Test passed with 0.5 seconds as well, since this is a SAI bypass operation the updated stat should be near-instant). Improve debuggability of PG tunnel decap test by logging all failures and summarizing a report at the end. Fix up test_voq_watchdog.py test with new commonization. Rename parametrization to avoid shadowing.
1 parent 8651c10 commit 58b8b03

File tree

6 files changed

+109
-87
lines changed

6 files changed

+109
-87
lines changed

tests/qos/qos_helpers.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
from contextlib import contextmanager
12
from netaddr import IPNetwork
23
from .qos_fixtures import lossless_prio_dscp_map, leaf_fanouts # noqa F401
4+
from tests.common.cisco_data import is_cisco_device, copy_set_voq_watchdog_script_cisco_8000, run_dshell_command
35
import re
46
import os
57
import json
@@ -259,3 +261,58 @@ def dutBufferConfig(duthost, dut_asic=None):
259261
except Exception as err:
260262
logger.info(err)
261263
return bufferConfig
264+
265+
266+
def voq_watchdog_enabled(get_src_dst_asic_and_duts):
267+
dst_dut = get_src_dst_asic_and_duts['dst_dut']
268+
if not is_cisco_device(dst_dut):
269+
return False
270+
namespace_option = "-n asic0" if dst_dut.facts.get("modular_chassis") else ""
271+
show_command = "show platform npu global {}".format(namespace_option)
272+
result = run_dshell_command(dst_dut, show_command)
273+
pattern = r"voq_watchdog_enabled +: +True"
274+
match = re.search(pattern, result["stdout"])
275+
return match
276+
277+
278+
def modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, enable):
279+
# Skip if voq watchdog is not enabled.
280+
if not voq_watchdog_enabled(get_src_dst_asic_and_duts):
281+
logger.info("voq_watchdog is not enabled, skipping modify voq watchdog")
282+
return
283+
284+
dst_dut = get_src_dst_asic_and_duts['dst_dut']
285+
dst_asic = get_src_dst_asic_and_duts['dst_asic']
286+
dut_list = [dst_dut]
287+
asic_index_list = [dst_asic.asic_index]
288+
289+
if not get_src_dst_asic_and_duts["single_asic_test"]:
290+
src_dut = get_src_dst_asic_and_duts['src_dut']
291+
src_asic = get_src_dst_asic_and_duts['src_asic']
292+
dut_list.append(src_dut)
293+
asic_index_list.append(src_asic.asic_index)
294+
# fabric card asics
295+
for rp_dut in duthosts.supervisor_nodes:
296+
for asic in rp_dut.asics:
297+
dut_list.append(rp_dut)
298+
asic_index_list.append(asic.asic_index)
299+
300+
# Modify voq watchdog.
301+
for (dut, asic_index) in zip(dut_list, asic_index_list):
302+
copy_set_voq_watchdog_script_cisco_8000(
303+
dut=dut,
304+
asic=asic_index,
305+
enable=enable)
306+
cmd_opt = "-n asic{}".format(asic_index)
307+
if not dst_dut.sonichost.is_multi_asic:
308+
cmd_opt = ""
309+
dut.shell("sudo show platform npu script {} -s set_voq_watchdog.py".format(cmd_opt))
310+
311+
312+
@contextmanager
313+
def disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts):
314+
# Disable voq watchdog.
315+
modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, enable=False)
316+
yield
317+
# Enable voq watchdog.
318+
modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, enable=True)

tests/qos/qos_sai_base.py

Lines changed: 6 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@
1111
import copy
1212
import time
1313
import collections
14-
from contextlib import contextmanager
1514

1615
from tests.common.fixtures.ptfhost_utils import ptf_portmap_file # noqa F401
1716
from tests.common.helpers.assertions import pytest_assert, pytest_require
1817
from tests.common.helpers.multi_thread_utils import SafeThreadPoolExecutor
1918
from tests.common.mellanox_data import is_mellanox_device as isMellanoxDevice
20-
from tests.common.cisco_data import is_cisco_device, copy_set_voq_watchdog_script_cisco_8000, \
21-
copy_dshell_script_cisco_8000, run_dshell_command
19+
from tests.common.cisco_data import is_cisco_device, copy_dshell_script_cisco_8000, run_dshell_command
2220
from tests.common.dualtor.dual_tor_common import active_standby_ports # noqa F401
2321
from tests.common.dualtor.dual_tor_utils import upper_tor_host, lower_tor_host, dualtor_ports, is_tunnel_qos_remap_enabled # noqa F401
2422
from tests.common.dualtor.mux_simulator_control \
@@ -35,7 +33,7 @@
3533
from tests.common.snappi_tests.qos_fixtures import get_pfcwd_config, reapply_pfcwd
3634
from tests.common.snappi_tests.common_helpers import \
3735
stop_pfcwd, disable_packet_aging, enable_packet_aging
38-
from .qos_helpers import dutBufferConfig
36+
from .qos_helpers import dutBufferConfig, disable_voq_watchdog
3937

4038
logger = logging.getLogger(__name__)
4139

@@ -2783,66 +2781,14 @@ def set_cir_change(self, get_src_dst_asic_and_duts, dutConfig):
27832781
yield
27842782
return
27852783

2786-
def voq_watchdog_enabled(self, get_src_dst_asic_and_duts):
2787-
dst_dut = get_src_dst_asic_and_duts['dst_dut']
2788-
if not is_cisco_device(dst_dut):
2789-
return False
2790-
namespace_option = "-n asic0" if dst_dut.facts.get("modular_chassis") else ""
2791-
show_command = "show platform npu global {}".format(namespace_option)
2792-
result = run_dshell_command(dst_dut, show_command)
2793-
pattern = r"voq_watchdog_enabled +: +True"
2794-
match = re.search(pattern, result["stdout"])
2795-
return match
2796-
2797-
def modify_voq_watchdog(self, duthosts, get_src_dst_asic_and_duts, dutConfig, enable):
2798-
# Skip if voq watchdog is not enabled.
2799-
if not self.voq_watchdog_enabled(get_src_dst_asic_and_duts):
2800-
logger.info("voq_watchdog is not enabled, skipping modify voq watchdog")
2801-
return
2802-
2803-
dst_dut = get_src_dst_asic_and_duts['dst_dut']
2804-
dst_asic = get_src_dst_asic_and_duts['dst_asic']
2805-
dut_list = [dst_dut]
2806-
asic_index_list = [dst_asic.asic_index]
2807-
2808-
if not get_src_dst_asic_and_duts["single_asic_test"]:
2809-
src_dut = get_src_dst_asic_and_duts['src_dut']
2810-
src_asic = get_src_dst_asic_and_duts['src_asic']
2811-
dut_list.append(src_dut)
2812-
asic_index_list.append(src_asic.asic_index)
2813-
# fabric card asics
2814-
for rp_dut in duthosts.supervisor_nodes:
2815-
for asic in rp_dut.asics:
2816-
dut_list.append(rp_dut)
2817-
asic_index_list.append(asic.asic_index)
2818-
2819-
# Modify voq watchdog.
2820-
for (dut, asic_index) in zip(dut_list, asic_index_list):
2821-
copy_set_voq_watchdog_script_cisco_8000(
2822-
dut=dut,
2823-
asic=asic_index,
2824-
enable=enable)
2825-
cmd_opt = "-n asic{}".format(asic_index)
2826-
if not dst_dut.sonichost.is_multi_asic:
2827-
cmd_opt = ""
2828-
dut.shell("sudo show platform npu script {} -s set_voq_watchdog.py".format(cmd_opt))
2829-
2830-
@contextmanager
2831-
def disable_voq_watchdog(self, duthosts, get_src_dst_asic_and_duts, dutConfig):
2832-
# Disable voq watchdog.
2833-
self.modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig, enable=False)
2834-
yield
2835-
# Enable voq watchdog.
2836-
self.modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig, enable=True)
2837-
28382784
@pytest.fixture(scope='function')
2839-
def disable_voq_watchdog_function_scope(self, duthosts, get_src_dst_asic_and_duts, dutConfig):
2840-
with self.disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig) as result:
2785+
def disable_voq_watchdog_function_scope(self, duthosts, get_src_dst_asic_and_duts):
2786+
with disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts) as result:
28412787
yield result
28422788

28432789
@pytest.fixture(scope='class')
2844-
def disable_voq_watchdog_class_scope(self, duthosts, get_src_dst_asic_and_duts, dutConfig):
2845-
with self.disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig) as result:
2790+
def disable_voq_watchdog_class_scope(self, duthosts, get_src_dst_asic_and_duts):
2791+
with disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts) as result:
28462792
yield result
28472793

28482794
def oq_watchdog_enabled(self, get_src_dst_asic_and_duts):

tests/qos/test_tunnel_qos_remap.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
dut_config, qos_config, tunnel_qos_maps, run_ptf_test, toggle_mux_to_host,\
3030
setup_module, update_docker_services, swap_syncd, counter_poll_config # noqa F401
3131
from .tunnel_qos_remap_base import leaf_fanout_peer_info, start_pfc_storm, \
32-
stop_pfc_storm, get_queue_counter, get_queue_watermark, disable_packet_aging # noqa F401
32+
stop_pfc_storm, get_queue_counter, get_queue_watermark, disable_packet_aging, \
33+
disable_voq_watchdog_dualtor # noqa F401
3334
from ptf import testutils
3435
from ptf.testutils import simple_tcp_packet
3536
from tests.common.fixtures.conn_graph_facts import conn_graph_facts, fanout_graph_facts # noqa F401

tests/qos/test_voq_watchdog.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from tests.common.fixtures.ptfhost_utils import copy_ptftests_directory # noqa F401
2727
from tests.common.fixtures.ptfhost_utils import copy_saitests_directory # noqa F401
2828
from tests.common.fixtures.ptfhost_utils import change_mac_addresses # noqa F401
29+
from .qos_helpers import voq_watchdog_enabled, modify_voq_watchdog
2930
from .qos_sai_base import QosSaiBase
3031

3132
logger = logging.getLogger(__name__)
@@ -55,13 +56,13 @@ class TestVoqWatchdog(QosSaiBase):
5556
"""
5657
@pytest.fixture(scope="class", autouse=True)
5758
def check_skip_voq_watchdog_test(self, get_src_dst_asic_and_duts):
58-
if not self.voq_watchdog_enabled(get_src_dst_asic_and_duts):
59+
if not voq_watchdog_enabled(get_src_dst_asic_and_duts):
5960
pytest.skip("Voq watchdog test is skipped since voq watchdog is not enabled.")
6061

61-
@pytest.mark.parametrize("voq_watchdog_enabled", [True, False])
62+
@pytest.mark.parametrize("enable_voq_watchdog", [True, False])
6263
def testVoqWatchdog(
6364
self, ptfhost, dutTestParams, dutConfig, dutQosConfig,
64-
duthosts, get_src_dst_asic_and_duts, voq_watchdog_enabled
65+
duthosts, get_src_dst_asic_and_duts, enable_voq_watchdog
6566
):
6667
"""
6768
Test VOQ watchdog
@@ -71,16 +72,16 @@ def testVoqWatchdog(
7172
dutConfig (Fixture, dict): Map of DUT config containing dut interfaces, test port IDs, test port IPs,
7273
and test ports
7374
dutQosConfig (Fixture, dict): Map containing DUT host QoS configuration
74-
voq_watchdog_enabled (bool): if VOQ watchdog is enabled or not
75+
enable_voq_watchdog (bool): Whether to enable or disable VOQ watchdog during the test
7576
Returns:
7677
None
7778
Raises:
7879
RunAnsibleModuleFail if ptf test fails
7980
"""
8081

8182
try:
82-
if not voq_watchdog_enabled:
83-
self.modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig, enable=False)
83+
if not enable_voq_watchdog:
84+
modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, enable=False)
8485

8586
testParams = dict()
8687
testParams.update(dutTestParams["basicParams"])
@@ -94,7 +95,7 @@ def testVoqWatchdog(
9495
"src_port_vlan": dutConfig["testPorts"]["src_port_vlan"],
9596
"packet_size": 1350,
9697
"pkts_num": PKTS_NUM,
97-
"voq_watchdog_enabled": voq_watchdog_enabled,
98+
"voq_watchdog_enabled": enable_voq_watchdog,
9899
"dutInterfaces": dutConfig["dutInterfaces"],
99100
"testPorts": dutConfig["testPorts"],
100101
})
@@ -108,5 +109,5 @@ def testVoqWatchdog(
108109
testParams=testParams)
109110

110111
finally:
111-
if not voq_watchdog_enabled:
112-
self.modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, dutConfig, enable=True)
112+
if not enable_voq_watchdog:
113+
modify_voq_watchdog(duthosts, get_src_dst_asic_and_duts, enable=True)

tests/qos/tunnel_qos_remap_base.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from tests.common.fixtures.duthost_utils import dut_qos_maps_module # noqa F401
1616
from tests.common.fixtures.ptfhost_utils import ptf_portmap_file_module # noqa F401
1717
from tests.common.utilities import get_iface_ip
18-
from .qos_helpers import dutBufferConfig
18+
from .qos_helpers import dutBufferConfig, disable_voq_watchdog
1919
from .files.cisco.qos_param_generator import QosParamCisco
2020

2121
logger = logging.getLogger(__name__)
@@ -530,9 +530,7 @@ def run_ptf_test(ptfhost, test_case='', test_params={}):
530530
A helper function to run test script on ptf host
531531
"""
532532
logger.info("Start running {} on ptf host".format(test_case))
533-
pytest_assert(ptfhost.shell(
534-
argv=[
535-
"/root/env-python3/bin/ptf",
533+
argv = ["/root/env-python3/bin/ptf",
536534
"--test-dir",
537535
"saitests/py3",
538536
test_case,
@@ -552,7 +550,16 @@ def run_ptf_test(ptfhost, test_case='', test_params={}):
552550
"--log-file",
553551
"/tmp/{0}.log".format(test_case),
554552
"--test-case-timeout",
555-
"1200"
556-
],
557-
chdir="/root",
558-
)["rc"] == 0, "Failed when running test '{0}'".format(test_case))
553+
"1200"]
554+
result = ptfhost.shell(argv=argv, chdir="/root")
555+
pytest_assert(result["rc"] == 0, "Failed when running test '{0}'".format(test_case))
556+
557+
558+
@pytest.fixture(scope='module', autouse=True)
559+
def disable_voq_watchdog_dualtor(duthosts, rand_selected_dut):
560+
get_src_dst_asic_and_duts = {}
561+
get_src_dst_asic_and_duts["single_asic_test"] = True
562+
get_src_dst_asic_and_duts["dst_dut"] = rand_selected_dut
563+
get_src_dst_asic_and_duts["dst_asic"] = rand_selected_dut.asics[0]
564+
with disable_voq_watchdog(duthosts, get_src_dst_asic_and_duts) as result:
565+
yield result

tests/saitests/py3/sai_qos_tests.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1587,6 +1587,13 @@ def runTest(self):
15871587
# Disable tx on EGRESS port so that headroom buffer cannot be free
15881588
self.sai_thrift_port_tx_disable(self.dst_client, asic_type, [dst_port_id])
15891589

1590+
if 'cisco-8000' in asic_type:
1591+
PKT_NUM = 50
1592+
cntr_wait_time = 1
1593+
else:
1594+
PKT_NUM = 100
1595+
cntr_wait_time = 8
1596+
15901597
# There are packet leak even port tx is disabled (18 packets leak on TD3 found)
15911598
# Hence we send some packet to fill the leak before testing
15921599
if asic_type != 'mellanox':
@@ -1618,11 +1625,9 @@ def runTest(self):
16181625
else:
16191626
send_packet(self, src_port_id, pkt, 20)
16201627
assert not leakout_failed, "Failed filling leakout"
1621-
time.sleep(10)
1622-
if 'cisco-8000' in asic_type:
1623-
PKT_NUM = 50
1624-
else:
1625-
PKT_NUM = 100
1628+
time.sleep(cntr_wait_time)
1629+
1630+
fails = []
16261631
for inner_dscp, pg in dscp_to_pg_map.items():
16271632
logging.info("Iteration: inner_dscp:{}, pg: {}".format(inner_dscp, pg))
16281633
# Build and send packet to active tor.
@@ -1655,7 +1660,7 @@ def runTest(self):
16551660

16561661
send_packet(self, src_port_id, pkt, PKT_NUM)
16571662
# validate pg counters increment by the correct pkt num
1658-
time.sleep(8)
1663+
time.sleep(cntr_wait_time)
16591664

16601665
pg_shared_wm_res = sai_thrift_read_pg_shared_watermark(self.src_client, asic_type,
16611666
port_list['src'][src_port_id])
@@ -1664,9 +1669,14 @@ def runTest(self):
16641669
logging.info(f"pg_wm_inc: {pg_wm_inc}")
16651670
lower_bounds = (PKT_NUM - ERROR_TOLERANCE[pg]) * cell_size * cell_occupancy
16661671
upper_bounds = (PKT_NUM + ERROR_TOLERANCE[pg]) * cell_size * cell_occupancy
1667-
print("DSCP {}, PG {}, expectation: {} <= {} <= {}".format(
1668-
inner_dscp, pg, lower_bounds, pg_wm_inc, upper_bounds), file=sys.stderr)
1669-
assert lower_bounds <= pg_wm_inc <= upper_bounds
1672+
msg = "DSCP {}, PG {}, expectation: {} <= {} <= {}, base wmk {}, new wmk {}".format(
1673+
inner_dscp, pg, lower_bounds, pg_wm_inc, upper_bounds,
1674+
pg_shared_wm_res_base[pg], pg_shared_wm_res[pg])
1675+
print(msg, file=sys.stderr)
1676+
if not (lower_bounds <= pg_wm_inc <= upper_bounds):
1677+
print("FAILED CHECK", file=sys.stderr)
1678+
fails.append(msg)
1679+
assert len(fails) == 0, "Some PG watermark checks failed ({}): \n{}".format(len(fails), "\n".join(fails))
16701680

16711681
finally:
16721682
# Enable tx on dest port

0 commit comments

Comments
 (0)