Skip to content

Commit 42de329

Browse files
weiguo-nvidiagshemesh2
authored andcommitted
Verify if the queue is blocked successfully in trimming case (sonic-net#21077)
In packet trimming test, it execute cmd sonic-db-cli CONFIG_DB hset 'QUEUE|Ethernet120|1' scheduler SCHEDULER_BLOCK_DATA_PLANE to block the queue of egress port to simulate buffer full and trigger trimmed packets. This cmd needs to be processed by swss. In some trimming case, it executes ports shutdown/startup, config reload or reboot, which lead to BGP flap and lots of routes update message need to be processed by swss. SWSS process all the messages one by one. If swss is busy to process route update messages, the block queue cmd may be processed few time later, which lead to the queue is not blocked immediately and case fail Now add a check to make sure queue is blocked successfully before sending packets. Signed-off-by: Guy Shemesh <gshemesh@nvidia.com>
1 parent 14473d0 commit 42de329

3 files changed

Lines changed: 161 additions & 8 deletions

File tree

tests/packet_trimming/conftest.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,6 @@ def setup_trimming(duthost, test_params):
207207
status = duthost.get_counter_poll_status()
208208
logger.info(f"Counter poll status: {status}")
209209

210-
with allure.step("Clear ports and queue counters"):
211-
duthost.command("sonic-clear queuecounters")
212-
duthost.command("sonic-clear counters")
213-
214210
yield
215211

216212
with allure.step("Disable trimming in buffer profile"):
@@ -303,3 +299,15 @@ def pytest_addoption(parser):
303299
required=False,
304300
help="reboot type such as reload, cold"
305301
)
302+
303+
304+
@pytest.fixture(scope="function", autouse=True)
305+
def clear_counters(duthost):
306+
"""
307+
Clear all counters on the DUT.
308+
"""
309+
duthost.shell("sonic-clear counters")
310+
duthost.shell("sonic-clear queuecounters")
311+
duthost.shell("sonic-clear switchcounters")
312+
313+
logger.info("Successfully cleared all counters on the DUT")

tests/packet_trimming/constants.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
NORMAL_PACKET_DSCP = 4 # DSCP value for normal packet
7575

7676
BLOCK_DATA_PLANE_SCHEDULER_NAME = "SCHEDULER_BLOCK_DATA_PLANE"
77+
SCHEDULER_TYPE = "DWRR"
78+
SCHEDULER_WEIGHT = 15
79+
SCHEDULER_PIR = 1
80+
7781
DATA_PLANE_QUEUE_LIST = ["0", "1", "2", "3", "4", "5", "6"]
7882
DEFAULT_QUEUE_SCHEDULER_CONFIG = {
7983
"0": "scheduler.0",
@@ -165,7 +169,7 @@
165169
]
166170

167171
# Drop counter
168-
SWITCH_INTERVAL = 10000
172+
SWITCH_INTERVAL = 1000
169173
PORT_INTERVAL = 100
170174
QUEUE_INTERVAL = 100
171175

tests/packet_trimming/packet_trimming_helper.py

Lines changed: 144 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
ACL_RULE_PRIORITY, ACL_TABLE_TYPE_NAME, ACL_RULE_NAME, SRV6_MY_SID_LIST,
2424
SRV6_INNER_SRC_IP, SRV6_INNER_DST_IP, DEFAULT_QUEUE_SCHEDULER_CONFIG,
2525
SRV6_UNIFORM_MODE, SRV6_OUTER_SRC_IPV6, SRV6_INNER_SRC_IPV6, ECN,
26-
SRV6_INNER_DST_IPV6, SRV6_UN, ASYM_TC, ASYM_PORT_1_DSCP, ASYM_PORT_2_DSCP)
26+
SRV6_INNER_DST_IPV6, SRV6_UN, ASYM_TC, ASYM_PORT_1_DSCP, ASYM_PORT_2_DSCP,
27+
SCHEDULER_TYPE, SCHEDULER_WEIGHT, SCHEDULER_PIR)
2728

2829
logger = logging.getLogger(__name__)
2930

