Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sfputil base and helper class changes for multi-ASIC #100

Merged
merged 5 commits into from
Aug 25, 2020
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
40 changes: 34 additions & 6 deletions sonic_platform_base/sonic_sfp/sfputilbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from natsort import natsorted
from portconfig import get_port_config
from sonic_py_common import device_info
from sonic_py_common.interface import backplane_prefix

from . import bcmshell # Dot module supports both Python 2 and Python 3 using explicit relative import methods
from sonic_eeprom import eeprom_dts
Expand Down Expand Up @@ -157,6 +158,9 @@ class SfpUtilBase(object):
""" ["swp1", "swp5", "swp6", "swp7", "swp8" ...] """
logical = []

# Mapping of logical port names available on a system to ASIC num
logical_to_asic = {}

# dicts for easier conversions between logical, physical and bcm ports
logical_to_bcm = {}
logical_to_physical = {}
Expand Down Expand Up @@ -371,7 +375,7 @@ def _is_valid_port(self, port_num):

return False

def read_porttab_mappings(self, porttabfile):
def read_porttab_mappings(self, porttabfile, asic_inst=0):
logical = []
logical_to_bcm = {}
logical_to_physical = {}
Expand Down Expand Up @@ -455,12 +459,16 @@ def read_porttab_mappings(self, porttabfile):
# 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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is json format file depracated. I don't see similar check for json format files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do support only the port_config.ini files for multi_asic. The json format files was recently introduced. So I was currently adding the logic to handle multiple port_config.ini files alone.

Copy link
Contributor

@jleveque jleveque Aug 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All port_config.ini/platform.json parsing should eventually be moved to portconfig.py (currently in sonic-config-engine, to be moved to sonic-py-common) so that it is only done in one place. This is tracked by issues: #88, #110

@judyjoseph: Is there already multi-ASIC logic in portconfig.py? If so I would prefer resolving #88 with this PR, because this PR is adding even MORE parsing logic to this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jleveque I could move the json/ini file parsing from here --> to portconfig.py. But what I find is that I will have to write this logic as new API's in portconfig.py -- as the port_config.ini/platform.json parsing logic implemented here in sfpbase module is different to that is already present @ https://github.com/Azure/sonic-buildimage/blob/da69d57a8dffa37e285d7b93671d055ba193c61d/src/sonic-config-engine/portconfig.py#L142.

We could have separate parsing API's for now, and later on unify them in portconfig.py as a single parsing API ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, It's probably best to leave it here for now and do the move and unification at the same time, and maybe also move it all to sonic-py-common at the same time, as well.


bcm_port = str(port_pos_in_file)

if "index" in title:
fp_port_index = int(line.split()[title.index("index")])
# Leave the old code for backward compatibility
elif len(line.split()) >= 4:
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()
Expand All @@ -483,6 +491,9 @@ def read_porttab_mappings(self, porttabfile):

logical.append(portname)

# Mapping of logical port names available on a system to ASIC instance
self.logical_to_asic[portname] = asic_inst

logical_to_bcm[portname] = "xe" + bcm_port
logical_to_physical[portname] = [fp_port_index]
if physical_to_logical.get(fp_port_index) is None:
Expand All @@ -495,17 +506,30 @@ def read_porttab_mappings(self, porttabfile):

port_pos_in_file += 1

self.logical = logical
self.logical_to_bcm = logical_to_bcm
self.logical_to_physical = logical_to_physical
self.physical_to_logical = physical_to_logical
self.logical.extend(logical)
self.logical_to_bcm.update(logical_to_bcm)
self.logical_to_physical.update(logical_to_physical)
self.physical_to_logical.update(physical_to_logical)

"""
print("logical: " + self.logical)
print("logical to bcm: " + self.logical_to_bcm)
print("logical to physical: " + self.logical_to_physical)
print("physical to logical: " + self.physical_to_logical)
"""

