diff --git a/sonic_platform_base/sonic_sfp/inf8628.py b/sonic_platform_base/sonic_sfp/inf8628.py index c6b6ea011fa6..2d16c983457e 100644 --- a/sonic_platform_base/sonic_sfp/inf8628.py +++ b/sonic_platform_base/sonic_sfp/inf8628.py @@ -7,6 +7,7 @@ try: from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods + from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods except ImportError as e: raise ImportError ("%s - required module not found" % e) @@ -77,6 +78,14 @@ def decode_module_state(self, eeprom_data, offset, size): 'decode': type_of_transceiver} } + sfp_type_abbrv_name = { + 'type_abbrv_name': + {'offset': 0, + 'size': 1, + 'type': 'enum', + 'decode': type_abbrv_name} + } + vendor_name = { 'Vendor Name': {'offset': 0, @@ -121,6 +130,9 @@ def parse(self, eeprom_raw_data, start_pos): def parse_sfp_type(self, type_raw_data, start_pos): return sffbase.parse(self, self.sfp_type, type_raw_data, start_pos) + def parse_sfp_type_abbrv_name(self, type_raw_data, start_pos): + return sffbase.parse(self, self.sfp_type_abbrv_name, type_raw_data, start_pos) + def parse_vendor_name(self, name_raw_data, start_pos): return sffbase.parse(self, self.vendor_name, name_raw_data, start_pos) diff --git a/sonic_platform_base/sonic_sfp/sff8024.py b/sonic_platform_base/sonic_sfp/sff8024.py index 1bcfe1904242..2a8e5542661b 100644 --- a/sonic_platform_base/sonic_sfp/sff8024.py +++ b/sonic_platform_base/sonic_sfp/sff8024.py @@ -34,3 +34,33 @@ '19': 'OSFP 8X Pluggable Transceiver', '1a': 'SFP-DD Double Density 2X Pluggable Transceiver' } + +type_abbrv_name = { + '00': 'Unknown', + '01': 'GBIC', + '02': 'Soldered', + '03': 'SFP', + '04': 'XBI300', + '05': 'XENPAK', + '06': 'XFP', + '07': 'XFF', + '08': 'XFP-E', + '09': 'XPAK', + '0a': 'X2', + '0b': 'DWDM-SFP', + '0c': 'QSFP', + '0d': 'QSFP+', + '0e': 'CXP', + '0f': 'HD4X', + '10': 'HD8X', + '11': 'QSFP28', + '12': 'CXP2', + '13': 'CDFP-1/2', + '14': 'HD4X-Fanout', + '15': 'HD8X-Fanout', + '16': 'CDFP-3', + '17': 'MicroQSFP', + '18': 'QSFP-DD', + '19': 'OSFP-8X', + '1a': 'SFP-DD' +} diff --git a/sonic_platform_base/sonic_sfp/sff8436.py b/sonic_platform_base/sonic_sfp/sff8436.py index 3a3f31214240..c1ff01f43111 100644 --- a/sonic_platform_base/sonic_sfp/sff8436.py +++ b/sonic_platform_base/sonic_sfp/sff8436.py @@ -16,6 +16,7 @@ import types from math import log10 from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods + from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -352,6 +353,11 @@ class sff8436InterfaceId(sffbase): 'size':1, 'type' : 'enum', 'decode' : type_of_transceiver}, + 'type_abbrv_name': + {'offset':0, + 'size':1, + 'type' : 'enum', + 'decode' : type_abbrv_name}, 'Extended Identifier': {'offset':1, 'size':1, diff --git a/sonic_platform_base/sonic_sfp/sff8472.py b/sonic_platform_base/sonic_sfp/sff8472.py index f2741e9f5220..d0d3441b3e83 100644 --- a/sonic_platform_base/sonic_sfp/sff8472.py +++ b/sonic_platform_base/sonic_sfp/sff8472.py @@ -18,6 +18,7 @@ import types from math import log10 from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods + from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods except ImportError as e: raise ImportError (str(e) + "- required module not found") @@ -419,6 +420,11 @@ class sff8472InterfaceId(sffbase): 'size':1, 'type' : 'enum', 'decode' : type_of_transceiver}, + 'type_abbrv_name': + {'offset':0, + 'size':1, + 'type' : 'enum', + 'decode' : type_abbrv_name}, 'Extended Identifier': {'offset':1, 'size':1, diff --git a/sonic_platform_base/sonic_sfp/sfputilbase.py b/sonic_platform_base/sonic_sfp/sfputilbase.py index 3dd6f4f68807..1a37528ca10d 100644 --- a/sonic_platform_base/sonic_sfp/sfputilbase.py +++ b/sonic_platform_base/sonic_sfp/sfputilbase.py @@ -544,7 +544,7 @@ def read_phytab_mappings(self, phytabfile): 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] + return self.physical_to_logical.get(port_num) def get_logical_to_physical(self, logical_port): """Returns list of physical ports for the given logical port""" @@ -747,6 +747,12 @@ def get_transceiver_info_dict(self, port_num): else: return None + sfp_type_abbrv_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) + if sfp_type_abbrv_name_raw is not None: + sfp_type_abbrv_name = sfpi_obj.parse_sfp_type_abbrv_name(sfp_type_abbrv_name_raw, 0) + else: + return None + try: sysfsfile_eeprom.close() except IOError: @@ -754,6 +760,7 @@ def get_transceiver_info_dict(self, port_num): return None transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_type_abbrv_name['data']['type_abbrv_name']['value'] transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] @@ -855,6 +862,7 @@ def get_transceiver_info_dict(self, port_num): return None transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] diff --git a/sonic_sfp b/sonic_sfp new file mode 120000 index 000000000000..fd9b3493de40 --- /dev/null +++ b/sonic_sfp @@ -0,0 +1 @@ +./sonic_platform_base/sonic_sfp/ \ No newline at end of file diff --git a/sonic_sfp/__init__.py b/sonic_sfp/__init__.py deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/sonic_sfp/bcmshell.py b/sonic_sfp/bcmshell.py deleted file mode 100644 index 409e61071e7e..000000000000 --- a/sonic_sfp/bcmshell.py +++ /dev/null @@ -1,502 +0,0 @@ -#! /usr/bin/python -#------------------------------------------------------------------------------- -# -# Copyright 2012 Cumulus Networks, inc all rights reserved -# -#------------------------------------------------------------------------------- -# - -from __future__ import print_function - -try: - import sys - import os - import time - import socket - import re -except ImportError as e: - raise ImportError (str(e) + "- required module not found") - -#------------------------------------------------------------------------------- -# - -class bcmshell (object): - - """Simple expect like class that connects to a BCM diag shell, exported as a - socket fd by switchd, allowing users to run commands and extract delimited - output. bcmdiag opens the socket file, flushes the socket's read side and - issues commands via bcmdiag.run(). The command output, upto the diag shell - prompt, is read from the socket and returned to the caller.""" - - version = "1.0" - - #--------------- - # - def __init__(self, keepopen=False, timeout=10, opennow=False, logfileobj=None, - socketname="/var/run/docker-syncd/sswsyncd.socket", prompt='^drivshell>\s*$'): - """Constructor: - - keepopen - indicates that switchd socket should be kept open between - uses because the invoking application has a bunch of consecutive - activity. In this use case, the socket must be explicitly closed by - bcmshell.close() to allow multiplexing of multiple applications. - - timeout - the time, in seconds, that bcmshell.run() will sit on the - domain socket wait for read input. Note that as long as the socket is - handing us data, we'll keep reading for up seconds. - - logfileobj - a file object that should log all issued commands. None - disables command logging; sys.stdout logs every command to stdout. - logfileobj is flushed after every write. - - socketname - the name of the switchd socket file. - - prompt - the diag shell prompt that delimits the end of output""" - - if type(prompt) is not str: - raise SyntaxError("bcmshell constructor prompt expects an re string") - else: - self.re_prompt = re.compile(prompt, re.MULTILINE) - self.re_connectprompt = re.compile("bcmshell\r\n\s*" + prompt, re.MULTILINE) - - if timeout <= 0: - raise ValueError("bcmshell.timeout must be > 0") - else: - self.timeout = timeout - if timeout > 180: - sys.stderr.write("warning: bcmshell.timeout, %s, is > 180s\n" % - str(self.timeout)) - - if not os.access(socketname, os.F_OK): - raise ValueError("socket %s does not exist" % socketname) - elif not os.access(socketname, os.R_OK | os.W_OK): - raise ValueError("missing read/write permissions for %s" % socketname) - else: - self.socketname = socketname - - if logfileobj is None: - self.logfileobj = None - elif type(logfileobj) is not file: - raise TypeError("bcmshell.logfileobj must be a file object not %s" % - type(logfileobj)) - elif 'w' not in logfileobj.mode: - raise TypeError("bcmshell.logfileobj is not a writeable file object") - else: - self.logfileobj = logfileobj - - self.keepopen = keepopen - self.socketobj = None - self.buffer = '' - - # text editing tools - # - self.re_oneline = re.compile('\n\s+') - self.re_reg_parse_raw = re.compile('^[\w()]+\.(.+)\[.*=(.*)$') - self.re_reg_parse_fields = re.compile('^[\w()]+\.(.+)\[.*\<(.*)\>') - self.re_get_field = re.compile('^(.+)=(.+)') - self.re_table_header = re.compile('^.*:[ <]+', re.MULTILINE) - self.re_table_trailer = re.compile('[ >]+$', re.MULTILINE) - self.re_conv = re.compile(r'(\d+|\D+)') - - # interface name conversion - # - self.modname = dict() - for I in range(0, 63): - self.modname['xe' + str(I)] = 'swp' + str(I) - - # open socket if required - # - if opennow and keepopen: - self.__open__() - - #--------------- - # - def __del__(self): - - """Destructor: flush and close all files that we opened""" - - try: - self.close() - except: - pass - - #--------------- - # - def __str__(self): - - """Return object state in human-readable form""" - - s = [] - s.append(repr(self)) - s.append('version: ' + self.version) - s.append('keepopen: ' + str(self.keepopen)) - s.append('timeout: ' + str(self.timeout) + ' seconds') - s.append('logfileobj: ' + str(self.logfileobj)) - s.append('socketname: ' + str(self.socketname)) - s.append('socketobj: ' + str(self.socketobj)) - s.append('prompt: \"' + str(self.re_prompt.pattern) + '\"') - s.append('buffer (last 100 chars): ' + str(self.buffer)[-100:]) - return '\n'.join(s) - - #--------------- - # - def getreg(self, reg, fields=False): - - """Get device register(s) by name. - - The general format in which registers are returned from the shell is - reg_name(N).M=V for raw values and reg_name(N).M= where N - is an array index, M is a module or port name, V is a value, and F is a - field name. Register/field values are all converted to unsigned - integers. There is a built in name converstion fucntion to change - Broadcom "xe*" port names to "swp*" names that match the kernel. - - bcmshell.getreg('reg_name') returns dict of lists of values. As an - optimization, if there is only one entry in the dict, only the list of - values is returned and if there is only one entry in each list, only the - values are returned - - Examples: - bcmshell.getreg('cmic_config') returns a value... - 1057759299. - - bcmshell.getreg('protocol_pkt_control') returns a list of values... - [0, 0, 0, ..., 0] - - bcmshell.getreg('egr_mtu') returns a dict of values.... - {'cpu0': 0x3fff, - 'xe0': 0x3fff, - ... - 'lb0': 0x3fff} - - bcmshell.getreg('pg_min_cell') returns a dict of lists of values.... - {'cpu0:'[0, 0, 0, 0, 0, 0, 0, 0], - 'xe0': [0, 0, 0, 0, 0, 0, 0, 0], - ... - 'lb0': [0, 0, 0, 0, 0, 0, 0, 0]} - - - bcmshell.getreg('reg_name', True) returns dict of lists of dicts of - field/values. The same optimizations used for raw values apply. - - Examples: - bcmshell.getreg('cmic_config', True) returns a dict of field/values... - {'IGNORE_MMU_BKP_TXDMA_PKT': 0, - 'EN_SER_INTERLEAVE_PARITY': 1, - 'MIIM_ADDR_MAP_ENABLE': 1, - 'IGNORE_MMU_BKP_REMOTE_PKT': 0, - ... - 'DMA_GARBAGE_COLLECT_EN': 0} - - bcmshell.getreg('protocol_pkt_control', True) returns - [{'SRP_PKT_TO_CPU':0, 'SRP_FWD_ACTION':0,... 'ARP_REPLY_DROP':0}, - {'SRP_PKT_TO_CPU':0, 'SRP_FWD_ACTION':0,... 'ARP_REPLY_DROP':0}, - ... - {'SRP_PKT_TO_CPU':0, 'SRP_FWD_ACTION':0,... 'ARP_REPLY_DROP':0}] - - bcmshell.getreg('egr_mtu', fields=True) returns a dict of dicts... - {'cpu0': {'MTU_SIZE',0x3fff, 'MTU_ENABLE',0}, - 'xe0': {'MTU_SIZE',0x3fff, 'MTU_ENABLE',0}, - ... - 'lb0': {'MTU_SIZE',0x3fff, 'MTU_ENABLE',0}} - - bcmshell.getreg('pg_min_cell') returns a dict of lists of values.... - {'cpu0:'[{'PG_MIN':0}, {'PG_MIN':0},... {'PG_MIN':0}], - 'xe0:'[{'PG_MIN':0}, {'PG_MIN':0},... {'PG_MIN':0}], - ... - 'lb0:'[{'PG_MIN':0}, {'PG_MIN':0},... {'PG_MIN':0}]} - """ - - # make sure everything is sane and read the register - # - if type(reg) is not str: - raise TypeError("expecting string argument to bmcdiag.getreg(reg)") - elif reg.find('\n') >= 0: - raise ValueError("unexpected newline in bmcdiag.getreg(%s)" % reg ) - elif reg.find('\s') >= 0: - raise ValueError("unexpected whitespace in bmcdiag.getreg(%s)" % reg) - - if fields: - t = self.run('getreg ' + reg) - else: - t = self.run('getreg raw ' + reg) - - if 'Syntax error parsing' in t: - raise RuntimeError('\"%s\" is not a register' % reg) - - # get the results into a list - # - t = self.re_oneline.sub('', t) - t = t.split('\n') - if t[-1] is '': - t.pop() - - # get the results into a dict (module) of lists (array) of values/fields - # - def __parse_reg__(text, fields=False): - if fields: - m = self.re_reg_parse_fields.search(text) - s = m.group(2).split(',') - t = dict([self.__get_field__(S) for S in s]) - else: - m = self.re_reg_parse_raw.search(text) - t = int(m.group(2), 16) - return(self.modname.get(m.group(1), m.group(1)), t) - - t = [__parse_reg__(T, fields) for T in t] - d = dict() - for I in t: - if I[0] in d: - d[I[0]].append(I[1]) - else: - d[I[0]] = [I[1]] - - # now optimize the return - # - for I in iter(d): - if len(d[I]) is 1: - d[I] = d[I][0] - - if len(d) is 1: - return d.values()[0] - else: - return d - - - #--------------- - # - def gettable(self, table, fields=False, start=None, entries=None): - - """Get device memory based table(s) by name. Tables are returned as a - list of value/field-dict. Table entry/field values are converted into - unsigned integers. If "fields" is set to True, we return a list of - dictionaries of field/value. - - Examples: - bcmshell.gettable('egr_ing_port') returns - [0, 0, 0, ... 0] - - bcmshell.gettable('egr_ing_port', True) returns - [{'HIGIG2': 0, 'PORT_TYPE': 0}, - {'HIGIG2': 0, 'PORT_TYPE': 0}, - {'HIGIG2': 0, 'PORT_TYPE': 0}, - ... - {'HIGIG2': 0, 'PORT_TYPE': 0}] - """ - - if type(table) is not str: - raise TypeError("bcmshell.gettable(table) expects string not %s" % - type(table)) - elif table.find('\n') >= 0: - raise ValueError("unexpected newline in bmcshell.gettable(%s)" % - table ) - elif table.find('\s') >= 0: - raise ValueError("unexpected whitespace in bmcshell.gettable(%s)" % - table) - - cmd = 'dump all' - if not fields: - cmd += ' raw' - cmd += " %s" % table - if start != None or entries != None: - cmd += " %d" % (start or 0) - cmd += " %d" % (entries or 1) - - t = self.run(cmd) - - if 'Unknown option or memory' in t: - raise RuntimeError('\"%s\" is not a table' % table) - - if 'out of range' in t: - err = table - if start != None or entries != None: - err += " %d" % (start or 0) - err += " %d" % (entries or 1) - raise IndexError('\"%s\" table index is out of range' % err) - - # get all of the return into a list - # - t = self.re_oneline.sub('', t) - t = self.re_table_header.sub('', t) - t = self.re_table_trailer.sub('', t) - t = t.split('\n') - if t[-1] is '': - t.pop() - - # parse the contents - # - def __parse_table__(text, fields=False): - if fields: - t = text.split(',') - v = [self.__get_field__(T) for T in t] - return dict(v) - else: - t = text.split() - v = 0 - for I in range(len(t)): - v += (int(t[I], 16) << (32 * I)) - return v - t = [__parse_table__(T, fields) for T in t] - - return t - - #--------------- - # - def cmd(self, cmd): - - """Run a command and print the results""" - - s = self.run(cmd) - if 'Unknown command:' in s: - raise ValueError(s) - print(s) - - - #--------------- - # - def prettyprint(self, d, level=0): - - """Print the structured output generated by getreg and gettable in a - human readable format""" - - s = level * 8 * " " - if type(d) is dict: - for I in sorted(d, key=self.__name_conv__): - if type(d[I]) is int: - print("%s %30s: " % (s, I), end=" ") - else: - print("%s %s:" % (s, I)) - self.prettyprint(d[I], (level + 1)) - elif type(d) is list: - for I in range(len(d)): - i = "[" + str(I) + "]" - if type(d[I]) is int or type(d[I]) is long: - print("%s %10s: " % (s, i), end=" ") - else: - print("%s %s:" % (s, i)) - self.prettyprint(d[I], (level + 1)) - else: - print("%s" % (hex(d))) - - - #--------------- - # - def close(self): - - """Close the socket object""" - - if self.socketobj is not None: - self.socketobj.shutdown(socket.SHUT_RDWR) - self.socketobj.close() - self.socketobj = None - - #--------------- - # - def run(self, cmd): - - """Issue the command to the diag shell and collect the return data until - we detect the prompt. cmd must be a string and must not include a - newline, i.e. we expect a single command to be run per call.""" - - if type(cmd) is not str: - raise TypeError("expecting string argument to bmcdiag.run(cmd)") - elif cmd.find('\n') >= 0: - raise ValueError("unexpected newline in bmcdiag.run(cmd)") - - self.__open__() - try: - self.socketobj.sendall(cmd + '\n') - except socket.error as err: - (errno, errstr) = err.args - raise IOError("unable to send command \"%s\", %s" % (cmd, errstr)) - - self.buffer = '' - self.socketobj.settimeout(self.timeout) - quitting_time = time.time() + self.timeout - while True: - try: - self.buffer += self.socketobj.recv(4096) - except socket.timeout: - raise RuntimeError("recv stalled for %d seconds" % self.timeout) - found = self.re_prompt.search(self.buffer) - if found: - break - if time.time() > quitting_time: - raise RuntimeError("accepting input for %d seconds" % self.timeout) - - if found.end(0) != len(self.buffer): - raise RuntimeError("prompt detected in the middle of input") - - if not self.keepopen: - self.close() - return self.buffer[:found.start(0)] - - #--------------- - # - def __name_conv__(self, s): - l = self.re_conv.findall(s) - for I in range(len(l)): - if l[I].isdigit(): - l[I] = int(l[I]) - return l - - #--------------- - # - def __get_field__(self, text): - m = self.re_get_field.search(text) - return (m.group(1), int(m.group(2), 16)) - - #--------------- - # - def __open__(self): - - """Open the bcm diag shell socket exported by switchd. Complete any - dangling input by issuing a newline and flush the read side in case the - last user left something lying around. No-op if the socket is already - open. NOTE: socket.connect is non-blocking, so we need to exchange - a command with the bcm diag shell to know that we've actually obtained - socket ownership.""" - - if self.socketobj is None: - timeout = self.timeout - while True: - try: - self.socketobj = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.socketobj.settimeout(self.timeout) - self.socketobj.connect(self.socketname) - except socket.error as err: - (errno, errstr) = err.args - if timeout == 0: - raise IOError("unable to open %s, %s" % (self.socketname, errstr)) - time.sleep(1) - timeout -= 1 - else: - break; - - - # flush out the socket in case it was left dirty - try: - self.socketobj.sendall('echo bcmshell\n') - quitting_time = time.time() + self.timeout - buf = '' - while True: - try: - buf += self.socketobj.recv(1024) - except socket.timeout: - raise IOError("unable to receive data from %s for %d seconds" % - (self.socketname, self.timeout)) - - found = self.re_connectprompt.search(buf) - if found: - break - if time.time() > quitting_time: - raise IOError("unable to flush %s for %d seconds" % - (self.socketname, self.timeout)) - - except socket.error as err: - (errno, errstr) = err.args - raise IOError("Socket error: unable to flush %s on open: %s" % (self.socketname, errstr)) - except IOError as e: - raise IOError("unable to flush %s on open: %s" % (self.socketname, e.message)) - except: - raise IOError("unable to flush %s on open" % self.socketname) diff --git a/sonic_sfp/inf8628.py b/sonic_sfp/inf8628.py deleted file mode 100644 index 2d16c983457e..000000000000 --- a/sonic_sfp/inf8628.py +++ /dev/null @@ -1,161 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# QSFP-DD 8X Transceiver (QSFP Double Density) -#---------------------------------------------------------------------------- - -from __future__ import print_function - -try: - from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods -except ImportError as e: - raise ImportError ("%s - required module not found" % e) - -class inf8628InterfaceId(sffbase): - - def decode_revision_compliance(self, eeprom_data, offset, size): - return '%c.%c' % (eeprom_data[offset][0], eeprom_data[offset][1]) - - def decode_module_state(self, eeprom_data, offset, size): - module_state_byte = eeprom_data[offset] - module_state = int(module_state_byte, 16) & 14 - if module_state == 2: - return 'Low Power State' - elif module_state == 4: - return 'Power Up State' - elif module_state == 6: - return 'Ready State' - elif module_state == 8: - return 'Power Down State' - elif module_state == 10: - return 'Fault State' - return 'Unknown State %s' % module_state - - version = '1.0' - - interface_id = { - 'Identifier': - {'offset': 0, - 'size': 1, - 'type': 'enum', - 'decode': type_of_transceiver}, - 'Revision Compliance': - {'offset': 1, - 'type': 'func', - 'decode': {'func': decode_revision_compliance}}, - 'Module State': - {'offset': 3, - 'type': 'func', - 'decode': {'func': decode_module_state}}, - 'Interrupt Asserted': - {'offset': 3, - 'bit': 0, - 'type': 'bitvalue'}, - 'Vendor Name': - {'offset': 129, - 'size': 16, - 'type': 'str'}, - 'Vendor Part Number': - {'offset': 148, - 'size': 16, - 'type': 'str'}, - 'Vendor Revision': - {'offset': 164, - 'size': 2, - 'type': 'str'}, - 'Vendor Serial Number': - {'offset': 166, - 'size': 16, - 'type': 'str'}, - } - - sfp_type = { - 'type': - {'offset': 0, - 'size': 1, - 'type': 'enum', - 'decode': type_of_transceiver} - } - - sfp_type_abbrv_name = { - 'type_abbrv_name': - {'offset': 0, - 'size': 1, - 'type': 'enum', - 'decode': type_abbrv_name} - } - - vendor_name = { - 'Vendor Name': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_pn = { - 'Vendor PN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_rev = { - 'Vendor Rev': - {'offset': 0, - 'size': 2, - 'type': 'str'} - } - - vendor_sn = { - 'Vendor SN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - def __init__(self, eeprom_raw_data=None): - self.interface_data = None - start_pos = 0 - - if eeprom_raw_data is not None: - self.interface_data = sffbase.parse(self, - self.interface_id, - eeprom_raw_data, - start_pos) - - def parse(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.interface_id, eeprom_raw_data, start_pos) - - def parse_sfp_type(self, type_raw_data, start_pos): - return sffbase.parse(self, self.sfp_type, type_raw_data, start_pos) - - def parse_sfp_type_abbrv_name(self, type_raw_data, start_pos): - return sffbase.parse(self, self.sfp_type_abbrv_name, type_raw_data, start_pos) - - def parse_vendor_name(self, name_raw_data, start_pos): - return sffbase.parse(self, self.vendor_name, name_raw_data, start_pos) - - def parse_vendor_rev(self, rev_raw_data, start_pos): - return sffbase.parse(self, self.vendor_rev, rev_raw_data, start_pos) - - def parse_vendor_pn(self, pn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_pn, pn_raw_data, start_pos) - - def parse_vendor_sn(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_sn, sn_raw_data, start_pos) - - def dump_pretty(self): - if self.interface_data is None: - print('Object not initialized, nothing to print') - return - sffbase.dump_pretty(self, self.interface_data) - - def get_calibration_type(self): - return self.calibration_type - - def get_data(self): - return self.interface_data - - def get_data_pretty(self): - return sffbase.get_data_pretty(self, self.interface_data) diff --git a/sonic_sfp/sff8024.py b/sonic_sfp/sff8024.py deleted file mode 100644 index 2a8e5542661b..000000000000 --- a/sonic_sfp/sff8024.py +++ /dev/null @@ -1,66 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# SFF-8024 Rev 4.5 -#---------------------------------------------------------------------------- - -from __future__ import print_function - -type_of_transceiver = { - '00': 'Unknown or unspecified', - '01': 'GBIC', - '02': 'Module/connector soldered to motherboard', - '03': 'SFP/SFP+/SFP28', - '04': '300 pin XBI', - '05': 'XENPAK', - '06': 'XFP', - '07': 'XFF', - '08': 'XFP-E', - '09': 'XPAK', - '0a': 'X2', - '0b': 'DWDM-SFP/SFP+', - '0c': 'QSFP', - '0d': 'QSFP+ or later', - '0e': 'CXP or later', - '0f': 'Shielded Mini Multilane HD 4X', - '10': 'Shielded Mini Multilane HD 8X', - '11': 'QSFP28 or later', - '12': 'CXP2 (aka CXP28) or later', - '13': 'CDFP (Style 1/Style2)', - '14': 'Shielded Mini Multilane HD 4X Fanout Cable', - '15': 'Shielded Mini Multilane HD 8X Fanout Cable', - '16': 'CDFP (Style 3)', - '17': 'microQSFP', - '18': 'QSFP-DD Double Density 8X Pluggable Transceiver', - '19': 'OSFP 8X Pluggable Transceiver', - '1a': 'SFP-DD Double Density 2X Pluggable Transceiver' -} - -type_abbrv_name = { - '00': 'Unknown', - '01': 'GBIC', - '02': 'Soldered', - '03': 'SFP', - '04': 'XBI300', - '05': 'XENPAK', - '06': 'XFP', - '07': 'XFF', - '08': 'XFP-E', - '09': 'XPAK', - '0a': 'X2', - '0b': 'DWDM-SFP', - '0c': 'QSFP', - '0d': 'QSFP+', - '0e': 'CXP', - '0f': 'HD4X', - '10': 'HD8X', - '11': 'QSFP28', - '12': 'CXP2', - '13': 'CDFP-1/2', - '14': 'HD4X-Fanout', - '15': 'HD8X-Fanout', - '16': 'CDFP-3', - '17': 'MicroQSFP', - '18': 'QSFP-DD', - '19': 'OSFP-8X', - '1a': 'SFP-DD' -} diff --git a/sonic_sfp/sff8436.py b/sonic_sfp/sff8436.py deleted file mode 100644 index c1ff01f43111..000000000000 --- a/sonic_sfp/sff8436.py +++ /dev/null @@ -1,1700 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# SFF-8436 QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER -#---------------------------------------------------------------------------- - -from __future__ import print_function - -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 - from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods -except ImportError as e: - raise ImportError (str(e) + "- required module not found") - -class sff8436InterfaceId(sffbase): - - version = '1.0' - - specification_compliance = {'10/40G Ethernet Compliance Code': - {'offset':3, - 'size':1, - 'type' : 'bitmap', - 'decode' : { - '10GBase-LRM': - {'offset': 3, - 'bit': 6}, - '10GBase-LR': - {'offset': 3, - 'bit': 5}, - '10GBase-SR': - {'offset': 3, - 'bit': 4}, - '40GBASE-CR4': - {'offset': 3, - 'bit': 3}, - '40GBASE-SR4': - {'offset': 3, - 'bit': 2}, - '40GBASE-LR4': - {'offset': 3, - 'bit': 1}, - '40G Active Cable (XLPPI)': - {'offset': 3, - 'bit': 0}}}, - 'SONET Compliance codes': - {'offset':4, - 'size':1, - 'type' : 'bitmap', - 'decode' : { - '40G OTN (OTU3B/OTU3C)': - {'offset': 4, - 'bit': 3}, - 'OC 48, long reach': - {'offset': 4, - 'bit': 2}, - 'OC 48, intermediate reach': - {'offset': 4, - 'bit': 1}, - 'OC 48 short reach': - {'offset': 4, - 'bit': 0}}}, - 'SAS/SATA compliance codes': - {'offset': 5, - 'size' : 1, - 'type' : 'bitmap', - 'decode': { - 'SAS 6.0G': - {'offset': 5, - 'bit': 5}, - 'SAS 3.0G': - {'offset': 5, - 'bit': 4}}}, - 'Gigabit Ethernet Compliant codes': - {'offset': 6, - 'size' : 1, - 'type' : 'bitmap', - 'decode': { - '1000BASE-T': - {'offset': 6, - 'bit': 3}, - '1000BASE-CX': - {'offset': 6, - 'bit': 2}, - '1000BASE-LX': - {'offset': 6, - 'bit': 1}, - '1000BASE-SX': - {'offset': 6, - 'bit': 0}}}, - 'Fibre Channel link length/Transmitter Technology': - {'offset': 7, - 'size' : 2, - 'type' : 'bitmap', - 'decode': { - 'Very long distance (V)': - {'offset': 7, - 'bit': 7}, - 'Short distance (S)': - {'offset': 7, - 'bit': 6}, - 'Intermediate distance (I)': - {'offset': 7, - 'bit': 5}, - 'Long distance (L)': - {'offset': 7, - 'bit': 4}, - 'Medium (M)': - {'offset': 7, - 'bit': 3}, - 'Longwave laser (LC)': - {'offset': 7, - 'bit': 1}, - 'Electrical inter-enclosure (EL)': - {'offset': 7, - 'bit': 0}, - 'Electrical intra-enclosure': - {'offset': 8, - 'bit': 7}, - 'Shortwave laser w/o OFC (SN)': - {'offset': 8, - 'bit': 6}, - 'Shortwave laser w OFC (SL)': - {'offset': 8, - 'bit': 5}, - 'Longwave Laser (LL)': - {'offset': 8, - 'bit': 4}}}, - 'Fibre Channel transmission media': - {'offset': 8, - 'size' : 1, - 'type' : 'bitmap', - 'decode': { - 'Twin Axial Pair (TW)': - {'offset': 8, - 'bit': 7}, - 'Shielded Twisted Pair (TP)': - {'offset': 8, - 'bit': 6}, - 'Miniature Coax (MI)': - {'offset': 8, - 'bit': 5}, - 'Video Coax (TV)': - {'offset': 8, - 'bit': 4}, - 'Multi-mode 62.5m (M6)': - {'offset': 8, - 'bit': 3}, - 'Multi-mode 50m (M5)': - {'offset': 8, - 'bit': 2}, - 'Multi-mode 50um (OM3)': - {'offset': 8, - 'bit': 1}, - 'Single Mode (SM)': - {'offset': 8, - 'bit': 0}}}, - 'Fibre Channel Speed': - {'offset': 9, - 'size' : 1, - 'type' : 'bitmap', - 'decode': { - '1200 Mbytes/Sec': - {'offset': 9, - 'bit': 7}, - '800 Mbytes/Sec': - {'offset': 9, - 'bit': 6}, - '1600 Mbytes/Sec': - {'offset': 9, - 'bit': 5}, - '400 Mbytes/Sec': - {'offset': 9, - 'bit': 4}, - '200 Mbytes/Sec': - {'offset': 9, - 'bit': 2}, - '100 Mbytes/Sec': - {'offset': 9, - 'bit': 0}}}} - - ext_type_of_transceiver = { - '00': 'Power Class 1(1.5W max)', - '04': 'Power Class 1(1.5W max), CDR present in Tx', - '08': 'Power Class 1(1.5W max), CDR present in Rx', - '0c': 'Power Class 1(1.5W max), CDR present in Rx Tx', - '10': 'Power Class 1(1.5W max), CLEI present', - '14': 'Power Class 1(1.5W max), CLEI present, CDR present in Tx', - '18': 'Power Class 1(1.5W max), CLEI present, CDR present in Rx', - '1c': 'Power Class 1(1.5W max), CLEI present, CDR present in Rx Tx', - - '40': 'Power Class 2(2.0W max)', - '44': 'Power Class 2(2.0W max), CDR present in Rx', - '48': 'Power Class 2(2.0W max), CDR present in Tx', - '4c': 'Power Class 2(2.0W max), CDR present in Rx Tx', - '50': 'Power Class 2(2.0W max), CLEI present', - '54': 'Power Class 2(2.0W max), CLEI present, CDR present in Rx', - '58': 'Power Class 2(2.0W max), CLEI present, CDR present in Tx', - '5c': 'Power Class 2(2.0W max), CLEI present, CDR present in Rx Tx', - - '80': 'Power Class 3(2.5W max)', - '84': 'Power Class 3(2.5W max), CDR present in Rx', - '88': 'Power Class 3(2.5W max), CDR present in Tx', - '8c': 'Power Class 3(2.5W max), CDR present in Rx Tx', - '90': 'Power Class 3(2.5W max), CLEI present', - '94': 'Power Class 3(2.5W max), CLEI present, CDR present in Rx', - '98': 'Power Class 3(2.5W max), CLEI present, CDR present in Tx', - '9c': 'Power Class 3(2.5W max), CLEI present, CDR present in Rx Tx', - - 'c0': 'Power Class 4(3.5W max)', - 'c4': 'Power Class 4(3.5W max), CDR present in Rx', - 'c8': 'Power Class 4(3.5W max), CDR present in Tx', - 'cc': 'Power Class 4(3.5W max), CDR present in Rx Tx', - 'd0': 'Power Class 4(3.5W max), CLEI present', - 'd4': 'Power Class 4(3.5W max), CLEI present, CDR present in Rx', - 'd8': 'Power Class 4(3.5W max), CLEI present, CDR present in Tx', - 'dc': 'Power Class 4(3.5W max), CLEI present, CDR present in Rx Tx' - } - - connector = { - '00': 'Unknown or unspecified', - '01': 'SC', - '02': 'FC Style 1 copper connector', - '03': 'FC Style 2 copper connector', - '04': 'BNC/TNC', - '05': 'FC coax headers', - '06': 'Fiberjack', - '07': 'LC', - '08': 'MT-RJ', - '09': 'MU', - '0a': 'SG', - '0b': 'Optical Pigtail', - '0c': 'MPOx12', - '0d': 'MPOx16', - '20': 'HSSDC II', - '21': 'Copper pigtail', - '22': 'RJ45', - '23': 'No separable connector' - } - - encoding_codes = { - '00':'Unspecified', - '01': '8B10B', - '02': '4B5B', - '03': 'NRZ', - '04': 'SONET Scrambled', - '05': '64B66B', - '06': 'Manchester', - '07': '256B257B' - } - - rate_identifier = {'00':'QSFP+ Rate Select Version 1'} - - interface_id = {'Identifier': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_of_transceiver}, - 'Extended Identifier': - {'offset':1, - 'size':1, - 'type' : 'enum', - 'decode': ext_type_of_transceiver}, - 'Connector': - {'offset':2, - 'size':1, - 'type' : 'enum', - 'decode': connector}, - 'Specification compliance': - {'offset' : 3, - 'type' : 'nested', - 'decode' : specification_compliance}, - 'Encoding': - {'offset':11, - 'size':1, - 'type' : 'enum', - 'decode' : encoding_codes}, - 'Nominal Bit Rate(100Mbs)': - {'offset': 12, - 'size':1, - 'type':'int'}, - 'Extended RateSelect Compliance': - {'offset':13, - 'size':1, - 'type' : 'enum', - 'decode' : rate_identifier}, - 'Length(km)': - {'offset':14, - 'size':1, - 'type':'int'}, - 'Length OM3(2m)': - {'offset':15, - 'size':1, - 'type':'int'}, - 'Length OM2(m)': - {'offset':16, - 'size':1, - 'type':'int'}, - 'Length OM1(m)': - {'offset':17, - 'size':1, - 'type':'int'}, - 'Length Cable Assembly(m)': - {'offset':18, - 'size':1, - 'type':'int'}, - # Device Tech - 'Vendor Name': - {'offset' : 20, - 'size': 16, - 'type': 'str'}, - 'Vendor OUI': - {'offset': 37, - 'size' : 3, - 'type' : 'hex'}, - 'Vendor PN': - {'offset': 40, - 'size' : 16, - 'type' : 'str'}, - 'Vendor Rev': - {'offset': 56, - 'size' : 2, - 'type' : 'str'}, - 'Vendor SN': - {'offset': 68, - 'size' : 16, - 'type' : 'str'}, - 'Vendor Date Code(YYYY-MM-DD Lot)': - {'offset': 84, - 'size' : 8, - 'type' : 'date'}, - 'Diagnostic Monitoring Type': - {'offset': 92, - 'size' : 1, - 'type' : 'bitmap', - 'decode': {}}, - 'Enhanced Options': - {'offset': 93, - 'size' : 1, - 'type' : 'bitmap', - 'decode': {}}} - - sfp_info_bulk = {'type': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_of_transceiver}, - 'type_abbrv_name': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_abbrv_name}, - 'Extended Identifier': - {'offset':1, - 'size':1, - 'type' : 'enum', - 'decode': ext_type_of_transceiver}, - 'Connector': - {'offset':2, - 'size':1, - 'type' : 'enum', - 'decode': connector}, - 'Specification compliance': - {'offset' : 3, - 'type' : 'nested', - 'decode' : specification_compliance}, - 'EncodingCodes': - {'offset':11, - 'size':1, - 'type' : 'enum', - 'decode' : encoding_codes}, - 'Nominal Bit Rate(100Mbs)': - {'offset': 12, - 'size':1, - 'type':'int'}, - 'RateIdentifier': - {'offset':13, - 'size':1, - 'type' : 'enum', - 'decode' : rate_identifier}, - 'Length(km)': - {'offset':14, - 'size':1, - 'type':'int'}, - 'Length OM3(2m)': - {'offset':15, - 'size':1, - 'type':'int'}, - 'Length OM2(m)': - {'offset':16, - 'size':1, - 'type':'int'}, - 'Length OM1(m)': - {'offset':17, - 'size':1, - 'type':'int'}, - 'Length Cable Assembly(m)': - {'offset':18, - 'size':1, - 'type':'int'} - } - - vendor_name = { - 'Vendor Name': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_pn = { - 'Vendor PN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_rev = { - 'Vendor Rev': - {'offset': 0, - 'size': 2, - 'type': 'str'} - } - - vendor_sn = { - 'Vendor SN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_oui = { - 'Vendor OUI': - {'offset':0, - 'size':3, - 'type' : 'hex'} - } - - vendor_date = { - 'VendorDataCode(YYYY-MM-DD Lot)': - {'offset':0, - 'size':8, - 'type': 'date'} - } - - qsfp_dom_capability = { - 'Tx_power_support': - {'offset': 0, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx_power_support': - {'offset': 0, - 'bit': 3, - 'type': 'bitvalue'}, - 'Voltage_support': - {'offset': 0, - 'bit': 4, - 'type': 'bitvalue'}, - 'Temp_support': - {'offset': 0, - 'bit': 5, - 'type': 'bitvalue'} - } - - def __init__(self, eeprom_raw_data=None): - self.interface_data = None - start_pos = 128 - - if eeprom_raw_data != None: - self.interface_data = sffbase.parse(self, - self.interface_id, - eeprom_raw_data, - start_pos) - - def parse(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.interface_id, eeprom_raw_data, start_pos) - - def parse_sfp_info_bulk(self, type_raw_data, start_pos): - return sffbase.parse(self, self.sfp_info_bulk, type_raw_data, start_pos) - - def parse_vendor_name(self, name_raw_data, start_pos): - return sffbase.parse(self, self.vendor_name, name_raw_data, start_pos) - - def parse_vendor_rev(self, rev_raw_data, start_pos): - return sffbase.parse(self, self.vendor_rev, rev_raw_data, start_pos) - - def parse_vendor_pn(self, pn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_pn, pn_raw_data, start_pos) - - def parse_vendor_sn(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_sn, sn_raw_data, start_pos) - - def parse_vendor_date(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_date, sn_raw_data, start_pos) - - def parse_vendor_oui(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_oui, sn_raw_data, start_pos) - - def parse_qsfp_dom_capability(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.qsfp_dom_capability, sn_raw_data, start_pos) - - def dump_pretty(self): - if self.interface_data == None: - print('Object not initialized, nothing to print') - return - sffbase.dump_pretty(self, self.interface_data) - - def get_calibration_type(self): - return self.calibration_type - - def get_data(self): - return self.interface_data - - def get_data_pretty(self): - return sffbase.get_data_pretty(self, self.interface_data) - - -class sff8436Dom(sffbase): - - version = '1.0' - - def get_calibration_type(self): - return self._calibration_type - - def calc_temperature(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - - result = (msb << 8) | (lsb & 0xff) - result = self.twos_comp(result, 16) - - if cal_type == 1: - - # Internal calibration - - result = float(result / 256.0) - retval = '%.4f' %result + 'C' - elif cal_type == 2: - - # External calibration - - # T(C) = T_Slope * T_AD + T_Offset - off = self.dom_ext_calibration_constants['T_Slope']['offset'] - msb_t = int(eeprom_data[off], 16) - lsb_t = int(eeprom_data[off + 1], 16) - t_slope = (msb_t << 8) | (lsb_t & 0xff) - - off = self.dom_ext_calibration_constants['T_Offset']['offset'] - msb_t = int(eeprom_data[off], 16) - lsb_t = int(eeprom_data[off + 1], 16) - t_offset = (msb_t << 8) | (lsb_t & 0xff) - t_offset = self.twos_comp(t_offset, 16) - - result = t_slope * result + t_offset - result = float(result / 256.0) - retval = '%.4f' %result + 'C' - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_voltage(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - # Internal Calibration - - result = float(result * 0.0001) - #print(indent, name, ' : %.4f' %result, 'Volts') - retval = '%.4f' %result + 'Volts' - elif cal_type == 2: - - # External Calibration - - # V(uV) = V_Slope * VAD + V_Offset - off = self.dom_ext_calibration_constants['V_Slope']['offset'] - msb_v = int(eeprom_data[off], 16) - lsb_v = int(eeprom_data[off + 1], 16) - v_slope = (msb_v << 8) | (lsb_v & 0xff) - - off = self.dom_ext_calibration_constants['V_Offset']['offset'] - msb_v = int(eeprom_data[off], 16) - lsb_v = int(eeprom_data[off + 1], 16) - v_offset = (msb_v << 8) | (lsb_v & 0xff) - v_offset = self.twos_comp(v_offset, 16) - - result = v_slope * result + v_offset - result = float(result * 0.0001) - #print(indent, name, ' : %.4f' %result, 'Volts') - retval = '%.4f' %result + 'Volts' - else: - #print(indent, name, ' : Unknown') - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_bias(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - # Internal Calibration - - result = float(result * 0.002) - #print(indent, name, ' : %.4f' %result, 'mA') - retval = '%.4f' %result + 'mA' - - elif cal_type == 2: - # External Calibration - - # I(uA) = I_Slope * I_AD + I_Offset - off = self.dom_ext_calibration_constants['I_Slope']['offset'] - msb_i = int(eeprom_data[off], 16) - lsb_i = int(eeprom_data[off + 1], 16) - i_slope = (msb_i << 8) | (lsb_i & 0xff) - - off = self.dom_ext_calibration_constants['I_Offset']['offset'] - msb_i = int(eeprom_data[off], 16) - lsb_i = int(eeprom_data[off + 1], 16) - i_offset = (msb_i << 8) | (lsb_i & 0xff) - i_offset = self.twos_comp(i_offset, 16) - - result = i_slope * result + i_offset - result = float(result * 0.002) - #print(indent, name, ' : %.4f' %result, 'mA') - retval = '%.4f' %result + 'mA' - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_tx_power(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - result = float(result * 0.0001) - #print(indent, name, ' : ', power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - - elif cal_type == 2: - - # TX_PWR(uW) = TX_PWR_Slope * TX_PWR_AD + TX_PWR_Offset - off = self.dom_ext_calibration_constants['TX_PWR_Slope']['offset'] - msb_tx_pwr = int(eeprom_data[off], 16) - lsb_tx_pwr = int(eeprom_data[off + 1], 16) - tx_pwr_slope = (msb_tx_pwr << 8) | (lsb_tx_pwr & 0xff) - - off = self.dom_ext_calibration_constants['TX_PWR_Offset']['offset'] - msb_tx_pwr = int(eeprom_data[off], 16) - lsb_tx_pwr = int(eeprom_data[off + 1], 16) - tx_pwr_offset = (msb_tx_pwr << 8) | (lsb_tx_pwr & 0xff) - tx_pwr_offset = self.twos_comp(tx_pwr_offset, 16) - - result = tx_pwr_slope * result + tx_pwr_offset - result = float(result * 0.0001) - retval = self.power_in_dbm_str(result) - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_rx_power(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - # Internal Calibration - result = float(result * 0.0001) - #print(indent, name, " : ", power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - - elif cal_type == 2: - - # External Calibration - - # RX_PWR(uW) = RX_PWR_4 * RX_PWR_AD + - # RX_PWR_3 * RX_PWR_AD + - # RX_PWR_2 * RX_PWR_AD + - # RX_PWR_1 * RX_PWR_AD + - # RX_PWR(0) - off = self.dom_ext_calibration_constants['RX_PWR_4']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_4 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_3']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_3 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_2']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_2 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_1']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_1 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_0']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_0 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - rx_pwr = (rx_pwr_4 * result) + (rx_pwr_3 * result) + (rx_pwr_2 * result) + (rx_pwr_1 * result) + rx_pwr_0 - - result = float(result * 0.0001) - #print(indent, name, " : ", power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - dom_status_indicator = { - 'DataNotReady': - {'offset': 0, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_channel_status = { - 'Tx4LOS': - {'offset': 3, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx3LOS': - {'offset': 3, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx2LOS': - {'offset': 3, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx1LOS': - {'offset': 3, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx4LOS': - {'offset': 3, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx3LOS': - {'offset': 3, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx2LOS': - {'offset': 3, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx1LOS': - {'offset': 3, - 'bit': 0, - 'type': 'bitvalue'}, - 'Tx4Fault': - {'offset': 4, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx3Fault': - {'offset': 4, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx2Fault': - {'offset': 4, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx1Fault': - {'offset': 4, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_tx_rx_los = {'Tx4LOS': - {'offset': 0, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx3LOS': - {'offset': 0, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx2LOS': - {'offset': 0, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx1LOS': - {'offset': 0, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx4LOS': - {'offset': 0, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx3LOS': - {'offset': 0, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx2LOS': - {'offset': 0, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx1LOS': - {'offset': 0, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_tx_fault = {'Tx4Fault': - {'offset': 0, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx3Fault': - {'offset': 0, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx2Fault': - {'offset': 0, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx1Fault': - {'offset': 0, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_module_monitor = { - 'TempHighAlarm': - {'offset': 6, - 'bit': 7, - 'type': 'bitvalue'}, - 'TempLowAlarm': - {'offset': 6, - 'bit': 6, - 'type': 'bitvalue'}, - 'TempHighWarning': - {'offset': 6, - 'bit': 5, - 'type': 'bitvalue'}, - 'TempLowWarning': - {'offset': 6, - 'bit': 4, - 'type': 'bitvalue'}, - 'InitCompleteFlag': - {'offset': 6, - 'bit': 0, - 'type': 'bitvalue'}, - 'VccHighAlarm': - {'offset': 7, - 'bit': 7, - 'type': 'bitvalue'}, - 'VccLowAlarm': - {'offset': 7, - 'bit': 6, - 'type': 'bitvalue'}, - 'VccHighWarning': - {'offset': 7, - 'bit': 5, - 'type': 'bitvalue'}, - 'VccLowWarning': - {'offset': 7, - 'bit': 4, - 'type': 'bitvalue'}} - - dom_channel_monitor = { - 'Rx1PowerHighAlarm': - {'offset': 9, - 'bit': 7, - 'type': 'bitvalue'}, - 'Rx1PowerLowAlarm': - {'offset': 9, - 'bit': 6, - 'type': 'bitvalue'}, - 'Rx1PowerHighWarning': - {'offset': 9, - 'bit': 5, - 'type': 'bitvalue'}, - 'Rx1PowerLowWarning': - {'offset': 9, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx2PowerHighAlarm': - {'offset': 9, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx2PowerLowAlarm': - {'offset': 9, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx2PowerHighWarning': - {'offset': 9, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx2PowerLowWarning': - {'offset': 9, - 'bit': 0, - 'type': 'bitvalue'}, - 'Rx3PowerHighAlarm': - {'offset': 10, - 'bit': 7, - 'type': 'bitvalue'}, - 'Rx3PowerLowAlarm': - {'offset': 10, - 'bit': 6, - 'type': 'bitvalue'}, - 'Rx3PowerHighWarning': - {'offset': 10, - 'bit': 5, - 'type': 'bitvalue'}, - 'Rx3PowerLowWarning': - {'offset': 10, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx4PowerHighAlarm': - {'offset': 10, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx4PowerLowAlarm': - {'offset': 10, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx4PowerHighWarning': - {'offset': 10, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx4PowerLowWarning': - {'offset': 10, - 'bit': 0, - 'type': 'bitvalue'}, - 'Tx1BiasHighAlarm': - {'offset': 11, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx1BiasLowAlarm': - {'offset': 11, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx1BiasHighWarning': - {'offset': 11, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx1BiasLowWarning': - {'offset': 11, - 'bit': 4, - 'type': 'bitvalue'}, - 'Tx2BiasHighAlarm': - {'offset': 11, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx2BiasLowAlarm': - {'offset': 11, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx2BiasHighWarning': - {'offset': 11, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx2BiasLowWarning': - {'offset': 11, - 'bit': 0, - 'type': 'bitvalue'}, - 'Tx3BiasHighAlarm': - {'offset': 12, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx3BiasLowAlarm': - {'offset': 12, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx3BiasHighWarning': - {'offset': 12, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx3BiasLowWarning': - {'offset': 12, - 'bit': 4, - 'type': 'bitvalue'}, - 'Tx4BiasHighAlarm': - {'offset': 12, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx4BiasLowAlarm': - {'offset': 12, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx4BiasHighWarning': - {'offset': 12, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx4BiasLowWarning': - {'offset': 12, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_module_monitor_values = { - 'Temperature': - {'offset':22, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'Vcc': - {'offset':26, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}} - - dom_channel_monitor_values = { - 'RX1Power': - {'offset':34, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RX2Power': - {'offset':36, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RX3Power': - {'offset':38, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RX4Power': - {'offset':40, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'TX1Bias': - {'offset':42, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TX2Bias': - {'offset':44, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TX3Bias': - {'offset':46, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TX4Bias': - {'offset':48, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}} - - dom_map = { - 'ModuleMonitorValues': - {'offset': 7, - 'size': 2, - 'type': 'nested', - 'decode': dom_module_monitor_values}, - 'ChannelMonitorValues': - {'offset': 10, - 'size': 2, - 'type': 'nested', - 'decode': dom_channel_monitor_values}} - -# new added parser for some specific values interested by SNMP -# TO DO: find a way to reuse the definitions in above code, need refactor - revision_compliance = { - '00': 'Revision not specified', - '01': 'SFF-8436 Rev 4.8', - '02': 'SFF-8436 Rev 4.8 with extra bytes support', - '03': 'SFF-8636 Rev 1.3', - '04': 'SFF-8636 Rev 1.4', - '05': 'SFF-8636 Rev 1.5', - '06': 'SFF-8636 Rev 2.0', - '07': 'SFF-8636 Rev 2.5' - } - - sfp_dom_rev = { - 'dom_rev': - {'offset': 0, - 'size': 1, - 'type': 'enum', - 'decode': revision_compliance} - } - - dom_module_temperature = { - 'Temperature': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_temperature}} - } - - dom_module_voltage = { - 'Vcc': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_voltage}} - } - - dom_channel_monitor_params = { - 'RX1Power': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX2Power': - {'offset': 2, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX3Power': - {'offset': 4, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX4Power': - {'offset': 6, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'TX1Bias': - {'offset': 8, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX2Bias': - {'offset': 10, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX3Bias': - {'offset': 12, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX4Bias': - {'offset': 14, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}} - } - - dom_channel_monitor_params_with_tx_power = { - 'RX1Power': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX2Power': - {'offset': 2, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX3Power': - {'offset': 4, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'RX4Power': - {'offset': 6, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}}, - 'TX1Bias': - {'offset': 8, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX2Bias': - {'offset': 10, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX3Bias': - {'offset': 12, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX4Bias': - {'offset': 14, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TX1Power': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_tx_power}}, - 'TX2Power': - {'offset': 2, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_tx_power}}, - 'TX3Power': - {'offset': 4, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_tx_power}}, - 'TX4Power': - {'offset': 6, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_tx_power}} - } - - dom_module_threshold_values = { - 'TempHighAlarm': - {'offset':0, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempLowAlarm': - {'offset':2, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempHighWarning': - {'offset':4, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempLowWarning': - {'offset':6, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'VccHighAlarm': - {'offset':16, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VccLowAlarm': - {'offset':18, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VccHighWarning': - {'offset':20, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VccLowWarning': - {'offset':22, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}} - - dom_channel_threshold_values = { - 'RxPowerHighAlarm': - {'offset':0, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RxPowerLowAlarm': - {'offset':2, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RxPowerHighWarning': - {'offset':4, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RxPowerLowWarning': - {'offset':6, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'TxBiasHighAlarm': - {'offset':8, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TxBiasLowAlarm': - {'offset':10, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TxBiasHighWarning': - {'offset':12, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TxBiasLowWarning': - {'offset':14, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}} - - dom_channel_monitor_masks = { - 'Rx1PowerHighAlarm': - {'offset':0, - 'bit': 7, - 'type': 'bitvalue'}, - 'Rx1PowerLowAlarm': - {'offset':0, - 'bit': 6, - 'type': 'bitvalue'}, - 'Rx1PowerHighWarning': - {'offset':0, - 'bit': 5, - 'type': 'bitvalue'}, - 'Rx1PowerLowWarning': - {'offset':0, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx2PowerHighAlarm': - {'offset':0, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx2PowerLowAlarm': - {'offset':0, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx2PowerHighWarning': - {'offset':0, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx2PowerLowWarning': - {'offset':0, - 'bit': 0, - 'type': 'bitvalue'}, - 'Rx3PowerHighAlarm': - {'offset':1, - 'bit': 7, - 'type': 'bitvalue'}, - 'Rx3PowerLowAlarm': - {'offset':1, - 'bit': 6, - 'type': 'bitvalue'}, - 'Rx3PowerHighWarning': - {'offset':1, - 'bit': 5, - 'type': 'bitvalue'}, - 'Rx3PowerLowWarning': - {'offset':1, - 'bit': 4, - 'type': 'bitvalue'}, - 'Rx4PowerHighAlarm': - {'offset':1, - 'bit': 3, - 'type': 'bitvalue'}, - 'Rx4PowerLowAlarm': - {'offset':1, - 'bit': 2, - 'type': 'bitvalue'}, - 'Rx4PowerHighWarning': - {'offset':1, - 'bit': 1, - 'type': 'bitvalue'}, - 'Rx4PowerLowWarning': - {'offset':1, - 'bit': 0, - 'type': 'bitvalue'}, - 'Tx1BiasHighAlarm': - {'offset':2, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx1BiasLowAlarm': - {'offset':2, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx1BiasHighWarning': - {'offset':2, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx1BiasLowWarning': - {'offset':2, - 'bit': 4, - 'type': 'bitvalue'}, - 'Tx2BiasHighAlarm': - {'offset':2, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx2BiasLowAlarm': - {'offset':2, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx2BiasHighWarning': - {'offset':2, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx2BiasLowWarning': - {'offset':2, - 'bit': 0, - 'type': 'bitvalue'}, - 'Tx3BiasHighAlarm': - {'offset':3, - 'bit': 7, - 'type': 'bitvalue'}, - 'Tx3BiasLowAlarm': - {'offset':3, - 'bit': 6, - 'type': 'bitvalue'}, - 'Tx3BiasHighWarning': - {'offset': 3, - 'bit': 5, - 'type': 'bitvalue'}, - 'Tx3BiasLowWarning': - {'offset': 3, - 'bit': 4, - 'type': 'bitvalue'}, - 'Tx4BiasHighAlarm': - {'offset': 3, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx4BiasLowAlarm': - {'offset': 3, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx4BiasHighWarning': - {'offset': 3, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx4BiasLowWarning': - {'offset': 3, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_tx_disable = { - 'Tx4Disable': - {'offset':0, - 'bit': 3, - 'type': 'bitvalue'}, - 'Tx3Disable': - {'offset':0, - 'bit': 2, - 'type': 'bitvalue'}, - 'Tx2Disable': - {'offset':0, - 'bit': 1, - 'type': 'bitvalue'}, - 'Tx1Disable': - {'offset':0, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_power_control = { - 'PowerSet': - {'offset': 0, - 'bit': 1, - 'type': 'bitvalue'}, - 'PowerOverRide': - {'offset': 0, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_threshold_map = { - 'ChannelThresholdValues': - {'offset': 11, - 'size': 2, - 'type': 'nested', - 'decode': dom_channel_threshold_values}, - 'ChannelMonitorMasks': - {'offset': 12, - 'size': 2, - 'type': 'nested', - 'decode': dom_channel_monitor_masks}, - 'ModuleThresholdValues': - {'offset': 13, - 'size': 2, - 'type': 'nested', - 'decode': dom_module_threshold_values}} - - dom_control_bytes_masks = { - 'TX4Disable': - {'offset': 0, - 'bit': 3, - 'type': 'bitvalue'}, - 'TX3Disable': - {'offset': 0, - 'bit': 2, - 'type': 'bitvalue'}, - 'TX2Disable': - {'offset': 0, - 'bit': 1, - 'type': 'bitvalue'}, - 'TX1Disable': - {'offset': 0, - 'bit': 0, - 'type': 'bitvalue'}, - # RxXRateSelect & Tx4RateSelect are not supported yet. - 'Rx4AppSelect': - {'offset': 3, - 'size': 1, - 'type': 'int'}, - 'Rx3AppSelect': - {'offset': 4, - 'size': 1, - 'type': 'int'}, - 'Rx2AppSelect': - {'offset': 5, - 'size': 1, - 'type': 'int'}, - 'Rx1AppSelect': - {'offset': 6, - 'size': 1, - 'type': 'int'}, - 'PowerSet': - {'offset': 7, - 'bit': 1, - 'type': 'bitvalue'}, - 'PowerOverride': - {'offset': 7, - 'bit': 0, - 'type': 'bitvalue'}, - } - - #SFF8436 Table 39, Option Values (Address 192-195) (Page 00) - #each field indicates whether that feature is supported on this module - dom_option_value_masks = { - 'RXOutputAmplitudeProgramming': - {'offset': 1, - 'bit': 0, - 'type': 'bitvalue'}, - 'RxSquelchDisable': - {'offset': 2, - 'bit': 3, - 'type': 'bitvalue'}, - 'RxOutputDisableCapable': - {'offset': 2, - 'bit': 2, - 'type': 'bitvalue'}, - 'TxSquelchDisable': - {'offset': 2, - 'bit': 1, - 'type': 'bitvalue'}, - 'TxSquelch': - {'offset': 2, - 'bit': 0, - 'type': 'bitvalue'}, - 'MemoryPage02Provided': - {'offset': 3, - 'bit': 7, - 'type': 'bitvalue'}, - 'MemoryPage01Provided': - {'offset': 3, - 'bit': 6, - 'type': 'bitvalue'}, - 'RATE_SELECT': - {'offset': 3, - 'bit': 5, - 'type': 'bitvalue'}, - 'TxDisable': - {'offset': 3, - 'bit': 4, - 'type': 'bitvalue'}, - 'TxFault': - {'offset': 3, - 'bit': 3, - 'type': 'bitvalue'}, - 'TxSquelch_OMA_or_ReducePave': - {'offset': 3, - 'bit': 2, - 'type': 'bitvalue'}, - 'TxLOS': - {'offset': 3, - 'bit': 1, - 'type': 'bitvalue'}, - } - - - def __init__(self, eeprom_raw_data=None, calibration_type=1): - self._calibration_type = calibration_type - start_pos = 0 - - if eeprom_raw_data != None: - self.dom_data = sffbase.parse(self, self.dom_map, - eeprom_raw_data, start_pos) - - def parse(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_map, eeprom_raw_data, - start_pos) - -# Parser functions for specific values interested by SNMP - def parse_sfp_dom_rev(self, type_raw_data, start_pos): - return sffbase.parse(self, self.sfp_dom_rev, type_raw_data, start_pos) - - def parse_temperature(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_temperature, eeprom_raw_data, - start_pos) - - def parse_voltage(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_voltage, eeprom_raw_data, - start_pos) - - def parse_channel_monitor_params(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_monitor_params, eeprom_raw_data, - start_pos) - - def parse_channel_monitor_params_with_tx_power(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_monitor_params_with_tx_power, eeprom_raw_data, - start_pos) - - def parse_module_threshold_values(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_threshold_values, eeprom_raw_data, - start_pos) - - def parse_channel_threshold_values(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_threshold_values, eeprom_raw_data, - start_pos) - - def parse_channel_monitor_mask(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_monitor_masks, eeprom_raw_data, - start_pos) - - def parse_control_bytes(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_control_bytes_masks, eeprom_raw_data, start_pos) - - def parse_module_monitor_params(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_monitor, eeprom_raw_data, - start_pos) - - def parse_option_params(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_option_value_masks, eeprom_raw_data, - start_pos) - - def parse_dom_status_indicator(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_status_indicator, eeprom_raw_data, - start_pos) - - def parse_dom_channel_status(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_status, eeprom_raw_data, - start_pos) - - def parse_dom_tx_rx_los(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_tx_rx_los, eeprom_raw_data, - start_pos) - - def parse_dom_tx_fault(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_tx_fault, eeprom_raw_data, - start_pos) - - def parse_dom_tx_disable (self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_tx_disable, eeprom_raw_data, - start_pos) - - def parse_dom_power_control(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_power_control, eeprom_raw_data, - start_pos) - - def dump_pretty(self): - if self.dom_data == None: - print('Object not initialized, nothing to print') - return - sffbase.dump_pretty(self, self.dom_data) - - def get_data(self): - return self.dom_data - - def get_data_pretty(self): - return sffbase.get_data_pretty(self, self.dom_data) diff --git a/sonic_sfp/sff8472.py b/sonic_sfp/sff8472.py deleted file mode 100644 index d0d3441b3e83..000000000000 --- a/sonic_sfp/sff8472.py +++ /dev/null @@ -1,1219 +0,0 @@ -#! /usr/bin/env python -#-------------------------------------------------------------------------- -# -# Copyright 2012 Cumulus Networks, inc all rights reserved -# -#-------------------------------------------------------------------------- - -from __future__ import print_function - -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 - from .sff8024 import type_of_transceiver # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8024 import type_abbrv_name # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sffbase import sffbase # Dot module supports both Python 2 and Python 3 using explicit relative import methods -except ImportError as e: - raise ImportError (str(e) + "- required module not found") - -#------------------------------------------------------------------------------ - -class sff8472InterfaceId(sffbase): - """Parser and interpreter for Two wire Interface ID Data fields - - Address A0h - - Base types: - XXX - Complete documentation - - outtype - can be used to dictate the type of output you get - Mainly used with bitmap type. - if outtype == 'allbits': - parse gives all bitnames with values - if outtype == 'onbits': - parse gives all onbits with value = None - """ - - version = '1.0' - - transceiver_codes = { '10GEthernetComplianceCode': - {'offset':3, - 'size':1, - 'type' : 'bitmap', - 'decode' : {'10G Base-ER': - {'offset': 3, - 'bit': 7}, - '10G Base-LRM': - {'offset': 3, - 'bit': 6}, - '10G Base-LR': - {'offset': 3, - 'bit': 5}, - '10G Base-SR': - {'offset': 3, - 'bit': 4}}}, - 'InfinibandComplianceCode': - {'offset':3, - 'size':1, - 'type' : 'bitmap', - 'decode' : {'1X SX': - {'offset': 3, - 'bit': 3}, - '1X LX': - {'offset': 3, - 'bit': 2}, - '1X Copper Active': - {'offset': 3, - 'bit': 1}, - '1X Copper Passive': - {'offset': 3, - 'bit': 0}}}, - 'ESCONComplianceCodes': - {'offset':4, - 'size':1, - 'type' : 'bitmap', - 'decode' : {'ESCON MMF, 1310nm LED': - {'offset': 4, - 'bit': 7}, - 'ESCON SMF, 1310nm Laser': - {'offset': 4, - 'bit': 6}}}, - 'SONETComplianceCodes': - {'offset': 4, - 'size':2, - 'type' : 'bitmap', - 'decode' : { 'OC-192, short reach': - {'offset': 4, - 'bit': 5}, - 'SONET reach specifier bit 1': - {'offset': 4, - 'bit': 4}, - 'SONET reach specifier bit 2': - {'offset': 4, - 'bit': 3}, - 'OC-48, long reach': - {'offset': 4, - 'bit': 2}, - 'OC-48, intermediate reach': - {'offset': 4, - 'bit': 1}, - 'OC-48, short reach': - {'offset': 4, - 'bit': 0}, - 'OC-12, single mode, long reach': - {'offset': 5, - 'bit': 6}, - 'OC-12, single mode, inter reach': - {'offset': 5, - 'bit': 5}, - 'OC-12, short reach': - {'offset': 5, - 'bit': 4}, - 'OC-3, single mode, long reach': - {'offset': 5, - 'bit': 2}, - 'OC-3, single mode, inter reach': - {'offset': 5, - 'bit': 1}, - 'OC-3, short reach': - {'offset': 5, - 'bit': 0}}}, - 'EthernetComplianceCodes': - {'offset': 6, - 'size':2, - 'type' : 'bitmap', - 'decode' : { - 'BASE-PX': - {'offset': 6, - 'bit': 7}, - 'BASE-BX10': - {'offset': 6, - 'bit': 6}, - '100BASE-FX': - {'offset': 6, - 'bit': 5}, - '100BASE-LX/LX10': - {'offset': 6, - 'bit': 4}, - '1000BASE-T': - {'offset': 6, - 'bit': 3}, - '1000BASE-CX': - {'offset': 6, - 'bit': 2}, - '1000BASE-LX': - {'offset': 6, - 'bit': 1}, - '1000BASE-SX': - {'offset': 6, - 'bit': 0}}}, - 'FibreChannelLinkLength': - {'offset': 7, - 'size':2, - 'type' : 'bitmap', - 'decode' : - {'very long distance (V)': - {'offset': 7, - 'bit': 7}, - 'short distance (S)': - {'offset': 7, - 'bit': 6}, - 'Intermediate distance (I)': - {'offset': 7, - 'bit': 5}, - 'Long distance (L)': - {'offset': 7, - 'bit': 4}, - 'medium distance (M)': - {'offset': 7, - 'bit': 3}}}, - 'FibreChannelTechnology': - {'offset': 7, - 'size':2, - 'type' : 'bitmap', - 'decode' : - {'Shortwave laser, linear Rx (SA)': - {'offset': 7, - 'bit': 2}, - 'Longwave Laser (LC)': - {'offset': 7, - 'bit': 1}, - 'Electrical inter-enclosure (EL)': - {'offset': 7, - 'bit': 0}, - 'Electrical intra-enclosure (EL)': - {'offset': 8, - 'bit': 7}, - 'Shortwave laser w/o OFC (SN)': - {'offset': 8, - 'bit': 6}, - 'Shortwave laser with OFC (SL)': - {'offset': 8, - 'bit': 5}, - 'Longwave laser (LL)': - {'offset': 8, - 'bit': 4}}}, - 'SFP+CableTechnology': - {'offset': 7, - 'size':2, - 'type' : 'bitmap', - 'decode' : - {'Active Cable': - {'offset': 8, - 'bit': 3}, - 'Passive Cable': - {'offset': 8, - 'bit': 2}}}, - 'FibreChannelTransmissionMedia': - {'offset': 7, - 'size':2, - 'type' : 'bitmap', - 'decode' : - {'Twin Axial Pair (TW)': - {'offset': 9, - 'bit': 7}, - 'Twisted Pair (TP)': - {'offset': 9, - 'bit': 6}, - 'Miniature Coax (MI)': - {'offset': 9, - 'bit': 5}, - 'Video Coax (TV)': - {'offset': 9, - 'bit': 4}, - 'Multimode, 62.5um (M6)': - {'offset': 9, - 'bit': 3}, - 'Multimode, 50um (M5, M5E)': - {'offset': 9, - 'bit': 2}, - 'Single Mode (SM)': - {'offset': 9, - 'bit': 0}}}, - 'FibreChannelSpeed': - {'offset': 7, - 'size':2, - 'type': 'bitmap', - 'decode' : - {'1200 MBytes/sec': - {'offset': 10, - 'bit': 7}, - '800 MBytes/sec': - {'offset': 10, - 'bit': 6}, - '1600 MBytes/sec': - {'offset': 10, - 'bit': 5}, - '400 MBytes/sec': - {'offset': 10, - 'bit': 4}, - '200 MBytes/sec': - {'offset': 10, - 'bit': 2}, - '100 MBytes/sec': - {'offset': 10, - 'bit': 0}}}} - - exttypeoftransceiver = {'00': 'GBIC def not specified', - '01':'GBIC is compliant with MOD_DEF 1', - '02':'GBIC is compliant with MOD_DEF 2', - '03':'GBIC is compliant with MOD_DEF 3', - '04':'GBIC/SFP defined by twowire interface ID', - '05':'GBIC is compliant with MOD_DEF 5', - '06':'GBIC is compliant with MOD_DEF 6', - '07':'GBIC is compliant with MOD_DEF 7'} - - connector = {'00': 'Unknown', - '01': 'SC', - '02': 'Fibre Channel Style 1 copper connector', - '03': 'Fibre Channel Style 2 copper connector', - '04': 'BNC/TNC', - '05': 'Fibre Channel coaxial headers', - '06': 'FibreJack', - '07': 'LC', - '08': 'MT-RJ', - '09': 'MU', - '0a': 'SG', - '0b': 'Optical pigtail', - '0C': 'MPO Parallel Optic', - '20': 'HSSDCII', - '21': 'CopperPigtail', - '22': 'RJ45'} - - encoding_codes = {'00':'Unspecified', - '01':'8B/10B', - '02':'4B/5B', - '03':'NRZ', - '04':'Manchester', - '05': 'SONET Scrambled', - '06':'64B/66B'} - - rate_identifier = {'00':'Unspecified', - '01':'Defined for SFF-8079 (4/2/1G Rate_Select & AS0/AS1)', - '02': 'Defined for SFF-8431 (8/4/2G Rx Rate_Select only)', - '03':'Unspecified', - '04': 'Defined for SFF-8431 (8/4/2G Tx Rate_Select only)', - '05':'Unspecified', - '06':'Defined for SFF-8431 (8/4/2G Independent Rx & Tx Rate_select)', - '07':'Unspecified', - '08': 'Defined for FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G', - '09': 'Unspecified', - '0a': 'Defined for FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only, Low=8G/4G'} - - - interface_id = {'TypeOfTransceiver': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_of_transceiver}, - 'ExtIdentOfTypeOfTransceiver': - {'offset':1, - 'size':1, - 'type' : 'enum', - 'outlevel' : 2, - 'decode': exttypeoftransceiver}, - 'Connector': - {'offset':2, - 'size':1, - 'type' : 'enum', - 'decode': connector}, - 'EncodingCodes': - {'offset':11, - 'size':1, - 'type' : 'enum', - 'decode' : encoding_codes}, - 'VendorName': - {'offset' : 20, - 'size' : 16, - 'type' : 'str'}, - 'VendorOUI': - {'offset':37, - 'size':3, - 'type' : 'hex'}, - 'VendorPN': - {'offset':40, - 'size':16, - 'type' : 'str'}, - 'VendorSN': - {'offset':68, - 'size':16, - 'type' : 'str'}, - 'VendorRev': - {'offset':56, - 'size':4, - 'type' : 'str'}, - 'CalibrationType': - {'offset':92, - 'size':1, - 'type' : 'bitmap', - 'short_name' : 'calType', - 'decode' : {'Internally Calibrated': - {'offset': 92, - 'bit':5}, - 'Externally Calibrated': - {'offset': 92, - 'bit':4}, - }}, - 'ReceivedPowerMeasurementType': - {'offset':92, - 'size':1, - 'type' : 'bitmap', - 'decode' : {'Avg power': - {'offset': 92, - 'bit':3}, - 'OMA': - {'offset': 92, - 'bit':3, - 'value':0}}}, - 'RateIdentifier': - {'offset':13, - 'size':1, - 'type' : 'enum', - 'decode' : rate_identifier}, - 'TransceiverCodes': - {'offset' : 3, - 'type' : 'nested', - 'decode' : transceiver_codes}, - 'NominalSignallingRate(UnitsOf100Mbd)': - {'offset': 12, - 'size':1, - 'type':'int'}, - 'LengthSMFkm-UnitsOfKm': - {'offset':14, - 'size':1, - 'type':'int'}, - 'LengthSMF(UnitsOf100m)': - {'offset':15, - 'size':1, - 'type':'int'}, - 'Length50um(UnitsOf10m)': - {'offset':16, - 'size':1, - 'type':'int'}, - 'Length62.5um(UnitsOfm)': - {'offset':17, - 'size':1, - 'type':'int'}, - 'LengthCable(UnitsOfm)': - {'offset':18, - 'size':1, - 'type':'int'}, - 'LengthOM3(UnitsOf10m)': - {'offset':19, - 'size':1, - 'type':'int'}, - 'VendorDataCode(YYYY-MM-DD Lot)': - {'offset':84, - 'size':8, - 'type': 'date'}} - -# Parser for specific values that interested by SNMP - - sfp_info_bulk = {'type': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_of_transceiver}, - 'type_abbrv_name': - {'offset':0, - 'size':1, - 'type' : 'enum', - 'decode' : type_abbrv_name}, - 'Extended Identifier': - {'offset':1, - 'size':1, - 'type' : 'enum', - 'decode': exttypeoftransceiver}, - 'Connector': - {'offset':2, - 'size':1, - 'type' : 'enum', - 'decode': connector}, - 'Specification compliance': - {'offset' : 3, - 'type' : 'nested', - 'decode' : transceiver_codes}, - 'EncodingCodes': - {'offset':11, - 'size':1, - 'type' : 'enum', - 'decode' : encoding_codes}, - 'NominalSignallingRate(UnitsOf100Mbd)': - {'offset': 12, - 'size':1, - 'type':'int'}, - 'RateIdentifier': - {'offset':13, - 'size':1, - 'type' : 'enum', - 'decode' : rate_identifier}, - 'LengthSMFkm-UnitsOfKm': - {'offset':14, - 'size':1, - 'type':'int'}, - 'LengthSMF(UnitsOf100m)': - {'offset':15, - 'size':1, - 'type':'int'}, - 'Length50um(UnitsOf10m)': - {'offset':16, - 'size':1, - 'type':'int'}, - 'Length62.5um(UnitsOfm)': - {'offset':17, - 'size':1, - 'type':'int'}, - 'LengthCable(UnitsOfm)': - {'offset':18, - 'size':1, - 'type':'int'}, - 'LengthOM3(UnitsOf10m)': - {'offset':19, - 'size':1, - 'type':'int'} - } - - vendor_name = { - 'Vendor Name': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_pn = { - 'Vendor PN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_rev = { - 'Vendor Rev': - {'offset': 0, - 'size': 4, - 'type': 'str'} - } - - vendor_sn = { - 'Vendor SN': - {'offset': 0, - 'size': 16, - 'type': 'str'} - } - - vendor_oui = { - 'Vendor OUI': - {'offset':0, - 'size':3, - 'type' : 'hex'} - } - - vendor_date = { - 'VendorDataCode(YYYY-MM-DD Lot)': - {'offset':0, - 'size':8, - 'type': 'date'} - } - - # Returns calibration type - def _get_calibration_type(self, eeprom_data): - try: - data = int(eeprom_data[92], 16) - if self.test_bit(data, 5) != 0: - return 1 # internally calibrated - elif self.test_bit(data, 4) != 0: - return 2 # externally calibrated - else: - return 0 # Could not find calibration type - except: - return 0 - - def __init__(self, eeprom_raw_data=None): - self.interface_data = None - start_pos = 0 - - if eeprom_raw_data != None: - self.interface_data = sffbase.parse(self, - self.interface_id, - eeprom_raw_data, start_pos) - self.calibration_type = self._get_calibration_type( - eeprom_raw_data) - - def parse(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.interface_id, eeprom_raw_data, start_pos) - -#new parser functions for specific values that interested by SNMP - def parse_sfp_info_bulk(self, type_raw_data, start_pos): - return sffbase.parse(self, self.sfp_info_bulk, type_raw_data, start_pos) - - def parse_vendor_name(self, name_raw_data, start_pos): - return sffbase.parse(self, self.vendor_name, name_raw_data, start_pos) - - def parse_vendor_rev(self, rev_raw_data, start_pos): - return sffbase.parse(self, self.vendor_rev, rev_raw_data, start_pos) - - def parse_vendor_pn(self, pn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_pn, pn_raw_data, start_pos) - - def parse_vendor_sn(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_sn, sn_raw_data, start_pos) - - def parse_vendor_date(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_date, sn_raw_data, start_pos) - - def parse_vendor_oui(self, sn_raw_data, start_pos): - return sffbase.parse(self, self.vendor_oui, sn_raw_data, start_pos) - - def dump_pretty(self): - if self.interface_data == None: - print('Object not initialized, nothing to print') - return - sffbase.dump_pretty(self, self.interface_data) - - def get_calibration_type(self): - return self.calibration_type - - def get_data(self): - return self.interface_data - - def get_data_pretty(self): - return sffbase.get_data_pretty(self, self.interface_data) - -class sff8472Dom(sffbase): - """Parser and interpretor for Diagnostics data fields at address A2h""" - - version = '1.0' - - dom_ext_calibration_constants = {'RX_PWR_4': - {'offset':56, - 'size':4}, - 'RX_PWR_3': - {'offset':60, - 'size':4}, - 'RX_PWR_2': - {'offset':64, - 'size':4}, - 'RX_PWR_1': - {'offset':68, - 'size':4}, - 'RX_PWR_0': - {'offset':72, - 'size':4}, - 'TX_I_Slope': - {'offset':76, - 'size':2}, - 'TX_I_Offset': - {'offset':78, - 'size':2}, - 'TX_PWR_Slope': - {'offset':80, - 'size':2}, - 'TX_PWR_Offset': - {'offset':82, - 'size':2}, - 'T_Slope': - {'offset':84, - 'size':2}, - 'T_Offset': - {'offset':86, - 'size':2}, - 'V_Slope': - {'offset':88, - 'size':2}, - 'V_Offset': - {'offset':90, - 'size':2}} - - - def get_calibration_type(self): - return self._calibration_type - - def calc_temperature(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - - result = (msb << 8) | (lsb & 0xff) - result = self.twos_comp(result, 16) - - if cal_type == 1: - - # Internal calibration - - result = float(result / 256.0) - retval = '%.4f' %result + 'C' - elif cal_type == 2: - - # External calibration - - # T(C) = T_Slope * T_AD + T_Offset - off = self.dom_ext_calibration_constants['T_Slope']['offset'] - msb_t = int(eeprom_data[off], 16) - lsb_t = int(eeprom_data[off + 1], 16) - t_slope = (msb_t << 8) | (lsb_t & 0xff) - - off = self.dom_ext_calibration_constants['T_Offset']['offset'] - msb_t = int(eeprom_data[off], 16) - lsb_t = int(eeprom_data[off + 1], 16) - t_offset = (msb_t << 8) | (lsb_t & 0xff) - t_offset = self.twos_comp(t_offset, 16) - - result = t_slope * result + t_offset - result = float(result / 256.0) - retval = '%.4f' %result + 'C' - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_voltage(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - # Internal Calibration - - result = float(result * 0.0001) - #print(indent, name, ' : %.4f' %result, 'Volts') - retval = '%.4f' %result + 'Volts' - elif cal_type == 2: - - # External Calibration - - # V(uV) = V_Slope * VAD + V_Offset - off = self.dom_ext_calibration_constants['V_Slope']['offset'] - msb_v = int(eeprom_data[off], 16) - lsb_v = int(eeprom_data[off + 1], 16) - v_slope = (msb_v << 8) | (lsb_v & 0xff) - - off = self.dom_ext_calibration_constants['V_Offset']['offset'] - msb_v = int(eeprom_data[off], 16) - lsb_v = int(eeprom_data[off + 1], 16) - v_offset = (msb_v << 8) | (lsb_v & 0xff) - v_offset = self.twos_comp(v_offset, 16) - - result = v_slope * result + v_offset - result = float(result * 0.0001) - #print(indent, name, ' : %.4f' %result, 'Volts') - retval = '%.4f' %result + 'Volts' - else: - #print(indent, name, ' : Unknown') - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_bias(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - # Internal Calibration - - result = float(result * 0.002) - #print(indent, name, ' : %.4f' %result, 'mA') - retval = '%.4f' %result + 'mA' - - elif cal_type == 2: - # External Calibration - - # I(uA) = I_Slope * I_AD + I_Offset - off = self.dom_ext_calibration_constants['I_Slope']['offset'] - msb_i = int(eeprom_data[off], 16) - lsb_i = int(eeprom_data[off + 1], 16) - i_slope = (msb_i << 8) | (lsb_i & 0xff) - - off = self.dom_ext_calibration_constants['I_Offset']['offset'] - msb_i = int(eeprom_data[off], 16) - lsb_i = int(eeprom_data[off + 1], 16) - i_offset = (msb_i << 8) | (lsb_i & 0xff) - i_offset = self.twos_comp(i_offset, 16) - - result = i_slope * result + i_offset - result = float(result * 0.002) - #print(indent, name, ' : %.4f' %result, 'mA') - retval = '%.4f' %result + 'mA' - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - def calc_tx_power(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - result = float(result * 0.0001) - #print(indent, name, ' : ', power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - - elif cal_type == 2: - - # TX_PWR(uW) = TX_PWR_Slope * TX_PWR_AD + TX_PWR_Offset - off = self.dom_ext_calibration_constants['TX_PWR_Slope']['offset'] - msb_tx_pwr = int(eeprom_data[off], 16) - lsb_tx_pwr = int(eeprom_data[off + 1], 16) - tx_pwr_slope = (msb_tx_pwr << 8) | (lsb_tx_pwr & 0xff) - - off = self.dom_ext_calibration_constants['TX_PWR_Offset']['offset'] - msb_tx_pwr = int(eeprom_data[off], 16) - lsb_tx_pwr = int(eeprom_data[off + 1], 16) - tx_pwr_offset = (msb_tx_pwr << 8) | (lsb_tx_pwr & 0xff) - tx_pwr_offset = self.twos_comp(tx_pwr_offset, 16) - - result = tx_pwr_slope * result + tx_pwr_offset - result = float(result * 0.0001) - retval = self.power_in_dbm_str(result) - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - def calc_rx_power(self, eeprom_data, offset, size): - try: - cal_type = self.get_calibration_type() - - msb = int(eeprom_data[offset], 16) - lsb = int(eeprom_data[offset + 1], 16) - result = (msb << 8) | (lsb & 0xff) - - if cal_type == 1: - - # Internal Calibration - result = float(result * 0.0001) - #print(indent, name, " : ", power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - - elif cal_type == 2: - - # External Calibration - - # RX_PWR(uW) = RX_PWR_4 * RX_PWR_AD + - # RX_PWR_3 * RX_PWR_AD + - # RX_PWR_2 * RX_PWR_AD + - # RX_PWR_1 * RX_PWR_AD + - # RX_PWR(0) - off = self.dom_ext_calibration_constants['RX_PWR_4']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_4 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_3']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_3 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_2']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_2 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_1']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_1 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - off = self.dom_ext_calibration_constants['RX_PWR_0']['offset'] - rx_pwr_byte3 = int(eeprom_data[off], 16) - rx_pwr_byte2 = int(eeprom_data[off + 1], 16) - rx_pwr_byte1 = int(eeprom_data[off + 2], 16) - rx_pwr_byte0 = int(eeprom_data[off + 3], 16) - rx_pwr_0 = (rx_pwr_byte3 << 24) | (rx_pwr_byte2 << 16) | (rx_pwr_byte1 << 8) | (rx_pwr_byte0 & 0xff) - - rx_pwr = (rx_pwr_4 * result) + (rx_pwr_3 * result) + (rx_pwr_2 * result) + (rx_pwr_1 * result) + rx_pwr_0 - - result = float(result * 0.0001) - #print(indent, name, " : ", power_in_dbm_str(result)) - retval = self.power_in_dbm_str(result) - else: - retval = 'Unknown' - except Exception as err: - retval = str(err) - - return retval - - - dom_aw_thresholds = { 'TempHighAlarm': - {'offset':0, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempLowAlarm': - {'offset':2, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempHighWarning': - {'offset':4, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'TempLowWarning': - {'offset':6, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'VoltageHighAlarm': - {'offset':8, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VoltageLowAlarm': - {'offset':10, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VoltageHighWarning': - {'offset':12, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'VoltageLowWarning': - {'offset':14, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'BiasHighAlarm': - {'offset':16, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'BiasLowAlarm': - {'offset':18, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'BiasHighWarning': - {'offset':20, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'BiasLowWarning': - {'offset':22, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TXPowerHighAlarm': - {'offset':24, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_tx_power}}, - 'TXPowerLowAlarm': - {'offset':26, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_tx_power}}, - 'TXPowerHighWarning': - {'offset':28, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_tx_power}}, - 'TXPowerLowWarning': - {'offset':30, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_tx_power}}, - 'RXPowerHighAlarm': - {'offset':32, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RXPowerLowAlarm': - {'offset':34, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RXPowerHighWarning': - {'offset':36, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}, - 'RXPowerLowWarning': - {'offset':38, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}} - - dom_monitor = {'Temperature': - {'offset':96, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_temperature}}, - 'Vcc': - {'offset':98, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_voltage}}, - 'TXBias': - {'offset':100, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_bias}}, - 'TXPower': - {'offset':102, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_tx_power}}, - 'RXPower': - {'offset':104, - 'size':2, - 'type': 'func', - 'decode': { 'func':calc_rx_power}}} - - dom_status_control = { 'TXDisableState': - {'offset': 110, - 'bit': 7, - 'type': 'bitvalue'}, - 'SoftTXDisableSelect': - {'offset': 110, - 'bit': 6, - 'type': 'bitvalue'}, - 'RS1State': - {'offset': 110, - 'bit': 5, - 'type': 'bitvalue'}, - 'RateSelectState': - {'offset': 110, - 'bit': 4, - 'type': 'bitvalue'}, - 'SoftRateSelect': - {'offset': 110, - 'bit': 3, - 'type': 'bitvalue'}, - 'TXFaultState': - {'offset': 110, - 'bit': 2, - 'type': 'bitvalue'}, - 'RXLOSState': - {'offset': 110, - 'bit': 1, - 'type': 'bitvalue'}, - 'DataReadyBarState': - {'offset': 110, - 'bit': 0, - 'type': 'bitvalue'}} - - dom_alarm_flags = {'TempHighAlarm': - {'offset':112, - 'bit':7, - 'type': 'bitvalue'}, - 'TempLowAlarm': - {'offset':112, - 'bit':6, - 'type': 'bitvalue'}, - 'VccHighAlarm': - {'offset':112, - 'bit':5, - 'type': 'bitvalue'}, - 'VccLowAlarm': - {'offset':112, - 'bit':4, - 'type': 'bitvalue'}, - 'TXBiasHighAlarm': - {'offset':112, - 'bit':3, - 'type': 'bitvalue'}, - 'TXBiasLowAlarm': - {'offset':112, - 'bit':2, - 'type': 'bitvalue'}, - 'TXPowerHighAlarm': - {'offset':112, - 'bit':1, - 'type': 'bitvalue'}, - 'TXPowerLowAlarm': - {'offset':112, - 'bit':0, - 'type': 'bitvalue'}, - 'RXPowerHighAlarm': - {'offset':113, - 'bit':7, - 'type': 'bitvalue'}, - 'RXPowerLowAlarm': - {'offset':113, - 'bit':6, - 'type': 'bitvalue'}} - - dom_warning_flags = { 'TempHighWarning': - {'offset':116, - 'bit':7, - 'type': 'bitvalue'}, - 'TempLowWarning': - {'offset':116, - 'bit':6, - 'type': 'bitvalue'}, - 'VccHighWarning': - {'offset':116, - 'bit':5, - 'type': 'bitvalue'}, - 'VccLowWarning': - {'offset':116, - 'bit':4, - 'type': 'bitvalue'}, - 'TXBiasHighWarning': - {'offset':116, - 'bit':3, - 'type': 'bitvalue'}, - 'TXBiasLowWarning': - {'offset':116, - 'bit':2, - 'type': 'bitvalue'}, - 'TXPowerHighWarning': - {'offset':116, - 'bit':1, - 'type': 'bitvalue'}, - 'TXPowerLowWarning': - {'offset':116, - 'bit':0, - 'type': 'bitvalue'}, - 'RXPowerHighWarning': - {'offset':117, - 'bit':7, - 'type': 'bitvalue'}, - 'RXPowerLowWarning': - {'offset':117, - 'bit':6, - 'type': 'bitvalue'}} - - dom_map = {'AwThresholds': - {'offset' : 0, - 'size' : 40, - 'type' : 'nested', - 'decode' : dom_aw_thresholds}, - 'MonitorData': - {'offset':96, - 'size':10, - 'type' : 'nested', - 'decode': dom_monitor}, - 'StatusControl': - {'offset':110, - 'size':1, - 'type' : 'nested', - 'decode':dom_status_control}, - 'AlarmFlagStatus': - {'offset':112, - 'size':2, - 'type' : 'nested', - 'decode':dom_alarm_flags}, - 'WarningFlagStatus': - {'offset':112, - 'size':2, - 'type' : 'nested', - 'decode':dom_warning_flags}} - -# parsers for specific values that interested by SNMP - dom_module_temperature = { - 'Temperature': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_temperature}} - } - - dom_module_voltage = { - 'Vcc': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func':calc_voltage}} - } - - dom_channel_monitor_params = { - 'TXBias': - {'offset': 0, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_bias}}, - 'TXPower': - {'offset': 2, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_tx_power}}, - 'RXPower': - {'offset': 4, - 'size': 2, - 'type': 'func', - 'decode': {'func': calc_rx_power}} - } - - def __init__(self, eeprom_raw_data=None, calibration_type=0): - self._calibration_type = calibration_type - start_pos = 0 - - if eeprom_raw_data != None: - self.dom_data = sffbase.parse(self, self.dom_map, - eeprom_raw_data, start_pos) - - def parse(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_map, eeprom_raw_data, start_pos) - -# parser functions for specific values interested by SNMP - def parse_temperature(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_temperature, eeprom_raw_data, - start_pos) - - def parse_voltage(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_module_voltage, eeprom_raw_data, - start_pos) - - def parse_channel_monitor_params(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_channel_monitor_params, eeprom_raw_data, - start_pos) - - def parse_alarm_warning_threshold(self, eeprom_raw_data, start_pos): - return sffbase.parse(self, self.dom_aw_thresholds, eeprom_raw_data, - start_pos) - - def dump_pretty(self): - if self.dom_data == None: - print('Object not initialized, nothing to print') - return - sffbase.dump_pretty(self, self.dom_data) - - - def get_data(self): - return self.dom_data - - - def get_data_pretty(self): - return sffbase.get_data_pretty(self, self.dom_data) diff --git a/sonic_sfp/sffbase.py b/sonic_sfp/sffbase.py deleted file mode 100644 index 6d944b6f154b..000000000000 --- a/sonic_sfp/sffbase.py +++ /dev/null @@ -1,251 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# sffbase class for sff8436 and sff8472 -#---------------------------------------------------------------------------- - -from __future__ import print_function - -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 -except ImportError as e: - raise ImportError (str(e) + "- required module not found") - -class sffbase(object): - """Class to parse and interpret sff8436 and sff8472 spec for - diagnostically monitoring interfaces of optical transceivers""" - - _indent = '\t' - - def inc_indent(self): - self._indent += '\t' - - def dec_indent(self): - self._indent = self._indent[:-1] - - # Convert Hex to String - def convert_hex_to_string(self, arr, start, end): - try: - ret_str = '' - for n in range(start, end): - ret_str += arr[n] - return str.strip(binascii.unhexlify(ret_str)) - except Exception as err: - return str(err) - - # Convert Date to String - def convert_date_to_string(self, eeprom_data, offset, size): - try: - year_offset = 0 - month_offset = 2 - day_offset = 4 - lot_offset = 6 - - date = self.convert_hex_to_string(eeprom_data, offset, offset + size) - retval = "20"+ date[year_offset:month_offset] + "-" + \ - date[month_offset:day_offset] + "-" + \ - date[day_offset:lot_offset] + " " + \ - date[lot_offset:size] - except Exception as err: - retval = str(err) - return retval - - def test_bit(self, n, bitpos): - try: - mask = 1 << bitpos - if (n & mask) == 0: - return 0 - else: - return 1 - except: - return -1 - - def twos_comp(self, num, bits): - try: - if ((num & (1 << (bits - 1))) != 0): - num = num - (1 << bits) - return num - except: - return 0 - - def mw_to_dbm(self, mW): - if mW == 0: - return float("-inf") - elif mW < 0: - return float("NaN") - return 10. * log10(mW) - - - def power_in_dbm_str(self, mW): - return "%.4f%s" % (self.mw_to_dbm(mW), "dBm") - - # Parse sff base elements - def parse_sff_element(self, eeprom_data, eeprom_ele, start_pos): - value = None - offset = eeprom_ele.get('offset') + start_pos - size = eeprom_ele.get('size') - type = eeprom_ele.get('type') - decode = eeprom_ele.get('decode'); - - if type == 'enum': - # Get the matched value - value = decode.get(str(eeprom_data[offset]), 'Unknown') - - elif type == 'bitmap': - # Get the 'on' bitname - bitvalue_dict = {} - for bitname, bitinfo in sorted(decode.iteritems()): - bitinfo_offset = bitinfo.get('offset') + start_pos - bitinfo_pos = bitinfo.get('bit') - bitinfo_value = bitinfo.get('value') - data = int(eeprom_data[bitinfo_offset], 16) - bit_value = self.test_bit(data, bitinfo_pos) - if bitinfo_value != None: - if bit_value == bitinfo_value: - value = bitname - break - elif bit_value == 1: - value = bitname - break - - elif type == 'bitvalue': - # Get the value of the bit - bitpos = eeprom_ele.get('bit') - data = int(eeprom_data[offset], 16) - bitval = self.test_bit(data, bitpos) - value = ['Off', 'On'][bitval] - - elif type == 'func': - # Call the decode func to get the value - value = decode['func'](self, eeprom_data, - offset, size) - - elif type == 'str': - value = self.convert_hex_to_string(eeprom_data, offset, - offset + size) - - elif type == 'int': - data = int(eeprom_data[offset], 16) - if data != 0: - value = data - - elif type == 'date': - value = self.convert_date_to_string(eeprom_data, offset, - size) - - elif type == 'hex': - value = '-'.join(eeprom_data[offset:offset+size]) - - return value - - # Recursively parses sff data into dictionary - def parse_sff(self, eeprom_map, eeprom_data, start_pos): - outdict = {} - for name, meta_data in sorted(eeprom_map.iteritems()): - type = meta_data.get('type') - - # Initialize output value - value_dict = {} - value_dict['outtype'] = meta_data.get('outtype') - value_dict['short_name'] = meta_data.get('short_name') - - if type != 'nested': - data = self.parse_sff_element(eeprom_data, - meta_data, start_pos) - else: - nested_map = meta_data.get('decode') - data = self.parse_sff(nested_map, - eeprom_data, start_pos) - - if data != None: - value_dict['value'] = data - outdict[name] = value_dict - - return outdict - - - # Main sff parser function - def parse(self, eeprom_map, eeprom_data, start_pos): - """ Example Return format: - {'version': '1.0', 'data': {'Length50um(UnitsOf10m)': - {'outtype': None, 'value': 8, 'short_name': None}, - 'TransceiverCodes': {'outtype': None, 'value': - {'10GEthernetComplianceCode': {'outtype': None, 'value': - '10G Base-SR', 'short_name': None}}, 'short_name': None}, - 'ExtIdentOfTypeOfTransceiver': {'outtype': None, 'value': - 'GBIC/SFP func defined by two-wire interface ID', 'short_name': - None}, 'Length62.5um(UnitsOfm)': {'outtype': None,""" - - outdict = {} - return_dict = {} - - outdict = self.parse_sff(eeprom_map, eeprom_data, start_pos) - - return_dict['version'] = self.version - return_dict['data'] = outdict - - return return_dict - - - # Returns sff parsed data in a pretty dictionary format - def get_data_pretty_dict(self, indict): - outdict = {} - - for elem, elem_val in sorted(indict.iteritems()): - value = elem_val.get('value') - if type(value) == types.DictType: - outdict[elem] = sffbase.get_data_pretty_dict( - self, value) - else: - outdict[elem] = value - - return outdict - - def get_data_pretty(self, indata): - """Example Return format: - {'version': '1.0', 'data': {'Length50um(UnitsOf10m)': 8, - 'TransceiverCodes': {'10GEthernetComplianceCode': - '10G Base-SR'}, 'ExtIdentOfTypeOfTransceiver': 'GBIC/SFP func - defined by two-wire interface ID', 'Length62.5um(UnitsOfm)': 3, - 'VendorPN': 'FTLX8571D3BNL', 'RateIdentifier': 'Unspecified', - 'NominalSignallingRate(UnitsOf100Mbd)': 103, 'VendorOUI': ..}} - {'version': '1.0', 'data': {'AwThresholds': - {'TXPowerLowWarning': '-5.0004 dBm', 'TempHighWarning': - '88.0000C', 'RXPowerHighAlarm': '0.0000 dBm', - 'TXPowerHighAlarm': '-0.7998 dBm', 'RXPowerLowAlarm': - '-20.0000 dBm', 'RXPowerHighWarning': '-1.0002 dBm', - 'VoltageLowAlarm': '2.9000Volts'""" - - return_dict = {} - - return_dict['version'] = indata.get('version') - return_dict['data'] = self.get_data_pretty_dict(indata.get( - 'data')) - return return_dict - - # Dumps dict in pretty format - def dump_pretty(self, indict): - for elem, elem_val in sorted(indict.iteritems()): - if type(elem_val) == types.DictType: - print(self._indent, elem, ': ') - self.inc_indent() - sff8472.dump_pretty(self, elem_val) - self.dec_indent() - elif type(elem_val) == types.ListType: - if len(elem_val) == 1: - print(self._indent, elem, ': ', elem_val.pop()) - else: - print(self._indent, elem, ': ') - self.inc_indent() - for e in elem_val: - print(self._indent, e) - self.dec_indent() - else: - print(self._indent, elem, ': ', elem_val) diff --git a/sonic_sfp/sfputilbase.py b/sonic_sfp/sfputilbase.py deleted file mode 100644 index 1a37528ca10d..000000000000 --- a/sonic_sfp/sfputilbase.py +++ /dev/null @@ -1,1268 +0,0 @@ -# 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 - from . import bcmshell # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from sonic_eeprom import eeprom_dts - from .sff8472 import sff8472InterfaceId # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8472 import sff8472Dom # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8436 import sff8436InterfaceId # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .sff8436 import sff8436Dom # Dot module supports both Python 2 and Python 3 using explicit relative import methods - from .inf8628 import inf8628InterfaceId # Dot module supports both Python 2 and Python 3 using explicit relative import methods -except ImportError as e: - raise ImportError("%s - required module not found" % str(e)) - -# definitions of the offset and width for values in XCVR info eeprom -XCVR_INTFACE_BULK_OFFSET = 0 -XCVR_INTFACE_BULK_WIDTH_QSFP = 20 -XCVR_INTFACE_BULK_WIDTH_SFP = 21 -XCVR_TYPE_OFFSET = 0 -XCVR_TYPE_WIDTH = 1 -XCVR_EXT_TYPE_OFFSET = 1 -XCVR_EXT_TYPE_WIDTH = 1 -XCVR_CONNECTOR_OFFSET = 2 -XCVR_CONNECTOR_WIDTH = 1 -XCVR_COMPLIANCE_CODE_OFFSET = 3 -XCVR_COMPLIANCE_CODE_WIDTH = 8 -XCVR_ENCODING_OFFSET = 11 -XCVR_ENCODING_WIDTH = 1 -XCVR_NBR_OFFSET = 12 -XCVR_NBR_WIDTH = 1 -XCVR_EXT_RATE_SEL_OFFSET = 13 -XCVR_EXT_RATE_SEL_WIDTH = 1 -XCVR_CABLE_LENGTH_OFFSET = 14 -XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 -XCVR_CABLE_LENGTH_WIDTH_SFP = 6 -XCVR_VENDOR_NAME_OFFSET = 20 -XCVR_VENDOR_NAME_WIDTH = 16 -XCVR_VENDOR_OUI_OFFSET = 37 -XCVR_VENDOR_OUI_WIDTH = 3 -XCVR_VENDOR_PN_OFFSET = 40 -XCVR_VENDOR_PN_WIDTH = 16 -XCVR_HW_REV_OFFSET = 56 -XCVR_HW_REV_WIDTH_OSFP = 2 -XCVR_HW_REV_WIDTH_QSFP = 2 -XCVR_HW_REV_WIDTH_SFP = 4 -XCVR_VENDOR_SN_OFFSET = 68 -XCVR_VENDOR_SN_WIDTH = 16 -XCVR_VENDOR_DATE_OFFSET = 84 -XCVR_VENDOR_DATE_WIDTH = 8 -XCVR_DOM_CAPABILITY_OFFSET = 92 -XCVR_DOM_CAPABILITY_WIDTH = 1 - -# definitions of the offset for values in OSFP info eeprom -OSFP_TYPE_OFFSET = 0 -OSFP_VENDOR_NAME_OFFSET = 129 -OSFP_VENDOR_PN_OFFSET = 148 -OSFP_HW_REV_OFFSET = 164 -OSFP_VENDOR_SN_OFFSET = 166 - -#definitions of the offset and width for values in DOM info eeprom -QSFP_DOM_REV_OFFSET = 1 -QSFP_DOM_REV_WIDTH = 1 -QSFP_TEMPE_OFFSET = 22 -QSFP_TEMPE_WIDTH = 2 -QSFP_VOLT_OFFSET = 26 -QSFP_VOLT_WIDTH = 2 -QSFP_CHANNL_MON_OFFSET = 34 -QSFP_CHANNL_MON_WIDTH = 16 -QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 -QSFP_MODULE_THRESHOLD_OFFSET = 128 -QSFP_MODULE_THRESHOLD_WIDTH = 24 -QSFP_CHANNL_THRESHOLD_OFFSET = 176 -QSFP_CHANNL_THRESHOLD_WIDTH = 16 -QSFP_CHANNL_MON_MASK_OFFSET = 242 -QSFP_CHANNL_MON_MASK_WIDTH = 4 - -SFP_TEMPE_OFFSET = 96 -SFP_TEMPE_WIDTH = 2 -SFP_VOLT_OFFSET = 98 -SFP_VOLT_WIDTH = 2 -SFP_CHANNL_MON_OFFSET = 100 -SFP_CHANNL_MON_WIDTH = 6 - -qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', - 'Length OM2(m)', 'Length OM1(m)', - 'Length Cable Assembly(m)') - -sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', - 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', - 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') - -sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', - 'ESCONComplianceCodes', 'SONETComplianceCodes', - 'EthernetComplianceCodes','FibreChannelLinkLength', - 'FibreChannelTechnology', 'SFP+CableTechnology', - 'FibreChannelTransmissionMedia','FibreChannelSpeed') - -qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', - 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', - 'Fibre Channel link length/Transmitter Technology', - 'Fibre Channel transmission media', 'Fibre Channel Speed') - -class SfpUtilError(Exception): - """Base class for exceptions in this module.""" - pass - - -class DeviceTreeError(SfpUtilError): - """Exception raised when unable to find SFP device attributes in the device tree.""" - def __init__(self, value): - self.value = value - - def __str__(self): - return repr(self.value) - - -class SfpUtilBase(object): - """ Abstract base class for SFP utility. This class - provides base EEPROM read attributes and methods common - to most platforms.""" - - __metaclass__ = abc.ABCMeta - - IDENTITY_EEPROM_ADDR = 0x50 - DOM_EEPROM_ADDR = 0x51 - SFP_DEVICE_TYPE = "24c02" - - # 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_bcm = {} - logical_to_physical = {} - - """ - phytab_mappings stores mapping between logical, physical and bcm ports - from /var/lib/cumulus/phytab - For a normal non-ganged port: - "swp8": {"bcmport": "xe4", "physicalport": [8], "phyid": ["0xb"]} - - For a ganged 40G/4 port: - "swp1": {"bcmport": "xe0", "physicalport": [1, 2, 3, 4], "phyid": ["0x4", "0x5", "0x6", "0x7"]} - - For ganged 4x10G port: - "swp52s0": {"bcmport": "xe51", "physicalport": [52], "phyid": ["0x48"]}, - "swp52s1": {"bcmport": "xe52", "physicalport": [52], "phyid": ["0x49"]}, - "swp52s2": {"bcmport": "xe53", "physicalport": [52], "phyid": ["0x4a"]}, - "swp52s3": {"bcmport": "xe54", "physicalport": [52], "phyid": ["0x4b"]}, - """ - phytab_mappings = {} - - physical_to_logical = {} - physical_to_phyaddrs = {} - - port_to_i2cbus_mapping = None - - @abc.abstractproperty - def port_start(self): - """ Starting index of physical port range """ - pass - - @abc.abstractproperty - def port_end(self): - """ Ending index of physical port range """ - pass - - @abc.abstractproperty - def qsfp_ports(self): - """ QSFP Ports """ - pass - - @property - def osfp_ports(self): - """ OSFP/QSFP-DD Ports """ - return [] - - @abc.abstractproperty - def port_to_eeprom_mapping(self): - """ Dictionary where key = physical port index (integer), - value = path to SFP EEPROM device file (string) """ - pass - - def __init__(self): - pass - - def _get_bcm_port(self, port_num): - bcm_port = None - - logical_port = self.physical_to_logical.get(port_num) - if logical_port is not None and len(logical_port) > 0: - bcm_port = self.logical_to_bcm.get(logical_port[0]) - - if bcm_port is None: - bcm_port = "xe%d" % (port_num - 1) - - return bcm_port - - def _get_port_i2c_adapter_id(self, port_num): - if len(self.port_to_i2cbus_mapping) == 0: - return -1 - - return self.port_to_i2cbus_mapping.get(port_num, -1) - - # Adds new sfp device on i2c adapter/bus via i2c bus new_device - # sysfs attribute - def _add_new_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr): - try: - sysfs_nd_path = "%s/new_device" % sysfs_sfp_i2c_adapter_path - - # Write device address to new_device file - nd_file = open(sysfs_nd_path, "w") - nd_str = "%s %s" % (self.SFP_DEVICE_TYPE, hex(devaddr)) - nd_file.write(nd_str) - nd_file.close() - - except Exception as err: - print("Error writing to new device file: %s" % str(err)) - return 1 - else: - return 0 - - # Deletes sfp device on i2c adapter/bus via i2c bus delete_device - # sysfs attribute - def _delete_sfp_device(self, sysfs_sfp_i2c_adapter_path, devaddr): - try: - sysfs_nd_path = "%s/delete_device" % sysfs_sfp_i2c_adapter_path - - # Write device address to delete_device file - nd_file = open(sysfs_nd_path, "w") - nd_file.write(devaddr) - nd_file.close() - except Exception as err: - print("Error writing to new device file: %s" % str(err)) - return 1 - else: - return 0 - - # Returns 1 if SFP EEPROM found. Returns 0 otherwise - def _sfp_eeprom_present(self, sysfs_sfp_i2c_client_eeprompath, offset): - """Tries to read the eeprom file to determine if the - device/sfp is present or not. If sfp present, the read returns - valid bytes. If not, read returns error 'Connection timed out""" - - if not os.path.exists(sysfs_sfp_i2c_client_eeprompath): - return False - else: - try: - with open(sysfs_sfp_i2c_client_eeprompath, mode="rb", buffering=0) as sysfsfile: - sysfsfile.seek(offset) - sysfsfile.read(1) - except IOError: - return False - except: - return False - else: - return True - - def _get_port_eeprom_path(self, port_num, devid): - sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" - - if port_num in self.port_to_eeprom_mapping.keys(): - sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[port_num] - else: - sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" - - i2c_adapter_id = self._get_port_i2c_adapter_id(port_num) - if i2c_adapter_id is None: - print("Error getting i2c bus num") - return None - - # Get i2c virtual bus path for the sfp - sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path, - str(i2c_adapter_id)) - - # If i2c bus for port does not exist - if not os.path.exists(sysfs_sfp_i2c_adapter_path): - print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path) - return None - - sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path, - str(i2c_adapter_id), - hex(devid)[-2:]) - - # If sfp device is not present on bus, Add it - if not os.path.exists(sysfs_sfp_i2c_client_path): - ret = self._add_new_sfp_device( - sysfs_sfp_i2c_adapter_path, devid) - if ret != 0: - print("Error adding sfp device") - return None - - sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path - - return sysfs_sfp_i2c_client_eeprom_path - - # Read out any bytes from any offset - def _read_eeprom_specific_bytes(self, sysfsfile_eeprom, offset, num_bytes): - eeprom_raw = [] - for i in range(0, num_bytes): - eeprom_raw.append("0x00") - - try: - sysfsfile_eeprom.seek(offset) - raw = sysfsfile_eeprom.read(num_bytes) - except IOError: - print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path) - return None - - try: - for n in range(0, num_bytes): - eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) - except: - return None - - return eeprom_raw - - # Read eeprom - def _read_eeprom_devid(self, port_num, devid, offset, num_bytes = 256): - sysfs_sfp_i2c_client_eeprom_path = self._get_port_eeprom_path(port_num, devid) - - if not self._sfp_eeprom_present(sysfs_sfp_i2c_client_eeprom_path, offset): - return None - - try: - sysfsfile_eeprom = open(sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % sysfs_sfp_i2c_client_eeprom_path) - return None - - eeprom_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, offset, num_bytes) - - try: - sysfsfile_eeprom.close() - except: - return None - - return eeprom_raw - - def _is_valid_port(self, port_num): - if port_num >= self.port_start and port_num <= self.port_end: - return True - - return False - - def read_porttab_mappings(self, porttabfile): - logical = [] - logical_to_bcm = {} - 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_bcm[portname] = "xe" + bcm_port - 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_bcm = logical_to_bcm - self.logical_to_physical = logical_to_physical - self.physical_to_logical = 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_phytab_mappings(self, phytabfile): - logical = [] - phytab_mappings = {} - physical_to_logical = {} - physical_to_phyaddrs = {} - - try: - f = open(phytabfile) - except: - raise - - # Read the phytab file and generate dicts - # with mapping for future reference. - # XXX: move the phytabfile - # parsing stuff to a separate module, or reuse - # if something already exists - for line in f: - line = line.strip() - line = re.sub(r"\s+", " ", line) - if len(line) < 4: - continue - if re.search("^#", line) is not None: - continue - (phy_addr, logical_port, bcm_port, type) = line.split(" ", 3) - - if re.match("xe", bcm_port) is None: - continue - - lport = re.findall("swp(\d+)s*(\d*)", logical_port) - if lport is not None: - lport_tuple = lport.pop() - physical_port = int(lport_tuple[0]) - else: - physical_port = logical_port.split("swp").pop() - physical_port = int(physical_port.split("s").pop(0)) - - # Some platforms have a list of physical sfp ports - # defined. If such a list exists, check to see if this - # port is blacklisted - if ((len(self.sfp_ports) > 0) and (physical_port not in self.sfp_ports)): - continue - - if logical_port not in logical: - logical.append(logical_port) - - if phytab_mappings.get(logical_port) is None: - phytab_mappings[logical_port] = {} - phytab_mappings[logical_port]['physicalport'] = [] - phytab_mappings[logical_port]['phyid'] = [] - phytab_mappings[logical_port]['type'] = type - - # If the port is 40G/4 ganged, there will be multiple - # physical ports corresponding to the logical port. - # Generate the next physical port number in the series - # and append it to the list - tmp_physical_port_list = phytab_mappings[logical_port]['physicalport'] - if (type == "40G/4" and physical_port in tmp_physical_port_list): - # Aha!...ganged port - new_physical_port = tmp_physical_port_list[-1] + 1 - else: - new_physical_port = physical_port - - if (new_physical_port not in phytab_mappings[logical_port]['physicalport']): - phytab_mappings[logical_port]['physicalport'].append(new_physical_port) - phytab_mappings[logical_port]['phyid'].append(phy_addr) - phytab_mappings[logical_port]['bcmport'] = bcm_port - - # Store in physical_to_logical dict - if physical_to_logical.get(new_physical_port) is None: - physical_to_logical[new_physical_port] = [] - physical_to_logical[new_physical_port].append(logical_port) - - # Store in physical_to_phyaddrs dict - if physical_to_phyaddrs.get(new_physical_port) is None: - physical_to_phyaddrs[new_physical_port] = [] - physical_to_phyaddrs[new_physical_port].append(phy_addr) - - self.logical = logical - self.phytab_mappings = phytab_mappings - self.physical_to_logical = physical_to_logical - self.physical_to_phyaddrs = physical_to_phyaddrs - - """ - pp = pprint.PrettyPrinter(indent=4) - pp.pprint(self.phytab_mappings) - - print("logical: " + self.logical) - print("logical to bcm: " + self.logical_to_bcm) - print("phytab mappings: " + self.phytab_mappings) - print("physical to logical: " + self.physical_to_logical) - print("physical to phyaddrs: " + self.physical_to_phyaddrs) - """ - - def get_physical_to_logical(self, port_num): - """Returns list of logical ports for the given physical port""" - - return self.physical_to_logical.get(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 - - 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: - return 1 - else: - return 0 - - def is_physical_port_ganged_40_by_4(self, port_num): - logical_port = self.get_physical_to_logical(port_num) - if logical_port is not None: - return self.is_logical_port_ganged_40_by_4(logical_port[0]) - - return 0 - - def get_physical_port_phyid(self, physical_port): - """Returns list of phyids for a physical port""" - - return self.physical_to_phyaddrs[physical_port] - - def get_40_by_4_gangport_phyid(self, logical_port): - """ Return the first ports phyid. One use case for - this is to address the gang port in single mode """ - - phyid_list = self.phytab_mappings[logical_port]['phyid'] - if phyid_list is not None: - return phyid_list[0] - - def is_valid_sfputil_port(self, port): - if port.startswith(""): - if self.is_logical_port(port): - return 1 - else: - return 0 - else: - return 0 - - def read_port_mappings(self): - if self.port_to_eeprom_mapping is None or self.port_to_i2cbus_mapping is None: - self.read_port_to_eeprom_mapping() - self.read_port_to_i2cbus_mapping() - - def read_port_to_eeprom_mapping(self): - eeprom_dev = "/sys/class/eeprom_dev" - self.port_to_eeprom_mapping = {} - for eeprom_path in [os.path.join(eeprom_dev, x) for x in os.listdir(eeprom_dev)]: - eeprom_label = open(os.path.join(eeprom_path, "label"), "r").read().strip() - if eeprom_label.startswith("port"): - port = int(eeprom_label[4:]) - self.port_to_eeprom_mapping[port] = os.path.join(eeprom_path, "device", "eeprom") - - def read_port_to_i2cbus_mapping(self): - if self.port_to_i2cbus_mapping is not None and len(self.port_to_i2cbus_mapping) > 0: - return - - self.eep_dict = eeprom_dts.get_dev_attr_from_dtb(['sfp']) - if len(self.eep_dict) == 0: - return - - # XXX: there should be a cleaner way to do this. - i2cbus_list = [] - self.port_to_i2cbus_mapping = {} - s = self.port_start - for sfp_sysfs_path, attrs in sorted(self.eep_dict.iteritems()): - i2cbus = attrs.get("dev-id") - if i2cbus is None: - raise DeviceTreeError("No 'dev-id' attribute found in attr: %s" % repr(attrs)) - if i2cbus in i2cbus_list: - continue - i2cbus_list.append(i2cbus) - self.port_to_i2cbus_mapping[s] = i2cbus - s += 1 - if s > self.port_end: - break - - def get_eeprom_raw(self, port_num, num_bytes=256): - # Read interface id EEPROM at addr 0x50 - return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 0, num_bytes) - - def get_eeprom_dom_raw(self, port_num): - if port_num in self.osfp_ports: - return None - if port_num in self.qsfp_ports: - # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw - return None - else: - # Read dom eeprom at addr 0x51 - return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 0) - - def get_eeprom_dict(self, port_num): - """Returns dictionary of interface and dom data. - format: { : {'interface': {'version' : '1.0', 'data' : {...}}, - 'dom' : {'version' : '1.0', 'data' : {...}}}} - """ - - sfp_data = {} - - eeprom_ifraw = self.get_eeprom_raw(port_num) - eeprom_domraw = self.get_eeprom_dom_raw(port_num) - - if eeprom_ifraw is None: - return None - - if port_num in self.osfp_ports: - sfpi_obj = inf8628InterfaceId(eeprom_ifraw) - if sfpi_obj is not None: - sfp_data['interface'] = sfpi_obj.get_data_pretty() - return sfp_data - elif port_num in self.qsfp_ports: - sfpi_obj = sff8436InterfaceId(eeprom_ifraw) - if sfpi_obj is not None: - sfp_data['interface'] = sfpi_obj.get_data_pretty() - # For Qsfp's the dom data is part of eeprom_if_raw - # The first 128 bytes - - sfpd_obj = sff8436Dom(eeprom_ifraw) - if sfpd_obj is not None: - sfp_data['dom'] = sfpd_obj.get_data_pretty() - - return sfp_data - else: - sfpi_obj = sff8472InterfaceId(eeprom_ifraw) - if sfpi_obj is not None: - sfp_data['interface'] = sfpi_obj.get_data_pretty() - cal_type = sfpi_obj.get_calibration_type() - - if eeprom_domraw is not None: - sfpd_obj = sff8472Dom(eeprom_domraw, cal_type) - if sfpd_obj is not None: - sfp_data['dom'] = sfpd_obj.get_data_pretty() - - return sfp_data - - # Read out SFP type, vendor name, PN, REV, SN from eeprom. - def get_transceiver_info_dict(self, port_num): - transceiver_info_dict = {} - compliance_code_dict = {} - - # ToDo: OSFP tranceiver info parsing not fully supported. - # in inf8628.py lack of some memory map definition - # will be implemented when the inf8628 memory map ready - if port_num in self.osfp_ports: - offset = 0 - vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP - - sfpi_obj = inf8628InterfaceId() - if sfpi_obj is None: - print("Error: sfp_object open failed") - return None - - file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - print("Error, file not exist %s" % file_path) - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfp_type_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) - if sfp_type_raw is not None: - sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0) - else: - return None - - sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) - if sfp_vendor_name_raw is not None: - sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) - else: - return None - - sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) - if sfp_vendor_pn_raw is not None: - sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) - else: - return None - - sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width) - if sfp_vendor_rev_raw is not None: - sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) - else: - return None - - sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) - if sfp_vendor_sn_raw is not None: - sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) - else: - return None - - sfp_type_abbrv_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH) - if sfp_type_abbrv_name_raw is not None: - sfp_type_abbrv_name = sfpi_obj.parse_sfp_type_abbrv_name(sfp_type_abbrv_name_raw, 0) - else: - return None - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - transceiver_info_dict['type'] = sfp_type_data['data']['type']['value'] - transceiver_info_dict['type_abbrv_name'] = sfp_type_abbrv_name['data']['type_abbrv_name']['value'] - transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] - transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] - transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] - transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] - # Below part is added to avoid fail the xcvrd, shall be implemented later - transceiver_info_dict['vendor_oui'] = 'N/A' - transceiver_info_dict['vendor_date'] = 'N/A' - transceiver_info_dict['Connector'] = 'N/A' - transceiver_info_dict['encoding'] = 'N/A' - transceiver_info_dict['ext_identifier'] = 'N/A' - transceiver_info_dict['ext_rateselect_compliance'] = 'N/A' - transceiver_info_dict['cable_type'] = 'N/A' - transceiver_info_dict['cable_length'] = 'N/A' - transceiver_info_dict['specification_compliance'] = 'N/A' - transceiver_info_dict['nominal_bit_rate'] = 'N/A' - - else: - if port_num in self.qsfp_ports: - offset = 128 - vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP - cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP - interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP - sfp_type = 'QSFP' - - sfpi_obj = sff8436InterfaceId() - if sfpi_obj is None: - print("Error: sfp_object open failed") - return None - - else: - offset = 0 - vendor_rev_width = XCVR_HW_REV_WIDTH_SFP - cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP - interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP - sfp_type = 'SFP' - - sfpi_obj = sff8472InterfaceId() - if sfpi_obj is None: - print("Error: sfp_object open failed") - return None - - file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - print("Error, file not exist %s" % file_path) - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfp_interface_bulk_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width) - if sfp_interface_bulk_raw is not None: - sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) - else: - return None - - sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) - if sfp_vendor_name_raw is not None: - sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) - else: - return None - - sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) - if sfp_vendor_pn_raw is not None: - sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) - else: - return None - - sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width) - if sfp_vendor_rev_raw is not None: - sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) - else: - return None - - sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) - if sfp_vendor_sn_raw is not None: - sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) - else: - return None - - sfp_vendor_oui_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) - if sfp_vendor_oui_raw is not None: - sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) - else: - return None - - sfp_vendor_date_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) - if sfp_vendor_date_raw is not None: - sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) - else: - return None - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] - transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] - transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] - transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] - transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] - transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] - transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] - transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] - transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value'] - transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] - transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] - transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] - if sfp_type == 'QSFP': - for key in qsfp_cable_length_tup: - if key in sfp_interface_bulk_data['data']: - transceiver_info_dict['cable_type'] = key - transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) - - for key in qsfp_compliance_code_tup: - if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: - compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] - transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) - - transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) - else: - for key in sfp_cable_length_tup: - if key in sfp_interface_bulk_data['data']: - transceiver_info_dict['cable_type'] = key - transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) - - for key in sfp_compliance_code_tup: - if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: - compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] - transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) - - transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) - - return transceiver_info_dict - - def get_transceiver_dom_info_dict(self, port_num): - transceiver_dom_info_dict = {} - - dom_info_dict_keys = ['temperature', 'voltage', 'rx1power', - 'rx2power', 'rx3power', 'rx4power', - 'tx1bias', 'tx2bias', 'tx3bias', - 'tx4bias', 'tx1power', 'tx2power', - 'tx3power', 'tx4power', - ] - transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') - - if port_num in self.osfp_ports: - # Below part is added to avoid fail xcvrd, shall be implemented later - transceiver_dom_info_dict['temperature'] = 'N/A' - transceiver_dom_info_dict['voltage'] = 'N/A' - transceiver_dom_info_dict['rx1power'] = 'N/A' - transceiver_dom_info_dict['rx2power'] = 'N/A' - transceiver_dom_info_dict['rx3power'] = 'N/A' - transceiver_dom_info_dict['rx4power'] = 'N/A' - transceiver_dom_info_dict['tx1bias'] = 'N/A' - transceiver_dom_info_dict['tx2bias'] = 'N/A' - transceiver_dom_info_dict['tx3bias'] = 'N/A' - transceiver_dom_info_dict['tx4bias'] = 'N/A' - transceiver_dom_info_dict['tx1power'] = 'N/A' - transceiver_dom_info_dict['tx2power'] = 'N/A' - transceiver_dom_info_dict['tx3power'] = 'N/A' - transceiver_dom_info_dict['tx4power'] = 'N/A' - - elif port_num in self.qsfp_ports: - offset = 0 - offset_xcvr = 128 - file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfpd_obj = sff8436Dom() - if sfpd_obj is None: - return None - - sfpi_obj = sff8436InterfaceId() - if sfpi_obj is None: - return None - - # QSFP capability byte parse, through this byte can know whether it support tx_power or not. - # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, - # need to add more code for determining the capability and version compliance - # in SFF-8636 dom capability definitions evolving with the versions. - qsfp_dom_capability_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) - if qsfp_dom_capability_raw is not None: - qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) - else: - return None - - dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) - if dom_temperature_raw is not None: - dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) - else: - return None - - dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) - if dom_voltage_raw is not None: - dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) - else: - return None - - qsfp_dom_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) - if qsfp_dom_rev_raw is not None: - qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) - else: - return None - - transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] - transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] - - # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 - # and claimed that it support tx_power with one indicator bit. - dom_channel_monitor_data = {} - qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] - qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] - if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): - dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) - if dom_channel_monitor_raw is not None: - dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) - else: - return None - - transceiver_dom_info_dict['tx1power'] = 'N/A' - transceiver_dom_info_dict['tx2power'] = 'N/A' - transceiver_dom_info_dict['tx3power'] = 'N/A' - transceiver_dom_info_dict['tx4power'] = 'N/A' - else: - dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) - if dom_channel_monitor_raw is not None: - dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) - else: - return None - - transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] - transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] - transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] - transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] - transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] - transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] - transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] - transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] - transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] - transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] - transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] - transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] - transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] - - else: - offset = 256 - file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfpd_obj = sff8472Dom() - if sfpd_obj is None: - return None - - dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) - if dom_temperature_raw is not None: - dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) - else: - return None - - dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) - if dom_voltage_raw is not None: - dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) - else: - return None - - dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) - if dom_channel_monitor_raw is not None: - dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) - else: - return None - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] - transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] - transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] - transceiver_dom_info_dict['rx2power'] = 'N/A' - transceiver_dom_info_dict['rx3power'] = 'N/A' - transceiver_dom_info_dict['rx4power'] = 'N/A' - transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] - transceiver_dom_info_dict['tx2bias'] = 'N/A' - transceiver_dom_info_dict['tx3bias'] = 'N/A' - transceiver_dom_info_dict['tx4bias'] = 'N/A' - transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] - transceiver_dom_info_dict['tx2power'] = 'N/A' - transceiver_dom_info_dict['tx3power'] = 'N/A' - transceiver_dom_info_dict['tx4power'] = 'N/A' - - return transceiver_dom_info_dict - - def get_transceiver_dom_threshold_info_dict(self, port_num): - transceiver_dom_threshold_info_dict = {} - - dom_info_dict_keys = ['temphighalarm', 'temphighwarning', - 'templowalarm', 'templowwarning', - 'vcchighalarm', 'vcchighwarning', - 'vcclowalarm', 'vcclowwarning', - 'rxpowerhighalarm', 'rxpowerhighwarning', - 'rxpowerlowalarm', 'rxpowerlowwarning', - 'txpowerhighalarm', 'txpowerhighwarning', - 'txpowerlowalarm', 'txpowerlowwarning', - 'txbiashighalarm', 'txbiashighwarning', - 'txbiaslowalarm', 'txbiaslowwarning' - ] - transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A') - - if port_num in self.qsfp_ports: - file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfpd_obj = sff8436Dom() - if sfpd_obj is None: - return None - - # Dom Threshold data starts from offset 384 - # Revert offset back to 0 once data is retrieved - offset = 384 - dom_module_threshold_raw = self._read_eeprom_specific_bytes( - sysfsfile_eeprom, - (offset + QSFP_MODULE_THRESHOLD_OFFSET), - QSFP_MODULE_THRESHOLD_WIDTH) - if dom_module_threshold_raw is not None: - dom_module_threshold_data = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) - else: - return None - - dom_channel_threshold_raw = self._read_eeprom_specific_bytes( - sysfsfile_eeprom, - (offset + QSFP_CHANNL_THRESHOLD_OFFSET), - QSFP_CHANNL_THRESHOLD_WIDTH) - if dom_channel_threshold_raw is not None: - dom_channel_threshold_data = sfpd_obj.parse_channel_threshold_values(dom_channel_threshold_raw, 0) - else: - return None - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - # Threshold Data - transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] - transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] - transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] - transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] - transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] - transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] - transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] - transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] - transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] - transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] - transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] - transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] - transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['TxBiasHighAlarm']['value'] - transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['TxBiasHighWarning']['value'] - transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['TxBiasLowAlarm']['value'] - transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['TxBiasLowWarning']['value'] - - else: - offset = 256 - file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) - if not self._sfp_eeprom_present(file_path, 0): - return None - - try: - sysfsfile_eeprom = open(file_path, mode="rb", buffering=0) - except IOError: - print("Error: reading sysfs file %s" % file_path) - return None - - sfpd_obj = sff8472Dom() - if sfpd_obj is None: - return None - - dom_module_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, - (offset + SFP_MODULE_THRESHOLD_OFFSET), - SFP_MODULE_THRESHOLD_WIDTH) - if dom_module_threshold_raw is not None: - dom_module_threshold_data = sfpd_obj.parse_module_monitor_params(dom_module_threshold_raw, 0) - else: - return None - - dom_channel_threshold_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, - (offset + SFP_CHANNL_THRESHOLD_OFFSET), - SFP_CHANNL_THRESHOLD_WIDTH) - if dom_channel_threshold_raw is not None: - dom_channel_threshold_data = sfpd_obj.parse_channel_monitor_params(dom_channel_threshold_raw, 0) - else: - return None - - try: - sysfsfile_eeprom.close() - except IOError: - print("Error: closing sysfs file %s" % file_path) - return None - - # Threshold Data - transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] - transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] - transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] - transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] - transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VccHighAlarm']['value'] - transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VccLowAlarm']['value'] - transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VccHighWarning']['value'] - transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VccLowWarning']['value'] - transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_channel_threshold_data['data']['BiasHighAlarm']['value'] - transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_channel_threshold_data['data']['BiasLowAlarm']['value'] - transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_channel_threshold_data['data']['BiasHighWarning']['value'] - transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_channel_threshold_data['data']['BiasLowWarning']['value'] - transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_channel_threshold_data['data']['TxPowerHighAlarm']['value'] - transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_channel_threshold_data['data']['TxPowerLowAlarm']['value'] - transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_channel_threshold_data['data']['TxPowerHighWarning']['value'] - transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_channel_threshold_data['data']['TxPowerLowWarning']['value'] - transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_channel_threshold_data['data']['RxPowerHighAlarm']['value'] - transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_channel_threshold_data['data']['RxPowerLowAlarm']['value'] - transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_channel_threshold_data['data']['RxPowerHighWarning']['value'] - transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_channel_threshold_data['data']['RxPowerLowWarning']['value'] - - return transceiver_dom_threshold_info_dict - - @abc.abstractmethod - def get_presence(self, port_num): - """ - :param port_num: Integer, index of physical port - :returns: Boolean, True if tranceiver is present, False if not - """ - return - - @abc.abstractmethod - def get_low_power_mode(self, port_num): - """ - :param port_num: Integer, index of physical port - :returns: Boolean, True if low-power mode enabled, False if disabled - """ - return - - @abc.abstractmethod - def set_low_power_mode(self, port_num, lpmode): - """ - :param port_num: Integer, index of physical port - :param lpmode: Boolean, True to enable low-power mode, False to disable it - :returns: Boolean, True if low-power mode set successfully, False if not - """ - return - - @abc.abstractmethod - def reset(self, port_num): - """ - :param port_num: Integer, index of physical port - :returns: Boolean, True if reset successful, False if not - """ - return - - @abc.abstractmethod - def get_transceiver_change_event(self, timeout=0): - """ - :param timeout in milliseconds. The method is a blocking call. When timeout is - zero, it only returns when there is change event, i.e., transceiver plug-in/out - event. When timeout is non-zero, the function can also return when the timer expires. - When timer expires, the return status is True and events is empty. - :returns: (status, events) - :status: Boolean, True if call successful, False if not; - :events: dictionary for pysical port index and the SFP status, - status='1' represent plug in, '0' represent plug out like {'0': '1', '31':'0'} - """ - return