Merge branch 'master' into platform2.0_s6100

This commit is contained in:
Arun Saravanan Balachandran 2019-09-09 12:45:07 +05:30 committed by GitHub
commit 4bad5eabb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
155 changed files with 24658 additions and 1637 deletions

View File

@ -227,18 +227,24 @@ init :
@git submodule update --init --recursive
@git submodule foreach --recursive '[ -f .git ] && echo "gitdir: $$(realpath --relative-to=. $$(cut -d" " -f2 .git))" > .git'
.ONESHELL : reset
reset :
@echo && echo -n "Warning! All local changes will be lost. Proceed? [y/N]: "
@read ans && \
if [ $$ans == y ]; then \
echo "Resetting local repository. Please wait..."; \
$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) sudo rm -rf fsroot; \
git clean -xfdf; \
git reset --hard; \
git submodule foreach --recursive git clean -xfdf; \
git submodule foreach --recursive git reset --hard; \
git submodule update --init --recursive; \
echo "Reset complete!"; \
else \
echo "Reset aborted"; \
fi
@read ans && (
if [ $$ans == y ]; then
echo "Resetting local repository. Please wait...";
$(DOCKER_RUN) $(SLAVE_IMAGE):$(SLAVE_TAG) sudo rm -rf fsroot;
if [[ "$(CONFIGURED_ARCH)" == "armhf" || "$(CONFIGURED_ARCH)" == "arm64" ]]; then
echo "Stopping march $(CONFIGURED_ARCH) docker"
sudo kill -9 `sudo cat /var/run/march/docker.pid` || true
sudo rm -f /var/run/march/docker.pid || true
fi
git clean -xfdf;
git reset --hard;
git submodule foreach --recursive git clean -xfdf;
git submodule foreach --recursive git reset --hard;
git submodule update --init --recursive;
echo "Reset complete!";
else
echo "Reset aborted";
fi )

View File

@ -51,6 +51,11 @@ Install pip and jinja in host build machine, execute below commands if j2/j2cli
sudo pip install --force-reinstall --upgrade jinja2>=2.10
sudo pip install j2cli
Configure your system to allow running the 'docker' command without 'sudo':
Add current user to the docker group
`sudo gpasswd -a ${USER} docker`
Log out and log back in so that your group membership is re-evaluated
## SAI Version
Please refer to [SONiC roadmap](https://github.com/Azure/SONiC/wiki/Sonic-Roadmap-Planning) on the SAI version for each SONiC release.

View File

@ -31,7 +31,12 @@ set -x -e
CONFIGURED_ARCH=$([ -f .arch ] && cat .arch || echo amd64)
## docker engine version (with platform)
DOCKER_VERSION=5:18.09.8~3-0~debian-stretch
if [[ $CONFIGURED_ARCH == armhf || $CONFIGURED_ARCH == arm64 ]]; then
# Version name differs between ARCH, copying same version as in sonic-slave docker
DOCKER_VERSION=18.06.3~ce~3-0~debian
else
DOCKER_VERSION=5:18.09.8~3-0~debian-stretch
fi
LINUX_KERNEL_VERSION=4.9.0-9-2
## Working directory to prepare the file system
@ -458,6 +463,14 @@ build_number: ${BUILD_NUMBER:-0}
built_by: $USER@$BUILD_HOSTNAME
EOF
## Copy ASIC config checksum
python files/build_scripts/generate_asic_config_checksum.py
if [[ ! -f './asic_config_checksum' ]]; then
echo 'asic_config_checksum not found'
exit 1
fi
sudo cp ./asic_config_checksum $FILESYSTEM_ROOT/etc/sonic/asic_config_checksum
if [ -f sonic_debian_extension.sh ]; then
./sonic_debian_extension.sh $FILESYSTEM_ROOT $PLATFORM_DIR
fi
@ -488,10 +501,7 @@ then
sudo LANG=C chroot $FILESYSTEM_ROOT /bin/bash -c "echo '/debug is mounted in each docker' >> /etc/motd"
sudo mkdir -p $FILESYSTEM_ROOT/src
pushd src
../scripts/dbg_files.sh | sudo tar -cvzf ../$FILESYSTEM_ROOT/src/sonic_src.tar.gz -T -
popd
sudo cp $DEBUG_SRC_ARCHIVE_FILE $FILESYSTEM_ROOT/src/
sudo mkdir -p $FILESYSTEM_ROOT/debug
fi

View File

@ -0,0 +1,33 @@
# name lanes alias index speed
Ethernet0 73,74,75,76,77,78,79,80 fourHundredGigE1 0 400000
Ethernet4 65,66,67,68,69,70,71,72 fourHundredGigE2 1 400000
Ethernet8 81,82,83,84,85,86,87,88 fourHundredGigE3 2 400000
Ethernet12 89,90,91,92,93,94,95,96 fourHundredGigE4 3 400000
Ethernet16 97,98,99,100,101,102,103,104 fourHundredGigE5 4 400000
Ethernet20 105,106,107,108,109,110,111,112 fourHundredGigE6 5 400000
Ethernet24 113,114,115,116,117,118,119,120 fourHundredGigE7 6 400000
Ethernet28 121,122,123,124,125,126,127,128 fourHundredGigE8 7 400000
Ethernet32 41,42,43,44,45,46,47,48 fourHundredGigE9 8 400000
Ethernet36 33,34,35,36,37,38,39,40 fourHundredGigE10 9 400000
Ethernet40 49,50,51,52,53,54,55,56 fourHundredGigE11 10 400000
Ethernet44 57,58,59,60,61,62,63,64 fourHundredGigE12 11 400000
Ethernet48 129,130,131,132,133,134,135,136 fourHundredGigE13 12 400000
Ethernet52 137,138,139,140,141,142,143,144 fourHundredGigE14 13 400000
Ethernet56 145,146,147,148,149,150,151,152 fourHundredGigE15 14 400000
Ethernet60 153,154,155,156,157,158,159,160 fourHundredGigE16 15 400000
Ethernet64 169,170,171,172,173,174,175,176 fourHundredGigE17 16 400000
Ethernet68 161,162,163,164,165,166,167,168 fourHundredGigE18 17 400000
Ethernet72 177,178,179,180,181,182,183,184 fourHundredGigE19 18 400000
Ethernet76 185,186,187,188,189,190,191,192 fourHundredGigE20 19 400000
Ethernet80 1,2,3,4,5,6,7,8 fourHundredGigE21 20 400000
Ethernet84 9,10,11,12,13,14,15,16 fourHundredGigE22 21 400000
Ethernet88 17,18,19,20,21,22,23,24 fourHundredGigE23 22 400000
Ethernet92 25,26,27,28,29,30,31,32 fourHundredGigE24 23 400000
Ethernet96 201,202,203,204,205,206,207,208 fourHundredGigE25 24 400000
Ethernet100 193,194,195,196,197,198,199,200 fourHundredGigE26 25 400000
Ethernet104 217,218,219,220,221,222,223,224 fourHundredGigE27 26 400000
Ethernet108 209,210,211,212,213,214,215,216 fourHundredGigE28 27 400000
Ethernet112 233,234,235,236,237,238,239,240 fourHundredGigE29 28 400000
Ethernet116 225,226,227,228,229,230,231,232 fourHundredGigE30 29 400000
Ethernet120 249,250,251,252,253,254,255,256 fourHundredGigE31 30 400000
Ethernet124 241,242,243,244,245,246,247,248 fourHundredGigE32 31 400000

View File

@ -0,0 +1 @@
SAI_INIT_CONFIG_FILE=/etc/bcm/th3-as9716-32x400G.config.bcm

View File

@ -0,0 +1 @@
Accton-AS9716-32D t1

View File

@ -0,0 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=115200
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="pcie_aspm=off"

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
try:
import exceptions
import binascii
import time
import optparse
import warnings
import os
import sys
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
import subprocess
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/sys/bus/i2c/devices/0-0056/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,61 @@
#!/usr/bin/env python
#############################################################################
# Accton
#
# Module contains an implementation of SONiC PSU Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
import os.path
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
def __init__(self):
PsuBase.__init__(self)
self.psu_path = "/sys/bus/i2c/devices/"
self.psu_presence = "/psu_present"
self.psu_oper_status = "/psu_power_good"
self.psu_mapping = {
2: "10-0051",
1: "9-0050",
}
def get_num_psus(self):
return len(self.psu_mapping)
def get_psu_status(self, index):
if index is None:
return False
status = 0
node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status
try:
with open(node, 'r') as power_status:
status = int(power_status.read())
except IOError:
return False
return status == 1
def get_psu_presence(self, index):
if index is None:
return False
status = 0
node = self.psu_path + self.psu_mapping[index] + self.psu_presence
try:
with open(node, 'r') as presence_status:
status = int(presence_status.read())
except IOError:
return False
return status == 1

View File

@ -0,0 +1,150 @@
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 0
PORT_END = 33
PORTS_IN_BLOCK = 34
BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/"
BASE_CPLD1_PATH = "/sys/bus/i2c/devices/20-0061/"
BASE_CPLD2_PATH = "/sys/bus/i2c/devices/21-0062/"
_port_to_is_present = {}
_port_to_lp_mode = {}
_port_to_eeprom_mapping = {}
_port_to_i2c_mapping = {
0: [1, 25],
1: [2, 26],
2: [3, 27],
3: [4, 28],
4: [5, 29],
5: [6, 30],
6: [7, 31],
7: [8, 32],
8: [9, 33],
9: [10, 34],
10: [11, 35],
11: [12, 36],
12: [13, 37],
13: [14, 38],
14: [15, 39],
15: [16, 40],
16: [17, 41],
17: [18, 42],
18: [19, 43],
19: [20, 44],
20: [21, 45],
21: [22, 46],
22: [23, 47],
23: [24, 48],
24: [25, 49],
25: [26, 50],
26: [27, 51],
27: [28, 52],
28: [29, 53],
29: [30, 54],
30: [31, 55],
31: [32, 56],
32: [33, 57],
33: [34, 58],
}
@property
def port_start(self):
return self.PORT_START
@property
def port_end(self):
return self.PORT_END
@property
def qsfp_ports(self):
return range(self.PORT_START, self.PORTS_IN_BLOCK + 1)
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
def __init__(self):
eeprom_path = self.BASE_OOM_PATH + "eeprom"
for x in range(0, self.port_end+1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(
self._port_to_i2c_mapping[x][1]
)
SfpUtilBase.__init__(self)
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
if port_num < 16 :
present_path = self.BASE_CPLD1_PATH + "module_present_" + str(port_num+1)
else:
present_path = self.BASE_CPLD2_PATH + "module_present_" + str(port_num+1)
self.__port_to_is_present = present_path
try:
val_file = open(self.__port_to_is_present)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
content = val_file.readline().rstrip()
val_file.close()
if content == "1":
return True
return False
def get_low_power_mode(self, port_num):
raise NotImplementedError
def set_low_power_mode(self, port_num, lpmode):
raise NotImplementedError
def reset(self, port_num):
if port_num < self.port_start or port_num > self.port_end:
return False
if port_num < 16 :
mod_rst_path = self.BASE_CPLD1_PATH + "module_reset_" + str(port_num+1)
else:
mod_rst_path = self.BASE_CPLD2_PATH + "module_reset_" + str(port_num+1)
self.__port_to_mod_rst = mod_rst_path
try:
reg_file = open(self.__port_to_mod_rst, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_value = '1'
reg_file.write(reg_value)
reg_file.close()
return True
def get_transceiver_change_event(self):
"""
TODO: This function need to be implemented
when decide to support monitoring SFP(Xcvrd)
on this platform.
"""
raise NotImplementedError

View File

@ -0,0 +1,4 @@
{
"skip_ledd": true
}

View File

@ -815,3 +815,37 @@ serdes_core_tx_polarity_flip_physical{233}=0x36
serdes_core_tx_polarity_flip_physical{241}=0xc6
serdes_core_tx_polarity_flip_physical{249}=0xc3
serdes_core_tx_polarity_flip_physical{257}=0x0
serdes_tx_taps_cd0=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd1=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd2=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd3=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd4=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd5=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd6=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd7=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd8=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd9=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd10=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd11=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd12=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd13=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd14=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd15=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd16=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd17=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd18=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd19=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd20=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd21=pam4:-28:124:0:4:0:0
serdes_tx_taps_cd22=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd23=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd24=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd25=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd26=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd27=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd28=pam4:-28:120:-4:4:0:0
serdes_tx_taps_cd29=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd30=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd31=pam4:-28:124:-12:4:0:0
serdes_tx_taps_cd32=pam4:1:34:9:0:0:0
serdes_tx_taps_cd33=pam4:1:34:9:0:0:0

View File

@ -22,13 +22,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -22,13 +22,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -23,13 +23,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -9,6 +9,9 @@ try:
import sys
import errno
import datetime
import logging
import logging.config
import yaml
sys.path.append(os.path.dirname(__file__))
import pltfm_mgr_rpc
@ -71,13 +74,17 @@ transport = None
pltfm_mgr = None
EEPROM_SYMLINK = "/var/run/platform/eeprom/syseeprom"
EEPROM_STATUS = "/var/run/platform/eeprom/status"
class board(eeprom_tlvinfo.TlvInfoDecoder):
RETRIES = 30
RETRIES = 3
def __init__(self, name, path, cpld_root, ro):
with open(os.path.dirname(__file__) + "/logging.conf", 'r') as f:
config_dict = yaml.load(f)
logging.config.dictConfig(config_dict)
if not os.path.exists(os.path.dirname(EEPROM_SYMLINK)):
try:
os.makedirs(os.path.dirname(EEPROM_SYMLINK))
@ -86,19 +93,17 @@ class board(eeprom_tlvinfo.TlvInfoDecoder):
raise
open(EEPROM_SYMLINK, 'a').close()
f = open(EEPROM_STATUS, 'w')
f.write("initializing..")
f.close()
self.eeprom_path = EEPROM_SYMLINK
super(board, self).__init__(self.eeprom_path, 0, '', True)
super(board, self).__init__(self.eeprom_path, 0, EEPROM_STATUS, True)
for attempt in range(self.RETRIES + 1):
if not self.eeprom_init():
time.sleep(1)
else:
for attempt in range(self.RETRIES):
if self.eeprom_init() or (attempt + 1 >= self.RETRIES):
break
if attempt == self.RETRIES:
raise RuntimeError("Could not initialize syseeprom")
time.sleep(1)
def thrift_setup(self):
global thrift_server, transport, pltfm_mgr
@ -119,13 +124,18 @@ class board(eeprom_tlvinfo.TlvInfoDecoder):
def eeprom_init(self):
global pltfm_mgr
try:
self.thrift_setup()
eeprom = pltfm_mgr.pltfm_mgr_sys_eeprom_get()
self.thrift_teardown()
self.thrift_setup()
eeprom = pltfm_mgr.pltfm_mgr_sys_eeprom_get()
self.thrift_teardown()
except:
return False
f = open(EEPROM_STATUS, 'w')
f.write("ok")
f.close()
eeprom_params = ""
for attr, val in eeprom.__dict__.iteritems():
if val is None:

View File

@ -0,0 +1,17 @@
version: 1
disable_existing_loggers: False
formatters:
simple:
format: '%(asctime)s %(name)-30s %(levelname)-7s %(message)s'
handlers:
file:
class: logging.handlers.RotatingFileHandler
formatter: simple
filename: /var/log/platform.log
root:
level: ERROR
handlers:
- file

View File

@ -34,6 +34,7 @@ class SfpUtil(SfpUtilBase):
QSFP_PORT_START = 1
QSFP_PORT_END = 0
EEPROM_OFFSET = 0
QSFP_CHECK_INTERVAL = 4
@property
def port_start(self):
@ -56,6 +57,11 @@ class SfpUtil(SfpUtilBase):
raise Exception()
def __init__(self):
self.ready = False
self.phy_port_dict = {'-1': 'system_not_ready'}
self.phy_port_cur_state = {}
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
if not os.path.exists(os.path.dirname(SFP_EEPROM_CACHE)):
try:
os.makedirs(os.path.dirname(SFP_EEPROM_CACHE))
@ -142,12 +148,76 @@ class SfpUtil(SfpUtilBase):
self.thrift_teardown()
return status
def check_transceiver_change(self):
if not self.ready:
return
self.phy_port_dict = {}
try:
self.thrift_setup()
except:
return
# Get presence of each SFP
for port in range(self.port_start, self.port_end + 1):
try:
sfp_resent = pltfm_mgr.pltfm_mgr_qsfp_presence_get(port)
except:
sfp_resent = False
sfp_state = '1' if sfp_resent else '0'
if port in self.phy_port_cur_state:
if self.phy_port_cur_state[port] != sfp_state:
self.phy_port_dict[port] = sfp_state
else:
self.phy_port_dict[port] = sfp_state
# Update port current state
self.phy_port_cur_state[port] = sfp_state
self.thrift_teardown()
def get_transceiver_change_event(self, timeout=0):
phy_port_dict = {}
status = True
# TODO: Process transceiver plug-in/out event
time.sleep(1)
return status, phy_port_dict
forever = False
if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
print "get_transceiver_change_event:Invalid timeout value", timeout
return False, {}
while forever or timeout > 0:
if not self.ready:
try:
self.thrift_setup()
self.thrift_teardown()
except:
pass
else:
self.ready = True
self.phy_port_dict = {}
break
elif self.qsfp_interval == 0:
self.qsfp_interval = self.QSFP_CHECK_INTERVAL
# Process transceiver plug-in/out event
self.check_transceiver_change()
# Break if tranceiver state has changed
if bool(self.phy_port_dict):
break
if timeout:
timeout -= 1
if self.qsfp_interval:
self.qsfp_interval -= 1
time.sleep(1)
return self.ready, self.phy_port_dict
def _get_port_eeprom_path(self, port_num, devid):
eeprom_path = None

View File

@ -23,13 +23,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -1,7 +1,7 @@
# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=2
DEVPATH=hwmon3=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-23/23-004d hwmon2=devices/pci0000:00/0000:00:13.0/i2c-0/i2c-8/i2c-11/11-001a
DEVNAME=hwmon3=emc2305 hwmon2=max6697
DEVNAME=hwmon3=emc2305 hwmon2=max6699
FCTEMPS=hwmon3/device/pwm1=hwmon2/temp1_input hwmon3/device/pwm2=hwmon2/temp1_input hwmon3/device/pwm4=hwmon2/temp1_input
FCFANS=hwmon3/device/pwm1=hwmon3/device/fan1_input hwmon3/device/pwm2=hwmon3/device/fan2_input hwmon3/device/pwm4=hwmon3/device/fan4_input
MINTEMP=hwmon3/device/pwm1=27 hwmon3/device/pwm2=27 hwmon3/device/pwm4=27

View File

@ -0,0 +1,2 @@
__all__ = ["platform", "chassis"]
from sonic_platform import *

View File

@ -26,13 +26,16 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN = 3
NUM_FAN_TRAY = 3
NUM_FAN = 1
NUM_PSU = 2
NUM_THERMAL = 7
NUM_SFP = 52
RESET_REGISTER = "0x112"
REBOOT_CAUSE_PATH = "/host/reboot-cause/previous-reboot-cause.txt"
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/previous-reboot-cause.txt"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/previous-reboot-cause.txt"
COMPONENT_NAME_LIST = ["SMC_CPLD", "MMC_CPLD", "BIOS"]
HOST_CHK_CMD = "docker > /dev/null 2>&1"
class Chassis(ChassisBase):
@ -40,9 +43,10 @@ class Chassis(ChassisBase):
def __init__(self):
self.config_data = {}
for index in range(0, NUM_FAN):
fan = Fan(index)
self._fan_list.append(fan)
for fant_index in range(0, NUM_FAN_TRAY):
for fan_index in range(0, NUM_FAN):
fan = Fan(fant_index, fan_index)
self._fan_list.append(fan)
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
@ -53,17 +57,23 @@ class Chassis(ChassisBase):
sfp = Sfp(index)
self._sfp_list.append(sfp)
ChassisBase.__init__(self)
self._reboot_cause_path = HOST_REBOOT_CAUSE_PATH if self.__is_host(
) else PMON_REBOOT_CAUSE_PATH
self._component_name_list = COMPONENT_NAME_LIST
self._watchdog = Watchdog()
self._eeprom = Tlv()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
raise IOError("Unable to open %s file !" % file_path)
pass
return None
def get_base_mac(self):
"""
@ -137,14 +147,15 @@ class Chassis(ChassisBase):
description = 'None'
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
hw_reboot_cause = self.component.get_register_value(RESET_REGISTER)
sw_reboot_cause = self.__read_txt_file(REBOOT_CAUSE_PATH)
sw_reboot_cause = self.__read_txt_file(
self._reboot_cause_path) or "Unknown"
if sw_reboot_cause != "Unexpected reboot":
if hw_reboot_cause == "0x55":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = sw_reboot_cause
elif hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
elif hw_reboot_cause == "0x33" or hw_reboot_cause == "0x55":
elif hw_reboot_cause == "0x33":
reboot_cause = self.REBOOT_CAUSE_WATCHDOG
else:
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER

View File

@ -17,34 +17,50 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
EMC2305_FAN_PATH = "/sys/bus/i2c/drivers/emc2305/"
EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/"
FAN_PATH = "/sys/devices/platform/e1031.smc/"
SYS_GPIO_DIR = "/sys/class/gpio"
EMC2305_MAX_PWM = 255
EMC2305_FAN_PWM = "pwm{}"
EMC2305_FAN_TARGET = "fan{}_target"
EMC2305_FAN_INPUT = "pwm{}"
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3"]
PSU_FAN_MAX_RPM = 11000
PSU_HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon"
PSU_I2C_MAPPING = {
0: {
"num": 13,
"addr": "5b"
},
1: {
"num": 12,
"addr": "5a"
},
}
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_index):
self.index = fan_index
self.config_data = {}
self.fan_speed = 0
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
self.is_psu_fan = is_psu_fan
if self.is_psu_fan:
self.psu_index = psu_index
self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"]
self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"]
self.psu_hwmon_path = PSU_HWMON_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
# e1031 fan attributes
# Single emc2305 chip located at i2c-23-4d
# to control a fan module
self.e1031_emc2305_chip = [
self.emc2305_chip_mapping = [
{
'device': "23-004d",
'index_map': [1, 2, 4]
}
]
self.fan_e1031_presence = "fan{}_prs"
self.fan_e1031_direction = "fan{}_dir"
self.fan_e1031_led = "fan{}_led"
@ -55,84 +71,103 @@ class Fan(FanBase):
}
FanBase.__init__(self)
def get_direction(self):
direction = self.FAN_DIRECTION_INTAKE
def __read_txt_file(self, file_path):
try:
fan_direction_file = (FAN_PATH +
self.fan_e1031_direction.format(self.index+1))
with open(fan_direction_file, 'r') as file:
raw = file.read().strip('\r\n')
if str(raw).upper() == "F2B":
direction = self.FAN_DIRECTION_INTAKE
else:
direction = self.FAN_DIRECTION_EXHAUST
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return ""
def __write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except:
return False
return True
def __search_file_by_name(self, directory, file_name):
for dirpath, dirnames, files in os.walk(directory):
for name in files:
file_path = os.path.join(dirpath, name)
if name in file_name:
return file_path
return None
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
direction = self.FAN_DIRECTION_EXHAUST
if not self.is_psu_fan:
fan_direction_file = (FAN_PATH +
self.fan_e1031_direction.format(self.fan_tray_index+1))
raw = self.__read_txt_file(fan_direction_file).strip('\r\n')
direction = self.FAN_DIRECTION_INTAKE if str(
raw).upper() == "F2B" else self.FAN_DIRECTION_EXHAUST
return direction
def get_speed(self):
"""
E1031 platform specific data:
Retrieves the speed of fan as a percentage of full speed
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed = pwm_in/255*100
"""
# TODO: Seperate PSU's fan and main fan class
if self.fan_speed != 0:
return self.fan_speed
else:
speed = 0
pwm = []
emc2305_chips = self.e1031_emc2305_chip
speed = 0
if self.is_psu_fan:
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
self.psu_hwmon_path, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
elif self.get_presence():
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
pwm = int(raw, 10) if raw else 0
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
speed = math.ceil(
float(pwm[0]) * 100 / EMC2305_MAX_PWM)
return int(speed)
return int(speed)
def get_target_speed(self):
"""
E1031 platform specific data:
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
target = 0
pwm = []
emc2305_chips = self.e1031_emc2305_chip
for chip in emc2305_chips:
if not self.is_psu_fan:
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_TARGET)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
target = pwm[0] * 100 / EMC2305_MAX_PWM
EMC2305_PATH, device, EMC2305_FAN_TARGET)
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
pwm = int(raw, 10) if raw else 0
target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM)
return target
@ -147,40 +182,50 @@ class Fan(FanBase):
def set_speed(self, speed):
"""
Depends on pwm or target mode is selected:
Sets the fan speed
Args:
speed: An integer, the percentage of full fan speed to set fan to,
in the range 0 (off) to 100 (full speed)
Returns:
A boolean, True if speed is set successfully, False if not
Note:
Depends on pwm or target mode is selected:
1) pwm = speed_pc * 255 <-- Currently use this mode.
2) target_pwm = speed_pc * 100 / 255
2.1) set pwm{}_enable to 3
"""
pwm = speed * 255 / 100
emc2305_chips = self.e1031_emc2305_chip
for chip in emc2305_chips:
if not self.is_psu_fan and self.get_presence():
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_FAN_PATH, device, EMC2305_FAN_PWM)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'w') as file:
file.write(str(int(pwm)))
except IOError:
return False
EMC2305_PATH, device, EMC2305_FAN_PWM)
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
return self.__write_txt_file(sysfs_path, int(pwm))
return True
return False
def set_status_led(self, color):
try:
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
set_status_led = False
if not self.is_psu_fan:
fan_led_file = (FAN_PATH +
self.fan_e1031_led.format(self.index+1))
with open(fan_led_file, 'r') as file:
file.write(self.fan_e1031_led_col_map[color])
except IOError:
return False
self.fan_e1031_led.format(self.fan_tray_index+1))
return True
set_status_led = self.__write_txt_file(
fan_led_file, self.fan_e1031_led_col_map[color]) if self.get_presence() else False
return set_status_led
def get_name(self):
"""
@ -188,7 +233,10 @@ class Fan(FanBase):
Returns:
string: The name of the device
"""
return FAN_NAME_LIST[self.index]
fan_name = FAN_NAME_LIST[self.fan_tray_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format(
self.psu_index+1, self.fan_index+1)
return fan_name
def get_presence(self):
"""
@ -196,13 +244,8 @@ class Fan(FanBase):
Returns:
bool: True if PSU is present, False if not
"""
fan_direction_file = (FAN_PATH +
self.fan_e1031_presence.format(self.fan_tray_index+1))
present_str = self.__read_txt_file(fan_direction_file) or '1'
try:
fan_direction_file = (FAN_PATH +
self.fan_e1031_presence.format(self.index+1))
with open(fan_direction_file, 'r') as file:
present = int(file.read().strip('\r\n'))
except IOError:
return False
return present == 0
return int(present_str) == 0 if not self.is_psu_fan else True

View File

@ -18,8 +18,20 @@ except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_E1031_SPEED_PATH = "/sys/class/hwmon/hwmon{}/fan1_input"
HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon"
FAN_MAX_RPM = 11000
PSU_NAME_LIST = ["PSU-R", "PSU-L"]
PSU_NUM_FAN = [1, 1]
PSU_I2C_MAPPING = {
0: {
"num": 13,
"addr": "5b"
},
1: {
"num": 12,
"addr": "5a"
},
}
class Psu(PsuBase):
@ -31,26 +43,109 @@ class Psu(PsuBase):
self.psu_path = "/sys/devices/platform/e1031.smc/"
self.psu_presence = "psu{}_prs"
self.psu_oper_status = "psu{}_status"
self.i2c_num = PSU_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr)
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
PsuBase.__init__(self)
def get_fan(self):
"""
Retrieves object representing the fan module contained in this PSU
Returns:
An object dervied from FanBase representing the fan module
contained in this PSU
"""
fan_speed_path = FAN_E1031_SPEED_PATH.format(
str(self.index+3))
def __read_txt_file(self, file_path):
try:
with open(fan_speed_path) as fan_speed_file:
fan_speed_rpm = int(fan_speed_file.read())
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
fan_speed = 0
pass
return ""
fan_speed = float(fan_speed_rpm)/FAN_MAX_RPM * 100
fan = Fan(0)
fan.fan_speed = int(fan_speed) if int(fan_speed) <= 100 else 100
return fan
def __search_file_by_contain(self, directory, search_str, file_start):
for dirpath, dirnames, files in os.walk(directory):
for name in files:
file_path = os.path.join(dirpath, name)
if name.startswith(file_start) and search_str in self.__read_txt_file(file_path):
return file_path
return None
def get_voltage(self):
"""
Retrieves current PSU voltage output
Returns:
A float number, the output voltage in volts,
e.g. 12.1
"""
psu_voltage = 0.0
voltage_name = "in{}_input"
voltage_label = "vout1"
vout_label_path = self.__search_file_by_contain(
self.hwmon_path, voltage_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = filter(str.isdigit, basename)
vout_path = os.path.join(
dir_name, voltage_name.format(in_num))
vout_val = self.__read_txt_file(vout_path)
psu_voltage = float(vout_val) / 1000
return psu_voltage
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
psu_current = 0.0
current_name = "curr{}_input"
current_label = "iout1"
curr_label_path = self.__search_file_by_contain(
self.hwmon_path, current_label, "cur")
if curr_label_path:
dir_name = os.path.dirname(curr_label_path)
basename = os.path.basename(curr_label_path)
cur_num = filter(str.isdigit, basename)
cur_path = os.path.join(
dir_name, current_name.format(cur_num))
cur_val = self.__read_txt_file(cur_path)
psu_current = float(cur_val) / 1000
return psu_current
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts, e.g. 302.6
"""
psu_power = 0.0
current_name = "power{}_input"
current_label = "pout1"
pw_label_path = self.__search_file_by_contain(
self.hwmon_path, current_label, "power")
if pw_label_path:
dir_name = os.path.dirname(pw_label_path)
basename = os.path.basename(pw_label_path)
pw_num = filter(str.isdigit, basename)
pw_path = os.path.join(
dir_name, current_name.format(pw_num))
pw_val = self.__read_txt_file(pw_path)
psu_power = float(pw_val) / 1000000
return psu_power
def get_powergood_status(self):
"""
Retrieves the powergood status of PSU
Returns:
A boolean, True if PSU has stablized its output voltages and passed all
its internal self-tests, False if not.
"""
return self.get_status()
def set_status_led(self, color):
"""
@ -64,6 +159,15 @@ class Psu(PsuBase):
# Hardware not supported
return False
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
# Hardware not supported
return self.STATUS_LED_COLOR_OFF
def get_name(self):
"""
Retrieves the name of the device
@ -79,14 +183,10 @@ class Psu(PsuBase):
bool: True if PSU is present, False if not
"""
psu_location = ["R", "L"]
status = 0
try:
with open(self.psu_path + self.psu_presence.format(psu_location[self.index]), 'r') as psu_prs:
status = int(psu_prs.read())
except IOError:
return False
presences_status = self.__read_txt_file(
self.psu_path + self.psu_presence.format(psu_location[self.index])) or 0
return status == 1
return int(presences_status) == 1
def get_status(self):
"""
@ -95,11 +195,7 @@ class Psu(PsuBase):
A boolean value, True if device is operating properly, False if not
"""
psu_location = ["R", "L"]
status = 0
try:
with open(self.psu_path + self.psu_oper_status.format(psu_location[self.index]), 'r') as power_status:
status = int(power_status.read())
except IOError:
return False
power_status = self.__read_txt_file(
self.psu_path + self.psu_oper_status.format(psu_location[self.index])) or 0
return status == 1
return int(power_status) == 1

View File

@ -15,16 +15,65 @@ import sonic_device_util
from ctypes import create_string_buffer
try:
from swsssdk import ConfigDBConnector
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom
from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId
from sonic_platform_base.sonic_sfp.sff8472 import sffbase
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
INFO_OFFSET = 0
DOM_OFFSET = 256
class Sfp(SfpBase, SfpUtilBase):
XCVR_INTFACE_BULK_OFFSET = 0
XCVR_INTFACE_BULK_WIDTH_SFP = 21
XCVR_VENDOR_NAME_OFFSET = 20
XCVR_VENDOR_NAME_WIDTH = 16
XCVR_VENDOR_OUI_OFFSET = 37
XCVR_VENDOR_OUI_WIDTH = 3
XCVR_VENDOR_PN_OFFSET = 40
XCVR_VENDOR_PN_WIDTH = 16
XCVR_HW_REV_OFFSET = 56
XCVR_HW_REV_WIDTH_SFP = 4
XCVR_VENDOR_SN_OFFSET = 68
XCVR_VENDOR_SN_WIDTH = 16
XCVR_VENDOR_DATE_OFFSET = 84
XCVR_VENDOR_DATE_WIDTH = 8
XCVR_DOM_CAPABILITY_OFFSET = 92
XCVR_DOM_CAPABILITY_WIDTH = 1
# Offset for values in SFP eeprom
SFP_TEMPE_OFFSET = 96
SFP_TEMPE_WIDTH = 2
SFP_VOLT_OFFSET = 98
SFP_VOLT_WIDTH = 2
SFP_CHANNL_MON_OFFSET = 100
SFP_CHANNL_MON_WIDTH = 6
SFP_MODULE_THRESHOLD_OFFSET = 0
SFP_MODULE_THRESHOLD_WIDTH = 40
SFP_CHANNL_THRESHOLD_OFFSET = 112
SFP_CHANNL_THRESHOLD_WIDTH = 2
SFP_STATUS_CONTROL_OFFSET = 110
SFP_STATUS_CONTROL_WIDTH = 1
SFP_TX_DISABLE_HARD_BIT = 7
SFP_TX_DISABLE_SOFT_BIT = 6
sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)',
'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)',
'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)')
sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode',
'ESCONComplianceCodes', 'SONETComplianceCodes',
'EthernetComplianceCodes', 'FibreChannelLinkLength',
'FibreChannelTechnology', 'SFP+CableTechnology',
'FibreChannelTransmissionMedia', 'FibreChannelSpeed')
class Sfp(SfpBase):
"""Platform-specific Sfp class"""
# Port number
PORT_START = 1
PORT_END = 52
port_to_i2c_mapping = {
@ -33,50 +82,39 @@ class Sfp(SfpBase, SfpUtilBase):
51: 17,
52: 16
}
_sfp_port = range(49, PORT_END + 1)
PRS_PATH = "/sys/devices/platform/e1031.smc/SFP/sfp_modabs"
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
SFP_STATUS_CONTROL_OFFSET = 110
SFP_STATUS_CONTROL_WIDTH = 1
PMON_HWSKU_PATH = '/usr/share/sonic/hwsku'
HOST_CHK_CMD = "docker > /dev/null 2>&1"
_port_to_eeprom_mapping = {}
_sfp_port = range(49, PORT_END + 1)
PLATFORM = "x86_64-cel_e1031-r0"
HWSKU = "Celestica-E1031-T48S4"
SFP_EEPROM_TYPE_KEY = "TypeOfTransceiver"
SFP_EEPROM_HW_REV_KEY = "VendorRev"
SFP_EEPROM_MF_NAME_KEY = "VendorName"
SFP_EEPROM_MODEL_NAME_KEY = "VendorPN"
SFP_EEPROM_SERIAL_KEY = "VendorSN"
SFP_EEPROM_CONNECTOR_KEY = "Connector"
SFP_EEPROM_ENCODE_KEY = "EncodingCodes"
SFP_EEPROM_EXT_IDENT_KEY = "ExtIdentOfTypeOfTransceiver"
SFP_EEPROM_CABLE_KEY = "LengthCable(UnitsOfm)"
SFP_EEPROM_BIT_RATE_KEY = "NominalSignallingRate(UnitsOf100Mbd)"
SFP_EEPROM_SPEC_COM_KEY = "Specification compliance"
SFP_EEPROM_DATE_KEY = "VendorDataCode(YYYY-MM-DD Lot)"
SFP_EEPROM_OUI_KEY = "VendorOUI"
SFP_EEPROM_MON_DATA_KEY = "MonitorData"
SFP_EEPROM_TEMP_KEY = "Temperature"
SFP_EEPROM_VCC_KEY = "Vcc"
SFP_EEPROM_RX_PWR_KEY = "RXPower"
SFP_EEPROM_TX_PWR_KEY = "TXPower"
SFP_EEPROM_TX_BS_KEY = "TXBias"
SFP_EEPROM_STATUS_CON_KEY = "StatusControl"
def __init__(self, sfp_index):
# Init index
self.index = sfp_index
self.port_num = self.index + 1
@property
def port_start(self):
return self.PORT_START
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
self.port_to_eeprom_mapping = {}
for x in range(self.PORT_START, self.PORT_END + 1):
if x not in self._sfp_port:
self.port_to_i2c_mapping[x] = None
self.port_to_eeprom_mapping[x] = eeprom_path.format(
self.port_to_i2c_mapping[x])
@property
def port_end(self):
return self.PORT_END
self.info_dict_keys = ['type', 'hardwarerev', 'serialnum', 'manufacturename', 'modelname', 'Connector', 'encoding', 'ext_identifier',
'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui']
@property
def qsfp_ports(self):
return []
self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage',
'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power']
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning',
'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning']
SfpBase.__init__(self)
def _convert_string_to_num(self, value_str):
if "-inf" in value_str:
@ -98,64 +136,45 @@ class Sfp(SfpBase, SfpUtilBase):
else:
return 'N/A'
def get_low_power_mode(self, port_num):
raise NotImplementedError
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return ""
def set_low_power_mode(self, port_num, lpmode):
raise NotImplementedError
def __is_host(self):
return os.system(self.HOST_CHK_CMD) == 0
def get_transceiver_change_event(self, timeout=0):
raise NotImplementedError
def __get_path_to_port_config_file(self):
platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM])
hwsku_path = "/".join([platform_path, self.HWSKU]
) if self.__is_host() else self.PMON_HWSKU_PATH
return "/".join([hwsku_path, "port_config.ini"])
def __init__(self, sfp_index):
# Init SfpUtilBase
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
for x in range(self.PORT_START, self.PORT_END + 1):
if x not in self._sfp_port:
self.port_to_i2c_mapping[x] = None
self.port_to_eeprom_mapping[x] = eeprom_path.format(
self.port_to_i2c_mapping[x])
self.read_porttab_mappings(self.__get_path_to_port_config_file())
SfpUtilBase.__init__(self)
# Init index
self.index = sfp_index
self.port_num = self.index + 1
def __get_sysfsfile_eeprom(self):
def __read_eeprom_specific_bytes(self, offset, num_bytes):
sysfsfile_eeprom = None
eeprom_raw = []
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num]
try:
sysfsfile_eeprom = open(
sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0)
except IOError:
print("Error: reading sysfs file %s" %
sysfs_sfp_i2c_client_eeprom_path)
return sysfsfile_eeprom
sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
sysfsfile_eeprom.seek(offset)
raw = sysfsfile_eeprom.read(num_bytes)
for n in range(0, num_bytes):
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except:
pass
finally:
if sysfsfile_eeprom:
sysfsfile_eeprom.close()
def __get_path_to_port_config_file(self):
# Get platform and hwsku
machine_info = sonic_device_util.get_machine_info()
platform = sonic_device_util.get_platform_info(machine_info)
config_db = ConfigDBConnector()
config_db.connect()
data = config_db.get_table('DEVICE_METADATA')
try:
hwsku = data['localhost']['hwsku']
except KeyError:
hwsku = "Unknown"
# Load platform module from source
platform_path = "/".join([self.PLATFORM_ROOT_PATH, platform])
hwsku_path = "/".join([platform_path, hwsku])
# First check for the presence of the new 'port_config.ini' file
port_config_file_path = "/".join([hwsku_path, "port_config.ini"])
if not os.path.isfile(port_config_file_path):
# port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file
port_config_file_path = "/".join([hwsku_path, "portmap.ini"])
return port_config_file_path
return eeprom_raw
def get_transceiver_info(self):
"""
@ -181,44 +200,84 @@ class Sfp(SfpBase, SfpUtilBase):
vendor_oui |1*255VCHAR |vendor OUI
========================================================================
"""
transceiver_info_dict = dict()
# get eeprom data
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('interface'):
transceiver_info_data = self.eeprom_dict['interface'].get('data')
# check present status
sfpi_obj = sff8472InterfaceId()
if not self.get_presence() or not sfpi_obj:
return {}
# set specification_compliance
spec_com = transceiver_info_data.get(
self.SFP_EEPROM_SPEC_COM_KEY, {})
spec_com_str = "/".join(list(spec_com.values()))
offset = INFO_OFFSET
# set normal transceiver info
transceiver_info_dict['type'] = transceiver_info_data.get(
self.SFP_EEPROM_TYPE_KEY, 'N/A')
transceiver_info_dict['hardwarerev'] = transceiver_info_data.get(
self.SFP_EEPROM_HW_REV_KEY, 'N/A')
transceiver_info_dict['manufacturename'] = transceiver_info_data.get(
self.SFP_EEPROM_MF_NAME_KEY, 'N/A')
transceiver_info_dict['modelname'] = transceiver_info_data.get(
self.SFP_EEPROM_MODEL_NAME_KEY, 'N/A')
transceiver_info_dict['serialnum'] = transceiver_info_data.get(
self.SFP_EEPROM_SERIAL_KEY, 'N/A')
transceiver_info_dict['Connector'] = transceiver_info_data.get(
self.SFP_EEPROM_CONNECTOR_KEY, 'N/A')
transceiver_info_dict['encoding'] = transceiver_info_data.get(
self.SFP_EEPROM_ENCODE_KEY, 'N/A')
transceiver_info_dict['ext_identifier'] = transceiver_info_data.get(
self.SFP_EEPROM_EXT_IDENT_KEY, 'N/A')
transceiver_info_dict['cable_length'] = transceiver_info_data.get(
self.SFP_EEPROM_CABLE_KEY, 'N/A')
transceiver_info_dict['nominal_bit_rate'] = transceiver_info_data.get(
self.SFP_EEPROM_BIT_RATE_KEY, 'N/A')
transceiver_info_dict['vendor_date'] = transceiver_info_data.get(
self.SFP_EEPROM_DATE_KEY, 'N/A')
transceiver_info_dict['vendor_oui'] = transceiver_info_data.get(
self.SFP_EEPROM_OUI_KEY, 'N/A')
transceiver_info_dict['ext_rateselect_compliance'] = "N/A"
transceiver_info_dict['specification_compliance'] = spec_com_str or "N/A"
sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP)
sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(
sfp_interface_bulk_raw, 0)
sfp_vendor_name_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(
sfp_vendor_name_raw, 0)
sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(
sfp_vendor_pn_raw, 0)
sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP)
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(
sfp_vendor_rev_raw, 0)
sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(
sfp_vendor_sn_raw, 0)
sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH)
if sfp_vendor_oui_raw is not None:
sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(
sfp_vendor_oui_raw, 0)
sfp_vendor_date_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH)
sfp_vendor_date_data = sfpi_obj.parse_vendor_date(
sfp_vendor_date_raw, 0)
transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A')
compliance_code_dict = dict()
if sfp_interface_bulk_data:
transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value']
transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value']
transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value']
transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data[
'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A'
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A'
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A'
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A'
transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A'
transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[
'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A'
transceiver_info_dict['cable_type'] = "Unknown"
transceiver_info_dict['cable_length'] = "Unknown"
for key in sfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(
sfp_interface_bulk_data['data'][key]['value'])
for key in sfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['nominal_bit_rate'] = str(
sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value'])
return transceiver_info_dict
@ -230,60 +289,146 @@ class Sfp(SfpBase, SfpUtilBase):
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
RX LOS |BOOLEAN |RX lost-of-signal status,
| |True if has RX los, False if not.
TX FAULT |BOOLEAN |TX fault status,
| |True if has TX fault, False if not.
Reset status |BOOLEAN |reset status,
| |True if SFP in reset, False if not.
LP mode |BOOLEAN |low power mode status,
| |True in lp mode, False if not.
TX disable |BOOLEAN |TX disable status,
| |True TX disabled, False if not.
TX disabled channel |HEX |disabled TX channles in hex,
| |bits 0 to 3 represent channel 0
rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not.
tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not.
reset_status |BOOLEAN |reset status, True if SFP in reset, False if not.
lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not.
tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not.
tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0
| |to channel 3.
Temperature |INT |module temperature in Celsius
Voltage |INT |supply voltage in mV
TX bias |INT |TX Bias Current in mA
RX power |INT |received optical power in mW
TX power |INT |TX output power in mW
temperature |INT |module temperature in Celsius
voltage |INT |supply voltage in mV
tx<n>bias |INT |TX Bias Current in mA, n is the channel number,
| |for example, tx2bias stands for tx bias of channel 2.
rx<n>power |INT |received optical power in mW, n is the channel number,
| |for example, rx2power stands for rx power of channel 2.
tx<n>power |INT |TX output power in mW, n is the channel number,
| |for example, tx2power stands for tx power of channel 2.
========================================================================
"""
transceiver_bulk_status_dict = dict()
# get eeprom data
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('dom'):
transceiver_dom_data = self.eeprom_dict['dom'].get('data', {})
transceiver_dom_data_mmv = transceiver_dom_data.get(
self.SFP_EEPROM_MON_DATA_KEY)
# check present status
sfpd_obj = sff8472Dom()
if not self.get_presence() or not sfpd_obj:
return {}
# set normal transceiver bulk status
transceiver_bulk_status_dict['temperature'] = transceiver_dom_data_mmv.get(
self.SFP_EEPROM_TEMP_KEY, 'N/A')
transceiver_bulk_status_dict['voltage'] = transceiver_dom_data_mmv.get(
self.SFP_EEPROM_VCC_KEY, 'N/A')
transceiver_bulk_status_dict['rx1power'] = transceiver_dom_data_mmv.get(
self.SFP_EEPROM_RX_PWR_KEY, 'N/A')
transceiver_bulk_status_dict['rx2power'] = "N/A"
transceiver_bulk_status_dict['rx3power'] = "N/A"
transceiver_bulk_status_dict['rx4power'] = "N/A"
transceiver_bulk_status_dict['tx1bias'] = transceiver_dom_data_mmv.get(
self.SFP_EEPROM_TX_BS_KEY, 'N/A')
transceiver_bulk_status_dict['tx2bias'] = "N/A"
transceiver_bulk_status_dict['tx3bias'] = "N/A"
transceiver_bulk_status_dict['tx4bias'] = "N/A"
transceiver_bulk_status_dict['tx1power'] = transceiver_dom_data_mmv.get(
self.SFP_EEPROM_TX_PWR_KEY, 'N/A')
transceiver_bulk_status_dict['tx2power'] = "N/A"
transceiver_bulk_status_dict['tx3power'] = "N/A"
transceiver_bulk_status_dict['tx4power'] = "N/A"
eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET)
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
cal_type = sfpi_obj.get_calibration_type()
sfpd_obj._calibration_type = cal_type
for key in transceiver_bulk_status_dict:
transceiver_bulk_status_dict[key] = self._convert_string_to_num(
transceiver_bulk_status_dict[key])
offset = DOM_OFFSET
transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A')
dom_temperature_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH)
return transceiver_bulk_status_dict
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(
dom_temperature_raw, 0)
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
dom_voltage_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_voltage_data = sfpd_obj.parse_channel_monitor_params(
dom_channel_monitor_raw, 0)
transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value']
transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value']
transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value']
for key in transceiver_dom_info_dict:
transceiver_dom_info_dict[key] = self._convert_string_to_num(
transceiver_dom_info_dict[key])
transceiver_dom_info_dict['rx_los'] = self.get_rx_los()
transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault()
transceiver_dom_info_dict['reset_status'] = self.get_reset_status()
transceiver_dom_info_dict['lp_mode'] = self.get_lpmode()
return transceiver_dom_info_dict
def get_transceiver_threshold_info(self):
"""
Retrieves transceiver threshold info of this SFP
Returns:
A dict which contains following keys/values :
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius.
templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius.
temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius.
templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius.
vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV.
vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV.
vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV.
vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV.
rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm.
rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm.
rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm.
rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm.
txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm.
txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm.
txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm.
txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm.
txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA.
txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA.
txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA.
txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA.
========================================================================
"""
# check present status
sfpd_obj = sff8472Dom()
if not self.get_presence() and not sfpd_obj:
return {}
eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET)
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
cal_type = sfpi_obj.get_calibration_type()
sfpd_obj._calibration_type = cal_type
offset = DOM_OFFSET
transceiver_dom_threshold_info_dict = dict.fromkeys(
self.threshold_dict_keys, 'N/A')
dom_module_threshold_raw = self.__read_eeprom_specific_bytes(
(offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH)
if dom_module_threshold_raw is not None:
dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(
dom_module_threshold_raw, 0)
transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value']
transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value']
transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value']
transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value']
transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value']
transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value']
transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data[
'data']['VoltageHighWarning']['value']
transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value']
transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value']
transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value']
transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value']
transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value']
transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value']
transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value']
transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value']
transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value']
transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value']
transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value']
transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value']
transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value']
for key in transceiver_dom_threshold_info_dict:
transceiver_dom_threshold_info_dict[key] = self._convert_string_to_num(
transceiver_dom_threshold_info_dict[key])
return transceiver_dom_threshold_info_dict
def get_reset_status(self):
"""
@ -292,7 +437,7 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if reset enabled, False if disabled
"""
# SFP doesn't support this feature
return NotImplementedError
return False
def get_rx_los(self):
"""
@ -302,14 +447,12 @@ class Sfp(SfpBase, SfpUtilBase):
Note : RX LOS status is latched until a call to get_rx_los or a reset.
"""
rx_los = False
rx_los_key = "RXLOSState"
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('dom'):
transceiver_dom_data = self.eeprom_dict['dom'].get('data', {})
transceiver_dom_data_sc = transceiver_dom_data.get(
self.SFP_EEPROM_STATUS_CON_KEY)
state = transceiver_dom_data_sc.get(rx_los_key)
rx_los = True if 'off' not in state.lower() else False
status_control_raw = self.__read_eeprom_specific_bytes(
SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
if status_control_raw:
data = int(status_control_raw[0], 16)
rx_los = (sffbase().test_bit(data, 1) != 0)
return rx_los
def get_tx_fault(self):
@ -320,14 +463,12 @@ class Sfp(SfpBase, SfpUtilBase):
Note : TX fault status is lached until a call to get_tx_fault or a reset.
"""
tx_fault = False
tx_fault_key = "TXFaultState"
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('dom'):
transceiver_dom_data = self.eeprom_dict['dom'].get('data', {})
transceiver_dom_data_sc = transceiver_dom_data.get(
self.SFP_EEPROM_STATUS_CON_KEY)
state = transceiver_dom_data_sc.get(tx_fault_key)
tx_fault = True if 'off' not in state.lower() else False
status_control_raw = self.__read_eeprom_specific_bytes(
SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
if status_control_raw:
data = int(status_control_raw[0], 16)
tx_fault = (sffbase().test_bit(data, 2) != 0)
return tx_fault
def get_tx_disable(self):
@ -337,14 +478,17 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if tx_disable is enabled, False if disabled
"""
tx_disable = False
tx_disable_key = "TXDisableState"
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('dom'):
transceiver_dom_data = self.eeprom_dict['dom'].get('data', {})
transceiver_dom_data_sc = transceiver_dom_data.get(
self.SFP_EEPROM_STATUS_CON_KEY)
state = transceiver_dom_data_sc.get(tx_disable_key)
tx_disable = True if 'off' not in state.lower() else False
tx_fault = False
status_control_raw = self.__read_eeprom_specific_bytes(
SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
if status_control_raw:
data = int(status_control_raw[0], 16)
tx_disable_hard = (sffbase().test_bit(
data, SFP_TX_DISABLE_HARD_BIT) != 0)
tx_disable_soft = (sffbase().test_bit(
data, SFP_TX_DISABLE_SOFT_BIT) != 0)
tx_disable = tx_disable_hard | tx_disable_soft
return tx_disable
def get_tx_disable_channel(self):
@ -357,7 +501,7 @@ class Sfp(SfpBase, SfpUtilBase):
and channel 2 have been disabled.
"""
# SFP doesn't support this feature
return NotImplementedError
return 0
def get_lpmode(self):
"""
@ -366,7 +510,7 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if lpmode is enabled, False if disabled
"""
# SFP doesn't support this feature
return self.get_low_power_mode(self.port_num)
return False
def get_power_override(self):
"""
@ -375,7 +519,7 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if power-override is enabled, False if disabled
"""
# SFP doesn't support this feature
return NotImplementedError
return False
def get_temperature(self):
"""
@ -405,7 +549,7 @@ class Sfp(SfpBase, SfpUtilBase):
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A")
return [tx1_bs, "N/A", "N/A", "N/A"]
return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
def get_rx_power(self):
"""
@ -417,7 +561,7 @@ class Sfp(SfpBase, SfpUtilBase):
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A")
return [rx1_pw, "N/A", "N/A", "N/A"]
return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
def get_tx_power(self):
"""
@ -429,7 +573,7 @@ class Sfp(SfpBase, SfpUtilBase):
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A")
return [tx1_pw, "N/A", "N/A", "N/A"]
return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else []
def reset(self):
"""
@ -438,7 +582,7 @@ class Sfp(SfpBase, SfpUtilBase):
A boolean, True if successful, False if not
"""
# SFP doesn't support this feature
return NotImplementedError
return False
def tx_disable(self, tx_disable):
"""
@ -449,26 +593,29 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
A boolean, True if tx_disable is set successfully, False if not
"""
sysfsfile_eeprom = self.__get_sysfsfile_eeprom()
status_control_raw = self._read_eeprom_specific_bytes(
sysfsfile_eeprom, self.SFP_STATUS_CONTROL_OFFSET, self.SFP_STATUS_CONTROL_WIDTH)
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num]
status_control_raw = self.__read_eeprom_specific_bytes(
SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH)
if status_control_raw is not None:
tx_disable_bit = 0x80 if tx_disable else 0x7f
# Set bit 6 for Soft TX Disable Select
# 01000000 = 64 and 10111111 = 191
tx_disable_bit = 64 if tx_disable else 191
status_control = int(status_control_raw[0], 16)
tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else (
status_control & tx_disable_bit)
try:
sysfsfile_eeprom = open(
sysfs_sfp_i2c_client_eeprom_path, mode="r+b", buffering=0)
buffer = create_string_buffer(1)
buffer[0] = chr(tx_disable_ctl)
# Write to eeprom
sysfsfile_eeprom.seek(self.SFP_STATUS_CONTROL_OFFSET)
sysfsfile_eeprom.seek(SFP_STATUS_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print "Error: unable to open file: %s" % str(e)
except:
#print("Error: unable to open file: %s" % str(e))
return False
finally:
if sysfsfile_eeprom is not None:
if sysfsfile_eeprom:
sysfsfile_eeprom.close()
time.sleep(0.01)
return True
@ -486,7 +633,7 @@ class Sfp(SfpBase, SfpUtilBase):
A boolean, True if successful, False if not
"""
# SFP doesn't support this feature
return NotImplementedError
return False
def set_lpmode(self, lpmode):
"""
@ -497,7 +644,8 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
A boolean, True if lpmode is set successfully, False if not
"""
return self.set_low_power_mode(self.port_num, lpmode)
# SFP doesn't support this feature
return False
def set_power_override(self, power_override, power_set):
"""
@ -516,7 +664,8 @@ class Sfp(SfpBase, SfpUtilBase):
A boolean, True if power-override and power_set are set successfully,
False if not
"""
return NotImplementedError
# SFP doesn't support this feature
return False
def get_name(self):
"""
@ -524,7 +673,11 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: The name of the device
"""
return self.logical[self.index]
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
name = sfputil_helper.logical[self.index] or "Unknown"
return name
def get_presence(self):
"""
@ -551,7 +704,7 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: Model/part number of device
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("modelname", "N/A")
def get_serial(self):
@ -560,5 +713,5 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: Serial number of device
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("serialnum", "N/A")

View File

@ -22,8 +22,8 @@ class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
MAINBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-11/11-001a/hwmon/"
CPUBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-3/3-001a/hwmon/"
MAINBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-11/11-001a/hwmon/hwmon2"
CPUBOARD_SS_PATH = "/sys/class/i2c-adapter/i2c-3/3-001a/hwmon/hwmon1"
SS_CONFIG_PATH = "/usr/share/sonic/device/x86_64-cel_e1031-r0/sensors.conf"
def __init__(self, thermal_index):
@ -41,10 +41,8 @@ class Thermal(ThermalBase):
self.THERMAL_NAME_LIST.append("CPU board temperature sensor : 2")
# Set hwmon path
self.ss_index, self.ss_path = self.__get_ss_info(self.index)
self.ss_index, self.hwmon_path = self.__get_ss_info(self.index)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.hwmon_name = os.listdir(self.ss_path)[0]
self.hwmon_path = os.path.join(self.ss_path, self.hwmon_name)
def __get_ss_info(self, index):
if self.index <= 4:

View File

@ -0,0 +1,2 @@
__all__ = ["platform", "chassis"]
from sonic_platform import *

View File

@ -26,13 +26,18 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN = 5
NUM_FAN_TRAY = 5
NUM_FAN = 2
NUM_PSU = 2
NUM_THERMAL = 5
NUM_SFP = 32
RESET_REGISTER = "0x103"
REBOOT_CAUSE_PATH = "/host/reboot-cause/previous-reboot-cause.txt"
HOST_REBOOT_CAUSE_PATH = "/host/reboot-cause/"
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/api_files/reboot-cause/"
REBOOT_CAUSE_FILE = "reboot-cause.txt"
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
COMPONENT_NAME_LIST = ["CPLD1", "CPLD2", "CPLD3", "CPLD4", "BIOS"]
HOST_CHK_CMD = "docker > /dev/null 2>&1"
class Chassis(ChassisBase):
@ -40,9 +45,10 @@ class Chassis(ChassisBase):
def __init__(self):
self.config_data = {}
for index in range(0, NUM_FAN):
fan = Fan(index)
self._fan_list.append(fan)
for fant_index in range(0, NUM_FAN_TRAY):
for fan_index in range(0, NUM_FAN):
fan = Fan(fant_index, fan_index)
self._fan_list.append(fan)
for index in range(0, NUM_PSU):
psu = Psu(index)
self._psu_list.append(psu)
@ -53,17 +59,22 @@ class Chassis(ChassisBase):
sfp = Sfp(index)
self._sfp_list.append(sfp)
ChassisBase.__init__(self)
self._component_name_list = COMPONENT_NAME_LIST
self._watchdog = Watchdog()
self._eeprom = Tlv()
def __is_host(self):
return os.system(HOST_CHK_CMD) == 0
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
raise IOError("Unable to open %s file !" % file_path)
pass
return None
def get_base_mac(self):
"""
@ -136,14 +147,27 @@ class Chassis(ChassisBase):
self.component = Component("CPLD1")
description = 'None'
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
hw_reboot_cause = self.component.get_register_value(RESET_REGISTER)
sw_reboot_cause = self.__read_txt_file(REBOOT_CAUSE_PATH)
if sw_reboot_cause != "Unexpected reboot":
reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE) if self.__is_host(
) else PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
prev_reboot_cause_path = (HOST_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE) if self.__is_host(
) else PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
hw_reboot_cause = self.component.get_register_value(RESET_REGISTER)
sw_reboot_cause = self.__read_txt_file(
reboot_cause_path) or "Unknown"
prev_sw_reboot_cause = self.__read_txt_file(
prev_reboot_cause_path) or "Unknown"
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS) and hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
elif sw_reboot_cause != "Unknown" and hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = sw_reboot_cause
elif hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
elif prev_reboot_cause_path != "Unknown" and hw_reboot_cause == "0x11":
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
description = prev_sw_reboot_cause
elif hw_reboot_cause == "0x22":
reboot_cause = self.REBOOT_CAUSE_WATCHDOG,
else:

View File

@ -17,29 +17,47 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CONFIG_DB_PATH = "/etc/sonic/config_db.json"
EMC2305_PATH = "/sys/bus/i2c/drivers/emc2305/"
SYS_GPIO_DIR = "/sys/class/gpio"
GPIO_DIR = "/sys/class/gpio"
GPIO_LABEL = "pca9505"
EMC2305_MAX_PWM = 255
EMC2305_FAN_PWM = "pwm{}"
EMC2305_FAN_TARGET = "fan{}_target"
EMC2305_FAN_INPUT = "pwm{}"
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4", "FAN-5"]
FAN_NAME_LIST = ["FAN-1F", "FAN-1R", "FAN-2F", "FAN-2R",
"FAN-3F", "FAN-3R", "FAN-4F", "FAN-4R", "FAN-5F", "FAN-5R"]
PSU_FAN_MAX_RPM = 11000
PSU_HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon"
PSU_I2C_MAPPING = {
0: {
"num": 10,
"addr": "5a"
},
1: {
"num": 11,
"addr": "5b"
},
}
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_index):
self.index = fan_index
self.config_data = {}
self.fan_speed = 0
FanBase.__init__(self)
def __init__(self, fan_tray_index, fan_index=0, is_psu_fan=False, psu_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
self.is_psu_fan = is_psu_fan
if self.is_psu_fan:
self.psu_index = psu_index
self.psu_i2c_num = PSU_I2C_MAPPING[self.psu_index]["num"]
self.psu_i2c_addr = PSU_I2C_MAPPING[self.psu_index]["addr"]
self.psu_hwmon_path = PSU_HWMON_PATH.format(
self.psu_i2c_num, self.psu_i2c_addr)
# dx010 fan attributes
# Two EMC2305s located at i2c-13-4d and i2c-13-2e
# to control a dual-fan module.
self.dx010_emc2305_chip = [
self.emc2305_chip_mapping = [
{
'device': "13-002e",
'index_map': [2, 1, 4, 5, 3]
@ -49,121 +67,133 @@ class Fan(FanBase):
'index_map': [2, 4, 5, 3, 1]
}
]
self.dx010_fan_gpio = [
{'base': self.get_gpio_base()},
{'prs': 10, 'dir': 15, 'color': {'red': 31, 'green': 32}},
{'prs': 11, 'dir': 16, 'color': {'red': 29, 'green': 30}},
{'prs': 12, 'dir': 17, 'color': {'red': 35, 'green': 36}},
{'prs': 13, 'dir': 18, 'color': {'red': 37, 'green': 38}},
{'prs': 14, 'dir': 19, 'color': {'red': 33, 'green': 34}},
{'base': self.__get_gpio_base()},
{'prs': 11, 'dir': 16, 'color': {'red': 31, 'green': 32}}, # 1
{'prs': 10, 'dir': 15, 'color': {'red': 29, 'green': 30}}, # 2
{'prs': 13, 'dir': 18, 'color': {'red': 35, 'green': 36}}, # 3
{'prs': 14, 'dir': 19, 'color': {'red': 37, 'green': 38}}, # 4
{'prs': 12, 'dir': 17, 'color': {'red': 33, 'green': 34}}, # 5
]
FanBase.__init__(self)
def get_gpio_base(self):
for r in os.listdir(SYS_GPIO_DIR):
if "gpiochip" in r:
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return ""
def __write_txt_file(self, file_path, value):
try:
with open(file_path, 'w') as fd:
fd.write(str(value))
except:
return False
return True
def __search_file_by_name(self, directory, file_name):
for dirpath, dirnames, files in os.walk(directory):
for name in files:
file_path = os.path.join(dirpath, name)
if name in file_name:
return file_path
return None
def __get_gpio_base(self):
for r in os.listdir(GPIO_DIR):
label_path = os.path.join(GPIO_DIR, r, "label")
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
return int(r[8:], 10)
return 216 # Reserve
def get_gpio_value(self, pinnum):
def __get_gpio_value(self, pinnum):
gpio_base = self.dx010_fan_gpio[0]['base']
gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_file = gpio_dir + "/value"
retval = self.__read_txt_file(gpio_file)
return retval.rstrip('\r\n')
try:
with open(gpio_file, 'r') as fd:
retval = fd.read()
except IOError:
raise IOError("Unable to open " + gpio_file + "file !")
retval = retval.rstrip('\r\n')
return retval
def set_gpio_value(self, pinnum, value=0):
def __set_gpio_value(self, pinnum, value=0):
gpio_base = self.dx010_fan_gpio[0]['base']
gpio_dir = SYS_GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_file = gpio_dir + "/value"
try:
with open(gpio_file, 'w') as fd:
retval = fd.write(str(value))
except IOError:
raise IOError("Unable to open " + gpio_file + "file !")
return self.__write_txt_file(gpio_file, value)
def get_direction(self):
"""
Retrieves the direction of fan
Returns:
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
depending on fan direction
"""
direction = self.FAN_DIRECTION_EXHAUST
if not self.is_psu_fan:
raw = self.__get_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['dir'])
direction = self.FAN_DIRECTION_INTAKE
raw = self.get_gpio_value(self.dx010_fan_gpio[self.index+1]['dir'])
if int(raw, 10) == 0:
direction = self.FAN_DIRECTION_INTAKE
else:
direction = self.FAN_DIRECTION_EXHAUST
direction = self.FAN_DIRECTION_INTAKE if int(
raw, 10) == 0 else self.FAN_DIRECTION_EXHAUST
return direction
def get_speed(self):
"""
DX010 platform specific data:
Retrieves the speed of fan as a percentage of full speed
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed = pwm_in/255*100
"""
# TODO: Seperate PSU's fan and main fan class
if self.fan_speed != 0:
return self.fan_speed
else:
speed = 0
pwm = []
emc2305_chips = self.dx010_emc2305_chip
speed = 0
if self.is_psu_fan:
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
self.psu_hwmon_path, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
fan_speed_raw = float(fan_speed_rpm)/PSU_FAN_MAX_RPM * 100
speed = math.ceil(float(fan_speed_rpm) * 100 / PSU_FAN_MAX_RPM)
elif self.get_presence():
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
pwm = int(raw, 10) if raw else 0
speed = math.ceil(float(pwm * 100 / EMC2305_MAX_PWM))
for chip in emc2305_chips:
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_INPUT)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
speed = math.ceil(
float(pwm[0]) * 100 / EMC2305_MAX_PWM)
return int(speed)
return int(speed)
def get_target_speed(self):
"""
DX010 platform specific data:
Retrieves the target (expected) speed of the fan
Returns:
An integer, the percentage of full fan speed, in the range 0 (off)
to 100 (full speed)
Note:
speed_pc = pwm_target/255*100
0 : when PWM mode is use
pwm : when pwm mode is not use
"""
target = 0
pwm = []
emc2305_chips = self.dx010_emc2305_chip
for chip in emc2305_chips:
if not self.is_psu_fan:
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_TARGET)
sysfs_path = sysfs_path.format(fan_index[self.index])
try:
with open(sysfs_path, 'r') as file:
raw = file.read().strip('\r\n')
pwm.append(int(raw, 10))
except IOError:
raise IOError("Unable to open " + sysfs_path)
target = pwm[0] * 100 / EMC2305_MAX_PWM
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
raw = self.__read_txt_file(sysfs_path).strip('\r\n')
pwm = int(raw, 10) if raw else 0
target = math.ceil(float(pwm) * 100 / EMC2305_MAX_PWM)
return target
@ -178,55 +208,68 @@ class Fan(FanBase):
def set_speed(self, speed):
"""
Depends on pwm or target mode is selected:
Sets the fan speed
Args:
speed: An integer, the percentage of full fan speed to set fan to,
in the range 0 (off) to 100 (full speed)
Returns:
A boolean, True if speed is set successfully, False if not
Note:
Depends on pwm or target mode is selected:
1) pwm = speed_pc * 255 <-- Currently use this mode.
2) target_pwm = speed_pc * 100 / 255
2.1) set pwm{}_enable to 3
"""
pwm = speed * 255 / 100
emc2305_chips = self.dx010_emc2305_chip
for chip in emc2305_chips:
if not self.is_psu_fan and self.get_presence():
chip = self.emc2305_chip_mapping[self.fan_index]
device = chip['device']
fan_index = chip['index_map']
sysfs_path = "%s%s/%s" % (
EMC2305_PATH, device, EMC2305_FAN_PWM)
sysfs_path = sysfs_path.format(fan_index[self.index])
sysfs_path = sysfs_path.format(fan_index[self.fan_tray_index])
return self.__write_txt_file(sysfs_path, int(pwm))
return False
def set_status_led(self, color):
"""
Sets the state of the fan module status LED
Args:
color: A string representing the color with which to set the
fan module status LED
Returns:
bool: True if status LED state is set successfully, False if not
"""
set_status_led = False
if not self.is_psu_fan:
s1, s2 = False, False
try:
with open(sysfs_path, 'w') as file:
file.write(str(int(pwm)))
if color == self.STATUS_LED_COLOR_GREEN:
s1 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1)
s2 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 0)
elif color == self.STATUS_LED_COLOR_RED:
s1 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 0)
s2 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1)
elif color == self.STATUS_LED_COLOR_OFF:
s1 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['red'], 1)
s2 = self.__set_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['color']['green'], 1)
set_status_led = s1 and s2
return set_status_led
except IOError:
return False
return True
def set_status_led(self, color):
try:
if color == self.STATUS_LED_COLOR_GREEN:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 1)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 0)
elif color == self.STATUS_LED_COLOR_RED:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 0)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 1)
elif color == self.STATUS_LED_COLOR_OFF:
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['red'], 1)
self.set_gpio_value(
self.dx010_fan_gpio[self.index+1]['color']['green'], 1)
else:
return False
except IOError:
return False
return True
return set_status_led
def get_name(self):
"""
@ -234,7 +277,10 @@ class Fan(FanBase):
Returns:
string: The name of the device
"""
return FAN_NAME_LIST[self.index]
fan_name = FAN_NAME_LIST[self.fan_tray_index*2 + self.fan_index] if not self.is_psu_fan else "PSU-{} FAN-{}".format(
self.psu_index+1, self.fan_index+1)
return fan_name
def get_presence(self):
"""
@ -242,6 +288,7 @@ class Fan(FanBase):
Returns:
bool: True if PSU is present, False if not
"""
raw = self.get_gpio_value(self.dx010_fan_gpio[self.index+1]['prs'])
present_str = self.__get_gpio_value(
self.dx010_fan_gpio[self.fan_tray_index+1]['prs'])
return int(raw, 10) == 0
return int(present_str, 10) == 0 if not self.is_psu_fan else True

