diff --git a/tests/generic_config_updater/gcu_field_operation_validators.conf.json b/tests/generic_config_updater/gcu_field_operation_validators.conf.json new file mode 100644 index 0000000000..2dcf1649b7 --- /dev/null +++ b/tests/generic_config_updater/gcu_field_operation_validators.conf.json @@ -0,0 +1,137 @@ +{ + "README": [ + "field_operation_validators provides, module & method name as ", + " .", + "NOTE: module name could have '.'", + " ", + "The last element separated by '.' is considered as ", + "method name", + "", + "e.g. 'show.acl.test_acl'", + "", + "field_operation_validators for a given table defines a list of validators that all must pass for modification to the specified field and table to be allowed", + "", + "validator_data provides data relevant to each validator", + "" + ], + "helper_data": { + "rdma_config_update_validator": { + "mellanox_asics": { + "spc1": [ "ACS-MSN2700", "ACS-MSN2740", "ACS-MSN2100", "ACS-MSN2410", "ACS-MSN2010", "Mellanox-SN2700", "Mellanox-SN2700-D48C8" ] + }, + "broadcom_asics": { + "th": [ "Force10-S6100", "Arista-7060CX-32S-C32", "Arista-7060CX-32S-C32-T1", "Arista-7060CX-32S-D48C8", "Celestica-DX010-C32", "Seastone-DX010" ], + "th2": [ "Arista-7260CX3-D108C8", "Arista-7260CX3-C64", "Arista-7260CX3-Q64" ], + "td2": [ "Force10-S6000", "Force10-S6000-Q24S32", "Arista-7050-QX32", "Arista-7050-QX-32S", "Nexus-3164", "Arista-7050QX32S-Q32" ], + "td3": [ "Arista-7050CX3-32S-C32", "Arista-7050CX3-32S-D48C8" ] + } + } + }, + "tables": { + "PFC_WD": { + "field_operation_validators": [ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ], + "validator_data": { + "rdma_config_update_validator": { + "PFCWD enable/disable": { + "fields": [ + "restoration_time", + "detection_time", + "action", + "global/poll_interval" + ], + "operations": ["remove", "add", "replace"], + "platforms": { + "spc1": "20181100", + "td2": "20181100", + "th": "20181100", + "th2": "20181100", + "td3": "20201200", + "cisco-8000": "20201200" + } + } + } + } + }, + "BUFFER_POOL": { + "field_operation_validators": [ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ], + "validator_data": { + "rdma_config_update_validator": { + "Shared/headroom pool size changes": { + "fields": [ + "ingress_lossless_pool/xoff", + "ingress_lossless_pool/size", + "egress_lossy_pool/size" + ], + "operations": ["replace"], + "platforms": { + "spc1": "20191100", + "td2": "", + "th": "20221100", + "th2": "20221100", + "td3": "20221100", + "cisco-8000": "" + } + } + } + } + }, + "BUFFER_PROFILE": { + "field_operation_validators": [ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ], + "validator_data": { + "rdma_config_update_validator": { + "Dynamic threshold tuning": { + "fields": [ + "dynamic_th" + ], + "operations": ["replace"], + "platforms": { + "spc1": "20181100", + "td2": "20181100", + "th": "20181100", + "th2": "20181100", + "td3": "20201200", + "cisco-8000": "" + } + }, + "PG headroom modification": { + "fields": [ + "xoff" + ], + "operations": ["replace"], + "platforms": { + "spc1": "20191100", + "td2": "", + "th": "20221100", + "th2": "20221100", + "td3": "20221100", + "cisco-8000": "" + } + } + } + } + }, + "WRED_PROFILE": { + "field_operation_validators": [ "generic_config_updater.field_operation_validators.rdma_config_update_validator" ], + "validator_data": { + "rdma_config_update_validator": { + "ECN tuning": { + "fields": [ + "azure_lossless/green_min_threshold", + "azure_lossless/green_max_threshold", + "azure_lossless/green_drop_probability" + ], + "operations": ["replace"], + "platforms": { + "spc1": "20181100", + "td2": "20181100", + "th": "20181100", + "th2": "20181100", + "td3": "20201200", + "cisco-8000": "" + } + } + } + } + } + } +} diff --git a/tests/generic_config_updater/gu_utils.py b/tests/generic_config_updater/gu_utils.py index e4ed739d8f..8ee9b43bce 100644 --- a/tests/generic_config_updater/gu_utils.py +++ b/tests/generic_config_updater/gu_utils.py @@ -1,3 +1,4 @@ +import os import json import logging import pytest @@ -10,6 +11,8 @@ CONTAINER_SERVICES_LIST = ["swss", "syncd", "radv", "lldp", "dhcp_relay", "teamd", "bgp", "pmon", "telemetry", "acms"] DEFAULT_CHECKPOINT_NAME = "test" +GCU_FIELD_OPERATION_CONF_FILE = "gcu_field_operation_validators.conf.json" +GET_HWSKU_CMD = "sonic-cfggen -d -v DEVICE_METADATA.localhost.hwsku" def generate_tmpfile(duthost): @@ -286,3 +289,50 @@ def check_vrf_route_for_intf(duthost, vrf_name, intf_name, is_ipv4=True): output = duthost.shell("show {} route vrf {} | grep -w {}".format(address_family, vrf_name, intf_name)) pytest_assert(not output['rc'], "Route not found for {} in vrf {}".format(intf_name, vrf_name)) + + +def get_gcu_field_operations_conf(): + conf_path = os.path.join(os.path.dirname(__file__), GCU_FIELD_OPERATION_CONF_FILE) + with open(conf_path, 'r') as s: + gcu_conf = json.load(s) + return gcu_conf + + +def get_asic_name(duthost): + asic_type = duthost.facts["asic_type"] + asic = "unknown" + gcu_conf = get_gcu_field_operations_conf() + asic_mapping = gcu_conf["helper_data"]["rdma_config_update_validator"] + if asic_type == 'cisco-8000': + asic = "cisco-8000" + elif asic_type == 'mellanox' or asic_type == 'vs' or asic_type == 'broadcom': + hwsku = duthost.shell(GET_HWSKU_CMD)['stdout'].rstrip('\n') + if asic_type == 'mellanox' or asic_type == 'vs': + spc1_hwskus = asic_mapping["mellanox_asics"]["spc1"] + if hwsku.lower() in [spc1_hwsku.lower() for spc1_hwsku in spc1_hwskus]: + asic = "spc1" + return asic + if asic_type == 'broadcom' or asic_type == 'vs': + broadcom_asics = asic_mapping["broadcom_asics"] + for asic_shorthand, hwskus in broadcom_asics.items(): + for hwsku_cur in hwskus: + if hwsku_cur.lower() in hwsku.lower(): + asic = asic_shorthand + break + else: + continue + break + + return asic + + +def is_valid_platform_and_version(duthost, table, scenario): + asic = get_asic_name(duthost) + os_version = duthost.os_version + if asic == "unknown": + return False + if "master" or "internal" in os_version: + return True + gcu_conf = get_gcu_field_operations_conf() + version_required = gcu_conf["tables"][table]["validator_data"]["rdma_config_update_validator"][scenario][asic][0:6] + return os_version >= version_required diff --git a/tests/generic_config_updater/test_ecn_config_update.py b/tests/generic_config_updater/test_ecn_config_update.py index 2f81f1e463..9c03c0b016 100644 --- a/tests/generic_config_updater/test_ecn_config_update.py +++ b/tests/generic_config_updater/test_ecn_config_update.py @@ -5,9 +5,10 @@ from tests.common.helpers.assertions import pytest_assert from tests.common.utilities import wait_until from tests.common.helpers.dut_utils import verify_orchagent_running_or_assert -from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success +from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success, expect_op_failure from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload +from tests.generic_config_updater.gu_utils import is_valid_platform_and_version pytestmark = [ pytest.mark.topology('any'), @@ -94,8 +95,11 @@ def test_ecn_config_updates(duthost, ensure_dut_readiness, configdb_field, opera "value": "{}".format(value)}) try: - output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success(duthost, output) - ensure_application_of_updated_config(duthost, configdb_field, ",".join(values)) + if is_valid_platform_and_version(duthost, "WRED_PROFILE", "ECN tuning"): + output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) + expect_op_success(duthost, output) + ensure_application_of_updated_config(duthost, configdb_field, ",".join(values)) + else: + expect_op_failure(output) finally: delete_tmpfile(duthost, tmpfile) diff --git a/tests/generic_config_updater/test_incremental_qos.py b/tests/generic_config_updater/test_incremental_qos.py index 8231e4e0e7..f06bf0eb60 100644 --- a/tests/generic_config_updater/test_incremental_qos.py +++ b/tests/generic_config_updater/test_incremental_qos.py @@ -10,6 +10,7 @@ expect_res_success, expect_op_failure # noqa F401 from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload +from tests.generic_config_updater.gu_utils import is_valid_platform_and_version pytestmark = [ pytest.mark.topology('t0'), @@ -232,7 +233,10 @@ def test_incremental_qos_config_updates(duthost, tbinfo, ensure_dut_readiness, c try: output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success(duthost, output) - ensure_application_of_updated_config(duthost, configdb_field, value) + if is_valid_platform_and_version(duthost, "BUFFER_POOL", "Shared/headroom pool size changes"): + expect_op_success(duthost, output) + ensure_application_of_updated_config(duthost, configdb_field, value) + else: + expect_op_failure(output) finally: delete_tmpfile(duthost, tmpfile) diff --git a/tests/generic_config_updater/test_pfcwd_interval.py b/tests/generic_config_updater/test_pfcwd_interval.py index 69e79577b9..09ac5ba49b 100644 --- a/tests/generic_config_updater/test_pfcwd_interval.py +++ b/tests/generic_config_updater/test_pfcwd_interval.py @@ -7,6 +7,7 @@ from tests.generic_config_updater.gu_utils import apply_patch, expect_op_success, expect_op_failure from tests.generic_config_updater.gu_utils import generate_tmpfile, delete_tmpfile from tests.generic_config_updater.gu_utils import create_checkpoint, delete_checkpoint, rollback_or_reload +from tests.generic_config_updater.gu_utils import is_valid_platform_and_version pytestmark = [ pytest.mark.asic('mellanox'), @@ -163,15 +164,17 @@ def test_stop_pfcwd(duthost, ensure_dut_readiness): "path": "/PFC_WD/{}/action".format(interface) } ] - try: tmpfile = generate_tmpfile(duthost) output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - expect_op_success(duthost, output) - pfcwd_updated_config = duthost.shell("show pfcwd config") - pytest_assert(not pfcwd_config['rc'], "Unable to read updated pfcwd config") - pytest_assert(interface not in pfcwd_updated_config['stdout'].split(), - "pfcwd unexpectedly still running on interface {}".format(interface)) + if is_valid_platform_and_version(duthost, "PFC_WD", "PFCWD enable/disable"): + expect_op_success(duthost, output) + pfcwd_updated_config = duthost.shell("show pfcwd config") + pytest_assert(not pfcwd_config['rc'], "Unable to read updated pfcwd config") + pytest_assert(interface not in pfcwd_updated_config['stdout'].split(), + "pfcwd unexpectedly still running on interface {}".format(interface)) + else: + expect_op_failure(output) finally: delete_tmpfile(duthost, tmpfile) # Restore default config @@ -209,7 +212,7 @@ def test_pfcwd_interval_config_updates(duthost, ensure_dut_readiness, operation, try: output = apply_patch(duthost, json_data=json_patch, dest_file=tmpfile) - if is_valid_config_update: + if is_valid_config_update and is_valid_platform_and_version(duthost, "PFC_WD", "PFCWD enable/disable"): expect_op_success(duthost, output) ensure_application_of_updated_config(duthost, value) else: