diff --git a/tests/qos/qos_sai_base.py b/tests/qos/qos_sai_base.py index 95525307aa2..032d494c710 100644 --- a/tests/qos/qos_sai_base.py +++ b/tests/qos/qos_sai_base.py @@ -676,8 +676,8 @@ def get_src_dst_asic_and_duts(self, duthosts, tbinfo, select_src_dst_dut_and_asi rtn_dict.update(select_src_dst_dut_and_asic) yield rtn_dict - def __buildTestPorts(self, request, testPortIds, testPortIps, src_port_ids, - dst_port_ids, get_src_dst_asic_and_duts, uplinkPortIds): + def __buildTestPorts(self, request, testPortIds, testPortIps, src_port_ids, dst_port_ids, + get_src_dst_asic_and_duts, uplinkPortIds, sysPortMap=None): """ Build map of test ports index and IPs @@ -688,6 +688,7 @@ def __buildTestPorts(self, request, testPortIds, testPortIps, src_port_ids, Returns: testPorts (dict): Map of test ports index and IPs + sysPortMap (dict): Map of system port IDs and Qos SAI test port IDs """ dstPorts = request.config.getoption("--qos_dst_ports") srcPorts = request.config.getoption("--qos_src_ports") @@ -757,23 +758,40 @@ def __buildTestPorts(self, request, testPortIds, testPortIps, src_port_ids, srcVlan = src_test_port_ips[srcPort]['vlan_id'] if 'vlan_id' in src_test_port_ips[srcPort] else None src_port_ip = src_test_port_ips[srcPorts[0] if src_port_ids else src_test_port_ids[srcPorts[0]]] + # collecting the system ports associated with dst ports + # In case of PortChannel as dst port, all lag ports will be added to the list + # ex. {dstPort: system_port, dstPort1:system_port1 ...} + dst_all_sys_port = {} + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + sysPorts = sysPortMap[get_src_dst_asic_and_duts['dst_dut_index']][ + get_src_dst_asic_and_duts['dst_asic_index']] + for port_id in [dstPort, dstPort2, dstPort3]: + if port_id in sysPorts and port_id not in dst_all_sys_port: + dst_all_sys_port.update({port_id: sysPorts[port_id]['system_port']}) + if 'PortChannel' in sysPorts[port_id]['port_type']: + for sport, sysMap in sysPorts.items(): + if sysMap['port_type'] == sysPorts[port_id]['port_type'] and sport != port_id: + dst_all_sys_port.update({sport: sysMap['system_port']}) + return { - "dst_port_id": dstPort, - "dst_port_ip": dst_test_port_ips[dstPort]['peer_addr'], - "dst_port_ipv6": dst_test_port_ips[dstPort]['peer_addr_ipv6'], - "dst_port_vlan": dstVlan, - "dst_port_2_id": dstPort2, - "dst_port_2_ip": dst_test_port_ips[dstPort2]['peer_addr'], - "dst_port_2_ipv6": dst_test_port_ips[dstPort2]['peer_addr_ipv6'], - "dst_port_2_vlan": dstVlan2, - 'dst_port_3_id': dstPort3, - "dst_port_3_ip": dst_test_port_ips[dstPort3]['peer_addr'], - "dst_port_3_ipv6": dst_test_port_ips[dstPort3]['peer_addr_ipv6'], - "dst_port_3_vlan": dstVlan3, - "src_port_id": srcPort, - "src_port_ip": src_port_ip["peer_addr"], - "src_port_ipv6": src_port_ip["peer_addr_ipv6"], - "src_port_vlan": srcVlan + "dst_port_id": dstPort, + "dst_port_ip": dst_test_port_ips[dstPort]['peer_addr'], + "dst_port_ipv6": dst_test_port_ips[dstPort]['peer_addr_ipv6'], + "dst_port_vlan": dstVlan, + "dst_port_2_id": dstPort2, + "dst_port_2_ip": dst_test_port_ips[dstPort2]['peer_addr'], + "dst_port_2_ipv6": dst_test_port_ips[dstPort2]['peer_addr_ipv6'], + "dst_port_2_vlan": dstVlan2, + 'dst_port_3_id': dstPort3, + "dst_port_3_ip": dst_test_port_ips[dstPort3]['peer_addr'], + "dst_port_3_ipv6": dst_test_port_ips[dstPort3]['peer_addr_ipv6'], + "dst_port_3_vlan": dstVlan3, + "src_port_id": srcPort, + "src_port_ip": src_port_ip["peer_addr"], + "src_port_ipv6": src_port_ip["peer_addr_ipv6"], + "src_port_vlan": srcVlan, + "dst_sys_ports": dst_all_sys_port } @pytest.fixture(scope='class', autouse=True) @@ -807,6 +825,7 @@ def dutConfig( downlinkPortIds = [] downlinkPortIps = [] downlinkPortNames = [] + sysPortMap = {} src_dut_index = get_src_dst_asic_and_duts['src_dut_index'] src_asic_index = get_src_dst_asic_and_duts['src_asic_index'] @@ -950,11 +969,18 @@ def dutConfig( src_asic = get_src_dst_asic_and_duts['src_asic'] dst_dut_index = get_src_dst_asic_and_duts['dst_dut_index'] dst_asic = get_src_dst_asic_and_duts['dst_asic'] + src_system_port = {} + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + src_system_port = src_dut.config_facts(host=src_dut.hostname, source='running')['ansible_facts'][ + 'SYSTEM_PORT'][src_dut.hostname] # Lets get data for the src dut and src asic dutPortIps[src_dut_index] = {} + sysPortMap[src_dut_index] = {} testPortIds[src_dut_index] = {} dutPortIps[src_dut_index][src_asic_index] = {} + sysPortMap[src_dut_index][src_asic_index] = {} active_ips = src_asic.get_active_ip_interfaces(tbinfo, include_ipv6=True) for iface, addr in active_ips.items(): if iface.startswith("Ethernet") and ("Ethernet-Rec" not in iface): @@ -962,6 +988,15 @@ def dutConfig( portIpMap = {'peer_addr': addr["peer_ipv4"], 'peer_addr_ipv6': addr['peer_ipv6'], 'port': iface} dutPortIps[src_dut_index][src_asic_index].update({portIndex: portIpMap}) + # Map port IDs to system port for dnx chassis + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + sys_key = src_asic.namespace + '|' + iface + if sys_key in src_system_port: + system_port = src_system_port[sys_key]['system_port_id'] + sysPort = {'port': iface, 'system_port': system_port, 'port_type': iface} + sysPortMap[src_dut_index][src_asic_index].update({portIndex: sysPort}) + elif iface.startswith("PortChannel"): portName = next( iter(src_mgFacts["minigraph_portchannels"][iface]["members"]) @@ -970,6 +1005,16 @@ def dutConfig( portIpMap = {'peer_addr': addr["peer_ipv4"], 'peer_addr_ipv6': addr['peer_ipv6'], 'port': portName} dutPortIps[src_dut_index][src_asic_index].update({portIndex: portIpMap}) + # Map lag port IDs to system port IDs for dnx chassis + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + for portName in src_mgFacts["minigraph_portchannels"][iface]["members"]: + sys_key = src_asic.namespace + '|' + portName + port_Index = src_mgFacts["minigraph_ptf_indices"][portName] + if sys_key in src_system_port: + system_port = src_system_port[sys_key]['system_port_id'] + sysPort = {'port': portName, 'system_port': system_port, 'port_type': iface} + sysPortMap[src_dut_index][src_asic_index].update({port_Index: sysPort}) testPortIds[src_dut_index][src_asic_index] = sorted(dutPortIps[src_dut_index][src_asic_index].keys()) @@ -981,9 +1026,16 @@ def dutConfig( dst_mgFacts = dst_dut.get_extended_minigraph_facts(tbinfo) dutPortIps[dst_dut_index] = {} testPortIds[dst_dut_index] = {} + sysPortMap[dst_dut_index] = {} + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + dst_system_port = dst_dut.config_facts(host=dst_dut.hostname, source='running')[ + 'ansible_facts']['SYSTEM_PORT'][dst_dut.hostname] else: dst_mgFacts = src_mgFacts + dst_system_port = src_system_port dutPortIps[dst_dut_index][dst_asic_index] = {} + sysPortMap[dst_dut_index][dst_asic_index] = {} active_ips = dst_asic.get_active_ip_interfaces(tbinfo, include_ipv6=True) for iface, addr in active_ips.items(): if iface.startswith("Ethernet") and ("Ethernet-Rec" not in iface): @@ -991,6 +1043,15 @@ def dutConfig( portIpMap = {'peer_addr': addr["peer_ipv4"], 'peer_addr_ipv6': addr['peer_ipv6'], 'port': iface} dutPortIps[dst_dut_index][dst_asic_index].update({portIndex: portIpMap}) + # Map port IDs to system port IDs + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + sys_key = dst_asic.namespace + '|' + iface + if sys_key in dst_system_port: + system_port = dst_system_port[sys_key]['system_port_id'] + sysPort = {'port': iface, 'system_port': system_port, 'port_type': iface} + sysPortMap[dst_dut_index][dst_asic_index].update({portIndex: sysPort}) + elif iface.startswith("PortChannel"): portName = next( iter(dst_mgFacts["minigraph_portchannels"][iface]["members"]) @@ -999,6 +1060,16 @@ def dutConfig( portIpMap = {'peer_addr': addr["peer_ipv4"], 'peer_addr_ipv6': addr['peer_ipv6'], 'port': portName} dutPortIps[dst_dut_index][dst_asic_index].update({portIndex: portIpMap}) + # Map lag port IDs to system port IDs + if 'platform_asic' in get_src_dst_asic_and_duts["src_dut"].facts and \ + get_src_dst_asic_and_duts["src_dut"].facts['platform_asic'] == 'broadcom-dnx': + for portName in dst_mgFacts["minigraph_portchannels"][iface]["members"]: + sys_key = dst_asic.namespace + '|' + portName + port_Index = dst_mgFacts["minigraph_ptf_indices"][portName] + if sys_key in dst_system_port: + system_port = dst_system_port[sys_key]['system_port_id'] + sysPort = {'port': portName, 'system_port': system_port, 'port_type': iface} + sysPortMap[dst_dut_index][dst_asic_index].update({port_Index: sysPort}) testPortIds[dst_dut_index][dst_asic_index] = sorted(dutPortIps[dst_dut_index][dst_asic_index].keys()) @@ -1067,8 +1138,8 @@ def dutConfig( if dualTor: testPortIds = dualTorPortIndexes - testPorts = self.__buildTestPorts(request, testPortIds, testPortIps, - src_port_ids, dst_port_ids, get_src_dst_asic_and_duts, uplinkPortIds) + testPorts = self.__buildTestPorts(request, testPortIds, testPortIps, src_port_ids, dst_port_ids, + get_src_dst_asic_and_duts, uplinkPortIds, sysPortMap) # Update the uplink/downlink ports to testPorts testPorts.update({ "uplink_port_ids": uplinkPortIds, diff --git a/tests/qos/test_qos_sai.py b/tests/qos/test_qos_sai.py index fd96df188fe..e093d7d49c3 100644 --- a/tests/qos/test_qos_sai.py +++ b/tests/qos/test_qos_sai.py @@ -1167,6 +1167,7 @@ def testQosSaiLossyQueue( "buffer_max_size": ingressLossyProfile["static_th"], "headroom_size": ingressLossyProfile["size"], "dst_port_id": dutConfig["testPorts"]["dst_port_id"], + "dst_sys_ports": dutConfig["testPorts"]["dst_sys_ports"], "dst_port_ip": dutConfig["testPorts"]["dst_port_ip"], "dst_port_2_id": dutConfig["testPorts"]["dst_port_2_id"], "dst_port_2_ip": dutConfig["testPorts"]["dst_port_2_ip"], diff --git a/tests/saitests/py3/sai_qos_tests.py b/tests/saitests/py3/sai_qos_tests.py index 1a40a49eb09..88128cec60f 100755 --- a/tests/saitests/py3/sai_qos_tests.py +++ b/tests/saitests/py3/sai_qos_tests.py @@ -36,7 +36,10 @@ sai_thrift_read_buffer_pool_watermark, sai_thrift_read_headroom_pool_watermark, sai_thrift_read_queue_occupancy, - sai_thrift_read_pg_occupancy) + sai_thrift_read_pg_occupancy, + sai_thrift_read_port_voq_counters, + sai_thrift_get_voq_port_id + ) from switch_sai_thrift.ttypes import (sai_thrift_attribute_value_t, sai_thrift_attribute_t) from switch_sai_thrift.sai_headers import SAI_PORT_ATTR_QOS_SCHEDULER_PROFILE_ID @@ -3653,6 +3656,7 @@ def runTest(self): sonic_version = self.test_params['sonic_version'] router_mac = self.test_params['router_mac'] dst_port_id = int(self.test_params['dst_port_id']) + dst_sys_port_ids = self.test_params.get('dst_sys_ports', None) dst_port_ip = self.test_params['dst_port_ip'] dst_port_mac = self.dataplane.get_mac(0, dst_port_id) src_port_id = int(self.test_params['src_port_id']) @@ -3709,6 +3713,15 @@ def runTest(self): self.src_client, asic_type, port_list['src'][src_port_id]) xmit_counters_base, queue_counters = sai_thrift_read_port_counters( self.dst_client, asic_type, port_list['dst'][dst_port_id]) + # for t2 chassis + if platform_asic and platform_asic == "broadcom-dnx": + if dst_port_id in dst_sys_port_ids: + for port_id, sysport in dst_sys_port_ids.items(): + if dst_port_id == port_id: + dst_sys_port_id = int(sysport) + print("actual dst_sys_port_id: %d" % (dst_sys_port_id), file=sys.stderr) + voq_list = sai_thrift_get_voq_port_id(self.src_client, dst_sys_port_id) + voq_queue_counters_base = sai_thrift_read_port_voq_counters(self.src_client, voq_list) # add slight tolerance in threshold characterization to consider # the case that cpu puts packets in the egress queue after we pause the egress # or the leak out is simply less than expected as we have occasionally observed @@ -3776,6 +3789,9 @@ def runTest(self): self.src_client, asic_type, port_list['src'][src_port_id]) xmit_counters, queue_counters = sai_thrift_read_port_counters( self.dst_client, asic_type, port_list['dst'][dst_port_id]) + # for t2 chassis + if platform_asic and platform_asic == "broadcom-dnx": + voq_queue_counters = sai_thrift_read_port_voq_counters(self.src_client, voq_list) # recv port no pfc assert (recv_counters[pg] == recv_counters_base[pg]) # recv port no ingress drop @@ -3822,6 +3838,13 @@ def runTest(self): for cntr in egress_counters: assert (xmit_counters[cntr] > xmit_counters_base[cntr]) + # voq ingress drop + if platform_asic and platform_asic == "broadcom-dnx": + voq_index = pg - 2 + print("voq_counters_base: %d, voq_counters: %d " % (voq_queue_counters_base[voq_index], + voq_queue_counters[voq_index]), file=sys.stderr) + assert (voq_queue_counters[voq_index] > ( + voq_queue_counters_base[voq_index] + pkts_num_trig_egr_drp - margin)) finally: self.sai_thrift_port_tx_enable(self.dst_client, asic_type, [dst_port_id]) diff --git a/tests/saitests/py3/switch.py b/tests/saitests/py3/switch.py index 7ebde5f8034..225aadf12df 100644 --- a/tests/saitests/py3/switch.py +++ b/tests/saitests/py3/switch.py @@ -68,7 +68,7 @@ SAI_INGRESS_PRIORITY_GROUP_STAT_CURR_OCCUPANCY_BYTES -from switch_sai_thrift.sai_headers import SAI_SWITCH_ATTR_SRC_MAC_ADDRESS +from switch_sai_thrift.sai_headers import SAI_SWITCH_ATTR_SRC_MAC_ADDRESS, SAI_SYSTEM_PORT_ATTR_QOS_VOQ_LIST this_dir = os.path.dirname(os.path.abspath(__file__)) @@ -822,6 +822,33 @@ def sai_thrift_read_port_counters(client, asic_type, port): return (counters_results, queue_counters_results) +def sai_thrift_get_voq_port_id(client, system_port_id): + object_id = client.sai_thrift_get_sys_port_obj_id_by_port_id(system_port_id) + voq_list = [] + port_attr_list = client.sai_thrift_get_system_port_attribute(object_id) + attr_list = port_attr_list.attr_list + for attribute in attr_list: + if attribute.id == SAI_SYSTEM_PORT_ATTR_QOS_VOQ_LIST: + for voq_id in attribute.value.objlist.object_id_list: + voq_list.append(voq_id) + return (voq_list) + + +def sai_thrift_read_port_voq_counters(client, voq_list): + cnt_ids = [] + thrift_results = [] + voq_counters_results = [] + cnt_ids.append(SAI_QUEUE_STAT_PACKETS) + counter = 0 + for voq in voq_list: + if counter <= 7: + thrift_results = client.sai_thrift_get_queue_stats( + voq, cnt_ids, len(cnt_ids)) + voq_counters_results.append(thrift_results[0]) + counter += 1 + return (voq_counters_results) + + def sai_thrift_read_port_watermarks(client, port): q_wm_ids = [] q_wm_ids.append(SAI_QUEUE_STAT_SHARED_WATERMARK_BYTES)