def read_all_porttab_mappings(self, platform_dir, num_asic_inst):
# In multi asic scenario, get all the port_config files for different asics
for inst in range(num_asic_inst):
port_map_dir = os.path.join(platform_dir, str(inst))
port_map_file = os.path.join(port_map_dir, PORT_CONFIG_INI)
if os.path.exists(port_map_file):
self.read_porttab_mappings(port_map_file, inst)
else:
port_json_file = os.path.join(port_map_dir, PLATFORM_JSON)
if os.path.exists(port_json_file):
self.read_porttab_mappings(port_json_file, inst)

def read_phytab_mappings(self, phytabfile):
logical = []
phytab_mappings = {}
Expand Down Expand Up @@ -615,6 +639,10 @@ def is_logical_port(self, port):
else:
return 0

def get_asic_id_for_logical_port(self, logical_port):
"""Returns the asic_id list of physical ports for the given logical port"""
return self.logical_to_asic.get(logical_port)

def is_logical_port_ganged_40_by_4(self, logical_port):
physical_port_list = self.logical_to_physical[logical_port]
if len(physical_port_list) > 1:
Expand Down
39 changes: 34 additions & 5 deletions sonic_platform_base/sonic_sfp/sfputilhelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from natsort import natsorted
from portconfig import get_port_config
from sonic_py_common import device_info
from sonic_py_common.interface import backplane_prefix

except ImportError as e:
raise ImportError("%s - required module not found" % str(e))

Expand All @@ -33,6 +35,9 @@ class SfpUtilHelper(object):
""" ["swp1", "swp5", "swp6", "swp7", "swp8" ...] """
logical = []

# Mapping of logical port names available on a system to ASIC num
logical_to_asic = {}

# dicts for easier conversions between logical, physical and bcm ports
logical_to_physical = {}

Expand All @@ -42,7 +47,7 @@ class SfpUtilHelper(object):
def __init__(self):
pass

def read_porttab_mappings(self, porttabfile):
def read_porttab_mappings(self, porttabfile, asic_inst=0):
logical = []
logical_to_physical = {}
physical_to_logical = {}
Expand Down Expand Up @@ -122,12 +127,16 @@ def read_porttab_mappings(self, porttabfile):
# 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

bcm_port = str(port_pos_in_file)

if "index" in title:
fp_port_index = int(line.split()[title.index("index")])
# Leave the old code for backward compatibility
elif len(line.split()) >= 4:
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()
Expand All @@ -150,6 +159,9 @@ def read_porttab_mappings(self, porttabfile):

logical.append(portname)

# Mapping of logical port names available on a system to ASIC instance
self.logical_to_asic[portname] = asic_inst

logical_to_physical[portname] = [fp_port_index]
if physical_to_logical.get(fp_port_index) is None:
physical_to_logical[fp_port_index] = [portname]
Expand All @@ -161,15 +173,28 @@ def read_porttab_mappings(self, porttabfile):

port_pos_in_file += 1

self.logical = logical
self.logical_to_physical = logical_to_physical
self.physical_to_logical = physical_to_logical
self.logical.extend(logical)
self.logical_to_physical.update(logical_to_physical)
self.physical_to_logical.update(physical_to_logical)

"""
print("logical: " + self.logical)
print("logical to physical: " + self.logical_to_physical)
print("physical to logical: " + self.physical_to_logical)
"""

def read_all_porttab_mappings(self, platform_dir, num_asic_inst):
# In multi asic scenario, get all the port_config files for different asics
for inst in range(num_asic_inst):
port_map_dir = os.path.join(platform_dir, str(inst))
port_map_file = os.path.join(port_map_dir, PORT_CONFIG_INI)
if os.path.exists(port_map_file):
self.read_porttab_mappings(port_map_file, inst)
else:
port_json_file = os.path.join(port_map_dir, PLATFORM_JSON)
if os.path.exists(port_json_file):
self.read_porttab_mappings(port_json_file, inst)

def get_physical_to_logical(self, port_num):
"""Returns list of logical ports for the given physical port"""

Expand All @@ -185,3 +210,7 @@ def is_logical_port(self, port):
return 1
else:
return 0

def get_asic_id_for_logical_port(self, logical_port):
"""Returns the asic_id list of physical ports for the given logical port"""
return self.logical_to_asic.get(logical_port)