From 495584bd2f228af81934b23e4cf19648ab387fab Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Fri, 12 Jan 2018 16:59:20 -0800 Subject: [PATCH] Remove platform-specific hardware plugin packages; They have been moved to sonic-platform-common repo (#184) - Also increment package version to 1.2 --- README.md | 4 +- setup.py | 18 +- sonic_eeprom/__init__.py | 0 sonic_eeprom/eeprom_base.py | 359 ----------- sonic_eeprom/eeprom_dts.py | 141 ----- sonic_eeprom/eeprom_tlvinfo.py | 545 ----------------- sonic_psu/__init__.py | 0 sonic_psu/psu_base.py | 49 -- sonic_sfp/__init__.py | 0 sonic_sfp/bcmshell.py | 496 --------------- sonic_sfp/sff8436.py | 908 --------------------------- sonic_sfp/sff8472.py | 1050 -------------------------------- sonic_sfp/sffbase.py | 250 -------- sonic_sfp/sfputilbase.py | 608 ------------------ 14 files changed, 6 insertions(+), 4422 deletions(-) delete mode 100644 sonic_eeprom/__init__.py delete mode 100644 sonic_eeprom/eeprom_base.py delete mode 100644 sonic_eeprom/eeprom_dts.py delete mode 100644 sonic_eeprom/eeprom_tlvinfo.py delete mode 100644 sonic_psu/__init__.py delete mode 100644 sonic_psu/psu_base.py delete mode 100644 sonic_sfp/__init__.py delete mode 100644 sonic_sfp/bcmshell.py delete mode 100644 sonic_sfp/sff8436.py delete mode 100644 sonic_sfp/sff8472.py delete mode 100644 sonic_sfp/sffbase.py delete mode 100644 sonic_sfp/sfputilbase.py diff --git a/README.md b/README.md index 7c7a56679a..b419224f55 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Command-line utilities for SONiC # Contribution guide -All contributors must sign a contribution license agreement before contributions can be accepted. Contact kasubra@microsoft.com or daloher@microsoft.com. Later this will be automated. +All contributors must sign a contribution license agreement (CLA) before contributions can be accepted. This process is now automated via a GitHub bot when submitting new pull request. If the contributor has not yet signed a CLA, the bot will create a comment on the pull request containing a link to electronically sign the CLA. ### GitHub Workflow @@ -34,7 +34,7 @@ For example: > * Health-Monitor - The idea of the patch is that if something went wrong with the notification channel, > we will have the option to know about it (Query the LLEN table length). > -> Signed-off-by: user@dev.null +> Signed-off-by: John Doe user@dev.null * Each developer should fork this repository and [add the team as a Contributor](https://help.github.com/articles/adding-collaborators-to-a-personal-repository) diff --git a/setup.py b/setup.py index 6e5e524413..bc23ad9d29 100644 --- a/setup.py +++ b/setup.py @@ -1,21 +1,15 @@ import glob -import sys from setuptools import setup import unittest -# For python3 wheel, we currently don't need test -# TODO: build python3 wheel of all the dependencies, and remove conditional test def get_test_suite(): - if sys.version_info >= (3, 0): - return unittest.TestSuite() - else: - test_loader = unittest.TestLoader() - test_suite = test_loader.discover('sonic-utilities-tests', pattern='*.py') - return test_suite + test_loader = unittest.TestLoader() + test_suite = test_loader.discover('sonic-utilities-tests', pattern='*.py') + return test_suite setup( name='sonic-utilities', - version='1.1', + version='1.2', description='Command-line utilities for SONiC', license='Apache 2.0', author='SONiC Team', @@ -32,10 +26,7 @@ def get_test_suite(): 'sfputil', 'psuutil', 'show', - 'sonic_eeprom', 'sonic_installer', - 'sonic_psu', - 'sonic_sfp', 'sonic-utilities-tests', 'undebug', ], @@ -92,7 +83,6 @@ def get_test_suite(): 'Natural Language :: English', 'Operating System :: POSIX :: Linux', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.6', 'Topic :: Utilities', ], keywords='sonic SONiC utilities command line cli CLI', diff --git a/sonic_eeprom/__init__.py b/sonic_eeprom/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sonic_eeprom/eeprom_base.py b/sonic_eeprom/eeprom_base.py deleted file mode 100644 index c41ea5967d..0000000000 --- a/sonic_eeprom/eeprom_base.py +++ /dev/null @@ -1,359 +0,0 @@ -#! /usr/bin/python -# Copyright 2012 Cumulus Networks LLC, all rights reserved - -############################################################################# -# Base eeprom class containing the main logic for reading, writing, and -# setting the eeprom. The format definition is a list of tuples of: -# ('data name', 'data type', 'size in bytes') -# data type is one of 's', 'C', and 'x' (string, char, and ignore) -# 'burn' as a data name indicates the corresponding number of bytes are to -# be ignored - -try: - import exceptions - import binascii - import optparse - import os - import io - import sys - import struct - import subprocess - import fcntl -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -class EepromDecoder(object): - def __init__(self, path, format, start, status, readonly): - self.p = path - self.f = format - self.s = start - self.u = status - self.r = readonly - self.cache_name = None - self.cache_update_needed = False - self.lock_file = None - - def check_status(self): - if self.u <> '': - F = open(self.u, "r") - d = F.readline().rstrip() - F.close() - return d - else: - return 'ok' - - def set_cache_name(self, name): - # before accessing the eeprom we acquire an exclusive lock on the eeprom file. - # this will prevent a race condition where multiple instances of this app - # could try to update the cache at the same time - self.cache_name = name - self.lock_file = open(self.p, 'r') - fcntl.flock(self.lock_file, fcntl.LOCK_EX) - - def is_read_only(self): - return self.r - - def decoder(self, s, t): - return t - - def encoder(self, I, v): - return v - - def checksum_field_size(self): - return 4 # default - - def is_checksum_field(self, I): - return I[0] == 'crc' # default - - def checksum_type(self): - return 'crc32' - - def encode_checksum(self, crc): - if self.checksum_field_size() == 4: - return struct.pack('>I', crc) - elif self.checksum_field_size() == 1: - return struct.pack('>B', crc) - print 'checksum type not yet supported' - exit(1) - - def compute_2s_complement(self, e, size): - crc = 0 - loc = 0 - end = len(e) - while loc <> end: - crc += int('0x' + binascii.b2a_hex(e[loc:loc+size]), 0) - loc += size - T = 1 << (size * 8) - return (T - crc) & (T - 1) - - def compute_dell_crc(self, message): - poly = 0x8005 - reg = 0x0000 - message += '\x00\x00' - for byte in message: - mask = 0x80 - while (mask > 0): - reg<<=1 - if ord(byte) & mask: - reg += 1 - mask>>=1 - if reg > 0xffff: - reg &= 0xffff - reg ^= poly - return reg - - def calculate_checksum(self, e): - if self.checksum_type() == 'crc32': - return binascii.crc32(e) & 0xffffffff - - if self.checksum_type() == '2s-complement': - size = self.checksum_field_size() - return self.compute_2s_complement(e, size) - - if self.checksum_type() == 'dell-crc': - return self.compute_dell_crc(e) - print 'checksum type not yet supported' - exit(1) - - def is_checksum_valid(self, e): - offset = 0 - self.checksum_field_size() - crc = self.calculate_checksum(e[:offset]) - - loc = 0 - for I in self.f: - end = loc + I[2] - t = e[loc:end] - loc = end - if self.is_checksum_field(I): - i = self.decoder(I[0], t) - if int(i, 0) == crc: - return (True, crc) - else: - return (False, crc) - else: - continue - return (False, crc) - - def decode_eeprom(self, e): - loc = 0 - for I in self.f: - end = loc + I[2] - t = e[loc:end] - loc = end - if I[0] == 'burn': - continue - elif I[1] == 's': - i = t - else: - i = self.decoder(I[0], t) - print "%-20s: %s" %(I[0], i) - - def set_eeprom(self, e, cmd_args): - line = '' - loc = 0 - ndict = {} - fields = list(I[0] for I in list(self.f)) - if len(cmd_args): - for arg in cmd_args[0].split(','): - k, v = arg.split('=') - k = k.strip() - v = v.strip() - if k not in fields: - print "Error: invalid field '%s'" %(k) - exit(1) - ndict[k] = v - - for I in self.f: - # print the original value - end = loc + I[2] - sl = e[loc:end] - loc = end - if I[0] == 'burn': - #line += sl - # fill with zeros - line = line.ljust(len(line) + I[2], '\x00') - continue - elif I[1] == 's': - i = sl - else: - i = self.decoder(I[0], sl) - - if len(cmd_args) == 0: - if self.is_checksum_field(I): - print ("%-20s: %s " %(I[0], i)) - continue - - # prompt for new value - v = raw_input("%-20s: [%s] " %(I[0], i)) - if v == '': - v = i - else: - if I[0] not in ndict.keys(): - v = i - else: - v = ndict[I[0]] - - line += self.encoder(I, v) - - # compute and append crc at the end - crc = self.encode_checksum(self.calculate_checksum(line)) - - line += crc - - return line - - def open_eeprom(self): - ''' - Open the EEPROM device file. - If a cache file exists, use that instead of the EEPROM. - ''' - using_eeprom = True - eeprom_file = self.p - try: - if os.path.isfile(self.cache_name): - eeprom_file = self.cache_name - using_eeprom = False - except: - pass - self.cache_update_needed = using_eeprom - return io.open(eeprom_file, "rb") - - def read_eeprom(self): - sizeof_info = 0 - for I in self.f: - sizeof_info += I[2] - o = self.read_eeprom_bytes(sizeof_info) - return o - - def read_eeprom_bytes(self, byteCount, offset=0): - F = self.open_eeprom() - F.seek(self.s + offset) - o = F.read(byteCount) - if len(o) != byteCount: - raise RuntimeError("expected to read %d bytes from %s, " \ - %(byteCount, self.p) + - "but only read %d" %(len(o))) - F.close() - return o - - def write_eeprom(self, e): - F = open(self.p, "wb") - F.seek(self.s) - F.write(e) - F.close() - self.write_cache(e) - - def write_cache(self, e): - if self.cache_name: - F = open(self.cache_name, "wb") - F.seek(self.s) - F.write(e) - F.close() - - def update_cache(self, e): - if self.cache_update_needed: - self.write_cache(e) - fcntl.flock(self.lock_file, fcntl.LOCK_UN) - - def diff_mac(self, mac1, mac2): - if mac1 == '' or mac2 == '': - return 0 - mac1_octets = [] - mac1_octets = mac1.split(':') - mac1val = int(mac1_octets[5], 16) | int(mac1_octets[4], 16) << 8 | int(mac1_octets[3], 16) << 16 - mac2_octets = [] - mac2_octets = mac2.split(':') - mac2val = int(mac2_octets[5], 16) | int(mac2_octets[4], 16) << 8 | int(mac2_octets[3], 16) << 16 - # check oui matches - if (mac1_octets[0] != mac2_octets[0] - or mac1_octets[1] != mac2_octets[1] - or mac1_octets[2] != mac2_octets[2]) : - return 0 - - if mac2val < mac1val: - return 0 - - return (mac2val - mac1val) - - def increment_mac(self, mac): - if mac != "": - mac_octets = [] - mac_octets = mac.split(':') - ret_mac = int(mac_octets[5], 16) | int(mac_octets[4], 16) << 8 | int(mac_octets[3], 16) << 16 - ret_mac = ret_mac + 1 - - if (ret_mac & 0xff000000): - print 'Error: increment carries into OUI' - return '' - - mac_octets[5] = hex(ret_mac & 0xff)[2:].zfill(2) - mac_octets[4] = hex((ret_mac >> 8) & 0xff)[2:].zfill(2) - mac_octets[3] = hex((ret_mac >> 16) & 0xff)[2:].zfill(2) - - return ':'.join(mac_octets).upper() - - return '' - - @classmethod - def find_field(cls, e, name): - if not hasattr(cls, 'brd_fmt'): - raise RuntimeError("Class %s does not have brb_fmt" % cls) - if not e: - raise RuntimeError("EEPROM can not be empty") - brd_fmt = cls.brd_fmt - loc = 0 - for f in brd_fmt: - end = loc + f[2] - t = e[loc:end] - loc = end - if f[0] == name: - return t - - def base_mac_addr(self, e): - ''' - Returns the base MAC address found in the EEPROM. - - Sub-classes must override this method as reading the EEPROM - and finding the base MAC address entails platform specific - details. - - See also mgmtaddrstr() and switchaddrstr(). - ''' - print "ERROR: Platform did not implement base_mac_addr()" - raise NotImplementedError - - def mgmtaddrstr(self, e): - ''' - Returns the base MAC address to use for the Ethernet - management interface(s) on the CPU complex. - - By default this is the same as the base MAC address listed in - the EEPROM. - - See also switchaddrstr(). - ''' - return self.base_mac_addr(e) - - def switchaddrstr(self, e): - ''' - Returns the base MAC address to use for the switch ASIC - interfaces. - - By default this is *next* address after the base MAC address - listed in the EEPROM. - - See also mgmtaddrstr(). - ''' - return self.increment_mac(self.base_mac_addr(e)) - - def switchaddrrange(self, e): - # this function is in the base class only to catch errors - # the platform specific import should have an override of this method - # to provide the allocated mac range from syseeprom or flash sector or - # wherever that platform stores this info - print "Platform did not indicate allocated mac address range" - raise NotImplementedError - - def serial_number_str(self, e): - raise NotImplementedError("Platform did not indicate serial number") diff --git a/sonic_eeprom/eeprom_dts.py b/sonic_eeprom/eeprom_dts.py deleted file mode 100644 index e449f952d3..0000000000 --- a/sonic_eeprom/eeprom_dts.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/python -# Copyright 2012 Cumulus Networks LLC, all rights reserved - -try: - import os - import exceptions - import binascii - import subprocess -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - -i2c_root = '/sys/class/i2c-adapter/' -mtd_root = '/dev/mtd' -dts_root = '/proc/device-tree/' -sys_dev = '/sys/devices/' - -# -# This routine takes a token list containing the desired eeprom types -# (e.g. 'sfp', 'psu', 'board'), and returns a dict of {[dts path:(dev attrs)]} -# for the corresponding eeproms. For those accessible via i2c, the attrs -# will contain (i2c bus index, i2c device number). For those mounted to -# /dev/mtd, the attrs will be (mtd partition number). -# -def get_dev_attr_from_dtb(tokens): - - dts_paths = [] - i2c_devices = [] - sub_devices = [] - - eep_dict = {} - - # - # first try i2c - # - try: - ph = subprocess.Popen(['/bin/ls', '-R', dts_root], - stdout=subprocess.PIPE, - shell=False, stderr=subprocess.STDOUT) - cmdout = ph.communicate()[0] - ph.wait() - except OSError, e: - raise OSError("cannot access directory") - - lines = cmdout.splitlines() - for I in lines: - if not I.endswith(':') or 'i2c' not in I: - continue - - I = I.rstrip(':\n\r') - last = I.split('/')[-1] - if 'i2c' in last: - depth = I.count('i2c') - while len(sub_devices) < depth: - sub_devices.append([]) - sub_devices[depth-1].append(I) - elif 'eeprom' in last: - dts_paths.append(I) - - # re-order the device heirarchy and build the device list - for i in sub_devices: - for j in i: - i2c_devices.append(j) - - for eep in dts_paths: - instance = '' - if os.path.isfile('/'.join([eep, 'label'])): - F = open('/'.join([eep, 'label']), "rb") - instance = F.read().partition('_eeprom')[0] - F.close() - - # check for read-only - read_only = os.path.isfile('/'.join([eep, 'read-only'])) - - for t in tokens: - if t not in eep and t not in instance: - continue - - # get the i2c idx by matching the path prefix - i2c_idx = i2c_devices.index(eep.rsplit('/', 1)[0]) - - # read the reg - reg_path = '/'.join([eep, 'reg']) - F = open(reg_path, "rb") - o = F.read() - reg = binascii.b2a_hex(o)[-2:] - F.close() - - eep_dict[eep] = {'type': 'i2c', \ - 'dev-id': i2c_idx, \ - 'reg': reg, \ - 'ro': read_only} - break - - - # - # now try flash - # - try: - ph = subprocess.Popen(['/bin/grep', '-r', 'eeprom', dts_root], - stdout=subprocess.PIPE, - shell=False, stderr=subprocess.STDOUT) - cmdout = ph.communicate()[0] - ph.wait() - except OSError, e: - raise OSError("cannot access directory") - - lines = cmdout.splitlines() - for I in lines: - if 'flash' not in I or 'label' not in I: - continue - - eep = I.partition(dts_root)[2].rpartition('label')[0] - full_eep = '/'.join([dts_root, eep]) - F = open('/'.join([full_eep, 'label']), "rb") - instance = F.read().partition('_eeprom')[0] - F.close() - - read_only = os.path.isfile('/'.join([full_eep, 'read-only'])) - - for t in tokens: - if t not in instance: - continue - - mtd_n = eep.partition('partition@')[2].rstrip('/') - eep_dict[full_eep] = {'type': 'mtd', \ - 'dev-id': mtd_n, \ - 'ro': read_only} - - return eep_dict - - -def dev_attr_to_path(dev_attrs): - dev_path = '' - if dev_attrs['type'] == 'i2c': - dev_path = i2c_root + 'i2c-' + str(dev_attrs['dev-id']) + '/' + \ - str(dev_attrs['dev-id']) + '-00' + str(dev_attrs['reg']) + \ - '/' + 'eeprom' - elif dev_attrs['type'] == 'mtd': - dev_path = mtd_root + dev_attrs['dev-id'] - - return dev_path diff --git a/sonic_eeprom/eeprom_tlvinfo.py b/sonic_eeprom/eeprom_tlvinfo.py deleted file mode 100644 index ca4b073be0..0000000000 --- a/sonic_eeprom/eeprom_tlvinfo.py +++ /dev/null @@ -1,545 +0,0 @@ -#! /usr/bin/python -# Copyright 2012 Cumulus Networks LLC, all rights reserved - -############################################################################# -# Base eeprom class containing the main logic for reading, writing, and -# setting the eeprom. The format definition is a list of tuples of: -# ('data name', 'data type', 'size in bytes') -# data type is one of 's', 'C', and 'x' (string, char, and ignore) -# 'burn' as a data name indicates the corresponding number of bytes are to -# be ignored - -try: - import exceptions - import binascii - import optparse - import os - import sys - import eeprom_base -except ImportError, e: - raise ImportError (str(e) + "- required module not found") - - -# -# TlvInfo Format - This eeprom format was defined by Cumulus Networks -# and can be found here: -# -# -class TlvInfoDecoder(eeprom_base.EepromDecoder): - - # Header Field Constants - _TLV_INFO_ID_STRING = "TlvInfo\x00" - _TLV_INFO_VERSION = 0x01 - _TLV_INFO_HDR_LEN = 11 - _TLV_INFO_MAX_LEN = 2048 - _TLV_TOTAL_LEN_MAX = _TLV_INFO_MAX_LEN - _TLV_INFO_HDR_LEN - _TLV_HDR_ENABLED = 1 - - # The Undefined TLV Type - _TLV_CODE_UNDEFINED = 0xFC - - # Default TLV Types - _TLV_CODE_PRODUCT_NAME = 0x21 - _TLV_CODE_PART_NUMBER = 0x22 - _TLV_CODE_SERIAL_NUMBER = 0x23 - _TLV_CODE_MAC_BASE = 0x24 - _TLV_CODE_MANUF_DATE = 0x25 - _TLV_CODE_DEVICE_VERSION = 0x26 - _TLV_CODE_LABEL_REVISION = 0x27 - _TLV_CODE_PLATFORM_NAME = 0x28 - _TLV_CODE_ONIE_VERSION = 0x29 - _TLV_CODE_MAC_SIZE = 0x2A - _TLV_CODE_MANUF_NAME = 0x2B - _TLV_CODE_MANUF_COUNTRY = 0x2C - _TLV_CODE_VENDOR_NAME = 0x2D - _TLV_CODE_DIAG_VERSION = 0x2E - _TLV_CODE_SERVICE_TAG = 0x2F - _TLV_CODE_VENDOR_EXT = 0xFD - _TLV_CODE_CRC_32 = 0xFE - - # By default disable the Quanta specific codes - _TLV_CODE_QUANTA_MAGIC = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_CRC = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_CARD_TYPE = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_HW_VERSION = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_SW_VERSION = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_MANUF_DATE = _TLV_CODE_UNDEFINED - _TLV_CODE_QUANTA_MODEL_NAME = _TLV_CODE_UNDEFINED - - # TLV Value Display Switch - _TLV_DISPLAY_VENDOR_EXT = False - - def __init__(self, path, start, status, ro, max_len=_TLV_INFO_MAX_LEN): - super(TlvInfoDecoder, self).__init__(path, \ - None, \ - start, \ - status, \ - ro) - self.eeprom_start = start - self.eeprom_max_len = max_len - - def decode_eeprom(self, e): - ''' - Decode and print out the contents of the EEPROM. - ''' - if self._TLV_HDR_ENABLED : - if not self.is_valid_tlvinfo_header(e): - print "EEPROM does not contain data in a valid TlvInfo format." - return - - print "TlvInfo Header:" - print " Id String: %s" % (e[0:7],) - print " Version: %d" % (ord(e[8]),) - total_len = (ord(e[9]) << 8) | ord(e[10]) - print " Total Length: %d" % (total_len,) - tlv_index = self._TLV_INFO_HDR_LEN - tlv_end = self._TLV_INFO_HDR_LEN + total_len - else : - tlv_index = self.eeprom_start - tlv_end = self._TLV_INFO_MAX_LEN - - print "TLV Name Code Len Value" - print "-------------------- ---- --- -----" - while (tlv_index + 2) < len(e) and tlv_index < tlv_end: - if not self.is_valid_tlv(e[tlv_index:]): - print "Invalid TLV field starting at EEPROM offset %d" % (tlv_index,) - return - print self.decoder(None, e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])]) - if ord(e[tlv_index]) == self._TLV_CODE_QUANTA_CRC or \ - ord(e[tlv_index]) == self._TLV_CODE_CRC_32: - return - tlv_index += ord(e[tlv_index+1]) + 2 - - def set_eeprom(self, e, cmd_args): - ''' - Returns the new contents of the EEPROM. If command line arguments are supplied, - then those fields are overwritten or added to the existing EEPROM contents. If - not command line arguments are supplied, the user is prompted for the contents - of the EEPROM. - ''' - new_tlvs = "" - (crc_is_valid, crc) = self.is_checksum_valid(e) - if crc_is_valid: - if self._TLV_HDR_ENABLED: - tlv_index = self._TLV_INFO_HDR_LEN - tlv_end = self._TLV_INFO_HDR_LEN + ((ord(e[9]) << 8) | ord(e[10])) - else : - tlv_index = self.eeprom_start - tlv_end = self._TLV_INFO_MAX_LEN - - while tlv_index < len(e) and \ - tlv_index < tlv_end and \ - self.is_valid_tlv(e[tlv_index:]) and \ - ord(e[tlv_index]) != self._TLV_CODE_CRC_32 and \ - ord(e[tlv_index]) != self._TLV_CODE_QUANTA_CRC: - new_tlvs += e[tlv_index:tlv_index + 2 + ord(e[tlv_index + 1])] - tlv_index += ord(e[tlv_index+1]) + 2 - - if len(cmd_args): - for arg_str in cmd_args: - for arg in arg_str.split(','): - k, v = arg.split('=') - k = int(k.strip(), 0) - v = v.strip() - new_tlv = self.encoder((k,), v) - (tlv_found, index) = self.get_tlv_index(new_tlvs, k) - if tlv_found: - new_tlvs = new_tlvs[:index] + new_tlv + \ - new_tlvs[index + 2 + ord(new_tlvs[index + 1]):] - else: - new_tlvs += new_tlv - - else: - action = "a" - while action not in ['f', 'F']: - - action = raw_input("\n[a]dd, [m]odify, [d]elete, [f]inished: ") - if action in ['a', 'A', 'm', 'M']: - code = raw_input("Enter a TLV type code: ") - code = int(code, 0) - value = raw_input("Enter the value: ") - new_tlv = self.encoder((code,), value) - (tlv_found, index) = self.get_tlv_index(new_tlvs, code) - if tlv_found: - new_tlvs = new_tlvs[:index] + new_tlv + \ - new_tlvs[index + 2 + ord(new_tlvs[index + 1]):] - else: - new_tlvs += new_tlv - elif action in ['d', 'D']: - code = raw_input("Enter a TLV type code: ") - code = int(code, 0) - (tlv_found, index) = self.get_tlv_index(new_tlvs, code) - if tlv_found: - new_tlvs = new_tlvs[:index] + \ - new_tlvs[index + 2 + ord(new_tlvs[index + 1]):] - elif action in ['f', 'F']: - pass - else: - print "\nInvalid input, please enter 'a', 'm', 'd', or 'f'\n" - - if self._TLV_HDR_ENABLED: - new_tlvs_len = len(new_tlvs) + 6 - new_e = self._TLV_INFO_ID_STRING + chr(self._TLV_INFO_VERSION) + \ - chr((new_tlvs_len >> 8) & 0xFF) + \ - chr(new_tlvs_len & 0xFF) + new_tlvs - else: - new_e = new_tlvs - - if self._TLV_CODE_CRC_32 != self._TLV_CODE_UNDEFINED: - new_e = new_e + chr(self._TLV_CODE_CRC_32) + chr(4) - elif self._TLV_CODE_QUANTA_CRC != self._TLV_CODE_UNDEFINED: - new_e = new_e + chr(self._TLV_CODE_QUANTA_CRC) + chr(2) - else: - print "\nFailed to formulate new eeprom\n" - exit - new_e += self.encode_checksum(self.calculate_checksum(new_e)) - self.decode_eeprom(new_e) - if len(new_e) > min(self._TLV_INFO_MAX_LEN, self.eeprom_max_len): - sys.stderr.write("\nERROR: There is not enough room in the EEPROM to save data.\n") - exit(1) - return new_e - - def is_valid_tlvinfo_header(self, e): - ''' - Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM - data passed in as a string. - 1. Large enough to hold the header - 2. First 8 bytes contain null-terminated ASCII string "TlvInfo" - 3. Version byte is 1 - 4. Total length bytes contain value which is less than or equal - to the allowed maximum (2048-11) - ''' - return len(e) >= self._TLV_INFO_HDR_LEN and \ - e[0:8] == self._TLV_INFO_ID_STRING and \ - ord(e[8]) == self._TLV_INFO_VERSION and \ - ((ord(e[9]) << 8) | ord(e[10])) <= self._TLV_TOTAL_LEN_MAX - - def is_valid_tlv(self, e): - ''' - Perform basic sanity checks on a TLV field. The TLV is in the string - provided. - 1. The TLV is at least 2 bytes long - 2. The length byte contains a value which does not cause the value - field to go beyond the length of the string. - ''' - return (len(e) >= 2 and (2 + ord(e[1]) <= len(e))) - - def is_checksum_valid(self, e): - ''' - Validate the checksum in the provided TlvInfo EEPROM data. - ''' - if not self.is_valid_tlvinfo_header(e): - return (False, 0) - - offset = self._TLV_INFO_HDR_LEN + ((ord(e[9]) << 8) | ord(e[10])) - if len(e) < offset or \ - ord(e[offset-6]) != self._TLV_CODE_CRC_32 or \ - ord(e[offset-5]) != 4: - return (False, 0) - - crc = self.calculate_checksum(e[:offset-4]) - tlv_crc = ord(e[offset-4]) << 24 | ord(e[offset-3]) << 16 | \ - ord(e[offset-2]) << 8 | ord(e[offset-1]) - if tlv_crc == crc: - return(True, crc) - - return (False, crc) - - def read_eeprom(self): - ''' - Read the eeprom contents. This is performed in two steps. First - the 11 bytes of the TlvInfo structure (the header) are read and - sanity checked. Then using the total length field in the header, - the rest of the data is read from the EEPROM. - ''' - offset = 0 - if self._TLV_HDR_ENABLED: - h = self.read_eeprom_bytes(self._TLV_INFO_HDR_LEN) - offset = self._TLV_INFO_HDR_LEN - if len(h) != self._TLV_INFO_HDR_LEN: - raise RuntimeError("expected to read %d bytes from %s, " \ - %(self._TLV_INFO_HDR_LEN, self.p) + \ - "but only read %d" %(len(h),)) - if not self.is_valid_tlvinfo_header(h): - return h - sizeof_tlvs = (ord(h[9]) << 8) | ord(h[10]) - else: - h = "" - sizeof_tlvs = self._TLV_INFO_MAX_LEN - - t = self.read_eeprom_bytes(sizeof_tlvs, offset) - if len(t) != sizeof_tlvs: - raise RuntimeError("expected to read %d bytes from %s, " \ - %(sizeof_tlvs, self.p) + \ - "but only read %d" %(len(t))) - return h + t - - def get_tlv_field(self, e, code): - ''' - Given an EEPROM string the TLV field for the provided code is - returned. This routine validates the EEPROM data (checksum and - other sanity checks) and then searches for a TLV field with the - supplied type code. A tuple of two items is returned. The first - item is a boolean indicating success and, if True, the second - item is a 3 element list with the type (int), length (int), - and value (string) of the requested TLV. - ''' - (is_valid, valid_crc) = self.is_checksum_valid(e) - if not is_valid: - return (False, None) - if self._TLV_HDR_ENABLED: - tlv_index = self._TLV_INFO_HDR_LEN - tlv_end = ((ord(e[9]) << 8) | ord(e[10])) + self._TLV_INFO_HDR_LEN - else : - tlv_index = self.eeprom_start - tlv_end = self._TLV_INFO_MAX_LEN - while tlv_index < len(e) and tlv_index < tlv_end: - if not self.is_valid_tlv(e[tlv_index:]): - return (False, None) - if ord(e[tlv_index]) == code: - return (True, [ord(e[tlv_index]), ord(e[tlv_index+1]), \ - e[tlv_index+2:tlv_index+2+ord(e[tlv_index+1])]]) - tlv_index += ord(e[tlv_index+1]) + 2 - return (False, None) - - def get_tlv_index(self, e, code): - ''' - Given an EEPROM string with just TLV fields (no TlvInfo header) - finds the index of the requested type code. This routine searches - for a TLV field with the supplied type code. A tuple of two items - is returned. The first item is a boolean indicating success and, - if True, the second item is the index in the supplied EEPROM string - of the matching type code. - ''' - tlv_index = 0 - while tlv_index < len(e): - if not self.is_valid_tlv(e[tlv_index:]): - return (False, 0) - if ord(e[tlv_index]) == code: - return (True, tlv_index ) - tlv_index += ord(e[tlv_index+1]) + 2 - return (False, 0) - - def base_mac_addr(self, e): - ''' - Returns the value field of the MAC #1 Base TLV formatted as a string - of colon-separated hex digits. - ''' - (is_valid, t) = self.get_tlv_field(e, self._TLV_CODE_MAC_BASE) - if not is_valid or t[1] != 6: - return super(TlvInfoDecoder, self).switchaddrstr(e) - - return ":".join([binascii.b2a_hex(T) for T in t[2]]) - - def switchaddrrange(self, e): - ''' - Returns the value field of the MAC #1 Size TLV formatted as a decimal - string - ''' - (is_valid, t) = self.get_tlv_field(e, self._TLV_CODE_MAC_SIZE) - if not is_valid: - return super(TlvInfoDecoder, self).switchaddrrange(e) - - return str((ord(t[2][0]) << 8) | ord(t[2][1])) - - def modelstr(self, e): - ''' - Returns the value field of the Product Name TLV as a string - ''' - (is_valid, t) = self.get_tlv_field(e, self._TLV_CODE_PRODUCT_NAME) - if not is_valid: - return super(TlvInfoDecoder, self).modelstr(e) - - return t[2] - - def serial_number_str(self, e): - ''' - Returns the value field of the Serial Number TLV as a string - ''' - valid, t = self.get_tlv_field(e, self._TLV_CODE_SERIAL_NUMBER) - if not valid: - return super(TlvInfoDecoder, self).serial_number_str(e) - return t[2] - - def decoder(self, s, t): - ''' - Return a string representing the contents of the TLV field. The format of - the string is: - 1. The name of the field left justified in 20 characters - 2. The type code in hex right justified in 5 characters - 3. The length in decimal right justified in 4 characters - 4. The value, left justified in however many characters it takes - The vailidity of EEPROM contents and the TLV field has been verified - prior to calling this function. The 's' parameter is unused - ''' - if ord(t[0]) == self._TLV_CODE_PRODUCT_NAME: - name = "Product Name" - value = str(t[2:2 + ord(t[1])]) - elif ord(t[0]) == self._TLV_CODE_PART_NUMBER: - name = "Part Number" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_SERIAL_NUMBER: - name = "Serial Number" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_MAC_BASE: - name = "Base MAC Address" - value = ":".join([binascii.b2a_hex(T) for T in t[2:8]]).upper() - elif ord(t[0]) == self._TLV_CODE_MANUF_DATE: - name = "Manufacture Date" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_DEVICE_VERSION: - name = "Device Version" - value = str(ord(t[2])) - elif ord(t[0]) == self._TLV_CODE_LABEL_REVISION: - name = "Label Revision" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_PLATFORM_NAME: - name = "Platform Name" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_ONIE_VERSION: - name = "ONIE Version" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_MAC_SIZE: - name = "MAC Addresses" - value = str((ord(t[2]) << 8) | ord(t[3])) - elif ord(t[0]) == self._TLV_CODE_MANUF_NAME: - name = "Manufacturer" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_MANUF_COUNTRY: - name = "Manufacture Country" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_VENDOR_NAME: - name = "Vendor Name" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_DIAG_VERSION: - name = "Diag Version" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_SERVICE_TAG: - name = "Service Tag" - value = t[2:2 + ord(t[1])] - elif ord(t[0]) == self._TLV_CODE_VENDOR_EXT: - name = "Vendor Extension" - value = "" - if self._TLV_DISPLAY_VENDOR_EXT: - for c in t[2:2 + ord(t[1])]: - value += "0x%02X " % (ord(c),) - elif ord(t[0]) == self._TLV_CODE_CRC_32 and len(t) == 6: - name = "CRC-32" - value = "0x%08X" % (((ord(t[2]) << 24) | (ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) - # Quanta specific codes below here. - # These decodes are lifted from their U-Boot codes - elif ord(t[0]) == self._TLV_CODE_QUANTA_MAGIC and len(t) == 3: - name = "Magic Number" - value = "0x%02X" % (ord(t[2])) - elif ord(t[0]) == self._TLV_CODE_QUANTA_CRC and len(t) == 4: - name = "QUANTA-CRC" - value = "0x%04X" % ((ord(t[2]) << 8) + ord(t[3])) - elif ord(t[0]) == self._TLV_CODE_QUANTA_CARD_TYPE and len(t) == 6: - name = "Card Type" - value = "0x%08X" % (((ord(t[2]) << 24) | (ord(t[3]) << 16) | (ord(t[4]) << 8) | ord(t[5])),) - elif ord(t[0]) == self._TLV_CODE_QUANTA_HW_VERSION and len(t) == 6: - name = "Hardware Version" - value = "%d.%d" % (ord(t[2]), ord(t[3])) - elif ord(t[0]) == self._TLV_CODE_QUANTA_SW_VERSION and len(t) == 6: - name = "Software Version" - value = "%d.%d.%d.%d" % ((ord(t[2]) >> 4), (ord(t[2]) & 0xF), (ord(t[3]) >> 4), (ord(t[3]) & 0xF)) - elif ord(t[0]) == self._TLV_CODE_QUANTA_MANUF_DATE and len(t) == 6: - name = "Manufacture Date" - value = "%04d/%d/%d" % (((ord(t[2]) << 8) | ord(t[3])), ord(t[4]), ord(t[5])) - elif ord(t[0]) == self._TLV_CODE_QUANTA_MODEL_NAME: - name = "Model Name" - value = t[2:2 + ord(t[1])] - else: - name = "Unknown" - value = "" - for c in t[2:2 + ord(t[1])]: - value += "0x%02X " % (ord(c),) - return "%-20s 0x%02X %3d %s" % (name, ord(t[0]), ord(t[1]), value) - - def encoder(self, I, v): - ''' - Validate and encode the string 'v' into the TLV specified by 'I'. - I[0] is the TLV code. - ''' - try: - if I[0] == self._TLV_CODE_PRODUCT_NAME or \ - I[0] == self._TLV_CODE_PART_NUMBER or \ - I[0] == self._TLV_CODE_SERIAL_NUMBER or \ - I[0] == self._TLV_CODE_LABEL_REVISION or \ - I[0] == self._TLV_CODE_PLATFORM_NAME or \ - I[0] == self._TLV_CODE_ONIE_VERSION or \ - I[0] == self._TLV_CODE_MANUF_NAME or \ - I[0] == self._TLV_CODE_VENDOR_NAME or \ - I[0] == self._TLV_CODE_DIAG_VERSION or \ - I[0] == self._TLV_CODE_SERVICE_TAG: - errstr = "A string less than 256 characters" - if len(v) > 255: - raise - value = v - elif I[0] == self._TLV_CODE_DEVICE_VERSION: - errstr = "A number between 0 and 255" - num = int(v, 0) - if num < 0 or num > 255: - raise - value = chr(num) - elif I[0] == self._TLV_CODE_MAC_SIZE: - errstr = "A number between 0 and 65535" - num = int(v, 0) - if num < 0 or num > 65535: - raise - value = chr((num >> 8) & 0xFF) + chr(num & 0xFF) - elif I[0] == self._TLV_CODE_MANUF_DATE: - errstr = 'MM/DD/YYYY HH:MM:SS' - date, time = v.split() - mo, da, yr = [int(i) for i in date.split('/')] - hr, mn, sc = [int(i) for i in time.split(':')] - if len(v) < 19 or \ - mo < 1 or mo > 12 or da < 1 or da > 31 or yr < 0 or yr > 9999 or \ - hr < 0 or hr > 23 or mn < 0 or mn > 59 or sc < 0 or sc > 59: - raise - value = v - elif I[0] == self._TLV_CODE_MAC_BASE: - errstr = 'XX:XX:XX:XX:XX:XX' - mac_digits = v.split(':') - if len(mac_digits) != 6: - raise - value = "" - for c in mac_digits: - value = value + chr(int(c, 16)) - elif I[0] == self._TLV_CODE_MANUF_COUNTRY: - errstr = 'CC, a two character ISO 3166-1 alpha-2 country code' - if len(v) < 2: - raise - value = v[0:2] - elif I[0] == self._TLV_CODE_CRC_32: - value = '' - # Disallow setting any Quanta specific codes - elif I[0] == self._TLV_CODE_QUANTA_MAGIC or \ - I[0] == self._TLV_CODE_QUANTA_CARD_TYPE or \ - I[0] == self._TLV_CODE_QUANTA_HW_VERSION or \ - I[0] == self._TLV_CODE_QUANTA_SW_VERSION or \ - I[0] == self._TLV_CODE_QUANTA_MANUF_DATE or \ - I[0] == self._TLV_CODE_QUANTA_MODEL_NAME: - raise Exception('quanta-read-only') - else: - errstr = '0xXX ... A list of space-separated hexidecimal numbers' - value = "" - for c in v.split(): - value += chr(int(c, 0)) - except Exception as inst: - if (len(inst.args) > 0) and (inst.args[0] == 'quanta-read-only'): - sys.stderr.write("Error: '" + "0x%02X" % (I[0],) + "' -- Unable to set the read-only Quanta codes.\n") - else: - sys.stderr.write("Error: '" + "0x%02X" % (I[0],) + "' correct format is " + errstr + "\n") - exit(0) - - return chr(I[0]) + chr(len(value)) + value - - def is_checksum_field(self, I): - return False - - def checksum_field_size(self): - return 4 - - def checksum_type(self): - return 'crc32' diff --git a/sonic_psu/__init__.py b/sonic_psu/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sonic_psu/psu_base.py b/sonic_psu/psu_base.py deleted file mode 100644 index 2e2204298e..0000000000 --- a/sonic_psu/psu_base.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -# psu_base.py -# -# Abstract base class for implementing platform-specific -# PSU control functionality for SONiC -# - -try: - import abc -except ImportError as e: - raise ImportError (str(e) + " - required module not found") - -class PsuBase(object): - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def get_num_psus(self): - """ - Retrieves the number of PSUs supported on the device - - :return: An integer, the number of PSUs supported on the device - """ - return 0 - - @abc.abstractmethod - def get_psu_status(self, index): - """ - Retrieves the operational status of power supply unit (PSU) defined - by index 1-based - - :param index: An integer, 1-based index of the PSU of which to query status - :return: Boolean, - - True if PSU is operating properly: PSU is inserted and powered in the device - - False if PSU is faulty: PSU is inserted in the device but not powered - """ - return False - - @abc.abstractmethod - def get_psu_presence(self, index): - """ - Retrieves the presence status of power supply unit (PSU) defined - by 1-based index - - :param index: An integer, 1-based index of the PSU of which to query status - :return: Boolean, True if PSU is plugged, False if not - """ - return False - diff --git a/sonic_sfp/__init__.py b/sonic_sfp/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/sonic_sfp/bcmshell.py b/sonic_sfp/bcmshell.py deleted file mode 100644 index 63156c7538..0000000000 --- a/sonic_sfp/bcmshell.py +++ /dev/null @@ -1,496 +0,0 @@ -#! /usr/bin/python -#------------------------------------------------------------------------------- -# -# Copyright 2012 Cumulus Networks, inc all rights reserved -# -#------------------------------------------------------------------------------- -# -try: - import sys - import os - import time - import socket - import re -except ImportError, 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" + 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), - 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), - 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 (errno, errstr): - 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 (errno, errstr): - 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 (errno, errstr): - 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/sff8436.py b/sonic_sfp/sff8436.py deleted file mode 100644 index 503ad21299..0000000000 --- a/sonic_sfp/sff8436.py +++ /dev/null @@ -1,908 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# SFF-8436 QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER -#---------------------------------------------------------------------------- - -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 - from sffbase import sffbase -except ImportError, 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}}}} - - type_of_transceiver = { - '00':'Unknown or unspecified', - '01':'GBIC', - '02': 'Module/connector soldered to motherboard', - '03': 'SFP', - '04': '300 pin XBI', - '05': 'XENPAK', - '06': 'XFP', - '07': 'XFF', - '08': 'XFP-E', - '09': 'XPAK', - '0a': 'X2', - '0b': 'DWDM-SFP', - '0c': 'QSFP', - '0d': 'QSFP+' - } - - ext_type_of_transceiver = {} - - 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': 'MPO', - '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' - } - - 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': {}}} - - - 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 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, 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, 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, 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, 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, err: - retval = str(err) - - return retval - - - dom_status_indicator = {'DataNotReady': - {'offset': 2, - '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_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'}, - '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}} - - - 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) - - 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 8415cbeddc..0000000000 --- a/sonic_sfp/sff8472.py +++ /dev/null @@ -1,1050 +0,0 @@ -#! /usr/bin/env python -#-------------------------------------------------------------------------- -# -# Copyright 2012 Cumulus Networks, inc all rights reserved -# -#-------------------------------------------------------------------------- -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 - from sffbase import sffbase -except ImportError, 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}}}} - - type_of_transceiver = {'00':'Unknown', - '01':'GBIC', - '02': 'Module soldered to motherboard', - '03': 'SFP or SFP Plus', - '04': '300 pin XBI', - '05': 'XENPAK', - '06': 'XFP', - '07': 'XFF', - '08': 'XFP-E', - '09': 'XPAK', - '0a': 'X2', - '0b': 'DWDM-SFP', - '0d': 'QSFP'} - - 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':20, - 'size':3, - 'type' : 'str'}, - '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'}} - - # 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) - - 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, 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, 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, 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, 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, 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}} - - - 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) - - - 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 55b5a734d3..0000000000 --- a/sonic_sfp/sffbase.py +++ /dev/null @@ -1,250 +0,0 @@ -#! /usr/bin/env python -#---------------------------------------------------------------------------- -# sffbase class for sff8436 and sff8472 -#---------------------------------------------------------------------------- - -try: - import fcntl - import struct - import sys - import time - import binascii - import os - import getopt - import types - from math import log10 -except ImportError, 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, 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, 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 d8e522b140..0000000000 --- a/sonic_sfp/sfputilbase.py +++ /dev/null @@ -1,608 +0,0 @@ -# sfputilbase.py -# -# Base class for creating platform-specific SFP transceiver interfaces for SONiC -# - -try: - import abc - import binascii - import os - import re - import bcmshell - from sonic_eeprom import eeprom_dts - from sff8472 import sff8472InterfaceId - from sff8472 import sff8472Dom - from sff8436 import sff8436InterfaceId - from sff8436 import sff8436Dom -except ImportError as e: - raise ImportError("%s - required module not found" % str(e)) - - -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): - """ Ending index of physical port range """ - pass - - @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, 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 - print devaddr > sysfs_nd_path - - # Write device address to delete_device file - nd_file = open(sysfs_nd_path, "w") - nd_file.write(devaddr) - nd_file.close() - except Exception, 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: - sysfsfile = open(sysfs_sfp_i2c_client_eeprompath, "rb") - sysfsfile.seek(offset) - sysfsfile.read(1) - except IOError: - return False - except: - return False - else: - return True - - # Read eeprom - def _read_eeprom_devid(self, port_num, devid, offset): - sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter" - eeprom_raw = [] - num_bytes = 256 - - for i in range(0, num_bytes): - eeprom_raw.append("0x00") - - 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 - - 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, "rb") - 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 - - try: - sysfsfile_eeprom.close() - except: - return 0 - - 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. - # XXX: move the porttab - # parsing stuff to a separate module, or reuse - # if something already exists - for line in f: - line.strip() - if re.search("^#", line) is not None: - 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 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) - - if (fp_port_index - last_fp_port_index) > 1: - # last port was a gang port - for p in range(last_fp_port_index+1, fp_port_index): - logical_to_physical[last_portname].append(p) - if physical_to_logical.get(p) is None: - physical_to_logical[p] = [last_portname] - else: - physical_to_logical[p].append(last_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[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): - # Read interface id EEPROM at addr 0x50 - return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, 0) - - def get_eeprom_dom_raw(self, port_num): - 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.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 - - 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 - - @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