View File

@ -8,7 +8,7 @@
#
#############################################################################
import os.path
import os
import sonic_platform
try:
@ -17,66 +17,152 @@ try:
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_DX010_SPEED_PATH = "/sys/class/hwmon/hwmon{}/fan1_input"
GREEN_LED_PATH = "/sys/devices/platform/leds_dx010/leds/dx010:green:p-{}/brightness"
FAN_MAX_RPM = 11000
SYS_GPIO_DIR = "/sys/class/gpio"
HWMON_PATH = "/sys/bus/i2c/devices/i2c-{0}/{0}-00{1}/hwmon"
GPIO_DIR = "/sys/class/gpio"
GPIO_LABEL = "pca9505"
PSU_NAME_LIST = ["PSU-1", "PSU-2"]
PSU_NUM_FAN = [1, 1]
PSU_I2C_MAPPING = {
0: {
"num": 10,
"addr": "5a"
},
1: {
"num": 11,
"addr": "5b"
},
}
class Psu(PsuBase):
"""Platform-specific Psu class"""
def __init__(self, psu_index):
PsuBase.__init__(self)
self.index = psu_index
self.green_led_path = GREEN_LED_PATH.format(self.index+1)
self.dx010_psu_gpio = [
{'base': self.get_gpio_base()},
{'base': self.__get_gpio_base()},
{'prs': 27, 'status': 22},
{'prs': 28, 'status': 25}
]
self.i2c_num = PSU_I2C_MAPPING[self.index]["num"]
self.i2c_addr = PSU_I2C_MAPPING[self.index]["addr"]
self.hwmon_path = HWMON_PATH.format(self.i2c_num, self.i2c_addr)
for fan_index in range(0, PSU_NUM_FAN[self.index]):
fan = Fan(fan_index, 0, is_psu_fan=True, psu_index=self.index)
self._fan_list.append(fan)
PsuBase.__init__(self)
def get_gpio_base(self):
for r in os.listdir(SYS_GPIO_DIR):
if "gpiochip" in r:
def __read_txt_file(self, file_path):
try:
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return ""
def __search_file_by_contain(self, directory, search_str, file_start):
for dirpath, dirnames, files in os.walk(directory):
for name in files:
file_path = os.path.join(dirpath, name)
if name.startswith(file_start) and search_str in self.__read_txt_file(file_path):
return file_path
return None
def __get_gpio_base(self):
for r in os.listdir(GPIO_DIR):
label_path = os.path.join(GPIO_DIR, r, "label")
if "gpiochip" in r and GPIO_LABEL in self.__read_txt_file(label_path):
return int(r[8:], 10)
return 216 # Reserve
def get_gpio_value(self, pinnum):
def __get_gpio_value(self, pinnum):
gpio_base = self.dx010_psu_gpio[0]['base']
gpio_file = "{}/gpio{}/value".format(SYS_GPIO_DIR,
str(gpio_base+pinnum))
gpio_dir = GPIO_DIR + '/gpio' + str(gpio_base+pinnum)
gpio_file = gpio_dir + "/value"
retval = self.__read_txt_file(gpio_file)
return retval.rstrip('\r\n')
try:
with open(gpio_file, 'r') as fd:
retval = fd.read()
except IOError:
raise IOError("Unable to open " + gpio_file + "file !")
retval = retval.rstrip('\r\n')
return retval
def get_fan(self):
def get_voltage(self):
"""
Retrieves object representing the fan module contained in this PSU
Retrieves current PSU voltage output
Returns:
An object dervied from FanBase representing the fan module
contained in this PSU
A float number, the output voltage in volts,
e.g. 12.1
"""
psu_voltage = 0.0
voltage_name = "in{}_input"
voltage_label = "vout1"
fan_speed_path = FAN_DX010_SPEED_PATH.format(
str(self.index+8))
try:
with open(fan_speed_path) as fan_speed_file:
fan_speed_rpm = int(fan_speed_file.read())
except IOError:
fan_speed = 0
vout_label_path = self.__search_file_by_contain(
self.hwmon_path, voltage_label, "in")
if vout_label_path:
dir_name = os.path.dirname(vout_label_path)
basename = os.path.basename(vout_label_path)
in_num = filter(str.isdigit, basename)
vout_path = os.path.join(
dir_name, voltage_name.format(in_num))
vout_val = self.__read_txt_file(vout_path)
psu_voltage = float(vout_val) / 1000
fan_speed = float(fan_speed_rpm)/FAN_MAX_RPM * 100
fan = Fan(0)
fan.fan_speed = int(fan_speed) if int(fan_speed) <= 100 else 100
return fan
return psu_voltage
def get_current(self):
"""
Retrieves present electric current supplied by PSU
Returns:
A float number, the electric current in amperes, e.g 15.4
"""
psu_current = 0.0
current_name = "curr{}_input"
current_label = "iout1"
curr_label_path = self.__search_file_by_contain(
self.hwmon_path, current_label, "cur")
if curr_label_path:
dir_name = os.path.dirname(curr_label_path)
basename = os.path.basename(curr_label_path)
cur_num = filter(str.isdigit, basename)
cur_path = os.path.join(
dir_name, current_name.format(cur_num))
cur_val = self.__read_txt_file(cur_path)
psu_current = float(cur_val) / 1000
return psu_current
def get_power(self):
"""
Retrieves current energy supplied by PSU
Returns:
A float number, the power in watts, e.g. 302.6
"""
psu_power = 0.0
current_name = "power{}_input"
current_label = "pout1"
pw_label_path = self.__search_file_by_contain(
self.hwmon_path, current_label, "power")
if pw_label_path:
dir_name = os.path.dirname(pw_label_path)
basename = os.path.basename(pw_label_path)
pw_num = filter(str.isdigit, basename)
pw_path = os.path.join(
dir_name, current_name.format(pw_num))
pw_val = self.__read_txt_file(pw_path)
psu_power = float(pw_val) / 1000000
return psu_power
def get_powergood_status(self):
"""
Retrieves the powergood status of PSU
Returns:
A boolean, True if PSU has stablized its output voltages and passed all
its internal self-tests, False if not.
"""
return self.get_status()
def set_status_led(self, color):
"""
@ -104,6 +190,20 @@ class Psu(PsuBase):
return True
def get_status_led(self):
"""
Gets the state of the PSU status LED
Returns:
A string, one of the predefined STATUS_LED_COLOR_* strings above
"""
status = self.__read_txt_file(self.green_led_path)
status_str = {
'255': self.STATUS_LED_COLOR_GREEN,
'0': self.STATUS_LED_COLOR_OFF
}.get(status, None)
return status_str
def get_name(self):
"""
Retrieves the name of the device
@ -118,7 +218,7 @@ class Psu(PsuBase):
Returns:
bool: True if PSU is present, False if not
"""
raw = self.get_gpio_value(self.dx010_psu_gpio[self.index+1]['prs'])
raw = self.__get_gpio_value(self.dx010_psu_gpio[self.index+1]['prs'])
return int(raw, 10) == 0
def get_status(self):
@ -127,5 +227,6 @@ class Psu(PsuBase):
Returns:
A boolean value, True if device is operating properly, False if not
"""
raw = self.get_gpio_value(self.dx010_psu_gpio[self.index+1]['status'])
raw = self.__get_gpio_value(
self.dx010_psu_gpio[self.index+1]['status'])
return int(raw, 10) == 1

