Skip to content

Commit

Permalink
Update y_cable_simulator_client to address SFP issue. (#2952)
Browse files Browse the repository at this point in the history
Summary:
Fixes # (issue)
In topo dualtor_56, a 100G interfaces are splited into two 50G interfaces according to port_config.ini.

As a result, the physical port id got from SFP is different with host interface index, which is used as the name of mux bridge.
For example, the physical port id for Ethernet4 is 2 according port_config.ini, but the interface is connect to mux bridge mbr-vms17-8-2. Therefore, we need to calculate host interface index from physical port id.

This PR addressed the issue by calculating host interface index according to port config file. Most of the logic is same with read_porttab_mappings in sfputilhelper.py
  • Loading branch information
bingwang-ms authored Feb 19, 2021
1 parent a4cc76e commit 9b41a7a
Showing 1 changed file with 120 additions and 2 deletions.
122 changes: 120 additions & 2 deletions tests/templates/y_cable_simulator_client.j2
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from urllib import request, error
import json
from sonic_py_common import logger
import os
import re
from sonic_py_common import logger, device_info
from portconfig import get_port_config
from natsort import natsorted
from sonic_py_common.interface import backplane_prefix

DUTS_MAP = {{ duts_map }}

Expand All @@ -16,6 +21,118 @@ helper_logger = logger.Logger(SYSLOG_IDENTIFIER)
UPPER_TOR = "upper_tor"
LOWER_TOR = "lower_tor"

PLATFORM_JSON = 'platform.json'
PORT_CONFIG_INI = 'port_config.ini'

# A dict for mapping physical port to host interface
g_physical_to_host_port_mapping = {}

def _physical_port_to_host_port(physical_port):
"""
Convert physical port to host interface index.
The physical port index got from spf is different with host interface index when interface is splited.
However, the mux bridges on vm_host are named according to host interface index (vm_topology.py).
So a convert is needed.

@arg physical_port: The physical port index got from sfputil
@returns: The host interface index (0-based)
"""
global g_physical_to_host_port_mapping

if not g_physical_to_host_port_mapping:
_load_port_info()
# Return physical_port - 1 in case loading port config file failure
return g_physical_to_host_port_mapping.get(physical_port, physical_port - 1)

def _load_port_info():
"""
Parse platform.json or port_config.ini to get the mapping between physical_port and host interface index
and physical_port and logical port name. The mapping is saved in two global variables.
"""
porttabfile = device_info.get_path_to_port_config_file()
parse_fmt_platform_json = (os.path.basename(porttabfile) == PLATFORM_JSON)

if parse_fmt_platform_json:
_load_port_config_json()
else:
_load_port_config_ini(porttabfile)

def _load_port_config_json():
"""
A helper function for loading port config from 'platform.json'
"""
global g_physical_to_host_port_mapping

(platform, hwsku) = device_info.get_platform_and_hwsku()
ports, _, _ = get_port_config(hwsku, platform)
if not ports:
helper_logger.log_warning('Failed to get port config')
return
else:
logical_list = []
for intf in ports.keys():
logical_list.append(intf)

logical = natsorted(logical_list, key=lambda y: y.lower())
host_intf_index = 0
for intf_name in logical:
fp_port_index = -1
if 'index' in ports[intf_name].keys():
fp_port_index = int(ports[intf_name]['index'])
if fp_port_index not in g_physical_to_host_port_mapping:
g_physical_to_host_port_mapping[fp_port_index] = host_intf_index;
host_intf_index += 1

def _load_port_config_ini(porttabfile):
"""
A helper function for loading port config from 'port_config.ini'
"""
global g_physical_to_host_port_mapping

parse_fmt_port_config_ini = (os.path.basename(porttabfile) == PORT_CONFIG_INI)
host_intf_index = 0
with open(porttabfile, "r") as f:
# Read the porttab file and generate dicts
# with mapping for future reference.
title = []
for line in f:
line.strip()
if re.search("^#", line) is not None:
# The current format is: # name lanes alias index speed
# Where the ordering of the columns can vary
title = line.lstrip('#').strip().split()
continue
# Parsing logic for 'port_config.ini' file
if (parse_fmt_port_config_ini):
# bcm_port is not explicitly listed in port_config.ini format
# Currently we assume ports are listed in numerical order according to bcm_port
# so we use the port's position in the file (zero-based) as bcm_port
portname = line.split()[0]

# Ignore if this is an internal backplane interface
if portname.startswith(backplane_prefix()):
continue

if "index" in title:
fp_port_index = int(line.split()[title.index("index")])
# Leave the old code for backward compatibility
elif "asic_port_name" not in title and len(line.split()) >= 4:
fp_port_index = int(line.split()[3])
else:
fp_port_index = portname.split("Ethernet").pop()
fp_port_index = int(fp_port_index.split("s").pop(0))/4
else:
# Parsing logic for older 'portmap.ini' file
(portname, bcm_port) = line.split("=")[1].split(",")[:2]

fp_port_index = portname.split("Ethernet").pop()
fp_port_index = int(fp_port_index.split("s").pop(0))/4
if fp_port_index not in g_physical_to_host_port_mapping:
g_physical_to_host_port_mapping[fp_port_index] = host_intf_index

# Next line, next host index
host_intf_index += 1

def _url(physical_port):
"""
Helper function to build an url for given physical_port
Expand All @@ -25,7 +142,8 @@ def _url(physical_port):
Returns:
str: The url for post/get.
"""
return BASE_URL + "/mux/{}/{}".format(VM_SET, physical_port - 1)
host_intf_index = _physical_port_to_host_port(physical_port)
return BASE_URL + "/mux/{}/{}".format(VM_SET, host_intf_index)

def _post(physical_port, data):
"""
Expand Down

0 comments on commit 9b41a7a

Please sign in to comment.