Skip to content

Commit 8bd0058

Browse files
authored
[202412][GCU] Update WRED_PROFILE and BUFFER_POOL validators for GCU (#276)
* cp #4219 * add illegal buffer pool test * create wrapper for ingesting extra args
1 parent eb456fc commit 8bd0058

3 files changed

Lines changed: 196 additions & 134 deletions

File tree

generic_config_updater/field_operation_validators.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,6 @@ def buffer_profile_config_update_validator(patch_element):
169169
return rdma_config_update_validator_common(patch_element)
170170

171171

172-
def wred_profile_config_update_validator(patch_element):
173-
return rdma_config_update_validator_common(patch_element)
174-
175-
176172
def read_statedb_entry(table, key, field):
177173
state_db = swsscommon.DBConnector("STATE_DB", 0)
178174
tbl = swsscommon.Table(state_db, table)

generic_config_updater/gcu_field_operation_validators.conf.json

Lines changed: 1 addition & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -78,26 +78,9 @@
7878
"rdma_config_update_validator": {
7979
"Shared/headroom pool size changes": {
8080
"fields": [
81-
"ingress_lossless_pool/xoff",
82-
"ingress_lossless_pool/size",
83-
"egress_lossy_pool/size"
8481
],
85-
"operations": ["replace"],
82+
"operations": [],
8683
"platforms": {
87-
"spc1": "20191100",
88-
"spc2": "20191100",
89-
"spc3": "20220500",
90-
"spc4": "20221100",
91-
"spc5": "20241200",
92-
"td2": "",
93-
"th": "20221100",
94-
"th2": "20221100",
95-
"th3": "20240500",
96-
"th4": "20240500",
97-
"th5": "20240500",
98-
"td3": "20221100",
99-
"j2c+": "20220500",
100-
"cisco-8000": "20201200"
10184
}
10285
}
10386
}
@@ -174,37 +157,6 @@
174157
}
175158
}
176159
},
177-
"WRED_PROFILE": {
178-
"field_operation_validators": [ "generic_config_updater.field_operation_validators.wred_profile_config_update_validator" ],
179-
"validator_data": {
180-
"rdma_config_update_validator": {
181-
"ECN tuning": {
182-
"fields": [
183-
"green_min_threshold",
184-
"green_max_threshold",
185-
"green_drop_probability"
186-
],
187-
"operations": ["replace"],
188-
"platforms": {
189-
"spc1": "20181100",
190-
"spc2": "20191100",
191-
"spc3": "20220500",
192-
"spc4": "20221100",
193-
"spc5": "20241200",
194-
"td2": "20181100",
195-
"th": "20181100",
196-
"th2": "20181100",
197-
"th3": "20240500",
198-
"th4": "20240500",
199-
"th5": "20240500",
200-
"td3": "20201200",
201-
"j2c+": "20220500",
202-
"cisco-8000": "20201200"
203-
}
204-
}
205-
}
206-
}
207-
},
208160
"PORT": {
209161
"field_operation_validators": [ "generic_config_updater.field_operation_validators.port_config_update_validator" ]
210162
}

tests/generic_config_updater/field_operation_validator_test.py

Lines changed: 195 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -177,92 +177,62 @@ def test_rdma_config_update_validator_spc_asic_other_field(self):
177177
patch_element = {"path": "/PFC_WD/Ethernet8/other_field", "op": "add", "value": "sample_value"}
178178
assert generic_config_updater.field_operation_validators.rdma_config_update_validator(patch_element) == False
179179

