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

[Mellanox] Enhance Platform API to support SN2201 - RJ45 ports and new components mgmt. #10299

Closed
wants to merge 20 commits into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"component": {
"ONIE": { },
"SSD": { },
"BIOS": { },
"CPLD1": { },
"CPLD2": { }
}
Expand Down
35 changes: 27 additions & 8 deletions platform/mellanox/mlnx-platform-api/sonic_platform/chassis.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@
from sonic_py_common.logger import Logger
import os
from functools import reduce

from .utils import load_json_file, extract_RJ45_ports_index
from . import utils
from .device_data import DeviceDataManager
from .sfp import SFP, deinitialize_sdk_handle
from .sfp import SFP, RJ45Port, deinitialize_sdk_handle
except ImportError as e:
raise ImportError (str(e) + "- required module not found")

MAX_SELECT_DELAY = 3600

RJ45_TYPE = "RJ45"

DMI_FILE = '/sys/firmware/dmi/entries/2-0/raw'
DMI_HEADER_LEN = 15
DMI_PRODUCT_NAME = "Product Name"
Expand Down Expand Up @@ -107,6 +109,10 @@ def __init__(self):
self.sfp_initialized_count = 0
self.sfp_event = None
self.reboot_cause_initialized = False

# Build the RJ45 port list from platform.json and hwsku.json
self.RJ45_port_list = extract_RJ45_ports_index()

logger.log_info("Chassis loaded successfully")

def __del__(self):
Expand Down Expand Up @@ -241,22 +247,31 @@ def initialize_single_sfp(self, index):

if not self._sfp_list[index]:
from .sfp import SFP
self._sfp_list[index] = SFP(index)
if self.RJ45_port_list and index in self.RJ45_port_list:
self._sfp_list[index] = RJ45Port(index)
else:
self._sfp_list[index] = SFP(index)
self.sfp_initialized_count += 1

def initialize_sfp(self):
if not self._sfp_list:
from .sfp import SFP
sfp_count = self.get_num_sfps()
for index in range(sfp_count):
sfp_module = SFP(index)
if self.RJ45_port_list and index in self.RJ45_port_list:
sfp_module = RJ45Port(index)
else:
sfp_module = SFP(index)
self._sfp_list.append(sfp_module)
self.sfp_initialized_count = sfp_count
elif self.sfp_initialized_count != len(self._sfp_list):
from .sfp import SFP
for index in range(len(self._sfp_list)):
if self._sfp_list[index] is None:
self._sfp_list[index] = SFP(index)
if self.RJ45_port_list and index in self.RJ45_port_list:
self._sfp_list[index] = RJ45Port(index)
else:
self._sfp_list[index] = SFP(index)
self.sfp_initialized_count = len(self._sfp_list)

def get_num_sfps(self):
Expand Down Expand Up @@ -323,7 +338,7 @@ def get_change_event(self, timeout=0):
# Initialize SFP event first
if not self.sfp_event:
from .sfp_event import sfp_event
self.sfp_event = sfp_event()
self.sfp_event = sfp_event(self.RJ45_port_list)
self.sfp_event.initialize()

wait_for_ever = (timeout == 0)
Expand All @@ -339,7 +354,8 @@ def get_change_event(self, timeout=0):
status = self.sfp_event.check_sfp_status(port_dict, error_dict, timeout)

if status:
self.reinit_sfps(port_dict)
if port_dict:
self.reinit_sfps(port_dict)
result_dict = {'sfp':port_dict}
if error_dict:
result_dict['sfp_error'] = error_dict
Expand Down Expand Up @@ -514,7 +530,10 @@ def initialize_components(self):
from .component import ComponentONIE, ComponentSSD, ComponentBIOS, ComponentCPLD
self._component_list.append(ComponentONIE())
self._component_list.append(ComponentSSD())
self._component_list.append(ComponentBIOS())
biosComponent = DeviceDataManager.get_bios_component()
if not biosComponent:
biosComponent = ComponentBIOS()
self._component_list.append(biosComponent)
self._component_list.extend(ComponentCPLD.get_component_list())

def get_num_components(self):
Expand Down
45 changes: 45 additions & 0 deletions platform/mellanox/mlnx-platform-api/sonic_platform/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import glob
import tempfile
import subprocess
from sonic_py_common import device_info
if sys.version_info[0] > 2:
import configparser
else:
Expand Down Expand Up @@ -136,7 +137,17 @@ class ONIEUpdater(object):

ONIE_IMAGE_INFO_COMMAND = '/bin/bash {} -q -i'

# Upgrading fireware from ONIE is not supported from the beginning on some platforms, like SN2700.
# There is a logic to check the ONIE version in order to know whether it is supported.
# If it is not supported, we will not proceed and print some error message.
# For SN2201, upgrading fireware from ONIE is supported from day one so we do not need to check it.
PLATFORM_ALWAYS_SUPPORT_UPGRADE = ['x86_64-nvidia_sn2201-r0']

BIOS_UPDATE_FILE_EXT = '.rom'


def __init__(self):
self.platform = device_info.get_platform()

def __add_prefix(self, image_path):
if self.BIOS_UPDATE_FILE_EXT not in image_path:
Expand Down Expand Up @@ -336,6 +347,9 @@ def update_firmware(self, image_path, allow_reboot=True):
raise

def is_non_onie_firmware_update_supported(self):
if self.platform in self.PLATFORM_ALWAYS_SUPPORT_UPGRADE:
return True

current_version = self.get_onie_version()
_, _, major1, minor1, release1, _ = self.parse_onie_version(current_version)
version1 = int("{}{}{}".format(major1, minor1, release1))
Expand Down Expand Up @@ -698,6 +712,37 @@ def update_firmware(self, image_path):
self.__install_firmware(image_path)


class ComponentBIOSSN2201(Component):
COMPONENT_NAME = 'BIOS'
COMPONENT_DESCRIPTION = 'BIOS - Basic Input/Output System'

BIOS_VERSION_COMMAND = 'dmidecode -t0'

def __init__(self):
super(ComponentBIOSSN2201, self).__init__()

self.name = self.COMPONENT_NAME
self.description = self.COMPONENT_DESCRIPTION

def get_firmware_version(self):
cmd = self.BIOS_VERSION_COMMAND

try:
output = subprocess.check_output(cmd.split(),
stderr=subprocess.STDOUT,
universal_newlines=True).rstrip('\n')
except subprocess.CalledProcessError as e:
raise RuntimeError("Failed to get {} version: {}".format(self.name, str(e)))

match = re.search('Version: (.*)', output)
if match:
version = match.group(1)
else:
version = 'Unknown version'

return version


class ComponentCPLD(Component):
COMPONENT_NAME = 'CPLD{}'
COMPONENT_DESCRIPTION = 'CPLD - Complex Programmable Logic Device'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,12 @@ def get_linecard_max_port_count(cls):
if not sfp_data:
return 0
return sfp_data.get('max_port_per_line_card', 0)

@classmethod
def get_bios_component(cls):
if cls.get_platform_name() in ['x86_64-nvidia_sn2201-r0']:
from .component import ComponentBIOSSN2201
# For SN2201, special chass is required for handle BIOS
# Currently, only fetching BIOS version is supported
return ComponentBIOSSN2201()
return None
Loading