View File

@ -15,71 +15,110 @@ import sonic_device_util
from ctypes import create_string_buffer
try:
from swsssdk import ConfigDBConnector
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_sfp.sfputilbase import sff8436Dom
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
INFO_OFFSET = 128
DOM_OFFSET = 0
class Sfp(SfpBase, SfpUtilBase):
XCVR_INTFACE_BULK_OFFSET = 0
XCVR_INTFACE_BULK_WIDTH_QSFP = 20
XCVR_HW_REV_WIDTH_QSFP = 2
XCVR_CABLE_LENGTH_WIDTH_QSFP = 5
XCVR_VENDOR_NAME_OFFSET = 20
XCVR_VENDOR_NAME_WIDTH = 16
XCVR_VENDOR_OUI_OFFSET = 37
XCVR_VENDOR_OUI_WIDTH = 3
XCVR_VENDOR_PN_OFFSET = 40
XCVR_VENDOR_PN_WIDTH = 16
XCVR_HW_REV_OFFSET = 56
XCVR_HW_REV_WIDTH_OSFP = 2
XCVR_HW_REV_WIDTH_SFP = 4
XCVR_VENDOR_SN_OFFSET = 68
XCVR_VENDOR_SN_WIDTH = 16
XCVR_VENDOR_DATE_OFFSET = 84
XCVR_VENDOR_DATE_WIDTH = 8
XCVR_DOM_CAPABILITY_OFFSET = 92
XCVR_DOM_CAPABILITY_WIDTH = 1
# Offset for values in QSFP eeprom
QSFP_DOM_REV_OFFSET = 1
QSFP_DOM_REV_WIDTH = 1
QSFP_TEMPE_OFFSET = 22
QSFP_TEMPE_WIDTH = 2
QSFP_VOLT_OFFSET = 26
QSFP_VOLT_WIDTH = 2
QSFP_CHANNL_MON_OFFSET = 34
QSFP_CHANNL_MON_WIDTH = 16
QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24
QSFP_CONTROL_OFFSET = 86
QSFP_CONTROL_WIDTH = 8
QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3
QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4
QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1
QSFP_POWEROVERRIDE_OFFSET = 93
QSFP_POWEROVERRIDE_WIDTH = 1
QSFP_MODULE_THRESHOLD_OFFSET = 128
QSFP_MODULE_THRESHOLD_WIDTH = 24
QSFP_CHANNEL_THRESHOLD_OFFSET = 176
QSFP_CHANNEL_THRESHOLD_WIDTH = 16
qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)',
'Length OM2(m)', 'Length OM1(m)',
'Length Cable Assembly(m)')
qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes',
'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media', 'Fibre Channel Speed')
class Sfp(SfpBase):
"""Platform-specific Sfp class"""
# Port number
PORT_START = 1
PORT_END = 32
PORTS_IN_BLOCK = 32
# Offset for values in QSFP info eeprom
QSFP_CONTROL_OFFSET = 86
QSFP_CONTROL_WIDTH = 8
QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3
QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4
QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1
QSFP_POWEROVERRIDE_OFFSET = 93
QSFP_POWEROVERRIDE_WIDTH = 1
# Key for values in QSFP eeprom dict
QSFP_EEPROM_TYPE_KEY = "Identifier"
QSFP_EEPROM_HW_REV_KEY = "Vendor Rev"
QSFP_EEPROM_MF_NAME_KEY = "Vendor Name"
QSFP_EEPROM_MODEL_NAME_KEY = "Vendor PN"
QSFP_EEPROM_SERIAL_KEY = "Vendor SN"
QSFP_EEPROM_CONNECTOR_KEY = "Connector"
QSFP_EEPROM_ENCODE_KEY = "Encoding"
QSFP_EEPROM_EXT_IDENT_KEY = "Extended Identifier"
QSFP_EEPROM_EXT_RATE_KEY = "Extended RateSelect Compliance"
QSFP_EEPROM_CABLE_KEY = "Length(km)"
QSFP_EEPROM_BIT_RATE_KEY = "Nominal Bit Rate(100Mbs)"
QSFP_EEPROM_SPEC_COM_KEY = "Specification compliance"
QSFP_EEPROM_DATE_KEY = "Vendor Date Code(YYYY-MM-DD Lot)"
QSFP_EEPROM_OUI_KEY = "Vendor OUI"
# Path to QSFP sysfs
RESET_PATH = "/sys/devices/platform/dx010_cpld/qsfp_reset"
LP_PATH = "/sys/devices/platform/dx010_cpld/qsfp_lpmode"
PRS_PATH = "/sys/devices/platform/dx010_cpld/qsfp_modprs"
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
HOST_CHK_CMD = "docker > /dev/null 2>&1"
_port_to_eeprom_mapping = {}
PLATFORM = "x86_64-cel_seastone-r0"
HWSKU = "Seastone-DX010"
@property
def port_start(self):
return self.PORT_START
def __init__(self, sfp_index):
# Init index
self.index = sfp_index
self.port_num = self.index + 1 if self.PORT_START == 1 else index
@property
def port_end(self):
return self.PORT_END
# Init eeprom path
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
self.port_to_eeprom_mapping = {}
for x in range(self.PORT_START, self.PORT_END + 1):
p_num = x - 1 if self.PORT_START == 1 else x
self.port_to_eeprom_mapping[x] = eeprom_path.format(p_num + 26)
@property
def qsfp_ports(self):
return range(self.PORT_START, self.PORTS_IN_BLOCK + 1)
self.info_dict_keys = ['type', 'hardwarerev', 'serialnum', 'manufacturename', 'modelname', 'Connector', 'encoding', 'ext_identifier',
'ext_rateselect_compliance', 'cable_type', 'cable_length', 'nominal_bit_rate', 'specification_compliance', 'vendor_date', 'vendor_oui']
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
self.dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status', 'power_lpmode', 'tx_disable', 'tx_disable_channel', 'temperature', 'voltage',
'rx1power', 'rx2power', 'rx3power', 'rx4power', 'tx1bias', 'tx2bias', 'tx3bias', 'tx4bias', 'tx1power', 'tx2power', 'tx3power', 'tx4power']
self.threshold_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', 'rxpowerhighalarm', 'rxpowerhighwarning',
'rxpowerlowalarm', 'rxpowerlowwarning', 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning']
SfpBase.__init__(self)
def _convert_string_to_num(self, value_str):
if "-inf" in value_str:
@ -101,122 +140,44 @@ class Sfp(SfpBase, SfpUtilBase):
else:
return 'N/A'
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
def __read_txt_file(self, file_path):
try:
reg_file = open(self.LP_PATH, "r")
content = reg_file.readline().rstrip()
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
with open(file_path, 'r') as fd:
data = fd.read()
return data.strip()
except IOError:
pass
return ""
# content is a string containing the hex representation of the register
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = port_num - 1 if self.port_start == 1 else port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
# LPMode is active high
if reg_value & mask == 0:
return False
return True
def set_low_power_mode(self, port_num, lpmode):
try:
reg_file = open(self.LP_PATH, "r+")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
content = reg_file.readline().rstrip()
# content is a string containing the hex representation of the register
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = port_num - 1 if self.port_start == 1 else port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
# LPMode is active high; set or clear the bit accordingly
reg_value = reg_value | mask if lpmode else reg_value & ~mask
# Convert our register value back to a hex string and write back
content = hex(reg_value).strip('L')
reg_file.seek(0)
reg_file.write(content)
reg_file.close()
return True
def get_transceiver_change_event(self, timeout=0):
raise NotImplementedError
def __init__(self, sfp_index):
# Init SfpUtilBase
eeprom_path = '/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom'
for x in range(self.PORT_START, self.PORT_END + 1):
if self.port_start == 1:
self._port_to_eeprom_mapping[x] = eeprom_path.format(
(x - 1) + 26)
else:
self._port_to_eeprom_mapping[x] = eeprom_path.format(x + 26)
self.read_porttab_mappings(self.__get_path_to_port_config_file())
SfpUtilBase.__init__(self)
# Init index
self.index = sfp_index
self.port_num = self.index + 1
def __is_host(self):
return os.system(self.HOST_CHK_CMD) == 0
def __get_path_to_port_config_file(self):
# Get platform and hwsku
machine_info = sonic_device_util.get_machine_info()
platform = sonic_device_util.get_platform_info(machine_info)
config_db = ConfigDBConnector()
config_db.connect()
data = config_db.get_table('DEVICE_METADATA')
try:
hwsku = data['localhost']['hwsku']
except KeyError:
hwsku = "Unknown"
# Load platform module from source
platform_path = "/".join([self.PLATFORM_ROOT_PATH, platform])
hwsku_path = "/".join([platform_path, hwsku])
# First check for the presence of the new 'port_config.ini' file
port_config_file_path = "/".join([hwsku_path, "port_config.ini"])
if not os.path.isfile(port_config_file_path):
# port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file
port_config_file_path = "/".join([hwsku_path, "portmap.ini"])
return port_config_file_path
platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM])
hwsku_path = "/".join([platform_path, self.HWSKU]
) if self.__is_host() else self.PMON_HWSKU_PATH
return "/".join([hwsku_path, "port_config.ini"])
def __read_eeprom_specific_bytes(self, offset, num_bytes):
sysfsfile_eeprom = None
eeprom_raw = None
eeprom_raw = []
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
sysfs_sfp_i2c_client_eeprom_path = self.port_to_eeprom_mapping[self.port_num]
try:
sysfsfile_eeprom = open(
sysfs_sfp_i2c_client_eeprom_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" %
sysfs_sfp_i2c_client_eeprom_path)
sysfsfile_eeprom.seek(offset)
raw = sysfsfile_eeprom.read(num_bytes)
for n in range(0, num_bytes):
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except:
pass
finally:
if sysfsfile_eeprom:
eeprom_raw = self._read_eeprom_specific_bytes(
sysfsfile_eeprom, offset, num_bytes)
sysfsfile_eeprom.close()
return eeprom_raw
def get_transceiver_info(self):
@ -243,45 +204,84 @@ class Sfp(SfpBase, SfpUtilBase):
vendor_oui |1*255VCHAR |vendor OUI
========================================================================
"""
transceiver_info_dict = dict()
# get eeprom data
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('interface'):
transceiver_info_data = self.eeprom_dict['interface'].get('data')
# check present status
sfpi_obj = sff8436InterfaceId()
if not self.get_presence() or not sfpi_obj:
return {}
# set specification_compliance
spec_com = transceiver_info_data.get(
self.QSFP_EEPROM_SPEC_COM_KEY, {})
spec_com_str = "/".join(list(spec_com.values()))
offset = INFO_OFFSET
# set normal transceiver info
transceiver_info_dict['type'] = transceiver_info_data.get(
self.QSFP_EEPROM_TYPE_KEY, 'N/A')
transceiver_info_dict['hardwarerev'] = transceiver_info_data.get(
self.QSFP_EEPROM_HW_REV_KEY, 'N/A')
transceiver_info_dict['manufacturename'] = transceiver_info_data.get(
self.QSFP_EEPROM_MF_NAME_KEY, 'N/A')
transceiver_info_dict['modelname'] = transceiver_info_data.get(
self.QSFP_EEPROM_MODEL_NAME_KEY, 'N/A')
transceiver_info_dict['serialnum'] = transceiver_info_data.get(
self.QSFP_EEPROM_SERIAL_KEY, 'N/A')
transceiver_info_dict['Connector'] = transceiver_info_data.get(
self.QSFP_EEPROM_CONNECTOR_KEY, 'N/A')
transceiver_info_dict['encoding'] = transceiver_info_data.get(
self.QSFP_EEPROM_ENCODE_KEY, 'N/A')
transceiver_info_dict['ext_identifier'] = transceiver_info_data.get(
self.QSFP_EEPROM_EXT_IDENT_KEY, 'N/A')
transceiver_info_dict['ext_rateselect_compliance'] = transceiver_info_data.get(
self.QSFP_EEPROM_EXT_RATE_KEY, 'N/A')
transceiver_info_dict['cable_length'] = transceiver_info_data.get(
self.QSFP_EEPROM_CABLE_KEY, 'N/A')
transceiver_info_dict['vendor_date'] = transceiver_info_data.get(
self.QSFP_EEPROM_DATE_KEY, 'N/A')
transceiver_info_dict['vendor_oui'] = transceiver_info_data.get(
self.QSFP_EEPROM_OUI_KEY, 'N/A')
transceiver_info_dict['nominal_bit_rate'] = transceiver_info_data.get(
self.QSFP_EEPROM_BIT_RATE_KEY, 'N/A')
transceiver_info_dict['specification_compliance'] = spec_com_str or "N/A"
sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP)
sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(
sfp_interface_bulk_raw, 0)
sfp_vendor_name_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(
sfp_vendor_name_raw, 0)
sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(
sfp_vendor_pn_raw, 0)
sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP)
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(
sfp_vendor_rev_raw, 0)
sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(
sfp_vendor_sn_raw, 0)
sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH)
if sfp_vendor_oui_raw is not None:
sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(
sfp_vendor_oui_raw, 0)
sfp_vendor_date_raw = self.__read_eeprom_specific_bytes(
(offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH)
sfp_vendor_date_data = sfpi_obj.parse_vendor_date(
sfp_vendor_date_raw, 0)
transceiver_info_dict = dict.fromkeys(self.info_dict_keys, 'N/A')
compliance_code_dict = dict()
if sfp_interface_bulk_data:
transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value']
transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value']
transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value']
transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data[
'data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A'
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A'
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A'
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A'
transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A'
transceiver_info_dict['vendor_date'] = sfp_vendor_date_data[
'data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A'
transceiver_info_dict['cable_type'] = "Unknown"
transceiver_info_dict['cable_length'] = "Unknown"
for key in qsfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(
sfp_interface_bulk_data['data'][key]['value'])
for key in qsfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['nominal_bit_rate'] = str(
sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value'])
return transceiver_info_dict
@ -293,83 +293,200 @@ class Sfp(SfpBase, SfpUtilBase):
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
RX LOS |BOOLEAN |RX lost-of-signal status,
| |True if has RX los, False if not.
TX FAULT |BOOLEAN |TX fault status,
| |True if has TX fault, False if not.
Reset status |BOOLEAN |reset status,
| |True if SFP in reset, False if not.
LP mode |BOOLEAN |low power mode status,
| |True in lp mode, False if not.
TX disable |BOOLEAN |TX disable status,
| |True TX disabled, False if not.
TX disabled channel |HEX |disabled TX channles in hex,
| |bits 0 to 3 represent channel 0
rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not.
tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not.
reset_status |BOOLEAN |reset status, True if SFP in reset, False if not.
lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not.
tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not.
tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0
| |to channel 3.
Temperature |INT |module temperature in Celsius
Voltage |INT |supply voltage in mV
TX bias |INT |TX Bias Current in mA
RX power |INT |received optical power in mW
TX power |INT |TX output power in mW
temperature |INT |module temperature in Celsius
voltage |INT |supply voltage in mV
tx<n>bias |INT |TX Bias Current in mA, n is the channel number,
| |for example, tx2bias stands for tx bias of channel 2.
rx<n>power |INT |received optical power in mW, n is the channel number,
| |for example, rx2power stands for rx power of channel 2.
tx<n>power |INT |TX output power in mW, n is the channel number,
| |for example, tx2power stands for tx power of channel 2.
========================================================================
"""
transceiver_dom_info_dict = dict()
self.eeprom_dict = self.get_eeprom_dict(self.port_num)
if self.eeprom_dict and self.eeprom_dict.get('dom'):
transceiver_dom_data = self.eeprom_dict['dom'].get('data', {})
transceiver_dom_data_mmv = transceiver_dom_data.get(
"ModuleMonitorValues")
transceiver_dom_data_cmv = transceiver_dom_data.get(
"ChannelMonitorValues")
transceiver_dom_info_dict['temperature'] = transceiver_dom_data_mmv.get(
'Temperature', 'N/A')
transceiver_dom_info_dict['voltage'] = transceiver_dom_data_mmv.get(
'Vcc', 'N/A')
transceiver_dom_info_dict['rx1power'] = transceiver_dom_data_cmv.get(
'RX1Power', 'N/A')
transceiver_dom_info_dict['rx2power'] = transceiver_dom_data_cmv.get(
'RX2Power', 'N/A')
transceiver_dom_info_dict['rx3power'] = transceiver_dom_data_cmv.get(
'RX3Power', 'N/A')
transceiver_dom_info_dict['rx4power'] = transceiver_dom_data_cmv.get(
'RX4Power', 'N/A')
transceiver_dom_info_dict['tx1bias'] = transceiver_dom_data_cmv.get(
'TX1Bias', 'N/A')
transceiver_dom_info_dict['tx2bias'] = transceiver_dom_data_cmv.get(
'TX2Bias', 'N/A')
transceiver_dom_info_dict['tx3bias'] = transceiver_dom_data_cmv.get(
'TX3Bias', 'N/A')
transceiver_dom_info_dict['tx4bias'] = transceiver_dom_data_cmv.get(
'TX4Bias', 'N/A')
transceiver_dom_info_dict['tx1power'] = transceiver_dom_data_cmv.get(
'TX1Power', 'N/A')
transceiver_dom_info_dict['tx2power'] = transceiver_dom_data_cmv.get(
'TX2Power', 'N/A')
transceiver_dom_info_dict['tx3power'] = transceiver_dom_data_cmv.get(
'TX3Power', 'N/A')
transceiver_dom_info_dict['tx4power'] = transceiver_dom_data_cmv.get(
'TX4Power', 'N/A')
# check present status
sfpd_obj = sff8436Dom()
sfpi_obj = sff8436InterfaceId()
if not self.get_presence() or not sfpi_obj or not sfpd_obj:
return {}
transceiver_dom_info_dict = dict.fromkeys(self.dom_dict_keys, 'N/A')
offset = DOM_OFFSET
offset_xcvr = INFO_OFFSET
# QSFP capability byte parse, through this byte can know whether it support tx_power or not.
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
# need to add more code for determining the capability and version compliance
# in SFF-8636 dom capability definitions evolving with the versions.
qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes(
(offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
if qsfp_dom_capability_raw is not None:
qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(
qsfp_dom_capability_raw, 0)
else:
return None
dom_temperature_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(
dom_temperature_raw, 0)
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
dom_voltage_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
if qsfp_dom_rev_raw is not None:
qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
# The tx_power monitoring is only available on QSFP which compliant with SFF-8636
# and claimed that it support tx_power with one indicator bit.
dom_channel_monitor_data = {}
dom_channel_monitor_raw = None
qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(
dom_channel_monitor_raw, 0)
else:
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
(offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(
dom_channel_monitor_raw, 0)
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
if dom_channel_monitor_raw:
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
for key in transceiver_dom_info_dict:
transceiver_dom_info_dict[key] = self._convert_string_to_num(
transceiver_dom_info_dict[key])
transceiver_dom_info_dict['rx_los'] = self.get_rx_los()
transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault()
transceiver_dom_info_dict['reset_status'] = self.get_reset_status()
transceiver_dom_info_dict['lp_mode'] = self.get_lpmode()
return transceiver_dom_info_dict
def get_transceiver_threshold_info(self):
"""
Retrieves transceiver threshold info of this SFP
Returns:
A dict which contains following keys/values :
========================================================================
keys |Value Format |Information
---------------------------|---------------|----------------------------
temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius.
templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius.
temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius.
templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius.
vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV.
vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV.
vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV.
vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV.
rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm.
rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm.
rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm.
rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm.
txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm.
txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm.
txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm.
txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm.
txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA.
txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA.
txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA.
txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA.
========================================================================
"""
# check present status
sfpd_obj = sff8436Dom()
if not self.get_presence() or not sfpd_obj:
return {}
transceiver_dom_threshold_dict = dict.fromkeys(
self.threshold_dict_keys, 'N/A')
dom_thres_raw = self.__read_eeprom_specific_bytes(
QSFP_MODULE_THRESHOLD_OFFSET, QSFP_MODULE_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None
if dom_thres_raw:
module_threshold_values = sfpd_obj.parse_module_threshold_values(
dom_thres_raw, 0)
module_threshold_data = module_threshold_values.get('data')
if module_threshold_data:
transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value']
transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value']
transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value']
transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value']
transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value']
transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value']
transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value']
transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value']
dom_thres_raw = self.__read_eeprom_specific_bytes(
QSFP_CHANNEL_THRESHOLD_OFFSET, QSFP_CHANNEL_THRESHOLD_WIDTH) if self.get_presence() and sfpd_obj else None
channel_threshold_values = sfpd_obj.parse_channel_threshold_values(
dom_thres_raw, 0)
channel_threshold_data = channel_threshold_values.get('data')
if channel_threshold_data:
transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value']
transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value']
transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value']
transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value']
transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm"
transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm"
transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value']
transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value']
transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value']
transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value']
for key in transceiver_dom_threshold_dict:
transceiver_dom_threshold_dict[key] = self._convert_string_to_num(
transceiver_dom_threshold_dict[key])
return transceiver_dom_threshold_dict
def get_reset_status(self):
"""
Retrieves the reset status of SFP
Returns:
A Boolean, True if reset enabled, False if disabled
"""
try:
reg_file = open(self.RESET_PATH, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
reset_status_raw = self.__read_txt_file(self.RESET_PATH).rstrip()
if not reset_status_raw:
return False
content = reg_file.readline().rstrip()
reg_value = int(content, 16)
reg_value = int(reset_status_raw, 16)
bin_format = bin(reg_value)[2:].zfill(32)
return bin_format[::-1][self.index] == '0'
@ -380,16 +497,18 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if SFP has RX LOS, False if not.
Note : RX LOS status is latched until a call to get_rx_los or a reset.
"""
rx_los = False
rx_los_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
self.QSFP_CHANNL_RX_LOS_STATUS_OFFSET, self.QSFP_CHANNL_RX_LOS_STATUS_WIDTH)
QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) if self.get_presence() else None
if dom_channel_monitor_raw is not None:
rx_los_data = int(dom_channel_monitor_raw[0], 16)
rx_los_list.append(rx_los_data & 0x01 != 0)
rx_los_list.append(rx_los_data & 0x02 != 0)
rx_los_list.append(rx_los_data & 0x04 != 0)
rx_los_list.append(rx_los_data & 0x08 != 0)
return rx_los_list
rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3]
return rx_los
def get_tx_fault(self):
"""
@ -398,16 +517,19 @@ class Sfp(SfpBase, SfpUtilBase):
A Boolean, True if SFP has TX fault, False if not
Note : TX fault status is lached until a call to get_tx_fault or a reset.
"""
tx_fault = False
tx_fault_list = []
dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(
self.QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, self.QSFP_CHANNL_TX_FAULT_STATUS_WIDTH)
QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) if self.get_presence() else None
if dom_channel_monitor_raw is not None:
tx_fault_data = int(dom_channel_monitor_raw[0], 16)
tx_fault_list.append(tx_fault_data & 0x01 != 0)
tx_fault_list.append(tx_fault_data & 0x02 != 0)
tx_fault_list.append(tx_fault_data & 0x04 != 0)
tx_fault_list.append(tx_fault_data & 0x08 != 0)
return tx_fault_list
tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3]
return tx_fault
def get_tx_disable(self):
"""
@ -422,7 +544,7 @@ class Sfp(SfpBase, SfpUtilBase):
return False
dom_control_raw = self.__read_eeprom_specific_bytes(
self.QSFP_CONTROL_OFFSET, self.QSFP_CONTROL_WIDTH)
QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0)
tx_disable_list.append(
@ -460,7 +582,27 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
A Boolean, True if lpmode is enabled, False if disabled
"""
return self.get_low_power_mode(self.port_num)
try:
reg_file = open(self.LP_PATH, "r")
content = reg_file.readline().rstrip()
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
# content is a string containing the hex representation of the register
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = self.port_num - 1 if self.PORT_START == 1 else self.port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
# LPMode is active high
if reg_value & mask == 0:
return False
return True
def get_power_override(self):
"""
@ -476,7 +618,7 @@ class Sfp(SfpBase, SfpUtilBase):
return False
dom_control_raw = self.__read_eeprom_specific_bytes(
self.QSFP_CONTROL_OFFSET, self.QSFP_CONTROL_WIDTH)
QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) if self.get_presence() else None
if dom_control_raw is not None:
dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0)
power_override = (
@ -515,7 +657,7 @@ class Sfp(SfpBase, SfpUtilBase):
tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A")
tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A")
tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A")
return [tx1_bs, tx2_bs, tx3_bs, tx4_bs]
return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else []
def get_rx_power(self):
"""
@ -530,7 +672,7 @@ class Sfp(SfpBase, SfpUtilBase):
rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A")
rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A")
rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A")
return [rx1_pw, rx2_pw, rx3_pw, rx4_pw]
return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else []
def get_tx_power(self):
"""
@ -568,7 +710,7 @@ class Sfp(SfpBase, SfpUtilBase):
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = self.port_num - 1 if self.port_start == 1 else self.port_num
bit_index = self.port_num - 1 if self.PORT_START == 1 else self.port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
@ -615,7 +757,7 @@ class Sfp(SfpBase, SfpUtilBase):
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(self.QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print "Error: unable to open file: %s" % str(e)
@ -649,7 +791,7 @@ class Sfp(SfpBase, SfpUtilBase):
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(self.QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print "Error: unable to open file: %s" % str(e)
@ -669,7 +811,33 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
A boolean, True if lpmode is set successfully, False if not
"""
return self.set_low_power_mode(self.port_num, lpmode)
try:
reg_file = open(self.LP_PATH, "r+")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
return False
content = reg_file.readline().rstrip()
# content is a string containing the hex representation of the register
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = self.port_num - 1 if self.PORT_START == 1 else self.port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
# LPMode is active high; set or clear the bit accordingly
reg_value = reg_value | mask if lpmode else reg_value & ~mask
# Convert our register value back to a hex string and write back
content = hex(reg_value).strip('L')
reg_file.seek(0)
reg_file.write(content)
reg_file.close()
return True
def set_power_override(self, power_override, power_set):
"""
@ -702,7 +870,7 @@ class Sfp(SfpBase, SfpUtilBase):
# Write to eeprom
sysfsfile_eeprom = open(
self.port_to_eeprom_mapping[self.port_num], "r+b")
sysfsfile_eeprom.seek(self.QSFP_POWEROVERRIDE_OFFSET)
sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET)
sysfsfile_eeprom.write(buffer[0])
except IOError as e:
print "Error: unable to open file: %s" % str(e)
@ -719,7 +887,11 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: The name of the device
"""
return self.logical[self.index]
sfputil_helper = SfpUtilHelper()
sfputil_helper.read_porttab_mappings(
self.__get_path_to_port_config_file())
name = sfputil_helper.logical[self.index] or "Unknown"
return name
def get_presence(self):
"""
@ -727,17 +899,15 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
bool: True if PSU is present, False if not
"""
try:
reg_file = open(self.PRS_PATH, "r")
except IOError as e:
print("Error: unable to open file: %s" % str(e))
presence_status_raw = self.__read_txt_file(self.PRS_PATH).rstrip()
if not presence_status_raw:
return False
content = reg_file.readline().rstrip()
content = presence_status_raw.rstrip()
reg_value = int(content, 16)
# Determind if port_num start from 1 or 0
bit_index = self.port_num - 1 if self.port_start == 1 else self.port_num
bit_index = self.port_num - 1 if self.PORT_START == 1 else self.port_num
# Mask off the bit corresponding to our port
mask = (1 << bit_index)
@ -754,7 +924,7 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: Model/part number of device
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("modelname", "N/A")
def get_serial(self):
@ -763,5 +933,13 @@ class Sfp(SfpBase, SfpUtilBase):
Returns:
string: Serial number of device
"""
transceiver_dom_info_dict = self.get_transceiver_bulk_status()
transceiver_dom_info_dict = self.get_transceiver_info()
return transceiver_dom_info_dict.get("serialnum", "N/A")
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
return self.get_presence() and self.get_transceiver_bulk_status()

View File

@ -37,18 +37,16 @@ class Thermal(ThermalBase):
# Set hwmon path
i2c_path = {
0: "i2c-5/5-0048", # u4 system-inlet
1: "i2c-6/6-0049", # u2 system-inlet
2: "i2c-7/7-004a", # u44 bmc56960-on-board
3: "i2c-14/14-0048", # u9200 cpu-on-board
4: "i2c-15/15-004e" # u9201 system-outlet
0: "i2c-5/5-0048/hwmon/hwmon1", # u4 system-inlet
1: "i2c-6/6-0049/hwmon/hwmon2", # u2 system-inlet
2: "i2c-7/7-004a/hwmon/hwmon3", # u44 bmc56960-on-board
3: "i2c-14/14-0048/hwmon/hwmon4", # u9200 cpu-on-board
4: "i2c-15/15-004e/hwmon/hwmon5" # u9201 system-outlet
}.get(self.index, None)
self.ss_path = "{}/{}/hwmon".format(self.I2C_ADAPTER_PATH, i2c_path)
self.hwmon_path = "{}/{}".format(self.I2C_ADAPTER_PATH, i2c_path)
self.ss_key = self.THERMAL_NAME_LIST[self.index]
self.ss_index = 1
self.hwmon_name = os.listdir(self.ss_path)[0]
self.hwmon_path = os.path.join(self.ss_path, self.hwmon_name)
def __read_txt_file(self, file_path):
try:
@ -56,7 +54,7 @@ class Thermal(ThermalBase):
data = fd.read()
return data.strip()
except IOError:
raise IOError("Unable to open %s file !" % file_path)
pass
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)

View File

@ -23,13 +23,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -23,13 +23,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -0,0 +1,65 @@
# name lanes alias
Ethernet0 73,74,75,76 hundredGigE1
Ethernet4 65,66,67,68 hundredGigE2
Ethernet8 81,82,83,84 hundredGigE3
Ethernet12 89,90,91,92 hundredGigE4
Ethernet16 105,106,107,108 hundredGigE5
Ethernet20 97,98,99,100 hundredGigE6
Ethernet24 113,114,115,116 hundredGigE7
Ethernet28 121,122,123,124 hundredGigE8
Ethernet32 41,42,43,44 hundredGigE9
Ethernet36 33,34,35,36 hundredGigE10
Ethernet40 49,50,51,52 hundredGigE11
Ethernet44 57,58,59,60 hundredGigE12
Ethernet48 137,138,139,140 hundredGigE13
Ethernet52 129,130,131,132 hundredGigE14
Ethernet56 145,146,147,148 hundredGigE15
Ethernet60 153,154,155,156 hundredGigE16
Ethernet64 173,174,175,176 hundredGigE17
Ethernet68 165,166,167,168 hundredGigE18
Ethernet72 181,182,183,184 hundredGigE19
Ethernet76 189,190,191,192 hundredGigE20
Ethernet80 13,14,15,16 hundredGigE21
Ethernet84 5,6,7,8 hundredGigE22
Ethernet88 29,30,31,32 hundredGigE23
Ethernet92 21,22,23,24 hundredGigE24
Ethernet96 205,206,207,208 hundredGigE25
Ethernet100 197,198,199,200 hundredGigE26
Ethernet104 213,214,215,216 hundredGigE27
Ethernet108 221,222,223,224 hundredGigE28
Ethernet112 229,230,231,232 hundredGigE29
Ethernet116 237,238,239,240 hundredGigE30
Ethernet120 245,246,247,248 hundredGigE31
Ethernet124 253,254,255,256 hundredGigE32
Ethernet128 69,70,71,72 hundredGigE33
Ethernet132 77,78,79,80 hundredGigE34
Ethernet136 93,94,95,96 hundredGigE35
Ethernet140 85,86,87,88 hundredGigE36
Ethernet144 101,102,103,104 hundredGigE37
Ethernet148 109,110,111,112 hundredGigE38
Ethernet152 125,126,127,128 hundredGigE39
Ethernet156 117,118,119,120 hundredGigE40
Ethernet160 37,38,39,40 hundredGigE41
Ethernet164 45,46,47,48 hundredGigE42
Ethernet168 61,62,63,64 hundredGigE43
Ethernet172 53,54,55,56 hundredGigE44
Ethernet176 133,134,135,136 hundredGigE45
Ethernet180 141,142,143,144 hundredGigE46
Ethernet184 157,158,159,160 hundredGigE47
Ethernet188 149,150,151,152 hundredGigE48
Ethernet192 161,162,163,164 hundredGigE49
Ethernet196 169,170,171,172 hundredGigE50
Ethernet200 185,186,187,188 hundredGigE51
Ethernet204 177,178,179,180 hundredGigE52
Ethernet208 1,2,3,4 hundredGigE53
Ethernet212 9,10,11,12 hundredGigE54
Ethernet216 25,26,27,28 hundredGigE55
Ethernet220 17,18,19,20 hundredGigE56
Ethernet224 193,194,195,196 hundredGigE57
Ethernet228 201,202,203,204 hundredGigE58
Ethernet232 217,218,219,220 hundredGigE59
Ethernet236 209,210,211,212 hundredGigE60
Ethernet240 225,226,227,228 hundredGigE61
Ethernet244 233,234,235,236 hundredGigE62
Ethernet248 249,250,251,252 hundredGigE63
Ethernet252 241,242,243,244 hundredGigE64

View File

@ -0,0 +1 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th2-qfx5210-64x100G.config.bcm

View File

@ -0,0 +1,875 @@
# Broadcom Tomahawk SDK configuration
os=unix
schan_intr_enable=0
l2_mem_entries=40960
l2xmsg_mode=1
l3_mem_entries=40960
parity_correction=0
parity_enable=0
mmu_lossless=1
pbmp_xport_xe=0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
pbmp_oversubscribe=0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
# platform specific setting
arl_clean_timeout_usec=15000000
asf_mem_profile=2
bcm_num_cos=8
bcm_stat_flags=1
bcm_stat_jumbo=9236
cdma_timeout_usec=15000000
dma_desc_timeout_usec=15000000
ipv6_lpm_128b_enable=1
l3_alpm_enable=2
lpm_scaling_enable=0
max_vp_lags=0
miim_intr_enable=0
module_64ports=1
oversubscribe_mode=1
#add loopback port
# port 33 is the first loopback port
portmap_33=260:10
# port 66 is the first management port
portmap_66=257:10
# port 67 is the second loopback port
portmap_67=261:10
# port 100 is the second management port
portmap_100=259:10
# port 101 is the third loopback port
portmap_101=262:10
# port 135 is the fourth loopback port
portmap_135=263:10
#Port0
#FC18
portmap_36=73:100
phy_chain_rx_lane_map_physical{73.0}=0x3210
phy_chain_tx_lane_map_physical{73.0}=0x3021
phy_chain_rx_polarity_flip_physical{73.0}=0x0
phy_chain_rx_polarity_flip_physical{74.0}=0x0
phy_chain_rx_polarity_flip_physical{75.0}=0x0
phy_chain_rx_polarity_flip_physical{76.0}=0x1
phy_chain_tx_polarity_flip_physical{73.0}=0x0
phy_chain_tx_polarity_flip_physical{74.0}=0x0
phy_chain_tx_polarity_flip_physical{75.0}=0x1
phy_chain_tx_polarity_flip_physical{76.0}=0x0
#Port1
#FC16
portmap_34=65:100
phy_chain_rx_lane_map_physical{65.0}=0x3210
phy_chain_tx_lane_map_physical{65.0}=0x3210
phy_chain_rx_polarity_flip_physical{65.0}=0x0
phy_chain_rx_polarity_flip_physical{66.0}=0x0
phy_chain_rx_polarity_flip_physical{67.0}=0x0
phy_chain_rx_polarity_flip_physical{68.0}=0x0
phy_chain_tx_polarity_flip_physical{65.0}=0x1
phy_chain_tx_polarity_flip_physical{66.0}=0x0
phy_chain_tx_polarity_flip_physical{67.0}=0x0
phy_chain_tx_polarity_flip_physical{68.0}=0x0
#Port2
#FC20
portmap_38=81:100
phy_chain_rx_lane_map_physical{81.0}=0x1230
phy_chain_tx_lane_map_physical{81.0}=0x1032
phy_chain_rx_polarity_flip_physical{81.0}=0x1
phy_chain_rx_polarity_flip_physical{82.0}=0x0
phy_chain_rx_polarity_flip_physical{83.0}=0x1
phy_chain_rx_polarity_flip_physical{84.0}=0x0
phy_chain_tx_polarity_flip_physical{81.0}=0x1
phy_chain_tx_polarity_flip_physical{82.0}=0x1
phy_chain_tx_polarity_flip_physical{83.0}=0x1
phy_chain_tx_polarity_flip_physical{84.0}=0x0
#Port3
#FC22
portmap_40=89:100
phy_chain_rx_lane_map_physical{89.0}=0x0132
phy_chain_tx_lane_map_physical{89.0}=0x1203
phy_chain_rx_polarity_flip_physical{89.0}=0x1
phy_chain_rx_polarity_flip_physical{90.0}=0x0
phy_chain_rx_polarity_flip_physical{91.0}=0x0
phy_chain_rx_polarity_flip_physical{92.0}=0x1
phy_chain_tx_polarity_flip_physical{89.0}=0x1
phy_chain_tx_polarity_flip_physical{90.0}=0x0
phy_chain_tx_polarity_flip_physical{91.0}=0x1
phy_chain_tx_polarity_flip_physical{92.0}=0x1
#Port4
#FC26
portmap_44=105:100
phy_chain_rx_lane_map_physical{105.0}=0x3210
phy_chain_tx_lane_map_physical{105.0}=0x0231
phy_chain_rx_polarity_flip_physical{105.0}=0x0
phy_chain_rx_polarity_flip_physical{106.0}=0x0
phy_chain_rx_polarity_flip_physical{107.0}=0x0
phy_chain_rx_polarity_flip_physical{108.0}=0x1
phy_chain_tx_polarity_flip_physical{105.0}=0x0
phy_chain_tx_polarity_flip_physical{106.0}=0x1
phy_chain_tx_polarity_flip_physical{107.0}=0x0
phy_chain_tx_polarity_flip_physical{108.0}=0x1
#Port5
#FC24
portmap_42=97:100
phy_chain_rx_lane_map_physical{97.0}=0x0213
phy_chain_tx_lane_map_physical{97.0}=0x3210
phy_chain_rx_polarity_flip_physical{97.0}=0x1
phy_chain_rx_polarity_flip_physical{98.0}=0x0
phy_chain_rx_polarity_flip_physical{99.0}=0x0
phy_chain_rx_polarity_flip_physical{100.0}=0x1
phy_chain_tx_polarity_flip_physical{97.0}=0x1
phy_chain_tx_polarity_flip_physical{98.0}=0x1
phy_chain_tx_polarity_flip_physical{99.0}=0x0
phy_chain_tx_polarity_flip_physical{100.0}=0x0
#Port6
#FC 28
portmap_46=113:100
phy_chain_rx_lane_map_physical{113.0}=0x3021
phy_chain_tx_lane_map_physical{113.0}=0x0312
phy_chain_rx_polarity_flip_physical{113.0}=0x0
phy_chain_rx_polarity_flip_physical{114.0}=0x1
phy_chain_rx_polarity_flip_physical{115.0}=0x1
phy_chain_rx_polarity_flip_physical{116.0}=0x0
phy_chain_tx_polarity_flip_physical{113.0}=0x1
phy_chain_tx_polarity_flip_physical{114.0}=0x0
phy_chain_tx_polarity_flip_physical{115.0}=0x0
phy_chain_tx_polarity_flip_physical{116.0}=0x1
#Port7
#FC30
portmap_48=121:100
phy_chain_rx_lane_map_physical{121.0}=0x3021
phy_chain_tx_lane_map_physical{121.0}=0x2130
phy_chain_rx_polarity_flip_physical{121.0}=0x0
phy_chain_rx_polarity_flip_physical{122.0}=0x1
phy_chain_rx_polarity_flip_physical{123.0}=0x1
phy_chain_rx_polarity_flip_physical{124.0}=0x0
phy_chain_tx_polarity_flip_physical{121.0}=0x1
phy_chain_tx_polarity_flip_physical{122.0}=0x1
phy_chain_tx_polarity_flip_physical{123.0}=0x1
phy_chain_tx_polarity_flip_physical{124.0}=0x0
#Port8
#FC10
portmap_11=41:100
phy_chain_rx_lane_map_physical{41.0}=0x0132
phy_chain_tx_lane_map_physical{41.0}=0x1302
phy_chain_rx_polarity_flip_physical{41.0}=0x0
phy_chain_rx_polarity_flip_physical{42.0}=0x0
phy_chain_rx_polarity_flip_physical{43.0}=0x0
phy_chain_rx_polarity_flip_physical{44.0}=0x0
phy_chain_tx_polarity_flip_physical{41.0}=0x1
phy_chain_tx_polarity_flip_physical{42.0}=0x0
phy_chain_tx_polarity_flip_physical{43.0}=0x0
phy_chain_tx_polarity_flip_physical{44.0}=0x0
#Port9
#FC8
portmap_9=33:100
phy_chain_rx_lane_map_physical{33.0}=0x2310
phy_chain_tx_lane_map_physical{33.0}=0x0213
phy_chain_rx_polarity_flip_physical{33.0}=0x0
phy_chain_rx_polarity_flip_physical{34.0}=0x1
phy_chain_rx_polarity_flip_physical{35.0}=0x0
phy_chain_rx_polarity_flip_physical{36.0}=0x0
phy_chain_tx_polarity_flip_physical{33.0}=0x1
phy_chain_tx_polarity_flip_physical{34.0}=0x1
phy_chain_tx_polarity_flip_physical{35.0}=0x0
phy_chain_tx_polarity_flip_physical{36.0}=0x0
#Port10
#FC12
portmap_13=49:100
phy_chain_rx_lane_map_physical{49.0}=0x3210
phy_chain_tx_lane_map_physical{49.0}=0x3102
phy_chain_rx_polarity_flip_physical{49.0}=0x1
phy_chain_rx_polarity_flip_physical{50.0}=0x0
phy_chain_rx_polarity_flip_physical{51.0}=0x1
phy_chain_rx_polarity_flip_physical{52.0}=0x0
phy_chain_tx_polarity_flip_physical{49.0}=0x1
phy_chain_tx_polarity_flip_physical{50.0}=0x1
phy_chain_tx_polarity_flip_physical{51.0}=0x0
phy_chain_tx_polarity_flip_physical{52.0}=0x1
#Port11
#FC14
portmap_15=57:100
phy_chain_rx_lane_map_physical{57.0}=0x3210
phy_chain_tx_lane_map_physical{57.0}=0x1302
phy_chain_rx_polarity_flip_physical{57.0}=0x1
phy_chain_rx_polarity_flip_physical{58.0}=0x0
phy_chain_rx_polarity_flip_physical{59.0}=0x1
phy_chain_rx_polarity_flip_physical{60.0}=0x0
phy_chain_tx_polarity_flip_physical{57.0}=0x0
phy_chain_tx_polarity_flip_physical{58.0}=0x0
phy_chain_tx_polarity_flip_physical{59.0}=0x0
phy_chain_tx_polarity_flip_physical{60.0}=0x1
#Port12
#FC34
portmap_70=137:100
phy_chain_rx_lane_map_physical{137.0}=0x3210
phy_chain_tx_lane_map_physical{137.0}=0x0213
phy_chain_rx_polarity_flip_physical{137.0}=0x0
phy_chain_rx_polarity_flip_physical{138.0}=0x0
phy_chain_rx_polarity_flip_physical{139.0}=0x1
phy_chain_rx_polarity_flip_physical{140.0}=0x0
phy_chain_tx_polarity_flip_physical{137.0}=0x1
phy_chain_tx_polarity_flip_physical{138.0}=0x0
phy_chain_tx_polarity_flip_physical{139.0}=0x0
phy_chain_tx_polarity_flip_physical{140.0}=0x0
#Port13
#FC32
portmap_68=129:100
phy_chain_rx_lane_map_physical{129.0}=0x3021
phy_chain_tx_lane_map_physical{129.0}=0x1203
phy_chain_rx_polarity_flip_physical{129.0}=0x1
phy_chain_rx_polarity_flip_physical{130.0}=0x0
phy_chain_rx_polarity_flip_physical{131.0}=0x0
phy_chain_rx_polarity_flip_physical{132.0}=0x0
phy_chain_tx_polarity_flip_physical{129.0}=0x1
phy_chain_tx_polarity_flip_physical{130.0}=0x1
phy_chain_tx_polarity_flip_physical{131.0}=0x1
phy_chain_tx_polarity_flip_physical{132.0}=0x1
#Port14
#FC36
portmap_72=145:100
phy_chain_rx_lane_map_physical{145.0}=0x0213
phy_chain_tx_lane_map_physical{145.0}=0x2301
phy_chain_rx_polarity_flip_physical{145.0}=0x1
phy_chain_rx_polarity_flip_physical{146.0}=0x1
phy_chain_rx_polarity_flip_physical{147.0}=0x0
phy_chain_rx_polarity_flip_physical{148.0}=0x0
phy_chain_tx_polarity_flip_physical{145.0}=0x0
phy_chain_tx_polarity_flip_physical{146.0}=0x0
phy_chain_tx_polarity_flip_physical{147.0}=0x0
phy_chain_tx_polarity_flip_physical{148.0}=0x1
#Port15
#FC38
portmap_74=153:100
phy_chain_rx_lane_map_physical{153.0}=0x0213
phy_chain_tx_lane_map_physical{153.0}=0x1302
phy_chain_rx_polarity_flip_physical{153.0}=0x1
phy_chain_rx_polarity_flip_physical{154.0}=0x0
phy_chain_rx_polarity_flip_physical{155.0}=0x1
phy_chain_rx_polarity_flip_physical{156.0}=0x1
phy_chain_tx_polarity_flip_physical{153.0}=0x0
phy_chain_tx_polarity_flip_physical{154.0}=0x1
phy_chain_tx_polarity_flip_physical{155.0}=0x0
phy_chain_tx_polarity_flip_physical{156.0}=0x0
#Port16
#FC43
portmap_79=173:100
phy_chain_rx_lane_map_physical{173.0}=0x1032
phy_chain_tx_lane_map_physical{173.0}=0x1203
phy_chain_rx_polarity_flip_physical{173.0}=0x0
phy_chain_rx_polarity_flip_physical{174.0}=0x0
phy_chain_rx_polarity_flip_physical{175.0}=0x0
phy_chain_rx_polarity_flip_physical{176.0}=0x0
phy_chain_tx_polarity_flip_physical{173.0}=0x1
phy_chain_tx_polarity_flip_physical{174.0}=0x1
phy_chain_tx_polarity_flip_physical{175.0}=0x0
phy_chain_tx_polarity_flip_physical{176.0}=0x1
#Port17
#FC41
portmap_77=165:100
phy_chain_rx_lane_map_physical{165.0}=0x1230
phy_chain_tx_lane_map_physical{165.0}=0x2130
phy_chain_rx_polarity_flip_physical{165.0}=0x1
phy_chain_rx_polarity_flip_physical{166.0}=0x0
phy_chain_rx_polarity_flip_physical{167.0}=0x1
phy_chain_rx_polarity_flip_physical{168.0}=0x1
phy_chain_tx_polarity_flip_physical{165.0}=0x1
phy_chain_tx_polarity_flip_physical{166.0}=0x0
phy_chain_tx_polarity_flip_physical{167.0}=0x1
phy_chain_tx_polarity_flip_physical{168.0}=0x0
#Port18
#FC45
portmap_81=181:100
phy_chain_rx_lane_map_physical{181.0}=0x0312
phy_chain_tx_lane_map_physical{181.0}=0x3120
phy_chain_rx_polarity_flip_physical{181.0}=0x0
phy_chain_rx_polarity_flip_physical{182.0}=0x1
phy_chain_rx_polarity_flip_physical{183.0}=0x1
phy_chain_rx_polarity_flip_physical{184.0}=0x0
phy_chain_tx_polarity_flip_physical{181.0}=0x0
phy_chain_tx_polarity_flip_physical{182.0}=0x0
phy_chain_tx_polarity_flip_physical{183.0}=0x1
phy_chain_tx_polarity_flip_physical{184.0}=0x0
#Port19
#FC47
portmap_83=189:100
phy_chain_rx_lane_map_physical{189.0}=0x0132
phy_chain_tx_lane_map_physical{189.0}=0x3210
phy_chain_rx_polarity_flip_physical{189.0}=0x0
phy_chain_rx_polarity_flip_physical{190.0}=0x1
phy_chain_rx_polarity_flip_physical{191.0}=0x1
phy_chain_rx_polarity_flip_physical{192.0}=0x1
phy_chain_tx_polarity_flip_physical{189.0}=0x1
phy_chain_tx_polarity_flip_physical{190.0}=0x0
phy_chain_tx_polarity_flip_physical{191.0}=0x0
phy_chain_tx_polarity_flip_physical{192.0}=0x0
#Port20
#FC3
portmap_4=13:100
phy_chain_rx_lane_map_physical{13.0}=0x3120
phy_chain_tx_lane_map_physical{13.0}=0x3210
phy_chain_rx_polarity_flip_physical{13.0}=0x1
phy_chain_rx_polarity_flip_physical{14.0}=0x0
phy_chain_rx_polarity_flip_physical{15.0}=0x1
phy_chain_rx_polarity_flip_physical{16.0}=0x1
phy_chain_tx_polarity_flip_physical{13.0}=0x0
phy_chain_tx_polarity_flip_physical{14.0}=0x0
phy_chain_tx_polarity_flip_physical{15.0}=0x0
phy_chain_tx_polarity_flip_physical{16.0}=0x1
#Port21
#FC1
portmap_2=5:100
phy_chain_rx_lane_map_physical{5.0}=0x0213
phy_chain_tx_lane_map_physical{5.0}=0x0321
phy_chain_rx_polarity_flip_physical{5.0}=0x0
phy_chain_rx_polarity_flip_physical{6.0}=0x0
phy_chain_rx_polarity_flip_physical{7.0}=0x1
phy_chain_rx_polarity_flip_physical{8.0}=0x0
phy_chain_tx_polarity_flip_physical{5.0}=0x1
phy_chain_tx_polarity_flip_physical{6.0}=0x1
phy_chain_tx_polarity_flip_physical{7.0}=0x0
phy_chain_tx_polarity_flip_physical{8.0}=0x1
#Port22
#FC7
portmap_8=29:100
phy_chain_rx_lane_map_physical{29.0}=0x3021
phy_chain_tx_lane_map_physical{29.0}=0x2130
phy_chain_rx_polarity_flip_physical{29.0}=0x1
phy_chain_rx_polarity_flip_physical{30.0}=0x0
phy_chain_rx_polarity_flip_physical{31.0}=0x0
phy_chain_rx_polarity_flip_physical{32.0}=0x1
phy_chain_tx_polarity_flip_physical{29.0}=0x1
phy_chain_tx_polarity_flip_physical{30.0}=0x0
phy_chain_tx_polarity_flip_physical{31.0}=0x0
phy_chain_tx_polarity_flip_physical{32.0}=0x0
#Port23
#FC5
portmap_6=21:100
phy_chain_rx_lane_map_physical{21.0}=0x0321
phy_chain_tx_lane_map_physical{21.0}=0x0123
phy_chain_rx_polarity_flip_physical{21.0}=0x1
phy_chain_rx_polarity_flip_physical{22.0}=0x0
phy_chain_rx_polarity_flip_physical{23.0}=0x1
phy_chain_rx_polarity_flip_physical{24.0}=0x0
phy_chain_tx_polarity_flip_physical{21.0}=0x0
phy_chain_tx_polarity_flip_physical{22.0}=0x1
phy_chain_tx_polarity_flip_physical{23.0}=0x1
phy_chain_tx_polarity_flip_physical{24.0}=0x1
#Port24
#FC51
portmap_105=205:100
phy_chain_rx_lane_map_physical{205.0}=0x0132
phy_chain_tx_lane_map_physical{205.0}=0x1230
phy_chain_rx_polarity_flip_physical{205.0}=0x1
phy_chain_rx_polarity_flip_physical{206.0}=0x1
phy_chain_rx_polarity_flip_physical{207.0}=0x1
phy_chain_rx_polarity_flip_physical{208.0}=0x0
phy_chain_tx_polarity_flip_physical{205.0}=0x0
phy_chain_tx_polarity_flip_physical{206.0}=0x1
phy_chain_tx_polarity_flip_physical{207.0}=0x0
phy_chain_tx_polarity_flip_physical{208.0}=0x1
#Port25
#FC49
portmap_103=197:100
phy_chain_rx_lane_map_physical{197.0}=0x1230
phy_chain_tx_lane_map_physical{197.0}=0x3021
phy_chain_rx_polarity_flip_physical{197.0}=0x0
phy_chain_rx_polarity_flip_physical{198.0}=0x0
phy_chain_rx_polarity_flip_physical{199.0}=0x0
phy_chain_rx_polarity_flip_physical{200.0}=0x0
phy_chain_tx_polarity_flip_physical{197.0}=0x1
phy_chain_tx_polarity_flip_physical{198.0}=0x0
phy_chain_tx_polarity_flip_physical{199.0}=0x1
phy_chain_tx_polarity_flip_physical{200.0}=0x0
#Port26
#FC53
portmap_107=213:100
phy_chain_rx_lane_map_physical{213.0}=0x3210
phy_chain_tx_lane_map_physical{213.0}=0x1230
phy_chain_rx_polarity_flip_physical{213.0}=0x0
phy_chain_rx_polarity_flip_physical{214.0}=0x1
phy_chain_rx_polarity_flip_physical{215.0}=0x0
phy_chain_rx_polarity_flip_physical{216.0}=0x1
phy_chain_tx_polarity_flip_physical{213.0}=0x0
phy_chain_tx_polarity_flip_physical{214.0}=0x0
phy_chain_tx_polarity_flip_physical{215.0}=0x0
phy_chain_tx_polarity_flip_physical{216.0}=0x1
#Port27
#FC55
portmap_109=221:100
phy_chain_rx_lane_map_physical{221.0}=0x3210
phy_chain_tx_lane_map_physical{221.0}=0x3210
phy_chain_rx_polarity_flip_physical{221.0}=0x1
phy_chain_rx_polarity_flip_physical{222.0}=0x1
phy_chain_rx_polarity_flip_physical{223.0}=0x0
phy_chain_rx_polarity_flip_physical{224.0}=0x0
phy_chain_tx_polarity_flip_physical{221.0}=0x0
phy_chain_tx_polarity_flip_physical{222.0}=0x0
phy_chain_tx_polarity_flip_physical{223.0}=0x0
phy_chain_tx_polarity_flip_physical{224.0}=0x0
#Port28
#FC57
portmap_111=229:100
phy_chain_rx_lane_map_physical{229.0}=0x2301
phy_chain_tx_lane_map_physical{229.0}=0x3210
phy_chain_rx_polarity_flip_physical{229.0}=0x1
phy_chain_rx_polarity_flip_physical{230.0}=0x1
phy_chain_rx_polarity_flip_physical{231.0}=0x0
phy_chain_rx_polarity_flip_physical{232.0}=0x1
phy_chain_tx_polarity_flip_physical{229.0}=0x0
phy_chain_tx_polarity_flip_physical{230.0}=0x1
phy_chain_tx_polarity_flip_physical{231.0}=0x0
phy_chain_tx_polarity_flip_physical{232.0}=0x0
#Port29
#FC59
portmap_113=237:100
phy_chain_rx_lane_map_physical{237.0}=0x0123
phy_chain_tx_lane_map_physical{237.0}=0x3210
phy_chain_rx_polarity_flip_physical{237.0}=0x1
phy_chain_rx_polarity_flip_physical{238.0}=0x0
phy_chain_rx_polarity_flip_physical{239.0}=0x1
phy_chain_rx_polarity_flip_physical{240.0}=0x1
phy_chain_tx_polarity_flip_physical{237.0}=0x1
phy_chain_tx_polarity_flip_physical{238.0}=0x1
phy_chain_tx_polarity_flip_physical{239.0}=0x0
phy_chain_tx_polarity_flip_physical{240.0}=0x0
#Port30
#FC61
portmap_115=245:100
phy_chain_rx_lane_map_physical{245.0}=0x0213
phy_chain_tx_lane_map_physical{245.0}=0x3210
phy_chain_rx_polarity_flip_physical{245.0}=0x0
phy_chain_rx_polarity_flip_physical{246.0}=0x0
phy_chain_rx_polarity_flip_physical{247.0}=0x1
phy_chain_rx_polarity_flip_physical{248.0}=0x1
phy_chain_tx_polarity_flip_physical{245.0}=0x1
phy_chain_tx_polarity_flip_physical{246.0}=0x0
phy_chain_tx_polarity_flip_physical{247.0}=0x1
phy_chain_tx_polarity_flip_physical{248.0}=0x0
#Port31
#FC63
portmap_117=253:100
phy_chain_rx_lane_map_physical{253.0}=0x0213
phy_chain_tx_lane_map_physical{253.0}=0x0312
phy_chain_rx_polarity_flip_physical{253.0}=0x0
phy_chain_rx_polarity_flip_physical{254.0}=0x0
phy_chain_rx_polarity_flip_physical{255.0}=0x0
phy_chain_rx_polarity_flip_physical{256.0}=0x1
phy_chain_tx_polarity_flip_physical{253.0}=0x0
phy_chain_tx_polarity_flip_physical{254.0}=0x1
phy_chain_tx_polarity_flip_physical{255.0}=0x0
phy_chain_tx_polarity_flip_physical{256.0}=0x0
#Port32
#FC17
portmap_35=69:100
phy_chain_rx_lane_map_physical{69.0}=0x1032
phy_chain_tx_lane_map_physical{69.0}=0x3102
phy_chain_rx_polarity_flip_physical{69.0}=0x1
phy_chain_rx_polarity_flip_physical{70.0}=0x0
phy_chain_rx_polarity_flip_physical{71.0}=0x0
phy_chain_rx_polarity_flip_physical{72.0}=0x1
phy_chain_tx_polarity_flip_physical{69.0}=0x0
phy_chain_tx_polarity_flip_physical{70.0}=0x0
phy_chain_tx_polarity_flip_physical{71.0}=0x1
phy_chain_tx_polarity_flip_physical{72.0}=0x1
#Port33
#FC19
portmap_37=77:100
phy_chain_rx_lane_map_physical{77.0}=0x1230
phy_chain_tx_lane_map_physical{77.0}=0x3021
phy_chain_rx_polarity_flip_physical{77.0}=0x1
phy_chain_rx_polarity_flip_physical{78.0}=0x0
phy_chain_rx_polarity_flip_physical{79.0}=0x1
phy_chain_rx_polarity_flip_physical{80.0}=0x0
phy_chain_tx_polarity_flip_physical{77.0}=0x0
phy_chain_tx_polarity_flip_physical{78.0}=0x0
phy_chain_tx_polarity_flip_physical{79.0}=0x1
phy_chain_tx_polarity_flip_physical{80.0}=0x0
#Port34
#FC23
portmap_41=93:100
phy_chain_rx_lane_map_physical{93.0}=0x1032
phy_chain_tx_lane_map_physical{93.0}=0x0231
phy_chain_rx_polarity_flip_physical{93.0}=0x1
phy_chain_rx_polarity_flip_physical{94.0}=0x1
phy_chain_rx_polarity_flip_physical{95.0}=0x1
phy_chain_rx_polarity_flip_physical{96.0}=0x1
phy_chain_tx_polarity_flip_physical{93.0}=0x0
phy_chain_tx_polarity_flip_physical{94.0}=0x1
phy_chain_tx_polarity_flip_physical{95.0}=0x1
phy_chain_tx_polarity_flip_physical{96.0}=0x1
#Port35
#FC21
portmap_39=85:100
phy_chain_rx_lane_map_physical{85.0}=0x0312
phy_chain_tx_lane_map_physical{85.0}=0x1230
phy_chain_rx_polarity_flip_physical{85.0}=0x0
phy_chain_rx_polarity_flip_physical{86.0}=0x0
phy_chain_rx_polarity_flip_physical{87.0}=0x0
phy_chain_rx_polarity_flip_physical{88.0}=0x1
phy_chain_tx_polarity_flip_physical{85.0}=0x1
phy_chain_tx_polarity_flip_physical{86.0}=0x0
phy_chain_tx_polarity_flip_physical{87.0}=0x1
phy_chain_tx_polarity_flip_physical{88.0}=0x0
#Port36
#FC25
portmap_43=101:100
phy_chain_rx_lane_map_physical{101.0}=0x1302
phy_chain_tx_lane_map_physical{101.0}=0x0213
phy_chain_rx_polarity_flip_physical{101.0}=0x1
phy_chain_rx_polarity_flip_physical{102.0}=0x0
phy_chain_rx_polarity_flip_physical{103.0}=0x0
phy_chain_rx_polarity_flip_physical{104.0}=0x0
phy_chain_tx_polarity_flip_physical{101.0}=0x0
phy_chain_tx_polarity_flip_physical{102.0}=0x1
phy_chain_tx_polarity_flip_physical{103.0}=0x0
phy_chain_tx_polarity_flip_physical{104.0}=0x1
#Port37
#FC27
portmap_45=109:100
phy_chain_rx_lane_map_physical{109.0}=0x0213
phy_chain_tx_lane_map_physical{109.0}=0x1032
phy_chain_rx_polarity_flip_physical{109.0}=0x1
phy_chain_rx_polarity_flip_physical{110.0}=0x1
phy_chain_rx_polarity_flip_physical{111.0}=0x0
phy_chain_rx_polarity_flip_physical{112.0}=0x0
phy_chain_tx_polarity_flip_physical{109.0}=0x0
phy_chain_tx_polarity_flip_physical{110.0}=0x1
phy_chain_tx_polarity_flip_physical{111.0}=0x1
phy_chain_tx_polarity_flip_physical{112.0}=0x1
#Port38
#FC31
portmap_49=125:100
phy_chain_rx_lane_map_physical{125.0}=0x2130
phy_chain_tx_lane_map_physical{125.0}=0x1203
phy_chain_rx_polarity_flip_physical{125.0}=0x0
phy_chain_rx_polarity_flip_physical{126.0}=0x0
phy_chain_rx_polarity_flip_physical{127.0}=0x1
phy_chain_rx_polarity_flip_physical{128.0}=0x1
phy_chain_tx_polarity_flip_physical{125.0}=0x0
phy_chain_tx_polarity_flip_physical{126.0}=0x1
phy_chain_tx_polarity_flip_physical{127.0}=0x1
phy_chain_tx_polarity_flip_physical{128.0}=0x1
#Port39
#FC29
portmap_47=117:100
phy_chain_rx_lane_map_physical{117.0}=0x3102
phy_chain_tx_lane_map_physical{117.0}=0x2310
phy_chain_rx_polarity_flip_physical{117.0}=0x1
phy_chain_rx_polarity_flip_physical{118.0}=0x0
phy_chain_rx_polarity_flip_physical{119.0}=0x1
phy_chain_rx_polarity_flip_physical{120.0}=0x0
phy_chain_tx_polarity_flip_physical{117.0}=0x1
phy_chain_tx_polarity_flip_physical{118.0}=0x0
phy_chain_tx_polarity_flip_physical{119.0}=0x1
phy_chain_tx_polarity_flip_physical{120.0}=0x0
#Port40
#FC9
portmap_10=37:100
phy_chain_rx_lane_map_physical{37.0}=0x3210
phy_chain_tx_lane_map_physical{37.0}=0x1302
phy_chain_rx_polarity_flip_physical{37.0}=0x1
phy_chain_rx_polarity_flip_physical{38.0}=0x0
phy_chain_rx_polarity_flip_physical{39.0}=0x0
phy_chain_rx_polarity_flip_physical{40.0}=0x0
phy_chain_tx_polarity_flip_physical{37.0}=0x1
phy_chain_tx_polarity_flip_physical{38.0}=0x0
phy_chain_tx_polarity_flip_physical{39.0}=0x1
phy_chain_tx_polarity_flip_physical{40.0}=0x1
#Port41
#FC11
portmap_12=45:100
phy_chain_rx_lane_map_physical{45.0}=0x3210
phy_chain_tx_lane_map_physical{45.0}=0x0123
phy_chain_rx_polarity_flip_physical{45.0}=0x0
phy_chain_rx_polarity_flip_physical{46.0}=0x0
phy_chain_rx_polarity_flip_physical{47.0}=0x0
phy_chain_rx_polarity_flip_physical{48.0}=0x0
phy_chain_tx_polarity_flip_physical{45.0}=0x0
phy_chain_tx_polarity_flip_physical{46.0}=0x1
phy_chain_tx_polarity_flip_physical{47.0}=0x0
phy_chain_tx_polarity_flip_physical{48.0}=0x1
#Port42
#FC15
portmap_16=61:100
phy_chain_rx_lane_map_physical{61.0}=0x3210
phy_chain_tx_lane_map_physical{61.0}=0x1230
phy_chain_rx_polarity_flip_physical{61.0}=0x0
phy_chain_rx_polarity_flip_physical{62.0}=0x1
phy_chain_rx_polarity_flip_physical{63.0}=0x0
phy_chain_rx_polarity_flip_physical{64.0}=0x0
phy_chain_tx_polarity_flip_physical{61.0}=0x0
phy_chain_tx_polarity_flip_physical{62.0}=0x1
phy_chain_tx_polarity_flip_physical{63.0}=0x1
phy_chain_tx_polarity_flip_physical{64.0}=0x0
#Port43
#FC13
portmap_14=53:100
phy_chain_rx_lane_map_physical{53.0}=0x3210
phy_chain_tx_lane_map_physical{53.0}=0x3210
phy_chain_rx_polarity_flip_physical{53.0}=0x0
phy_chain_rx_polarity_flip_physical{54.0}=0x0
phy_chain_rx_polarity_flip_physical{55.0}=0x1
phy_chain_rx_polarity_flip_physical{56.0}=0x0
phy_chain_tx_polarity_flip_physical{53.0}=0x1
phy_chain_tx_polarity_flip_physical{54.0}=0x1
phy_chain_tx_polarity_flip_physical{55.0}=0x1
phy_chain_tx_polarity_flip_physical{56.0}=0x0
#Port44
#FC33
portmap_69=133:100
phy_chain_rx_lane_map_physical{133.0}=0x0312
phy_chain_tx_lane_map_physical{133.0}=0x2310
phy_chain_rx_polarity_flip_physical{133.0}=0x0
phy_chain_rx_polarity_flip_physical{134.0}=0x0
phy_chain_rx_polarity_flip_physical{135.0}=0x1
phy_chain_rx_polarity_flip_physical{136.0}=0x0
phy_chain_tx_polarity_flip_physical{133.0}=0x0
phy_chain_tx_polarity_flip_physical{134.0}=0x1
phy_chain_tx_polarity_flip_physical{135.0}=0x0
phy_chain_tx_polarity_flip_physical{136.0}=0x1
#Port45
#FC35
portmap_71=141:100
phy_chain_rx_lane_map_physical{141.0}=0x3012
phy_chain_tx_lane_map_physical{141.0}=0x0123
phy_chain_rx_polarity_flip_physical{141.0}=0x1
phy_chain_rx_polarity_flip_physical{142.0}=0x0
phy_chain_rx_polarity_flip_physical{143.0}=0x1
phy_chain_rx_polarity_flip_physical{144.0}=0x0
phy_chain_tx_polarity_flip_physical{141.0}=0x1
phy_chain_tx_polarity_flip_physical{142.0}=0x1
phy_chain_tx_polarity_flip_physical{143.0}=0x0
phy_chain_tx_polarity_flip_physical{144.0}=0x0
#Port46
#FC39
portmap_75=157:100
phy_chain_rx_lane_map_physical{157.0}=0x2103
phy_chain_tx_lane_map_physical{157.0}=0x0231
phy_chain_rx_polarity_flip_physical{157.0}=0x0
phy_chain_rx_polarity_flip_physical{158.0}=0x0
phy_chain_rx_polarity_flip_physical{159.0}=0x1
phy_chain_rx_polarity_flip_physical{160.0}=0x0
phy_chain_tx_polarity_flip_physical{157.0}=0x0
phy_chain_tx_polarity_flip_physical{158.0}=0x1
phy_chain_tx_polarity_flip_physical{159.0}=0x0
phy_chain_tx_polarity_flip_physical{160.0}=0x0
#Port47
#FC37
portmap_73=149:100
phy_chain_rx_lane_map_physical{149.0}=0x3120
phy_chain_tx_lane_map_physical{149.0}=0x1023
phy_chain_rx_polarity_flip_physical{149.0}=0x0
phy_chain_rx_polarity_flip_physical{150.0}=0x1
phy_chain_rx_polarity_flip_physical{151.0}=0x0
phy_chain_rx_polarity_flip_physical{152.0}=0x0
phy_chain_tx_polarity_flip_physical{149.0}=0x1
phy_chain_tx_polarity_flip_physical{150.0}=0x0
phy_chain_tx_polarity_flip_physical{151.0}=0x0
phy_chain_tx_polarity_flip_physical{152.0}=0x1
#Port48
#FC40
portmap_76=161:100
phy_chain_rx_lane_map_physical{161.0}=0x3012
phy_chain_tx_lane_map_physical{161.0}=0x1023
phy_chain_rx_polarity_flip_physical{161.0}=0x1
phy_chain_rx_polarity_flip_physical{162.0}=0x1
phy_chain_rx_polarity_flip_physical{163.0}=0x0
phy_chain_rx_polarity_flip_physical{164.0}=0x0
phy_chain_tx_polarity_flip_physical{161.0}=0x0
phy_chain_tx_polarity_flip_physical{162.0}=0x1
phy_chain_tx_polarity_flip_physical{163.0}=0x0
phy_chain_tx_polarity_flip_physical{164.0}=0x0
#Port49
#FC42
portmap_78=169:100
phy_chain_rx_lane_map_physical{169.0}=0x3210
phy_chain_tx_lane_map_physical{169.0}=0x2031
phy_chain_rx_polarity_flip_physical{169.0}=0x0
phy_chain_rx_polarity_flip_physical{170.0}=0x1
phy_chain_rx_polarity_flip_physical{171.0}=0x0
phy_chain_rx_polarity_flip_physical{172.0}=0x0
phy_chain_tx_polarity_flip_physical{169.0}=0x1
phy_chain_tx_polarity_flip_physical{170.0}=0x0
phy_chain_tx_polarity_flip_physical{171.0}=0x0
phy_chain_tx_polarity_flip_physical{172.0}=0x0
#Port50
#FC46
portmap_82=185:100
phy_chain_rx_lane_map_physical{185.0}=0x2310
phy_chain_tx_lane_map_physical{185.0}=0x3021
phy_chain_rx_polarity_flip_physical{185.0}=0x1
phy_chain_rx_polarity_flip_physical{186.0}=0x0
phy_chain_rx_polarity_flip_physical{187.0}=0x1
phy_chain_rx_polarity_flip_physical{188.0}=0x0
phy_chain_tx_polarity_flip_physical{185.0}=0x0
phy_chain_tx_polarity_flip_physical{186.0}=0x1
phy_chain_tx_polarity_flip_physical{187.0}=0x0
phy_chain_tx_polarity_flip_physical{188.0}=0x0
#Port51
#FC44
portmap_80=177:100
phy_chain_rx_lane_map_physical{177.0}=0x1032
phy_chain_tx_lane_map_physical{177.0}=0x2301
phy_chain_rx_polarity_flip_physical{177.0}=0x1
phy_chain_rx_polarity_flip_physical{178.0}=0x1
phy_chain_rx_polarity_flip_physical{179.0}=0x0
phy_chain_rx_polarity_flip_physical{180.0}=0x1
phy_chain_tx_polarity_flip_physical{177.0}=0x1
phy_chain_tx_polarity_flip_physical{178.0}=0x1
phy_chain_tx_polarity_flip_physical{179.0}=0x1
phy_chain_tx_polarity_flip_physical{180.0}=0x0
#Port52
#FC6
portmap_7=25:100
phy_chain_rx_lane_map_physical{25.0}=0x3102
phy_chain_tx_lane_map_physical{25.0}=0x0132
phy_chain_rx_polarity_flip_physical{25.0}=0x0
phy_chain_rx_polarity_flip_physical{26.0}=0x0
phy_chain_rx_polarity_flip_physical{27.0}=0x1
phy_chain_rx_polarity_flip_physical{28.0}=0x0
phy_chain_tx_polarity_flip_physical{25.0}=0x0
phy_chain_tx_polarity_flip_physical{26.0}=0x1
phy_chain_tx_polarity_flip_physical{27.0}=0x0
phy_chain_tx_polarity_flip_physical{28.0}=0x1
#Port53
#FC4
portmap_5=17:100
phy_chain_rx_lane_map_physical{17.0}=0x3120
phy_chain_tx_lane_map_physical{17.0}=0x3021
phy_chain_rx_polarity_flip_physical{17.0}=0x0
phy_chain_rx_polarity_flip_physical{18.0}=0x1
phy_chain_rx_polarity_flip_physical{19.0}=0x0
phy_chain_rx_polarity_flip_physical{20.0}=0x0
phy_chain_tx_polarity_flip_physical{17.0}=0x0
phy_chain_tx_polarity_flip_physical{18.0}=0x0
phy_chain_tx_polarity_flip_physical{19.0}=0x1
phy_chain_tx_polarity_flip_physical{20.0}=0x0
#Port54
#FC0
portmap_1=1:100
phy_chain_rx_lane_map_physical{1.0}=0x2130
phy_chain_tx_lane_map_physical{1.0}=0x1203
phy_chain_rx_polarity_flip_physical{1.0}=0x1
phy_chain_rx_polarity_flip_physical{2.0}=0x0
phy_chain_rx_polarity_flip_physical{3.0}=0x1
phy_chain_rx_polarity_flip_physical{4.0}=0x1
phy_chain_tx_polarity_flip_physical{1.0}=0x0
phy_chain_tx_polarity_flip_physical{2.0}=0x0
phy_chain_tx_polarity_flip_physical{3.0}=0x0
phy_chain_tx_polarity_flip_physical{4.0}=0x1
#Port55
#FC2
portmap_3=9:100
phy_chain_rx_lane_map_physical{9.0}=0x1203
phy_chain_tx_lane_map_physical{9.0}=0x1230
phy_chain_rx_polarity_flip_physical{9.0}=0x0
phy_chain_rx_polarity_flip_physical{10.0}=0x1
phy_chain_rx_polarity_flip_physical{11.0}=0x0
phy_chain_rx_polarity_flip_physical{12.0}=0x0
phy_chain_tx_polarity_flip_physical{9.0}=0x1
phy_chain_tx_polarity_flip_physical{10.0}=0x0
phy_chain_tx_polarity_flip_physical{11.0}=0x1
phy_chain_tx_polarity_flip_physical{12.0}=0x0
#Port56
#FC48
portmap_102=193:100
phy_chain_rx_lane_map_physical{193.0}=0x2103
phy_chain_tx_lane_map_physical{193.0}=0x1230
phy_chain_rx_polarity_flip_physical{193.0}=0x0
phy_chain_rx_polarity_flip_physical{194.0}=0x1
phy_chain_rx_polarity_flip_physical{195.0}=0x0
phy_chain_rx_polarity_flip_physical{196.0}=0x1
phy_chain_tx_polarity_flip_physical{193.0}=0x0
phy_chain_tx_polarity_flip_physical{194.0}=0x0
phy_chain_tx_polarity_flip_physical{195.0}=0x1
phy_chain_tx_polarity_flip_physical{196.0}=0x0
#Port57
#FC50
portmap_104=201:100
phy_chain_rx_lane_map_physical{201.0}=0x0321
phy_chain_tx_lane_map_physical{201.0}=0x3021
phy_chain_rx_polarity_flip_physical{201.0}=0x0
phy_chain_rx_polarity_flip_physical{202.0}=0x0
phy_chain_rx_polarity_flip_physical{203.0}=0x1
phy_chain_rx_polarity_flip_physical{204.0}=0x0
phy_chain_tx_polarity_flip_physical{201.0}=0x1
phy_chain_tx_polarity_flip_physical{202.0}=0x1
phy_chain_tx_polarity_flip_physical{203.0}=0x0
phy_chain_tx_polarity_flip_physical{204.0}=0x1
#Port58
#FC54
portmap_108=217:100
phy_chain_rx_lane_map_physical{217.0}=0x1203
phy_chain_tx_lane_map_physical{217.0}=0x2031
phy_chain_rx_polarity_flip_physical{217.0}=0x1
phy_chain_rx_polarity_flip_physical{218.0}=0x0
phy_chain_rx_polarity_flip_physical{219.0}=0x1
phy_chain_rx_polarity_flip_physical{220.0}=0x1
phy_chain_tx_polarity_flip_physical{217.0}=0x1
phy_chain_tx_polarity_flip_physical{218.0}=0x0
phy_chain_tx_polarity_flip_physical{219.0}=0x1
phy_chain_tx_polarity_flip_physical{220.0}=0x0
#Port59
#FC52
portmap_106=209:100
phy_chain_rx_lane_map_physical{209.0}=0x0321
phy_chain_tx_lane_map_physical{209.0}=0x3102
phy_chain_rx_polarity_flip_physical{209.0}=0x0
phy_chain_rx_polarity_flip_physical{210.0}=0x0
phy_chain_rx_polarity_flip_physical{211.0}=0x1
phy_chain_rx_polarity_flip_physical{212.0}=0x0
phy_chain_tx_polarity_flip_physical{209.0}=0x0
phy_chain_tx_polarity_flip_physical{210.0}=0x0
phy_chain_tx_polarity_flip_physical{211.0}=0x1
phy_chain_tx_polarity_flip_physical{212.0}=0x0
#Port60
#FC56
portmap_110=225:100
phy_chain_rx_lane_map_physical{225.0}=0x2103
phy_chain_tx_lane_map_physical{225.0}=0x2031
phy_chain_rx_polarity_flip_physical{225.0}=0x0
phy_chain_rx_polarity_flip_physical{226.0}=0x0
phy_chain_rx_polarity_flip_physical{227.0}=0x1
phy_chain_rx_polarity_flip_physical{228.0}=0x1
phy_chain_tx_polarity_flip_physical{225.0}=0x1
phy_chain_tx_polarity_flip_physical{226.0}=0x0
phy_chain_tx_polarity_flip_physical{227.0}=0x1
phy_chain_tx_polarity_flip_physical{228.0}=0x1
#Port61
#FC58
portmap_112=233:100
phy_chain_rx_lane_map_physical{233.0}=0x2130
phy_chain_tx_lane_map_physical{233.0}=0x0312
phy_chain_rx_polarity_flip_physical{233.0}=0x0
phy_chain_rx_polarity_flip_physical{234.0}=0x1
phy_chain_rx_polarity_flip_physical{235.0}=0x1
phy_chain_rx_polarity_flip_physical{236.0}=0x0
phy_chain_tx_polarity_flip_physical{233.0}=0x0
phy_chain_tx_polarity_flip_physical{234.0}=0x0
phy_chain_tx_polarity_flip_physical{235.0}=0x1
phy_chain_tx_polarity_flip_physical{236.0}=0x0
#Port62
#FC62
portmap_116=249:100
phy_chain_rx_lane_map_physical{249.0}=0x1302
phy_chain_tx_lane_map_physical{249.0}=0x1302
phy_chain_rx_polarity_flip_physical{249.0}=0x0
phy_chain_rx_polarity_flip_physical{250.0}=0x1
phy_chain_rx_polarity_flip_physical{251.0}=0x0
phy_chain_rx_polarity_flip_physical{252.0}=0x1
phy_chain_tx_polarity_flip_physical{249.0}=0x1
phy_chain_tx_polarity_flip_physical{250.0}=0x1
phy_chain_tx_polarity_flip_physical{251.0}=0x1
phy_chain_tx_polarity_flip_physical{252.0}=0x1
#Port63
#FC60
portmap_114=241:100
phy_chain_rx_lane_map_physical{241.0}=0x3012
phy_chain_tx_lane_map_physical{241.0}=0x2301
phy_chain_rx_polarity_flip_physical{241.0}=0x1
phy_chain_rx_polarity_flip_physical{242.0}=0x1
phy_chain_rx_polarity_flip_physical{243.0}=0x0
phy_chain_rx_polarity_flip_physical{244.0}=0x1
phy_chain_tx_polarity_flip_physical{241.0}=0x1
phy_chain_tx_polarity_flip_physical{242.0}=0x0
phy_chain_tx_polarity_flip_physical{243.0}=0x1
phy_chain_tx_polarity_flip_physical{244.0}=0x0

View File

@ -0,0 +1 @@
Juniper-QFX5210-64C t1

View File

@ -0,0 +1,2 @@
CONSOLE_SPEED=9600
ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="tg3.short_preamble=1 tg3.bcm5718s_reset=1"

View File

@ -0,0 +1,155 @@
m CMIC_LEDUP0_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000
m CMIC_LEDUP1_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000
m CMIC_LEDUP2_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000
m CMIC_LEDUP3_CLK_PARAMS REFRESH_CYCLE_PERIOD=0xc00000
m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60
m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56
m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52
m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48
m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44
m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40
m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36
m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32
m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28
m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24
m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20
m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16
m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12
m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8
m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4
m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0
m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0
m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4
m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8
m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12
m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16
m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20
m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24
m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28
m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32
m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36
m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40
m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44
m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48
m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52
m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56
m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60
m CMIC_LEDUP2_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=63 REMAP_PORT_1=62 REMAP_PORT_2=61 REMAP_PORT_3=60
m CMIC_LEDUP2_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=59 REMAP_PORT_5=58 REMAP_PORT_6=57 REMAP_PORT_7=56
m CMIC_LEDUP2_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=55 REMAP_PORT_9=54 REMAP_PORT_10=53 REMAP_PORT_11=52
m CMIC_LEDUP2_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=51 REMAP_PORT_13=50 REMAP_PORT_14=49 REMAP_PORT_15=48
m CMIC_LEDUP2_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47 REMAP_PORT_17=46 REMAP_PORT_18=45 REMAP_PORT_19=44
m CMIC_LEDUP2_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43 REMAP_PORT_21=42 REMAP_PORT_22=41 REMAP_PORT_23=40
m CMIC_LEDUP2_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39 REMAP_PORT_25=38 REMAP_PORT_26=37 REMAP_PORT_27=36
m CMIC_LEDUP2_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35 REMAP_PORT_29=34 REMAP_PORT_30=33 REMAP_PORT_31=32
m CMIC_LEDUP2_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=31 REMAP_PORT_33=30 REMAP_PORT_34=29 REMAP_PORT_35=28
m CMIC_LEDUP2_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=27 REMAP_PORT_37=26 REMAP_PORT_38=25 REMAP_PORT_39=24
m CMIC_LEDUP2_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=23 REMAP_PORT_41=22 REMAP_PORT_42=21 REMAP_PORT_43=20
m CMIC_LEDUP2_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=19 REMAP_PORT_45=18 REMAP_PORT_46=17 REMAP_PORT_47=16
m CMIC_LEDUP2_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15 REMAP_PORT_49=14 REMAP_PORT_50=13 REMAP_PORT_51=12
m CMIC_LEDUP2_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11 REMAP_PORT_53=10 REMAP_PORT_54=9 REMAP_PORT_55=8
m CMIC_LEDUP2_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7 REMAP_PORT_57=6 REMAP_PORT_58=5 REMAP_PORT_59=4
m CMIC_LEDUP2_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3 REMAP_PORT_61=2 REMAP_PORT_62=1 REMAP_PORT_63=0
m CMIC_LEDUP3_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=3 REMAP_PORT_1=2 REMAP_PORT_2=1 REMAP_PORT_3=0
m CMIC_LEDUP3_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=7 REMAP_PORT_5=6 REMAP_PORT_6=5 REMAP_PORT_7=4
m CMIC_LEDUP3_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=11 REMAP_PORT_9=10 REMAP_PORT_10=9 REMAP_PORT_11=8
m CMIC_LEDUP3_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=15 REMAP_PORT_13=14 REMAP_PORT_14=13 REMAP_PORT_15=12
m CMIC_LEDUP3_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=19 REMAP_PORT_17=18 REMAP_PORT_18=17 REMAP_PORT_19=16
m CMIC_LEDUP3_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=23 REMAP_PORT_21=22 REMAP_PORT_22=21 REMAP_PORT_23=20
m CMIC_LEDUP3_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=27 REMAP_PORT_25=26 REMAP_PORT_26=25 REMAP_PORT_27=24
m CMIC_LEDUP3_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=31 REMAP_PORT_29=30 REMAP_PORT_30=29 REMAP_PORT_31=28
m CMIC_LEDUP3_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=35 REMAP_PORT_33=34 REMAP_PORT_34=33 REMAP_PORT_35=32
m CMIC_LEDUP3_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=39 REMAP_PORT_37=38 REMAP_PORT_38=37 REMAP_PORT_39=36
m CMIC_LEDUP3_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=43 REMAP_PORT_41=42 REMAP_PORT_42=41 REMAP_PORT_43=40
m CMIC_LEDUP3_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=47 REMAP_PORT_45=46 REMAP_PORT_46=45 REMAP_PORT_47=44
m CMIC_LEDUP3_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=51 REMAP_PORT_49=50 REMAP_PORT_50=49 REMAP_PORT_51=48
m CMIC_LEDUP3_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=55 REMAP_PORT_53=54 REMAP_PORT_54=53 REMAP_PORT_55=52
m CMIC_LEDUP3_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=59 REMAP_PORT_57=58 REMAP_PORT_58=57 REMAP_PORT_59=56
m CMIC_LEDUP3_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=63 REMAP_PORT_61=62 REMAP_PORT_62=61 REMAP_PORT_63=60
led 0 stop
led 0 prog \
02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \
02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \
67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \
86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \
3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \
98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \
4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \
F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \
71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \
52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \
74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \
98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \
88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \
88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \
84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
led 1 stop
led 1 prog \
02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \
02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \
67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \
86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \
3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \
98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \
4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \
F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \
71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \
52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \
74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \
98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \
88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \
88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \
84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
led 2 stop
led 2 prog \
02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \
02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \
67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \
86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \
3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \
98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \
4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \
F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \
71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \
52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \
74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \
98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \
88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \
88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \
84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
led 3 stop
led 3 prog \
02 FD 42 80 02 FF 42 00 02 FE 42 00 02 FA 42 E0 \
02 FB 42 40 06 F9 D2 00 74 1E 02 F9 42 03 67 AC \
67 C3 67 52 86 FE 67 C3 67 52 86 FE 67 C3 67 52 \
86 FE 67 C3 67 52 86 FE 06 FB D6 FE 74 1E 86 FC \
3E FA 06 FE 88 4A 03 71 4C 67 84 57 67 84 57 67 \
98 57 06 FE 88 80 4A 00 27 97 75 4F 90 4A 00 27 \
4A 01 27 B7 97 71 69 77 42 06 F9 D6 FC 74 7C 02 \
F9 4A 07 37 4E 07 02 FC 42 00 4E 07 06 F9 0A 07 \
71 4F 77 42 16 FF 06 FD 17 4D DA 07 74 95 12 FF \
52 00 86 FD 57 86 FF 57 16 FF 06 FD 07 4D DA 07 \
74 A9 12 FF 52 00 86 FD 57 86 FF 57 06 FE C2 FC \
98 98 12 F4 50 C2 FC 98 98 F2 F0 14 06 F4 C2 03 \
88 77 D1 06 FE C2 FC 98 98 F2 E0 14 06 FE C2 03 \
88 18 71 E2 80 18 71 DD 67 98 67 98 57 67 98 67 \
84 57 80 18 71 EB 67 84 67 98 57 67 84 67 84 57 \
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
led auto on
led 0 start
led 1 start
led 2 start
led 3 start

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
try:
import exceptions
import binascii
import time
import optparse
import warnings
import os
import sys
from sonic_eeprom import eeprom_base
from sonic_eeprom import eeprom_tlvinfo
import subprocess
import syslog
from struct import *
from array import *
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
SYSLOG_IDENTIFIER = "eeprom.py"
EEPROM_PATH = "/sys/bus/i2c/devices/0-0056/eeprom"
def log_error(msg):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_ERR, msg)
syslog.closelog()
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
if not os.path.exists(EEPROM_PATH):
log_error("Cannot find system eeprom")
raise RuntimeError("No syseeprom found")
self.eeprom_path = EEPROM_PATH
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,61 @@
#!/usr/bin/env python
#############################################################################
# Accton
#
# Module contains an implementation of SONiC PSU Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
import os.path
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
def __init__(self):
PsuBase.__init__(self)
self.psu_path = "/sys/bus/i2c/devices/"
self.psu_presence = "/psu_present"
self.psu_oper_status = "/psu_power_good"
self.psu_mapping = {
1: "10-0053",
2: "9-0050",
}
def get_num_psus(self):
return len(self.psu_mapping)
def get_psu_status(self, index):
if index is None:
return False
status = 0
node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status
try:
with open(node, 'r') as power_status:
status = int(power_status.read())
except IOError:
return False
return status == 1
def get_psu_presence(self, index):
if index is None:
return False
status = 0
node = self.psu_path + self.psu_mapping[index] + self.psu_presence
try:
with open(node, 'r') as presence_status:
status = int(presence_status.read())
except IOError:
return False
return status == 1

View File

@ -0,0 +1,761 @@
#!/usr/bin/env python
try:
import time
from sonic_sfp.sfputilbase import *
import sys
import os
import string
from ctypes import create_string_buffer
# sys.path.append('/usr/local/bin')
# import sfp_detect
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
qfx5210_qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)',
'Length OM2(m)', 'Length OM1(m)',
'Length Cable Assembly(m)')
qfx5210_sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)',
'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)',
'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)')
qfx5210_sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode',
'ESCONComplianceCodes', 'SONETComplianceCodes',
'EthernetComplianceCodes','FibreChannelLinkLength',
'FibreChannelTechnology', 'SFP+CableTechnology',
'FibreChannelTransmissionMedia','FibreChannelSpeed')
qfx5210_qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes',
'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media', 'Fibre Channel Speed')
class SfpUtil(SfpUtilBase):
"""Platform specific SfpUtill class"""
_port_start = 0
_port_end = 63
ports_in_block = 64
cmd = '/var/run/sfppresence'
_port_to_eeprom_mapping = {}
port_to_i2c_mapping = {
61 : 25,
62 : 26,
63 : 27,
64 : 28,
55 : 29,
56 : 30,
53 : 31,
54 : 32,
9 : 33,
10 : 34,
11 : 35,
12 : 36,
1 : 37,
2 : 38,
3 : 39,
4 : 40,
6 : 41,
5 : 42,
8 : 43,
7 : 44,
13 : 45,
14 : 46,
15 : 47,
16 : 48,
17 : 49,
18 : 50,
19 : 51,
20 : 52,
25 : 53,
26 : 54,
27 : 55,
28 : 56,
29 : 57,
30 : 58,
31 : 59,
32 : 60,
21 : 61,
22 : 62,
23 : 63,
24 : 64,
41 : 65,
42 : 66,
43 : 67,
44 : 68,
33 : 69,
34 : 70,
35 : 71,
36 : 72,
45 : 73,
46 : 74,
47 : 75,
48 : 76,
37 : 77,
38 : 78,
39 : 79,
40 : 80,
57 : 81,
58 : 82,
59 : 83,
60 : 84,
49 : 85,
50 : 86,
51 : 87,
52 : 88,}
port_to_sysfs_map = [
'/sys/bus/i2c/devices/37-0050/sfp_is_present',
'/sys/bus/i2c/devices/38-0050/sfp_is_present',
'/sys/bus/i2c/devices/39-0050/sfp_is_present',
'/sys/bus/i2c/devices/40-0050/sfp_is_present',
'/sys/bus/i2c/devices/42-0050/sfp_is_present',
'/sys/bus/i2c/devices/41-0050/sfp_is_present',
'/sys/bus/i2c/devices/44-0050/sfp_is_present',
'/sys/bus/i2c/devices/43-0050/sfp_is_present',
'/sys/bus/i2c/devices/33-0050/sfp_is_present',
'/sys/bus/i2c/devices/34-0050/sfp_is_present',
'/sys/bus/i2c/devices/35-0050/sfp_is_present',
'/sys/bus/i2c/devices/36-0050/sfp_is_present',
'/sys/bus/i2c/devices/45-0050/sfp_is_present',
'/sys/bus/i2c/devices/46-0050/sfp_is_present',
'/sys/bus/i2c/devices/47-0050/sfp_is_present',
'/sys/bus/i2c/devices/48-0050/sfp_is_present',
'/sys/bus/i2c/devices/49-0050/sfp_is_present',
'/sys/bus/i2c/devices/50-0050/sfp_is_present',
'/sys/bus/i2c/devices/51-0050/sfp_is_present',
'/sys/bus/i2c/devices/52-0050/sfp_is_present',
'/sys/bus/i2c/devices/61-0050/sfp_is_present',
'/sys/bus/i2c/devices/62-0050/sfp_is_present',
'/sys/bus/i2c/devices/63-0050/sfp_is_present',
'/sys/bus/i2c/devices/64-0050/sfp_is_present',
'/sys/bus/i2c/devices/53-0050/sfp_is_present',
'/sys/bus/i2c/devices/54-0050/sfp_is_present',
'/sys/bus/i2c/devices/55-0050/sfp_is_present',
'/sys/bus/i2c/devices/56-0050/sfp_is_present',
'/sys/bus/i2c/devices/57-0050/sfp_is_present',
'/sys/bus/i2c/devices/58-0050/sfp_is_present',
'/sys/bus/i2c/devices/59-0050/sfp_is_present',
'/sys/bus/i2c/devices/60-0050/sfp_is_present',
'/sys/bus/i2c/devices/69-0050/sfp_is_present',
'/sys/bus/i2c/devices/70-0050/sfp_is_present',
'/sys/bus/i2c/devices/71-0050/sfp_is_present',
'/sys/bus/i2c/devices/72-0050/sfp_is_present',
'/sys/bus/i2c/devices/77-0050/sfp_is_present',
'/sys/bus/i2c/devices/78-0050/sfp_is_present',
'/sys/bus/i2c/devices/79-0050/sfp_is_present',
'/sys/bus/i2c/devices/80-0050/sfp_is_present',
'/sys/bus/i2c/devices/65-0050/sfp_is_present',
'/sys/bus/i2c/devices/66-0050/sfp_is_present',
'/sys/bus/i2c/devices/67-0050/sfp_is_present',
'/sys/bus/i2c/devices/68-0050/sfp_is_present',
'/sys/bus/i2c/devices/73-0050/sfp_is_present',
'/sys/bus/i2c/devices/74-0050/sfp_is_present',
'/sys/bus/i2c/devices/75-0050/sfp_is_present',
'/sys/bus/i2c/devices/76-0050/sfp_is_present',
'/sys/bus/i2c/devices/85-0050/sfp_is_present',
'/sys/bus/i2c/devices/86-0050/sfp_is_present',
'/sys/bus/i2c/devices/87-0050/sfp_is_present',
'/sys/bus/i2c/devices/88-0050/sfp_is_present',
'/sys/bus/i2c/devices/31-0050/sfp_is_present',
'/sys/bus/i2c/devices/32-0050/sfp_is_present',
'/sys/bus/i2c/devices/29-0050/sfp_is_present',
'/sys/bus/i2c/devices/30-0050/sfp_is_present',
'/sys/bus/i2c/devices/81-0050/sfp_is_present',
'/sys/bus/i2c/devices/82-0050/sfp_is_present',
'/sys/bus/i2c/devices/83-0050/sfp_is_present',
'/sys/bus/i2c/devices/84-0050/sfp_is_present',
'/sys/bus/i2c/devices/25-0050/sfp_is_present',
'/sys/bus/i2c/devices/26-0050/sfp_is_present',
'/sys/bus/i2c/devices/27-0050/sfp_is_present',
'/sys/bus/i2c/devices/28-0050/sfp_is_present'
]
# sys.path.append('/usr/local/bin')
_qsfp_ports = range(0, ports_in_block + 1)
def __init__(self):
eeprom_path = '/sys/bus/i2c/devices/{0}-0050/sfp_eeprom'
for x in range(0, self._port_end + 1):
port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x+1])
self._port_to_eeprom_mapping[x] = port_eeprom_path
SfpUtilBase.__init__(self)
def reset(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/19-0060/module_reset_{0}"
port_ps = path.format(port_num+1)
try:
reg_file = open(port_ps, 'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
#HW will clear reset after set.
reg_file.seek(0)
reg_file.write('1')
reg_file.close()
return True
def get_presence(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
path = "/sys/bus/i2c/devices/{0}-0050/sfp_is_present"
port_ps = path.format(self.port_to_i2c_mapping[port_num+1])
try:
reg_file = open(port_ps)
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
reg_value = reg_file.readline().rstrip()
if reg_value == '1':
return True
return False
@property
def port_start(self):
return self._port_start
@property
def port_end(self):
return self._port_end
@property
def qsfp_ports(self):
return range(0, self.ports_in_block + 1)
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
# Writing to a file from a list
def write_to_file(self, file_name, from_list):
try:
fp1 = open(file_name, 'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
for i in from_list:
fp1.write(i)
fp1.write('\n')
fp1.close()
return True
# Reading from a file to a list
def read_from_file(self, file_name):
try:
fp = open(file_name, 'r')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
to_list = fp.readlines()
to_list = [x.rstrip() for x in to_list]
fp.close()
return to_list
def sfp_detect(self):
x = 0
ret_dict = {}
defl_dict = {}
current_sfp_values = [0] * 64
previous_sfp_values = [0] * 64
if not os.path.isfile(self.cmd):
pass
else:
if (self.read_from_file(self.cmd) == False):
return False, defl_dict
else:
previous_sfp_values = self.read_from_file(self.cmd)
# Read the current values from sysfs
for x in range(len(self.port_to_sysfs_map)):
try:
reg_file = open(self.port_to_sysfs_map[x], 'r')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False, defl_dict
sfp_present = reg_file.readline().rstrip()
reg_file.close()
current_sfp_values[x] = sfp_present
if (current_sfp_values[x] != previous_sfp_values[x]):
ret_dict.update({x:current_sfp_values[x]})
if(self.write_to_file(self.cmd, current_sfp_values) == True):
return True, ret_dict
else:
return False, defl_dict
def get_transceiver_change_event(self):
time.sleep(3)
return self.sfp_detect()
def get_low_power_mode(self, port_num):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
try:
eeprom = None
if not self.get_presence(port_num):
return False
eeprom = open(self.port_to_eeprom_mapping[port_num], "rb")
eeprom.seek(93)
lpmode = ord(eeprom.read(1))
if ((lpmode & 0x3) == 0x3):
return True # Low Power Mode if "Power override" bit is 1 and "Power set" bit is 1
else:
return False # High Power Mode if one of the following conditions is matched:
# 1. "Power override" bit is 0
# 2. "Power override" bit is 1 and "Power set" bit is 0
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
finally:
if eeprom is not None:
eeprom.close()
time.sleep(0.01)
def set_low_power_mode(self, port_num, lpmode):
# Check for invalid port_num
if port_num < self._port_start or port_num > self._port_end:
return False
try:
eeprom = None
if not self.get_presence(port_num):
return False # Port is not present, unable to set the eeprom
# Fill in write buffer
regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode
buffer = create_string_buffer(1)
buffer[0] = chr(regval)
# Write to eeprom
eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b")
eeprom.seek(93)
eeprom.write(buffer[0])
return True
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
finally:
if eeprom is not None:
eeprom.close()
time.sleep(0.01)
# Read out SFP type, vendor name, PN, REV, SN from eeprom.
def get_transceiver_info_dict(self, port_num):
transceiver_info_dict = {}
compliance_code_dict = {}
# ToDo: OSFP tranceiver info parsing not fully supported.
# in inf8628.py lack of some memory map definition
# will be implemented when the inf8628 memory map ready
if port_num in self.osfp_ports:
offset = 0
vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP
sfpi_obj = inf8628InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
print("Error, file not exist %s" % file_path)
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfp_type_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH)
if sfp_type_raw is not None:
sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0)
else:
return None
sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
if sfp_vendor_name_raw is not None:
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0)
else:
return None
sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
if sfp_vendor_pn_raw is not None:
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0)
else:
return None
sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width)
if sfp_vendor_rev_raw is not None:
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0)
else:
return None
sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
if sfp_vendor_sn_raw is not None:
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_info_dict['type'] = sfp_type_data['data']['type']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_type_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value']
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value']
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value']
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value']
# Below part is added to avoid fail the xcvrd, shall be implemented later
transceiver_info_dict['vendor_oui'] = 'N/A'
transceiver_info_dict['vendor_date'] = 'N/A'
transceiver_info_dict['Connector'] = 'N/A'
transceiver_info_dict['encoding'] = 'N/A'
transceiver_info_dict['ext_identifier'] = 'N/A'
transceiver_info_dict['ext_rateselect_compliance'] = 'N/A'
transceiver_info_dict['cable_type'] = 'N/A'
transceiver_info_dict['cable_length'] = 'N/A'
transceiver_info_dict['specification_compliance'] = 'N/A'
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
else:
if port_num in self.qsfp_ports:
offset = 128
vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP
cable_length_width = XCVR_CABLE_LENGTH_WIDTH_QSFP
interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP
sfp_type = 'QSFP'
sfpi_obj = sff8436InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
else:
offset = 0
vendor_rev_width = XCVR_HW_REV_WIDTH_SFP
cable_length_width = XCVR_CABLE_LENGTH_WIDTH_SFP
interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP
sfp_type = 'SFP'
sfpi_obj = sff8472InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
print("Error, file not exist %s" % file_path)
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfp_interface_bulk_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width)
if sfp_interface_bulk_raw is not None:
sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0)
else:
return None
sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
if sfp_vendor_name_raw is not None:
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0)
else:
return None
sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
if sfp_vendor_pn_raw is not None:
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0)
else:
return None
sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width)
if sfp_vendor_rev_raw is not None:
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0)
else:
return None
sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
if sfp_vendor_sn_raw is not None:
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0)
else:
return None
sfp_vendor_oui_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH)
if sfp_vendor_oui_raw is not None:
sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0)
else:
return None
sfp_vendor_date_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH)
if sfp_vendor_date_raw is not None:
sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value']
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value']
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value']
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value']
transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value']
transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value']
transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value']
transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value']
transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value']
if sfp_type == 'QSFP':
for key in qfx5210_qsfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value'])
break
else:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = 'N/A'
for key in qfx5210_qsfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(compliance_code_dict)
if sfp_interface_bulk_data['data'].has_key('Nominal Bit Rate(100Mbs)'):
transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value'])
else:
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
else:
for key in qfx5210_sfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value'])
else:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = 'N/A'
for key in qfx5210_sfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(compliance_code_dict)
if sfp_interface_bulk_data['data'].has_key('NominalSignallingRate(UnitsOf100Mbd)'):
transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value'])
else:
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
#transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value'])
return transceiver_info_dict
def get_transceiver_dom_info_dict(self, port_num):
transceiver_dom_info_dict = {}
if port_num in self.osfp_ports:
# Below part is added to avoid fail xcvrd, shall be implemented later
transceiver_dom_info_dict['temperature'] = 'N/A'
transceiver_dom_info_dict['voltage'] = 'N/A'
transceiver_dom_info_dict['rx1power'] = 'N/A'
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = 'N/A'
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
elif port_num in self.qsfp_ports:
offset = 0
offset_xcvr = 128
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return None
sfpi_obj = sff8436InterfaceId()
if sfpi_obj is None:
return None
# QSFP capability byte parse, through this byte can know whether it support tx_power or not.
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
# need to add more code for determining the capability and version compliance
# in SFF-8636 dom capability definitions evolving with the versions.
qsfp_dom_capability_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
if qsfp_dom_capability_raw is not None:
qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0)
else:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return None
qsfp_dom_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
if qsfp_dom_rev_raw is not None:
qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
else:
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
# The tx_power monitoring is only available on QSFP which compliant with SFF-8636
# and claimed that it support tx_power with one indicator bit.
dom_channel_monitor_data = {}
qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return None
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
else:
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0)
else:
return None
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
else:
offset = 256
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfpd_obj = sff8472Dom()
if sfpd_obj is None:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return None
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
return transceiver_dom_info_dict

