Skip to content

Commit aa11f06

Browse files
mramezani95mssonicbld
authored andcommitted
Updated the WRED ECN config update test so that it no longer requires a WRED profile named 'AZURE_LOSSLESS'. (#19246)
What is the motivation for this PR? The test_ecn_config_update.py test fails on devices that do not have a WRED_PROFILE named AZURE_LOSSLESS. How did you do it? Instead of updating the WRED_PROFILE named AZURE_LOSSLESS, the test now updates all WRED profiles found in CONFIG DB and then verifies that these updates are applied to ASIC DB. Note: In order for this test to pass, changes on the GCU side are also needed. Here is the PR in sonic-utilities for GCU changes: sonic-net/sonic-utilities#3910 How did you verify/test it? Tested on a Mellanox switch with 3 WRED profiles, none of which were named AZURE_LOSSLESS. The old version of the test failed, while the new version passed. Signed-off-by: Mahdi Ramezani <[email protected]>
1 parent 86f5e62 commit aa11f06

File tree

1 file changed

+107
-43
lines changed

1 file changed

+107
-43
lines changed

tests/generic_config_updater/test_ecn_config_update.py

Lines changed: 107 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ast
2+
from functools import cmp_to_key
23
import logging
34
import pytest
45

@@ -45,45 +46,99 @@ def ensure_dut_readiness(duthost):
4546
delete_checkpoint(duthost)
4647

4748

48-
def ensure_application_of_updated_config(duthost, configdb_field, values):
49+
def get_asic_db_values(duthost, fields):
50+
"""
51+
Args:
52+
duthost: DUT host object
53+
fields: CONFIG DB field(s) under test
54+
55+
Returns:
56+
A dictionary where keys are WRED profile OIDs in ASIC DB and values are the field-value pairs
57+
for the fields in configdb_field.
58+
"""
59+
wred_objects = duthost.shell('sonic-db-cli ASIC_DB keys *WRED*')["stdout"]
60+
wred_objects = wred_objects.split("\n")
61+
asic_db_values = {}
62+
for wred_object in wred_objects:
63+
oid = wred_object[wred_object.rfind(':') + 1:]
64+
asic_db_values[oid] = {}
65+
wred_data = duthost.shell('sonic-db-cli ASIC_DB hgetall {}'.format(wred_object))["stdout"]
66+
if "NULL" in wred_data:
67+
continue
68+
wred_data = ast.literal_eval(wred_data)
69+
for field in fields:
70+
value = int(wred_data[WRED_MAPPING[field]])
71+
asic_db_values[oid][field] = value
72+
return asic_db_values
73+
74+
75+
def get_wred_objects(duthost):
76+
"""
77+
Args:
78+
duthost: DUT host object
79+
80+
Returns:
81+
A list of WRED profile objects in ASIC DB.
82+
"""
83+
wred_objects = duthost.shell('sonic-db-cli ASIC_DB keys *WRED*')["stdout"]
84+
wred_objects = wred_objects.split("\n")
85+
return wred_objects
86+
87+
88+
def dict_compare(fields):
89+
"""
90+
Compares two dictionaries for equality based on a subset of keys.
91+
92+
Args:
93+
fields: The keys to compare.
94+
95+
Returns:
96+
A function that compares two dictionaries.
97+
"""
98+
def compare(dict1, dict2):
99+
for field in fields:
100+
if dict1.get(field, 0) < dict2.get(field, 0):
101+
return -1
102+
elif dict1.get(field, 0) > dict2.get(field, 0):
103+
return 1
104+
# If all compared fields are equal, return 0
105+
return 0
106+
107+
return compare
108+
109+
110+
def ensure_application_of_updated_config(duthost, fields, new_values):
49111
"""
50112
Ensures application of the JSON patch config update
51113
52114
Args:
53115
duthost: DUT host object
54-
configdb_field: config db field(s) under test
55-
values: expected value(s) of configdb_field
116+
fields: config db field(s) under test
117+
new_values: expected value(s) of fields. It is a dictionary where keys are WRED profile names
118+
and values are dictionaries of field-value pairs for all fields in fields.
56119
"""
57-
def _confirm_value_in_asic_db():
58-
wred_objects = duthost.shell('sonic-db-cli ASIC_DB keys *WRED*')["stdout"]
59-
wred_objects = wred_objects.split("\n")
60-
if (len(wred_objects) > 1):
61-
for wred_object in wred_objects:
62-
wred_data = duthost.shell('sonic-db-cli ASIC_DB hgetall {}'.format(wred_object))["stdout"]
63-
if ('NULL' in wred_data):
64-
continue
65-
wred_data = ast.literal_eval(wred_data)
66-
for field, value in zip(configdb_field.split(','), values.split(',')):
67-
if value != wred_data[WRED_MAPPING[field]]:
68-
return False
69-
return True
70-
return False
71-
else:
72-
wred_data = duthost.shell('sonic-db-cli ASIC_DB hgetall {}'.format(wred_objects[0]))["stdout"]
73-
wred_data = ast.literal_eval(wred_data)
74-
for field, value in zip(configdb_field.split(','), values.split(',')):
75-
if value != wred_data[WRED_MAPPING[field]]:
76-
return False
77-
return True
78-
79-
logger.info("Validating fields in ASIC DB...")
120+
# Since there is no direct way to obtain the WRED profile name to oid mapping, we will just make sure
121+
# that the set of values in ASIC DB matches the set of values in CONFIG DB.
122+
def validate_wred_objects_in_asic_db():
123+
asic_db_values = get_asic_db_values(duthost, fields)
124+
asic_db_values_list = sorted(list(asic_db_values.values()), key=cmp_to_key(dict_compare(fields)))
125+
new_values_list = sorted(list(new_values.values()), key=cmp_to_key(dict_compare(fields)))
126+
return asic_db_values_list == new_values_list
127+
128+
logger.info("Validating WRED objects in ASIC DB...")
80129
pytest_assert(
81-
wait_until(READ_ASICDB_TIMEOUT, READ_ASICDB_INTERVAL, 0, _confirm_value_in_asic_db),
130+
wait_until(READ_ASICDB_TIMEOUT, READ_ASICDB_INTERVAL, 0, validate_wred_objects_in_asic_db),
82131
"ASIC DB does not properly reflect newly configured field(s): {} expected value(s): {}"
83-
.format(configdb_field, values)
132+
.format(fields, new_values)
84133
)
85134

86135

136+
def get_wred_profiles(duthost):
137+
wred_profiles = duthost.shell("sonic-db-cli CONFIG_DB keys 'WRED_PROFILE|*' | cut -d '|' -f 2")["stdout"]
138+
wred_profiles = wred_profiles.split('\n')
139+
return wred_profiles
140+
141+
87142
@pytest.mark.parametrize("configdb_field", ["green_min_threshold", "green_max_threshold", "green_drop_probability",
88143
"green_min_threshold,green_max_threshold,green_drop_probability"])
89144
@pytest.mark.parametrize("operation", ["replace"])
@@ -92,28 +147,37 @@ def test_ecn_config_updates(duthost, ensure_dut_readiness, configdb_field, opera
92147
logger.info("tmpfile {} created for json patch of field: {} and operation: {}"
93148
.format(tmpfile, configdb_field, operation))
94149

150+
fields = configdb_field.split(',')
151+
wred_profiles = get_wred_profiles(duthost)
152+
if not wred_profiles:
153+
pytest.skip("No WRED profiles found in CONFIG_DB, skipping test.")
95154
json_patch = list()
96-
values = list()
97-
ecn_data = duthost.shell('sonic-db-cli CONFIG_DB hgetall "WRED_PROFILE|AZURE_LOSSLESS"')['stdout']
98-
ecn_data = ast.literal_eval(ecn_data)
99-
for field in configdb_field.split(','):
100-
value = int(ecn_data[field]) + 1
101-
values.append(str(value))
102-
103-
logger.info("value to be added to json patch: {}, operation: {}, field: {}"
104-
.format(value, operation, field))
105-
106-
json_patch.append(
107-
{"op": "{}".format(operation),
108-
"path": "/WRED_PROFILE/AZURE_LOSSLESS/{}".format(field),
109-
"value": "{}".format(value)})
155+
# new_values is a dictionary from WRED profile name to its field-value mapping (with new values)
156+
# for the fields in configdb_field.
157+
new_values = {}
158+
# Creating a JSON patch for all WRED profiles in CONFIG_DB.
159+
for wred_profile in wred_profiles:
160+
ecn_data = duthost.shell(f"sonic-db-cli CONFIG_DB hgetall 'WRED_PROFILE|{wred_profile}'")["stdout"]
161+
ecn_data = ast.literal_eval(ecn_data)
162+
new_values[wred_profile] = {}
163+
for field in fields:
164+
value = int(ecn_data[field]) + 1
165+
new_values[wred_profile][field] = value
166+
167+
logger.info("value to be added to json patch: {}, operation: {}, field: {}"
168+
.format(value, operation, field))
169+
170+
json_patch.append(
171+
{"op": "{}".format(operation),
172+
"path": f"/WRED_PROFILE/{wred_profile}/{field}",
173+
"value": "{}".format(value)})
110174

111175
json_patch = format_json_patch_for_multiasic(duthost=duthost, json_data=json_patch, is_asic_specific=True)
112176
try:
113177
output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile)
114178
if is_valid_platform_and_version(duthost, "WRED_PROFILE", "ECN tuning", operation):
115179
expect_op_success(duthost, output)
116-
ensure_application_of_updated_config(duthost, configdb_field, ",".join(values))
180+
ensure_application_of_updated_config(duthost, fields, new_values)
117181
else:
118182
expect_op_failure(output)
119183
finally:

0 commit comments

Comments
 (0)