From af6b6319b5c4fd0702c52137dfe29432edd537b2 Mon Sep 17 00:00:00 2001 From: Stephen Sun <5379172+stephenxs@users.noreply.github.com> Date: Tue, 6 Aug 2019 06:57:27 +0800 Subject: [PATCH] [sonic_platform_base] support new-platform-api-based daemons (#48) [sonic_platform_base/chassis] 1. add _eeprom and get_eeprom into class ChassisBase so that syseepromd can access eeprom related stuff. 2. fix typo (non-asic characters) [sonic_platform_base/sonic_sfp/sfputilhelper] For xcvrd, originally we plan to remain the module sfputilbase to provide functions like mapping between logical and physical interfaces. However, SfpUtilBase is an abstract class and can not be instantiated. In that case, a new module sfputilhelper has to be introduced to provide the required interfaces. 1. read_porttab_mappings, which reads port_config.ini and generats mappings 2. get_physical_to_logical 3. get_logical_to_physical 4. is_logical_port [sonic_platform_base/sfp_base] support interface get_transceiver_threshold_status --- sonic_platform_base/chassis_base.py | 24 ++- sonic_platform_base/sfp_base.py | 91 +++++------- .../sonic_sfp/sfputilhelper.py | 137 ++++++++++++++++++ 3 files changed, 191 insertions(+), 61 deletions(-) create mode 100644 sonic_platform_base/sonic_sfp/sfputilhelper.py diff --git a/sonic_platform_base/chassis_base.py b/sonic_platform_base/chassis_base.py index 27093b144..9ffc7c4e5 100644 --- a/sonic_platform_base/chassis_base.py +++ b/sonic_platform_base/chassis_base.py @@ -52,6 +52,9 @@ class ChassisBase(device_base.DeviceBase): # Object derived from WatchdogBase for interacting with hardware watchdog _watchdog = None + # Object derived from eeprom_tlvinfo.TlvInfoDecoder indicating the eeprom on the chassis + _eeprom = None + def get_base_mac(self): """ Retrieves the base MAC address for the chassis @@ -79,9 +82,9 @@ def get_system_eeprom_info(self): A dictionary where keys are the type code defined in OCP ONIE TlvInfo EEPROM format and values are their corresponding values. - Ex. { ‘0x21’:’AG9064’, ‘0x22’:’V1.0’, ‘0x23’:’AG9064-0109867821’, - ‘0x24’:’001c0f000fcd0a’, ‘0x25’:’02/03/2018 16:22:00’, - ‘0x26’:’01’, ‘0x27’:’REV01’, ‘0x28’:’AG9064-C2358-16G’} + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} """ raise NotImplementedError @@ -339,7 +342,10 @@ def get_sfp(self, index): Retrieves sfp represented by (0-based) index Args: - index: An integer, the index (0-based) of the sfp to retrieve + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. Returns: An object dervied from SfpBase representing the specified sfp @@ -368,6 +374,16 @@ def get_watchdog(self): """ return self._watchdog + def get_eeprom(self): + """ + Retreives eeprom device on this chassis + + Returns: + An object derived from WatchdogBase representing the hardware + eeprom device + """ + return self._eeprom + def get_change_event(self, timeout=0): """ Returns a nested dictionary containing all devices which have diff --git a/sonic_platform_base/sfp_base.py b/sonic_platform_base/sfp_base.py index b9ba6996d..23a0ba10a 100644 --- a/sonic_platform_base/sfp_base.py +++ b/sonic_platform_base/sfp_base.py @@ -52,24 +52,21 @@ def get_transceiver_bulk_status(self): ======================================================================== keys |Value Format |Information ---------------------------|---------------|---------------------------- - RX LOS |BOOLEAN |RX lost-of-signal status, - | |True if has RX los, False if not. - TX FAULT |BOOLEAN |TX fault status, - | |True if has TX fault, False if not. - Reset status |BOOLEAN |reset status, - | |True if SFP in reset, False if not. - LP mode |BOOLEAN |low power mode status, - | |True in lp mode, False if not. - TX disable |BOOLEAN |TX disable status, - | |True TX disabled, False if not. - TX disabled channel |HEX |disabled TX channles in hex, - | |bits 0 to 3 represent channel 0 + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 | |to channel 3. - Temperature |INT |module temperature in Celsius - Voltage |INT |supply voltage in mV - TX bias |INT |TX Bias Current in mA - RX power |INT |received optical power in mW - TX power |INT |TX output power in mW + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. ======================================================================== """ return NotImplementedError @@ -83,46 +80,26 @@ def get_transceiver_threshold_info(self): ======================================================================== keys |Value Format |Information ---------------------------|---------------|---------------------------- - Temperature High Alarm |FLOAT |High Alarm Threshold value, - | |of temperature in Celsius. - Temperature Low Alarm |FLOAT |Low Alarm Threshold value, - | |of temperature in Celsius. - Temperature High Warning |FLOAT |High Warning Threshold value, - | |of temperature in Celsius. - Temperature Low Warning |FLOAT |Low Warning Threshold value, - | |of temperature in Celsius. - Voltage High Alarm |FLOAT |High Alarm Threshold value, - | |of supply voltage in mV. - Voltage Low Alarm |FLOAT |Low Alarm Threshold value, - | |of supply voltage in mV. - Voltage High Warning |FLOAT |High Warning Threshold value, - | |of supply voltage in mV. - Voltage Low Warning |FLOAT |Low Warning Threshold value, - | |of supply voltage in mV. - Rx Power High Alarm |FLOAT |High Alarm Threshold value, - | |of received power in dBm. - Rx Power Low Alarm |FLOAT |Low Alarm Threshold value, - | |of received power in dBm. - Rx Power High Warning |FLOAT |High Warning Threshold value, - | |of received power in dBm. - Rx Power Low Warning |FLOAT |Low Warning Threshold value, - | |of received power in dBm. - Tx Power High Alarm |FLOAT |High Alarm Threshold value, - | |of transmit power in dBm. - Tx Power Low Alarm |FLOAT |Low Alarm Threshold value, - | |of transmit power in dBm. - Tx Power High Warning |FLOAT |High Warning Threshold value, - | |of transmit power in dBm. - Tx Power Low Warning |FLOAT |Low Warning Threshold value, - | |of transmit power in dBm. - Tx Bias High Alarm |FLOAT |High Alarm Threshold value, - | |of tx Bias Current in mA. - Tx Bias Low Alarm |FLOAT |Low Alarm Threshold value, - | |of tx Bias Current in mA. - Tx Bias High Warning |FLOAT |High Warning Threshold value, - | |of tx Bias Current in mA. - Tx Bias Low Warning |FLOAT |Low Warning Threshold value, - | |of tx Bias Current in mA. + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. ======================================================================== """ return NotImplementedError diff --git a/sonic_platform_base/sonic_sfp/sfputilhelper.py b/sonic_platform_base/sonic_sfp/sfputilhelper.py new file mode 100644 index 000000000..49e9ef92d --- /dev/null +++ b/sonic_platform_base/sonic_sfp/sfputilhelper.py @@ -0,0 +1,137 @@ +# sfputilbase.py +# +# Base class for creating platform-specific SFP transceiver interfaces for SONiC +# + +from __future__ import print_function + +try: + import abc + import binascii + import os + import re +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) + +class SfpUtilHelper(object): + # List to specify filter for sfp_ports + # Needed by platforms like dni-6448 which + # have only a subset of ports that support sfp + sfp_ports = [] + + # List of logical port names available on a system + """ ["swp1", "swp5", "swp6", "swp7", "swp8" ...] """ + logical = [] + + # dicts for easier conversions between logical, physical and bcm ports + logical_to_physical = {} + + physical_to_logical = {} + physical_to_phyaddrs = {} + + def __init__(self): + pass + + def read_porttab_mappings(self, porttabfile): + logical = [] + logical_to_physical = {} + physical_to_logical = {} + last_fp_port_index = 0 + last_portname = "" + first = 1 + port_pos_in_file = 0 + parse_fmt_port_config_ini = False + + try: + f = open(porttabfile) + except: + raise + + parse_fmt_port_config_ini = (os.path.basename(porttabfile) == "port_config.ini") + + # Read the porttab file and generate dicts + # with mapping for future reference. + # + # TODO: Refactor this to use the portconfig.py module that now + # exists as part of the sonic-config-engine package. + 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.split()[1:] + 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] + + 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: + 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 ((len(self.sfp_ports) > 0) and (fp_port_index not in self.sfp_ports)): + continue + + if first == 1: + # Initialize last_[physical|logical]_port + # to the first valid port + last_fp_port_index = fp_port_index + last_portname = portname + first = 0 + + logical.append(portname) + + logical_to_physical[portname] = [fp_port_index] + if physical_to_logical.get(fp_port_index) is None: + physical_to_logical[fp_port_index] = [portname] + else: + physical_to_logical[fp_port_index].append( + portname) + + last_fp_port_index = fp_port_index + last_portname = portname + + port_pos_in_file += 1 + + self.logical = logical + self.logical_to_physical = logical_to_physical + self.physical_to_logical = physical_to_logical + + """ + print("logical: " + self.logical) + print("logical to physical: " + self.logical_to_physical) + print("physical to logical: " + self.physical_to_logical) + """ + + def get_physical_to_logical(self, port_num): + """Returns list of logical ports for the given physical port""" + + return self.physical_to_logical[port_num] + + def get_logical_to_physical(self, logical_port): + """Returns list of physical ports for the given logical port""" + + return self.logical_to_physical[logical_port] + + def is_logical_port(self, port): + if port in self.logical: + return 1 + else: + return 0