View File

@ -4,6 +4,7 @@ declare -r EXIT_SUCCESS="0"
declare -r EXIT_ERROR="1"
declare -r FW_UPGRADE_SCRIPT="/usr/bin/mlnx-fw-upgrade.sh"
declare -r SYSFS_PWR_CYCLE="/sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/pwr_cycle"
FORCE_REBOOT="no"
@ -20,7 +21,7 @@ function ParseArguments() {
ParseArguments "$@"
${FW_UPGRADE_SCRIPT} --upgrade
${FW_UPGRADE_SCRIPT} --upgrade --verbose
EXIT_CODE="$?"
if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then
echo "Failed to burn MLNX FW: errno=${EXIT_CODE}"
@ -31,4 +32,7 @@ if [[ "${EXIT_CODE}" != "${EXIT_SUCCESS}" ]]; then
fi
fi
exec /sbin/reboot $@
# perform "hardware" reboot
echo 1 > $SYSFS_PWR_CYCLE
sleep 3
echo 0 > $SYSFS_PWR_CYCLE

View File

@ -1 +0,0 @@
../x86_64-mlnx_msn2700-r0/platform_reboot

View File

@ -0,0 +1,21 @@
#!/bin/bash
declare -r EXIT_SUCCESS="0"
declare -r EXIT_ERROR="1"
FORCE_REBOOT="no"
function ParseArguments() {
while [ $# -ge 1 ]; do
case "$1" in
-f|--force)
FORCE_REBOOT="yes"
;;
esac
shift
done
}
ParseArguments "$@"
exec /sbin/reboot $@

View File

@ -1 +0,0 @@
../x86_64-mlnx_msn2700-r0/platform_wait

View File

@ -1 +1 @@
../x86_64-mlnx_msn3700-r0/platform_reboot
../x86_64-mlnx_msn2700_simx-r0/platform_reboot

View File

@ -1 +0,0 @@
../x86_64-mlnx_msn3700-r0/platform_wait

View File

@ -23,13 +23,13 @@
"p4_pipelines": [
{
"p4_pipeline_name": "pipe",
"config": "share/tofinopd/switch/pipe/tofino.bin",
"context": "share/tofinopd/switch/pipe/context.json"
"config": "share/switch/pipe/tofino.bin",
"context": "share/switch/pipe/context.json"
}
],
"program-name": "switch",
"switchsai": "lib/libswitchsai.so",
"bfrt-config": "share/tofinopd/switch/bf-rt.json",
"bfrt-config": "share/switch/bf-rt.json",
"model_json_path" : "share/switch/aug_model.json",
"switchapi_port_add": false,
"non_default_port_ppgs": 5

View File

@ -32,6 +32,9 @@ RUN apt-get clean -y && \
s/^client-output-buffer-limit pubsub [0-9]+mb [0-9]+mb [0-9]+/client-output-buffer-limit pubsub 0 0 0/ \
' /etc/redis/redis.conf
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]
COPY ["supervisord.conf.j2", "/usr/share/sonic/templates/"]
COPY ["docker-database-init.sh", "/usr/local/bin/"]
COPY ["ping_pong_db_insts", "/usr/local/bin/"]
COPY ["database_config.json", "/etc/default/sonic-db/"]
ENTRYPOINT ["/usr/bin/supervisord"]
ENTRYPOINT ["/usr/local/bin/docker-database-init.sh"]

