diff --git a/tests/qos/files/dynamic_buffer_param.json b/tests/qos/files/dynamic_buffer_param.json index 60e67e01498..e57ca6370c3 100644 --- a/tests/qos/files/dynamic_buffer_param.json +++ b/tests/qos/files/dynamic_buffer_param.json @@ -55,5 +55,39 @@ "x86_64-nvidia_sn5600-r0": "800000", "x86_64-nvidia_sn5600_simx-r0": "800000" } + }, + "barefoot": { + "default_cable_length": ["5m", "40m", "300m"], + "testparam_cable_length": ["15m", "40m"], + "headroom-override": { + "add": { + "xon": "18432", + "xoff": "18432", + "size": "36864", + "dynamic_th": "1" + }, + "set": { + "xon": "18432", + "xoff": "36864", + "size": "55296" + } + }, + "lossless_pg": { + "headroom-override": { + "xon": "18432", + "xoff": "16384", + "size": "34816" + }, + "non-default-dynamic_th": { + "dynamic_th": "7" + } + }, + "lossy_pg": { + "default": "4096" + }, + "shared-headroom-pool": { + "size": "3153920", + "private_pg_headroom": "70400" + } } } diff --git a/tests/qos/test_buffer.py b/tests/qos/test_buffer.py index 3ca549ac5df..a2c5fe6afa4 100644 --- a/tests/qos/test_buffer.py +++ b/tests/qos/test_buffer.py @@ -1,6 +1,4 @@ import logging -import os -import sys import time import re import json @@ -10,16 +8,15 @@ import pytest from tests.common import config_reload -from tests.common.broadcom_data import is_broadcom_device +from tests.common.barefoot_data import is_barefoot_device from tests.common.utilities import wait_until from tests.common.helpers.assertions import pytest_assert, pytest_require -from tests.common.fixtures.conn_graph_facts import conn_graph_facts from tests.common.mellanox_data import is_mellanox_device from tests.common.innovium_data import is_innovium_device from tests.common.plugins.loganalyzer.loganalyzer import LogAnalyzer from tests.common.utilities import check_qos_db_fv_reference_with_table from tests.common.utilities import skip_release -from tests.common.dualtor.dual_tor_utils import is_tunnel_qos_remap_enabled, dualtor_ports # lgtm[py/unused-import] +from tests.common.dualtor.dual_tor_utils import is_tunnel_qos_remap_enabled pytestmark = [ pytest.mark.topology('any') @@ -60,25 +57,32 @@ KEY_2_LOSSLESS_QUEUE = "2_lossless_queues" KEY_4_LOSSLESS_QUEUE = "4_lossless_queues" + def detect_buffer_model(duthost): - """Detect the current buffer model (dynamic or traditional) and store it for further use. Called only once when the module is initialized + """ + Detect the current buffer model (dynamic or traditional) and store it for further use. Called only once when the + module is initialized Args: duthost: The DUT host object """ global BUFFER_MODEL_DYNAMIC - buffer_model = duthost.shell('redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] + buffer_model = duthost.shell( + 'redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] BUFFER_MODEL_DYNAMIC = (buffer_model == 'dynamic') def detect_ingress_pool_number(duthost): - """Detect the number of ingress buffer pools and store it for further use. Called only once when the module is initialized + """ + Detect the number of ingress buffer pools and store it for further use. Called only once when the module is + initialized Args: duthost: The DUT host object """ global DEFAULT_INGRESS_POOL_NUMBER - pools = duthost.shell('redis-cli -n 4 keys "BUFFER_POOL|ingress*"')['stdout'] + pools = duthost.shell( + 'redis-cli -n 4 keys "BUFFER_POOL|ingress*"')['stdout'] DEFAULT_INGRESS_POOL_NUMBER = len(pools.split()) @@ -92,12 +96,14 @@ def detect_shared_headroom_pool_mode(duthost): global DEFAULT_SHARED_HEADROOM_POOL_SIZE global DEFAULT_OVER_SUBSCRIBE_RATIO - over_subscribe_ratio = duthost.shell('redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] + over_subscribe_ratio = duthost.shell( + 'redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] if over_subscribe_ratio and over_subscribe_ratio != '0': DEFAULT_SHARED_HEADROOM_POOL_ENABLED = True DEFAULT_OVER_SUBSCRIBE_RATIO = int(over_subscribe_ratio) - shared_headroom_pool_size = duthost.shell('redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] + shared_headroom_pool_size = duthost.shell( + 'redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] if shared_headroom_pool_size and shared_headroom_pool_size != '0': DEFAULT_SHARED_HEADROOM_POOL_ENABLED = True DEFAULT_SHARED_HEADROOM_POOL_SIZE = int(shared_headroom_pool_size) @@ -111,7 +117,8 @@ def detect_default_mtu(duthost, port_to_test): """ global DEFAULT_MTU if not DEFAULT_MTU: - DEFAULT_MTU = duthost.shell('redis-cli -n 4 hget "PORT|{}" mtu'.format(port_to_test))['stdout'] + DEFAULT_MTU = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" mtu'.format(port_to_test))['stdout'] logging.info("Default MTU {}".format(DEFAULT_MTU)) @@ -122,7 +129,8 @@ def get_asic_table_data_from_db(duthost): # Get cell size from state DB # Command: redis-cli -n 6 hget "ASIC_TABLE|MELLANOX-SPECTRUM-2" 'cell_size' asic_keys = duthost.shell('redis-cli -n 6 keys *ASIC_TABLE*')['stdout'] - cell_size = float(duthost.shell('redis-cli -n 6 hget "{}" "cell_size"'.format(asic_keys))['stdout']) + cell_size = float(duthost.shell( + 'redis-cli -n 6 hget "{}" "cell_size"'.format(asic_keys))['stdout']) # Get PIPELINE_LATENCY from state DB # Command: redis-cli -n 6 hget "ASIC_TABLE|MELLANOX-SPECTRUM-2" 'pipeline_latency' @@ -131,10 +139,12 @@ def get_asic_table_data_from_db(duthost): # Get MAC_PHY_DELAY from state DB # Command: redis-cli -n 6 hget "ASIC_TABLE|MELLANOX-SPECTRUM-2" 'mac_phy_delay' - mac_phy_delay = float(duthost.shell('redis-cli -n 6 hget "{}" "mac_phy_delay"'.format(asic_keys))['stdout']) * 1024 + mac_phy_delay = float(duthost.shell( + 'redis-cli -n 6 hget "{}" "mac_phy_delay"'.format(asic_keys))['stdout']) * 1024 return cell_size, pipeline_latency, mac_phy_delay + def detect_asic_table_keys(duthost): """ Get CELL_SIZE, PIPELINE_LATENCY and MAC_PHY_DELAY by function get_asic_table_data_from_db @@ -144,7 +154,8 @@ def detect_asic_table_keys(duthost): global MAC_PHY_DELAY global ASIC_TABLE_KEYS_LOADED - CELL_SIZE, PIPELINE_LATENCY, MAC_PHY_DELAY = get_asic_table_data_from_db(duthost) + CELL_SIZE, PIPELINE_LATENCY, MAC_PHY_DELAY = get_asic_table_data_from_db( + duthost) ASIC_TABLE_KEYS_LOADED = True @@ -155,8 +166,10 @@ def get_lossless_traffic_pattern_data_from_db(duthost): """ # Get LOSSLESS_MTU from config DB # Command: redis-cli -n 4 hget 'LOSSLESS_TRAFFIC_PATTERN|AZURE' 'mtu' - lossless_traffic_keys = duthost.shell('redis-cli -n 4 keys LOSSLESS_TRAFFIC_PATTERN*')['stdout'] - lossless_mtu = float(duthost.shell('redis-cli -n 4 hget "{}" "mtu"'.format(lossless_traffic_keys))['stdout']) + lossless_traffic_keys = duthost.shell( + 'redis-cli -n 4 keys LOSSLESS_TRAFFIC_PATTERN*')['stdout'] + lossless_mtu = float(duthost.shell( + 'redis-cli -n 4 hget "{}" "mtu"'.format(lossless_traffic_keys))['stdout']) # Get SMALL_PACKET_PERCENTAGE from config DB # Command: redis-cli -n 4 hget 'LOSSLESS_TRAFFIC_PATTERN|AZURE' 'small_packet_percentage' @@ -173,7 +186,8 @@ def detect_lossless_traffic_pattern_keys(duthost): global LOSSLESS_MTU global SMALL_PACKET_PERCENTAGE global LOSSLESS_TRAFFIC_PATTERN_KEYS_LOADED - LOSSLESS_MTU, SMALL_PACKET_PERCENTAGE = get_lossless_traffic_pattern_data_from_db(duthost) + LOSSLESS_MTU, SMALL_PACKET_PERCENTAGE = get_lossless_traffic_pattern_data_from_db( + duthost) LOSSLESS_TRAFFIC_PATTERN_KEYS_LOADED = True @@ -188,8 +202,10 @@ def load_lossless_headroom_data(duthost): if not DEFAULT_LOSSLESS_HEADROOM_DATA: dut_hwsku = duthost.facts["hwsku"] dut_platform = duthost.facts["platform"] - skudir = "/usr/share/sonic/device/{}/{}/".format(dut_platform, dut_hwsku) - lines = duthost.shell('cat {}/pg_profile_lookup.ini'.format(skudir))["stdout"] + skudir = "/usr/share/sonic/device/{}/{}/".format( + dut_platform, dut_hwsku) + lines = duthost.shell( + 'cat {}/pg_profile_lookup.ini'.format(skudir))["stdout"] DEFAULT_LOSSLESS_HEADROOM_DATA = {} for line in lines.split('\n'): if line[0] == '#': @@ -202,7 +218,8 @@ def load_lossless_headroom_data(duthost): xoff = tokens[4] if not DEFAULT_LOSSLESS_HEADROOM_DATA.get(speed): DEFAULT_LOSSLESS_HEADROOM_DATA[speed] = {} - DEFAULT_LOSSLESS_HEADROOM_DATA[speed][cable_length] = {'size': size, 'xon': xon, 'xoff': xoff} + DEFAULT_LOSSLESS_HEADROOM_DATA[speed][cable_length] = { + 'size': size, 'xon': xon, 'xoff': xoff} DEFAULT_LOSSLESS_HEADROOM_DATA = DEFAULT_LOSSLESS_HEADROOM_DATA @@ -224,53 +241,70 @@ def load_test_parameters(duthost): param_file_name = "qos/files/dynamic_buffer_param.json" with open(param_file_name) as file: params = json.load(file) - logging.info("Loaded test parameters {} from {}".format(params, param_file_name)) - ASIC_TYPE = duthost.facts['asic_type'] - vendor_specific_param = params[ASIC_TYPE] - DEFAULT_CABLE_LENGTH_LIST = vendor_specific_param['default_cable_length'] - TESTPARAM_HEADROOM_OVERRIDE = vendor_specific_param['headroom-override'] - TESTPARAM_LOSSLESS_PG = vendor_specific_param['lossless_pg'] - TESTPARAM_SHARED_HEADROOM_POOL = vendor_specific_param['shared-headroom-pool'] - TESTPARAM_EXTRA_OVERHEAD = vendor_specific_param['extra_overhead'] - TESTPARAM_ADMIN_DOWN = vendor_specific_param['admin-down'] - MAX_SPEED_8LANE_PORT = vendor_specific_param['max_speed_8lane_platform'].get(duthost.facts['platform']) - - # For ingress profile list, we need to check whether the ingress lossy profile exists - ingress_lossy_pool = duthost.shell('redis-cli -n 4 keys "BUFFER_POOL|ingress_lossy_pool"')['stdout'] - if ingress_lossy_pool: - ingress_profile_list = TESTPARAM_ADMIN_DOWN.get('BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') - ingress_profile_list.append('[BUFFER_PROFILE_TABLE:ingress_lossy_zero_profile]') - - # 'admin-down' section contains references to buffer profiles - # We need to convert the format of the references according to whether table name should be in the reference - if not check_qos_db_fv_reference_with_table(duthost): - expected_pgs = TESTPARAM_ADMIN_DOWN.get('BUFFER_PG_TABLE') - if expected_pgs: - new_pgs = {} - for pg, profile in expected_pgs.items(): - new_pgs[pg] = profile.replace('[BUFFER_PROFILE_TABLE:', '').replace(']', '') - TESTPARAM_ADMIN_DOWN['BUFFER_PG_TABLE'] = new_pgs - - expected_queues = TESTPARAM_ADMIN_DOWN.get('BUFFER_QUEUE_TABLE') - if expected_queues: - new_queues = {} - for queue, profile in expected_queues.items(): - new_queues[queue] = profile.replace('[BUFFER_PROFILE_TABLE:', '').replace(']', '') - TESTPARAM_ADMIN_DOWN['BUFFER_QUEUE_TABLE'] = new_queues - - expected_ingress_profile_list = TESTPARAM_ADMIN_DOWN.get('BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') - if expected_ingress_profile_list: - new_list = [] - for profile in expected_ingress_profile_list: - new_list.append(profile.replace('[BUFFER_PROFILE_TABLE:', '').replace(']', '')) - TESTPARAM_ADMIN_DOWN['BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE'] = new_list - - expected_egress_profile_list = TESTPARAM_ADMIN_DOWN.get('BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE') - if expected_egress_profile_list: - new_list = [] - for profile in expected_egress_profile_list: - new_list.append(profile.replace('[BUFFER_PROFILE_TABLE:', '').replace(']', '')) - TESTPARAM_ADMIN_DOWN['BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE'] = new_list + logging.info("Loaded test parameters {} from {}".format( + params, param_file_name)) + ASIC_TYPE = duthost.facts.get('asic_type') + vendor_specific_param = params.get(ASIC_TYPE) + DEFAULT_CABLE_LENGTH_LIST = vendor_specific_param.get( + 'default_cable_length') + TESTPARAM_HEADROOM_OVERRIDE = vendor_specific_param.get( + 'headroom-override') + TESTPARAM_LOSSLESS_PG = vendor_specific_param.get('lossless_pg') + TESTPARAM_SHARED_HEADROOM_POOL = vendor_specific_param.get( + 'shared-headroom-pool') + TESTPARAM_EXTRA_OVERHEAD = vendor_specific_param.get('extra_overhead') + TESTPARAM_ADMIN_DOWN = vendor_specific_param.get('admin-down') + if 'max_speed_8lane_platform' in vendor_specific_param: + MAX_SPEED_8LANE_PORT = vendor_specific_param['max_speed_8lane_platform'].get( + duthost.facts['platform']) + + if TESTPARAM_ADMIN_DOWN is not None: + # For ingress profile list, we need to check whether the ingress lossy profile exists + ingress_lossy_pool = duthost.shell( + 'redis-cli -n 4 keys "BUFFER_POOL|ingress_lossy_pool"')['stdout'] + if ingress_lossy_pool: + ingress_profile_list = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') + ingress_profile_list.append( + '[BUFFER_PROFILE_TABLE:ingress_lossy_zero_profile]') + + # 'admin-down' section contains references to buffer profiles + # We need to convert the format of the references according to whether table name should be in the reference + if not check_qos_db_fv_reference_with_table(duthost): + expected_pgs = TESTPARAM_ADMIN_DOWN.get('BUFFER_PG_TABLE') + if expected_pgs: + new_pgs = {} + for pg, profile in expected_pgs.items(): + new_pgs[pg] = profile.replace( + '[BUFFER_PROFILE_TABLE:', '').replace(']', '') + TESTPARAM_ADMIN_DOWN['BUFFER_PG_TABLE'] = new_pgs + + expected_queues = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_QUEUE_TABLE') + if expected_queues: + new_queues = {} + for queue, profile in expected_queues.items(): + new_queues[queue] = profile.replace( + '[BUFFER_PROFILE_TABLE:', '').replace(']', '') + TESTPARAM_ADMIN_DOWN['BUFFER_QUEUE_TABLE'] = new_queues + + expected_ingress_profile_list = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') + if expected_ingress_profile_list: + new_list = [] + for profile in expected_ingress_profile_list: + new_list.append(profile.replace( + '[BUFFER_PROFILE_TABLE:', '').replace(']', '')) + TESTPARAM_ADMIN_DOWN['BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE'] = new_list + + expected_egress_profile_list = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE') + if expected_egress_profile_list: + new_list = [] + for profile in expected_egress_profile_list: + new_list.append(profile.replace( + '[BUFFER_PROFILE_TABLE:', '').replace(']', '')) + TESTPARAM_ADMIN_DOWN['BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE'] = new_list def configure_shared_headroom_pool(duthost, enable): @@ -281,9 +315,11 @@ def configure_shared_headroom_pool(duthost, enable): enable: True to enable and false to disable the shared headroom pool """ if enable: - duthost.shell("config buffer shared-headroom-pool over-subscribe-ratio 2") + duthost.shell( + "config buffer shared-headroom-pool over-subscribe-ratio 2") else: - duthost.shell("config buffer shared-headroom-pool over-subscribe-ratio 0") + duthost.shell( + "config buffer shared-headroom-pool over-subscribe-ratio 0") time.sleep(20) @@ -300,7 +336,7 @@ def setup_module(duthosts, rand_one_dut_hostname, request): duthost = duthosts[rand_one_dut_hostname] detect_buffer_model(duthost) - if not is_mellanox_device(duthost) and not is_innovium_device(duthost): + if not is_mellanox_device(duthost) and not is_innovium_device(duthost) and not is_barefoot_device(duthost): load_lossless_headroom_data(duthost) yield return @@ -314,13 +350,16 @@ def setup_module(duthosts, rand_one_dut_hostname, request): # which in turn significantly slows down the process in orchagent and makes many checks timeout. # As the buffer test has already taken ~30 minutes, we don't want to extend the wait time. # So disabling BGP neighbors is a reasonal way to tolerance this situation. - bgp_neighbors = duthost.shell('redis-cli -n 4 keys BGP_NEIGHBOR*')['stdout'] + bgp_neighbors = duthost.shell( + 'redis-cli -n 4 keys BGP_NEIGHBOR*')['stdout'] if bgp_neighbors: duthost.shell('config bgp shutdown all') - logging.info("Shutting down BGP neighbors and waiting for all routing entries withdrawn") + logging.info( + "Shutting down BGP neighbors and waiting for all routing entries withdrawn") time.sleep(60) - enable_shared_headroom_pool = request.config.getoption("--enable_shared_headroom_pool") + enable_shared_headroom_pool = request.config.getoption( + "--enable_shared_headroom_pool") need_to_disable_shared_headroom_pool_after_test = False if BUFFER_MODEL_DYNAMIC: detect_ingress_pool_number(duthost) @@ -330,19 +369,24 @@ def setup_module(duthosts, rand_one_dut_hostname, request): load_lossless_headroom_data(duthost) load_test_parameters(duthost) - logging.info("Cable length: default {}".format(DEFAULT_CABLE_LENGTH_LIST)) - logging.info("Ingress pool number {}".format(DEFAULT_INGRESS_POOL_NUMBER)) - logging.info("Lossless headroom data {}".format(DEFAULT_LOSSLESS_HEADROOM_DATA)) + logging.info("Cable length: default {}".format( + DEFAULT_CABLE_LENGTH_LIST)) + logging.info("Ingress pool number {}".format( + DEFAULT_INGRESS_POOL_NUMBER)) + logging.info("Lossless headroom data {}".format( + DEFAULT_LOSSLESS_HEADROOM_DATA)) if enable_shared_headroom_pool and not DEFAULT_SHARED_HEADROOM_POOL_ENABLED: configure_shared_headroom_pool(duthost, True) DEFAULT_SHARED_HEADROOM_POOL_ENABLED = True DEFAULT_OVER_SUBSCRIBE_RATIO = 2 - logging.info("Shared headroom pool enabled according to test option") + logging.info( + "Shared headroom pool enabled according to test option") need_to_disable_shared_headroom_pool_after_test = True else: load_lossless_headroom_data(duthost) - logging.info("Lossless headroom data {}".format(DEFAULT_LOSSLESS_HEADROOM_DATA)) + logging.info("Lossless headroom data {}".format( + DEFAULT_LOSSLESS_HEADROOM_DATA)) yield @@ -413,18 +457,22 @@ def _fetch_size_difference_for_8lane_ports(duthost, conn_graph_facts): hostname = conn_graph_facts['device_conn'].keys()[0] ports_info = conn_graph_facts['device_conn'][hostname] if not ports_info: - ports = [port.split('|')[1] for port in duthost.shell('redis-cli -n 4 keys "PORT|*"')['stdout'].split('\n')] + ports = [port.split('|')[1] for port in duthost.shell( + 'redis-cli -n 4 keys "PORT|*"')['stdout'].split('\n')] else: ports = ports_info.keys() if PORTS_WITH_8LANES is None: PORTS_WITH_8LANES = [] for port in ports: - lanes = duthost.shell('redis-cli -n 4 hget "PORT|{}" lanes'.format(port))['stdout'] + lanes = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" lanes'.format(port))['stdout'] if len(lanes.split(',')) == 8: PORTS_WITH_8LANES.append(port) - lossless_pgs = duthost.shell('redis-cli keys "BUFFER_PG_TABLE:Ethernet*:3-4"')['stdout'].split() - lossless_pgs_8lane = [pg for pg in lossless_pgs if pg[16:-4] in PORTS_WITH_8LANES] + lossless_pgs = duthost.shell( + 'redis-cli keys "BUFFER_PG_TABLE:Ethernet*:3-4"')['stdout'].split() + lossless_pgs_8lane = [ + pg for pg in lossless_pgs if pg[16:-4] in PORTS_WITH_8LANES] return len(lossless_pgs_8lane) * 2 * 9216 logging.debug("Kwargs {}".format(kwargs)) @@ -439,13 +487,17 @@ def _fetch_size_difference_for_8lane_ports(duthost, conn_graph_facts): original_memory = curr_pool_size * DEFAULT_INGRESS_POOL_NUMBER + curr_shp_size if new_ratio == 0: expected_shp_size = 0 - expected_pool_size = (original_memory - curr_shp_size * old_ratio) + expected_pool_size = ( + original_memory - curr_shp_size * old_ratio) if old_ratio != 0: - expected_pool_size = expected_pool_size - _fetch_size_difference_for_8lane_ports(duthost, conn_graph_facts) + expected_pool_size = expected_pool_size - \ + _fetch_size_difference_for_8lane_ports( + duthost, conn_graph_facts) expected_pool_size = expected_pool_size / DEFAULT_INGRESS_POOL_NUMBER else: expected_shp_size = curr_shp_size * old_ratio / new_ratio - expected_pool_size = (original_memory - expected_shp_size) / DEFAULT_INGRESS_POOL_NUMBER + expected_pool_size = ( + original_memory - expected_shp_size) / DEFAULT_INGRESS_POOL_NUMBER elif kwargs.get("config_shp_size"): expected_shp_size = int(kwargs.get("config_shp_size")) expected_pool_size = None @@ -481,10 +533,12 @@ def _fetch_size_difference_for_8lane_ports(duthost, conn_graph_facts): else: adjust_extra_overhead = 0 - original_memory = curr_pool_size * DEFAULT_INGRESS_POOL_NUMBER + old_size * old_pg_number + adjust_extra_overhead + original_memory = curr_pool_size * DEFAULT_INGRESS_POOL_NUMBER + \ + old_size * old_pg_number + adjust_extra_overhead if DEFAULT_OVER_SUBSCRIBE_RATIO: - private_headroom_str = TESTPARAM_SHARED_HEADROOM_POOL.get("private_pg_headroom") + private_headroom_str = TESTPARAM_SHARED_HEADROOM_POOL.get( + "private_pg_headroom") if private_headroom_str: private_headroom_number = int(private_headroom_str) else: @@ -512,41 +566,55 @@ def _fetch_size_difference_for_8lane_ports(duthost, conn_graph_facts): expected_shp_size = None curr_shp_size = None - expected_pool_size = (original_memory - new_reserved) / DEFAULT_INGRESS_POOL_NUMBER + expected_pool_size = ( + original_memory - new_reserved) / DEFAULT_INGRESS_POOL_NUMBER - logging.debug("Expected pool {}, expec shp {}, curr_shp {} default ovs {}".format(expected_pool_size, expected_shp_size, curr_shp_size, DEFAULT_OVER_SUBSCRIBE_RATIO)) + logging.debug("Expected pool {}, expec shp {}, curr_shp {} default ovs {}".format( + expected_pool_size, expected_shp_size, curr_shp_size, DEFAULT_OVER_SUBSCRIBE_RATIO)) + + elif duthost.facts['asic_type'] == 'barefoot': + expected_pool_size = 43067728 + expected_shp_size = 3153920 pytest_assert(ensure_pool_size(duthost, 20, expected_pool_size, expected_shp_size, ingress_lossless_pool_oid), "Pool size isn't correct in database: expected pool {} shp {}, size in APPL_DB pool {} shp {}, size in ASIC_DB {}".format( expected_pool_size, expected_shp_size, - duthost.shell('redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" size')['stdout'], - duthost.shell('redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" xoff')['stdout'], + duthost.shell( + 'redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" size')['stdout'], + duthost.shell( + 'redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" xoff')['stdout'], get_pool_size_from_asic_db(duthost, ingress_lossless_pool_oid)) if DEFAULT_OVER_SUBSCRIBE_RATIO else "Pool size isn't correct in database: expected {}, size in APPL_DB pool {}, size in ASIC_DB {}".format( expected_pool_size, - duthost.shell('redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" size')['stdout'], + duthost.shell( + 'redis-cli hget "BUFFER_POOL_TABLE:ingress_lossless_pool" size')['stdout'], get_pool_size_from_asic_db(duthost, ingress_lossless_pool_oid)) ) def get_pool_size_from_asic_db(duthost, ingress_lossless_pool_oid): - pool_sai = _compose_dict_from_cli(duthost.shell('redis-cli -n 1 hgetall ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL:{}'.format(ingress_lossless_pool_oid))['stdout'].split('\n')) + pool_sai = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 1 hgetall ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_POOL:{}'.format(ingress_lossless_pool_oid))['stdout'].split('\n')) return pool_sai.get('SAI_BUFFER_POOL_ATTR_SIZE'), pool_sai.get('SAI_BUFFER_POOL_ATTR_XOFF_SIZE') def ensure_pool_size(duthost, timeout, expected_pool_size, expected_shp_size, ingress_lossless_pool_oid=None): - """Make sure the size of the buffer pool and shared headroom pool is as expected within a given time in APPL_DB and ASIC_DB (optional) + """ + Make sure the size of the buffer pool and shared headroom pool is as expected within a given time in APPL_DB and + ASIC_DB (optional) Args: timeout: The time out value expected_pool_size: The expected shared buffer pool size expected_shp_size: The expected shared headroom pool size - ingress_lossless_pool_oid: The SAI OID of ingress lossless buffer pool. If it is omitted, the ASIC DB won't be checked + ingress_lossless_pool_oid: The SAI OID of ingress lossless buffer pool. If it is omitted, the ASIC DB won't be + checked """ def _ensure_pool_size(duthost, expected_pool_size, expected_shp_size, ingress_lossless_pool_oid=None): - pool_app =_compose_dict_from_cli(duthost.shell('redis-cli hgetall "BUFFER_POOL_TABLE:ingress_lossless_pool"')['stdout'].split('\n')) + pool_app = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall "BUFFER_POOL_TABLE:ingress_lossless_pool"')['stdout'].split('\n')) if expected_pool_size and int(pool_app['size']) != expected_pool_size: return False @@ -555,7 +623,8 @@ def _ensure_pool_size(duthost, expected_pool_size, expected_shp_size, ingress_lo return False if ingress_lossless_pool_oid: - pool_size, shp_size = get_pool_size_from_asic_db(duthost, ingress_lossless_pool_oid) + pool_size, shp_size = get_pool_size_from_asic_db( + duthost, ingress_lossless_pool_oid) if expected_pool_size and int(pool_size) != expected_pool_size: return False @@ -569,11 +638,14 @@ def _ensure_pool_size(duthost, expected_pool_size, expected_shp_size, ingress_lo else: delay = 1 - return wait_until(timeout, delay, 0, _ensure_pool_size, duthost, expected_pool_size, expected_shp_size, ingress_lossless_pool_oid) + return wait_until(timeout, delay, 0, _ensure_pool_size, duthost, expected_pool_size, expected_shp_size, + ingress_lossless_pool_oid) def check_pg_profile(duthost, pg, expected_profile, fail_test=True): - """Check whether the profile in BUFFER_PG match the expected value in a wait_until loop with maximum timeout as 10 seconds + """ + Check whether the profile in BUFFER_PG match the expected value in a wait_until loop with maximum timeout as 10 + seconds Args: pg: The key of buffer pg in BUFFER_PG table. Format: BUFFER_PG|| @@ -584,31 +656,36 @@ def check_pg_profile(duthost, pg, expected_profile, fail_test=True): Whether the expected profile has been found within given time """ def _check_pg_profile(duthost, pg, expected_profile): - if check_qos_db_fv_reference_with_table(duthost) == True: - profile = duthost.shell('redis-cli hget {} profile'.format(pg))['stdout'][1:-1] + if check_qos_db_fv_reference_with_table(duthost): + profile = duthost.shell( + 'redis-cli hget {} profile'.format(pg))['stdout'][1:-1] return (profile == 'BUFFER_PROFILE_TABLE:' + expected_profile) else: - profile = duthost.shell('redis-cli hget {} profile'.format(pg))['stdout'] + profile = duthost.shell( + 'redis-cli hget {} profile'.format(pg))['stdout'] return (profile == expected_profile) if wait_until(10, 2, 0, _check_pg_profile, duthost, pg, expected_profile): return True else: if fail_test: - pytest_assert(False, "Profile in PG {} isn't {}".format(pg, expected_profile)) + pytest_assert(False, "Profile in PG {} isn't {}".format( + pg, expected_profile)) else: return False def check_pfc_enable(duthost, port, expected_pfc_enable_map): - """Check whether the pfc_enable map in port table is correct in a wait_until loop with maximum timeout as 10 seconds + """ + Check whether the pfc_enable map in port table is correct in a wait_until loop with maximum timeoutas 10 seconds Args: port: The port to be checked expected_pfc_enable_map: The expected pfc_enable map """ def _check_pfc_enable(duthost, port, expected_pfc_enable_map): - pfc_enable = duthost.shell('redis-cli -n 4 hget "PORT_QOS_MAP|{}" pfc_enable'.format(port))['stdout'] + pfc_enable = duthost.shell( + 'redis-cli -n 4 hget "PORT_QOS_MAP|{}" pfc_enable'.format(port))['stdout'] return (expected_pfc_enable_map == pfc_enable) pytest_assert(wait_until(10, 2, 0, _check_pfc_enable, duthost, port, expected_pfc_enable_map), @@ -626,18 +703,26 @@ def check_lossless_profile_removed(duthost, profile, sai_oid=None): sai_oid: The SAI OID in ASIC_DB of the buffer profile If it is None the ASIC_DB won't be checked """ - profile_info = duthost.shell('redis-cli -n 6 hgetall "BUFFER_PROFILE_TABLE|{}"'.format(profile))['stdout'] - pytest_assert(not profile_info, "Profile {} isn't removed from STATE_DB".format(profile)) - profile_info = duthost.shell('redis-cli hgetall "BUFFER_PROFILE_TABLE:{}"'.format(profile))['stdout'] - pytest_assert(not profile_info, "Profile {} isn't removed from APPL_DB".format(profile)) - logging.debug('Profile {} has been removed from STATE_DB and APPL_DB'.format(profile)) + profile_info = duthost.shell( + 'redis-cli -n 6 hgetall "BUFFER_PROFILE_TABLE|{}"'.format(profile))['stdout'] + pytest_assert(not profile_info, + "Profile {} isn't removed from STATE_DB".format(profile)) + profile_info = duthost.shell( + 'redis-cli hgetall "BUFFER_PROFILE_TABLE:{}"'.format(profile))['stdout'] + pytest_assert(not profile_info, + "Profile {} isn't removed from APPL_DB".format(profile)) + logging.debug( + 'Profile {} has been removed from STATE_DB and APPL_DB'.format(profile)) if sai_oid: - profile_info = duthost.shell('redis-cli -n 1 hgetall {}'.format(sai_oid))['stdout'] - pytest_assert(not profile_info, "Profile {} hasn't been removed from ASIC_DB".format(sai_oid)) + profile_info = duthost.shell( + 'redis-cli -n 1 hgetall {}'.format(sai_oid))['stdout'] + pytest_assert( + not profile_info, "Profile {} hasn't been removed from ASIC_DB".format(sai_oid)) def fetch_initial_asic_db(duthost): - profiles_in_asicdb = duthost.shell('redis-cli -n 1 keys "ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE*"')['stdout'] + profiles_in_asicdb = duthost.shell( + 'redis-cli -n 1 keys "ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE*"')['stdout'] return set(profiles_in_asicdb.split('\n')) @@ -665,14 +750,16 @@ def check_buffer_profile_details(duthost, initial_profiles, profile_name, profil profile_oid: SAI OID of the profile pool_oid: SAI OID of ingress lossless pool """ - profile_appldb = _compose_dict_from_cli(duthost.shell('redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(profile_name))['stdout'].split('\n')) - logging.debug("APPL_DB buffer profile {}: {} ".format(profile_name, profile_appldb)) + profile_appldb = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(profile_name))['stdout'].split('\n')) + logging.debug("APPL_DB buffer profile {}: {} ".format( + profile_name, profile_appldb)) # Check the profile against the standard value m = re.search(LOSSLESS_PROFILE_PATTERN, profile_name) if m: # This means it's a dynamic profile - if check_qos_db_fv_reference_with_table(duthost) == True: + if check_qos_db_fv_reference_with_table(duthost): # SONiC version is 202106 and before, compare with standard profile in pg_profile_lookup table speed = m.group(1) cable_length = m.group(2) @@ -680,10 +767,14 @@ def check_buffer_profile_details(duthost, initial_profiles, profile_name, profil if std_profiles_for_speed: std_profile = std_profiles_for_speed.get(cable_length) if std_profile: - # This means it's a profile with std speed and cable length. We can check whether the headroom data is correct - pytest_assert(profile_appldb['xon'] == std_profile['xon'] and profile_appldb['xoff'] == std_profile['xoff'] - and (profile_appldb['size'] == std_profile['size'] or DEFAULT_SHARED_HEADROOM_POOL_ENABLED), - "Generated profile {} doesn't match the std profile {}".format(profile_appldb, std_profile)) + # This means it's a profile with std speed and cable length. We can check whether the headroom + # data is correct + pytest_assert(profile_appldb['xon'] == std_profile['xon'] and + profile_appldb['xoff'] == std_profile['xoff'] and + (profile_appldb['size'] == std_profile['size'] or + DEFAULT_SHARED_HEADROOM_POOL_ENABLED), + "Generated profile {} doesn't match the std profile {}".format(profile_appldb, + std_profile)) else: for std_cable_len, std_profile in std_profiles_for_speed.items(): if int(std_cable_len[:-1]) > int(cable_length[:-1]): @@ -693,32 +784,43 @@ def check_buffer_profile_details(duthost, initial_profiles, profile_name, profil pytest_assert(int(std_profile['xoff']) <= int(profile_appldb['xoff']), "XOFF of generated profile {} is less than standard profile {} while its cable length is greater".format(profile_appldb, std_profile)) else: - logging.info("Skip headroom checking because headroom information is not provided for speed {}".format(speed)) + logging.info( + "Skip headroom checking because headroom information is not provided for speed {}".format(speed)) else: # SONiC version is after 202106, compare with the returned value from function calculate_headroom_data - ret, head_room_data = calculate_headroom_data(duthost, port_to_test) + ret, head_room_data = calculate_headroom_data( + duthost, port_to_test) if ret: - # This means it's a profile with std speed and cable length. We can check whether the headroom data is correct - pytest_assert(int(profile_appldb['xon']) == head_room_data['xon'] and int(profile_appldb['xoff']) == head_room_data['xoff'] - and (int(profile_appldb['size']) == head_room_data['size'] or DEFAULT_SHARED_HEADROOM_POOL_ENABLED), - "Generated profile {} doesn't match the std profile {}".format(profile_appldb, head_room_data)) + # This means it's a profile with std speed and cable length. We can check whether the headroom data is + # correct + pytest_assert(int(profile_appldb['xon']) == head_room_data['xon'] and + int(profile_appldb['xoff']) == head_room_data['xoff'] and + (int(profile_appldb['size']) == head_room_data['size'] or + DEFAULT_SHARED_HEADROOM_POOL_ENABLED), + "Generated profile {} doesn't match the std profile {}".format(profile_appldb, + head_room_data)) else: - logging.info("Skip headroom checking because headroom information is not able to be calculated for speed {}".format(speed)) + logging.info( + "Skip headroom checking because headroom information is not able to be calculated for speed {}".format(speed)) - profiles_in_asicdb = set(duthost.shell('redis-cli -n 1 keys "ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE*"')['stdout'].split('\n')) + profiles_in_asicdb = set(duthost.shell( + 'redis-cli -n 1 keys "ASIC_STATE:SAI_OBJECT_TYPE_BUFFER_PROFILE*"')['stdout'].split('\n')) diff = profiles_in_asicdb - initial_profiles if len(diff) == 1: profile_oid = diff.pop() pytest_assert(profile_oid, "Unable to fetch SAI OID for profile {}, initial SAI OID set {} current set {}".format( profile_name, initial_profiles, profiles_in_asicdb)) - logging.debug("Initial profiles {} and current profiles {} have the following difference(s) {}".format(initial_profiles, profiles_in_asicdb, diff)) + logging.debug("Initial profiles {} and current profiles {} have the following difference(s) {}".format( + initial_profiles, profiles_in_asicdb, diff)) - profile_sai = _compose_dict_from_cli(duthost.shell('redis-cli -n 1 hgetall {}'.format(profile_oid))['stdout'].split('\n')) + profile_sai = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 1 hgetall {}'.format(profile_oid))['stdout'].split('\n')) - logging.debug("SAI object for new profile {}: oid {} content {}".format(profile_name, profile_oid, profile_sai)) + logging.debug("SAI object for new profile {}: oid {} content {}".format( + profile_name, profile_oid, profile_sai)) - if pool_oid == None: + if pool_oid is None: pool_oid = profile_sai['SAI_BUFFER_PROFILE_ATTR_POOL_ID'] if profile_appldb.get('dynamic_th'): sai_threshold_value = profile_appldb['dynamic_th'] @@ -819,7 +921,6 @@ def port_to_test(request, duthost): dutLagInterfaces = [] mgFacts = duthost.minigraph_facts(host=duthost.hostname)['ansible_facts'] - ports = mgFacts['minigraph_ports'].keys() for _, lag in mgFacts["minigraph_portchannels"].items(): dutLagInterfaces += lag["members"] @@ -831,14 +932,17 @@ def port_to_test(request, duthost): PORT_TO_TEST = request.config.getoption("--port_to_test") if PORT_TO_TEST in lagMembers: - logging.info("LAG member port {} can not be used for dynamic buffer test".format(PORT_TO_TEST)) + logging.info( + "LAG member port {} can not be used for dynamic buffer test".format(PORT_TO_TEST)) PORT_TO_TEST = None if not PORT_TO_TEST: PORT_TO_TEST = list(testPort)[0] - lanes = duthost.shell('redis-cli -n 4 hget "PORT|{}" lanes'.format(PORT_TO_TEST))['stdout'] + lanes = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" lanes'.format(PORT_TO_TEST))['stdout'] NUMBER_OF_LANES = len(lanes.split(',')) - logging.info("Port to test {}, number of lanes {}".format(PORT_TO_TEST, NUMBER_OF_LANES)) + logging.info("Port to test {}, number of lanes {}".format( + PORT_TO_TEST, NUMBER_OF_LANES)) return PORT_TO_TEST @@ -859,7 +963,8 @@ def pg_to_test(request): def test_change_speed_cable(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_test, speed_to_test, mtu_to_test, cable_len_to_test): """The testcase for changing the speed and cable length of a port - Change the variables of the port, including speed, mtu and cable length, in different ways and observe whether the DUT behaves correctly + Change the variables of the port, including speed, mtu and cable length, in different ways and observe whether + the DUT behaves correctly. For any of the variable, if it matches the current port configuration, we will skip configuring it. If all of the speed_to_test, mtu_to_test and cable_len_to_test match the current value, the test will be skipped @@ -867,19 +972,24 @@ def test_change_speed_cable(duthosts, rand_one_dut_hostname, conn_graph_facts, p 1. Update the port configuration according to input parameters 2. Determine whether the profile removing behavior can be verified: If neither mtu nor cable length is default value, they will be applied on the port_to_test only, - and the generated profile will be removed after the configuration change because the profile is referenced by this port only. + and the generated profile will be removed after the configuration change because the profile is referenced + by this port only. For example: - The mtu_to_test 1500 only applied on the port_to_test, thus the *_mtu1500_* profile is referenced by the port only + The mtu_to_test 1500 only applied on the port_to_test, thus the *_mtu1500_* profile is referenced by the + port only. The *_mtu1500_* mtu will be removed after the mtu of the port is updated to default value. - In this case, we are able to verify whether the buffer profile is removed after mtu reverted or all PGs are removed. - Other the other hand, if the mtu is 9100, the buffer profile can be referenced by many other ports and it's less possible for us to verify the removing behavior. + In this case, we are able to verify whether the buffer profile is removed after mtu reverted or all PGs + are removed. + On the other hand, if the mtu is 9100, the buffer profile can be referenced by many other ports and it's + less possible for us to verify the removing behavior. We will remove and readd an extra PG 6 to verify the removing behavior as well. 3. Each time the port configuration updated, the following items will be checked as much as possible: - Whether the new profile is generated in APPL_DB, STATE_DB and ASIC_DB. - Whether the pool size is updated in APPL_DB and ASIC_DB. 4. Each time the PG on a port is added or removed, the following items will be checked: - Whether the profile referenced by PGs is as expected according to the port configuration. - - Whether the profile is removed if all PGs are removed and we are able to check removing behavior (result of step 2). + - Whether the profile is removed if all PGs are removed and we are able to check removing behavior (result + of step 2). - Whether the pfc_enable filed of the port has been updated accordingly. Args: @@ -891,23 +1001,33 @@ def test_change_speed_cable(duthosts, rand_one_dut_hostname, conn_graph_facts, p skip_traditional_model() duthost = duthosts[rand_one_dut_hostname] - supported_speeds = duthost.shell('redis-cli -n 6 hget "PORT_TABLE|{}" supported_speeds'.format(port_to_test))['stdout'] + supported_speeds = duthost.shell( + 'redis-cli -n 6 hget "PORT_TABLE|{}" supported_speeds'.format(port_to_test))['stdout'] if supported_speeds and speed_to_test not in supported_speeds: pytest.skip('Speed is not supported by the port, skip') - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + original_cable_len = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - if check_qos_db_fv_reference_with_table(duthost) == True: - profile = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] + if check_qos_db_fv_reference_with_table(duthost): + profile = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] else: - profile = "BUFFER_PROFILE_TABLE:" + duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] + profile = "BUFFER_PROFILE_TABLE:" + \ + duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] detect_default_mtu(duthost, port_to_test) - original_pg_size = int(duthost.shell('redis-cli hget "{}" size'.format(profile))['stdout']) - original_pool_size = int(duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout']) + original_pg_size = int(duthost.shell( + 'redis-cli hget "{}" size'.format(profile))['stdout']) + original_pool_size = int(duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout']) if DEFAULT_OVER_SUBSCRIBE_RATIO: - original_pg_xoff = int(duthost.shell('redis-cli hget "{}" xoff'.format(profile))['stdout']) - original_shp_size = int(duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) + original_pg_xoff = int(duthost.shell( + 'redis-cli hget "{}" xoff'.format(profile))['stdout']) + original_shp_size = int(duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) else: original_pg_xoff = None original_shp_size = None @@ -916,179 +1036,228 @@ def test_change_speed_cable(duthosts, rand_one_dut_hostname, conn_graph_facts, p if mtu_to_test == DEFAULT_MTU: if speed_to_test == original_speed and cable_len_to_test == original_cable_len: - pytest.skip('Speed, MTU and cable length matches the default value, nothing to test, skip') - expected_profile = make_expected_profile_name(speed_to_test, cable_len_to_test) - if duthost.shell('redis-cli hget BUFFER_PROFILE_TABLE:{}'.format(expected_profile))['stdout']: - pytest.skip('The buffer profile has existed, most of the checks can not be performed, skip') + pytest.skip( + 'Speed, MTU and cable length matches the default value, nothing to test, skip') + expected_profile = make_expected_profile_name( + speed_to_test, cable_len_to_test) + if duthost.shell('redis-cli keys BUFFER_PROFILE_TABLE:{}'.format(expected_profile))['stdout'] != '': + pytest.skip( + 'The buffer profile has existed, most of the checks can not be performed, skip') try: if not speed_to_test == original_speed: logging.info("Changing port's speed to {}".format(speed_to_test)) - duthost.shell('config interface speed {} {}'.format(port_to_test, speed_to_test)) + duthost.shell('config interface speed {} {}'.format( + port_to_test, speed_to_test)) if not mtu_to_test == DEFAULT_MTU: logging.info("Changing port's mtu to {}".format(mtu_to_test)) - duthost.shell('config interface mtu {} {}'.format(port_to_test, mtu_to_test)) + duthost.shell('config interface mtu {} {}'.format( + port_to_test, mtu_to_test)) if not cable_len_to_test == original_cable_len: - logging.info("Changing port's cable length to {}".format(cable_len_to_test)) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, cable_len_to_test)) + logging.info( + "Changing port's cable length to {}".format(cable_len_to_test)) + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, cable_len_to_test)) check_profile_removed = cable_len_to_test not in DEFAULT_CABLE_LENGTH_LIST # Check whether profile is correct in PG table if mtu_to_test != DEFAULT_MTU: - expected_profile = make_expected_profile_name(speed_to_test, cable_len_to_test, other_factors=['mtu{}'.format(mtu_to_test)]) + expected_profile = make_expected_profile_name( + speed_to_test, cable_len_to_test, other_factors=['mtu{}'.format(mtu_to_test)]) check_profile_removed = True else: - expected_profile = make_expected_profile_name(speed_to_test, cable_len_to_test) + expected_profile = make_expected_profile_name( + speed_to_test, cable_len_to_test) - logging.info('[Speed and/or cable-len and/or MTU updated] Checking whether new profile {} has been created and pfc_enable has been updated'.format(expected_profile)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + logging.info( + '[Speed and/or cable-len and/or MTU updated] Checking whether new profile {} has been created and pfc_enable has been updated'.format(expected_profile)) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) check_pfc_enable(duthost, port_to_test, '3,4') - profile_oid, pool_oid = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) - logging.info('SAI OID for newly created profile {} ingress lossless pool {}'.format(profile_oid, pool_oid)) + profile_oid, pool_oid = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) + logging.info('SAI OID for newly created profile {} ingress lossless pool {}'.format( + profile_oid, pool_oid)) # Check whether profile exist - pg_size = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" size'.format(expected_profile))['stdout']) - pg_xoff = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" xoff'.format(expected_profile))['stdout']) if DEFAULT_OVER_SUBSCRIBE_RATIO else None + pg_size = int(duthost.shell( + 'redis-cli hget "BUFFER_PROFILE_TABLE:{}" size'.format(expected_profile))['stdout']) + pg_xoff = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" xoff'.format( + expected_profile))['stdout']) if DEFAULT_OVER_SUBSCRIBE_RATIO else None check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = pg_xoff, - old_size = original_pg_size, - new_size = pg_size) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=pg_xoff, + old_size=original_pg_size, + new_size=pg_size) # Remove all the lossless profile on the port - logging.info('[Remove all lossless PGs] Checking pool size and pfc_enable') - duthost.shell('config interface buffer priority-group lossless remove {} 3-4'.format(port_to_test)) + logging.info( + '[Remove all lossless PGs] Checking pool size and pfc_enable') + duthost.shell( + 'config interface buffer priority-group lossless remove {} 3-4'.format(port_to_test)) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size, - new_pg_number = 0) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size, + new_pg_number=0) check_pfc_enable(duthost, port_to_test, '') if check_profile_removed: - logging.info('[Remove dynamic profile on PG removed] Checking whether the profile {} is removed on receiving all lossless PG removed'.format(expected_profile)) - check_lossless_profile_removed(duthost, expected_profile, profile_oid) + logging.info('[Remove dynamic profile on PG removed] Checking whether the profile {} is removed on receiving all lossless PG removed'.format( + expected_profile)) + check_lossless_profile_removed( + duthost, expected_profile, profile_oid) # Re-add another lossless priority - logging.info('Re-add a lossless_pg and check pool size and pfc_enable') - duthost.shell('config interface buffer priority-group lossless add {} 6'.format(port_to_test)) + logging.info( + 'Re-add a lossless_pg and check pool size and pfc_enable') + duthost.shell( + 'config interface buffer priority-group lossless add {} 6'.format(port_to_test)) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = pg_xoff, - old_size = original_pg_size, - new_size = pg_size, - new_pg_number = 1) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=pg_xoff, + old_size=original_pg_size, + new_size=pg_size, + new_pg_number=1) check_pfc_enable(duthost, port_to_test, '6') - profile_oid, _ = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, None, pool_oid, port_to_test) + profile_oid, _ = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, None, pool_oid, port_to_test) if cable_len_to_test != original_cable_len: - logging.info('[Revert the cable length to the default value] Checking whether the profile is updated') - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len)) + logging.info( + '[Revert the cable length to the default value] Checking whether the profile is updated') + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, original_cable_len)) if mtu_to_test != DEFAULT_MTU: - logging.info('[Revert the mtu to the default value] Checking whether the profile is updated') - duthost.shell('config interface mtu {} {}'.format(port_to_test, DEFAULT_MTU)) + logging.info( + '[Revert the mtu to the default value] Checking whether the profile is updated') + duthost.shell('config interface mtu {} {}'.format( + port_to_test, DEFAULT_MTU)) # Remove old profile on cable length change - logging.info('[Remove dynamic profile on cable length and/or MTU updated] Checking whether the old profile is removed') - check_lossless_profile_removed(duthost, expected_profile, profile_oid) - expected_profile = make_expected_profile_name(speed_to_test, original_cable_len) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format(port_to_test), expected_profile) - - pg_size = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" size'.format(expected_profile))['stdout']) - pg_xoff = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" xoff'.format(expected_profile))['stdout']) if DEFAULT_OVER_SUBSCRIBE_RATIO else None + logging.info( + '[Remove dynamic profile on cable length and/or MTU updated] Checking whether the old profile is removed') + check_lossless_profile_removed( + duthost, expected_profile, profile_oid) + expected_profile = make_expected_profile_name( + speed_to_test, original_cable_len) + check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format( + port_to_test), expected_profile) + + pg_size = int(duthost.shell( + 'redis-cli hget "BUFFER_PROFILE_TABLE:{}" size'.format(expected_profile))['stdout']) + pg_xoff = int(duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:{}" xoff'.format( + expected_profile))['stdout']) if DEFAULT_OVER_SUBSCRIBE_RATIO else None check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = pg_xoff, - old_size = original_pg_size, - new_size = pg_size, - new_pg_number = 1) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=pg_xoff, + old_size=original_pg_size, + new_size=pg_size, + new_pg_number=1) - duthost.shell('config interface buffer priority-group lossless remove {} 6'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless remove {} 6'.format(port_to_test)) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = pg_xoff, - old_size = original_pg_size, - new_pg_number = 0) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=pg_xoff, + old_size=original_pg_size, + new_pg_number=0) check_pfc_enable(duthost, port_to_test, '') else: if cable_len_to_test != original_cable_len: - logging.info('[Update cable length without any lossless pg configured]') - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len)) + logging.info( + '[Update cable length without any lossless pg configured]') + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, original_cable_len)) if mtu_to_test != DEFAULT_MTU: logging.info('[Update mtu without any lossless pg configured]') - duthost.shell('config interface mtu {} {}'.format(port_to_test, DEFAULT_MTU)) + duthost.shell('config interface mtu {} {}'.format( + port_to_test, DEFAULT_MTU)) if speed_to_test != original_speed: logging.info('[Update speed without any lossless pg configured]') - duthost.shell('config interface speed {} {}'.format(port_to_test, original_speed)) + duthost.shell('config interface speed {} {}'.format( + port_to_test, original_speed)) logging.info('[Add lossless pg with speed and cable length ready]') - duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless add {} 3-4'.format(port_to_test)) - expected_profile = make_expected_profile_name(original_speed, original_cable_len) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + expected_profile = make_expected_profile_name( + original_speed, original_cable_len) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) check_pfc_enable(duthost, port_to_test, '3,4') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size) logging.info('[Extra lossless PG]') - duthost.shell('config interface buffer priority-group lossless add {} 6'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless add {} 6'.format(port_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format(port_to_test), expected_profile) + check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format( + port_to_test), expected_profile) check_pfc_enable(duthost, port_to_test, '3,4,6') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size, - new_pg_number = 3) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size, + new_pg_number=3) logging.info('[Restore config]') - duthost.shell('config interface buffer priority-group lossless remove {} 6'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless remove {} 6'.format(port_to_test)) check_pfc_enable(duthost, port_to_test, '3,4') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size) finally: - duthost.shell('config interface buffer priority-group lossless remove {}'.format(port_to_test), module_ignore_errors = True) - duthost.shell('config interface speed {} {}'.format(port_to_test, original_speed), module_ignore_errors = True) - duthost.shell('config interface mtu {} {}'.format(port_to_test, DEFAULT_MTU), module_ignore_errors = True) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len), module_ignore_errors = True) - duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format(port_to_test), module_ignore_errors = True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface buffer priority-group lossless remove {}'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface speed {} {}'.format( + port_to_test, original_speed), module_ignore_errors=True) + duthost.shell('config interface mtu {} {}'.format( + port_to_test, DEFAULT_MTU), module_ignore_errors=True) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_len), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format( + port_to_test), module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) def _parse_buffer_profile_params(param, cmd, name): @@ -1159,21 +1328,26 @@ def test_headroom_override(duthosts, rand_one_dut_hostname, conn_graph_facts, po duthost = duthosts[rand_one_dut_hostname] if not TESTPARAM_HEADROOM_OVERRIDE: - pytest.skip("Headroom override test skipped due to no parameters provided") + pytest.skip( + "Headroom override test skipped due to no parameters provided") - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - if check_qos_db_fv_reference_with_table(duthost) == True: - original_profile = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] + if check_qos_db_fv_reference_with_table(duthost): + original_profile = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] else: - original_profile = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] + original_profile = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] original_profile = "BUFFER_PROFILE_TABLE:" + original_profile - original_pg_size = duthost.shell('redis-cli hget "{}" size'.format(original_profile))['stdout'] - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + original_pg_size = duthost.shell( + 'redis-cli hget "{}" size'.format(original_profile))['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] if DEFAULT_OVER_SUBSCRIBE_RATIO: - original_shp_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] - original_pg_xoff = duthost.shell('redis-cli hget "{}" xoff'.format(original_profile))['stdout'] + original_shp_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + original_pg_xoff = duthost.shell( + 'redis-cli hget "{}" xoff'.format(original_profile))['stdout'] else: original_shp_size = None original_pg_xoff = None @@ -1184,98 +1358,125 @@ def test_headroom_override(duthosts, rand_one_dut_hostname, conn_graph_facts, po # Configure a static profile param = TESTPARAM_HEADROOM_OVERRIDE.get("add") if not param: - pytest.skip('Headroom override test skipped due to no parameters for "add" command provided') + pytest.skip( + 'Headroom override test skipped due to no parameters for "add" command provided') else: - cli_str, new_size, new_xoff = _parse_buffer_profile_params(param, "add", "headroom-override") + cli_str, new_size, new_xoff = _parse_buffer_profile_params( + param, "add", "headroom-override") logging.info("[Prepare configuration] {}".format(cli_str)) duthost.shell(cli_str) - logging.info("[Test: headroom override on lossless PG 3-4] Apply the profile on the PG and check pool size") - duthost.shell('config interface buffer priority-group lossless set {} 3-4 headroom-override'.format(port_to_test)) + logging.info( + "[Test: headroom override on lossless PG 3-4] Apply the profile on the PG and check pool size") + duthost.shell( + 'config interface buffer priority-group lossless set {} 3-4 headroom-override'.format(port_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), 'headroom-override') + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), 'headroom-override') check_pfc_enable(duthost, port_to_test, '3,4') - profile_oid, pool_oid = check_buffer_profile_details(duthost, initial_asic_db_profiles, "headroom-override", None, None, port_to_test) + profile_oid, pool_oid = check_buffer_profile_details( + duthost, initial_asic_db_profiles, "headroom-override", None, None, port_to_test) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = new_xoff, - old_size = original_pg_size, - new_size = new_size) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=new_xoff, + old_size=original_pg_size, + new_size=new_size) # Add another headroom override - logging.info("[Test: headroom override on more lossless PGs 6] Apply the profile on the PG and check pool size") - duthost.shell('config interface buffer priority-group lossless add {} 6 headroom-override'.format(port_to_test)) + logging.info( + "[Test: headroom override on more lossless PGs 6] Apply the profile on the PG and check pool size") + duthost.shell( + 'config interface buffer priority-group lossless add {} 6 headroom-override'.format(port_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format(port_to_test), 'headroom-override') + check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format( + port_to_test), 'headroom-override') check_pfc_enable(duthost, port_to_test, '3,4,6') - profile_oid, _ = check_buffer_profile_details(duthost, initial_asic_db_profiles, "headroom-override", profile_oid, pool_oid, port_to_test) + profile_oid, _ = check_buffer_profile_details( + duthost, initial_asic_db_profiles, "headroom-override", profile_oid, pool_oid, port_to_test) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = new_xoff, - old_size = original_pg_size, - new_size = new_size, - new_pg_number = 3) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=new_xoff, + old_size=original_pg_size, + new_size=new_size, + new_pg_number=3) param = TESTPARAM_HEADROOM_OVERRIDE.get("set") if not param: - pytest.skip('Headroom override test skipped due to no parameters for "set" command provided') + pytest.skip( + 'Headroom override test skipped due to no parameters for "set" command provided') else: - cli_str, new_size, new_xoff = _parse_buffer_profile_params(param, "set", "headroom-override") + cli_str, new_size, new_xoff = _parse_buffer_profile_params( + param, "set", "headroom-override") - logging.info("[Test: update headroom-override profile] Update the profile and check pool size: {}".format(cli_str)) + logging.info( + "[Test: update headroom-override profile] Update the profile and check pool size: {}".format(cli_str)) duthost.shell(cli_str) check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - new_xoff = new_xoff, - old_size = original_pg_size, - new_size = new_size, - new_pg_number = 3) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + new_xoff=new_xoff, + old_size=original_pg_size, + new_size=new_size, + new_pg_number=3) # Restore configuration - logging.info("[Test: static headroom being referenced can not be removed]") - duthost.shell('config buffer profile remove headroom-override', module_ignore_errors = True) - - profile = duthost.shell('redis-cli hgetall "BUFFER_PROFILE_TABLE:headroom-override"')['stdout'] - pytest_assert(profile, 'Headroom override profile has been removed when being referenced') + logging.info( + "[Test: static headroom being referenced can not be removed]") + duthost.shell( + 'config buffer profile remove headroom-override', module_ignore_errors=True) + + profile = duthost.shell( + 'redis-cli hgetall "BUFFER_PROFILE_TABLE:headroom-override"')['stdout'] + pytest_assert( + profile, 'Headroom override profile has been removed when being referenced') logging.info("[Restore configuration]") - duthost.shell('config interface buffer priority-group lossless remove {}'.format(port_to_test)) - duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless remove {}'.format(port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless add {} 3-4'.format(port_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), original_profile.split(':')[1]) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), original_profile.split(':')[1]) check_pfc_enable(duthost, port_to_test, '3,4') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size, - new_pg_number = 2) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size, + new_pg_number=2) finally: - duthost.shell('config interface buffer priority-group lossless remove {}'.format(port_to_test), module_ignore_errors = True) - duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format(port_to_test), module_ignore_errors = True) - duthost.shell('config buffer profile remove headroom-override', module_ignore_errors = True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface buffer priority-group lossless remove {}'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format( + port_to_test), module_ignore_errors=True) + duthost.shell( + 'config buffer profile remove headroom-override', module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) + def check_buffer_profiles_for_shp(duthost, shp_enabled=True): def _check_buffer_profiles_for_shp(duthost, shp_enabled): - buffer_profiles = duthost.shell('redis-cli keys "BUFFER_PROFILE_TABLE:*"')['stdout'].split('\n') + buffer_profiles = duthost.shell( + 'redis-cli keys "BUFFER_PROFILE_TABLE:*"')['stdout'].split('\n') for profile_name in buffer_profiles: m = re.search(LOSSLESS_PROFILE_PATTERN, profile_name) if m: - profile_obj = _compose_dict_from_cli(duthost.shell('redis-cli hgetall {}'.format(profile_name))['stdout'].split('\n')) + profile_obj = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall {}'.format(profile_name))['stdout'].split('\n')) if shp_enabled: if not profile_obj['xon'] == profile_obj['size']: return False @@ -1285,13 +1486,15 @@ def _check_buffer_profiles_for_shp(duthost, shp_enabled): # Return True only if all lossless profiles pass the check return True - pytest_assert(wait_until(20, 2, 0, _check_buffer_profiles_for_shp, duthost, shp_enabled)) + pytest_assert(wait_until( + 20, 2, 0, _check_buffer_profiles_for_shp, duthost, shp_enabled)) def test_shared_headroom_pool_configure(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_test): """Test case for shared headroom pool configuration - Test case to verify the variant commands of shared headroom pool configuration and how they affect the other buffer configurations + Test case to verify the variant commands of shared headroom pool configuration and how they affect the other buffer + configurations The flow of the test case: 1. If the over subscribe ratio isn't 2, configure it to 2 @@ -1316,16 +1519,27 @@ def test_shared_headroom_pool_configure(duthosts, rand_one_dut_hostname, conn_gr duthost = duthosts[rand_one_dut_hostname] - pool_size_before_shp = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] - shp_size_before_shp = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + if duthost.facts['asic_type'] == 'barefoot': + pytest.skip( + 'Oversubscribe ratio is not supported for Barefoot platforms yet') - original_over_subscribe_ratio = duthost.shell('redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] - original_configured_shp_size = duthost.shell('redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + pool_size_before_shp = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + shp_size_before_shp = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + + original_over_subscribe_ratio = duthost.shell( + 'redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] + original_configured_shp_size = duthost.shell( + 'redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + original_cable_len = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] if not TESTPARAM_SHARED_HEADROOM_POOL: - pytest.skip('Shared headroom pool test skipped due to no parameters defined') + pytest.skip( + 'Shared headroom pool test skipped due to no parameters defined') shp_size_to_test = TESTPARAM_SHARED_HEADROOM_POOL.get("size") if not shp_size_to_test: pytest.skip('Shared headroom pool test skipped due to size not defined') @@ -1334,17 +1548,22 @@ def test_shared_headroom_pool_configure(duthosts, rand_one_dut_hostname, conn_gr # First, we need to fetch the SAI OID of ingress lossless pool. # The only way to achieve that is to trigger a new buffer profile creation and then fetch the SAI OID from it initial_asic_db_profiles = fetch_initial_asic_db(duthost) - duthost.shell('config interface cable-length {} 10m'.format(port_to_test)) + duthost.shell( + 'config interface cable-length {} 10m'.format(port_to_test)) expected_profile = make_expected_profile_name(original_speed, '10m') time.sleep(20) - profile_oid, pool_oid = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) - logging.info('Got SAI OID of ingress lossless pool: {}'.format(pool_oid)) + profile_oid, pool_oid = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) + logging.info( + 'Got SAI OID of ingress lossless pool: {}'.format(pool_oid)) # Restore the cable length - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len)) + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, original_cable_len)) time.sleep(20) if original_over_subscribe_ratio != '2': - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 2') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 2') if original_configured_shp_size and original_configured_shp_size != '0': duthost.shell('config buffer shared-headroom-pool size 0') @@ -1355,83 +1574,102 @@ def test_shared_headroom_pool_configure(duthosts, rand_one_dut_hostname, conn_gr check_buffer_profiles_for_shp(duthost) # Fetch initial buffer pool size and shared headroom pool size - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] - original_shp_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + original_shp_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] - logging.info('[Test: check shared headroom pool size consistency between APPL_DB and ASIC_DB]') + logging.info( + '[Test: check shared headroom pool size consistency between APPL_DB and ASIC_DB]') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_pg_number = 0, - new_pg_number = 0) - - logging.info('[Test: update over-subscribe-ratio to 4 and check sizes of buffer pool and shared headroom pool]') - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 4') + pool_size=original_pool_size, + shp_size=original_shp_size, + old_pg_number=0, + new_pg_number=0) + + logging.info( + '[Test: update over-subscribe-ratio to 4 and check sizes of buffer pool and shared headroom pool]') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 4') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_ratio = '2', - new_ratio = '4', - old_pg_number = 0, - new_pg_number = 0) - - logging.info('[Test: configure shared headroom pool size and check APPL_DB and ASIC_DB]') - duthost.shell('config buffer shared-headroom-pool size {}'.format(shp_size_to_test)) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_ratio='2', + new_ratio='4', + old_pg_number=0, + new_pg_number=0) + + logging.info( + '[Test: configure shared headroom pool size and check APPL_DB and ASIC_DB]') + duthost.shell( + 'config buffer shared-headroom-pool size {}'.format(shp_size_to_test)) check_pool_size(duthost, pool_oid, - config_shp_size = shp_size_to_test) + config_shp_size=shp_size_to_test) check_buffer_profiles_for_shp(duthost) - logging.info('[Test: remove the over subscribe ratio configuration while size is configured]') - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 0') + logging.info( + '[Test: remove the over subscribe ratio configuration while size is configured]') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 0') check_pool_size(duthost, pool_oid, - config_shp_size = shp_size_to_test) + config_shp_size=shp_size_to_test) check_buffer_profiles_for_shp(duthost) - logging.info('[Test: remove the size configuration while over subscribe ratio is configured]') - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 1') + logging.info( + '[Test: remove the size configuration while over subscribe ratio is configured]') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 1') duthost.shell('config buffer shared-headroom-pool size 0') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_ratio = '2', - new_ratio = '1', - old_pg_number = 0, - new_pg_number = 0) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_ratio='2', + new_ratio='1', + old_pg_number=0, + new_pg_number=0) check_buffer_profiles_for_shp(duthost) logging.info('[Test: remove over subscribe ratio]') - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 0') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 0') check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_ratio = '2', - new_ratio = '0', - conn_graph_facts = conn_graph_facts, - old_pg_number = 0, - new_pg_number = 0) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_ratio='2', + new_ratio='0', + conn_graph_facts=conn_graph_facts, + old_pg_number=0, + new_pg_number=0) logging.info('[Test: remove over subscribe ratio and then the size]') # Configure over subscribe ratio and shared headroom pool size - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 2') - duthost.shell('config buffer shared-headroom-pool size {}'.format(shp_size_to_test)) + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 2') + duthost.shell( + 'config buffer shared-headroom-pool size {}'.format(shp_size_to_test)) check_pool_size(duthost, pool_oid, - config_shp_size = shp_size_to_test) + config_shp_size=shp_size_to_test) # Remove the over subscribe ratio and then the size - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 0') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 0') duthost.shell('config buffer shared-headroom-pool size 0') - check_buffer_profiles_for_shp(duthost, shp_enabled = False) + check_buffer_profiles_for_shp(duthost, shp_enabled=False) finally: - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio {}'.format(original_over_subscribe_ratio), module_ignore_errors = True) - duthost.shell('config buffer shared-headroom-pool size {}'.format(original_configured_shp_size), module_ignore_errors = True) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len), module_ignore_errors = True) - ensure_pool_size(duthost, 60, pool_size_before_shp, shp_size_before_shp, None) + duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio {}'.format( + original_over_subscribe_ratio), module_ignore_errors=True) + duthost.shell('config buffer shared-headroom-pool size {}'.format( + original_configured_shp_size), module_ignore_errors=True) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_len), module_ignore_errors=True) + ensure_pool_size(duthost, 60, pool_size_before_shp, + shp_size_before_shp, None) def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_test, pg_to_test): @@ -1460,15 +1698,21 @@ def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_ skip_traditional_model() duthost = duthosts[rand_one_dut_hostname] - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] - original_shp_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + original_cable_len = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + original_shp_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] initial_asic_db_profiles = fetch_initial_asic_db(duthost) - set_command = 'config interface buffer priority-group lossless set {} {} '.format(port_to_test, pg_to_test) - add_command = 'config interface buffer priority-group lossless add {} {} '.format(port_to_test, pg_to_test) + set_command = 'config interface buffer priority-group lossless set {} {} '.format( + port_to_test, pg_to_test) + add_command = 'config interface buffer priority-group lossless add {} {} '.format( + port_to_test, pg_to_test) if pg_to_test == '3-4': first_command = set_command else: @@ -1479,14 +1723,18 @@ def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_ try: param = TESTPARAM_LOSSLESS_PG.get("headroom-override") if not param: - pytest.skip('Lossless pg test skipped due to no parameters for "headroom-override" command provided') + pytest.skip( + 'Lossless pg test skipped due to no parameters for "headroom-override" command provided') else: - cli_str, new_size, new_xoff = _parse_buffer_profile_params(param, "add", "headroom-override") + cli_str, new_size, new_xoff = _parse_buffer_profile_params( + param, "add", "headroom-override") # Create profiles - logging.info('[Preparing]: Create static buffer profile for headroom override') + logging.info( + '[Preparing]: Create static buffer profile for headroom override') duthost.shell(cli_str) - headroom_override_profile_oid, pool_oid = check_buffer_profile_details(duthost, initial_asic_db_profiles, "headroom-override", None, None, port_to_test) + headroom_override_profile_oid, pool_oid = check_buffer_profile_details( + duthost, initial_asic_db_profiles, "headroom-override", None, None, port_to_test) initial_asic_db_profiles = fetch_initial_asic_db(duthost) @@ -1494,19 +1742,25 @@ def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_ # Profile won't be created until configured on some pg param = TESTPARAM_LOSSLESS_PG.get("non-default-dynamic_th") if not param: - pytest.skip('Lossless pg test skipped due to no parameters for "non-default-dynamic_th" command provided') + pytest.skip( + 'Lossless pg test skipped due to no parameters for "non-default-dynamic_th" command provided') else: - cli_str, new_size, new_xoff = _parse_buffer_profile_params(param, "add", "non-default-dynamic_th") + cli_str, new_size, new_xoff = _parse_buffer_profile_params( + param, "add", "non-default-dynamic_th") - logging.info('[Preparing]: Create static buffer profile for non default dynamic_th') + logging.info( + '[Preparing]: Create static buffer profile for non default dynamic_th') duthost.shell(cli_str) # Update cable length to 15m logging.info('[Preparing]: Update cable length') - duthost.shell('config interface cable-length {} 15m'.format(port_to_test)) + duthost.shell( + 'config interface cable-length {} 15m'.format(port_to_test)) expected_profile = make_expected_profile_name(original_speed, '15m') - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - profile_oid, _ = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, None, pool_oid, port_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + profile_oid, _ = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, None, pool_oid, port_to_test) # Originally, it should be a dynamic PG, update it to override logging.info('[Testcase: dynamic headroom => headroom override]') @@ -1514,39 +1768,53 @@ def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_ # Check whether lossless dynamic profile is removed check_pg_profile(duthost, buffer_pg, 'headroom-override') if pg_to_test == '3-4': - check_lossless_profile_removed(duthost, expected_profile, profile_oid) + check_lossless_profile_removed( + duthost, expected_profile, profile_oid) else: initial_asic_db_profiles = fetch_initial_asic_db(duthost) # Update it to non-default dynamic_th - logging.info('[Testcase: headroom override => dynamically calculated headroom with non-default dynamic_th]') + logging.info( + '[Testcase: headroom override => dynamically calculated headroom with non-default dynamic_th]') duthost.shell(set_command + 'non-default-dynamic_th') - expected_nondef_profile = make_expected_profile_name(original_speed, '15m', other_factors=['th2']) + if is_barefoot_device(duthost): + expected_nondef_profile = make_expected_profile_name( + original_speed, '15m', other_factors=['th7']) + else: + expected_nondef_profile = make_expected_profile_name( + original_speed, '15m', other_factors=['th2']) check_pg_profile(duthost, buffer_pg, expected_nondef_profile) # A new profile should be created in ASIC DB - profile_oid, _ = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_nondef_profile, None, pool_oid, port_to_test) + profile_oid, _ = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_nondef_profile, None, pool_oid, port_to_test) # Update it to dynamic PG - logging.info('[Testcase: dynamically calculated headroom with non-default dynamic_th => dynamic headroom]') + logging.info( + '[Testcase: dynamically calculated headroom with non-default dynamic_th => dynamic headroom]') duthost.shell(set_command) check_pg_profile(duthost, buffer_pg, expected_profile) - check_lossless_profile_removed(duthost, expected_nondef_profile, profile_oid) + check_lossless_profile_removed( + duthost, expected_nondef_profile, profile_oid) # Update it to non-default dynamic_th - logging.info('[Testcase: dynamic headroom => dynamically calculated headroom with non-default dynamic_th]') + logging.info( + '[Testcase: dynamic headroom => dynamically calculated headroom with non-default dynamic_th]') duthost.shell(set_command + 'non-default-dynamic_th') check_pg_profile(duthost, buffer_pg, expected_nondef_profile) # A new profile should be created in ASIC DB - profile_oid, _ = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_nondef_profile, None, pool_oid, port_to_test) + profile_oid, _ = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_nondef_profile, None, pool_oid, port_to_test) if pg_to_test == '3-4': # The oid can be reused by SAI. So we don't check whether profile_oid is removed. check_lossless_profile_removed(duthost, expected_profile) # Update it to headroom override - logging.info('[Testcase: dynamically calculated headroom with non-default dynamic_th => headroom override]') + logging.info( + '[Testcase: dynamically calculated headroom with non-default dynamic_th => headroom override]') duthost.shell(set_command + 'headroom-override') check_pg_profile(duthost, buffer_pg, 'headroom-override') - check_lossless_profile_removed(duthost, expected_nondef_profile, profile_oid) + check_lossless_profile_removed( + duthost, expected_nondef_profile, profile_oid) # Update it to dynamic PG, restore the configuration logging.info('[Testcase: headroom override => dynamic headroom]') @@ -1557,26 +1825,35 @@ def test_lossless_pg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_ logging.info('[Restoring configuration]') duthost.shell('config buffer profile remove headroom-override') duthost.shell('config buffer profile remove non-default-dynamic_th') - check_lossless_profile_removed(duthost, 'headroom-override', headroom_override_profile_oid) + check_lossless_profile_removed( + duthost, 'headroom-override', headroom_override_profile_oid) # No need to check non-default-dynamic_th because it won't propagated to APPL_DB # Restore the cable length duthost.shell(set_command) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len)) + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, original_cable_len)) old_profile = expected_profile - expected_profile = make_expected_profile_name(original_speed, original_cable_len) + expected_profile = make_expected_profile_name( + original_speed, original_cable_len) check_pg_profile(duthost, buffer_pg, expected_profile) check_lossless_profile_removed(duthost, old_profile, profile_oid) finally: if pg_to_test == '3-4': - duthost.shell(set_command, module_ignore_errors = True) + duthost.shell(set_command, module_ignore_errors=True) else: - duthost.shell('config interface buffer priority-group lossless remove {} {} '.format(port_to_test, pg_to_test), module_ignore_errors = True) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len), module_ignore_errors = True) - duthost.shell('config buffer profile remove headroom-override', module_ignore_errors = True) - duthost.shell('config buffer profile remove non-default-dynamic_th', module_ignore_errors = True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface buffer priority-group lossless remove {} {} '.format( + port_to_test, pg_to_test), module_ignore_errors=True) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_len), module_ignore_errors=True) + duthost.shell( + 'config buffer profile remove headroom-override', module_ignore_errors=True) + duthost.shell( + 'config buffer profile remove non-default-dynamic_th', module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) + def test_port_admin_down(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_test): """The test case for admin down ports @@ -1637,20 +1914,26 @@ def _check_buffer_object_aligns_between_appldb_configdb(port_to_test, key, profi key: The key in buffer tables in CONFIG_DB format, like BUFFER_PG|Ethernet0|3-4 profile_field_name: profile for BUFFER_QUEUE table and profile_list for buffer profile list tables """ - objects_in_configdb = duthost.shell('redis-cli -n 4 keys "{}"'.format(key))['stdout'].split() + objects_in_configdb = duthost.shell( + 'redis-cli -n 4 keys "{}"'.format(key))['stdout'].split() if objects_in_configdb: for object_in_configdb in objects_in_configdb: - profile_in_configdb = duthost.shell('redis-cli -n 4 hget "{}" {}'.format(object_in_configdb, profile_field_name))['stdout'] + profile_in_configdb = duthost.shell( + 'redis-cli -n 4 hget "{}" {}'.format(object_in_configdb, profile_field_name))['stdout'] # Convert config db reference to appl db reference if is_qos_db_reference_with_table: - expected_profile_in_appldb = _convert_ref_from_configdb_to_appldb(profile_in_configdb) + expected_profile_in_appldb = _convert_ref_from_configdb_to_appldb( + profile_in_configdb) else: expected_profile_in_appldb = profile_in_configdb # Convert queue id - object_in_app_db = _convert_ref_from_configdb_to_appldb(object_in_configdb) - profile_in_appl_db = duthost.shell('redis-cli hget "{}" {}'.format(object_in_app_db, profile_field_name))['stdout'] + object_in_app_db = _convert_ref_from_configdb_to_appldb( + object_in_configdb) + profile_in_appl_db = duthost.shell( + 'redis-cli hget "{}" {}'.format(object_in_app_db, profile_field_name))['stdout'] pytest_assert(profile_in_appl_db == expected_profile_in_appldb, - "Buffer object {} contains {} which isn't expected ({})".format(key, profile_in_appl_db, expected_profile_in_appldb)) + "Buffer object {} contains {} which isn't expected ({})".format(key, profile_in_appl_db, + expected_profile_in_appldb)) def _check_buffer_object_aligns_with_expected_ones(port_to_test, table, expected_objects): """Check whether the content in BUFFER_PG or BUFFER_QUEUE tables is exactly the same as the expected objects @@ -1662,17 +1945,25 @@ def _check_buffer_object_aligns_with_expected_ones(port_to_test, table, expected They are predefined parameters and loaded at the beginning of the test. Typically, they are zero profiles. """ - objects_in_appl_db = duthost.shell('redis-cli keys "{}:{}:*"'.format(table, port_to_test))['stdout'].split() + objects_in_appl_db = duthost.shell( + 'redis-cli keys "{}:{}:*"'.format(table, port_to_test))['stdout'].split() if expected_objects: - expected_object_keys = ['{}:{}:{}'.format(table, port_to_test, objectid) for objectid in expected_objects.keys()] + expected_object_keys = ['{}:{}:{}'.format( + table, port_to_test, objectid) for objectid in expected_objects.keys()] pytest_assert(set(expected_object_keys) == set(objects_in_appl_db), - "Objects in {} on admin-down port is {} but should be {}".format(table, objects_in_appl_db, expected_object_keys)) + "Objects in {} on admin-down port is {} but should be {}".format(table, objects_in_appl_db, + expected_object_keys)) for objectid, expected_profile in expected_objects.items(): - profile = duthost.shell('redis-cli hget {}:{}:{} profile'.format(table, port_to_test, objectid))['stdout'] + profile = duthost.shell( + 'redis-cli hget {}:{}:{} profile'.format(table, port_to_test, objectid))['stdout'] pytest_assert(profile == expected_profile, - "Profile in {}:{}:{} should be {} but got {}".format(table, port_to_test, objectid, expected_objects[objectid], profile)) + "Profile in {}:{}:{} should be {} but got {}".format(table, port_to_test, objectid, + expected_objects[objectid], + profile)) else: - pytest_assert(not objects_in_appl_db, "There shouldn't be any object in {} on an administratively down port but we got {}".format(table, objects_in_appl_db)) + pytest_assert(not objects_in_appl_db, + "There shouldn't be any object in {} on an administratively down port but we got {}".format( + table, objects_in_appl_db)) def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, expected_objects): """Check whether the content in BUFFER_PG or BUFFER_QUEUE tables is exactly the same as the expected objects @@ -1683,44 +1974,66 @@ def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, exp expected_objects: The expected buffer items of BUFFER_PG or BUFFER_QUEUE when the port is admin down. They are predefined parameters and loaded at the beginning of the test. """ - object_list_in_appl_db = duthost.shell('redis-cli hget "{}:{}" profile_list'.format(table, port_to_test))['stdout'].split(',') + object_list_in_appl_db = duthost.shell( + 'redis-cli hget "{}:{}" profile_list'.format(table, port_to_test))['stdout'].split(',') if expected_objects: pytest_assert(set(expected_objects) == set(object_list_in_appl_db), - "Profile in {}:{} should be {} but got {}".format(table, port_to_test, expected_objects, object_list_in_appl_db)) + "Profile in {}:{} should be {} but got {}".format(table, port_to_test, expected_objects, + object_list_in_appl_db)) else: - pytest_assert(not object_list_in_appl_db, "There shouldn't be any object in {} on an administratively down port but we got {}".format(table, object_list_in_appl_db)) + pytest_assert(not object_list_in_appl_db, + "There shouldn't be any object in {} on an administratively down port but we got {}".format( + table, object_list_in_appl_db)) skip_traditional_model() + if not TESTPARAM_HEADROOM_OVERRIDE: + pytest.skip( + 'Shutdown port test skipped due to no headroom override parameter defined') param = TESTPARAM_HEADROOM_OVERRIDE.get("add") if not param: - pytest.skip('Shutdown port test skipped due to no headroom override parameters defined') + pytest.skip( + 'Shutdown port test skipped due to no headroom override parameters for add operation defined') duthost = duthosts[rand_one_dut_hostname] - is_qos_db_reference_with_table = check_qos_db_fv_reference_with_table(duthost) - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - raw_lanes_str = duthost.shell('redis-cli -n 4 hget "PORT|{}" lanes'.format(port_to_test))['stdout'] + is_qos_db_reference_with_table = check_qos_db_fv_reference_with_table( + duthost) + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + raw_lanes_str = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" lanes'.format(port_to_test))['stdout'] list_of_lanes = raw_lanes_str.split(',') - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - if check_qos_db_fv_reference_with_table(duthost) == True: - original_profile = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] + original_cable_len = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + if check_qos_db_fv_reference_with_table(duthost): + original_profile = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'][1:-1] else: - original_profile = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] + original_profile = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:3-4" profile'.format(port_to_test))['stdout'] original_profile = "BUFFER_PROFILE_TABLE:" + original_profile - original_pg_size = duthost.shell('redis-cli hget "{}" size'.format(original_profile))['stdout'] - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + original_pg_size = duthost.shell( + 'redis-cli hget "{}" size'.format(original_profile))['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] new_cable_len = '15m' + if not TESTPARAM_EXTRA_OVERHEAD: + pytest.skip( + 'Shutdown port test skipped due to no extra overhead parameter defined') extra_overhead = TESTPARAM_EXTRA_OVERHEAD.get(str(len(list_of_lanes))) if not extra_overhead: extra_overhead = TESTPARAM_EXTRA_OVERHEAD.get('default') if not extra_overhead: - pytest.skip('Shutdown port test skipped due to no lossy pg size defined') + pytest.skip( + 'Shutdown port test skipped due to no lossy pg size defined') if DEFAULT_OVER_SUBSCRIBE_RATIO: - original_pg_xoff = int(duthost.shell('redis-cli hget "{}" xoff'.format(original_profile))['stdout']) - original_shp_size = int(duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) + original_pg_xoff = int(duthost.shell( + 'redis-cli hget "{}" xoff'.format(original_profile))['stdout']) + original_shp_size = int(duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) else: original_pg_xoff = None original_shp_size = None @@ -1730,52 +2043,65 @@ def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, exp # Create a non default dynamic-th profile non_default_dynamic_th_profile = 'test-profile-non-default-dynamic_th' dynamic_th_value = '2' - duthost.shell('config buffer profile add {} --dynamic_th {}'.format(non_default_dynamic_th_profile, dynamic_th_value)) + duthost.shell('config buffer profile add {} --dynamic_th {}'.format( + non_default_dynamic_th_profile, dynamic_th_value)) # Create a headroom override profile headroom_override_profile = 'test-profile-headroom-override' - duthost.shell('config buffer profile add {} --xon {} --xoff {}'.format(headroom_override_profile, param['xon'], param['xoff'])) + duthost.shell('config buffer profile add {} --xon {} --xoff {}'.format( + headroom_override_profile, param['xon'], param['xoff'])) - _, pool_oid = check_buffer_profile_details(duthost, initial_asic_db_profiles, headroom_override_profile, None, None, port_to_test) + _, pool_oid = check_buffer_profile_details( + duthost, initial_asic_db_profiles, headroom_override_profile, None, None, port_to_test) """ Each item is a tuple consisting of: - Hint message to user - Command to be executed - The expected profile after the command is executed and the port is administratively up - - Whether we need to check whether the previous expected_profile has been removed after port is administratively down + - Whether we need to check whether the previous expected_profile has been removed after port is + administratively down """ scenarios = [ ('Remove the generic PG when port is administratively down', - 'config interface buffer priority-group lossless remove {} 3-4'.format(port_to_test), + 'config interface buffer priority-group lossless remove {} 3-4'.format( + port_to_test), None, False), ('Add a PG with non default dynamic_th when port is administratively down', - 'config interface buffer priority-group lossless add {} 3-4 {}'.format(port_to_test, non_default_dynamic_th_profile), - make_expected_profile_name(original_speed, original_cable_len, other_factors=['th{}'.format(dynamic_th_value)]), + 'config interface buffer priority-group lossless add {} 3-4 {}'.format( + port_to_test, non_default_dynamic_th_profile), + make_expected_profile_name(original_speed, original_cable_len, other_factors=[ + 'th{}'.format(dynamic_th_value)]), False), ('Remove the PG with non default dynamic_th when port is administratively down', - 'config interface buffer priority-group lossless remove {} 3-4'.format(port_to_test), + 'config interface buffer priority-group lossless remove {} 3-4'.format( + port_to_test), None, True), ('Add a PG with headroom override profile when port is administratively down', - 'config interface buffer priority-group lossless add {} 3-4 {}'.format(port_to_test, headroom_override_profile), + 'config interface buffer priority-group lossless add {} 3-4 {}'.format( + port_to_test, headroom_override_profile), headroom_override_profile, False), ('Remove the PG with headroom override when port is administratively down', - 'config interface buffer priority-group lossless remove {} 3-4'.format(port_to_test), + 'config interface buffer priority-group lossless remove {} 3-4'.format( + port_to_test), None, False), ('Readd the generic PG when port is administratively down', - 'config interface buffer priority-group lossless add {} 3-4'.format(port_to_test), + 'config interface buffer priority-group lossless add {} 3-4'.format( + port_to_test), make_expected_profile_name(original_speed, original_cable_len), False), ('Change the cable length when port is administratively down', - 'config interface cable-length {} {}'.format(port_to_test, new_cable_len), + 'config interface cable-length {} {}'.format( + port_to_test, new_cable_len), make_expected_profile_name(original_speed, new_cable_len), False), ('Restore the cable length when port is administratively down', - 'config interface cable-length {} {}'.format(port_to_test, original_cable_len), + 'config interface cable-length {} {}'.format( + port_to_test, original_cable_len), make_expected_profile_name(original_speed, original_cable_len), True) ] @@ -1788,41 +2114,52 @@ def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, exp duthost.shell('config interface shutdown {}'.format(port_to_test)) # Make sure there isn't any PG on the port or zero profile configured for PGs time.sleep(10) - logging.info('Check whether all PGs are removed from port {}'.format(port_to_test)) + logging.info( + 'Check whether all PGs are removed from port {}'.format(port_to_test)) expected_pgs = TESTPARAM_ADMIN_DOWN.get('BUFFER_PG_TABLE') - _check_buffer_object_aligns_with_expected_ones(port_to_test, 'BUFFER_PG_TABLE', expected_pgs) + _check_buffer_object_aligns_with_expected_ones( + port_to_test, 'BUFFER_PG_TABLE', expected_pgs) # Make sure the zero profiles have been applied on queues on the port - logging.info('Check whether all queues are configured as zero profile or removed from port {}'.format(port_to_test)) + logging.info( + 'Check whether all queues are configured as zero profile or removed from port {}'.format(port_to_test)) expected_queues = TESTPARAM_ADMIN_DOWN.get('BUFFER_QUEUE_TABLE') - _check_buffer_object_aligns_with_expected_ones(port_to_test, 'BUFFER_QUEUE_TABLE', expected_queues) + _check_buffer_object_aligns_with_expected_ones( + port_to_test, 'BUFFER_QUEUE_TABLE', expected_queues) # Make sure the zero profiles have been applied on ingress buffer profile list on the port - logging.info('Check whether ingress profile list is configured as zero profile or removed from port {}'.format(port_to_test)) - expected_ingress_profile_list = TESTPARAM_ADMIN_DOWN.get('BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') - _check_buffer_object_list_aligns_with_expected_ones(port_to_test, 'BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE', expected_ingress_profile_list) + logging.info( + 'Check whether ingress profile list is configured as zero profile or removed from port {}'.format(port_to_test)) + expected_ingress_profile_list = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE') + _check_buffer_object_list_aligns_with_expected_ones( + port_to_test, 'BUFFER_PORT_INGRESS_PROFILE_LIST_TABLE', expected_ingress_profile_list) # Make sure the zero profiles have been applied on egress buffer profile list on the port - logging.info('Check whether egress profile list is configured as zero profile or removed from port {}'.format(port_to_test)) - expected_egress_profile_list = TESTPARAM_ADMIN_DOWN.get('BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE') - _check_buffer_object_list_aligns_with_expected_ones(port_to_test, 'BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE', expected_egress_profile_list) + logging.info( + 'Check whether egress profile list is configured as zero profile or removed from port {}'.format(port_to_test)) + expected_egress_profile_list = TESTPARAM_ADMIN_DOWN.get( + 'BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE') + _check_buffer_object_list_aligns_with_expected_ones( + port_to_test, 'BUFFER_PORT_EGRESS_PROFILE_LIST_TABLE', expected_egress_profile_list) # Check the pool size after the port is admin down check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size, - new_pg_number = 0, - adjust_extra_overhead = extra_overhead) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size, + new_pg_number=0, + adjust_extra_overhead=extra_overhead) previous_profile = expected_profile_in_appldb hint, command, expected_profile_in_appldb, need_remove_previous_profile = scenario # Check whether the profile that is expected to be removed is removed if need_remove_previous_profile: - logging.info('Check whether profile {} has been removed after port being administratively down'.format(previous_profile)) + logging.info('Check whether profile {} has been removed after port being administratively down'.format( + previous_profile)) check_lossless_profile_removed(duthost, previous_profile) logging.info(hint) duthost.shell(command) @@ -1830,25 +2167,35 @@ def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, exp logging.info('Start up port {}'.format(port_to_test)) duthost.shell('config interface startup {}'.format(port_to_test)) if expected_profile_in_appldb: - logging.info('Check whether profile in PG is as expected({})'.format(expected_profile_in_appldb)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile_in_appldb) + logging.info('Check whether profile in PG is as expected({})'.format( + expected_profile_in_appldb)) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile_in_appldb) else: logging.info('Check whether profile in PG has been removed') time.sleep(10) - pgs_in_appl_db = duthost.shell('redis-cli keys "BUFFER_PG_TABLE:{}:3-4"'.format(port_to_test))['stdout'] - pytest_assert(not pgs_in_appl_db, "There shouldn't be PGs 3-4 but we got {}".format(pgs_in_appl_db)) + pgs_in_appl_db = duthost.shell( + 'redis-cli keys "BUFFER_PG_TABLE:{}:3-4"'.format(port_to_test))['stdout'] + pytest_assert( + not pgs_in_appl_db, "There shouldn't be PGs 3-4 but we got {}".format(pgs_in_appl_db)) # Check whether the queues have been applied correctly - logging.info('Check whether queues are readded to port {}'.format(port_to_test)) - _check_buffer_object_aligns_between_appldb_configdb(port_to_test, "BUFFER_QUEUE|{}|*".format(port_to_test), 'profile') + logging.info( + 'Check whether queues are readded to port {}'.format(port_to_test)) + _check_buffer_object_aligns_between_appldb_configdb( + port_to_test, "BUFFER_QUEUE|{}|*".format(port_to_test), 'profile') # Check whether the ingress profile list have been applied correctly - logging.info('Check whether ingress profile list are readded to port {}'.format(port_to_test)) - _check_buffer_object_aligns_between_appldb_configdb(port_to_test, "BUFFER_PORT_INGRESS_PROFILE_LIST|{}".format(port_to_test), 'profile_list') + logging.info( + 'Check whether ingress profile list are readded to port {}'.format(port_to_test)) + _check_buffer_object_aligns_between_appldb_configdb( + port_to_test, "BUFFER_PORT_INGRESS_PROFILE_LIST|{}".format(port_to_test), 'profile_list') # Check whether the egress profile list have been applied correctly - logging.info('Check whether egress profile list are readded to port {}'.format(port_to_test)) - _check_buffer_object_aligns_between_appldb_configdb(port_to_test, "BUFFER_PORT_EGRESS_PROFILE_LIST|{}".format(port_to_test), 'profile_list') + logging.info( + 'Check whether egress profile list are readded to port {}'.format(port_to_test)) + _check_buffer_object_aligns_between_appldb_configdb( + port_to_test, "BUFFER_PORT_EGRESS_PROFILE_LIST|{}".format(port_to_test), 'profile_list') # Check the pool size at the end of test. # We don't check the pool size each time the port is admin down because @@ -1856,20 +2203,27 @@ def _check_buffer_object_list_aligns_with_expected_ones(port_to_test, table, exp # 2. We have done this kind of test for many times in other testcases check_pool_size(duthost, pool_oid, - pool_size = original_pool_size, - shp_size = original_shp_size, - old_xoff = original_pg_xoff, - old_size = original_pg_size, - new_pg_number = 2) + pool_size=original_pool_size, + shp_size=original_shp_size, + old_xoff=original_pg_xoff, + old_size=original_pg_size, + new_pg_number=2) finally: - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len), module_ignore_errors=True) - duthost.shell('config interface startup {}'.format(port_to_test), module_ignore_errors=True) - duthost.shell('config interface buffer priority-group lossless set {} 3-4'.format(port_to_test), module_ignore_errors=True) - duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format(port_to_test), module_ignore_errors=True) - duthost.shell('config buffer profile remove {}'.format(non_default_dynamic_th_profile), module_ignore_errors=True) - duthost.shell('config buffer profile remove {}'.format(headroom_override_profile), module_ignore_errors=True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_len), module_ignore_errors=True) + duthost.shell('config interface startup {}'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless set {} 3-4'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless add {} 3-4'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config buffer profile remove {}'.format( + non_default_dynamic_th_profile), module_ignore_errors=True) + duthost.shell('config buffer profile remove {}'.format( + headroom_override_profile), module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) def test_port_auto_neg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_to_test): @@ -1889,7 +2243,8 @@ def test_port_auto_neg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_t - Configure the speed to the minimum supported one and the cable length to 15m - This is to enforce there is a new buffer profile created 3. Enable the port auto negotiation and then configure the advertised speed list and then disable it - - The maximum supported speed should be taken into account for buffer calculation after port auto negotiation enabled + - The maximum supported speed should be taken into account for buffer calculation after port + auto negotiation enabled - The maximum advertised speed should be taken after it is configured - The configured speed should be taken after the port auto negotiation is disabled 4. Enable the port auto negotiation with the advertised speed list configured @@ -1903,8 +2258,10 @@ def test_port_auto_neg(duthosts, rand_one_dut_hostname, conn_graph_facts, port_t The buffer pool size is not verified in this test because: - Only the logic to generate effective speed is updated in port auto-negotiation, which will affect only the buffer priority-groups and profiles on the port, which is verified in the test. - - The buffer pool size depends on the buffer priority-groups and profiles but not directly on the effective speed. - As buffer pool size has been verified in other test cases and checking it will consume more time, we don't repeat it here. + - The buffer pool size depends on the buffer priority-groups and profiles but not directly on the effective + speed. + As buffer pool size has been verified in other test cases and checking it will consume more time, we don't + repeat it here. """ def _get_max_speed_from_list(speed_list_str): speed_list = natsorted(speed_list_str.split(',')) @@ -1913,14 +2270,20 @@ def _get_max_speed_from_list(speed_list_str): skip_traditional_model() duthost = duthosts[rand_one_dut_hostname] - supported_speeds = duthost.shell('redis-cli -n 6 hget "PORT_TABLE|{}" supported_speeds'.format(port_to_test))['stdout'] + supported_speeds = duthost.shell( + 'redis-cli -n 6 hget "PORT_TABLE|{}" supported_speeds'.format(port_to_test))['stdout'] if not supported_speeds: - pytest.skip('No supported_speeds found for port {}, skip the test'.format(port_to_test))['stdout'] - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_cable_length = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + pytest.skip('No supported_speeds found for port {}, skip the test'.format( + port_to_test))['stdout'] + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + original_cable_length = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] if DEFAULT_OVER_SUBSCRIBE_RATIO: - original_shp_size = int(duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) + original_shp_size = int(duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout']) else: original_shp_size = None @@ -1932,69 +2295,105 @@ def _get_max_speed_from_list(speed_list_str): max_advertised_speed = _get_max_speed_from_list(advertised_speeds_to_test) initial_asic_db_profiles = fetch_initial_asic_db(duthost) - expected_profile = make_expected_profile_name(speed_before_test, cable_length_to_test) + expected_profile = make_expected_profile_name( + speed_before_test, cable_length_to_test) try: # Preparing: configure the speed to one which is not the maximum speed and the cable length to 15m # This is to enforce there is a new buffer profile created - duthost.shell('config interface speed {} {}'.format(port_to_test, speed_before_test)) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, cable_length_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - new_profile_id, pool_id = check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) + duthost.shell('config interface speed {} {}'.format( + port_to_test, speed_before_test)) + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, cable_length_to_test)) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + new_profile_id, pool_id = check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, None, None, port_to_test) # As comments at the beginning of the method, we don't check buffer pool size in this test case. # The same for all the following steps. # Enable port auto negotiation first and then configure the advertised speed list logging.info('Enable port auto negotiation') - duthost.shell('config interface autoneg {} enabled'.format(port_to_test)) + duthost.shell( + 'config interface autoneg {} enabled'.format(port_to_test)) # Check whether the maximum supported speed is used for creating lossless profile - expected_profile = make_expected_profile_name(max_supported_speed, cable_length_to_test) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) + expected_profile = make_expected_profile_name( + max_supported_speed, cable_length_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) # Configure advertised speeds - logging.info('Update advertised speeds to {}'.format(advertised_speeds_to_test)) - duthost.shell('config interface advertised-speeds {} {}'.format(port_to_test, advertised_speeds_to_test)) + logging.info('Update advertised speeds to {}'.format( + advertised_speeds_to_test)) + duthost.shell( + 'config interface advertised-speeds {} {}'.format(port_to_test, advertised_speeds_to_test)) # Check whether the maximum advertised speed is used for creating lossless profile - expected_profile = make_expected_profile_name(max_advertised_speed, cable_length_to_test) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) + expected_profile = make_expected_profile_name( + max_advertised_speed, cable_length_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) # Disable port auto negotiation logging.info('Disable port auto negotiation') - duthost.shell('config interface autoneg {} disabled'.format(port_to_test)) - expected_profile = make_expected_profile_name(speed_before_test, cable_length_to_test) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) + duthost.shell( + 'config interface autoneg {} disabled'.format(port_to_test)) + expected_profile = make_expected_profile_name( + speed_before_test, cable_length_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) # Enable port auto negotiation with advertised speed configured - logging.info('Reenable port auto negotiation with advertised speeds configured') - duthost.shell('config interface autoneg {} enabled'.format(port_to_test)) + logging.info( + 'Reenable port auto negotiation with advertised speeds configured') + duthost.shell( + 'config interface autoneg {} enabled'.format(port_to_test)) # Check whether the maximum advertised speed is used for creating lossless profile - expected_profile = make_expected_profile_name(max_advertised_speed, cable_length_to_test) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) + expected_profile = make_expected_profile_name( + max_advertised_speed, cable_length_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) # Add new PGs. The maximum advertised speed should be used logging.info('Add new PG 6') - duthost.shell('config interface buffer priority-group lossless add {} 6'.format(port_to_test)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format(port_to_test), expected_profile) + duthost.shell( + 'config interface buffer priority-group lossless add {} 6'.format(port_to_test)) + check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format( + port_to_test), expected_profile) # Update the advertised speed to all logging.info('Update advertised speeds to all') - duthost.shell('config interface advertised-speeds {} all'.format(port_to_test)) - expected_profile = make_expected_profile_name(max_supported_speed, cable_length_to_test) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format(port_to_test), expected_profile) - check_buffer_profile_details(duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) + duthost.shell( + 'config interface advertised-speeds {} all'.format(port_to_test)) + expected_profile = make_expected_profile_name( + max_supported_speed, cable_length_to_test) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:6'.format( + port_to_test), expected_profile) + check_buffer_profile_details( + duthost, initial_asic_db_profiles, expected_profile, new_profile_id, pool_id, port_to_test) finally: # Clean up - duthost.shell('config interface buffer priority-group lossless remove {} 6'.format(port_to_test), module_ignore_errors=True) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_length), module_ignore_errors=True) - duthost.shell('config interface speed {} {}'.format(port_to_test, original_speed), module_ignore_errors=True) - duthost.shell('config interface advertised-speeds {} all'.format(port_to_test), module_ignore_errors=True) - duthost.shell('config interface autoneg {} disabled'.format(port_to_test), module_ignore_errors=True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface buffer priority-group lossless remove {} 6'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_length), module_ignore_errors=True) + duthost.shell('config interface speed {} {}'.format( + port_to_test, original_speed), module_ignore_errors=True) + duthost.shell( + 'config interface advertised-speeds {} all'.format(port_to_test), module_ignore_errors=True) + duthost.shell('config interface autoneg {} disabled'.format( + port_to_test), module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) @pytest.mark.disable_loganalyzer @@ -2022,22 +2421,31 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p skip_traditional_model() duthost = duthosts[rand_one_dut_hostname] - max_headroom_size = duthost.shell('redis-cli -n 6 hget "BUFFER_MAX_PARAM_TABLE|{}" max_headroom_size'.format(port_to_test))['stdout'] + max_headroom_size = duthost.shell( + 'redis-cli -n 6 hget "BUFFER_MAX_PARAM_TABLE|{}" max_headroom_size'.format(port_to_test))['stdout'] if not max_headroom_size: - pytest.skip('No max headroom found on port {}, skip'.format(port_to_test)) - - original_cable_len = duthost.shell('redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] - original_speed = duthost.shell('redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] - original_over_subscribe_ratio = duthost.shell('redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] - original_configured_shp_size = duthost.shell('redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] - original_pool_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] - original_shp_size = duthost.shell('redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] + pytest.skip( + 'No max headroom found on port {}, skip'.format(port_to_test)) + + original_cable_len = duthost.shell( + 'redis-cli -n 4 hget "CABLE_LENGTH|AZURE" {}'.format(port_to_test))['stdout'] + original_speed = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" speed'.format(port_to_test))['stdout'] + original_over_subscribe_ratio = duthost.shell( + 'redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" over_subscribe_ratio')['stdout'] + original_configured_shp_size = duthost.shell( + 'redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool" xoff')['stdout'] + original_pool_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool size')['stdout'] + original_shp_size = duthost.shell( + 'redis-cli hget BUFFER_POOL_TABLE:ingress_lossless_pool xoff')['stdout'] try: # Test case runs with shared headroom pool disabled # because the headroom size is very small with shared headroom pool enabled if original_over_subscribe_ratio and original_over_subscribe_ratio != '0': - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 0') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 0') if original_configured_shp_size and original_configured_shp_size != '0': duthost.shell('config buffer shared-headroom-pool size 0') @@ -2050,18 +2458,24 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p 'oid is set to null object id on SAI_OBJECT_TYPE_BUFFER_PROFILE', 'Failed to remove buffer profile .* with type BUFFER_PROFILE_TABLE', 'doTask: Failed to process buffer task, drop it']) - logging.info('[Find out the longest cable length the port can support]') + logging.info( + '[Find out the longest cable length the port can support]') cable_length = int(original_cable_len[:-1]) cable_length_step = 128 while True: - duthost.shell('config interface cable-length {} {}m'.format(port_to_test, cable_length)) - expected_profile = make_expected_profile_name(original_speed, '{}m'.format(cable_length)) - profile_applied = check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile, False) + duthost.shell( + 'config interface cable-length {} {}m'.format(port_to_test, cable_length)) + expected_profile = make_expected_profile_name( + original_speed, '{}m'.format(cable_length)) + profile_applied = check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile, False) if not profile_applied: break - logging.info('Cable length {} has been applied successfully'.format(cable_length)) + logging.info( + 'Cable length {} has been applied successfully'.format(cable_length)) if cable_length > 10000: - pytest.skip("Not able to find the maximum headroom of port {} after cable length has been increased to 10km, skip the test".format(port_to_test)) + pytest.skip( + "Not able to find the maximum headroom of port {} after cable length has been increased to 10km, skip the test".format(port_to_test)) cable_length += cable_length_step cable_length_step *= 2 @@ -2070,18 +2484,24 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p cable_length_step /= 2 cable_length -= cable_length_step cable_length_lower = cable_length - logging.info("Cable length {} can be applied but {} can't. Finding the exact maximum cable length".format(cable_length_lower, cable_length_upper)) + logging.info("Cable length {} can be applied but {} can't. Finding the exact maximum cable length".format( + cable_length_lower, cable_length_upper)) while True: cable_length = (cable_length_upper + cable_length_lower) / 2 - duthost.shell('config interface cable-length {} {}m'.format(port_to_test, cable_length)) - expected_profile = make_expected_profile_name(original_speed, '{}m'.format(cable_length)) - profile_applied = check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile, False) + duthost.shell( + 'config interface cable-length {} {}m'.format(port_to_test, cable_length)) + expected_profile = make_expected_profile_name( + original_speed, '{}m'.format(cable_length)) + profile_applied = check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile, False) if profile_applied: cable_length_lower = cable_length - logging.info('Cable length {} has been applied successfully, moving forward. Range now is [{}, {})'.format(cable_length, cable_length_lower, cable_length_upper)) + logging.info('Cable length {} has been applied successfully, moving forward. Range now is [{}, {})'.format( + cable_length, cable_length_lower, cable_length_upper)) else: cable_length_upper = cable_length - logging.info('Cable length {} has not been applied, moving backward. Range now is [{}, {})'.format(cable_length, cable_length_lower, cable_length_upper)) + logging.info('Cable length {} has not been applied, moving backward. Range now is [{}, {})'.format( + cable_length, cable_length_lower, cable_length_upper)) if cable_length_lower + 1 >= cable_length_upper: cable_length = cable_length_lower break @@ -2089,7 +2509,8 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p # We've got the maximum cable length that can be applied on the port violating_cable_length = cable_length_upper maximum_cable_length = cable_length_lower - logging.info('Got maximum cable length {}'.format(maximum_cable_length)) + logging.info('Got maximum cable length {}'.format( + maximum_cable_length)) # Check whether there is the expected error message in the log logging.info('Check whether the expected error message is found') @@ -2100,26 +2521,37 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p ['Update speed .* and cable length .* for port .* failed, accumulative headroom size exceeds the limit', 'Unable to update profile for port .*. Accumulative headroom size exceeds limit']) - maximum_profile_name = make_expected_profile_name(original_speed, '{}m'.format(maximum_cable_length)) - maximum_profile = _compose_dict_from_cli(duthost.shell('redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(maximum_profile_name))['stdout'].split()) + maximum_profile_name = make_expected_profile_name( + original_speed, '{}m'.format(maximum_cable_length)) + maximum_profile = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(maximum_profile_name))['stdout'].split()) # Config the cable length to the longest acceptable value and check the profile - logging.info('[Config the cable length to the longest acceptable value on the port]') - duthost.shell('config interface cable-length {} {}m'.format(port_to_test, maximum_cable_length)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), maximum_profile_name) + logging.info( + '[Config the cable length to the longest acceptable value on the port]') + duthost.shell( + 'config interface cable-length {} {}m'.format(port_to_test, maximum_cable_length)) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), maximum_profile_name) # 2. Add extra PGs to a port, which causes the accumulative headroom exceed the limit logging.info('Add another PG and make sure the system isn\'t broken') - duthost.shell('config interface buffer priority-group lossless add {} {}'.format(port_to_test, '5-7')) - profile_applied = check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:5-7'.format(port_to_test), maximum_profile_name, False) - pytest_assert(not profile_applied, "Profile {} applied on {}:5-7, which makes the accumulative headroom exceed the limit".format(maximum_profile_name, port_to_test)) + duthost.shell( + 'config interface buffer priority-group lossless add {} {}'.format(port_to_test, '5-7')) + profile_applied = check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:5-7'.format(port_to_test), maximum_profile_name, False) + pytest_assert(not profile_applied, + "Profile {} applied on {}:5-7, which makes the accumulative headroom exceed the limit".format( + maximum_profile_name, port_to_test)) # Check whether there is the expected error message in the log check_log_analyzer(loganalyzer, marker) # Restore the configuration - duthost.shell('config interface buffer priority-group lossless remove {} {}'.format(port_to_test, '5-7')) - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len)) + duthost.shell( + 'config interface buffer priority-group lossless remove {} {}'.format(port_to_test, '5-7')) + duthost.shell( + 'config interface cable-length {} {}'.format(port_to_test, original_cable_len)) # 3. Configure a headroom-override on a port and then enlarge the size of the profile. loganalyzer, marker = init_log_analyzer(duthost, @@ -2130,22 +2562,29 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p logging.info('[Config headroom override to PG 3-4]') duthost.shell('config buffer profile add test-headroom --xon {} --xoff {} --size {}'.format( maximum_profile['xon'], maximum_profile['xoff'], maximum_profile['size'])) - duthost.shell('config interface buffer priority-group lossless set {} {} {}'.format(port_to_test, '3-4', 'test-headroom')) + duthost.shell('config interface buffer priority-group lossless set {} {} {}'.format( + port_to_test, '3-4', 'test-headroom')) logging.info('Verify the profile is applied') - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), 'test-headroom') + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), 'test-headroom') # Apply the profile on other PGs, which make the accumulative headroom exceed the limit - duthost.shell('config interface buffer priority-group lossless add {} {} {}'.format(port_to_test, '5-7', 'test-headroom')) + duthost.shell('config interface buffer priority-group lossless add {} {} {}'.format( + port_to_test, '5-7', 'test-headroom')) # Make sure the profile hasn't been applied - profile_applied = check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:5-7'.format(port_to_test), 'test-headroom', False) - pytest_assert(not profile_applied, "Profile {} applied on {}:5-7, which makes the accumulative headroom exceed the limit".format(maximum_profile_name, port_to_test)) + profile_applied = check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:5-7'.format(port_to_test), 'test-headroom', False) + pytest_assert(not profile_applied, + "Profile {} applied on {}:5-7, which makes the accumulative headroom exceed the limit".format( + maximum_profile_name, port_to_test)) # Check log check_log_analyzer(loganalyzer, marker) # Restore configuration - duthost.shell('config interface buffer priority-group lossless remove {} {}'.format(port_to_test, '5-7')) + duthost.shell( + 'config interface buffer priority-group lossless remove {} {}'.format(port_to_test, '5-7')) # Update static profile to a larger size, which makes it exceeds the port headroom limit # Setup the log analyzer @@ -2155,18 +2594,22 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p 'Unable to update profile for port .*. Accumulative headroom size exceeds limit']) logging.info('[Update headroom override to a larger size]') - duthost.shell('config buffer profile set test-headroom --size {}'.format(int(maximum_profile['size']) * 2)) + duthost.shell( + 'config buffer profile set test-headroom --size {}'.format(int(maximum_profile['size']) * 2)) # This should make it exceed the limit, so the profile should not applied to the APPL_DB time.sleep(20) - size_in_appldb = duthost.shell('redis-cli hget "BUFFER_PROFILE_TABLE:test-headroom" size')['stdout'] - pytest_assert(size_in_appldb == maximum_profile['size'], 'The profile with a large size was applied to APPL_DB, which can make headroom exceeding') + size_in_appldb = duthost.shell( + 'redis-cli hget "BUFFER_PROFILE_TABLE:test-headroom" size')['stdout'] + pytest_assert(size_in_appldb == maximum_profile['size'], + 'The profile with a large size was applied to APPL_DB, which can make headroom exceeding') # Check log check_log_analyzer(loganalyzer, marker) # Restore config - duthost.shell('config interface buffer priority-group lossless set {} {}'.format(port_to_test, '3-4')) + duthost.shell( + 'config interface buffer priority-group lossless set {} {}'.format(port_to_test, '3-4')) duthost.shell('config buffer profile remove test-headroom') # 4. Configure a long cable length with shared headroom pool enabled. @@ -2177,31 +2620,44 @@ def test_exceeding_headroom(duthosts, rand_one_dut_hostname, conn_graph_facts, p 'refreshSharedHeadroomPool: Failed to update buffer profile .* when toggle shared headroom pool']) # Enable shared headroom pool - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 2') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 2') time.sleep(20) # And then configure the cable length which causes the accumulative headroom exceed the limit - duthost.shell('config interface cable-length {} {}m'.format(port_to_test, violating_cable_length)) - expected_profile = make_expected_profile_name(original_speed, '{}m'.format(violating_cable_length)) - check_pg_profile(duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) + duthost.shell( + 'config interface cable-length {} {}m'.format(port_to_test, violating_cable_length)) + expected_profile = make_expected_profile_name( + original_speed, '{}m'.format(violating_cable_length)) + check_pg_profile( + duthost, 'BUFFER_PG_TABLE:{}:3-4'.format(port_to_test), expected_profile) # Disable shared headroom pool - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio 0') + duthost.shell( + 'config buffer shared-headroom-pool over-subscribe-ratio 0') time.sleep(20) # Make sure the size isn't updated - profile_appldb = _compose_dict_from_cli(duthost.shell('redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(expected_profile))['stdout'].split('\n')) + profile_appldb = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall BUFFER_PROFILE_TABLE:{}'.format(expected_profile))['stdout'].split('\n')) assert profile_appldb['xon'] == profile_appldb['size'] # Check log check_log_analyzer(loganalyzer, marker) finally: logging.info('[Clean up]') - duthost.shell('config interface cable-length {} {}'.format(port_to_test, original_cable_len), module_ignore_errors = True) - duthost.shell('config interface buffer priority-group lossless remove {} 5-7'.format(port_to_test), module_ignore_errors = True) - duthost.shell('config interface buffer priority-group lossless set {} 3-4'.format(port_to_test), module_ignore_errors = True) - duthost.shell('config buffer profile remove test-headroom', module_ignore_errors = True) - duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio {}'.format(original_over_subscribe_ratio), module_ignore_errors = True) - duthost.shell('config buffer shared-headroom-pool size {}'.format(original_configured_shp_size), module_ignore_errors = True) - ensure_pool_size(duthost, 60, original_pool_size, original_shp_size, None) + duthost.shell('config interface cable-length {} {}'.format(port_to_test, + original_cable_len), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless remove {} 5-7'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config interface buffer priority-group lossless set {} 3-4'.format( + port_to_test), module_ignore_errors=True) + duthost.shell('config buffer profile remove test-headroom', + module_ignore_errors=True) + duthost.shell('config buffer shared-headroom-pool over-subscribe-ratio {}'.format( + original_over_subscribe_ratio), module_ignore_errors=True) + duthost.shell('config buffer shared-headroom-pool size {}'.format( + original_configured_shp_size), module_ignore_errors=True) + ensure_pool_size(duthost, 60, original_pool_size, + original_shp_size, None) def _recovery_to_dynamic_buffer_model(duthost): @@ -2223,13 +2679,17 @@ def test_buffer_model_test(duthosts, rand_one_dut_hostname, conn_graph_facts): try: logging.info('[Config load_minigraph]') config_reload(duthost, config_source='minigraph') - buffer_model = duthost.shell('redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] - pytest_assert(buffer_model == 'traditional', 'Got buffer model {} after executing config load_minigraph, traditional expected') + buffer_model = duthost.shell( + 'redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] + pytest_assert(buffer_model == 'traditional', + 'Got buffer model {} after executing config load_minigraph, traditional expected') logging.info('[Recover the DUT to default buffer model]') _recovery_to_dynamic_buffer_model(duthost) - buffer_model = duthost.shell('redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] - pytest_assert(buffer_model == 'dynamic', 'Got buffer model {} after executing recovering the buffer model to dynamic') + buffer_model = duthost.shell( + 'redis-cli -n 4 hget "DEVICE_METADATA|localhost" buffer_model')['stdout'] + pytest_assert(buffer_model == 'dynamic', + 'Got buffer model {} after executing recovering the buffer model to dynamic') finally: _recovery_to_dynamic_buffer_model(duthost) @@ -2240,7 +2700,8 @@ def test_buffer_deployment(duthosts, rand_one_dut_hostname, conn_graph_facts, tb 1. For all ports in the config_db, - Check whether there is no lossless buffer PG configured on an admin-down port - Check whether the lossless PG and queues aligns with the port's speed and cable length - - If name to oid maps exist for port and PG, check whether the information in ASIC_DB aligns with that in CONFIG_DB + - If name to oid maps exist for port and PG, check whether the information in ASIC_DB aligns with that in + CONFIG_DB - If a lossless profile hasn't been checked, check whether lossless profile in CONFIG_DB aligns with - pg_profile_lookup.ini according to speed and cable length - information in ASIC_DB @@ -2266,7 +2727,8 @@ def _check_condition(condition, message, use_assert): return True - def _check_buffer_item_in_asic_db(duthost, port, buffer_item, name_map, buffer_profile_oid, asic_key_name, should_have_profile, use_assert): + def _check_buffer_item_in_asic_db(duthost, port, buffer_item, name_map, buffer_profile_oid, asic_key_name, + should_have_profile, use_assert): """Check whether the buffer queues or priority groups align between APPL_DB and ASIC_DB Args: @@ -2281,19 +2743,23 @@ def _check_buffer_item_in_asic_db(duthost, port, buffer_item, name_map, buffer_p It should return false if it is called in a wait_until loop """ buffer_item_asic_oid = name_map['{}:{}'.format(port, buffer_item)] - buffer_item_asic_key = duthost.shell('redis-cli -n 1 keys *{}*'.format(buffer_item_asic_oid))['stdout'] - buffer_profile_oid_in_pg = duthost.shell('redis-cli -n 1 hget {} {}'.format(buffer_item_asic_key, asic_key_name))['stdout'] + buffer_item_asic_key = duthost.shell( + 'redis-cli -n 1 keys *{}*'.format(buffer_item_asic_oid))['stdout'] + buffer_profile_oid_in_pg = duthost.shell( + 'redis-cli -n 1 hget {} {}'.format(buffer_item_asic_key, asic_key_name))['stdout'] if should_have_profile: if buffer_profile_oid: if not _check_condition(buffer_profile_oid == buffer_profile_oid_in_pg, - "Different OIDs in buffer items ({}) and ({}) in port {}".format(buffer_profile_oid, buffer_profile_oid_in_pg, port), + "Different OIDs in buffer items ({}) and ({}) in port {}".format( + buffer_profile_oid, buffer_profile_oid_in_pg, port), use_assert): return None, False else: buffer_profile_oid = buffer_profile_oid_in_pg else: if not _check_condition(not buffer_profile_oid_in_pg or buffer_profile_oid_in_pg == 'oid:0x0', - "Buffer PG configured on admin down port in ASIC_DB {}".format(port), + "Buffer PG configured on admin down port in ASIC_DB {}".format( + port), use_assert): return None, False @@ -2328,7 +2794,8 @@ def _check_port_buffer_info_and_get_profile_oid(duthost, table, ids, port, expec Return: A tuple consisting of the OID of buffer profile and whether there is any check failed """ - profile_in_db = duthost.shell('redis-cli hget "{}:{}:{}" profile'.format(table, port, ids))['stdout'] + profile_in_db = duthost.shell( + 'redis-cli hget "{}:{}:{}" profile'.format(table, port, ids))['stdout'] buffer_profile_oid = None if table == 'BUFFER_PG_TABLE': sai_field = 'SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE' @@ -2340,23 +2807,31 @@ def _check_port_buffer_info_and_get_profile_oid(duthost, table, ids, port, expec id_list = _ids_to_id_list(ids) if expected_profile: - if not _check_condition(profile_in_db == expected_profile, "The profile of {}:{}:{} isn't the expected ({})".format(table, port, ids, expected_profile), use_assert): + if not _check_condition(profile_in_db == expected_profile, + "The profile of {}:{}:{} isn't the expected ({})".format(table, port, ids, + expected_profile), + use_assert): return None, False if buffer_name_map: buffer_profile_oid = None for item in id_list: - logging.info("Checking {}:{}:{} in ASIC_DB".format(table, port, item)) - buffer_profile_oid, success = _check_buffer_item_in_asic_db(duthost, port, item, buffer_name_map, buffer_profile_oid, sai_field, True, use_assert) + logging.info( + "Checking {}:{}:{} in ASIC_DB".format(table, port, item)) + buffer_profile_oid, success = _check_buffer_item_in_asic_db( + duthost, port, item, buffer_name_map, buffer_profile_oid, sai_field, True, use_assert) if not success: return None, False else: - if not _check_condition(not profile_in_db, "{}:{}:{} configured on admin down port".format(table, port, ids), use_assert): + if not _check_condition(not profile_in_db, + "{}:{}:{} configured on admin down port".format(table, port, ids), use_assert): return None, False if buffer_name_map: for item in id_list: - logging.info("Checking {}:{}:{} in ASIC_DB".format(table, port, item)) - buffer_profile_oid, success = _check_buffer_item_in_asic_db(duthost, port, item, buffer_name_map, None, sai_field, False, use_assert) + logging.info( + "Checking {}:{}:{} in ASIC_DB".format(table, port, item)) + buffer_profile_oid, success = _check_buffer_item_in_asic_db( + duthost, port, item, buffer_name_map, None, sai_field, False, use_assert) return buffer_profile_oid, True @@ -2373,68 +2848,98 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi Return: Whether all the checks passed """ - _, result = _check_port_buffer_info_and_get_profile_oid(duthost, table, ids, port, expected_profile, False) + _, result = _check_port_buffer_info_and_get_profile_oid( + duthost, table, ids, port, expected_profile, False) return result duthost = duthosts[rand_one_dut_hostname] - asic_type = duthost.get_asic_name() # Skip the legacy branches skip_release(duthost, ["201811", "201911"]) # Check whether the COUNTERS_PG_NAME_MAP and COUNTERS_QUEUE_NAME_MAP exists. Skip ASIC_DB checking if it isn't - pg_name_map = _compose_dict_from_cli(duthost.shell('redis-cli -n 2 hgetall COUNTERS_PG_NAME_MAP')['stdout'].split()) - queue_name_map = _compose_dict_from_cli(duthost.shell('redis-cli -n 2 hgetall COUNTERS_QUEUE_NAME_MAP')['stdout'].split()) - cable_length_map = _compose_dict_from_cli(duthost.shell('redis-cli -n 4 hgetall "CABLE_LENGTH|AZURE"')['stdout'].split()) + pg_name_map = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 2 hgetall COUNTERS_PG_NAME_MAP')['stdout'].split()) + queue_name_map = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 2 hgetall COUNTERS_QUEUE_NAME_MAP')['stdout'].split()) + cable_length_map = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 4 hgetall "CABLE_LENGTH|AZURE"')['stdout'].split()) buffer_table_up = { KEY_2_LOSSLESS_QUEUE: [('BUFFER_PG_TABLE', '0', '[BUFFER_PROFILE_TABLE:ingress_lossy_profile]'), - ('BUFFER_QUEUE_TABLE', '0-2', '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), - ('BUFFER_QUEUE_TABLE', '3-4', '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), - ('BUFFER_QUEUE_TABLE', '5-6', '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), - (None, None, None) - ], + ('BUFFER_QUEUE_TABLE', '0-2', + '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), + ('BUFFER_QUEUE_TABLE', '3-4', + '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), + ('BUFFER_QUEUE_TABLE', '5-6', + '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), + (None, None, None) + ], KEY_4_LOSSLESS_QUEUE: [('BUFFER_PG_TABLE', '0', '[BUFFER_PROFILE_TABLE:ingress_lossy_profile]'), - ('BUFFER_QUEUE_TABLE', '0-1', '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), - ('BUFFER_QUEUE_TABLE', '2-4', '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), - ('BUFFER_QUEUE_TABLE', '5', '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), - ('BUFFER_QUEUE_TABLE', '6', '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), - ('BUFFER_QUEUE_TABLE', '7', '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), - (None, None, None) - ] + ('BUFFER_QUEUE_TABLE', '0-1', + '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), + ('BUFFER_QUEUE_TABLE', '2-4', + '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), + ('BUFFER_QUEUE_TABLE', '5', + '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), + ('BUFFER_QUEUE_TABLE', '6', + '[BUFFER_PROFILE_TABLE:egress_lossless_profile]'), + ('BUFFER_QUEUE_TABLE', '7', + '[BUFFER_PROFILE_TABLE:q_lossy_profile]'), + (None, None, None) + ] } if is_tunnel_qos_remap_enabled(duthost): - buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:q_lossy_profile]') + buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:q_lossy_profile]') if not is_mellanox_device(duthost): - buffer_table_up[KEY_2_LOSSLESS_QUEUE][1] = ('BUFFER_QUEUE_TABLE', '0-2', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_table_up[KEY_2_LOSSLESS_QUEUE][1] = ( + 'BUFFER_QUEUE_TABLE', '0-2', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') if is_tunnel_qos_remap_enabled(duthost): - buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') else: - buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-6', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') - - buffer_table_up[KEY_4_LOSSLESS_QUEUE][1] = ('BUFFER_QUEUE_TABLE', '0-1', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') - buffer_table_up[KEY_4_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') - buffer_table_up[KEY_4_LOSSLESS_QUEUE][5] = ('BUFFER_QUEUE_TABLE', '7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-6', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + if is_barefoot_device(duthost): + buffer_table_up[KEY_2_LOSSLESS_QUEUE][1] = ( + 'BUFFER_QUEUE_TABLE', '0-2', '[BUFFER_PROFILE_TABLE:]') + buffer_table_up[KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-6', '[BUFFER_PROFILE_TABLE:]') + + buffer_table_up[KEY_4_LOSSLESS_QUEUE][1] = ( + 'BUFFER_QUEUE_TABLE', '0-1', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_table_up[KEY_4_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_table_up[KEY_4_LOSSLESS_QUEUE][5] = ( + 'BUFFER_QUEUE_TABLE', '7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') buffer_table_down = { KEY_2_LOSSLESS_QUEUE: [('BUFFER_PG_TABLE', '0', '[BUFFER_PROFILE_TABLE:ingress_lossy_pg_zero_profile]'), - ('BUFFER_QUEUE_TABLE', '0-2', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]'), - ('BUFFER_QUEUE_TABLE', '3-4', '[BUFFER_PROFILE_TABLE:egress_lossless_zero_profile]'), - ('BUFFER_QUEUE_TABLE', '5-6', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]'), - (None, None, None) - ], - KEY_4_LOSSLESS_QUEUE: [(None, None, None)] # The admin_down ports can not be dualtor_ports. Hence there is no 4_lossless_queue profile + ('BUFFER_QUEUE_TABLE', '0-2', + '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]'), + ('BUFFER_QUEUE_TABLE', '3-4', + '[BUFFER_PROFILE_TABLE:egress_lossless_zero_profile]'), + ('BUFFER_QUEUE_TABLE', '5-6', + '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]'), + (None, None, None) + ], + # The admin_down ports can not be dualtor_ports. Hence there is no 4_lossless_queue profile + KEY_4_LOSSLESS_QUEUE: [(None, None, None)] } if is_tunnel_qos_remap_enabled(duthost): - buffer_table_down[KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]') - - buffer_items_to_check_dict = {"up": buffer_table_up, "down": buffer_table_down} + buffer_table_down[KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]') + buffer_items_to_check_dict = { + "up": buffer_table_up, "down": buffer_table_down} if is_innovium_device(duthost): - buffer_items_to_check_dict["up"][KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') - buffer_items_to_check_dict["down"][KEY_2_LOSSLESS_QUEUE][3] = ('BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]') + buffer_items_to_check_dict["up"][KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_profile]') + buffer_items_to_check_dict["down"][KEY_2_LOSSLESS_QUEUE][3] = ( + 'BUFFER_QUEUE_TABLE', '5-7', '[BUFFER_PROFILE_TABLE:egress_lossy_zero_profile]') if check_qos_db_fv_reference_with_table(duthost): profile_wrapper = '[BUFFER_PROFILE_TABLE:{}]' @@ -2446,22 +2951,26 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi for item in buffer_items_to_check: table, ids, profiles = item if profiles: - profiles = profiles.replace('[BUFFER_PROFILE_TABLE:', '').replace(']', '') + profiles = profiles.replace( + '[BUFFER_PROFILE_TABLE:', '').replace(']', '') new_buffer_items_to_check.append((table, ids, profiles)) buffer_items_to_check_dict[status][queue_4_6] = new_buffer_items_to_check profile_wrapper = '{}' is_qos_db_reference_with_table = False - configdb_ports = [x.split('|')[1] for x in duthost.shell('redis-cli -n 4 keys "PORT|*"')['stdout'].split()] + configdb_ports = [x.split('|')[1] for x in duthost.shell( + 'redis-cli -n 4 keys "PORT|*"')['stdout'].split()] profiles_checked = {} lossless_pool_oid = None admin_up_ports = set() for port in configdb_ports: logging.info("Checking port buffer information: {}".format(port)) - port_config = _compose_dict_from_cli(duthost.shell('redis-cli -n 4 hgetall "PORT|{}"'.format(port))['stdout'].split()) + port_config = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 4 hgetall "PORT|{}"'.format(port))['stdout'].split()) cable_length = cable_length_map[port] speed = port_config['speed'] - expected_profile = make_expected_profile_name(speed, cable_length, number_of_lanes=len(port_config['lanes'].split(','))) + expected_profile = make_expected_profile_name( + speed, cable_length, number_of_lanes=len(port_config['lanes'].split(','))) if port in dualtor_ports: key_name = KEY_4_LOSSLESS_QUEUE @@ -2475,9 +2984,10 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi if key_name == KEY_4_LOSSLESS_QUEUE: buffer_items_to_check.extend( [('BUFFER_PG_TABLE', '2-4', profile_wrapper.format(expected_profile)), - ('BUFFER_PG_TABLE', '6', profile_wrapper.format(expected_profile))]) + ('BUFFER_PG_TABLE', '6', profile_wrapper.format(expected_profile))]) else: - buffer_items_to_check.append(('BUFFER_PG_TABLE', '3-4', profile_wrapper.format(expected_profile))) + buffer_items_to_check.append( + ('BUFFER_PG_TABLE', '3-4', profile_wrapper.format(expected_profile))) else: if is_mellanox_device(duthost): buffer_items_to_check = buffer_items_to_check_dict["down"][key_name] @@ -2485,36 +2995,49 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi buffer_items_to_check = [(None, None, None)] for table, ids, expected_profile in buffer_items_to_check: - logging.info("Checking buffer item {}:{}:{}".format(table, port, ids)) + logging.info( + "Checking buffer item {}:{}:{}".format(table, port, ids)) if not expected_profile: continue - buffer_profile_oid, _ = _check_port_buffer_info_and_get_profile_oid(duthost, table, ids, port, expected_profile) + buffer_profile_oid, _ = _check_port_buffer_info_and_get_profile_oid( + duthost, table, ids, port, expected_profile) if is_qos_db_reference_with_table: expected_profile_key = expected_profile[1:-1] else: - expected_profile_key = "BUFFER_PROFILE_TABLE:{}".format(expected_profile) + expected_profile_key = "BUFFER_PROFILE_TABLE:{}".format( + expected_profile) if expected_profile not in profiles_checked: - profile_info = _compose_dict_from_cli(duthost.shell('redis-cli hgetall "{}"'.format(expected_profile_key))['stdout'].split()) + profile_info = _compose_dict_from_cli(duthost.shell( + 'redis-cli hgetall "{}"'.format(expected_profile_key))['stdout'].split()) is_ingress_lossless = expected_profile[:12] == 'pg_lossless_' if is_ingress_lossless and not BUFFER_MODEL_DYNAMIC: - std_profiles_for_speed = DEFAULT_LOSSLESS_HEADROOM_DATA.get(speed) + std_profiles_for_speed = DEFAULT_LOSSLESS_HEADROOM_DATA.get( + speed) if std_profiles_for_speed: std_profile = std_profiles_for_speed.get(cable_length) if std_profile: - # This means it's a profile with std speed and cable length. We can check whether the headroom data is correct - pytest_assert(profile_info['xon'] == std_profile['xon'] and profile_info['xoff'] == std_profile['xoff'] - and (profile_info['size'] == std_profile['size'] or DEFAULT_SHARED_HEADROOM_POOL_ENABLED), - "Buffer profile {} {} doesn't match default {}".format(expected_profile, profile_info, std_profile)) + # This means it's a profile with std speed and cable length. We can check whether the + # headroom data is correct + pytest_assert(profile_info['xon'] == std_profile['xon'] and + profile_info['xoff'] == std_profile['xoff'] and + (profile_info['size'] == std_profile['size'] or + DEFAULT_SHARED_HEADROOM_POOL_ENABLED), + "Buffer profile {} {} doesn't match default {}".format(expected_profile, + profile_info, + std_profile)) if buffer_profile_oid: # Further check the buffer profile in ASIC_DB - logging.info("Checking profile {} oid {}".format(expected_profile, buffer_profile_oid)) - buffer_profile_key = duthost.shell('redis-cli -n 1 keys *{}*'.format(buffer_profile_oid))['stdout'] - buffer_profile_asic_info = _compose_dict_from_cli(duthost.shell('redis-cli -n 1 hgetall {}'.format(buffer_profile_key))['stdout'].split()) + logging.info("Checking profile {} oid {}".format( + expected_profile, buffer_profile_oid)) + buffer_profile_key = duthost.shell( + 'redis-cli -n 1 keys *{}*'.format(buffer_profile_oid))['stdout'] + buffer_profile_asic_info = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 1 hgetall {}'.format(buffer_profile_key))['stdout'].split()) pytest_assert(buffer_profile_asic_info.get('SAI_BUFFER_PROFILE_ATTR_XON_TH') == profile_info.get('xon') and buffer_profile_asic_info.get('SAI_BUFFER_PROFILE_ATTR_XOFF_TH') == profile_info.get('xoff') and buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_RESERVED_BUFFER_SIZE'] == profile_info['size'] and @@ -2522,7 +3045,8 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH'] == profile_info['dynamic_th'] or buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE'] == 'SAI_BUFFER_PROFILE_THRESHOLD_MODE_STATIC' and buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_SHARED_STATIC_TH'] == profile_info['static_th']), - "Buffer profile {} {} doesn't align with ASIC_TABLE {}".format(expected_profile, profile_info, buffer_profile_asic_info)) + "Buffer profile {} {} doesn't align with ASIC_TABLE {}".format(expected_profile, + profile_info, buffer_profile_asic_info)) profiles_checked[expected_profile] = buffer_profile_oid if is_ingress_lossless: @@ -2530,7 +3054,10 @@ def _check_port_buffer_info_and_return(duthost, table, ids, port, expected_profi lossless_pool_oid = buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_POOL_ID'] else: pytest_assert(lossless_pool_oid == buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_POOL_ID'], - "Buffer profile {} has different buffer pool id {} from others {}".format(expected_profile, buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_POOL_ID'], lossless_pool_oid)) + "Buffer profile {} has different buffer pool id {} from others {}".format( + expected_profile, + buffer_profile_asic_info['SAI_BUFFER_PROFILE_ATTR_POOL_ID'], + lossless_pool_oid)) else: pytest_assert(profiles_checked[expected_profile] == buffer_profile_oid, "PG {}:{} has different OID of profile from other PGs sharing the same profile {}".format(port, ids, expected_profile)) @@ -2541,7 +3068,8 @@ def _profile_name(duthost, port, pg_id_name): if is_mellanox_device(duthost): profile_name = None else: - profile_name = duthost.shell('redis-cli hget "BUFFER_PG_TABLE:{}:{}" profile'.format(port, pg_id_name))['stdout'] + profile_name = duthost.shell( + 'redis-cli hget "BUFFER_PG_TABLE:{}:{}" profile'.format(port, pg_id_name))['stdout'] return profile_name @@ -2552,17 +3080,25 @@ def _profile_name(duthost, port, pg_id_name): pg_id_names = ["3-4"] try: # Shutdown the port and check whether the lossless PG has been remvoed - logging.info("Shut down an admin-up port {} and check its buffer information".format(port_to_shutdown)) - duthost.shell('config interface shutdown {}'.format(port_to_shutdown)) + logging.info( + "Shut down an admin-up port {} and check its buffer information".format(port_to_shutdown)) + duthost.shell( + 'config interface shutdown {}'.format(port_to_shutdown)) for pg_id_name in pg_id_names: - wait_until(60, 5, 0, _check_port_buffer_info_and_return, duthost, 'BUFFER_PG_TABLE', pg_id_name, port_to_shutdown, _profile_name(duthost, port, pg_id_name)) + wait_until(60, 5, 0, _check_port_buffer_info_and_return, duthost, 'BUFFER_PG_TABLE', + pg_id_name, port_to_shutdown, _profile_name(duthost, port, pg_id_name)) # Startup the port and check whether the lossless PG has been reconfigured - logging.info("Re-startup the port {} and check its buffer information".format(port_to_shutdown)) - duthost.shell('config interface startup {}'.format(port_to_shutdown)) + logging.info( + "Re-startup the port {} and check its buffer information".format(port_to_shutdown)) + duthost.shell( + 'config interface startup {}'.format(port_to_shutdown)) for pg_id_name in pg_id_names: - wait_until(60, 5, 0, _check_port_buffer_info_and_return, duthost, 'BUFFER_PG_TABLE', pg_id_name, port_to_shutdown, _profile_name(duthost, port, pg_id_name)) + wait_until(60, 5, 0, _check_port_buffer_info_and_return, duthost, 'BUFFER_PG_TABLE', + pg_id_name, port_to_shutdown, _profile_name(duthost, port, pg_id_name)) finally: - duthost.shell('config interface startup {}'.format(port_to_shutdown), module_ignore_errors=True) + duthost.shell('config interface startup {}'.format( + port_to_shutdown), module_ignore_errors=True) + def calculate_headroom_data(duthost, port_to_test): """ @@ -2571,6 +3107,8 @@ def calculate_headroom_data(duthost, port_to_test): """ if ASIC_TYPE == 'mellanox': return mellanox_calculate_headroom_data(duthost, port_to_test) + elif ASIC_TYPE == 'barefoot': + return barefoot_calculate_headroom_data(duthost, port_to_test) else: return False, None @@ -2578,8 +3116,10 @@ def calculate_headroom_data(duthost, port_to_test): def mellanox_calculate_headroom_data(duthost, port_to_test): """ This function is Mellanox platform specific. - It intends to calculate the headroom size based on the input port attributes(speed, cable_length, number of lanes..., etc) - This algorithm is the same as the implementation in https://github.com/sonic-net/sonic-swss/blob/master/cfgmgr/buffer_headroom_mellanox.lua + It intends to calculate the headroom size based on the input port attributes(speed, cable_length, + number of lanes..., etc) + This algorithm is the same as the implementation in + https://github.com/sonic-net/sonic-swss/blob/master/cfgmgr/buffer_headroom_mellanox.lua """ global ASIC_TABLE_KEYS_LOADED global CELL_SIZE @@ -2609,20 +3149,23 @@ def mellanox_calculate_headroom_data(duthost, port_to_test): # elif advertised speeds is configured or supported speeds is fetched # effective speed is the maximum speed in the speeds list # else the effective speed can not be conducted and the test fail - port_info = _compose_dict_from_cli(duthost.shell('redis-cli -n 4 hgetall "PORT|{}"'.format(port_to_test))['stdout'].split('\n')) + port_info = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 4 hgetall "PORT|{}"'.format(port_to_test))['stdout'].split('\n')) if port_info.get('autoneg') == 'on': adv_speeds = port_info.get('adv_speeds') if adv_speeds and adv_speeds != 'all': available_speeds = adv_speeds else: - available_speeds = duthost.shell('redis-cli -n 6 hget "PORT_TABLE|{}" "supported_speeds"'.format(port_to_test))['stdout'] + available_speeds = duthost.shell( + 'redis-cli -n 6 hget "PORT_TABLE|{}" "supported_speeds"'.format(port_to_test))['stdout'] port_speed_raw = natsorted(available_speeds.split(','))[-1] else: port_speed_raw = port_info.get('speed') if port_speed_raw: port_speed = int(port_speed_raw) else: - logging.error("failed to get speed from config db for port {}".format(port_to_test)) + logging.error( + "failed to get speed from config db for port {}".format(port_to_test)) return False, None # Get pause_quanta with port speed from pause_quanta_per_speed_dict @@ -2631,52 +3174,66 @@ def mellanox_calculate_headroom_data(duthost, port_to_test): else: # Get default peer response time from State DB # Command: redis-cli -n 6 hget "ASIC_TABLE|MELLANOX-SPECTRUM-3" "peer_response_time" - peer_response_time_keys = duthost.shell('redis-cli -n 6 keys ASIC_TABLE*')['stdout'] - peer_response_time = float(duthost.shell('redis-cli -n 6 hget "{}" "peer_response_time"'.format(peer_response_time_keys))['stdout']) + peer_response_time_keys = duthost.shell( + 'redis-cli -n 6 keys ASIC_TABLE*')['stdout'] + peer_response_time = float(duthost.shell( + 'redis-cli -n 6 hget "{}" "peer_response_time"'.format(peer_response_time_keys))['stdout']) use_default_peer_response_time = True # Get port mtu from config DB # Command: redis-cli -n 4 hget "PORT|Ethernet0" 'mtu' - port_mtu_raw = duthost.shell('redis-cli -n 4 hget "PORT|{}" "mtu"'.format(port_to_test))['stdout'] + port_mtu_raw = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" "mtu"'.format(port_to_test))['stdout'] if port_mtu_raw: port_mtu = int(port_mtu_raw) else: - logging.error("failed to get MTU from config db for port {}".format(port_to_test)) + logging.error( + "failed to get MTU from config db for port {}".format(port_to_test)) return False, None # Determine gearbox_delay with platform name, so far only MSN3800 has gear_box installed if duthost.facts["platform"] not in ["x86_64-mlnx_msn3800-r0"]: gearbox_delay = 0 else: - gearbox_delay_keys = duthost.shell('redis-cli -n 6 keys PERIPHERAL_TABLE*')['stdout'] - gearbox_delay = float(duthost.shell('redis-cli -n 6 hget "{}" "gearbox_delay"'.format(gearbox_delay_keys))['stdout']) + gearbox_delay_keys = duthost.shell( + 'redis-cli -n 6 keys PERIPHERAL_TABLE*')['stdout'] + gearbox_delay = float(duthost.shell( + 'redis-cli -n 6 hget "{}" "gearbox_delay"'.format(gearbox_delay_keys))['stdout']) # Get cable length from config DB # Command: redis-cli -n 4 hget "CABLE_LENGTH|AZURE" 'Ethernet0' - cable_length_keys = duthost.shell('redis-cli -n 4 keys *CABLE_LENGTH*')['stdout'] - cable_length_raw = duthost.shell('redis-cli -n 4 hget "{}" "{}"'.format(cable_length_keys, port_to_test))['stdout'] + cable_length_keys = duthost.shell( + 'redis-cli -n 4 keys *CABLE_LENGTH*')['stdout'] + cable_length_raw = duthost.shell( + 'redis-cli -n 4 hget "{}" "{}"'.format(cable_length_keys, port_to_test))['stdout'] if cable_length_raw and cable_length_raw.endswith('m'): cable_length = float(cable_length_raw[:-1]) else: - logging.error("failed to get a valid cable length from config db for port {}".format(port_to_test)) + logging.error( + "failed to get a valid cable length from config db for port {}".format(port_to_test)) return False, None - logging.info('port_speed = {}, port_mtu = {}, cable_length = {}'.format(port_speed, port_mtu, cable_length)) + logging.info('port_speed = {}, port_mtu = {}, cable_length = {}'.format( + port_speed, port_mtu, cable_length)) # Get port lanes number from config DB # Command: redis-cli -n 4 hget "PORT|Ethernet0" 'lanes' - port_lanes = duthost.shell('redis-cli -n 4 hget "PORT|{}" "lanes"'.format(port_to_test))['stdout'] + port_lanes = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" "lanes"'.format(port_to_test))['stdout'] is_8lane = port_lanes and len(port_lanes.split(',')) == 8 if not ASIC_TABLE_KEYS_LOADED: - CELL_SIZE, PIPELINE_LATENCY, MAC_PHY_DELAY = get_asic_table_data_from_db(duthost) + CELL_SIZE, PIPELINE_LATENCY, MAC_PHY_DELAY = get_asic_table_data_from_db( + duthost) if not LOSSLESS_TRAFFIC_PATTERN_KEYS_LOADED: - LOSSLESS_MTU, SMALL_PACKET_PERCENTAGE = get_lossless_traffic_pattern_data_from_db(duthost) + LOSSLESS_MTU, SMALL_PACKET_PERCENTAGE = get_lossless_traffic_pattern_data_from_db( + duthost) # Get over_subscribe_ratio from config DB # Command: redis-cli -n 4 hget "DEFAULT_LOSSLESS_BUFFER_PARAMETER|AZURE" 'over_subscribe_ratio' - default_lossless_param_keys = duthost.shell('redis-cli -n 4 keys DEFAULT_LOSSLESS_BUFFER_PARAMETER*')['stdout'][0] + default_lossless_param_keys = duthost.shell( + 'redis-cli -n 4 keys DEFAULT_LOSSLESS_BUFFER_PARAMETER*')['stdout'][0] over_subscribe_ratio_raw = duthost.shell( 'redis-cli -n 4 hget "{}" "over_subscribe_ratio"'.format(default_lossless_param_keys))['stdout'] if over_subscribe_ratio_raw: @@ -2684,7 +3241,8 @@ def mellanox_calculate_headroom_data(duthost, port_to_test): else: over_subscribe_ratio = None - shp_size_raw = duthost.shell('redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool", "xoff"')['stdout'] + shp_size_raw = duthost.shell( + 'redis-cli -n 4 hget "BUFFER_POOL|ingress_lossless_pool", "xoff"')['stdout'] if shp_size_raw: shp_size = float(shp_size_raw) else: @@ -2717,18 +3275,22 @@ def mellanox_calculate_headroom_data(duthost, port_to_test): else: worst_case_factor = (2 * CELL_SIZE) / (1 + CELL_SIZE) - cell_occupancy = (100 - SMALL_PACKET_PERCENTAGE + SMALL_PACKET_PERCENTAGE * worst_case_factor) / 100 + cell_occupancy = (100 - SMALL_PACKET_PERCENTAGE + + SMALL_PACKET_PERCENTAGE * worst_case_factor) / 100 if gearbox_delay == 0: bytes_on_gearbox = 0 else: bytes_on_gearbox = port_speed * gearbox_delay / (8 * 1024) - logging.debug('gearbox_delay = {}, bytes_on_gearbox = {}'.format(gearbox_delay, bytes_on_gearbox)) + logging.debug('gearbox_delay = {}, bytes_on_gearbox = {}'.format( + gearbox_delay, bytes_on_gearbox)) if not use_default_peer_response_time: peer_response_time = (float(pause_quanta)) * 512 / (1024 * 8) - bytes_on_cable = 2 * (float(cable_length)) * port_speed * 1000000000 / speed_of_light / (8 * 1024) - propagation_delay = port_mtu + bytes_on_cable + 2 * bytes_on_gearbox + MAC_PHY_DELAY + peer_response_time * 1024 + bytes_on_cable = 2 * (float(cable_length)) * port_speed * \ + 1000000000 / speed_of_light / (8 * 1024) + propagation_delay = port_mtu + bytes_on_cable + 2 * \ + bytes_on_gearbox + MAC_PHY_DELAY + peer_response_time * 1024 # Calculate the xoff and xon and then round up at 1024 bytes xoff_value = LOSSLESS_MTU + propagation_delay * cell_occupancy @@ -2747,3 +3309,128 @@ def mellanox_calculate_headroom_data(duthost, port_to_test): head_room_data['xon'] = int(xon_value) head_room_data['xoff'] = int(xoff_value) return True, head_room_data + + +def barefoot_calculate_headroom_data(duthost, port_to_test): + """ + Calculates the headroom size based on the input port attributes; speed, cable length, MTU + It is the Python implementation of buffer_headroom_barefoot.lua script. + It can be found here: https://github.com/Azure/sonic-swss/blob/master/cfgmgr/buffer_headroom_barefoot.lua + """ + global ASIC_TABLE_KEYS_LOADED + global CELL_SIZE + global PIPELINE_LATENCY + global MAC_PHY_DELAY + + global LOSSLESS_TRAFFIC_PATTERN_KEYS_LOADED + global LOSSLESS_MTU + global SMALL_PACKET_PERCENTAGE + + peer_response_time = 0 + use_default_peer_response_time = False + + head_room_data = {} + + # Init pause_quanta_per_speed_dict + pause_quanta_per_speed_dict = {400000: 905, 200000: 453, 100000: 394, 50000: 147, 40000: 118, 25000: 80, 10000: 67, + 1000: 2, 100: 1} + port_info = _compose_dict_from_cli(duthost.shell( + 'redis-cli -n 4 hgetall "PORT|{}"'.format(port_to_test))['stdout'].split('\n')) + if port_info.get('autoneg') == 'on': + adv_speeds = port_info.get('adv_speeds') + if adv_speeds and adv_speeds != 'all': + available_speeds = adv_speeds + else: + available_speeds = duthost.shell( + 'redis-cli -n 6 hget "PORT_TABLE|{}" "supported_speeds"'.format(port_to_test))['stdout'] + port_speed_raw = natsorted(available_speeds.split(','))[-1] + else: + port_speed_raw = port_info.get('speed') + if port_speed_raw: + port_speed = int(port_speed_raw) + else: + logging.error( + "failed to get speed from config db for port {}".format(port_to_test)) + return False, None + + # Get pause_quanta with port speed from pause_quanta_per_speed_dict + if port_speed in pause_quanta_per_speed_dict.keys(): + pause_quanta = pause_quanta_per_speed_dict[port_speed] + else: + # Get default peer response time from State DB + # Command: redis-cli -n 6 hget "ASIC_TABLE|BAREFOOT-TOFINO-2" "peer_response_time" + peer_response_time_keys = duthost.shell( + 'redis-cli -n 6 keys ASIC_TABLE*')['stdout'] + peer_response_time = float(duthost.shell( + 'redis-cli -n 6 hget "{}" "peer_response_time"'.format(peer_response_time_keys))['stdout']) + use_default_peer_response_time = True + # Get port mtu from config DB + # Command: redis-cli -n 4 hget "PORT|Ethernet0" "mtu" + port_mtu_raw = duthost.shell( + 'redis-cli -n 4 hget "PORT|{}" "mtu"'.format(port_to_test))['stdout'] + if port_mtu_raw: + port_mtu = int(port_mtu_raw) + else: + logging.error( + "failed to get MTU from config db for port {}".format(port_to_test)) + return False, None + + # Get cable length from config DB + # Command: redis-cli -n 4 hget "CABLE_LENGTH|AZURE" 'Ethernet0' + cable_length_keys = duthost.shell( + 'redis-cli -n 4 keys *CABLE_LENGTH*')['stdout'] + cable_length_raw = duthost.shell( + 'redis-cli -n 4 hget "{}" "{}"'.format(cable_length_keys, port_to_test))['stdout'] + if cable_length_raw and cable_length_raw.endswith('m'): + cable_length = float(cable_length_raw[:-1]) + else: + logging.error( + "failed to get a valid cable length from config db for port {}".format(port_to_test)) + return False, None + + logging.info('port_speed = {}, port_mtu = {}, cable_length = {}'.format( + port_speed, port_mtu, cable_length)) + + if not ASIC_TABLE_KEYS_LOADED: + CELL_SIZE, PIPELINE_LATENCY, MAC_PHY_DELAY = get_asic_table_data_from_db( + duthost) + + if not LOSSLESS_TRAFFIC_PATTERN_KEYS_LOADED: + LOSSLESS_MTU, SMALL_PACKET_PERCENTAGE = get_lossless_traffic_pattern_data_from_db( + duthost) + + speed_of_light = 198000000 + minimal_packet_size = 64 + + if CELL_SIZE > 2 * minimal_packet_size: + worst_case_factor = CELL_SIZE / minimal_packet_size + else: + worst_case_factor = (2 * CELL_SIZE) / (1 + CELL_SIZE) + + cell_occupancy = (100 - SMALL_PACKET_PERCENTAGE + + SMALL_PACKET_PERCENTAGE * worst_case_factor) / 100 + + if not use_default_peer_response_time: + peer_response_time = (float(pause_quanta)) * 512 / (1024 * 8) + + if port_speed == 400000: + peer_response_time *= 2 + bytes_on_cable = 2 * (float(cable_length)) * port_speed * \ + 1000000000 / speed_of_light / (8 * 1024) + propagation_delay = port_mtu + bytes_on_cable + \ + MAC_PHY_DELAY + peer_response_time * 1024 + + # Calculate the xoff and xon and then round up at 1024 bytes + xoff_value = LOSSLESS_MTU + propagation_delay * cell_occupancy + xoff_value = math.ceil(xoff_value / 1024) * 1024 + xon_value = PIPELINE_LATENCY + xon_value = math.ceil(xon_value / 1024) * 1024 + + headroom_size = xon_value + + headroom_size = math.ceil(headroom_size / 1024) * 1024 + + head_room_data['size'] = int(headroom_size) + head_room_data['xon'] = int(xon_value) + head_room_data['xoff'] = int(xoff_value) + return True, head_room_data