180-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "20250530.12"}))
181-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="th5"))
182-
@patch("os.path.exists", mock.Mock(return_value=True))
183-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
184-
def test_wred_profile_config_update_validator_lossless(self):
185-
patch_element = {
186-
"path": "/WRED_PROFILE/AZURE_LOSSLESS/green_min_threshold",
187-
"op": "replace",
188-
"value": "1234"
189-
}
190-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == True
191-
192-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "20250530.12"}))
193-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="th5"))
194-
@patch("os.path.exists", mock.Mock(return_value=True))
195-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
196-
def test_wred_profile_config_update_validator_lossy(self):
197-
patch_element = {
198-
"path": "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold",
199-
"op": "replace",
200-
"value": "1234"
201-
}
202-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == True
203-
204-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "20250530.12"}))
205-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="th5"))
206-
@patch("os.path.exists", mock.Mock(return_value=True))
207-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
208-
def test_wred_profile_config_update_validator_invalid_field(self):
209-
patch_element = {
210-
"path": "/WRED_PROFILE/AZURE_LOSSY/invalid",
211-
"op": "replace",
212-
"value": "1234"
213-
}
214-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == False
215-
216-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="unknown"))
217-
def test_wred_profile_config_update_validator_unknown_asic(self):
218-
patch_element = {
219-
"path": "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold",
220-
"op": "replace",
221-
"value": "1234"
222-
}
223-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == False
224-
225-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "SONiC.20220530"}))
226-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="th5"))
227-
@patch("os.path.exists", mock.Mock(return_value=True))
228-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
229-
def test_wred_profile_config_update_validator_old_version(self):
230-
patch_element = {
231-
"path": "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold",
232-
"op": "replace",
233-
"value": "1234"
234-
}
235-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == False
236-
237-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "20250530.12"}))
238-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="th5"))
239-
@patch("os.path.exists", mock.Mock(return_value=True))
240-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
241-
def test_wred_profile_config_update_validator_invalid_op(self):
242-
patch_element = {
243-
"path": "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold",
244-
"op": "add",
245-
"value": "1234"
246-
}
247-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == False
248-
249-
@patch("sonic_py_common.device_info.get_sonic_version_info", mock.Mock(return_value={"build_version": "20250530.12"}))
250-
@patch("generic_config_updater.field_operation_validators.get_asic_name", mock.Mock(return_value="spc1"))
251-
@patch("os.path.exists", mock.Mock(return_value=True))
252-
@patch("builtins.open", mock_open(read_data='{"tables": {"WRED_PROFILE": {"validator_data": {"rdma_config_update_validator": {"ECN tuning": {"fields": ["green_min_threshold", "green_max_threshold", "green_drop_probability"], "operations": ["replace"], "platforms": {"th5": "20240500"}}}}}}}'))
253-
def test_wred_profile_config_update_validator_invalid_asic(self):
254-
patch_element = {
255-
"path": "/WRED_PROFILE/AZURE_LOSSY/green_min_threshold",
256-
"op": "replace",
257-
"value": "1234"
258-
}
259-
assert generic_config_updater.field_operation_validators.wred_profile_config_update_validator(patch_element) == False
260-
261180
def test_validate_field_operation_illegal__pfcwd(self):
262181
old_config = {"PFC_WD": {"GLOBAL": {"POLL_INTERVAL": "60"}}}
263182
target_config = {"PFC_WD": {"GLOBAL": {}}}
264183
config_wrapper = gu_common.ConfigWrapper()
265184
pytest.raises(gu_common.IllegalPatchOperationError, config_wrapper.validate_field_operation, old_config, target_config)
185+
186+
@patch("sonic_py_common.device_info.get_sonic_version_info",
187+
mock.Mock(return_value={"build_version": "20241211.49"}))
188+
@patch("generic_config_updater.field_operation_validators.get_asic_name",
189+
mock.Mock(return_value="spc1"))
190+
@patch("os.path.exists", mock.Mock(return_value=True))
191+
@patch(
192+
"builtins.open",
193+
mock_open(
194+
read_data=(
195+
'{"tables": {"BUFFER_POOL": {'
196+
'"field_operation_validators": ['
197+
'"generic_config_updater.field_operation_validators.rdma_config_update_validator"'
198+
'], "validator_data": {"rdma_config_update_validator": {"Blocked ops": '
199+
'{"fields": ["ingress_lossless_pool/xoff", '
200+
'"ingress_lossless_pool/size", "egress_lossy_pool/size"], '
201+
'"operations": [], "platforms": {"spc1": "20181100"}}}}}}}'
202+
)
203+
)
204+
)
205+
def test_validate_field_operation_illegal__buffer_pool(self):
206+
old_config = {
207+
"BUFFER_POOL": {
208+
"ingress_lossless_pool": {"xoff": "1000"}
209+
}
210+
}
211+
target_config = {
212+
"BUFFER_POOL": {
213+
"ingress_lossless_pool": {"xoff": "2000"}
214+
}
215+
}
216+
config_wrapper = gu_common.ConfigWrapper()
217+
original_validator = fov.rdma_config_update_validator
218+
219+
def _rdma_validator_wrapper(*args, **kwargs):
220+
if args:
221+
patch_element = args[-1]
222+
else:
223+
patch_element = kwargs.get("patch_element")
224+
return original_validator(patch_element)
225+
226+
with patch(
227+
"generic_config_updater.field_operation_validators.rdma_config_update_validator",
228+
side_effect=_rdma_validator_wrapper,
229+
):
230+
pytest.raises(
231+
gu_common.IllegalPatchOperationError,
232+
config_wrapper.validate_field_operation,
233+
old_config,
234+
target_config
235+
)
266236

267237
def test_validate_field_operation_legal__rm_loopback1(self):
268238
old_config = {
@@ -386,6 +356,150 @@ def test_validate_field_operation_legal__only_dataacl_rule_update(self):
386356
config_wrapper.validate_field_operation(old_config, target_config)
387357

388358

359+
@pytest.mark.parametrize(
360+
"field,old_value,new_value,op", [
361+
("ecn", "ecn_all", "ecn_green", "replace"),
362+
("green_drop_probability", "5", "6", "replace"),
363+
("green_max_threshold", "136200192", "136200193", "replace"),
364+
("green_min_threshold", "136200192", "136200193", "replace"),
365+
("red_drop_probability", "5", "6", "replace"),
366+
("red_max_threshold", "282624", "282625", "replace"),
367+
("red_min_threshold", "166912", "166913", "replace"),
368+
("wred_green_enable", "false", "true", "replace"),
369+
("wred_red_enable", "false", "true", "replace"),
370+
("wred_yellow_enable", "false", "true", "replace"),
371+
("yellow_drop_probability", "5", "6", "replace"),
372+
("yellow_max_threshold", "282624", "282625", "replace"),
373+
("yellow_min_threshold", "166912", "166913", "replace")
374+
]
375+
)
376+
def test_validate_field_operation_wred_profile_replace(self, field, old_value, new_value, op):
377+
old_config = {"WRED_PROFILE": {"AZURE_LOSSY": {field: old_value}}}
378+
target_config = {"WRED_PROFILE": {"AZURE_LOSSY": {field: new_value}}}
379+
config_wrapper = gu_common.ConfigWrapper()
380+
config_wrapper.validate_field_operation(old_config, target_config)
381+
382+
@pytest.mark.parametrize(
383+
"field,value", [
384+
("green_min_threshold", "1200"),
385+
("yellow_max_threshold", "2400"),
386+
("red_min_threshold", "3200"),
387+
("green_drop_probability", "10"),
388+
("wred_green_enable", "true"),
389+
("wred_yellow_enable", "true"),
390+
("wred_red_enable", "true")
391+
]
392+
)
393+
def test_validate_field_operation_wred_profile_add(self, field, value):
394+
old_config = {"WRED_PROFILE": {"AZURE_LOSSY": {}}}
395+
target_config = {"WRED_PROFILE": {"AZURE_LOSSY": {field: value}}}
396+
config_wrapper = gu_common.ConfigWrapper()
397+
config_wrapper.validate_field_operation(old_config, target_config)
398+
399+
@pytest.mark.parametrize(
400+
"table", [
401+
"BUFFER_PORT_EGRESS_PROFILE_LIST",
402+
"BUFFER_PORT_INGRESS_PROFILE_LIST"
403+
]
404+
)
405+
def test_validate_field_operation_buffer_port_profile_list_add(self, table):
406+
old_config = {table: {"Ethernet0": {}}}
407+
target_config = {table: {"Ethernet0": {"profile_list": "AZURE_PROFILE"}}}
408+
config_wrapper = gu_common.ConfigWrapper()
409+
config_wrapper.validate_field_operation(old_config, target_config)
410+
411+
@pytest.mark.parametrize(
412+
"table", [
413+
"BUFFER_PORT_EGRESS_PROFILE_LIST",
414+
"BUFFER_PORT_INGRESS_PROFILE_LIST"
415+
]
416+
)
417+
def test_validate_field_operation_buffer_port_profile_list_replace(self, table):
418+
old_config = {table: {"Ethernet0": {"profile_list": "AZURE_PROFILE"}}}
419+
target_config = {table: {"Ethernet0": {"profile_list": "NEW_PROFILE"}}}
420+
config_wrapper = gu_common.ConfigWrapper()
421+
config_wrapper.validate_field_operation(old_config, target_config)
422+
423+
@pytest.mark.parametrize(
424+
"table", [
425+
"BUFFER_PORT_EGRESS_PROFILE_LIST",
426+
"BUFFER_PORT_INGRESS_PROFILE_LIST"
427+
]
428+
)
429+
def test_validate_field_operation_buffer_port_profile_list_remove(self, table):
430+
old_config = {table: {"Ethernet0": {"profile_list": "AZURE_PROFILE"}}}
431+
target_config = {table: {"Ethernet0": {}}}
432+
config_wrapper = gu_common.ConfigWrapper()
433+
config_wrapper.validate_field_operation(old_config, target_config)
434+
435+
def test_validate_field_operation_queue_scheduler_replace(self):
436+
old_config = {"QUEUE": {"Ethernet0|0": {"scheduler": "sched0"}}}
437+
target_config = {"QUEUE": {"Ethernet0|0": {"scheduler": "sched1"}}}
438+
config_wrapper = gu_common.ConfigWrapper()
439+
config_wrapper.validate_field_operation(old_config, target_config)
440+
441+
def test_validate_field_operation_queue_wred_profile_add(self):
442+
old_config = {"QUEUE": {"Ethernet0|1": {}}}
443+
target_config = {"QUEUE": {"Ethernet0|1": {"wred_profile": "WRED_PROFILE"}}}
444+
config_wrapper = gu_common.ConfigWrapper()
445+
config_wrapper.validate_field_operation(old_config, target_config)
446+
447+
def test_validate_field_operation_queue_wred_profile_replace(self):
448+
old_config = {"QUEUE": {"Ethernet0|1": {"wred_profile": "WRED_PROFILE"}}}
449+
target_config = {"QUEUE": {"Ethernet0|1": {"wred_profile": "WRED_PROFILE_NEW"}}}
450+
config_wrapper = gu_common.ConfigWrapper()
451+
config_wrapper.validate_field_operation(old_config, target_config)
452+
453+
@pytest.mark.parametrize(
454+
"field,new_value", [
455+
("dscp_to_tc_map", "AZURE"),
456+
("tc_to_pg_map", "AZURE"),
457+
("tc_to_queue_map", "AZURE")
458+
]
459+
)
460+
def test_validate_field_operation_port_qos_map_replace(self, field, new_value):
461+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {field: "DEFAULT"}}}
462+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {field: new_value}}}
463+
config_wrapper = gu_common.ConfigWrapper()
464+
config_wrapper.validate_field_operation(old_config, target_config)
465+
466+
def test_validate_field_operation_port_qos_map_tc_to_dscp_add(self):
467+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {}}}
468+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_dscp_map": "AZURE"}}}
469+
config_wrapper = gu_common.ConfigWrapper()
470+
config_wrapper.validate_field_operation(old_config, target_config)
471+
472+
def test_validate_field_operation_port_qos_map_tc_to_dscp_replace(self):
473+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_dscp_map": "DEFAULT"}}}
474+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_dscp_map": "AZURE"}}}
475+
config_wrapper = gu_common.ConfigWrapper()
476+
config_wrapper.validate_field_operation(old_config, target_config)
477+
478+
def test_validate_field_operation_port_qos_map_dscp_to_tc_replace(self):
479+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {"dscp_to_tc_map": "DEFAULT"}}}
480+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {"dscp_to_tc_map": "AZURE"}}}
481+
config_wrapper = gu_common.ConfigWrapper()
482+
config_wrapper.validate_field_operation(old_config, target_config)
483+
484+
def test_validate_field_operation_port_qos_map_tc_to_pg_replace(self):
485+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_pg_map": "DEFAULT"}}}
486+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_pg_map": "AZURE"}}}
487+
config_wrapper = gu_common.ConfigWrapper()
488+
config_wrapper.validate_field_operation(old_config, target_config)
489+
490+
def test_validate_field_operation_port_qos_map_tc_to_queue_replace(self):
491+
old_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_queue_map": "DEFAULT"}}}
492+
target_config = {"PORT_QOS_MAP": {"Ethernet0": {"tc_to_queue_map": "AZURE"}}}
493+
config_wrapper = gu_common.ConfigWrapper()
494+
config_wrapper.validate_field_operation(old_config, target_config)
495+
496+
def test_validate_field_operation_scheduler_weight_replace(self):
497+
old_config = {"SCHEDULER": {"scheduler.0": {"weight": "10", "type": "DWRR"}}}
498+
target_config = {"SCHEDULER": {"scheduler.0": {"weight": "20", "type": "DWRR"}}}
499+
config_wrapper = gu_common.ConfigWrapper()
500+
config_wrapper.validate_field_operation(old_config, target_config)
501+
502+
389503
class TestGetAsicName(unittest.TestCase):
390504

391505
@patch('sonic_py_common.device_info.get_sonic_version_info')

0 commit comments

Comments
 (0)