View File

@ -0,0 +1,43 @@
{
"INSTANCES": {
"redis":{
"port": 6379,
"socket": "/var/run/redis/redis.sock"
}
},
"DATABASES" : {
"APPL_DB" : {
"id" : 0,
"instance" : "redis"
},
"ASIC_DB" : {
"id" : 1,
"instance" : "redis"
},
"COUNTERS_DB" : {
"id" : 2,
"instance" : "redis"
},
"LOGLEVEL_DB" : {
"id" : 3,
"instance" : "redis"
},
"CONFIG_DB" : {
"id" : 4,
"instance" : "redis"
},
"PFC_WD_DB" : {
"id" : 5,
"instance" : "redis"
},
"FLEX_COUNTER_DB" : {
"id" : 5,
"instance" : "redis"
},
"STATE_DB" : {
"id" : 6,
"instance" : "redis"
}
},
"VERSION" : "1.0"
}

View File

@ -0,0 +1,14 @@
#!/usr/bin/env bash
mkdir -p /var/run/redis/sonic-db
if [ -f /etc/sonic/database_config.json ]; then
cp /etc/sonic/database_config.json /var/run/redis/sonic-db
else
cp /etc/default/sonic-db/database_config.json /var/run/redis/sonic-db
fi
mkdir -p /etc/supervisor/conf.d/
# generate all redis server supervisord configuration file
sonic-cfggen -j /var/run/redis/sonic-db/database_config.json -t /usr/share/sonic/templates/supervisord.conf.j2 > /etc/supervisor/conf.d/supervisord.conf
exec /usr/bin/supervisord

