diff --git a/.azure-pipelines/pr_test_scripts.yaml b/.azure-pipelines/pr_test_scripts.yaml index fa63203405d..12dc426c3d3 100644 --- a/.azure-pipelines/pr_test_scripts.yaml +++ b/.azure-pipelines/pr_test_scripts.yaml @@ -413,6 +413,7 @@ multi-asic-t1-lag: - snmp/test_snmp_loopback.py - snmp/test_snmp_pfc_counters.py - snmp/test_snmp_queue.py + - snmp/test_snmp_queue_counters.py - tacacs/test_accounting.py - tacacs/test_authorization.py - tacacs/test_jit_user.py diff --git a/tests/snmp/test_snmp_queue_counters.py b/tests/snmp/test_snmp_queue_counters.py index 5098ccb3e66..07a2fdbf4a2 100644 --- a/tests/snmp/test_snmp_queue_counters.py +++ b/tests/snmp/test_snmp_queue_counters.py @@ -24,15 +24,47 @@ def get_queue_ctrs(duthost, cmd): return len(duthost.shell(cmd)["stdout_lines"]) +def get_queue_cntrs_oid(interface): + """ + @summary: Returns queue_cntrs_oid value based on the interface chosen + for single/multi-asic sonic host. + Args: + interface: Asic interface selected + Returns: + queue_cntrs_oid + """ + intf_num = interface.split('Ethernet')[1] + queue_cntrs_oid = '1.3.6.1.4.1.9.9.580.1.5.5.1.4.{}'.format(int(intf_num) + 1) + return queue_cntrs_oid + + +def get_asic_interface(inter_facts): + """ + @summary: Returns interface dynamically based on the asic chosen + for single/multi-asic sonic host. + """ + ansible_inter_facts = inter_facts['ansible_interface_facts'] + interface = None + for key, v in ansible_inter_facts.items(): + # Exclude internal interfaces + if 'IB' in key or 'Rec' in key or 'BP' in key: + continue + if 'Ether' in key and v['active']: + interface = key + break + + return interface + + def test_snmp_queue_counters(duthosts, - enum_rand_one_per_hwsku_frontend_hostname, - creds_all_duts): + enum_rand_one_per_hwsku_frontend_hostname, enum_frontend_asic_index, + creds_all_duts, teardown): """ Test SNMP queue counters - Set "create_only_config_db_buffers" to true in config db, to create only relevant counters - - Remove one of the buffer queues, Ethernet0|3-4 is chosen arbitrary - - Using snmpwalk compare number of queue counters on Ethernet0, assuming + - Remove one of the buffer queues for asic interface chosen, |3-4 is chosen arbitrary + - Using snmpwalk compare number of queue counters on the interface, assuming there will be 8 less after removing the buffer. (Assuming unicast only, 4 counters for each queue in this case) This test covers the issue: 'The feature "polling only configured ports @@ -41,17 +73,42 @@ def test_snmp_queue_counters(duthosts, """ duthost = duthosts[enum_rand_one_per_hwsku_frontend_hostname] + global ORIG_CFG_DB, CFG_DB_PATH hostip = duthost.host.options['inventory_manager'].get_host( duthost.hostname).vars['ansible_host'] - Ethernet0_queue_cntrs_oid = '1.3.6.1.4.1.9.9.580.1.5.5.1.4.1' + asic = duthost.asic_instance(enum_frontend_asic_index) + int_facts = asic.interface_facts()['ansible_facts'] + interface = get_asic_interface(int_facts) + if interface is None: + pytest.skip("No active interface present on the asic {}".format(asic)) + queue_cntrs_oid = get_queue_cntrs_oid(interface) get_bfr_queue_cntrs_cmd \ = "docker exec snmp snmpwalk -v2c -c {} {} {}".format( creds_all_duts[duthost.hostname]['snmp_rocommunity'], hostip, - Ethernet0_queue_cntrs_oid) + queue_cntrs_oid) + # Generate sonic-cfggen commands for multi-asic and single-asic duts + if duthost.sonichost.is_multi_asic and asic is not None: + ORIG_CFG_DB = "/etc/sonic/orig_config_db{}.json".format(asic.asic_index) + CFG_DB_PATH = "/etc/sonic/config_db{}.json".format(asic.asic_index) + cmd = "sonic-cfggen -n {} -d --print-data > {}".format(asic.namespace, ORIG_CFG_DB) + else: + cmd = "sonic-cfggen -d --print-data > {}".format(ORIG_CFG_DB) - duthost.shell("sonic-cfggen -d --print-data > {}".format(ORIG_CFG_DB)) + duthost.shell(cmd) data = json.loads(duthost.shell("cat {}".format(ORIG_CFG_DB), verbose=False)['stdout']) + buffer_queue_to_del = None + # Get appropriate buffer queue value to delete in case of multi-asic + if duthost.sonichost.is_multi_asic: + buffer_queues = list(data['BUFFER_QUEUE'].keys()) + iface_to_check = buffer_queues[0].split('|')[0] + iface_buffer_queues = [bq for bq in buffer_queues if any(val in iface_to_check for val in bq.split('|'))] + for queue in iface_buffer_queues: + if asic.namespace in queue and queue.split('|')[-1] == '3-4' and queue.split('|')[-2] == interface: + buffer_queue_to_del = queue + break + else: + buffer_queue_to_del = "{}|3-4".format(interface) # Add create_only_config_db_buffers entry to device metadata to enable # counters optimization and get number of queue counters of Ethernet0 prior @@ -63,16 +120,26 @@ def test_snmp_queue_counters(duthosts, # Remove buffer queue and reload and get number of queue counters of # Ethernet0 after removing two buffer queues - del data['BUFFER_QUEUE']["Ethernet0|3-4"] + del data['BUFFER_QUEUE'][buffer_queue_to_del] load_new_cfg(duthost, data) queue_counters_cnt_post = get_queue_ctrs(duthost, get_bfr_queue_cntrs_cmd) - unicast_expected_diff = BUFFER_QUEUES_REMOVED * UNICAST_CTRS - multicast_expected_diff = unicast_expected_diff + (BUFFER_QUEUES_REMOVED - * MULTICAST_CTRS) - pytest_assert((queue_counters_cnt_pre - queue_counters_cnt_post) - in [unicast_expected_diff, multicast_expected_diff], - "Queue counters count differs from expected") + # For broadcom-dnx voq chassis, number of voq are fixed (static), which cannot be modified dynamically + # Hence, make sure the queue counters before deletion and after deletion are same for broadcom-dnx voq chassis + if duthost.facts.get("platform_asic") == "broadcom-dnx" and duthost.sonichost.is_multi_asic: + pytest_assert((queue_counters_cnt_pre == queue_counters_cnt_post), + "Queue counters actual count {} differs from expected values {}". + format(queue_counters_cnt_post, queue_counters_cnt_pre)) + # check for other duts + else: + unicast_expected_diff = BUFFER_QUEUES_REMOVED * UNICAST_CTRS + multicast_expected_diff = unicast_expected_diff + (BUFFER_QUEUES_REMOVED + * MULTICAST_CTRS) + pytest_assert((queue_counters_cnt_pre - queue_counters_cnt_post) + in [unicast_expected_diff, multicast_expected_diff], + "Queue counters actual count {} differs from expected values {}, {}". + format(queue_counters_cnt_post, (queue_counters_cnt_pre - unicast_expected_diff), + (queue_counters_cnt_pre - multicast_expected_diff))) @pytest.fixture(scope="module") @@ -83,5 +150,5 @@ def teardown(duthost): """ yield # Cleanup - duthost.copy(src=ORIG_CFG_DB, dest=CFG_DB_PATH) + duthost.copy(src=ORIG_CFG_DB, dest=CFG_DB_PATH, remote_src=True) config_reload(duthost, config_source='config_db', safe_reload=True)