@@ -276,6 +277,101 @@ def generate_packet(duthost, packet_type, dst_addr, send_pkt_size, send_pkt_dscp
276277
return pkt, masked_exp_packet
277278

278279

280+
def get_scheduler_oid_by_attributes(duthost, **kwargs):
281+
"""
282+
Find scheduler OID in ASIC_DB by matching its attributes.
283+
284+
Args:
285+
duthost: DUT host object
286+
**kwargs: Scheduler attributes to match
287+
- type: Scheduler type (e.g., "DWRR", "STRICT")
288+
- weight: Scheduling weight (e.g., 15)
289+
- pir: Peak Information Rate (e.g., 1)
290+
291+
Returns:
292+
str: OID of the matched scheduler, or None if not found
293+
"""
294+
# Mapping from CONFIG_DB parameters to ASIC_DB SAI attributes
295+
param_to_sai_attr = {
296+
'type': 'SAI_SCHEDULER_ATTR_SCHEDULING_TYPE',
297+
'weight': 'SAI_SCHEDULER_ATTR_SCHEDULING_WEIGHT',
298+
'pir': 'SAI_SCHEDULER_ATTR_MAX_BANDWIDTH_RATE'
299+
}
300+
301+
# Mapping for type values
302+
type_value_mapping = {
303+
'DWRR': 'SAI_SCHEDULING_TYPE_DWRR',
304+
'STRICT': 'SAI_SCHEDULING_TYPE_STRICT'
305+
}
306+
307+
# Build expected attributes dictionary
308+
expected_attrs = {}
309+
for param, value in kwargs.items():
310+
if param not in param_to_sai_attr:
311+
logger.warning(f"Unknown scheduler parameter: {param}")
312+
continue
313+
314+
sai_attr = param_to_sai_attr[param]
315+
316+
# Convert type value to SAI format
317+
if param == 'type':
318+
if value in type_value_mapping:
319+
expected_attrs[sai_attr] = type_value_mapping[value]
320+
else:
321+
logger.warning(f"Unknown scheduler type: {value}")
322+
continue
323+
else:
324+
# For numeric values, convert to string for comparison
325+
expected_attrs[sai_attr] = str(value)
326+
327+
logger.info(f"Looking for scheduler with attributes: {expected_attrs}")
328+
329+
# Get all scheduler OIDs from ASIC_DB
330+
cmd_get_oids = 'redis-cli -n 1 keys "ASIC_STATE:SAI_OBJECT_TYPE_SCHEDULER:oid*"'
331+
result = duthost.shell(cmd_get_oids)
332+
333+
if not result["stdout"].strip():
334+
logger.warning("No schedulers found in ASIC_DB")
335+
return None
336+
337+
oid_keys = result["stdout"].strip().split('\n')
338+
logger.info(f"Found {len(oid_keys)} schedulers in ASIC_DB")
339+
340+
# Check each scheduler to find a match
341+
for oid_key in oid_keys:
342+
# Get all attributes of this scheduler
343+
cmd_get_attrs = f'redis-cli -n 1 hgetall "{oid_key}"'
344+
result = duthost.shell(cmd_get_attrs)
345+
346+
if not result["stdout"].strip():
347+
continue
348+
349+
# Parse the attributes
350+
lines = result["stdout"].strip().split('\n')
351+
scheduler_attrs = {}
352+
for i in range(0, len(lines), 2):
353+
if i + 1 < len(lines):
354+
scheduler_attrs[lines[i]] = lines[i + 1]
355+
356+
# Check if all expected attributes match
357+
is_match = True
358+
for attr_name, expected_value in expected_attrs.items():
359+
actual_value = scheduler_attrs.get(attr_name)
360+
if actual_value != expected_value:
361+
is_match = False
362+
break
363+
364+
if is_match:
365+
# Extract the OID value (e.g., "0x160000000059aa")
366+
oid_value = oid_key.split(':')[-1]
367+
logger.info(f"Found matching scheduler OID: {oid_value}")
368+
logger.debug(f"Scheduler attributes: {scheduler_attrs}")
369+
return oid_value
370+
371+
logger.warning(f"No scheduler found matching attributes: {expected_attrs}")
372+
return None
373+
374+
279375
def create_blocking_scheduler(duthost):
280376
"""
281377
Create a blocking scheduler for limiting egress traffic
@@ -295,7 +391,7 @@ def create_blocking_scheduler(duthost):
295391
# Create blocking scheduler
296392
cmd_create = (
297393
f'sonic-db-cli CONFIG_DB hset "SCHEDULER|{BLOCK_DATA_PLANE_SCHEDULER_NAME}" '
298-
f'"type" DWRR "weight" 15 "pir" 1'
394+
f'"type" {SCHEDULER_TYPE} "weight" {SCHEDULER_WEIGHT} "pir" {SCHEDULER_PIR}'
299395
)
300396
duthost.shell(cmd_create)
301397
logger.info(f"Successfully created blocking scheduler: {BLOCK_DATA_PLANE_SCHEDULER_NAME}")
@@ -351,6 +447,42 @@ def validate_scheduler_configuration(duthost, dut_port, queue, expected_schedule
351447
return False
352448

353449

450+
def validate_scheduler_apply_to_queue_in_asic_db(duthost, scheduler_oid):
451+
"""
452+
Validate that the scheduler is applied to queue in ASIC_DB.
453+
454+
Args:
455+
duthost: DUT host object
456+
scheduler_oid (str): Scheduler OID to validate (e.g., "0x160000000059aa")
457+
458+
Returns:
459+
bool: True if applied to queue in ASIC_DB, False otherwise
460+
"""
461+
logger.debug(f"Validating scheduler OID {scheduler_oid} in ASIC_DB")
462+
463+
# Dump ASIC_DB to a temporary file for faster searching
464+
tmp_file = "/tmp/asic_db_scheduler_check.json"
465+
dump_cmd = f"sonic-db-dump -n ASIC_DB -y > {tmp_file}"
466+
duthost.shell(dump_cmd)
467+
468+
# Search for the scheduler OID in SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID
469+
cmd_grep_oid = f'grep "SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID" {tmp_file} | grep -c "{scheduler_oid}"'
470+
result = duthost.shell(cmd_grep_oid)
471+
472+
# Clean up temporary file
473+
duthost.shell(f"rm -f {tmp_file}")
474+
475+
# Check if scheduler OID is found in ASIC_DB
476+
count = int(result["stdout"].strip()) if result["stdout"].strip() else 0
477+
478+
if count > 0:
479+
logger.debug(f"ASIC_DB scheduler validation successful: OID {scheduler_oid} found in {count} scheduler groups")
480+
return True
481+
else:
482+
logger.debug(f"ASIC_DB scheduler validation failed: OID {scheduler_oid} not found in any scheduler group")
483+
return False
484+
485+
354486
def disable_egress_data_plane(duthost, dut_port, queue):
355487
"""
356488
Disable egress data plane for a specific queue on a specific port.
@@ -378,11 +510,20 @@ def disable_egress_data_plane(duthost, dut_port, queue):
378510
cmd_block_q = f"sonic-db-cli CONFIG_DB hset 'QUEUE|{dut_port}|{queue}' scheduler {BLOCK_DATA_PLANE_SCHEDULER_NAME}"
379511
duthost.shell(cmd_block_q)
380512

381-
# Wait for the blocking scheduler configuration to take effect
513+
# Wait for the blocking scheduler configuration to take effect in CONFIG_DB
382514
pytest_assert(wait_until(60, 5, 0, validate_scheduler_configuration,
383515
duthost, dut_port, queue, BLOCK_DATA_PLANE_SCHEDULER_NAME),
384516
f"Blocking scheduler configuration failed for port {dut_port} queue {queue}")
385517

518+
# Get the blocking scheduler OID from ASIC_DB
519+
scheduler_oid = get_scheduler_oid_by_attributes(duthost, type=SCHEDULER_TYPE,
520+
weight=SCHEDULER_WEIGHT, pir=SCHEDULER_PIR)
521+
pytest_assert(scheduler_oid, "Failed to find blocking scheduler OID in ASIC_DB")
522+
523+
# Wait for the blocking scheduler configuration to take effect in ASIC_DB
524+
pytest_assert(wait_until(60, 5, 0, validate_scheduler_apply_to_queue_in_asic_db, duthost, scheduler_oid),
525+
f"Scheduler OID {scheduler_oid} validation in ASIC_DB failed for port {dut_port} queue {queue}")
526+
386527
logger.info(f"Successfully applied blocking scheduler to port {dut_port} queue {queue}")
387528

388529
return original_scheduler

0 commit comments

Comments
 (0)