Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions tests/common/devices/sonic.py
Original file line number Diff line number Diff line change
Expand Up @@ -1873,22 +1873,6 @@ def is_service_running(self, service_name, docker_name):

return "RUNNING" in service_status

def remove_ssh_tunnel_sai_rpc(self):
"""
Removes any ssh tunnels if present created for syncd RPC communication

Returns:
None
"""
try:
pid_list = self.shell(
'pgrep -f "ssh -o StrictHostKeyChecking=no -fN -L \*:9092"'
)["stdout_lines"]
except RunAnsibleModuleFail:
return
for pid in pid_list:
self.shell("kill {}".format(pid), module_ignore_errors=True)

def get_up_ip_ports(self):
"""
Get a list for all up ip interfaces
Expand Down
20 changes: 16 additions & 4 deletions tests/common/devices/sonic_asic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class SonicAsic(object):

_MULTI_ASIC_SERVICE_NAME = "{}@{}" # service name, asic_id
_MULTI_ASIC_DOCKER_NAME = "{}{}" # docker name, asic_id
_RPC_PORT_FOR_SSH_TUNNEL = 9092

def __init__(self, sonichost, asic_index):
""" Initializing a ASIC on a SONiC host.
Expand Down Expand Up @@ -325,6 +326,9 @@ def bgp_drop_rule(self, ip_version, state="present"):

logger.debug(output)

def get_rpc_port_ssh_tunnel(self):
return self._RPC_PORT_FOR_SSH_TUNNEL + self.asic_index

def remove_ssh_tunnel_sai_rpc(self):
"""
Removes any ssh tunnels if present created for syncd RPC communication
Expand All @@ -334,7 +338,15 @@ def remove_ssh_tunnel_sai_rpc(self):
"""
if not self.sonichost.is_multi_asic:
return
return self.sonichost.remove_ssh_tunnel_sai_rpc()

try:
pid_list = self.sonichost.shell(
r'pgrep -f "ssh -o StrictHostKeyChecking=no -fN -L \*:{}"'.format(self.get_rpc_port_ssh_tunnel())
)["stdout_lines"]
except RunAnsibleModuleFail:
return
for pid in pid_list:
self.shell("kill {}".format(pid), module_ignore_errors=True)