View File

@ -0,0 +1,40 @@
#!/usr/bin/python
import json
import os
import subprocess
import time
import syslog
def ping_redis(cmd):
output = ''
while True:
try:
output = subprocess.check_output(cmd, shell=True)
except subprocess.CalledProcessError as e:
syslog.syslog(syslog.LOG_ERR, 'ping redis failed, cmd : {}'.format(cmd))
if 'PONG' in output:
break
syslog.syslog(syslog.LOG_ERR, 'ping response : {}'.format(output))
time.sleep(1)
database_config_file = "/var/run/redis/sonic-db/database_config.json"
data = {}
while True:
if os.path.isfile(database_config_file):
with open(database_config_file, "r") as read_file:
data = json.load(read_file)
break
time.sleep(1)
syslog.syslog(syslog.LOG_ERR, 'config file {} does not exist right now'.format(database_config_file))
while True:
if 'INSTANCES' in data:
for inst in data["INSTANCES"]:
port = data["INSTANCES"][inst]["port"]
cmd = "redis-cli -p " + str(port) + " ping"
ping_redis(cmd)
break
time.sleep(1)
syslog.syslog(syslog.LOG_ERR, 'config file {} does not have INSTANCES'.format(database_config_file))

View File

@ -1,21 +0,0 @@
[supervisord]
logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
[program:rsyslogd]
command=/bin/bash -c "rm -f /var/run/rsyslogd.pid && /usr/sbin/rsyslogd -n"
priority=1
autostart=true
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
[program:redis-server]
command=/bin/bash -c "{ [[ -s /var/lib/redis/dump.rdb ]] || rm -f /var/lib/redis/dump.rdb; } && exec /usr/bin/redis-server /etc/redis/redis.conf"
priority=2
autostart=true
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog

View File

@ -0,0 +1,24 @@
[supervisord]
logfile_maxbytes=1MB
logfile_backups=2
nodaemon=true
[program:rsyslogd]
command=/bin/bash -c "rm -f /var/run/rsyslogd.pid && /usr/sbin/rsyslogd -n"
priority=1
autostart=true
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{% if INSTANCES %}
{% for redis_inst, redis_items in INSTANCES.iteritems() %}
[program: {{ redis_inst }}]
command=/bin/bash -c "{ [[ -s /var/lib/{{ redis_inst }}/dump.rdb ]] || rm -f /var/lib/{{ redis_inst }}/dump.rdb; } && mkdir -p /var/lib/{{ redis_inst }} && exec /usr/bin/redis-server /etc/redis/redis.conf --port {{ redis_items['port'] }} --unixsocket {{ redis_items['socket'] }} --pidfile /var/run/redis/{{ redis_inst }}.pid --dir /var/lib/{{ redis_inst }}"
priority=2
autostart=true
autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{% endfor %}
{% endif %}

View File

@ -43,8 +43,16 @@ isc-dhcp-relay-{{ vlan_name }}
{# Create a program entry for each DHCP relay agent instance #}
{% set relay_for_ipv4 = { 'flag': False } %}
{% for vlan_name in VLAN %}
{% if VLAN[vlan_name]['dhcp_servers'] %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{% if dhcp_server | ipv4 %}
{% set _dummy = relay_for_ipv4.update({'flag': True}) %}
{% endif %}
{% endfor %}
{% if relay_for_ipv4.flag %}
{% set _dummy = relay_for_ipv4.update({'flag': False}) %}
[program:isc-dhcp-relay-{{ vlan_name }}]
{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #}
command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }}
@ -58,7 +66,9 @@ command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /t
{% for (name, prefix) in PORTCHANNEL_INTERFACE|pfx_filter %}
{% if prefix | ipv4 %} -iu {{ name }}{% endif -%}
{% endfor %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %}
{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %}
{%- if dhcp_server | ipv4 %} {{ dhcp_server }}{% endif -%}
{% endfor %}
priority=3
autostart=false
@ -66,6 +76,7 @@ autorestart=false
stdout_logfile=syslog
stderr_logfile=syslog
{% endif %}
{% endif %}
{% endfor %}
{% endif %}

View File

@ -1,65 +1,124 @@
#!/usr/bin/env python
import sys
import copy
import Queue
import redis
import subprocess
import syslog
from swsssdk import ConfigDBConnector
import os
from swsscommon import swsscommon
class BGPConfigDaemon:
def run_command(command):
syslog.syslog(syslog.LOG_DEBUG, "execute command {}.".format(command))
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
stdout = p.communicate()[0]
p.wait()
if p.returncode != 0:
syslog.syslog(syslog.LOG_ERR, 'command execution returned {}. Command: "{}", stdout: "{}"'.format(p.returncode, command, stdout))
class BGPConfigManager(object):
def __init__(self, daemon):
self.daemon = daemon
self.bgp_asn = None
self.bgp_message = Queue.Queue(0)
daemon.add_manager(swsscommon.CONFIG_DB, swsscommon.CFG_DEVICE_METADATA_TABLE_NAME, self.__metadata_handler)
daemon.add_manager(swsscommon.CONFIG_DB, swsscommon.CFG_BGP_NEIGHBOR_TABLE_NAME, self.__bgp_handler)
def __metadata_handler(self, key, op, data):
if key != "localhost" \
or "bgp_asn" not in data \
or self.bgp_asn == data["bgp_asn"]:
return
# TODO add ASN update commands
self.bgp_asn = data["bgp_asn"]
self.__update_bgp()
def __update_bgp(self):
while not self.bgp_message.empty():
key, op, data = self.bgp_message.get()
syslog.syslog(syslog.LOG_INFO, 'value for {} changed to {}'.format(key, data))
if op == swsscommon.SET_COMMAND:
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format(self.bgp_asn, key, data['asn'])
run_command(command)
if "name" in data:
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format(self.bgp_asn, key, data['name'])
run_command(command)
if "admin_status" in data:
command_mod = "no " if data["admin_status"] == "up" else ""
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format(self.bgp_asn, command_mod, key)
run_command(command)
elif op == swsscommon.DEL_COMMAND:
# Neighbor is deleted
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key)
run_command(command)
def __bgp_handler(self, key, op, data):
self.bgp_message.put((key, op, data))
# If ASN is not set, we just cache this message until the ASN is set.
if self.bgp_asn == None:
return
self.__update_bgp()
class Daemon(object):
SELECT_TIMEOUT = 1000
SUPPORT_DATABASE_LIST = (swsscommon.APPL_DB, swsscommon.CONFIG_DB)
def __init__(self):
self.config_db = ConfigDBConnector()
self.config_db.connect()
self.bgp_asn = self.config_db.get_entry('DEVICE_METADATA', 'localhost')['bgp_asn']
self.bgp_neighbor = self.config_db.get_table('BGP_NEIGHBOR')
self.appl_db = swsscommon.DBConnector(swsscommon.APPL_DB, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
self.conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
self.selector = swsscommon.Select()
self.db_connectors = {}
self.callbacks = {}
self.subscribers = set()
def __run_command(self, command):
# print command
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
stdout = p.communicate()[0]
p.wait()
if p.returncode != 0:
syslog.syslog(syslog.LOG_ERR, '[bgp cfgd] command execution returned {}. Command: "{}", stdout: "{}"'.format(p.returncode, command, stdout))
def get_db_connector(self, db):
if db not in Daemon.SUPPORT_DATABASE_LIST:
raise ValueError("database {} not Daemon support list {}.".format(db, SUPPORT_DATABASE_LIST))
# if this database connector has been initialized
if db not in self.db_connectors:
self.db_connectors[db] = swsscommon.DBConnector(db, swsscommon.DBConnector.DEFAULT_UNIXSOCKET, 0)
return self.db_connectors[db]
def metadata_handler(self, key, data):
if key == 'localhost' and data.has_key('bgp_asn'):
if data['bgp_asn'] != self.bgp_asn:
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] ASN changed to {} from {}, restart BGP...'.format(data['bgp_asn'], self.bgp_asn))
self.__run_command("supervisorctl restart start.sh")
self.__run_command("service quagga restart")
self.bgp_asn = data['bgp_asn']
def bgp_handler(self, key, data):
syslog.syslog(syslog.LOG_INFO, '[bgp cfgd] value for {} changed to {}'.format(key, data))
if not data:
# Neighbor is deleted
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'no neighbor {}'".format(self.bgp_asn, key)
self.__run_command(command)
self.bgp_neighbor.pop(key)
else:
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} remote-as {}'".format(self.bgp_asn, key, data['asn'])
self.__run_command(command)
if data.has_key('name'):
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c 'neighbor {} description {}'".format(self.bgp_asn, key, data['name'])
self.__run_command(command)
if data.has_key('admin_status'):
command_mod = 'no ' if data['admin_status'] == 'up' else ''
command = "vtysh -c 'configure terminal' -c 'router bgp {}' -c '{}neighbor {} shutdown'".format(self.bgp_asn, command_mod, key)
self.__run_command(command)
self.bgp_neighbor[key] = data
def add_manager(self, db, table_name, callback):
if db not in self.callbacks:
self.callbacks[db] = {}
if table_name not in self.callbacks[db]:
self.callbacks[db][table_name] = []
conn = self.get_db_connector(db)
subscriber = swsscommon.SubscriberStateTable(conn, table_name)
self.subscribers.add(subscriber)
self.selector.addSelectable(subscriber)
self.callbacks[db][table_name].append(callback)
def start(self):
self.config_db.subscribe('BGP_NEIGHBOR',
lambda table, key, data: self.bgp_handler(key, data))
self.config_db.subscribe('DEVICE_METADATA',
lambda table, key, data: self.metadata_handler(key, data))
self.config_db.listen()
while True:
state, selectable = self.selector.select(Daemon.SELECT_TIMEOUT)
if not selectable:
continue
for subscriber in self.subscribers:
key, op, fvs = subscriber.pop()
# if no new message
if not key:
continue
data = dict(fvs)
syslog.syslog(syslog.LOG_DEBUG, "Receive message : {}".format((key, op, fvs)))
for callback in self.callbacks[subscriber.getDbConnector().getDbId()][subscriber.getTableName()]:
callback(key, op, data)
def main():
daemon = BGPConfigDaemon()
syslog.openlog("bgpcfgd")
daemon = Daemon()
bgp_manager = BGPConfigManager(daemon)
daemon.start()
syslog.closelog()
if __name__ == "__main__":
main()

View File

@ -6,6 +6,8 @@
{% set hash_seed = 0 %}
{% elif DEVICE_METADATA.localhost.type == "LeafRouter" %}
{% set hash_seed = 10 %}
{% elif DEVICE_METADATA.localhost.type == "SpineRouter" %}
{% set hash_seed = 15 %}
{% endif %}
{% endif %}
[

View File

@ -0,0 +1,67 @@
#!/usr/bin/env python
import syslog
import os
import hashlib
SYSLOG_IDENTIFIER = 'asic_config_checksum'
CHUNK_SIZE = 8192
CONFIG_FILES = {
os.path.abspath('./src/sonic-swss/swssconfig/sample/'): ['netbouncer.json', '00-copp.config.json']
}
OUTPUT_FILE = os.path.abspath('./asic_config_checksum')
def log_info(msg):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_INFO, msg)
syslog.closelog()
def log_error(msg):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_ERR, msg)
syslog.closelog()
def get_config_files(config_file_map):
'''
Generates a list of absolute paths to ASIC config files.
'''
config_files = []
for path, files in config_file_map.items():
for config_file in files:
config_files.append(os.path.join(path, config_file))
return config_files
def generate_checksum(checksum_files):
'''
Generates a checksum for a given list of files. Returns None if an error
occurs while reading the files.
NOTE: The checksum is performed in the order provided. This function does
NOT do any re-ordering of the files before creating the checksum.
'''
checksum = hashlib.sha1()
for checksum_file in checksum_files:
try:
with open(checksum_file, 'r') as f:
for chunk in iter(lambda: f.read(CHUNK_SIZE), b""):
checksum.update(chunk)
except IOError as e:
log_error('Error processing ASIC config file ' + checksum_file + ':' + e.strerror)
return None
return checksum.hexdigest()
def main():
config_files = sorted(get_config_files(CONFIG_FILES))
checksum = generate_checksum(config_files)
if checksum == None:
exit(1)
with open(OUTPUT_FILE, 'w') as output:
output.write(checksum + '\n')
if __name__ == '__main__':
main()

View File

@ -2,6 +2,7 @@
Description=Database container
Requires=docker.service
After=docker.service
After=rc-local.service
[Service]
User=root

View File

@ -71,10 +71,7 @@ function postStartAction()
{
{%- if docker_container_name == "database" %}
# Wait until redis starts
REDIS_SOCK="/var/run/redis/redis.sock"
until [[ $(/usr/bin/docker exec database redis-cli -s $REDIS_SOCK ping | grep -c PONG) -gt 0 ]]; do
sleep 1;
done
/usr/bin/docker exec database ping_pong_db_insts
if [[ ("$BOOT_TYPE" == "warm" || "$BOOT_TYPE" == "fastfast") && -f $WARM_DIR/dump.rdb ]]; then
rm -f $WARM_DIR/dump.rdb
else
@ -163,6 +160,11 @@ start() {
{%- if docker_container_name == "database" %}
echo "Creating new {{docker_container_name}} container"
# if database_config exists in old_config, use it; otherwise use the default one in new image
if [ -f /etc/sonic/old_config/database_config.json ]; then
echo "Use database_config.json from old system..."
mv /etc/sonic/old_config/database_config.json /etc/sonic/
fi
{%- else %}
echo "Creating new {{docker_container_name}} container with HWSKU $HWSKU"
{%- endif %}

View File

@ -29,6 +29,7 @@
{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%}
{%- set backend_device_types = ['BackEndToRRouter', 'BackEndLeafRouter'] -%}
{
@ -72,6 +73,20 @@
"7": "7"
}
},
{% if DEVICE_METADATA['localhost']['type'] in backend_device_types %}
"DOT1P_TO_TC_MAP": {
"AZURE": {
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7"
}
},
{% else %}
"DSCP_TO_TC_MAP": {
"AZURE": {
"0" : "1",
@ -140,6 +155,7 @@
"63": "1"
}
},
{% endif %}
"SCHEDULER": {
"scheduler.0": {
"type" : "DWRR",
@ -160,7 +176,11 @@
{% endif %}
"PORT_QOS_MAP": {
"{{ port_names_active }}": {
{% if DEVICE_METADATA['localhost']['type'] in backend_device_types %}
"dot1p_to_tc_map" : "[DOT1P_TO_TC_MAP|AZURE]",
{% else %}
"dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]",
{% endif %}
"tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]",
"tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]",
"pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]",

View File

@ -64,7 +64,7 @@ function getBootType()
TYPE='fastfast'
;;
*SONIC_BOOT_TYPE=fast*|*fast-reboot*)
TYPE='fast'
TYPE=$(awk '{ if ($1 <= 180) print "fast"; else print "cold" }' /proc/uptime)
;;
*)
TYPE='cold'

View File

@ -1,5 +1,5 @@
BFN_PLATFORM = bfnplatform_8_9_1.x.ab1e16f.deb
$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_8_9_1/bfnplatform_8_9_1.x.ab1e16f.deb"
BFN_PLATFORM = bfnplatform_9.0.0.cc6ccbe_pr_deb9.deb
$(BFN_PLATFORM)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_9_0/bfnplatform_9.0.0.cc6ccbe_pr_deb9.deb"
SONIC_ONLINE_DEBS += $(BFN_PLATFORM) # $(BFN_SAI_DEV)
SONIC_ONLINE_DEBS += $(BFN_PLATFORM)
$(BFN_SAI_DEV)_DEPENDS += $(BFN_PLATFORM)

View File

@ -1,5 +1,5 @@
BFN_SAI = bfnsdk_8_9_1.x.ab1e16f.deb
$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_8_9_1/bfnsdk_8_9_1.x.ab1e16f.deb"
BFN_SAI = bfnsdk_9.0.0.cc6ccbe_pr_deb9.deb
$(BFN_SAI)_URL = "https://github.com/barefootnetworks/sonic-release-pkgs/raw/rel_9_0/bfnsdk_9.0.0.cc6ccbe_pr_deb9.deb"
SONIC_ONLINE_DEBS += $(BFN_SAI) # $(BFN_SAI_DEV)
SONIC_ONLINE_DEBS += $(BFN_SAI)
$(BFN_SAI_DEV)_DEPENDS += $(BFN_SAI)

@ -1 +1 @@
Subproject commit 8c45a8e111534f9d4337d3552eaf08881fb19d30
Subproject commit 7b39cf3400dd728494b91810db9cc82542a22584

View File

@ -20,5 +20,6 @@ endif
$(DOCKER_SYNCD_BRCM_RPC)_CONTAINER_NAME = syncd
$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += --net=host --privileged -t
$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /host/machine.conf:/etc/machine.conf
$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /host/warmboot:/var/warmboot
$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /var/run/docker-syncd:/var/run/sswsyncd
$(DOCKER_SYNCD_BRCM_RPC)_RUN_OPT += -v /etc/sonic:/etc/sonic:ro

View File

@ -51,7 +51,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60A0_320FV2_PLATFORM_MODULE) \
$(ALPHANETWORKS_SNH60B0_640F_PLATFORM_MODULE) \
$(BRCM_XLR_GTS_PLATFORM_MODULE) \
$(DELTA_AG9032V2A_PLATFORM_MODULE)
$(DELTA_AG9032V2A_PLATFORM_MODULE) \
$(JUNIPER_QFX5210_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))

View File

@ -36,3 +36,6 @@ $(DELL_S5232F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5232f_c3538-r0
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5232F_PLATFORM_MODULE)))
SONIC_STRETCH_DEBS += $(DELL_Z9100_PLATFORM_MODULE)
#flashrom tool
$(shell ./$(PLATFORM_PATH)/sonic-platform-modules-dell/tools/flashrom.sh > /dev/null 2>&1)

View File