def create_ssh_tunnel_sai_rpc(self):
"""
Expand Down Expand Up @@ -363,9 +375,9 @@ def create_ssh_tunnel_sai_rpc(self):

self.sonichost.shell(
("ssh -o StrictHostKeyChecking=no -fN"
" -L *:9092:{}:9092 localhost"
).format(ns_docker_if_ipv4)
)
" -L *:{}:{}:{} localhost").format(self.get_rpc_port_ssh_tunnel(), ns_docker_if_ipv4,
self._RPC_PORT_FOR_SSH_TUNNEL ))


def command(self, cmdstr):
"""
Expand Down
36 changes: 18 additions & 18 deletions tests/common/fixtures/duthost_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ def utils_create_test_vlans(duthost, cfg_facts, vlan_ports_list, vlan_intfs_dict
duthost.shell_cmds(cmds=cmds)


@pytest.fixture(scope='module')
def dut_qos_maps(rand_selected_front_end_dut):
@pytest.fixture(scope='class')
def dut_qos_maps(get_src_dst_asic_and_duts):
"""
A module level fixture to get QoS map from DUT host.
Return a dict
Expand All @@ -452,32 +452,32 @@ def dut_qos_maps(rand_selected_front_end_dut):
or an empty dict if failed to parse the output
"""
maps = {}
dut = get_src_dst_asic_and_duts['src_dut']
try:
if rand_selected_front_end_dut.is_multi_asic:
if dut.is_multi_asic:
sonic_cfggen_cmd = "sonic-cfggen -n asic0 -d --var-json"
else:
sonic_cfggen_cmd = "sonic-cfggen -d --var-json"

# port_qos_map
port_qos_map_data = rand_selected_front_end_dut.shell("{} 'PORT_QOS_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['port_qos_map'] = json.loads(port_qos_map_data) if port_qos_map_data else None
port_qos_map = dut.shell("{} 'PORT_QOS_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['port_qos_map'] = json.loads(port_qos_map) if port_qos_map else None

# dscp_to_tc_map
dscp_to_tc_map_data = rand_selected_front_end_dut.shell(
"{} 'DSCP_TO_TC_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['dscp_to_tc_map'] = json.loads(dscp_to_tc_map_data) if dscp_to_tc_map_data else None
dscp_to_tc_map = dut.shell("{} 'DSCP_TO_TC_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['dscp_to_tc_map'] = json.loads(dscp_to_tc_map) if dscp_to_tc_map else None

# tc_to_queue_map
tc_to_queue_map_data = rand_selected_front_end_dut.shell(
"{} 'TC_TO_QUEUE_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_queue_map'] = json.loads(tc_to_queue_map_data) if tc_to_queue_map_data else None
tc_to_queue_map = dut.shell("{} 'TC_TO_QUEUE_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_queue_map'] = json.loads(tc_to_queue_map) if tc_to_queue_map else None

# tc_to_priority_group_map
tc_to_priority_group_map_data = rand_selected_front_end_dut.shell(
"{} 'TC_TO_PRIORITY_GROUP_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_priority_group_map'] = json.loads(
tc_to_priority_group_map_data) if tc_to_priority_group_map_data else None
tc_to_priority_group_map = dut.shell("{} 'TC_TO_PRIORITY_GROUP_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_priority_group_map'] = json.loads(tc_to_priority_group_map) if tc_to_priority_group_map else None

# tc_to_dscp_map
tc_to_dscp_map_data = rand_selected_front_end_dut.shell(
"{} 'TC_TO_DSCP_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_dscp_map'] = json.loads(tc_to_dscp_map_data) if tc_to_dscp_map_data else None
tc_to_dscp_map = dut.shell("{} 'TC_TO_DSCP_MAP'".format(sonic_cfggen_cmd))['stdout']
maps['tc_to_dscp_map'] = json.loads(tc_to_dscp_map) if tc_to_dscp_map else None
except Exception as e:
logger.error("Got exception: " + repr(e))
return maps
Expand Down
45 changes: 32 additions & 13 deletions tests/common/fixtures/ptfhost_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,24 +508,34 @@ def ptf_test_port_map_active_active(ptfhost, tbinfo, duthosts, mux_server_url, d
# Loop ptf_map of each DUT. Each ptf_map maps from ptf port index to dut port index
disabled_ptf_ports = disabled_ptf_ports.union(set(ptf_map.keys()))

router_macs = [duthost.facts['router_mac'] for duthost in duthosts]
router_macs = []
all_dut_names = [duthost.hostname for duthost in duthosts]
for a_dut_name in tbinfo['duts']:
if a_dut_name in all_dut_names:
duthost = duthosts[a_dut_name]
router_macs.append(duthost.facts['router_mac'])
else:
router_macs.append(None)

logger.info('active_dut_map={}'.format(active_dut_map))
logger.info('disabled_ptf_ports={}'.format(disabled_ptf_ports))
logger.info('router_macs={}'.format(router_macs))

asic_idx = 0
ports_map = {}
for ptf_port, dut_intf_map in tbinfo['topo']['ptf_dut_intf_map'].items():
if str(ptf_port) in disabled_ptf_ports:
# Skip PTF ports that are connected to disabled VLAN interfaces
continue
asic_idx = 0
dut_port = None

if len(dut_intf_map.keys()) == 2:
# PTF port is mapped to two DUTs -> dualtor topology and the PTF port is a vlan port
# Packet sent from this ptf port will only be accepted by the active side DUT
# DualToR DUTs use same special Vlan interface MAC address
# DualToR DUTs use same special Vlan interface MAC addres
target_dut_indexes = list(map(int, active_dut_map[ptf_port]))
target_dut_port = int(list(dut_intf_map.values())[0])
target_hostname = duthosts[target_dut_indexes[0]].hostname
ports_map[ptf_port] = {
'target_dut': target_dut_indexes,
'target_dest_mac': tbinfo['topo']['properties']['topology']['DUT']['vlan_configs']['one_vlan_a']
Expand All @@ -535,30 +545,39 @@ def ptf_test_port_map_active_active(ptfhost, tbinfo, duthosts, mux_server_url, d
}
else:
# PTF port is mapped to single DUT
dut_index_for_pft_port = int(dut_intf_map.keys()[0])
if router_macs[dut_index_for_pft_port] is None:
continue
target_dut_index = int(list(dut_intf_map.keys())[0])
target_dut_port = int(list(dut_intf_map.values())[0])
router_mac = router_macs[target_dut_index]
dut_port = None
if len(duts_minigraph_facts[duthosts[target_dut_index].hostname]) > 1:
for list_idx, mg_facts_tuple in enumerate(duts_minigraph_facts[duthosts[target_dut_index].hostname]):
target_hostname = tbinfo['duts'][target_dut_index]

if len(duts_minigraph_facts[target_hostname]) > 1:
# Dealing with multi-asic target dut
for list_idx, mg_facts_tuple in enumerate(duts_minigraph_facts[target_hostname]):
idx, mg_facts = mg_facts_tuple
if target_dut_port in list(mg_facts['minigraph_port_indices'].values()):
router_mac = duts_running_config_facts[duthosts[target_dut_index].hostname][list_idx][1]\
router_mac = duts_running_config_facts[target_hostname][list_idx][1]\
['DEVICE_METADATA']['localhost']['mac'].lower()
asic_idx = idx
for a_dut_port, a_dut_port_index in mg_facts['minigraph_port_indices'].items():
if a_dut_port_index == target_dut_port and "Ethernet-Rec" not in a_dut_port and \
"Ethernet-IB" not in a_dut_port and "Ethernet-BP" not in a_dut_port:
dut_port = a_dut_port
break

ports_map[ptf_port] = {
'target_dut': [target_dut_index],
'target_dest_mac': router_mac,
'target_src_mac': [router_mac],
'dut_port': dut_port,
'asic_idx': asic_idx
}

_, asic_mg_facts = duts_minigraph_facts[target_hostname][asic_idx]
for a_dut_port, a_dut_port_index in asic_mg_facts['minigraph_port_indices'].items():
if a_dut_port_index == target_dut_port and "Ethernet-Rec" not in a_dut_port and \
"Ethernet-IB" not in a_dut_port and "Ethernet-BP" not in a_dut_port:
dut_port = a_dut_port
break

ports_map[ptf_port]['dut_port'] = dut_port

logger.debug('ptf_test_port_map={}'.format(json.dumps(ports_map, indent=2)))

ptfhost.copy(content=json.dumps(ports_map), dest=PTF_TEST_PORT_MAP)
Expand Down
54 changes: 54 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
from tests.common.fixtures.duthost_utils import backup_and_restore_config_db_session
from tests.common.fixtures.ptfhost_utils import ptf_portmap_file # lgtm[py/unused-import]
from tests.common.fixtures.ptfhost_utils import run_icmp_responder_session # lgtm[py/unused-import]
from tests.common.fixtures.ptfhost_utils import ptf_test_port_map_active_active # noqa F401

from tests.common.helpers.constants import (
ASIC_PARAM_TYPE_ALL, ASIC_PARAM_TYPE_FRONTEND, DEFAULT_ASIC_ID, ASICS_PRESENT
Expand Down Expand Up @@ -1599,6 +1600,59 @@ def duts_running_config_facts(duthosts):
return cfg_facts

@pytest.fixture(scope='class')
def dut_test_params_qos(duthosts, tbinfo, ptfhost, get_src_dst_asic_and_duts, lower_tor_host, creds,
mux_server_url, mux_status_from_nic_simulator, duts_running_config_facts, duts_minigraph_facts):
if 'dualtor' in tbinfo['topo']['name']:
all_duts = [lower_tor_host]
else:
all_duts = get_src_dst_asic_and_duts['all_duts']

src_asic = get_src_dst_asic_and_duts['src_asic']
dst_asic = get_src_dst_asic_and_duts['dst_asic']

src_dut = get_src_dst_asic_and_duts['src_dut']
src_dut_ip = src_dut.host.options['inventory_manager'].get_host(src_dut.hostname).vars['ansible_host']
src_server = "{}:{}".format(src_dut_ip, src_asic.get_rpc_port_ssh_tunnel())

duthost = all_duts[0]
mgFacts = duthost.get_extended_minigraph_facts(tbinfo)
topo = tbinfo["topo"]["name"]

rtn_dict = {
"topo": topo,
"hwsku": mgFacts["minigraph_hwsku"],
"basicParams": {
"router_mac": duthost.facts["router_mac"],
"src_server" : src_server,
"port_map_file": ptf_test_port_map_active_active(
ptfhost, tbinfo, duthosts, mux_server_url,
duts_running_config_facts, duts_minigraph_facts,
mux_status_from_nic_simulator()),
"sonic_asic_type": duthost.facts['asic_type'],
"sonic_version": duthost.os_version,
"src_dut_index": get_src_dst_asic_and_duts['src_dut_index'],
"src_asic_index": get_src_dst_asic_and_duts['src_asic_index'],
"dst_dut_index": get_src_dst_asic_and_duts['dst_dut_index'],
"dst_asic_index": get_src_dst_asic_and_duts['dst_asic_index'],
"dut_username": creds['sonicadmin_user'],
"dut_password": creds['sonicadmin_password']
},

}

# Add dst server info if src and dst asic are different
if src_asic != dst_asic:
dst_dut = get_src_dst_asic_and_duts['dst_dut']
dst_dut_ip = dst_dut.host.options['inventory_manager'].get_host(dst_dut.hostname).vars['ansible_host']
rtn_dict["basicParams"]["dst_server"] = "{}:{}".format(dst_dut_ip, dst_asic.get_rpc_port_ssh_tunnel())

if 'platform_asic' in duthost.facts:
rtn_dict['basicParams']["platform_asic"] = duthost.facts['platform_asic']

yield rtn_dict


@ pytest.fixture(scope='class')
def dut_test_params(duthosts, enum_rand_one_per_hwsku_frontend_hostname, tbinfo,
ptf_portmap_file, lower_tor_host, creds): # noqa F811
"""
Expand Down
18 changes: 12 additions & 6 deletions tests/qos/files/mellanox/qos_param_generator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import math

class QosParamMellanox(object):
def __init__(self, qos_params, asic_type, speed_cable_len, dutConfig, ingressLosslessProfile, ingressLossyProfile, egressLosslessProfile, egressLossyProfile, sharedHeadroomPoolSize, dualTor):
def __init__(self, qos_params, asic_type, speed_cable_len, dutConfig, ingressLosslessProfile,
ingressLossyProfile, egressLosslessProfile, egressLossyProfile, sharedHeadroomPoolSize,
dualTor, src_dut_index, src_asic_index, dst_asic_index, dst_dut_index):
self.asic_param_dic = {
'spc1': {
'cell_size': 96,
Expand Down Expand Up @@ -44,7 +46,10 @@ def __init__(self, qos_params, asic_type, speed_cable_len, dutConfig, ingressLos
self.sharedHeadroomPoolSize = None
self.dutConfig = dutConfig
self.dualTor = dualTor

self.src_dut_index = src_dut_index
self.src_asic_index = src_asic_index
self.dst_dut_index = dst_dut_index
self.dst_asic_index = dst_asic_index
return

def run(self):
Expand Down Expand Up @@ -88,18 +93,19 @@ def collect_qos_configurations(self):
pkts_num_trig_egr_drp = egress_lossy_size + 1

if self.sharedHeadroomPoolSize:
testPortIds = self.dutConfig['testPortIds']
src_testPortIds = self.dutConfig['testPortIds'][self.src_dut_index][self.src_asic_index]
dst_testPortIds = self.dutConfig['testPortIds'][self.dst_dut_index][self.dst_asic_index]
ingress_ports_num_shp = 8
pkts_num_trig_pfc_shp = []
ingress_ports_list_shp = []
occupancy_per_port = ingress_lossless_size
self.qos_parameters['dst_port_id'] = testPortIds[0]
self.qos_parameters['dst_port_id'] = dst_testPortIds[0]
pgs_per_port = 2 if not self.dualTor else 4
for i in range(1, ingress_ports_num_shp):
for j in range(pgs_per_port):
pkts_num_trig_pfc_shp.append(occupancy_per_port + xon + hysteresis)
occupancy_per_port /= 2
ingress_ports_list_shp.append(testPortIds[i])
ingress_ports_list_shp.append(src_testPortIds[i])
self.qos_parameters['pkts_num_trig_pfc_shp'] = pkts_num_trig_pfc_shp
self.qos_parameters['src_port_ids'] = ingress_ports_list_shp
self.qos_parameters['pkts_num_hdrm_full'] = xoff - 2
Expand Down Expand Up @@ -209,4 +215,4 @@ def calculate_parameters(self):
self.qos_params_mlnx['ecn_{}'.format(i+1)]['cell_size'] = self.cell_size

self.qos_params_mlnx['shared-headroom-pool'] = self.sharedHeadroomPoolSize
self.qos_params_mlnx['pkts_num_private_headrooom'] = self.asic_param_dic[self.asic_type]['private_headroom']
self.qos_params_mlnx['pkts_num_private_headrooom'] = self.asic_param_dic[self.asic_type]['private_headroom']
2 changes: 2 additions & 0 deletions tests/qos/qos_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def eos_to_linux_intf(eos_intf_name, hwsku=None):
"""
if hwsku == "MLNX-OS":
linux_intf_name = eos_intf_name.replace("ernet 1/", "sl1p").replace("/", "sp")
elif hwsku and "Nokia" in hwsku:
linux_intf_name = eos_intf_name
else:
linux_intf_name = eos_intf_name.replace('Ethernet', 'et').replace('/', '_')
return linux_intf_name
Expand Down
Loading