@ -0,0 +1,13 @@
# Juniper Platform modules
JUNIPER_QFX5210_PLATFORM_MODULE_VERSION = 1.1
export JUNIPER_QFX5210_PLATFORM_MODULE_VERSION
JUNIPER_QFX5210_PLATFORM_MODULE = sonic-platform-juniper-qfx5210_$(JUNIPER_QFX5210_PLATFORM_MODULE_VERSION)_amd64.deb
$(JUNIPER_QFX5210_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-juniper
$(JUNIPER_QFX5210_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
$(JUNIPER_QFX5210_PLATFORM_MODULE)_PLATFORM = x86_64-juniper_qfx5210-r0
SONIC_DPKG_DEBS += $(JUNIPER_QFX5210_PLATFORM_MODULE)
SONIC_STRETCH_DEBS += $(JUNIPER_QFX5210_PLATFORM_MODULE)

View File

@ -10,6 +10,7 @@ include $(PLATFORM_PATH)/platform-modules-cel.mk
include $(PLATFORM_PATH)/platform-modules-delta.mk
include $(PLATFORM_PATH)/platform-modules-quanta.mk
#include $(PLATFORM_PATH)/platform-modules-mitac.mk
include $(PLATFORM_PATH)/platform-modules-juniper.mk
include $(PLATFORM_PATH)/platform-modules-brcm-xlr-gts.mk
include $(PLATFORM_PATH)/docker-syncd-brcm.mk
include $(PLATFORM_PATH)/docker-syncd-brcm-rpc.mk

View File

@ -1,26 +1,22 @@
#!/usr/bin/env python
# Copyright (c) 2019 Edgecore Networks Corporation
#
# Copyright (C) 2017 Accton Technology Corporation
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
#
# ------------------------------------------------------------------
# HISTORY:
# mm/dd/yyyy (A.D.)
# 11/13/2017: Polly Hsu, Create
# 1/10/2018: Jostar modify for as7716_32
# 12/03/2018: Jostar modify for as7726_32
# 8/27/2019:Jostar craete for as9716_32d
# ------------------------------------------------------------------
try:
@ -46,8 +42,8 @@ class FanUtil(object):
FAN_NODE_FAULT_IDX_OF_MAP = 1
FAN_NODE_DIR_IDX_OF_MAP = 2
BASE_VAL_PATH = '/sys/bus/i2c/devices/54-0066/{0}'
FAN_DUTY_PATH = '/sys/bus/i2c/devices/54-0066/fan_duty_cycle_percentage'
BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0066/{0}'
FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0066/fan_duty_cycle_percentage'
#logfile = ''
#loglevel = logging.INFO
@ -56,14 +52,14 @@ class FanUtil(object):
key1 = fan id index (integer) starting from 1
key2 = fan node index (interger) starting from 1
value = path to fan device file (string) """
_fan_to_device_path_mapping = {}
_fan_device_path_mapping = {}
#fan1_direction
#fan1_fault
#fan1_present
#(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage',
_fan_to_device_node_mapping = {
_fan_device_node_mapping = {
(FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault',
(FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction',
@ -83,8 +79,8 @@ class FanUtil(object):
(FAN_NUM_6_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan6_direction',
}
def _get_fan_to_device_node(self, fan_num, node_num):
return self._fan_to_device_node_mapping[(fan_num, node_num)]
def _get_fan_device_node(self, fan_num, node_num):
return self._fan_device_node_mapping[(fan_num, node_num)]
def _get_fan_node_val(self, fan_num, node_num):
if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
@ -95,7 +91,7 @@ class FanUtil(object):
logging.debug('GET. Parameter error. node_num:%d', node_num)
return None
device_path = self.get_fan_to_device_path(fan_num, node_num)
device_path = self.get_fan_device_path(fan_num, node_num)
try:
val_file = open(device_path, 'r')
@ -131,7 +127,7 @@ class FanUtil(object):
logging.debug('GET. content is NULL. device_path:%s', device_path)
return None
device_path = self.get_fan_to_device_path(fan_num, node_num)
device_path = self.get_fan_device_path(fan_num, node_num)
try:
val_file = open(device_path, 'w')
except IOError as e:
@ -153,8 +149,8 @@ class FanUtil(object):
for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1):
for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1):
self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format(
self._fan_to_device_node_mapping[(fan_num, node_num)])
self._fan_device_path_mapping[(fan_num, node_num)] = fan_path.format(
self._fan_device_node_mapping[(fan_num, node_num)])
def get_num_fans(self):
return self.FAN_NUM_ON_MAIN_BROAD
@ -169,20 +165,17 @@ class FanUtil(object):
return self.FAN_NODE_FAULT_IDX_OF_MAP
def get_size_node_map(self):
return len(self._fan_to_device_node_mapping)
return len(self._fan_device_node_mapping)
def get_size_path_map(self):
return len(self._fan_to_device_path_mapping)
return len(self._fan_device_path_mapping)
def get_fan_to_device_path(self, fan_num, node_num):
return self._fan_to_device_path_mapping[(fan_num, node_num)]
def get_fan_device_path(self, fan_num, node_num):
return self._fan_device_path_mapping[(fan_num, node_num)]
def get_fan_fault(self, fan_num):
return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP)
#def get_fan_speed(self, fan_num):
# return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP)
def get_fan_dir(self, fan_num):
return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP)
@ -198,28 +191,18 @@ class FanUtil(object):
val_file.close()
return int(content)
#self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP)
#static u32 reg_val_to_duty_cycle(u8 reg_val)
#{
# reg_val &= FAN_DUTY_CYCLE_REG_MASK;
# return ((u32)(reg_val+1) * 625 + 75)/ 100;
#}
#
def set_fan_duty_cycle(self, val):
try:
fan_file = open(self.FAN_DUTY_PATH, 'r+')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
#val = ((val + 1 ) * 625 +75 ) / 100
fan_file.write(str(val))
fan_file.close()
return True
#def get_fanr_fault(self, fan_num):
# return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP)
def get_fanr_speed(self, fan_num):
return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP)
@ -232,20 +215,4 @@ class FanUtil(object):
logging.debug('GET. FAN fault. fan_num, %d', fan_num)
return False
#if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0:
# logging.debug('GET. FANR fault. fan_num, %d', fan_num)
# return False
return True
#def main():
# fan = FanUtil()
#
# print 'get_size_node_map : %d' % fan.get_size_node_map()
# print 'get_size_path_map : %d' % fan.get_size_path_map()
# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1):
# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1):
# print fan.get_fan_to_device_path(x, y)
#
#if __name__ == '__main__':
# main()

View File

@ -1,24 +1,22 @@
#!/usr/bin/env python
# Copyright (c) 2019 Edgecore Networks Corporation
#
# Copyright (C) 2017 Accton Technology Corporation
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
#
# ------------------------------------------------------------------
# HISTORY:
# mm/dd/yyyy (A.D.)
# 12/18/2018:Jostar craete for as9716_32d
# 8/27/2019:Jostar craete for as9716_32d
# ------------------------------------------------------------------
try:
@ -34,38 +32,29 @@ except ImportError as e:
class ThermalUtil(object):
"""Platform-specific ThermalUtil class"""
THERMAL_NUM_MAX = 8
THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD. LM75
THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75
THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75
THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75
THERMAL_NUM_5_IDX = 5 # 5_ON_MAIN_BROAD. LM75
THERMAL_NUM_6_IDX = 6 # 6_ON_MAIN_BROAD. LM75
THERMAL_NUM_7_IDX = 7 # 7_ON_MAIN_BROAD. LM75
THERMAL_NUM_8_IDX = 8 # 8_ON_MAIN_BROAD. LM75
THERMAL_NUM_1_IDX = 1 # 1~7 are mainboard thermal sensors
THERMAL_NUM_2_IDX = 2
THERMAL_NUM_3_IDX = 3
THERMAL_NUM_4_IDX = 4
THERMAL_NUM_5_IDX = 5
THERMAL_NUM_6_IDX = 6
THERMAL_NUM_7_IDX = 7 # CPU core
THERMAL_NUM_8_IDX = 8
""" Dictionary where
key1 = thermal id index (integer) starting from 1
value = path to fan device file (string) """
#_thermal_to_device_path_mapping = {}
_thermal_to_device_node_mapping = {
THERMAL_NUM_1_IDX: ['18', '48'],
THERMAL_NUM_2_IDX: ['18', '49'],
THERMAL_NUM_3_IDX: ['18', '4a'],
THERMAL_NUM_4_IDX: ['18', '4b'],
THERMAL_NUM_5_IDX: ['18', '4c'],
THERMAL_NUM_6_IDX: ['18', '4e'],
THERMAL_NUM_7_IDX: ['18', '4f'],
}
thermal_sysfspath ={
THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-0048/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/18-0049/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_7_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_8_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"],
THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/18-004a/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/18-004c/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_5_IDX: ["/sys/bus/i2c/devices/18-004e/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_6_IDX: ["/sys/bus/i2c/devices/18-004f/hwmon/hwmon*/temp1_input"],
THERMAL_NUM_7_IDX: ["/sys/class/hwmon/hwmon0/temp1_input"],
THERMAL_NUM_8_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon*/temp1_input"],
}
#def __init__(self):
@ -75,7 +64,7 @@ class ThermalUtil(object):
logging.debug('GET. Parameter error. thermal_num, %d', thermal_num)
return None
device_path = self.get_thermal_to_device_path(thermal_num)
device_path = self.get_thermal_path(thermal_num)
for filename in glob.glob(device_path):
try:
val_file = open(filename, 'r')
@ -97,39 +86,17 @@ class ThermalUtil(object):
return 0
def get_num_thermals(self):
return self.THERMAL_NUM_MAX
def get_idx_thermal_start(self):
return self.THERMAL_NUM_1_IDX
def get_size_node_map(self):
return len(self._thermal_to_device_node_mapping)
return self.THERMAL_NUM_MAX
def get_size_path_map(self):
return len(self.thermal_sysfspath)
def get_thermal_to_device_path(self, thermal_num):
def get_thermal_path(self, thermal_num):
return self.thermal_sysfspath[thermal_num][0]
def get_thermal_temp(self):
return (self._get_thermal_node_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_node_val(self.THERMAL_NUM_3_IDX))
def main():
thermal = ThermalUtil()
print "termal1=%d" %thermal._get_thermal_val(1)
print "termal2=%d" %thermal._get_thermal_val(2)
print "termal3=%d" %thermal._get_thermal_val(3)
print "termal4=%d" %thermal._get_thermal_val(4)
print "termal5=%d" %thermal._get_thermal_val(5)
print "termal7=%d" %thermal._get_thermal_val(6)
print "termal8=%d" %thermal._get_thermal_val(7)
print "termal9=%d" %thermal._get_thermal_val(8)
#
# print 'get_size_node_map : %d' % thermal.get_size_node_map()
# print 'get_size_path_map : %d' % thermal.get_size_path_map()
# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1):
# print thermal.get_thermal_to_device_path(x)
#
thermal = ThermalUtil()
if __name__ == '__main__':
main()

View File

@ -1,28 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*
# Copyright (c) 2019 Edgecore Networks Corporation
#
# Copyright (C) 2017 Accton Technology Corporation
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ------------------------------------------------------------------
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
#
# HISTORY:
# mm/dd/yyyy (A.D.)#
# 12/19/2018:Jostar create for as9716_32d thermal plan
# 8/27/2019:Jostar create for as9716_32d thermal plan
# ------------------------------------------------------------------
try:
import os
import commands
import sys, getopt
import subprocess
import click
@ -41,31 +40,11 @@ except ImportError as e:
# Deafults
VERSION = '1.0'
FUNCTION_NAME = '/usr/local/bin/accton_as9716_32x_monitor'
FUNCTION_NAME = '/usr/local/bin/accton_as9716_32d_monitor'
global log_file
global log_level
# Air Flow Front to Back :
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=38C : Keep 37.5%(0x04) Fan speed
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 38C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08)
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 46C : Change Fan speed from 62.5%(0x08) to 100%(0x0E)
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 58C : Send alarm message
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 66C : Shut down system
# One Fan fail : Change Fan speed to 100%(0x0E)
# Air Flow Back to Front :
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 <=34C : Keep 37.5%(0x04) Fan speed
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 34C : Change Fan speed from 37.5%(0x04) to 62.5%(0x08)
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 44C : Change Fan speed from 62.5%(0x08) to 100%(0x0E)
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 59C : Send alarm message
# (Thermal sensor_LM75_4A + Thermal sensor_LM75_CPU) /2 > 67C : Shut down system
# One Fan fail: Change Fan speed to 100%(0x0E)
# sensor_LM75_CPU == sensor_LM75_4B
class switch(object):
def __init__(self, value):
self.value = value
@ -87,20 +66,217 @@ class switch(object):
return False
fan_policy_state=1
# Read fanN_direction=1: The air flow of Fan6 is “AFI-Back to Front”
# 0: The air flow of Fan6 is “AFO-Front to back”
#
# Thermal policy:
# a.Defaut fan duty_cycle=100%
# b.One fan fail, set to fan duty_cycle=100%
# 1.For AFI:
# Default fan duty_cycle will be 100%(fan_policy_state=LEVEL_FAN_MAX).
# If all below case meet with, set to 75%(LEVEL_FAN_MID).
# MB board
# LM75-1(0X48)<=57
# LM75-2(0X49)<=47.3
# LM75-3(0X4A)<=45
# LM75-4(0X4C)<=45.1
# LM75-5(0X4E)<=40.75
# LM75-6(0X4F)<=42.1
# CPU board
# Core<=44
# LM75-1(0X4B)<=35
# When fan_policy_state=LEVEL_FAN_MID, meet with below case, Fan duty_cycle will be 100%(LEVEL_FAN_DAX)
# (MB board)
# LM75-1(0X48)>=61.5
# LM75-2(0X49)>=51.5
# LM75-3(0X4A)>=49.4
# LM75-4(0X4C)>=49.4
# LM75-5(0X4E)>=45.1
# LM75-6(0X4F)>=46.75
# (CPU board)
# Core>=48
# LM75-1(0X4B)>=38.5
# 2. For AFO:
# At default, FAN duty_cycle was 100%(LEVEL_FAN_MAX). If all below case meet with, set to 75%(LEVEL_FAN_MID).
# (MB board)
# LM75-1(0X48)<=59
# LM75-2(0X49)<=53.5
# LM75-3(0X4A)<=55.3
# LM75-4(0X4C)<=50.3
# LM75-5(0X4E)<=50
# LM75-6(0X4F)<=52.5
# (CPU board)
# Core<=59
# LM75-1(0X4B)<=41.1
# When FAN duty_cycle was 75%(LEVEL_FAN_MID). If all below case meet with, set to 50%(LEVEL_FAN_DEF).
# (MB board)
# LM75-1(0X48)<=55.8
# LM75-2(0X49)<=50.5
# LM75-3(0X4A)<=51.1
# LM75-4(0X4C)<=47.6
# LM75-5(0X4E)<=45.75
# LM75-6(0X4F)<=50.1
# (CPU board)
# Core<=57
# LM75-1(0X4B)<=36.6
# When fan_speed 50%(LEVEL_FAN_DEF).
# Meet with below case, Fan duty_cycle will be 75%(LEVEL_FAN_MID)
# (MB board)
# LM75-1(0X48)>=70
# LM75-2(0X49)>=66
# LM75-3(0X4A)>=68
# LM75-4(0X4C)>=62
# LM75-5(0X4E)>=62
# LM75-6(0X4F)>=67
# (CPU board)
# Core>=77
# LM75-1(0X4B)>=50
# When FAN duty_cycle was 75%(LEVEL_FAN_MID). If all below case meet with, set to 100%(LEVEL_FAN_MAX).
# (MB board)
# LM75-1(0X48)>=67
# LM75-2(0X49)>=62.5
# LM75-3(0X4A)>=65
# LM75-4(0X4C)>=59
# LM75-5(0X4E)>=58.5
# LM75-6(0X4F)>=63
# (CPU board)
# Core >=69
# LM75-1(0X4B)>=49
#Yellow Alarm
#MB board
#LM75-1(0X48)>=68
#LM75-2(0X49)>=64
#LM75-3(0X4A)>=65
#LM75-4(0X4C)>=61
#LM75-5(0X4E)>=60
#LM75-6(0X4F)>=64
#CPU Board
#Core>=70
#LM75-1(0X4B)>=68
#Red Alarm
#MB board
#LM75-1(0X48)>=72
#LM75-2(0X49)>=68
#LM75-3(0X4A)>=69
#LM75-4(0X4C)>=65
#LM75-5(0X4E)>=64
#LM75-6(0X4F)>=68
#CPU Board
#Core>=74
#LM75-1(0X4B)>=72
#Shut down
#MB board
#LM75-1(0X48)>=77
#LM75-2(0X49)>=73
#LM75-3(0X4A)>=74
#LM75-4(0X4C)>=70
#LM75-5(0X4E)>=69
#LM75-6(0X4F)>=73
#CPU Board
#Core>=79
#LM75-1(0X4B)>=77
def power_off_dut():
cmd_str="i2cset -y -f 19 0x60 0x60 0x10"
status, output = commands.getstatusoutput(cmd_str)
return status
#If only one PSU insert(or one of PSU pwoer fail), and watt >800w. Must let DUT fan pwm >= 75% in AFO.
#Because the psu temp is high.
# Return 1: full load
# Return 0: Not full load
def check_psu_loading():
psu_power_status=[1, 1]
psu_power_good = {
2: "/sys/bus/i2c/devices/10-0051/psu_power_good",
1: "/sys/bus/i2c/devices/9-0050/psu_power_good",
}
psu_power_in = {
2: "/sys/bus/i2c/devices/10-0059/psu_p_in",
1: "/sys/bus/i2c/devices/9-0058/psu_p_in",
}
psu_power_out = {
2: "/sys/bus/i2c/devices/10-0059/psu_p_out",
1: "/sys/bus/i2c/devices/9-0058/psu_p_out",
}
check_psu_watt=0
for i in range(1,3):
node = psu_power_good[i]
try:
with open(node, 'r') as power_status:
status = int(power_status.read())
except IOError:
return None
psu_power_status[i-1]=int(status)
if status==0:
check_psu_watt=1
if check_psu_watt:
for i in range(1,3):
if psu_power_status[i-1]==1:
#check watt
node = psu_power_in[i]
try:
with open(node, 'r') as power_status:
status = int(power_status.read())
except IOError:
return None
psu_p_in= int(status)
if psu_p_in/1000 > 800:
return True
node = psu_power_out[i]
try:
with open(node, 'r') as power_status:
status = int(power_status.read())
except IOError:
return None
psu_p_out= int(status)
if psu_p_out/1000 > 800:
return True
else:
return False
return False
fan_policy_state=0
fan_policy_alarm=0
send_yellow_alarm=0
send_red_alarm=0
fan_fail=0
alarm_state = 0 #0->default or clear, 1-->alarm detect
count_check=0
test_temp = 0
test_temp_list = [0, 0, 0, 0, 0, 0]
test_temp_list = [0, 0, 0, 0, 0, 0, 0, 0]
temp_test_data=0
test_temp_revert=0
# Make a class we can use to capture stdout and sterr in the log
class device_monitor(object):
# static temp var
temp = 0
new_pwm = 0
pwm=0
ori_pwm = 0
default_pwm=0x4
new_duty_cycle = 0
duty_cycle=0
ori_duty_cycle = 0
def __init__(self, log_file, log_level):
"""Needs a logger and a logger level."""
@ -123,179 +299,197 @@ class device_monitor(object):
sys_handler = handler = logging.handlers.SysLogHandler(address = '/dev/log')
sys_handler.setLevel(logging.WARNING)
logging.getLogger('').addHandler(sys_handler)
#logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
def get_state_from_fan_policy(self, temp, policy):
state=0
logging.debug('temp=%d', temp)
for i in range(0, len(policy)):
#logging.debug('policy[%d][0]=%d, policy[%d][1]=%d, policy[%d][2]=%d', i,policy[i][0],i, policy[i][1], i, policy[i][2])
if temp > policy[i][2]:
if temp <= policy[i][3]:
state =i
logging.debug ('temp=%d >= policy[%d][2]=%d, temp=%d < policy[%d][3]=%d' , temp, i, policy[i][2], temp, i, policy[i][3])
logging.debug ('fan_state=%d', state)
break
return state
def manage_fans(self):
global fan_policy_state
global fan_policy_alarm
global send_yellow_alarm
global send_red_alarm
global fan_fail
global count_check
global test_temp
global test_temp_list
global alarm_state
global test_temp_list
global temp_test_data
LEVEL_FAN_DEF=0
LEVEL_FAN_MID=1
LEVEL_FAN_MAX=2
LEVEL_TEMP_HIGH=3
LEVEL_TEMP_CRITICAL=4
fan_policy_f2b = {
LEVEL_FAN_DEF: [38, 0x4, 0, 38000],
LEVEL_FAN_MID: [63, 0x6, 38000, 46000],
LEVEL_FAN_MAX: [100, 0xE, 46000, 58000],
LEVEL_TEMP_HIGH: [100, 0xE, 58000, 66000],
LEVEL_TEMP_CRITICAL: [100, 0xE, 58000, 200000],
global test_temp_revert
CHECK_TIMES=3
LEVEL_FAN_INIT=0
LEVEL_FAN_MIN=1
LEVEL_FAN_MID=2
LEVEL_FAN_MAX=3
LEVEL_FAN_DEF=LEVEL_FAN_MAX
LEVEL_FAN_YELLOW_ALARM=4
LEVEL_FAN_RED_ALARM=5
LEVEL_FAN_SHUTDOWN=6
fan_policy_f2b = { #AFO
LEVEL_FAN_MIN: [50, 0x7],
LEVEL_FAN_MID: [75, 0xb],
LEVEL_FAN_MAX: [100, 0xf]
}
fan_policy_b2f = {
LEVEL_FAN_DEF: [38, 0x4, 0, 34000],
LEVEL_FAN_MID: [63, 0x8, 34000, 44000],
LEVEL_FAN_MAX: [100, 0xE, 44000, 59000],
LEVEL_TEMP_HIGH: [100, 0xE, 59000, 67000],
LEVEL_TEMP_CRITICAL: [100, 0xE, 59000, 200000],
fan_policy_b2f = { #AFI
LEVEL_FAN_MID: [75, 0xb],
LEVEL_FAN_MAX: [100, 0xf]
}
afi_thermal_spec={
"mid_to_max_temp":[61500, 51500, 49400, 49400, 45100, 46750, 48000, 38500],
"max_to_mid_temp":[57000, 47300, 45000, 45100, 40750, 42100, 44000, 35000]
}
afo_thermal_spec={
"min_to_mid_temp": [70000, 66000, 68000, 62000, 62000, 67000, 77000, 50000],
"mid_to_max_temp": [67000, 62000, 65000, 59000, 58500, 63000, 69000, 49000],
"max_to_mid_temp": [59000, 53500, 55300, 50300, 50000, 52500, 59000, 41100],
"mid_to_min_temp": [55800, 50500, 51100, 47600, 45750, 50100, 57000, 36600],
"max_to_yellow_alarm": [68000, 64000, 65000, 61000, 60000, 64000, 70000, 68000],
"yellow_to_red_alarm": [72000, 68000, 69000, 65000, 64000, 68000, 74000, 72000],
"red_alarm_to_shutdown": [77000, 73000, 74000, 70000, 69000, 73000, 79000, 77000]
}
thermal_val=[0,0,0,0,0,0,0,0]
max_to_mid=0
mid_to_min=0
fan_policy = fan_policy_f2b
fan = FanUtil()
if fan_policy_state==LEVEL_FAN_INIT:
fan_policy_state=LEVEL_FAN_MAX #This is default state
logging.debug("fan_policy_state=LEVEL_FAN_MAX")
return
count_check=count_check+1
if count_check < CHECK_TIMES:
return
else:
count_check=0
thermal = ThermalUtil()
fan = FanUtil()
fan_dir=fan.get_fan_dir(1)
if fan_dir == 1:
fan_dri=1 #something wrong, set fan_dir to default val
fan_dir=1
fan_dir=fan.get_fan_dir(1)
if fan_dir==1: # AFI
fan_thermal_spec = afi_thermal_spec
fan_policy=fan_policy_b2f
elif fan_dir==0: # AFO
fan_thermal_spec = afo_thermal_spec
fan_policy=fan_policy_f2b
else:
fan_policy = fan_policy_b2f
logging.debug( "NULL case")
ori_pwm=fan.get_fan_duty_cycle()
new_pwm=0
logging.debug('fan_dir=%d, ori_pwm=%d', fan_dir, ori_pwm)
logging.debug('test_temp=%d', test_temp)
if test_temp==0:
temp1 = thermal._get_thermal_val(1)
temp2 = thermal._get_thermal_val(2)
temp3 = thermal._get_thermal_val(3)
temp4 = thermal._get_thermal_val(4)
temp5 = thermal._get_thermal_val(5)
ori_duty_cycle=fan.get_fan_duty_cycle()
new_duty_cycle=0
if test_temp_revert==0:
temp_test_data=temp_test_data+2000
else:
temp_test_data=temp_test_data-2000
if test_temp==0:
for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_MAX+1):
thermal_val[i-1]=thermal._get_thermal_val(i)
else:
temp1 = test_temp_list[0]
temp2 = test_temp_list[1]
temp3 = test_temp_list[2]
temp4 = test_temp_list[3]
temp5 = test_temp_list[4]
for i in range (thermal.THERMAL_NUM_1_IDX, thermal.THERMAL_NUM_MAX+1):
thermal_val[i-1]=test_temp_list[i-1]
thermal_val[i-1]= thermal_val[i-1] + temp_test_data
fan_fail=0
if temp3==0:
temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75%
logging.debug('lm75_49 detect fail, so set temp_get=50000, let fan to 75%')
elif temp4==0:
temp_get=50000 # if one detect sensor is fail or zero, assign temp=50000, let fan to 75%
logging.debug('lm75_4b detect fail, so set temp_get=50000, let fan to 75%')
else:
temp_get= (temp3 + temp4)/2 # Use (sensor_LM75_4a + sensor_LM75_4b) /2
ori_state=fan_policy_state
ori_state=fan_policy_state;
current_state=fan_policy_state;
if fan_dir==1: #AFI
for i in range (0, thermal.THERMAL_NUM_MAX):
if ori_state==LEVEL_FAN_MID:
if thermal_val[i] >= fan_thermal_spec["mid_to_max_temp"][i]:
current_state=LEVEL_FAN_MAX
logging.debug("current_state=LEVEL_FAN_MAX")
break
else:
if (thermal_val[i] <= fan_thermal_spec["max_to_mid_temp"][i]):
max_to_mid=max_to_mid+1
#temp_test_data=temp_test_data+1000
#temp_get = temp_get + temp_test_data
#print "Unit test:temp_get=%d"%temp_get
fan_policy_state=self.get_state_from_fan_policy(temp_get, fan_policy)
#print "temp3=%d"%temp3
#print "temp4=%d"%temp4
#print "temp_get=%d"%temp_get
if max_to_mid==thermal.THERMAL_NUM_MAX and fan_policy_state==LEVEL_FAN_MAX:
current_state=LEVEL_FAN_MID
logging.debug("current_state=LEVEL_FAN_MID")
else: #AFO
psu_full_load=check_psu_loading()
for i in range (0, thermal.THERMAL_NUM_MAX):
if ori_state==LEVEL_FAN_MID:
if thermal_val[i] >= fan_thermal_spec["mid_to_max_temp"][i]:
current_state=LEVEL_FAN_MAX
break
else:
if psu_full_load!=True and thermal_val[i] <= fan_thermal_spec["mid_to_min_temp"][i]:
mid_to_min=mid_to_min+1
elif ori_state==LEVEL_FAN_MIN:
if psu_full_load==True:
current_state=LEVEL_FAN_MID
logging.debug("psu_full_load, set current_state=LEVEL_FAN_MID")
if thermal_val[i] >= fan_thermal_spec["min_to_mid_temp"][i]:
current_state=LEVEL_FAN_MID
else:
if thermal_val[i] <= fan_thermal_spec["max_to_mid_temp"][i] :
max_to_mid=max_to_mid+1
if fan_policy_alarm==0:
if thermal_val[i] >= fan_thermal_spec["max_to_yellow_alarm"][i]:
if send_yellow_alarm==0:
logging.warning('Alarm-Yellow for temperature high is detected')
fan_policy_alarm=LEVEL_FAN_YELLOW_ALARM
send_yellow_alarm=1
elif fan_policy_alarm==LEVEL_FAN_YELLOW_ALARM:
if thermal_val[i] >= fan_thermal_spec["yellow_to_red_alarm"][i]:
if send_red_alarm==0:
logging.warning('Alarm-Red for temperature high is detected')
fan_policy_alarm=LEVEL_FAN_RED_ALARM
send_red_alarm=1
elif fan_policy_alarm==LEVEL_FAN_RED_ALARM:
if thermal_val[i] >= fan_thermal_spec["red_alarm_to_shutdown"][i]:
logging.critical('Alarm-Critical for temperature high is detected, shutdown DUT')
fan_policy_alarm=LEVEL_FAN_SHUTDOWN
time.sleep(2)
power_off_dut()
logging.debug('lm75_48=%d, lm75_49=%d, lm75_4a=%d, lm_4b=%d, lm_4b=%d', temp1,temp2,temp3,temp4,temp5)
logging.debug('ori_state=%d, fan_policy_state=%d', ori_state, fan_policy_state)
new_pwm = fan_policy[fan_policy_state][0]
if fan_fail==0:
logging.debug('new_fan_cycle=%d', new_pwm)
if fan_fail==0:
if new_pwm!=ori_pwm:
fan.set_fan_duty_cycle(new_pwm)
logging.info('Set fan speed from %d to %d', ori_pwm, new_pwm)
if max_to_mid==thermal.THERMAL_NUM_MAX and ori_state==LEVEL_FAN_MAX:
current_state=LEVEL_FAN_MID
if fan_policy_alarm!=0:
logging.warning('Alarm for temperature high is cleared')
fan_policy_alarm=0
send_yellow_alarm=0
send_red_alarm=0
test_temp_revert=0
logging.debug("current_state=LEVEL_FAN_MID")
if mid_to_min==thermal.THERMAL_NUM_MAX and ori_state==LEVEL_FAN_MID:
if psu_full_load==0:
current_state=LEVEL_FAN_MIN
logging.debug("current_state=LEVEL_FAN_MIN")
#Check Fan status
for i in range (fan.FAN_NUM_1_IDX, fan.FAN_NUM_ON_MAIN_BROAD+1):
if fan.get_fan_status(i)==0:
new_pwm=100
logging.debug('fan_%d fail, set pwm to 100',i)
new_duty_cycle=100
logging.debug('fan_%d fail, set duty_cycle to 100',i)
if test_temp==0:
fan_fail=1
fan.set_fan_duty_cycle(new_pwm)
fan.set_fan_duty_cycle(new_duty_cycle)
break
else:
fan_fail=0
#if fan_policy_state == ori_state:
# return True
#else:
new_state = fan_policy_state
#logging.warning('Temperature high alarm testing')
if ori_state==LEVEL_FAN_DEF:
if new_state==LEVEL_TEMP_HIGH:
if alarm_state==0:
logging.warning('Alarm for temperature high is detected')
alarm_state=1
if new_state==LEVEL_TEMP_CRITICAL:
logging.critical('Alarm for temperature critical is detected, reboot DUT')
time.sleep(2)
os.system('reboot')
if ori_state==LEVEL_FAN_MID:
if new_state==LEVEL_TEMP_HIGH:
if alarm_state==0:
logging.warning('Alarm for temperature high is detected')
alarm_state=1
if new_state==LEVEL_TEMP_CRITICAL:
logging.critical('Alarm for temperature critical is detected')
time.sleep(2)
os.system('reboot')
if ori_state==LEVEL_FAN_MAX:
if new_state==LEVEL_TEMP_HIGH:
if alarm_state==0:
logging.warning('Alarm for temperature high is detected')
alarm_state=1
if new_state==LEVEL_TEMP_CRITICAL:
logging.critical('Alarm for temperature critical is detected')
time.sleep(2)
os.system('reboot')
if alarm_state==1:
if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm
logging.warning('Alarm for temperature high is cleared')
alarm_state=0
if ori_state==LEVEL_TEMP_HIGH:
if new_state==LEVEL_TEMP_CRITICAL:
logging.critical('Alarm for temperature critical is detected')
time.sleep(2)
os.system('reboot')
if new_state <= LEVEL_FAN_MID:
logging.warning('Alarm for temperature high is cleared')
alarm_state=0
if new_state <= LEVEL_FAN_MAX:
if temp_get < (fan_policy[3][0] - 5000): #below 65 C, clear alarm
logging.warning('Alarm for temperature high is cleared')
alarm_state=0
if ori_state==LEVEL_TEMP_CRITICAL:
if new_state <= LEVEL_FAN_MAX:
logging.warning('Alarm for temperature critical is cleared')
if current_state!=ori_state:
fan_policy_state=current_state
new_duty_cycle=fan_policy[current_state][0]
logging.debug("fan_policy_state=%d, new_duty_cycle=%d", fan_policy_state, new_duty_cycle)
if new_duty_cycle!=ori_duty_cycle and fan_fail==0:
fan.set_fan_duty_cycle(new_duty_cycle)
return True
if new_duty_cycle==0 and fan_fail==0:
fan.set_fan_duty_cycle(FAN_DUTY_CYCLE_MAX)
return True
def main(argv):
@ -318,26 +512,25 @@ def main(argv):
log_file = arg
if sys.argv[1]== '-t':
if len(sys.argv)!=7:
print "temp test, need input six temp"
if len(sys.argv)!=10:
print "temp test, need input 8 temp"
return 0
i=0
for x in range(2, 7):
for x in range(2, 10):
test_temp_list[i]= int(sys.argv[x])*1000
i=i+1
test_temp = 1
test_temp = 1
log_level = logging.DEBUG
print test_temp_list
print test_temp_list
fan = FanUtil()
fan.set_fan_duty_cycle(38)
print "set default fan speed to 37.5%"
fan.set_fan_duty_cycle(100)
monitor = device_monitor(log_file, log_level)
# Loop forever, doing something useful hopefully:
while True:
#monitor.manage_fans()
time.sleep(5)
monitor.manage_fans()
time.sleep(10)
if __name__ == '__main__':
main(sys.argv[1:])

@ -1 +1 @@
Subproject commit 8c45a8e111534f9d4337d3552eaf08881fb19d30
Subproject commit 7b39cf3400dd728494b91810db9cc82542a22584

View File

@ -141,6 +141,8 @@ start)
sleep 0.1
done
/bin/sh /usr/local/bin/platform_api_mgnt.sh init
echo "done."
;;

View File

@ -1,3 +1,5 @@
dx010/scripts/dx010_check_qsfp.sh usr/local/bin
dx010/cfg/dx010-modules.conf etc/modules-load.d
dx010/systemd/platform-modules-dx010.service lib/systemd/system
dx010/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_seastone-r0
services/platform_api/platform_api_mgnt.sh usr/local/bin

View File

@ -1,3 +1,6 @@
depmod -a
systemctl enable platform-modules-dx010.service
systemctl start platform-modules-dx010.service
/usr/local/bin/platform_api_mgnt.sh install

View File

@ -69,6 +69,8 @@ start)
echo "both" > /sys/devices/platform/e1031.smc/SFP/modabs_trig
echo 0 > /sys/devices/platform/e1031.smc/SFP/modabs_mask
/bin/sh /usr/local/bin/platform_api_mgnt.sh init
echo "done."
;;

View File

@ -3,3 +3,5 @@ haliburton/systemd/platform-modules-haliburton.service lib/systemd/system
haliburton/script/fancontrol.sh etc/init.d
services/fancontrol/fancontrol.service lib/systemd/system
services/fancontrol/fancontrol usr/local/bin
haliburton/modules/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-cel_e1031-r0
services/platform_api/platform_api_mgnt.sh usr/local/bin

View File

@ -3,4 +3,6 @@ systemctl enable platform-modules-haliburton.service
systemctl enable fancontrol.service
systemctl start platform-modules-haliburton.service
systemctl start fancontrol.service
systemctl start fancontrol.service
/usr/local/bin/platform_api_mgnt.sh install

View File

@ -13,6 +13,9 @@ MODULE_DIRS:= dx010 haliburton
override_dh_auto_build:
(for mod in $(MODULE_DIRS); do \
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
cd $(MOD_SRC_DIR)/$${mod}; \
python2.7 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \
cd $(MOD_SRC_DIR); \
done)
override_dh_auto_install:

View File

@ -0,0 +1,34 @@
from setuptools import setup
DEVICE_NAME = 'celestica'
HW_SKU = 'x86_64-cel_seastone-r0'
setup(
name='sonic-platform',
version='1.0',
description='SONiC platform API implementation on Celestica Platforms',
license='Apache 2.0',
author='SONiC Team',
author_email='linuxnetdev@microsoft.com',
url='https://github.com/Azure/sonic-buildimage',
maintainer='Wirut Getbamrung',
maintainer_email='wgetbumr@celestica.com',
packages=[
'sonic_platform',
],
package_dir={
'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)},
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Plugins',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 2.7',
'Topic :: Utilities',
],
keywords='sonic SONiC platform PLATFORM',
)

View File

@ -0,0 +1,34 @@
from setuptools import setup
DEVICE_NAME = 'celestica'
HW_SKU = 'x86_64-cel_e1031-r0'
setup(
name='sonic-platform',
version='1.0',
description='SONiC platform API implementation on Celestica Platforms',
license='Apache 2.0',
author='SONiC Team',
author_email='linuxnetdev@microsoft.com',
url='https://github.com/Azure/sonic-buildimage',
maintainer='Wirut Getbamrung',
maintainer_email='wgetbumr@celestica.com',
packages=[
'sonic_platform',
],
package_dir={
'sonic_platform': '../../../../device/{}/{}/sonic_platform'.format(DEVICE_NAME, HW_SKU)},
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Plugins',
'Intended Audience :: Developers',
'Intended Audience :: Information Technology',
'Intended Audience :: System Administrators',
'License :: OSI Approved :: Apache Software License',
'Natural Language :: English',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 2.7',
'Topic :: Utilities',
],
keywords='sonic SONiC platform PLATFORM',
)

View File

@ -0,0 +1,41 @@
#!/bin/bash
PREV_REBOOT_CAUSE="/host/reboot-cause/"
DEVICE="/usr/share/sonic/device"
PLATFORM=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)
FILES=$DEVICE/$PLATFORM/api_files
install() {
# Install sonic-platform package
if [ -e $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl ]; then
pip install $DEVICE/$PLATFORM/sonic_platform-1.0-py2-none-any.whl
fi
}
init() {
# mount needed files for sonic-platform package
mkdir -p $FILES
mkdir -p $FILES/reboot-cause
mount -B $PREV_REBOOT_CAUSE $FILES/reboot-cause
}
deinit() {
# deinit sonic-platform package
umount -f $PREV_REBOOT_CAUSE $FILES/reboot-cause >/dev/null 2>/dev/null
}
uninstall() {
# Uninstall sonic-platform package
pip uninstall -y sonic-platform >/dev/null 2>/dev/null
}
case "$1" in
install | uninstall | init | deinit)
$1
;;
*)
echo "Usage: $0 {install|uninstall|init|deinit}"
exit 1
;;
esac

View File

@ -12,3 +12,4 @@ s6100/scripts/platform_watchdog_disable.sh usr/local/bin
s6100/scripts/sensors usr/bin
s6100/systemd/platform-modules-s6100.service etc/systemd/system
s6100/systemd/s6100-lpc-monitor.service etc/systemd/system
tools/flashrom/flashrom usr/local/bin/

View File

@ -22,7 +22,7 @@ start)
;;
stop)
/usr/local/bin/z9100_platform.sh deinit
/usr/local/bin/z9264f_platform.sh deinit
echo "done."
;;

View File

@ -9,6 +9,8 @@
try:
import os
import time
import datetime
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp
except ImportError as e:
@ -22,16 +24,19 @@ class Chassis(ChassisBase):
MAILBOX_DIR = "/sys/devices/platform/dell-s6000-cpld.0"
sfp_control = ""
PORT_START = 0
PORT_END = 0
reset_reason_dict = {}
reset_reason_dict[0xe] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
reset_reason_dict[0x6] = ChassisBase.REBOOT_CAUSE_NON_HARDWARE
def __init__(self):
# Initialize SFP list
PORT_START = 0
PORT_END = 31
self.PORT_START = 0
self.PORT_END = 31
EEPROM_OFFSET = 20
PORTS_IN_BLOCK = (PORT_END + 1)
PORTS_IN_BLOCK = (self.PORT_END + 1)
# sfp.py will read eeprom contents and retrive the eeprom data.
# It will also provide support sfp controls like reset and setting
@ -39,12 +44,16 @@ class Chassis(ChassisBase):
# We pass the eeprom path and sfp control path from chassis.py
# So that sfp.py implementation can be generic to all platforms
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
sfp_control = "/sys/devices/platform/dell-s6000-cpld.0/"
self.sfp_control = "/sys/devices/platform/dell-s6000-cpld.0/"
for index in range(0, PORTS_IN_BLOCK):
eeprom_path = eeprom_base.format(index + EEPROM_OFFSET)
sfp_node = Sfp(index, 'QSFP', eeprom_path, sfp_control, index)
sfp_node = Sfp(index, 'QSFP', eeprom_path, self.sfp_control, index)
self._sfp_list.append(sfp_node)
# Get Transceiver status
self.modprs_register = self._get_transceiver_status()
def get_register(self, reg_name):
rv = 'ERR'
mb_reg_file = self.MAILBOX_DIR+'/'+reg_name
@ -76,3 +85,69 @@ class Chassis(ChassisBase):
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
def _get_transceiver_status(self):
presence_ctrl = self.sfp_control + 'qsfp_modprs'
try:
reg_file = open(presence_ctrl)
except IOError as e:
return False
content = reg_file.readline().rstrip()
reg_file.close()
return int(content, 16)
def get_transceiver_change_event(self, timeout=0):
"""
Returns a dictionary containing sfp changes which have
experienced a change at chassis level
"""
start_time = time.time()
port_dict = {}
port = self.PORT_START
forever = False
if timeout == 0:
forever = True
elif timeout > 0:
timeout = timeout / float(1000) # Convert to secs
else:
return False, {}
end_time = start_time + timeout
if (start_time > end_time):
return False, {} # Time wrap or possibly incorrect timeout
while (timeout >= 0):
# Check for OIR events and return updated port_dict
reg_value = self._get_transceiver_status()
if (reg_value != self.modprs_register):
changed_ports = (self.modprs_register ^ reg_value)
while (port >= self.PORT_START and port <= self.PORT_END):
# Mask off the bit corresponding to our port
mask = (1 << port)
if (changed_ports & mask):
# ModPrsL is active low
if reg_value & mask == 0:
port_dict[port] = '1'
else:
port_dict[port] = '0'
port += 1
# Update reg value
self.modprs_register = reg_value
return True, port_dict
if forever:
time.sleep(1)
else:
timeout = end_time - time.time()
if timeout >= 1:
time.sleep(1) # We poll at 1 second granularity
else:
if timeout > 0:
time.sleep(timeout)
return True, {}
return False, {}

View File

@ -1 +0,0 @@
../../s6100/sonic_platform/sfp.py

View File

@ -0,0 +1,876 @@
#!/usr/bin/env python
#############################################################################
# DELLEMC
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
import os
import time
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PAGE_OFFSET = 0
KEY_OFFSET = 1
KEY_WIDTH = 2
FUNC_NAME = 3
INFO_OFFSET = 128
DOM_OFFSET = 0
DOM_OFFSET1 = 384
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
'Length OM1(m)', 'Length Cable Assembly(m)')
compliance_code_tup = (
'10/40G Ethernet Compliance Code',
'SONET Compliance codes',
'SAS/SATA compliance codes',
'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media',
'Fibre Channel Speed')
info_dict_keys = ['type', 'hardwarerev', 'serialnum',
'manufacturename', 'modelname', 'Connector',
'encoding', 'ext_identifier', 'ext_rateselect_compliance',
'cable_type', 'cable_length', 'nominal_bit_rate',
'specification_compliance', 'vendor_date', 'vendor_oui']
dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status',
'power_lpmode', 'tx_disable', 'tx_disable_channel',
'temperature', 'voltage', 'rx1power',
'rx2power', 'rx3power', 'rx4power',
'tx1bias', 'tx2bias', 'tx3bias',
'tx4bias', 'tx1power', 'tx2power',
'tx3power', 'tx4power']
threshold_dict_keys = ['temphighalarm', 'temphighwarning',
'templowalarm', 'templowwarning',
'vcchighalarm', 'vcchighwarning',
'vcclowalarm', 'vcclowwarning',
'rxpowerhighalarm', 'rxpowerhighwarning',
'rxpowerlowalarm', 'rxpowerlowwarning',
'txpowerhighalarm', 'txpowerhighwarning',
'txpowerlowalarm', 'txpowerlowwarning',
'txbiashighalarm', 'txbiashighwarning',
'txbiaslowalarm', 'txbiaslowwarning']
sff8436_parser = {
'reset_status': [DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'],
'rx_los': [DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'],
'tx_fault': [DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'],
'tx_disable': [DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'],
'power_lpmode': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'],
'power_override': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'],
'Temperature': [DOM_OFFSET, 22, 2, 'parse_temperature'],
'Voltage': [DOM_OFFSET, 26, 2, 'parse_voltage'],
'ChannelMonitor': [DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'],
'cable_type': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'cable_length': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'Connector': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'type': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'encoding': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'ext_identifier': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'ext_rateselect_compliance':
[INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'nominal_bit_rate': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'specification_compliance':
[INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'manufacturename': [INFO_OFFSET, 20, 16, 'parse_vendor_name'],
'vendor_oui': [INFO_OFFSET, 37, 3, 'parse_vendor_oui'],
'modelname': [INFO_OFFSET, 40, 16, 'parse_vendor_pn'],
'hardwarerev': [INFO_OFFSET, 56, 2, 'parse_vendor_rev'],
'serialnum': [INFO_OFFSET, 68, 16, 'parse_vendor_sn'],
'vendor_date': [INFO_OFFSET, 84, 8, 'parse_vendor_date'],
'ModuleThreshold': [DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'],
'ChannelThreshold': [DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'],
}
class Sfp(SfpBase):
"""
DELLEMC Platform-specific Sfp class
"""
def __init__(self, index, sfp_type, eeprom_path,
sfp_control, sfp_ctrl_idx):
SfpBase.__init__(self)
self.sfp_type = sfp_type
self.index = index
self.eeprom_path = eeprom_path
self.sfp_control = sfp_control
self.sfp_ctrl_idx = sfp_ctrl_idx
self.sfpInfo = sff8436InterfaceId()
self.sfpDomInfo = sff8436Dom()
def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes):
eeprom_raw = []
try:
eeprom = open(eeprom_path, mode="rb", buffering=0)
except IOError:
return None
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
try:
eeprom.seek(offset)
raw = eeprom.read(num_bytes)
except IOError:
eeprom.close()
return None
try:
for n in range(0, num_bytes):
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except BaseException:
eeprom.close()
return None
eeprom.close()
return eeprom_raw
def _get_eeprom_data(self, eeprom_key):
eeprom_data = None
page_offset = None
if (self.sfpInfo is None):
return None
page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET]
eeprom_data_raw = self._read_eeprom_bytes(
self.eeprom_path,
(sff8436_parser[eeprom_key][PAGE_OFFSET] +
sff8436_parser[eeprom_key][KEY_OFFSET]),
sff8436_parser[eeprom_key][KEY_WIDTH])
if (eeprom_data_raw is not None):
# Offset 128 is used to retrieve sff8436InterfaceId Info
# Offset 0 is used to retrieve sff8436Dom Info
if (page_offset == 128):
eeprom_data = getattr(
self.sfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
else:
eeprom_data = getattr(
self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
return eeprom_data
def get_transceiver_info(self):
"""
Retrieves transceiver info of this SFP
"""
transceiver_info_dict = {}
compliance_code_dict = {}
transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A')
# BaseInformation
iface_data = self._get_eeprom_data('type')
if (iface_data is not None):
connector = iface_data['data']['Connector']['value']
encoding = iface_data['data']['EncodingCodes']['value']
ext_id = iface_data['data']['Extended Identifier']['value']
rate_identifier = iface_data['data']['RateIdentifier']['value']
identifier = iface_data['data']['type']['value']
bit_rate = str(
iface_data['data']['Nominal Bit Rate(100Mbs)']['value'])
for key in compliance_code_tup:
if key in iface_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value']
for key in cable_length_tup:
if key in iface_data['data']:
cable_type = key
cable_length = str(iface_data['data'][key]['value'])
else:
return None
# Vendor Date
vendor_date_data = self._get_eeprom_data('vendor_date')
if (vendor_date_data is not None):
vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
else:
return None
# Vendor Name
vendor_name_data = self._get_eeprom_data('manufacturename')
if (vendor_name_data is not None):
vendor_name = vendor_name_data['data']['Vendor Name']['value']
else:
return None
# Vendor OUI
vendor_oui_data = self._get_eeprom_data('vendor_oui')
if (vendor_oui_data is not None):
vendor_oui = vendor_oui_data['data']['Vendor OUI']['value']
else:
return None
# Vendor PN
vendor_pn_data = self._get_eeprom_data('modelname')
if (vendor_pn_data is not None):
vendor_pn = vendor_pn_data['data']['Vendor PN']['value']
else:
return None
# Vendor Revision
vendor_rev_data = self._get_eeprom_data('hardwarerev')
if (vendor_rev_data is not None):
vendor_rev = vendor_rev_data['data']['Vendor Rev']['value']
else:
return None
# Vendor Serial Number
vendor_sn_data = self._get_eeprom_data('serialnum')
if (vendor_sn_data is not None):
vendor_sn = vendor_sn_data['data']['Vendor SN']['value']
else:
return None
# Fill The Dictionary and return
transceiver_info_dict['type'] = identifier
transceiver_info_dict['hardwarerev'] = vendor_rev
transceiver_info_dict['serialnum'] = vendor_sn
transceiver_info_dict['manufacturename'] = vendor_name
transceiver_info_dict['modelname'] = vendor_pn
transceiver_info_dict['Connector'] = connector
transceiver_info_dict['encoding'] = encoding
transceiver_info_dict['ext_identifier'] = ext_id
transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier
transceiver_info_dict['cable_type'] = cable_type
transceiver_info_dict['cable_length'] = cable_length
transceiver_info_dict['nominal_bit_rate'] = bit_rate
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['vendor_date'] = vendor_date
transceiver_info_dict['vendor_oui'] = vendor_oui
return transceiver_info_dict
def get_transceiver_threshold_info(self):
"""
Retrieves transceiver threshold info of this SFP
"""
transceiver_dom_threshold_dict = {}
transceiver_dom_threshold_dict = dict.fromkeys(
threshold_dict_keys, 'N/A')
# Module Threshold
module_threshold_data = self._get_eeprom_data('ModuleThreshold')
if (module_threshold_data is not None):
tempHighAlarm = module_threshold_data['data']['TempHighAlarm']['value']
tempLowAlarm = module_threshold_data['data']['TempLowAlarm']['value']
tempHighWarn = module_threshold_data['data']['TempHighWarning']['value']
tempLowWarn = module_threshold_data['data']['TempLowWarning']['value']
vccHighAlarm = module_threshold_data['data']['VccHighAlarm']['value']
vccLowAlarm = module_threshold_data['data']['VccLowAlarm']['value']
vccHighWarn = module_threshold_data['data']['VccHighWarning']['value']
vccLowWarn = module_threshold_data['data']['VccLowWarning']['value']
else:
return None
# Channel Threshold
channel_threshold_data = self._get_eeprom_data('ChannelThreshold')
if (channel_threshold_data is not None):
rxPowerHighAlarm = channel_threshold_data['data']['RxPowerHighAlarm']['value']
rxPowerLowAlarm = channel_threshold_data['data']['RxPowerLowAlarm']['value']
rxPowerHighWarn = channel_threshold_data['data']['RxPowerHighWarning']['value']
rxPowerLowWarn = channel_threshold_data['data']['RxPowerLowWarning']['value']
txBiasHighAlarm = channel_threshold_data['data']['TxBiasHighAlarm']['value']
txBiasLowAlarm = channel_threshold_data['data']['TxBiasLowAlarm']['value']
txBiasHighWarn = channel_threshold_data['data']['TxBiasHighWarning']['value']
txBiasLowWarn = channel_threshold_data['data']['TxBiasLowWarning']['value']
else:
return None
transceiver_dom_threshold_dict['temphighalarm'] = tempHighAlarm
transceiver_dom_threshold_dict['templowalarm'] = tempLowAlarm
transceiver_dom_threshold_dict['temphighwarning'] = tempHighWarn
transceiver_dom_threshold_dict['templowwarning'] = tempLowWarn
transceiver_dom_threshold_dict['vcchighalarm'] = vccHighAlarm
transceiver_dom_threshold_dict['vcclowalarm'] = vccLowAlarm
transceiver_dom_threshold_dict['vcchighwarning'] = vccHighWarn
transceiver_dom_threshold_dict['vcclowwarning'] = vccLowWarn
transceiver_dom_threshold_dict['rxpowerhighalarm'] = rxPowerHighAlarm
transceiver_dom_threshold_dict['rxpowerlowalarm'] = rxPowerLowAlarm
transceiver_dom_threshold_dict['rxpowerhighwarning'] = rxPowerHighWarn
transceiver_dom_threshold_dict['rxpowerlowwarning'] = rxPowerLowWarn
transceiver_dom_threshold_dict['txbiashighalarm'] = txBiasHighAlarm
transceiver_dom_threshold_dict['txbiaslowalarm'] = txBiasLowAlarm
transceiver_dom_threshold_dict['txbiashighwarning'] = txBiasHighWarn
transceiver_dom_threshold_dict['txbiaslowwarning'] = txBiasLowWarn
return transceiver_dom_threshold_dict
def get_transceiver_bulk_status(self):
"""
Retrieves transceiver bulk status of this SFP
"""
tx_bias_list = []
rx_power_list = []
transceiver_dom_dict = {}
transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A')
# RxLos
rx_los = self.get_rx_los()
# TxFault
tx_fault = self.get_tx_fault()
# ResetStatus
reset_state = self.get_reset_status()
# LowPower Mode
lp_mode = self.get_lpmode()
# TxDisable
tx_disable = self.get_tx_disable()
# TxDisable Channel
tx_disable_channel = self.get_tx_disable_channel()
# Temperature
temperature = self.get_temperature()
# Voltage
voltage = self.get_voltage()
# Channel Monitor
channel_monitor_data = self._get_eeprom_data('ChannelMonitor')
if (channel_monitor_data is not None):
tx_bias = channel_monitor_data['data']['TX1Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX2Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX3Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX4Bias']['value']
tx_bias_list.append(tx_bias)
rx_power = channel_monitor_data['data']['RX1Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX2Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX3Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX4Power']['value']
rx_power_list.append(rx_power)
else:
return None
transceiver_dom_dict['rx_los'] = rx_los
transceiver_dom_dict['tx_fault'] = tx_fault
transceiver_dom_dict['reset_status'] = reset_state
transceiver_dom_dict['power_lpmode'] = lp_mode
transceiver_dom_dict['tx_disable'] = tx_disable
transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel
transceiver_dom_dict['temperature'] = temperature
transceiver_dom_dict['voltage'] = voltage
transceiver_dom_dict['tx1bias'] = tx_bias_list[0]
transceiver_dom_dict['tx2bias'] = tx_bias_list[1]
transceiver_dom_dict['tx3bias'] = tx_bias_list[2]
transceiver_dom_dict['tx4bias'] = tx_bias_list[3]
transceiver_dom_dict['rx1power'] = rx_power_list[0]
transceiver_dom_dict['rx2power'] = rx_power_list[1]
transceiver_dom_dict['rx3power'] = rx_power_list[2]
transceiver_dom_dict['rx4power'] = rx_power_list[3]
return transceiver_dom_dict
def get_name(self):
"""
Retrieves the name of the sfp
Returns : QSFP or QSFP+ or QSFP28
"""
iface_data = self._get_eeprom_data('type')
if (iface_data is not None):
identifier = iface_data['data']['type']['value']
else:
return None
return identifier
def get_presence(self):
"""
Retrieves the presence of the sfp
"""
presence_ctrl = self.sfp_control + 'qsfp_modprs'
try:
reg_file = open(presence_ctrl)
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
mask = (1 << self.sfp_ctrl_idx)
# ModPrsL is active low
if ((reg_value & mask) == 0):
return True
return False
def get_model(self):
"""
Retrieves the model number (or part number) of the sfp
"""
vendor_pn_data = self._get_eeprom_data('modelname')
if (vendor_pn_data is not None):
vendor_pn = vendor_pn_data['data']['Vendor PN']['value']
else:
return None
return vendor_pn
def get_serial(self):
"""
Retrieves the serial number of the sfp
"""
vendor_sn_data = self._get_eeprom_data('serialnum')
if (vendor_sn_data is not None):
vendor_sn = vendor_sn_data['data']['Vendor SN']['value']
else:
return None
return vendor_sn
def get_reset_status(self):
"""
Retrieves the reset status of SFP
"""
reset_status = None
reset_ctrl = self.sfp_control + 'qsfp_reset'
try:
reg_file = open(reset_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
if ((reg_value & mask) == 0):
reset_status = True
else:
reset_status = False
return reset_status
def get_rx_los(self):
"""
Retrieves the RX LOS (lost-of-signal) status of SFP
"""
rx_los = None
rx_los_list = []
rx_los_data = self._get_eeprom_data('rx_los')
if (rx_los_data is not None):
rx_los = rx_los_data['data']['Rx1LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx2LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx3LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx4LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
if (rx_los_list[0] and rx_los_list[1]
and rx_los_list[2] and rx_los_list[3]):
rx_los = True
else:
rx_los = False
return rx_los
def get_tx_fault(self):
"""
Retrieves the TX fault status of SFP
"""
tx_fault = None
tx_fault_list = []
tx_fault_data = self._get_eeprom_data('tx_fault')
if (tx_fault_data is not None):
tx_fault = tx_fault_data['data']['Tx1Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx2Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx3Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx4Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
if (tx_fault_list[0] and tx_fault_list[1]
and tx_fault_list[2] and tx_fault_list[3]):
tx_fault = True
else:
tx_fault = False
return tx_fault
def get_tx_disable(self):
"""
Retrieves the tx_disable status of this SFP
"""
tx_disable = None
tx_disable_list = []
tx_disable_data = self._get_eeprom_data('tx_disable')
if (tx_disable_data is not None):
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
if (tx_disable_list[0] and tx_disable_list[1]
and tx_disable_list[2] and tx_disable_list[3]):
tx_disable = True
else:
tx_disable = False
return tx_disable
def get_tx_disable_channel(self):
"""
Retrieves the TX disabled channels in this SFP
"""
tx_disable = None
tx_disable_list = []
tx_disable_data = self._get_eeprom_data('tx_disable')
if (tx_disable_data is not None):
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
bit4 = int(tx_disable_list[3]) * 8
bit3 = int(tx_disable_list[2]) * 4
bit2 = int(tx_disable_list[1]) * 2
bit1 = int(tx_disable_list[0]) * 1
tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1)
return tx_disable_channel
def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
"""
lpmode_ctrl = self.sfp_control + 'qsfp_lpmode'
try:
reg_file = open(lpmode_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
if ((reg_value & mask) == 0):
lpmode_state = False
else:
lpmode_state = True
return lpmode_state
def get_power_override(self):
"""
Retrieves the power-override status of this SFP
"""
power_override_state = None
# Reset Status
power_override_data = self._get_eeprom_data('power_override')
if (power_override_data is not None):
power_override = power_override_data['data']['PowerOverRide']['value']
if (power_override is 'On'):
power_override_state = True
else:
power_override_state = False
return power_override_state
def get_temperature(self):
"""
Retrieves the temperature of this SFP
"""
temperature = None
temperature_data = self._get_eeprom_data('Temperature')
if (temperature_data is not None):
temperature = temperature_data['data']['Temperature']['value']
return temperature
def get_voltage(self):
"""
Retrieves the supply voltage of this SFP
"""
voltage = None
voltage_data = self._get_eeprom_data('Voltage')
if (voltage_data is not None):
voltage = voltage_data['data']['Vcc']['value']
return voltage
def get_tx_bias(self):
"""
Retrieves the TX bias current of this SFP
"""
tx_bias = None
tx_bias_list = []
tx_bias_data = self._get_eeprom_data('ChannelMonitor')
if (tx_bias_data is not None):
tx_bias = tx_bias_data['data']['TX1Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX2Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX3Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX4Bias']['value']
tx_bias_list.append(tx_bias)
return tx_bias_list
def get_rx_power(self):
"""
Retrieves the received optical power for this SFP
"""
rx_power = None
rx_power_list = []
rx_power_data = self._get_eeprom_data('ChannelMonitor')
if (rx_power_data is not None):
rx_power = rx_power_data['data']['RX1Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX2Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX3Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX4Power']['value']
rx_power_list.append(rx_power)
return rx_power_list
def get_tx_power(self):
"""
Retrieves the TX power of this SFP
"""
tx_power = None
tx_power_list = []
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
return tx_power_list
def reset(self):
"""
Reset SFP and return all user module settings to their default srate.
"""
reset_ctrl = self.sfp_control + 'qsfp_reset'
try:
# Open reset_ctrl in both read & write mode
reg_file = open(reset_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
# Mask off the bit corresponding to our port
mask = (1 << index)
# ResetL is active low
reg_value = (reg_value & ~mask)
# Convert our register value back to a
# hex string and write back
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
# Sleep 1 second to allow it to settle
time.sleep(1)
# Flip the bit back high and write back to the
# register to take port out of reset
try:
reg_file = open(reset_ctrl, "w")
except IOError as e:
return False
reg_value = reg_value | mask
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
return True
def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP
"""
lpmode_ctrl = self.sfp_control + 'qsfp_lpmode'
try:
reg_file = open(lpmode_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
# LPMode is active high; set or clear the bit accordingly
if lpmode is True:
reg_value = (reg_value | mask)
else:
reg_value = (reg_value & ~mask)
# Convert our register value back to a hex string and write back
content = hex(reg_value)
reg_file.seek(0)
reg_file.write(content)
reg_file.close()
return True
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def set_power_override(self, power_override, power_set):
"""
Sets SFP power level using power_override and power_set
"""
return False
def get_status(self):
"""
Retrieves the operational status of the device
"""
reset = self.get_reset_status()
if (reset == True):
status = False
else:
status = True
return status

View File

@ -10,6 +10,13 @@
try:
import os
import sys
import click
import subprocess
import glob
import sonic_device_util
from commands import getstatusoutput
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.sfp import Sfp
from sonic_platform.psu import Psu
@ -47,6 +54,8 @@ class Chassis(ChassisBase):
power_reason_dict[33] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
power_reason_dict[44] = ChassisBase.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED
_component_name_list = ["BIOS", "CPLD1", "CPLD2", "FPGA"]
def __init__(self):
ChassisBase.__init__(self)
@ -87,6 +96,19 @@ class Chassis(ChassisBase):
rv = rv.lstrip(" ")
return rv
# Run bash command and print output to stdout
def run_command(self, command):
click.echo(click.style("Command: ", fg='cyan') +
click.style(command, fg='green'))
proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE)
(out, err) = proc.communicate()
click.echo(out)
if proc.returncode != 0:
sys.exit(proc.returncode)
def get_name(self):
"""
Retrieves the name of the device
@ -177,3 +199,127 @@ class Chassis(ChassisBase):
return (self.reset_reason_dict[reset_reason], None)
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Invalid Reason")
def get_component_name_list(self):
"""
Retrieves chassis components list such as BIOS, CPLD, FPGA, etc.
Returns:
A list containing component name.
"""
return self._component_name_list
def get_firmware_version(self, component_name):
version = None
if component_name in self._component_name_list:
if component_name == self._component_name_list[0]: # BIOS
status, version = getstatusoutput(
"dmidecode -s system-version")
elif component_name == self._component_name_list[1]: # CPLD1
version = None
elif component_name == self._component_name_list[2]: # CPLD2
version = None
elif component_name == self._component_name_list[3]: # SMF
version = None
return version
def install_component_firmware(self, component_name, image_path):
bios_image = None
bios_version = "3.25.0."
bios_file_name = "S6100*BIOS*"
flashrom = "/usr/local/bin/flashrom"
PLATFORM_ROOT_PATH = '/usr/share/sonic/device'
machine_info = sonic_device_util.get_machine_info()
platform = sonic_device_util.get_platform_info(machine_info)
platform_path = "/".join([PLATFORM_ROOT_PATH, platform, "bin"])
warning = """
********************************************************************
* Warning - Upgrading BIOS is inherently risky and should only be *
* attempted when necessary. A failure at this upgrade may cause *
* a board RMA. Proceed with caution ! *
********************************************************************
"""
if component_name in self._component_name_list:
if component_name == self._component_name_list[0]: # BIOS
# current BIOS version
current_bios_version = self.get_firmware_version("BIOS")
# Construct BIOS image path
if image_path is not None:
image_path = image_path + platform_path
for name in glob.glob(
os.path.join(image_path, bios_file_name)):
bios_image = image_path = name
if not bios_image:
print "BIOS image file not found:", image_path
return False
# Extract BIOS image version
bios_image = os.path.basename(bios_image)
bios_image = bios_image.strip('S6100-BIOS-')
bios_image_version = bios_image.strip('.bin')
if bios_image_version.startswith(bios_version):
bios_image_minor = bios_image_version.replace(
bios_image_version[:7], '')
if bios_image_minor.startswith("2"):
bios_image_minor = bios_image_minor.split("-")[1]
if current_bios_version.startswith(bios_version):
current_bios_minor = current_bios_version.replace(
current_bios_version[:7], '')
if current_bios_minor.startswith("2"):
current_bios_minor = current_bios_minor.split("-")[1]
# BIOS version check
if bios_image_minor > current_bios_minor:
print warning
prompt_text = "New BIOS image " + bios_image_version + \
" available to install, continue?"
yes = click.confirm(prompt_text)
elif current_bios_minor > bios_image_minor:
print warning
prompt_text = "Do you want to downgrade BIOS image from " \
+ current_bios_version + " to " + \
bios_image_version + " continue?"
yes = click.confirm(prompt_text)
else:
print("BIOS is already with {} latest version".format(
current_bios_version))
return True
if yes:
command = flashrom + " -p" + " internal" + " -w " + \
image_path
self.run_command(command)
elif component_name == self._component_name_list[1]: # CPLD1
return False
elif component_name == self._component_name_list[2]: # CPLD2
return False
elif component_name == self._component_name_list[3]: # SMF
return False
else:
print "Invalid component Name:", component_name
return True

View File

@ -418,7 +418,13 @@ class Sfp(SfpBase):
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
mask = (1 << self.sfp_ctrl_idx)
if (self.sfp_ctrl_idx > 15):
index = self.sfp_ctrl_idx % 16
else:
index = self.sfp_ctrl_idx
# Mask off the bit corresponding to our port
mask = (1 << index)
# ModPrsL is active low
if ((reg_value & mask) == 0):
@ -849,3 +855,40 @@ class Sfp(SfpBase):
reg_file.close()
return True
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def set_power_override(self, power_override, power_set):
"""
Sets SFP power level using power_override and power_set
"""
return False
def get_status(self):
"""
Retrieves the operational status of the device
"""
reset = self.get_reset_status()
if (reset == True):
status = False
else:
status = True
return status

View File

@ -0,0 +1,10 @@
#!/bin/bash
export DELL_TOOLS_DIR="platform/broadcom/sonic-platform-modules-dell/tools"
cd $DELL_TOOLS_DIR
rm -rf $DELL_TOOLS_DIR/flashrom
git clone https://github.com/flashrom/flashrom.git
cd flashrom
git checkout tags/0.9.7
git apply ../0002-Flashrom-support-for-Intel-Rangeley-and-Denverton-CP.patch
make

View File

@ -1 +0,0 @@
../../s6100/sonic_platform/sfp.py

View File

@ -0,0 +1,879 @@
#!/usr/bin/env python
#############################################################################
# DELLEMC
#
# Module contains an implementation of SONiC Platform Base API and
# provides the platform information
#
#############################################################################
try:
import os
import time
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
PAGE_OFFSET = 0
KEY_OFFSET = 1
KEY_WIDTH = 2
FUNC_NAME = 3
INFO_OFFSET = 128
DOM_OFFSET = 0
DOM_OFFSET1 = 384
cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)',
'Length OM1(m)', 'Length Cable Assembly(m)')
compliance_code_tup = (
'10/40G Ethernet Compliance Code',
'SONET Compliance codes',
'SAS/SATA compliance codes',
'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media',
'Fibre Channel Speed')
info_dict_keys = ['type', 'hardwarerev', 'serialnum',
'manufacturename', 'modelname', 'Connector',
'encoding', 'ext_identifier', 'ext_rateselect_compliance',
'cable_type', 'cable_length', 'nominal_bit_rate',
'specification_compliance', 'vendor_date', 'vendor_oui']
dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status',
'power_lpmode', 'tx_disable', 'tx_disable_channel',
'temperature', 'voltage', 'rx1power',
'rx2power', 'rx3power', 'rx4power',
'tx1bias', 'tx2bias', 'tx3bias',
'tx4bias', 'tx1power', 'tx2power',
'tx3power', 'tx4power']
threshold_dict_keys = ['temphighalarm', 'temphighwarning',
'templowalarm', 'templowwarning',
'vcchighalarm', 'vcchighwarning',
'vcclowalarm', 'vcclowwarning',
'rxpowerhighalarm', 'rxpowerhighwarning',
'rxpowerlowalarm', 'rxpowerlowwarning',
'txpowerhighalarm', 'txpowerhighwarning',
'txpowerlowalarm', 'txpowerlowwarning',
'txbiashighalarm', 'txbiashighwarning',
'txbiaslowalarm', 'txbiaslowwarning']
sff8436_parser = {
'reset_status': [DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'],
'rx_los': [DOM_OFFSET, 3, 1, 'parse_dom_tx_rx_los'],
'tx_fault': [DOM_OFFSET, 4, 1, 'parse_dom_tx_fault'],
'tx_disable': [DOM_OFFSET, 86, 1, 'parse_dom_tx_disable'],
'power_lpmode': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'],
'power_override': [DOM_OFFSET, 93, 1, 'parse_dom_power_control'],
'Temperature': [DOM_OFFSET, 22, 2, 'parse_temperature'],
'Voltage': [DOM_OFFSET, 26, 2, 'parse_voltage'],
'ChannelMonitor': [DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'],
'cable_type': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'cable_length': [INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'Connector': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'type': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'encoding': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'ext_identifier': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'ext_rateselect_compliance':
[INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'nominal_bit_rate': [INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'specification_compliance':
[INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
'manufacturename': [INFO_OFFSET, 20, 16, 'parse_vendor_name'],
'vendor_oui': [INFO_OFFSET, 37, 3, 'parse_vendor_oui'],
'modelname': [INFO_OFFSET, 40, 16, 'parse_vendor_pn'],
'hardwarerev': [INFO_OFFSET, 56, 2, 'parse_vendor_rev'],
'serialnum': [INFO_OFFSET, 68, 16, 'parse_vendor_sn'],
'vendor_date': [INFO_OFFSET, 84, 8, 'parse_vendor_date'],
'ModuleThreshold': [DOM_OFFSET1, 128, 24, 'parse_module_threshold_values'],
'ChannelThreshold': [DOM_OFFSET1, 176, 16, 'parse_channel_threshold_values'],
}
class Sfp(SfpBase):
"""
DELLEMC Platform-specific Sfp class
"""
def __init__(self, index, sfp_type, eeprom_path,
sfp_control, sfp_ctrl_idx):
SfpBase.__init__(self)
self.sfp_type = sfp_type
self.index = index
self.eeprom_path = eeprom_path
self.sfp_control = sfp_control
self.sfp_ctrl_idx = sfp_ctrl_idx
self.sfpInfo = sff8436InterfaceId()
self.sfpDomInfo = sff8436Dom()
def _read_eeprom_bytes(self, eeprom_path, offset, num_bytes):
eeprom_raw = []
try:
eeprom = open(eeprom_path, mode="rb", buffering=0)
except IOError:
return None
for i in range(0, num_bytes):
eeprom_raw.append("0x00")
try:
eeprom.seek(offset)
raw = eeprom.read(num_bytes)
except IOError:
eeprom.close()
return None
try:
for n in range(0, num_bytes):
eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2)
except BaseException:
eeprom.close()
return None
eeprom.close()
return eeprom_raw
def _get_eeprom_data(self, eeprom_key):
eeprom_data = None
page_offset = None
if (self.sfpInfo is None):
return None
page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET]
eeprom_data_raw = self._read_eeprom_bytes(
self.eeprom_path,
(sff8436_parser[eeprom_key][PAGE_OFFSET] +
sff8436_parser[eeprom_key][KEY_OFFSET]),
sff8436_parser[eeprom_key][KEY_WIDTH])
if (eeprom_data_raw is not None):
# Offset 128 is used to retrieve sff8436InterfaceId Info
# Offset 0 is used to retrieve sff8436Dom Info
if (page_offset == 128):
eeprom_data = getattr(
self.sfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
else:
eeprom_data = getattr(
self.sfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
return eeprom_data
def get_transceiver_info(self):
"""
Retrieves transceiver info of this SFP
"""
transceiver_info_dict = {}
compliance_code_dict = {}
transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A')
# BaseInformation
iface_data = self._get_eeprom_data('type')
if (iface_data is not None):
connector = iface_data['data']['Connector']['value']
encoding = iface_data['data']['EncodingCodes']['value']
ext_id = iface_data['data']['Extended Identifier']['value']
rate_identifier = iface_data['data']['RateIdentifier']['value']
identifier = iface_data['data']['type']['value']
bit_rate = str(
iface_data['data']['Nominal Bit Rate(100Mbs)']['value'])
for key in compliance_code_tup:
if key in iface_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value']
for key in cable_length_tup:
if key in iface_data['data']:
cable_type = key
cable_length = str(iface_data['data'][key]['value'])
else:
return None
# Vendor Date
vendor_date_data = self._get_eeprom_data('vendor_date')
if (vendor_date_data is not None):
vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
else:
return None
# Vendor Name
vendor_name_data = self._get_eeprom_data('manufacturename')
if (vendor_name_data is not None):
vendor_name = vendor_name_data['data']['Vendor Name']['value']
else:
return None
# Vendor OUI
vendor_oui_data = self._get_eeprom_data('vendor_oui')
if (vendor_oui_data is not None):
vendor_oui = vendor_oui_data['data']['Vendor OUI']['value']
else:
return None
# Vendor PN
vendor_pn_data = self._get_eeprom_data('modelname')
if (vendor_pn_data is not None):
vendor_pn = vendor_pn_data['data']['Vendor PN']['value']
else:
return None
# Vendor Revision
vendor_rev_data = self._get_eeprom_data('hardwarerev')
if (vendor_rev_data is not None):
vendor_rev = vendor_rev_data['data']['Vendor Rev']['value']
else:
return None
# Vendor Serial Number
vendor_sn_data = self._get_eeprom_data('serialnum')
if (vendor_sn_data is not None):
vendor_sn = vendor_sn_data['data']['Vendor SN']['value']
else:
return None
# Fill The Dictionary and return
transceiver_info_dict['type'] = identifier
transceiver_info_dict['hardwarerev'] = vendor_rev
transceiver_info_dict['serialnum'] = vendor_sn
transceiver_info_dict['manufacturename'] = vendor_name
transceiver_info_dict['modelname'] = vendor_pn
transceiver_info_dict['Connector'] = connector
transceiver_info_dict['encoding'] = encoding
transceiver_info_dict['ext_identifier'] = ext_id
transceiver_info_dict['ext_rateselect_compliance'] = rate_identifier
transceiver_info_dict['cable_type'] = cable_type
transceiver_info_dict['cable_length'] = cable_length
transceiver_info_dict['nominal_bit_rate'] = bit_rate
transceiver_info_dict['specification_compliance'] = str(
compliance_code_dict)
transceiver_info_dict['vendor_date'] = vendor_date
transceiver_info_dict['vendor_oui'] = vendor_oui
return transceiver_info_dict
def get_transceiver_threshold_info(self):
"""
Retrieves transceiver threshold info of this SFP
"""
transceiver_dom_threshold_dict = {}
transceiver_dom_threshold_dict = dict.fromkeys(
threshold_dict_keys, 'N/A')
# Module Threshold
module_threshold_data = self._get_eeprom_data('ModuleThreshold')
if (module_threshold_data is not None):
tempHighAlarm = module_threshold_data['data']['TempHighAlarm']['value']
tempLowAlarm = module_threshold_data['data']['TempLowAlarm']['value']
tempHighWarn = module_threshold_data['data']['TempHighWarning']['value']
tempLowWarn = module_threshold_data['data']['TempLowWarning']['value']
vccHighAlarm = module_threshold_data['data']['VccHighAlarm']['value']
vccLowAlarm = module_threshold_data['data']['VccLowAlarm']['value']
vccHighWarn = module_threshold_data['data']['VccHighWarning']['value']
vccLowWarn = module_threshold_data['data']['VccLowWarning']['value']
else:
return None
# Channel Threshold
channel_threshold_data = self._get_eeprom_data('ChannelThreshold')
if (channel_threshold_data is not None):
rxPowerHighAlarm = channel_threshold_data['data']['RxPowerHighAlarm']['value']
rxPowerLowAlarm = channel_threshold_data['data']['RxPowerLowAlarm']['value']
rxPowerHighWarn = channel_threshold_data['data']['RxPowerHighWarning']['value']
rxPowerLowWarn = channel_threshold_data['data']['RxPowerLowWarning']['value']
txBiasHighAlarm = channel_threshold_data['data']['TxBiasHighAlarm']['value']
txBiasLowAlarm = channel_threshold_data['data']['TxBiasLowAlarm']['value']
txBiasHighWarn = channel_threshold_data['data']['TxBiasHighWarning']['value']
txBiasLowWarn = channel_threshold_data['data']['TxBiasLowWarning']['value']
else:
return None
transceiver_dom_threshold_dict['temphighalarm'] = tempHighAlarm
transceiver_dom_threshold_dict['templowalarm'] = tempLowAlarm
transceiver_dom_threshold_dict['temphighwarning'] = tempHighWarn
transceiver_dom_threshold_dict['templowwarning'] = tempLowWarn
transceiver_dom_threshold_dict['vcchighalarm'] = vccHighAlarm
transceiver_dom_threshold_dict['vcclowalarm'] = vccLowAlarm
transceiver_dom_threshold_dict['vcchighwarning'] = vccHighWarn
transceiver_dom_threshold_dict['vcclowwarning'] = vccLowWarn
transceiver_dom_threshold_dict['rxpowerhighalarm'] = rxPowerHighAlarm
transceiver_dom_threshold_dict['rxpowerlowalarm'] = rxPowerLowAlarm
transceiver_dom_threshold_dict['rxpowerhighwarning'] = rxPowerHighWarn
transceiver_dom_threshold_dict['rxpowerlowwarning'] = rxPowerLowWarn
transceiver_dom_threshold_dict['txbiashighalarm'] = txBiasHighAlarm
transceiver_dom_threshold_dict['txbiaslowalarm'] = txBiasLowAlarm
transceiver_dom_threshold_dict['txbiashighwarning'] = txBiasHighWarn
transceiver_dom_threshold_dict['txbiaslowwarning'] = txBiasLowWarn
return transceiver_dom_threshold_dict
def get_transceiver_bulk_status(self):
"""
Retrieves transceiver bulk status of this SFP
"""
tx_bias_list = []
rx_power_list = []
transceiver_dom_dict = {}
transceiver_dom_dict = dict.fromkeys(dom_dict_keys, 'N/A')
# RxLos
rx_los = self.get_rx_los()
# TxFault
tx_fault = self.get_tx_fault()
# ResetStatus
reset_state = self.get_reset_status()
# LowPower Mode
lp_mode = self.get_lpmode()
# TxDisable
tx_disable = self.get_tx_disable()
# TxDisable Channel
tx_disable_channel = self.get_tx_disable_channel()
# Temperature
temperature = self.get_temperature()
# Voltage
voltage = self.get_voltage()
# Channel Monitor
channel_monitor_data = self._get_eeprom_data('ChannelMonitor')
if (channel_monitor_data is not None):
tx_bias = channel_monitor_data['data']['TX1Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX2Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX3Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = channel_monitor_data['data']['TX4Bias']['value']
tx_bias_list.append(tx_bias)
rx_power = channel_monitor_data['data']['RX1Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX2Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX3Power']['value']
rx_power_list.append(rx_power)
rx_power = channel_monitor_data['data']['RX4Power']['value']
rx_power_list.append(rx_power)
else:
return None
transceiver_dom_dict['rx_los'] = rx_los
transceiver_dom_dict['tx_fault'] = tx_fault
transceiver_dom_dict['reset_status'] = reset_state
transceiver_dom_dict['power_lpmode'] = lp_mode
transceiver_dom_dict['tx_disable'] = tx_disable
transceiver_dom_dict['tx_disable_channel'] = tx_disable_channel
transceiver_dom_dict['temperature'] = temperature
transceiver_dom_dict['voltage'] = voltage
transceiver_dom_dict['tx1bias'] = tx_bias_list[0]
transceiver_dom_dict['tx2bias'] = tx_bias_list[1]
transceiver_dom_dict['tx3bias'] = tx_bias_list[2]
transceiver_dom_dict['tx4bias'] = tx_bias_list[3]
transceiver_dom_dict['rx1power'] = rx_power_list[0]
transceiver_dom_dict['rx2power'] = rx_power_list[1]
transceiver_dom_dict['rx3power'] = rx_power_list[2]
transceiver_dom_dict['rx4power'] = rx_power_list[3]
return transceiver_dom_dict
def get_name(self):
"""
Retrieves the name of the sfp
Returns : QSFP or QSFP+ or QSFP28
"""
iface_data = self._get_eeprom_data('type')
if (iface_data is not None):
identifier = iface_data['data']['type']['value']
else:
return None
return identifier
def get_presence(self):
"""
Retrieves the presence of the sfp
"""
presence_ctrl = self.sfp_control + 'qsfp_modprs'
try:
reg_file = open(presence_ctrl)
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
# Mask off the bit corresponding to our port
mask = (1 << index)
# ModPrsL is active low
if ((reg_value & mask) == 0):
return True
return False
def get_model(self):
"""
Retrieves the model number (or part number) of the sfp
"""
vendor_pn_data = self._get_eeprom_data('modelname')
if (vendor_pn_data is not None):
vendor_pn = vendor_pn_data['data']['Vendor PN']['value']
else:
return None
return vendor_pn
def get_serial(self):
"""
Retrieves the serial number of the sfp
"""
vendor_sn_data = self._get_eeprom_data('serialnum')
if (vendor_sn_data is not None):
vendor_sn = vendor_sn_data['data']['Vendor SN']['value']
else:
return None
return vendor_sn
def get_reset_status(self):
"""
Retrieves the reset status of SFP
"""
reset_status = None
reset_ctrl = self.sfp_control + 'qsfp_reset'
try:
reg_file = open(reset_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
if ((reg_value & mask) == 0):
reset_status = True
else:
reset_status = False
return reset_status
def get_rx_los(self):
"""
Retrieves the RX LOS (lost-of-signal) status of SFP
"""
rx_los = None
rx_los_list = []
rx_los_data = self._get_eeprom_data('rx_los')
if (rx_los_data is not None):
rx_los = rx_los_data['data']['Rx1LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx2LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx3LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
rx_los = rx_los_data['data']['Rx4LOS']['value']
if (rx_los is 'On'):
rx_los_list.append(True)
else:
rx_los_list.append(False)
if (rx_los_list[0] and rx_los_list[1]
and rx_los_list[2] and rx_los_list[3]):
rx_los = True
else:
rx_los = False
return rx_los
def get_tx_fault(self):
"""
Retrieves the TX fault status of SFP
"""
tx_fault = None
tx_fault_list = []
tx_fault_data = self._get_eeprom_data('tx_fault')
if (tx_fault_data is not None):
tx_fault = tx_fault_data['data']['Tx1Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx2Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx3Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
tx_fault = tx_fault_data['data']['Tx4Fault']['value']
if (tx_fault is 'On'):
tx_fault_list.append(True)
else:
tx_fault_list.append(False)
if (tx_fault_list[0] and tx_fault_list[1]
and tx_fault_list[2] and tx_fault_list[3]):
tx_fault = True
else:
tx_fault = False
return tx_fault
def get_tx_disable(self):
"""
Retrieves the tx_disable status of this SFP
"""
tx_disable = None
tx_disable_list = []
tx_disable_data = self._get_eeprom_data('tx_disable')
if (tx_disable_data is not None):
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(True)
else:
tx_disable_list.append(False)
if (tx_disable_list[0] and tx_disable_list[1]
and tx_disable_list[2] and tx_disable_list[3]):
tx_disable = True
else:
tx_disable = False
return tx_disable
def get_tx_disable_channel(self):
"""
Retrieves the TX disabled channels in this SFP
"""
tx_disable = None
tx_disable_list = []
tx_disable_data = self._get_eeprom_data('tx_disable')
if (tx_disable_data is not None):
tx_disable = tx_disable_data['data']['Tx1Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx2Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx3Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
tx_disable = tx_disable_data['data']['Tx4Disable']['value']
if (tx_disable is 'On'):
tx_disable_list.append(1)
else:
tx_disable_list.append(0)
bit4 = int(tx_disable_list[3]) * 8
bit3 = int(tx_disable_list[2]) * 4
bit2 = int(tx_disable_list[1]) * 2
bit1 = int(tx_disable_list[0]) * 1
tx_disable_channel = hex(bit4 + bit3 + bit2 + bit1)
return tx_disable_channel
def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
"""
lpmode_ctrl = self.sfp_control + 'qsfp_lpmode'
try:
reg_file = open(lpmode_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
if ((reg_value & mask) == 0):
lpmode_state = False
else:
lpmode_state = True
return lpmode_state
def get_power_override(self):
"""
Retrieves the power-override status of this SFP
"""
power_override_state = None
# Reset Status
power_override_data = self._get_eeprom_data('power_override')
if (power_override_data is not None):
power_override = power_override_data['data']['PowerOverRide']['value']
if (power_override is 'On'):
power_override_state = True
else:
power_override_state = False
return power_override_state
def get_temperature(self):
"""
Retrieves the temperature of this SFP
"""
temperature = None
temperature_data = self._get_eeprom_data('Temperature')
if (temperature_data is not None):
temperature = temperature_data['data']['Temperature']['value']
return temperature
def get_voltage(self):
"""
Retrieves the supply voltage of this SFP
"""
voltage = None
voltage_data = self._get_eeprom_data('Voltage')
if (voltage_data is not None):
voltage = voltage_data['data']['Vcc']['value']
return voltage
def get_tx_bias(self):
"""
Retrieves the TX bias current of this SFP
"""
tx_bias = None
tx_bias_list = []
tx_bias_data = self._get_eeprom_data('ChannelMonitor')
if (tx_bias_data is not None):
tx_bias = tx_bias_data['data']['TX1Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX2Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX3Bias']['value']
tx_bias_list.append(tx_bias)
tx_bias = tx_bias_data['data']['TX4Bias']['value']
tx_bias_list.append(tx_bias)
return tx_bias_list
def get_rx_power(self):
"""
Retrieves the received optical power for this SFP
"""
rx_power = None
rx_power_list = []
rx_power_data = self._get_eeprom_data('ChannelMonitor')
if (rx_power_data is not None):
rx_power = rx_power_data['data']['RX1Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX2Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX3Power']['value']
rx_power_list.append(rx_power)
rx_power = rx_power_data['data']['RX4Power']['value']
rx_power_list.append(rx_power)
return rx_power_list
def get_tx_power(self):
"""
Retrieves the TX power of this SFP
"""
tx_power = None
tx_power_list = []
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
tx_power_list.append('-infdBm')
return tx_power_list
def reset(self):
"""
Reset SFP and return all user module settings to their default srate.
"""
reset_ctrl = self.sfp_control + 'qsfp_reset'
try:
# Open reset_ctrl in both read & write mode
reg_file = open(reset_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
# Mask off the bit corresponding to our port
mask = (1 << index)
# ResetL is active low
reg_value = (reg_value & ~mask)
# Convert our register value back to a
# hex string and write back
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
# Sleep 1 second to allow it to settle
time.sleep(1)
# Flip the bit back high and write back to the
# register to take port out of reset
try:
reg_file = open(reset_ctrl, "w")
except IOError as e:
return False
reg_value = reg_value | mask
reg_file.seek(0)
reg_file.write(hex(reg_value))
reg_file.close()
return True
def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP
"""
lpmode_ctrl = self.sfp_control + 'qsfp_lpmode'
try:
reg_file = open(lpmode_ctrl, "r+")
except IOError as e:
return False
reg_hex = reg_file.readline().rstrip()
# content is a string containing the hex
# representation of the register
reg_value = int(reg_hex, 16)
# Mask off the bit corresponding to our port
index = self.sfp_ctrl_idx
mask = (1 << index)
# LPMode is active high; set or clear the bit accordingly
if lpmode is True:
reg_value = (reg_value | mask)
else:
reg_value = (reg_value & ~mask)
# Convert our register value back to a hex string and write back
content = hex(reg_value)
reg_file.seek(0)
reg_file.write(content)
reg_file.close()
return True
def tx_disable(self, tx_disable):
"""
Disable SFP TX for all channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def tx_disable_channel(self, channel, disable):
"""
Sets the tx_disable for specified SFP channels
"""
return False
def set_power_override(self, power_override, power_set):
"""
Sets SFP power level using power_override and power_set
"""
return False
def get_status(self):
"""
Retrieves the operational status of the device
"""
reset = self.get_reset_status()
if (reset == True):
status = False
else:
status = True
return status

View File

@ -85,6 +85,22 @@ switch_board_modsel() {
python /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1
done
}
# Copy led_proc_init.soc file according to the HWSKU
init_switch_port_led() {
device="/usr/share/sonic/device"
platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform)
hwsku=$(cat /etc/sonic/config_db.json | grep "hwsku" | cut -d ":" -f2 | sed 's/"//g' | sed 's/,//g'| xargs )
led_proc_init="$device/$platform/$hwsku/led_proc_init.soc"
# Remove old HWSKU LED file..
rm -rf $device/$platform/led_proc_init.soc
if [ -e $led_proc_init ] && [ ! -e $device/$platform/led_proc_init.soc ]; then
cp $led_proc_init $device/$platform/
fi
}
init_devnum
if [ "$1" == "init" ]; then
@ -98,6 +114,7 @@ if [ "$1" == "init" ]; then
switch_board_qsfp_mux "new_device"
switch_board_qsfp "new_device"
switch_board_modsel
init_switch_port_led
python /usr/bin/qsfp_irq_enable.py
elif [ "$1" == "deinit" ]; then

Some files were not shown because too many files have changed in this diff Show More