[Centec][arm64] support new board E530-48s4x and E530-24x2q (#7189)

1. support new board E530-48s4x E530-24x2q
2. optimize platform driver for Centec TsingMa board

Co-authored-by: shi lei <shil@centecnetworks.com>
This commit is contained in:
guxianghong 2021-05-02 01:37:07 +08:00 committed by GitHub
parent 78b45085e9
commit be4cf09b5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
121 changed files with 8259 additions and 471 deletions

View File

@ -1,27 +1,27 @@
# name lanes alias speed # name lanes alias index speed fec
Ethernet1 0 eth-0-1 10000 Ethernet0 0 eth-0-1 0 10000 none
Ethernet2 1 eth-0-2 10000 Ethernet1 1 eth-0-2 1 10000 none
Ethernet3 2 eth-0-3 10000 Ethernet2 2 eth-0-3 2 10000 none
Ethernet4 3 eth-0-4 10000 Ethernet3 3 eth-0-4 3 10000 none
Ethernet5 8 eth-0-5 10000 Ethernet4 8 eth-0-5 4 10000 none
Ethernet6 9 eth-0-6 10000 Ethernet5 9 eth-0-6 5 10000 none
Ethernet7 10 eth-0-7 10000 Ethernet6 10 eth-0-7 6 10000 none
Ethernet8 11 eth-0-8 10000 Ethernet7 11 eth-0-8 7 10000 none
Ethernet9 20 eth-0-9 10000 Ethernet8 20 eth-0-9 8 10000 none
Ethernet10 21 eth-0-10 10000 Ethernet9 21 eth-0-10 9 10000 none
Ethernet11 22 eth-0-11 10000 Ethernet10 22 eth-0-11 10 10000 none
Ethernet12 23 eth-0-12 10000 Ethernet11 23 eth-0-12 11 10000 none
Ethernet13 12 eth-0-13 10000 Ethernet12 12 eth-0-13 12 10000 none
Ethernet14 13 eth-0-14 10000 Ethernet13 13 eth-0-14 13 10000 none
Ethernet15 14 eth-0-15 10000 Ethernet14 14 eth-0-15 14 10000 none
Ethernet16 15 eth-0-16 10000 Ethernet15 15 eth-0-16 15 10000 none
Ethernet17 24 eth-0-17 10000 Ethernet16 24 eth-0-17 16 10000 none
Ethernet18 25 eth-0-18 10000 Ethernet17 25 eth-0-18 17 10000 none
Ethernet19 26 eth-0-19 10000 Ethernet18 26 eth-0-19 18 10000 none
Ethernet20 27 eth-0-20 10000 Ethernet19 27 eth-0-20 19 10000 none
Ethernet21 28 eth-0-21 10000 Ethernet20 28 eth-0-21 20 10000 none
Ethernet22 29 eth-0-22 10000 Ethernet21 29 eth-0-22 21 10000 none
Ethernet23 30 eth-0-23 10000 Ethernet22 30 eth-0-23 22 10000 none
Ethernet24 31 eth-0-24 10000 Ethernet23 31 eth-0-24 23 10000 none
Ethernet25 61,60,63,62 eth-0-25 100000 Ethernet24 61,60,63,62 eth-0-25 24 100000 none
Ethernet26 45,44,47,46 eth-0-26 100000 Ethernet25 45,44,47,46 eth-0-26 25 100000 none

View File

@ -1 +1,12 @@
# Configuration file generated by pwmconfig, changes will be lost # Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
DEVNAME=hwmon1=ctc5236fan
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18

View File

@ -0,0 +1,8 @@
{
"chassis": {
"E530-24x2c": {
"component": {
}
}
}
}

View File

@ -0,0 +1,11 @@
#!/usr/bin/python
import os
def main():
# reboot the system
os.system('echo 502 > /sys/class/gpio/export')
os.system('echo out > /sys/class/gpio/gpio502/direction')
os.system('echo 1 > /sys/class/gpio/gpio502/value')
if __name__ == "__main__":
main()

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
############################################################################# #############################################################################
# Centec E550-24X8Y2C # Centec E550-24X8Y2C
# #
@ -10,7 +12,7 @@
try: try:
from sonic_eeprom import eeprom_tlvinfo from sonic_eeprom import eeprom_tlvinfo
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder): class board(eeprom_tlvinfo.TlvInfoDecoder):

View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
# #
# led_control.py # led_control.py
# #
@ -5,37 +6,110 @@
# #
try: try:
from sonic_led.led_control_base import LedControlBase import os
import re
import syslog import syslog
from socket import * import collections
from select import * from sonic_led.led_control_base import LedControlBase
from sonic_py_common import device_info
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + " - required module not found") raise ImportError(str(e) + " - required module not found")
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
def DBG_PRINT(str): def DBG_PRINT(str):
syslog.openlog("centec-led") syslog.openlog("centec-led")
syslog.syslog(syslog.LOG_INFO, str) syslog.syslog(syslog.LOG_INFO, str)
syslog.closelog() syslog.closelog()
class LedControl(LedControlBase): class LedControl(LedControlBase):
"""Platform specific LED control class""" """Platform specific LED control class"""
# Constructor
def __init__(self):
self.mac_to_led = {
0: 1,
1: 2,
2: 3,
3: 4,
8: 5,
9: 6,
10: 7,
11: 8,
20: 9,
21:10,
22:11,
23:12,
12:13,
13:14,
14:15,
15:16,
24:17,
25:18,
26:19,
27:20,
28:21,
29:22,
30:23,
31:24,
61:-1,
60:25,
63:-1,
62:-1,
45:-1,
44:26,
47:-1,
46:-1,
}
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
self.LED_MODE_UP = [11, 11]
self.LED_MODE_DOWN = [7, 7]
self.f_led = "/sys/class/leds/{}/brightness"
self._initDefaultConfig()
# Helper method to map SONiC port name to index # Helper method to map SONiC port name to index
def _port_name_to_index(self, port_name): def _port_name_to_index(self, port_name):
# Strip "Ethernet" off port name for port_cfg in self._port_cfgs:
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX): if port_name == port_cfg.name:
return -1 macs = [int(x) for x in (port_cfg.lanes.split(','))]
led = self.mac_to_led[min(macs)]
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) if led < 0:
return port_idx return None
return led
return None
def _port_state_to_mode(self, port_idx, state): def _port_state_to_mode(self, port_idx, state):
if state == "up": if state == "up":
return self.LED_MODE_UP[0] if (port_idx < 25) else self.LED_MODE_UP[1] return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0]
else: else:
return self.LED_MODE_DOWN[0] if (port_idx < 25) else self.LED_MODE_DOWN[1] return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0]
def _port_led_mode_update(self, port_idx, ledMode): def _port_led_mode_update(self, port_idx, ledMode):
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file: with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
@ -57,11 +131,15 @@ class LedControl(LedControlBase):
shouldInit = (int(led_file.read()) == 0) shouldInit = (int(led_file.read()) == 0)
if shouldInit == True: if shouldInit == True:
for idx in range(1, 27): for port_cfg in self._port_cfgs:
defmode = self._port_state_to_mode(idx, "down") macs = [int(x) for x in (port_cfg.lanes.split(','))]
with open(self.f_led.format("port{}".format(idx)), 'w') as led_file: led = self.mac_to_led[min(macs)]
if led < 0:
continue
defmode = self._port_state_to_mode(led, "down")
with open(self.f_led.format("port{}".format(led)), 'w') as led_file:
led_file.write(str(defmode)) led_file.write(str(defmode))
DBG_PRINT("init port{} led to mode={}".format(idx, defmode)) DBG_PRINT("init port{} led to mode={}".format(led, defmode))
def _initDefaultConfig(self): def _initDefaultConfig(self):
DBG_PRINT("start init led") DBG_PRINT("start init led")
@ -72,9 +150,10 @@ class LedControl(LedControlBase):
DBG_PRINT("init led done") DBG_PRINT("init led done")
# Concrete implementation of port_link_state_change() method # Concrete implementation of port_link_state_change() method
def port_link_state_change(self, portname, state): def port_link_state_change(self, portname, state):
port_idx = self._port_name_to_index(portname) port_idx = self._port_name_to_index(portname)
if port_idx is None:
return
ledMode = self._port_state_to_mode(port_idx, state) ledMode = self._port_state_to_mode(port_idx, state)
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file: with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
saveMode = int(led_file.read()) saveMode = int(led_file.read())
@ -84,13 +163,3 @@ class LedControl(LedControlBase):
self._port_led_mode_update(port_idx, ledMode) self._port_led_mode_update(port_idx, ledMode)
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
# Constructor
def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.LED_MODE_UP = [11, 11]
self.LED_MODE_DOWN = [7, 7]
self.f_led = "/sys/class/leds/{}/brightness"
self._initDefaultConfig()

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
############################################################################# #############################################################################
# Centec # Centec
# #
@ -9,8 +11,7 @@
try: try:
from sonic_psu.psu_base import PsuBase from sonic_psu.psu_base import PsuBase
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError (str(e) + "- required module not found")
class PsuUtil(PsuBase): class PsuUtil(PsuBase):
"""Platform-specific PSUutil class""" """Platform-specific PSUutil class"""

View File

@ -1,28 +1,117 @@
#!/usr/bin/env python
# sfputil.py # sfputil.py
# #
# Platform-specific SFP transceiver interface for SONiC # Platform-specific SFP transceiver interface for SONiC
# #
try: try:
import os
import re
import time import time
from socket import * import collections
from select import *
from sonic_sfp.sfputilbase import SfpUtilBase from sonic_sfp.sfputilbase import SfpUtilBase
from sonic_py_common import device_info
except ImportError as e: except ImportError as e:
raise ImportError("%s - required module not found" % str(e)) raise ImportError("%s - required module not found" % str(e))
def DBG_PRINT(str):
print(str + "\n")
SFP_STATUS_INSERTED = '1' SFP_STATUS_INSERTED = '1'
SFP_STATUS_REMOVED = '0' SFP_STATUS_REMOVED = '0'
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class SfpUtil(SfpUtilBase): class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class""" """Platform-specific SfpUtil class"""
def __init__(self):
self.mac_to_sfp = {
0: 1,
1: 2,
2: 3,
3: 4,
8: 5,
9: 6,
10: 7,
11: 8,
20: 9,
21:10,
22:11,
23:12,
12:13,
13:14,
14:15,
15:16,
24:17,
25:18,
26:19,
27:20,
28:21,
29:22,
30:23,
31:24,
61:25,
60:25,
63:25,
62:25,
45:26,
44:26,
47:26,
46:26,
}
self.logical = []
self.physical_to_logical = {}
self.logical_to_physical = {}
self.logical_to_asic = {}
self.data = {'valid':0, 'last':0}
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
self.PORT_START = 256
self.PORT_END = 0
for port_cfg in self._port_cfgs:
if int(port_cfg.index) <= self.PORT_START:
self.PORT_START = int(port_cfg.index)
elif int(port_cfg.index) >= self.PORT_END:
self.PORT_END = int(port_cfg.index)
self.eeprom_mapping = {}
self.presence = {}
for port_cfg in self._port_cfgs:
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if sfp_idx > 0:
self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx)
self.logical.append(port_cfg.name)
else:
self.eeprom_mapping[int(port_cfg.index)] = None
self.presence[int(port_cfg.index)] = False
SfpUtilBase.__init__(self)
@property @property
def port_start(self): def port_start(self):
return self.PORT_START return self.PORT_START
@ -33,11 +122,20 @@ class SfpUtil(SfpUtilBase):
@property @property
def sfp_base(self): def sfp_base(self):
return self.SFP_BASE return self.PORT_START
@property @property
def qsfp_ports(self): def qsfp_ports(self):
return list(range(25, self.PORTS_IN_BLOCK + 1)) start = 256
end = 0
for port_cfg in self._port_cfgs:
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if sfp_idx == 25 or sfp_idx == 26:
if int(port_cfg.index) <= start:
start = int(port_cfg.index)
elif int(port_cfg.index) >= end:
end = int(port_cfg.index)
return range(start, end + 1)
@property @property
def port_to_eeprom_mapping(self): def port_to_eeprom_mapping(self):
@ -46,93 +144,32 @@ class SfpUtil(SfpUtilBase):
def is_logical_port(self, port_name): def is_logical_port(self, port_name):
return True return True
def get_eeprom_data(self, port):
ret = None
port_num = self.get_logical_to_physical(port)[0]
if port_num < self.port_start or port_num > self.port_end:
return ret
if port_num < self.sfp_base:
return ret
try:
with open(self.eeprom_mapping[port_num], 'r') as eeprom_file:
ret = eeprom_file.read()
except IOError as e:
DBG_PRINT(str(e))
return ret
# todo
# def _get_port_eeprom_path(self, port_num, devid):
# pass
def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.PORT_START = 1
self.PORT_END = 26
self.SFP_BASE = 1
self.PORTS_IN_BLOCK = 26
self.logical = []
self.physical_to_logical = {}
self.logical_to_physical = {}
self.eeprom_mapping = {}
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
for x in range(self.port_start, self.sfp_base):
self.eeprom_mapping[x] = None
for x in range(self.sfp_base, self.port_end + 1):
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(
x - self.sfp_base + 1)
self.presence = {}
for x in range(self.sfp_base, self.port_end + 1):
self.presence[x] = False
SfpUtilBase.__init__(self)
for x in range(self.sfp_base, self.port_end + 1):
self.logical.append('Ethernet' + str(x))
def get_presence(self, port_num): def get_presence(self, port_num):
# Check for invalid port_num for port_cfg in self._port_cfgs:
if port_num < self.port_start or port_num > self.port_end: if int(port_cfg.index) == port_num:
return False sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if port_num < self.sfp_base: if sfp_idx >= 0:
return False try:
try: with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file:
with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file: return 1 == int(sfp_file.read())
return 1 == int(sfp_file.read()) except IOError as e:
except IOError as e: DBG_PRINT(str(e))
DBG_PRINT(str(e))
return False return False
def get_low_power_mode(self, port_num): 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
return False return False
def set_low_power_mode(self, port_num, lpmode): 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
return False return False
def reset(self, port_num): def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
return False return False
def read_porttab_mappings(self, porttabfile): def read_porttab_mappings(self, porttabfile, asic_inst = 0):
for x in range(self.sfp_base, self.port_end + 1): for port_cfg in self._port_cfgs:
self.logical_to_physical['Ethernet' + str(x)] = [x] self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)]
self.physical_to_logical[x] = ['Ethernet' + str(x)] self.logical_to_asic[port_cfg.name] = 0
self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name]
data = {'valid': 0, 'last': 0}
def get_transceiver_change_event(self, timeout=2000): def get_transceiver_change_event(self, timeout=2000):
now = time.time() now = time.time()
@ -140,19 +177,19 @@ class SfpUtil(SfpUtilBase):
if timeout < 1000: if timeout < 1000:
timeout = 1000 timeout = 1000
timeout = (timeout) / float(1000) # Convert to secs timeout = (timeout) / float(1000) # Convert to secs
if now < (self.data['last'] + timeout) and self.data['valid']: if now < (self.data['last'] + timeout) and self.data['valid']:
return True, {} return True, {}
for x in range(self.sfp_base, self.port_end + 1): for port_cfg in self._port_cfgs:
presence = self.get_presence(x) presence = self.get_presence(int(port_cfg.index))
if presence != self.presence[x]: if presence != self.presence[int(port_cfg.index)]:
self.presence[x] = presence self.presence[int(port_cfg.index)] = presence
if presence: if presence:
port_dict[x] = SFP_STATUS_INSERTED port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED
else: else:
port_dict[x] = SFP_STATUS_REMOVED port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED
if bool(port_dict): if bool(port_dict):
self.data['last'] = now self.data['last'] = now

View File

@ -0,0 +1,3 @@
{
}

View File

@ -0,0 +1,70 @@
{# Default values which will be used if no actual configura available #}
{% set default_cable = '40m' %}
{% set default_ports_num = 54 -%}
{# Port configuration to cable length look-up table #}
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
{# Roles described in the minigraph #}
{% set ports2cable = {
'torrouter_server' : '5m',
'leafrouter_torrouter' : '40m',
'spinerouter_leafrouter' : '300m'
}
%}
{%- macro cable_length(port_name) -%}
{%- set cable_len = [] -%}
{%- for local_port in DEVICE_NEIGHBOR -%}
{%- if local_port == port_name -%}
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor_role = neighbor.type -%}
{%- set roles1 = switch_role + '_' + neighbor_role %}
{%- set roles2 = neighbor_role + '_' + switch_role -%}
{%- set roles1 = roles1 | lower -%}
{%- set roles2 = roles2 | lower -%}
{%- if roles1 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
{%- elif roles2 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- if cable_len -%}
{{ cable_len.0 }}
{%- else -%}
{{ default_cable }}
{%- endif -%}
{% endmacro %}
{%- if DEVICE_METADATA is defined %}
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
{%- endif -%}
{# Generate list of ports if not defined #}
{% if PORT is not defined %}
{% set PORT = [] %}
{% for port_idx in range(1,default_ports_num+1) %}
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
{% endfor %}
{% endif -%}
{% set port_names_list = [] %}
{% for port in PORT %}
{%- if port_names_list.append(port) %}{% endif %}
{% endfor %}
{% set port_names = port_names_list | join(',') -%}
{
"CABLE_LENGTH": {
"AZURE": {
{% for port in PORT %}
{% set cable = cable_length(port) -%}
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
{% endfor %}
}
}
}

View File

@ -0,0 +1,21 @@
# PG lossless profiles.
# speed cable size xon xoff threshold
1000 5m 34816 18432 16384 0
10000 5m 34816 18432 16384 0
25000 5m 34816 18432 16384 0
40000 5m 34816 18432 16384 0
50000 5m 34816 18432 16384 0
100000 5m 36864 18432 18432 0
1000 40m 36864 18432 18432 0
10000 40m 36864 18432 18432 0
25000 40m 39936 18432 21504 0
40000 40m 41984 18432 23552 0
50000 40m 41984 18432 23552 0
100000 40m 54272 18432 35840 0
1000 300m 49152 18432 30720 0
10000 300m 49152 18432 30720 0
25000 300m 71680 18432 53248 0
40000 300m 94208 18432 75776 0
50000 300m 94208 18432 75776 0
100000 300m 184320 18432 165888 0

View File

@ -0,0 +1,27 @@
# name lanes alias index speed fec
Ethernet0 0 eth-0-1 0 10000 none
Ethernet1 1 eth-0-2 1 10000 none
Ethernet2 2 eth-0-3 2 10000 none
Ethernet3 3 eth-0-4 3 10000 none
Ethernet4 8 eth-0-5 4 10000 none
Ethernet5 9 eth-0-6 5 10000 none
Ethernet6 10 eth-0-7 6 10000 none
Ethernet7 11 eth-0-8 7 10000 none
Ethernet8 20 eth-0-9 8 10000 none
Ethernet9 21 eth-0-10 9 10000 none
Ethernet10 22 eth-0-11 10 10000 none
Ethernet11 23 eth-0-12 11 10000 none
Ethernet12 12 eth-0-13 12 10000 none
Ethernet13 13 eth-0-14 13 10000 none
Ethernet14 14 eth-0-15 14 10000 none
Ethernet15 15 eth-0-16 15 10000 none
Ethernet16 24 eth-0-17 16 10000 none
Ethernet17 25 eth-0-18 17 10000 none
Ethernet18 26 eth-0-19 18 10000 none
Ethernet19 27 eth-0-20 19 10000 none
Ethernet20 28 eth-0-21 20 10000 none
Ethernet21 29 eth-0-22 21 10000 none
Ethernet22 30 eth-0-23 22 10000 none
Ethernet23 31 eth-0-24 23 10000 none
Ethernet24 61,60,63,62 eth-0-25 24 40000 none
Ethernet25 45,44,47,46 eth-0-26 25 40000 none

View File

@ -0,0 +1 @@
{%- include 'qos_config.j2' %}

View File

@ -0,0 +1,2 @@
SAI_INIT_CONFIG_FILE=/etc/centec/E530-24x2q-chip-profile.txt
SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-24x2q-datapath-cfg.txt

View File

@ -0,0 +1 @@
E530-24x2q l2

View File

@ -0,0 +1,12 @@
# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
DEVNAME=hwmon1=ctc5236fan
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18

View File

@ -0,0 +1,8 @@
{
"chassis": {
"E530-24x2q": {
"component": {
}
}
}
}

View File

@ -0,0 +1,11 @@
#!/usr/bin/python
import os
def main():
# reboot the system
os.system('echo 502 > /sys/class/gpio/export')
os.system('echo out > /sys/class/gpio/gpio502/direction')
os.system('echo 1 > /sys/class/gpio/gpio502/value')
if __name__ == "__main__":
main()

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
#############################################################################
# Centec E550-24X8Y2C
#
# Platform and model specific eeprom subclass, inherits from the base class,
# and provides the followings:
# - the eeprom format definition
# - specific encoder/decoder if there is special need
#############################################################################
try:
from sonic_eeprom import eeprom_tlvinfo
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/dev/mtd3"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,165 @@
#!/usr/bin/env python
#
# led_control.py
#
# Platform-specific LED control functionality for SONiC
#
try:
import os
import re
import syslog
import collections
from sonic_led.led_control_base import LedControlBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError(str(e) + " - required module not found")
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
def DBG_PRINT(str):
syslog.openlog("centec-led")
syslog.syslog(syslog.LOG_INFO, str)
syslog.closelog()
class LedControl(LedControlBase):
"""Platform specific LED control class"""
# Constructor
def __init__(self):
self.mac_to_led = {
0: 1,
1: 2,
2: 3,
3: 4,
8: 5,
9: 6,
10: 7,
11: 8,
20: 9,
21:10,
22:11,
23:12,
12:13,
13:14,
14:15,
15:16,
24:17,
25:18,
26:19,
27:20,
28:21,
29:22,
30:23,
31:24,
61:-1,
60:25,
63:-1,
62:-1,
45:-1,
44:26,
47:-1,
46:-1,
}
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
self.LED_MODE_UP = [11, 11]
self.LED_MODE_DOWN = [7, 7]
self.f_led = "/sys/class/leds/{}/brightness"
self._initDefaultConfig()
# Helper method to map SONiC port name to index
def _port_name_to_index(self, port_name):
for port_cfg in self._port_cfgs:
if port_name == port_cfg.name:
macs = [int(x) for x in (port_cfg.lanes.split(','))]
led = self.mac_to_led[min(macs)]
if led < 0:
return None
return led
return None
def _port_state_to_mode(self, port_idx, state):
if state == "up":
return self.LED_MODE_UP[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_UP[0]
else:
return self.LED_MODE_DOWN[1] if port_idx == 25 or port_idx == 26 else self.LED_MODE_DOWN[0]
def _port_led_mode_update(self, port_idx, ledMode):
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
led_file.write(str(ledMode))
def _initSystemLed(self):
try:
with open(self.f_led.format("system"), 'w') as led_file:
led_file.write("1")
DBG_PRINT("init system led to normal")
with open(self.f_led.format("idn"), 'w') as led_file:
led_file.write("1")
DBG_PRINT("init idn led to off")
except IOError as e:
DBG_PRINT(str(e))
def _initPanelLed(self):
with open(self.f_led.format("port1"), 'r') as led_file:
shouldInit = (int(led_file.read()) == 0)
if shouldInit == True:
for port_cfg in self._port_cfgs:
macs = [int(x) for x in (port_cfg.lanes.split(','))]
led = self.mac_to_led[min(macs)]
if led < 0:
continue
defmode = self._port_state_to_mode(led, "down")
with open(self.f_led.format("port{}".format(led)), 'w') as led_file:
led_file.write(str(defmode))
DBG_PRINT("init port{} led to mode={}".format(led, defmode))
def _initDefaultConfig(self):
DBG_PRINT("start init led")
self._initSystemLed()
self._initPanelLed()
DBG_PRINT("init led done")
# Concrete implementation of port_link_state_change() method
def port_link_state_change(self, portname, state):
port_idx = self._port_name_to_index(portname)
if port_idx is None:
return
ledMode = self._port_state_to_mode(port_idx, state)
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
saveMode = int(led_file.read())
if ledMode == saveMode:
return
self._port_led_mode_update(port_idx, ledMode)
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python
#############################################################################
# Centec
#
# Module contains an implementation of SONiC PSU Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
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/class/psu/psu{}/"
self.psu_presence = "psu_presence"
self.psu_oper_status = "psu_status"
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
return 2
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by 1-based index <index>
:param index: An integer, 1-based index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
"""
if index is None:
return False
status = 0
try:
with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status:
status = int(power_status.read())
except IOError:
return False
return status == 1
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by 1-based index <index>
:param index: An integer, 1-based index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
if index is None:
return False
status = 0
try:
with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status:
status = int(presence_status.read())
except IOError:
return False
return status == 1

View File

@ -0,0 +1,200 @@
#!/usr/bin/env python
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import os
import re
import time
import collections
from sonic_sfp.sfputilbase import SfpUtilBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
SFP_STATUS_INSERTED = '1'
SFP_STATUS_REMOVED = '0'
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
def __init__(self):
self.mac_to_sfp = {
0: 1,
1: 2,
2: 3,
3: 4,
8: 5,
9: 6,
10: 7,
11: 8,
20: 9,
21:10,
22:11,
23:12,
12:13,
13:14,
14:15,
15:16,
24:17,
25:18,
26:19,
27:20,
28:21,
29:22,
30:23,
31:24,
61:25,
60:25,
63:25,
62:25,
45:26,
44:26,
47:26,
46:26,
}
self.logical = []
self.physical_to_logical = {}
self.logical_to_physical = {}
self.logical_to_asic = {}
self.data = {'valid':0, 'last':0}
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
self._port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
self.PORT_START = 256
self.PORT_END = 0
for port_cfg in self._port_cfgs:
if int(port_cfg.index) <= self.PORT_START:
self.PORT_START = int(port_cfg.index)
elif int(port_cfg.index) >= self.PORT_END:
self.PORT_END = int(port_cfg.index)
self.eeprom_mapping = {}
self.presence = {}
for port_cfg in self._port_cfgs:
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if sfp_idx > 0:
self.eeprom_mapping[int(port_cfg.index)] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(sfp_idx)
self.logical.append(port_cfg.name)
else:
self.eeprom_mapping[int(port_cfg.index)] = None
self.presence[int(port_cfg.index)] = False
SfpUtilBase.__init__(self)
@property
def port_start(self):
return self.PORT_START
@property
def port_end(self):
return self.PORT_END
@property
def sfp_base(self):
return self.PORT_START
@property
def qsfp_ports(self):
start = 256
end = 0
for port_cfg in self._port_cfgs:
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if sfp_idx == 25 or sfp_idx == 26:
if int(port_cfg.index) <= start:
start = int(port_cfg.index)
elif int(port_cfg.index) >= end:
end = int(port_cfg.index)
return range(start, end + 1)
@property
def port_to_eeprom_mapping(self):
return self.eeprom_mapping
def is_logical_port(self, port_name):
return True
def get_presence(self, port_num):
for port_cfg in self._port_cfgs:
if int(port_cfg.index) == port_num:
sfp_idx = self.mac_to_sfp[int(port_cfg.lanes.split(',')[0])]
if sfp_idx >= 0:
try:
with open(self.f_sfp_present.format(sfp_idx), 'r') as sfp_file:
return 1 == int(sfp_file.read())
except IOError as e:
DBG_PRINT(str(e))
return False
def get_low_power_mode(self, port_num):
return False
def set_low_power_mode(self, port_num, lpmode):
return False
def reset(self, port_num):
return False
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
for port_cfg in self._port_cfgs:
self.logical_to_physical[port_cfg.name] = [int(port_cfg.index)]
self.logical_to_asic[port_cfg.name] = 0
self.physical_to_logical[int(port_cfg.index)] = [port_cfg.name]
def get_transceiver_change_event(self, timeout=2000):
now = time.time()
port_dict = {}
if timeout < 1000:
timeout = 1000
timeout = (timeout) / float(1000) # Convert to secs
if now < (self.data['last'] + timeout) and self.data['valid']:
return True, {}
for port_cfg in self._port_cfgs:
presence = self.get_presence(int(port_cfg.index))
if presence != self.presence[int(port_cfg.index)]:
self.presence[int(port_cfg.index)] = presence
if presence:
port_dict[int(port_cfg.index)] = SFP_STATUS_INSERTED
else:
port_dict[int(port_cfg.index)] = SFP_STATUS_REMOVED
if bool(port_dict):
self.data['last'] = now
self.data['valid'] = 1
return True, port_dict
else:
time.sleep(0.5)
return True, {}

View File

@ -0,0 +1,3 @@
{
}

View File

@ -0,0 +1,70 @@
{# Default values which will be used if no actual configura available #}
{% set default_cable = '40m' %}
{% set default_ports_num = 54 -%}
{# Port configuration to cable length look-up table #}
{# Each record describes mapping of DUT (DUT port) role and neighbor role to cable length #}
{# Roles described in the minigraph #}
{% set ports2cable = {
'torrouter_server' : '5m',
'leafrouter_torrouter' : '40m',
'spinerouter_leafrouter' : '300m'
}
%}
{%- macro cable_length(port_name) -%}
{%- set cable_len = [] -%}
{%- for local_port in DEVICE_NEIGHBOR -%}
{%- if local_port == port_name -%}
{%- if DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor = DEVICE_NEIGHBOR_METADATA[DEVICE_NEIGHBOR[local_port].name] -%}
{%- set neighbor_role = neighbor.type -%}
{%- set roles1 = switch_role + '_' + neighbor_role %}
{%- set roles2 = neighbor_role + '_' + switch_role -%}
{%- set roles1 = roles1 | lower -%}
{%- set roles2 = roles2 | lower -%}
{%- if roles1 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles1]) -%}{%- endif -%}
{%- elif roles2 in ports2cable -%}
{%- if cable_len.append(ports2cable[roles2]) -%}{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- if cable_len -%}
{{ cable_len.0 }}
{%- else -%}
{{ default_cable }}
{%- endif -%}
{% endmacro %}
{%- if DEVICE_METADATA is defined %}
{%- set switch_role = DEVICE_METADATA['localhost']['type'] %}
{%- endif -%}
{# Generate list of ports if not defined #}
{% if PORT is not defined %}
{% set PORT = [] %}
{% for port_idx in range(1,default_ports_num+1) %}
{% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %}
{% endfor %}
{% endif -%}
{% set port_names_list = [] %}
{% for port in PORT %}
{%- if port_names_list.append(port) %}{% endif %}
{% endfor %}
{% set port_names = port_names_list | join(',') -%}
{
"CABLE_LENGTH": {
"AZURE": {
{% for port in PORT %}
{% set cable = cable_length(port) -%}
"{{ port }}": "{{ cable }}"{%- if not loop.last -%},{% endif %}
{% endfor %}
}
}
}

View File

@ -0,0 +1,21 @@
# PG lossless profiles.
# speed cable size xon xoff threshold
1000 5m 34816 18432 16384 0
10000 5m 34816 18432 16384 0
25000 5m 34816 18432 16384 0
40000 5m 34816 18432 16384 0
50000 5m 34816 18432 16384 0
100000 5m 36864 18432 18432 0
1000 40m 36864 18432 18432 0
10000 40m 36864 18432 18432 0
25000 40m 39936 18432 21504 0
40000 40m 41984 18432 23552 0
50000 40m 41984 18432 23552 0
100000 40m 54272 18432 35840 0
1000 300m 49152 18432 30720 0
10000 300m 49152 18432 30720 0
25000 300m 71680 18432 53248 0
40000 300m 94208 18432 75776 0
50000 300m 94208 18432 75776 0
100000 300m 184320 18432 165888 0

View File

@ -0,0 +1,53 @@
# name lanes alias index speed fec
Ethernet0 0 eth-0-1 0 1000 none
Ethernet1 1 eth-0-2 1 1000 none
Ethernet2 2 eth-0-3 2 1000 none
Ethernet3 3 eth-0-4 3 1000 none
Ethernet4 4 eth-0-5 4 1000 none
Ethernet5 5 eth-0-6 5 1000 none
Ethernet6 6 eth-0-7 6 1000 none
Ethernet7 7 eth-0-8 7 1000 none
Ethernet8 16 eth-0-9 8 1000 none
Ethernet9 17 eth-0-10 9 1000 none
Ethernet10 18 eth-0-11 10 1000 none
Ethernet11 19 eth-0-12 11 1000 none
Ethernet12 20 eth-0-13 12 1000 none
Ethernet13 21 eth-0-14 13 1000 none
Ethernet14 22 eth-0-15 14 1000 none
Ethernet15 23 eth-0-16 15 1000 none
Ethernet16 8 eth-0-17 16 1000 none
Ethernet17 9 eth-0-18 17 1000 none
Ethernet18 10 eth-0-19 18 1000 none
Ethernet19 11 eth-0-20 19 1000 none
Ethernet20 32 eth-0-21 20 1000 none
Ethernet21 33 eth-0-22 21 1000 none
Ethernet22 34 eth-0-23 22 1000 none
Ethernet23 35 eth-0-24 23 1000 none
Ethernet24 36 eth-0-25 24 1000 none
Ethernet25 37 eth-0-26 25 1000 none
Ethernet26 38 eth-0-27 26 1000 none
Ethernet27 39 eth-0-28 27 1000 none
Ethernet28 40 eth-0-29 28 1000 none
Ethernet29 41 eth-0-30 29 1000 none
Ethernet30 42 eth-0-31 30 1000 none
Ethernet31 43 eth-0-32 31 1000 none
Ethernet32 25 eth-0-33 32 1000 none
Ethernet33 24 eth-0-34 33 1000 none
Ethernet34 27 eth-0-35 34 1000 none
Ethernet35 26 eth-0-36 35 1000 none
Ethernet36 13 eth-0-37 36 1000 none
Ethernet37 12 eth-0-38 37 1000 none
Ethernet38 15 eth-0-39 38 1000 none
Ethernet39 14 eth-0-40 39 1000 none
Ethernet40 29 eth-0-41 40 1000 none
Ethernet41 28 eth-0-42 41 1000 none
Ethernet42 31 eth-0-43 42 1000 none
Ethernet43 30 eth-0-44 43 1000 none
Ethernet44 61 eth-0-45 44 1000 none
Ethernet45 60 eth-0-46 45 1000 none
Ethernet46 63 eth-0-47 46 1000 none
Ethernet47 62 eth-0-48 47 1000 none
Ethernet48 44 eth-0-49 48 10000 none
Ethernet49 45 eth-0-50 49 10000 none
Ethernet50 47 eth-0-51 50 10000 none
Ethernet51 46 eth-0-52 51 10000 none

View File

@ -0,0 +1 @@
{%- include 'qos_config.j2' %}

View File

@ -0,0 +1,2 @@
SAI_INIT_CONFIG_FILE=/etc/centec/E530-48s4x-chip-profile.txt
SAI_HW_PORT_PROFILE_ID_CONFIG_FILE=/etc/centec/E530-48s4x-datapath.txt

View File

@ -0,0 +1 @@
E530-48s4x l2

View File

@ -0,0 +1,12 @@
# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
DEVNAME=hwmon1=ctc5236fan
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input hwmon1/pwm4=hwmon1/temp1_input
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input hwmon1/pwm4=hwmon1/fan4_input
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30 hwmon1/pwm4=30
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90 hwmon1/pwm4=90
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12 hwmon1/pwm4=12
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6 hwmon1/pwm4=6
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18 hwmon1/pwm4=18

View File

@ -0,0 +1,8 @@
{
"chassis": {
"E530-48s4x": {
"component": {
}
}
}
}

View File

@ -0,0 +1,12 @@
#!/usr/bin/python
import os
def main():
# reboot the system
os.system('modprobe i2c-dev')
os.system('i2cset -y 0 0x36 0x23 0x0')
os.system('sleep 1')
os.system('i2cset -y 0 0x36 0x23 0x3')
if __name__ == "__main__":
main()

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
#############################################################################
# Centec E530-48S4X
#
# Platform and model specific eeprom subclass, inherits from the base class,
# and provides the followings:
# - the eeprom format definition
# - specific encoder/decoder if there is special need
#############################################################################
try:
from sonic_eeprom import eeprom_tlvinfo
except ImportError as e:
raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self, name, path, cpld_root, ro):
self.eeprom_path = "/dev/mtd3"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
#
# led_control.py
#
# Platform-specific LED control functionality for SONiC
#
try:
from sonic_led.led_control_base import LedControlBase
import syslog
from socket import *
from select import *
except ImportError as e:
raise ImportError(str(e) + " - required module not found")
def DBG_PRINT(str):
syslog.openlog("centec-led")
syslog.syslog(syslog.LOG_INFO, str)
syslog.closelog()
class LedControl(LedControlBase):
"""Platform specific LED control class"""
# Helper method to map SONiC port name to index
def _port_name_to_index(self, port_name):
# Strip "Ethernet" off port name
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
return -1
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
return port_idx + 1
def _port_state_to_mode(self, port_idx, state):
if state == "up":
return self.LED_MODE_UP[0] if (port_idx < 49) else self.LED_MODE_UP[1]
else:
return self.LED_MODE_DOWN[0] if (port_idx < 49) else self.LED_MODE_DOWN[1]
def _port_led_mode_update(self, port_idx, ledMode):
with open(self.f_led.format("port{}".format(port_idx)), 'w') as led_file:
led_file.write(str(ledMode))
def _initSystemLed(self):
try:
with open(self.f_led.format("system"), 'w') as led_file:
led_file.write("3")
DBG_PRINT("init system led to normal")
with open(self.f_led.format("idn"), 'w') as led_file:
led_file.write("1")
DBG_PRINT("init idn led to off")
except IOError as e:
DBG_PRINT(str(e))
def _initPanelLed(self):
with open(self.f_led.format("port1"), 'r') as led_file:
shouldInit = (int(led_file.read()) == 0)
if shouldInit == True:
for idx in range(1, 53):
defmode = self._port_state_to_mode(idx, "down")
with open(self.f_led.format("port{}".format(idx)), 'w') as led_file:
led_file.write(str(defmode))
DBG_PRINT("init port{} led to mode={}".format(idx, defmode))
def _initDefaultConfig(self):
DBG_PRINT("start init led")
self._initSystemLed()
self._initPanelLed()
DBG_PRINT("init led done")
# Concrete implementation of port_link_state_change() method
def port_link_state_change(self, portname, state):
port_idx = self._port_name_to_index(portname)
ledMode = self._port_state_to_mode(port_idx, state)
with open(self.f_led.format("port{}".format(port_idx)), 'r') as led_file:
saveMode = int(led_file.read())
if ledMode == saveMode:
return
self._port_led_mode_update(port_idx, ledMode)
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
# Constructor
def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.LED_MODE_UP = [5, 6]
self.LED_MODE_DOWN = [7, 7]
self.f_led = "/sys/class/leds/{}/brightness"
self._initDefaultConfig()

View File

@ -0,0 +1,72 @@
#!/usr/bin/env python
#############################################################################
# Centec
#
# Module contains an implementation of SONiC PSU Base API and
# provides the PSUs status which are available in the platform
#
#############################################################################
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/class/psu/psu{}/"
self.psu_presence = "psu_presence"
self.psu_oper_status = "psu_status"
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
return 2
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by 1-based index <index>
:param index: An integer, 1-based index of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is faulty
"""
if index is None:
return False
status = 0
try:
with open(self.psu_path.format(index) + self.psu_oper_status, 'r') as power_status:
status = int(power_status.read())
except IOError:
return False
return status == 1
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by 1-based index <index>
:param index: An integer, 1-based index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
if index is None:
return False
status = 0
try:
with open(self.psu_path.format(index) + self.psu_presence, 'r') as presence_status:
status = int(presence_status.read())
except IOError:
return False
return status == 1

View File

@ -0,0 +1,161 @@
#!/usr/bin/env python
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import time
from socket import *
from select import *
from sonic_sfp.sfputilbase import SfpUtilBase
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
def DBG_PRINT(str):
print(str + "\n")
SFP_STATUS_INSERTED = '1'
SFP_STATUS_REMOVED = '0'
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
@property
def port_start(self):
return self.PORT_START
@property
def port_end(self):
return self.PORT_END
@property
def sfp_base(self):
return self.SFP_BASE
@property
def qsfp_ports(self):
return ()
@property
def port_to_eeprom_mapping(self):
return self.eeprom_mapping
def is_logical_port(self, port_name):
return True
def get_eeprom_data(self, port):
ret = None
port_num = self.get_logical_to_physical(port)[0] + 1
if port_num < self.port_start or port_num > self.port_end:
return ret
if port_num < self.sfp_base:
return ret
try:
with open(self.eeprom_mapping[port_num], 'r') as eeprom_file:
ret = eeprom_file.read()
except IOError as e:
DBG_PRINT(str(e))
return ret
def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.PORT_START = 0
self.PORT_END = 51
self.SFP_BASE = 0
self.PORTS_IN_BLOCK = 52
self.logical = []
self.physical_to_logical = {}
self.logical_to_physical = {}
self.logical_to_asic = {}
self.data = {'valid':0, 'last':0}
self.eeprom_mapping = {}
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
self.f_sfp_enable = "/sys/class/sfp/sfp{}/sfp_enable"
for x in range(self.port_start, self.sfp_base):
self.eeprom_mapping[x] = None
for x in range(self.sfp_base, self.port_end + 1):
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1)
self.presence = {}
for x in range(self.sfp_base, self.port_end + 1):
self.presence[x] = False;
SfpUtilBase.__init__(self)
for x in range(self.sfp_base, self.port_end + 1):
self.logical.append('Ethernet' + str(x))
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 < self.sfp_base:
return False
try:
with open(self.f_sfp_present.format(port_num - self.sfp_base + 1), 'r') as sfp_file:
return 1 == int(sfp_file.read())
except IOError as e:
DBG_PRINT(str(e))
return False
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
return False
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
return False
def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
return False
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
for x in range(self.sfp_base, self.port_end + 1):
self.logical_to_physical['Ethernet' + str(x)] = [x]
self.logical_to_asic['Ethernet' + str(x)] = 0
self.physical_to_logical[x] = ['Ethernet' + str(x)]
def get_transceiver_change_event(self, timeout=2000):
now = time.time()
port_dict = {}
if timeout < 1000:
timeout = 1000
timeout = (timeout) / float(1000) # Convert to secs
if now < (self.data['last'] + timeout) and self.data['valid']:
return True, {}
for x in range(self.sfp_base, self.port_end + 1):
presence = self.get_presence(x)
if presence != self.presence[x]:
self.presence[x] = presence
# index in port_config.ini
if presence:
port_dict[x] = SFP_STATUS_INSERTED
else:
port_dict[x] = SFP_STATUS_REMOVED
if bool(port_dict):
self.data['last'] = now
self.data['valid'] = 1
return True, port_dict
else:
time.sleep(0.5)
return True, {}

View File

@ -0,0 +1,3 @@
{
}

View File

@ -1,53 +1,53 @@
# name lanes alias speed # name lanes alias index speed fec
Ethernet1 1 eth-0-1 1000 Ethernet0 1 eth-0-1 0 1000 none
Ethernet2 0 eth-0-2 1000 Ethernet1 0 eth-0-2 1 1000 none
Ethernet3 3 eth-0-3 1000 Ethernet2 3 eth-0-3 2 1000 none
Ethernet4 2 eth-0-4 1000 Ethernet3 2 eth-0-4 3 1000 none
Ethernet5 5 eth-0-5 1000 Ethernet4 5 eth-0-5 4 1000 none
Ethernet6 4 eth-0-6 1000 Ethernet5 4 eth-0-6 5 1000 none
Ethernet7 7 eth-0-7 1000 Ethernet6 7 eth-0-7 6 1000 none
Ethernet8 6 eth-0-8 1000 Ethernet7 6 eth-0-8 7 1000 none
Ethernet9 17 eth-0-9 1000 Ethernet8 17 eth-0-9 8 1000 none
Ethernet10 16 eth-0-10 1000 Ethernet9 16 eth-0-10 9 1000 none
Ethernet11 19 eth-0-11 1000 Ethernet10 19 eth-0-11 10 1000 none
Ethernet12 18 eth-0-12 1000 Ethernet11 18 eth-0-12 11 1000 none
Ethernet13 21 eth-0-13 1000 Ethernet12 21 eth-0-13 12 1000 none
Ethernet14 20 eth-0-14 1000 Ethernet13 20 eth-0-14 13 1000 none
Ethernet15 23 eth-0-15 1000 Ethernet14 23 eth-0-15 14 1000 none
Ethernet16 22 eth-0-16 1000 Ethernet15 22 eth-0-16 15 1000 none
Ethernet17 9 eth-0-17 1000 Ethernet16 9 eth-0-17 16 1000 none
Ethernet18 8 eth-0-18 1000 Ethernet17 8 eth-0-18 17 1000 none
Ethernet19 11 eth-0-19 1000 Ethernet18 11 eth-0-19 18 1000 none
Ethernet20 10 eth-0-20 1000 Ethernet19 10 eth-0-20 19 1000 none
Ethernet21 33 eth-0-21 1000 Ethernet20 33 eth-0-21 20 1000 none
Ethernet22 32 eth-0-22 1000 Ethernet21 32 eth-0-22 21 1000 none
Ethernet23 35 eth-0-23 1000 Ethernet22 35 eth-0-23 22 1000 none
Ethernet24 34 eth-0-24 1000 Ethernet23 34 eth-0-24 23 1000 none
Ethernet25 37 eth-0-25 1000 Ethernet24 37 eth-0-25 24 1000 none
Ethernet26 36 eth-0-26 1000 Ethernet25 36 eth-0-26 25 1000 none
Ethernet27 39 eth-0-27 1000 Ethernet26 39 eth-0-27 26 1000 none
Ethernet28 38 eth-0-28 1000 Ethernet27 38 eth-0-28 27 1000 none
Ethernet29 41 eth-0-29 1000 Ethernet28 41 eth-0-29 28 1000 none
Ethernet30 40 eth-0-30 1000 Ethernet29 40 eth-0-30 29 1000 none
Ethernet31 43 eth-0-31 1000 Ethernet30 43 eth-0-31 30 1000 none
Ethernet32 42 eth-0-32 1000 Ethernet31 42 eth-0-32 31 1000 none
Ethernet33 25 eth-0-33 1000 Ethernet32 25 eth-0-33 32 1000 none
Ethernet34 24 eth-0-34 1000 Ethernet33 24 eth-0-34 33 1000 none
Ethernet35 27 eth-0-35 1000 Ethernet34 27 eth-0-35 34 1000 none
Ethernet36 26 eth-0-36 1000 Ethernet35 26 eth-0-36 35 1000 none
Ethernet37 49 eth-0-37 1000 Ethernet36 49 eth-0-37 36 1000 none
Ethernet38 48 eth-0-38 1000 Ethernet37 48 eth-0-38 37 1000 none
Ethernet39 51 eth-0-39 1000 Ethernet38 51 eth-0-39 38 1000 none
Ethernet40 50 eth-0-40 1000 Ethernet39 50 eth-0-40 39 1000 none
Ethernet41 53 eth-0-41 1000 Ethernet40 53 eth-0-41 40 1000 none
Ethernet42 52 eth-0-42 1000 Ethernet41 52 eth-0-42 41 1000 none
Ethernet43 55 eth-0-43 1000 Ethernet42 55 eth-0-43 42 1000 none
Ethernet44 54 eth-0-44 1000 Ethernet43 54 eth-0-44 43 1000 none
Ethernet45 57 eth-0-45 1000 Ethernet44 57 eth-0-45 44 1000 none
Ethernet46 56 eth-0-46 1000 Ethernet45 56 eth-0-46 45 1000 none
Ethernet47 59 eth-0-47 1000 Ethernet46 59 eth-0-47 46 1000 none
Ethernet48 58 eth-0-48 1000 Ethernet47 58 eth-0-48 47 1000 none
Ethernet49 13 eth-0-49 10000 Ethernet48 13 eth-0-49 48 10000 none
Ethernet50 12 eth-0-50 10000 Ethernet49 12 eth-0-50 49 10000 none
Ethernet51 15 eth-0-51 10000 Ethernet50 15 eth-0-51 50 10000 none
Ethernet52 14 eth-0-52 10000 Ethernet51 14 eth-0-52 51 10000 none

View File

@ -1 +1,12 @@
# Configuration file generated by pwmconfig, changes will be lost # Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon1=devices/platform/soc/soc:fan-ctc5236
DEVNAME=hwmon1=ctc5236fan
FCTEMPS=hwmon1/pwm1=hwmon1/temp1_input hwmon1/pwm2=hwmon1/temp1_input hwmon1/pwm3=hwmon1/temp1_input
FCFANS=hwmon1/pwm1=hwmon1/fan1_input hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input
MINTEMP=hwmon1/pwm1=30 hwmon1/pwm2=30 hwmon1/pwm3=30
MAXTEMP=hwmon1/pwm1=90 hwmon1/pwm2=90 hwmon1/pwm3=90
MINSTART=hwmon1/pwm1=12 hwmon1/pwm2=12 hwmon1/pwm3=12
MINSTOP=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MINPWM=hwmon1/pwm1=6 hwmon1/pwm2=6 hwmon1/pwm3=6
MAXPWM=hwmon1/pwm1=18 hwmon1/pwm2=18 hwmon1/pwm3=18

View File

@ -0,0 +1,8 @@
{
"chassis": {
"E530-48t4x-p": {
"component": {
}
}
}
}

View File

@ -0,0 +1,11 @@
#!/usr/bin/python
import os
def main():
# reboot the system
os.system('echo 502 > /sys/class/gpio/export')
os.system('echo out > /sys/class/gpio/gpio502/direction')
os.system('echo 1 > /sys/class/gpio/gpio502/value')
if __name__ == "__main__":
main()

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
############################################################################# #############################################################################
# Centec E550-24X8Y2C # Centec E550-24X8Y2C
# #
@ -10,7 +12,7 @@
try: try:
from sonic_eeprom import eeprom_tlvinfo from sonic_eeprom import eeprom_tlvinfo
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError (str(e) + "- required module not found")
class board(eeprom_tlvinfo.TlvInfoDecoder): class board(eeprom_tlvinfo.TlvInfoDecoder):

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
#
# led_control.py # led_control.py
# #
# Platform-specific LED control functionality for SONiC # Platform-specific LED control functionality for SONiC
@ -21,6 +23,7 @@ def DBG_PRINT(str):
class LedControl(LedControlBase): class LedControl(LedControlBase):
"""Platform specific LED control class""" """Platform specific LED control class"""
# Helper method to map SONiC port name to index # Helper method to map SONiC port name to index
def _port_name_to_index(self, port_name): def _port_name_to_index(self, port_name):
# Strip "Ethernet" off port name # Strip "Ethernet" off port name
@ -28,7 +31,7 @@ class LedControl(LedControlBase):
return -1 return -1
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):]) port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
return port_idx return port_idx + 1
def _port_state_to_mode(self, port_idx, state): def _port_state_to_mode(self, port_idx, state):
if state == "up": if state == "up":
@ -70,8 +73,8 @@ class LedControl(LedControlBase):
DBG_PRINT("init led done") DBG_PRINT("init led done")
# Concrete implementation of port_link_state_change() method
# Concrete implementation of port_link_state_change() method
def port_link_state_change(self, portname, state): def port_link_state_change(self, portname, state):
port_idx = self._port_name_to_index(portname) port_idx = self._port_name_to_index(portname)
ledMode = self._port_state_to_mode(port_idx, state) ledMode = self._port_state_to_mode(port_idx, state)
@ -84,8 +87,8 @@ class LedControl(LedControlBase):
self._port_led_mode_update(port_idx, ledMode) self._port_led_mode_update(port_idx, ledMode)
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode)) DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
# Constructor
# Constructor
def __init__(self): def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet" self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.LED_MODE_UP = [2, 11] self.LED_MODE_UP = [2, 11]

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
############################################################################# #############################################################################
# Centec # Centec
# #
@ -9,8 +11,7 @@
try: try:
from sonic_psu.psu_base import PsuBase from sonic_psu.psu_base import PsuBase
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError (str(e) + "- required module not found")
class PsuUtil(PsuBase): class PsuUtil(PsuBase):
"""Platform-specific PSUutil class""" """Platform-specific PSUutil class"""

View File

@ -1,3 +1,5 @@
#!/usr/bin/env python
# sfputil.py # sfputil.py
# #
# Platform-specific SFP transceiver interface for SONiC # Platform-specific SFP transceiver interface for SONiC
@ -15,6 +17,8 @@ except ImportError as e:
def DBG_PRINT(str): def DBG_PRINT(str):
print(str + "\n") print(str + "\n")
SFP_STATUS_INSERTED = '1'
SFP_STATUS_REMOVED = '0'
class SfpUtil(SfpUtilBase): class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class""" """Platform-specific SfpUtil class"""
@ -42,17 +46,9 @@ class SfpUtil(SfpUtilBase):
def is_logical_port(self, port_name): def is_logical_port(self, port_name):
return True return True
def get_logical_to_physical(self, port_name):
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
return None
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
return [port_idx]
def get_eeprom_data(self, port): def get_eeprom_data(self, port):
ret = None ret = None
port_num = self.get_logical_to_physical(port)[0] port_num = self.get_logical_to_physical(port)[0] + 1
if port_num < self.port_start or port_num > self.port_end: if port_num < self.port_start or port_num > self.port_end:
return ret return ret
if port_num < self.sfp_base: if port_num < self.sfp_base:
@ -65,16 +61,17 @@ class SfpUtil(SfpUtilBase):
return ret return ret
# todo
# def _get_port_eeprom_path(self, port_num, devid):
# pass
def __init__(self): def __init__(self):
self.SONIC_PORT_NAME_PREFIX = "Ethernet" self.SONIC_PORT_NAME_PREFIX = "Ethernet"
self.PORT_START = 1 self.PORT_START = 0
self.PORT_END = 52 self.PORT_END = 51
self.SFP_BASE = 49 self.SFP_BASE = 48
self.PORTS_IN_BLOCK = 52 self.PORTS_IN_BLOCK = 52
self.logical = []
self.physical_to_logical = {}
self.logical_to_physical = {}
self.logical_to_asic = {}
self.data = {'valid':0, 'last':0}
self.eeprom_mapping = {} self.eeprom_mapping = {}
self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence" self.f_sfp_present = "/sys/class/sfp/sfp{}/sfp_presence"
@ -82,14 +79,16 @@ class SfpUtil(SfpUtilBase):
for x in range(self.port_start, self.sfp_base): for x in range(self.port_start, self.sfp_base):
self.eeprom_mapping[x] = None self.eeprom_mapping[x] = None
for x in range(self.sfp_base, self.port_end + 1): for x in range(self.sfp_base, self.port_end + 1):
self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format( self.eeprom_mapping[x] = "/sys/class/sfp/sfp{}/sfp_eeprom".format(x - self.sfp_base + 1)
x - self.sfp_base + 1)
self.presence = {} self.presence = {}
for x in range(self.sfp_base, self.port_end + 1): for x in range(self.sfp_base, self.port_end + 1):
self.presence[x] = False self.presence[x] = False;
SfpUtilBase.__init__(self) SfpUtilBase.__init__(self)
for x in range(self.sfp_base, self.port_end + 1):
self.logical.append('Ethernet' + str(x))
def get_presence(self, port_num): def get_presence(self, port_num):
# Check for invalid port_num # Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end: if port_num < self.port_start or port_num > self.port_end:
@ -125,13 +124,38 @@ class SfpUtil(SfpUtilBase):
return False return False
def get_transceiver_change_event(self, timeout=0):
def read_porttab_mappings(self, porttabfile, asic_inst = 0):
for x in range(self.sfp_base, self.port_end + 1):
self.logical_to_physical['Ethernet' + str(x)] = [x]
self.logical_to_asic['Ethernet' + str(x)] = 0
self.physical_to_logical[x] = ['Ethernet' + str(x)]
def get_transceiver_change_event(self, timeout=2000):
now = time.time()
port_dict = {} port_dict = {}
while True:
for x in range(self.sfp_base, self.port_end + 1): if timeout < 1000:
presence = self.get_presence(x) timeout = 1000
if presence != self.presence[x]: timeout = (timeout) / float(1000) # Convert to secs
self.presence[x] = presence
port_dict[x] = presence if now < (self.data['last'] + timeout) and self.data['valid']:
return True, port_dict return True, {}
for x in range(self.sfp_base, self.port_end + 1):
presence = self.get_presence(x)
if presence != self.presence[x]:
self.presence[x] = presence
# index in port_config.ini
if presence:
port_dict[x] = SFP_STATUS_INSERTED
else:
port_dict[x] = SFP_STATUS_REMOVED
if bool(port_dict):
self.data['last'] = now
self.data['valid'] = 1
return True, port_dict
else:
time.sleep(0.5) time.sleep(0.5)
return True, {}

View File

@ -0,0 +1,3 @@
{
}

View File

@ -82,7 +82,7 @@ class SfpUtil(SfpUtilBase):
try: try:
reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode") reg_file = open("/sys/devices/platform/dell-s6000-cpld.0/qsfp_lpmode")
except IOError as e: except IOError as e:
print "Error: unable to open file: %s" % str(e) print("Error: unable to open file: %s" % str(e))
content = reg_file.readline().rstrip() content = reg_file.readline().rstrip()

View File

@ -8,6 +8,8 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
$(SONIC_ONE_IMAGE)_INSTALLS += $(TSINGMA_BSP_MODULE) $(SONIC_ONE_IMAGE)_INSTALLS += $(TSINGMA_BSP_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE) $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2C_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_48S4X_PLATFORM_MODULE)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(CENTEC_E530_24X2Q_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y) ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES) $(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)

View File

@ -1,8 +1,10 @@
# Centec E530-48T4X-P Platform modules # Centec E530-48T4X-P Platform modules
CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.1 CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION =1.3
CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.1 CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION =1.3
CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION =1.3
CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION =1.3
export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION export CENTEC_E530_48T4X_P_PLATFORM_MODULE_VERSION
@ -16,3 +18,11 @@ SONIC_DPKG_DEBS += $(CENTEC_E530_48T4X_P_PLATFORM_MODULE)
CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb CENTEC_E530_24X2C_PLATFORM_MODULE = platform-modules-e530-24x2c_$(CENTEC_E530_24X2C_PLATFORM_MODULE_VERSION)_arm64.deb
$(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0 $(CENTEC_E530_24X2C_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2c-r0
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE))) $(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2C_PLATFORM_MODULE)))
CENTEC_E530_48S4X_PLATFORM_MODULE = platform-modules-e530-48s4x_$(CENTEC_E530_48S4X_PLATFORM_MODULE_VERSION)_arm64.deb
$(CENTEC_E530_48S4X_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_48s4x-r0
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_48S4X_PLATFORM_MODULE)))
CENTEC_E530_24X2Q_PLATFORM_MODULE = platform-modules-e530-24x2q_$(CENTEC_E530_24X2Q_PLATFORM_MODULE_VERSION)_arm64.deb
$(CENTEC_E530_24X2Q_PLATFORM_MODULE)_PLATFORM = arm64-centec_e530_24x2q-r0
$(eval $(call add_extra_package,$(CENTEC_E530_48T4X_P_PLATFORM_MODULE),$(CENTEC_E530_24X2Q_PLATFORM_MODULE)))

View File

@ -4,43 +4,45 @@
echo "Preparing for installation ... " echo "Preparing for installation ... "
demo_mnt=/mnt
hw_load() {
echo "ext4load mmc 0:2 \$loadaddr onie_uimage"
}
create_partition() { create_partition() {
echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1 echo y | mkfs.ext4 -L CTC-SYSTEM /dev/mmcblk0p1
} }
mount_partition() { mount_partition() {
echo "mount flash" echo "mount flash partition"
demo_mnt=/mnt
mount -t ext4 /dev/mmcblk0p1 $demo_mnt mount -t ext4 /dev/mmcblk0p1 $demo_mnt
} }
bootloader_menu_config() { bootloader_menu_config() {
mkdir -p $demo_mnt/boot if [ "$install_env" = "onie" ]; then
mount -t ext4 /dev/mmcblk0p2 $demo_mnt/boot fw_setenv -f nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next"
rm $demo_mnt/boot/centec-e530.itb -rf fw_setenv -f sonic_image_1 "ext4load mmc 0:1 \$loadaddr \$sonic_dir_1/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_1/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr"
cp $demo_mnt/$image_dir/boot/sonic_arm64.fit $demo_mnt/boot/centec-e530.itb fw_setenv -f sonic_image_2 "NONE"
cd $demo_mnt/boot fw_setenv -f sonic_dir_1 $image_dir
rm onie_uimage -rf fw_setenv -f sonic_dir_2 "NONE"
ln -s centec-e530.itb onie_uimage fw_setenv -f sonic_version_1 `echo $image_dir | sed "s/^image-/SONiC-OS-/g"`
cd - fw_setenv -f sonic_version_2 "NONE"
sync
umount -l $demo_mnt/boot
hw_load_str="$(hw_load)" fw_setenv -f boot_next "run sonic_image_1"
else
running_sonic_revision=`cat /etc/sonic/sonic_version.yml | grep build_version | awk -F \' '{print $2}'`
SONIC_IMAGE_MAX=2
idx=0
for i in $(seq 1 $SONIC_IMAGE_MAX); do
if [ "`fw_printenv sonic_version_$i 2>/dev/null | awk -F = '{print $2}'`" != "SONiC-OS-$running_sonic_revision" ]; then
idx=$i
break
fi
done
(cat <<EOF fw_setenv nos_bootcmd "test -n \$boot_once && setenv do_boot_once \$boot_once && setenv boot_once && saveenv && run do_boot_once; run boot_next"
hw_load $hw_load_str
copy_img echo "Loading Demo $platform image..." && run hw_load
nos_bootcmd run copy_img && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=$image_dir/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr
EOF
) > /tmp/env.txt
fw_setenv -f -s /tmp/env.txt fw_setenv sonic_image_$idx "ext4load mmc 0:1 \$loadaddr \$sonic_dir_$idx/boot/sonic_arm64.fit && setenv bootargs quiet console=\$consoledev,\$baudrate root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 loopfstype=squashfs loop=\$sonic_dir_$idx/fs.squashfs systemd.unified_cgroup_hierarchy=0 && bootm \$loadaddr"
fw_setenv -f image_dir $image_dir fw_setenv sonic_dir_$idx $image_dir
fw_setenv sonic_version_$idx `echo $image_dir | sed "s/^image-/SONiC-OS-/g"`
fw_setenv boot_next "run sonic_image_$idx"
fi
} }

View File

@ -1,6 +1,6 @@
# Centec SAI # Centec SAI
export CENTEC_SAI_VERSION = 1.6.3-1 export CENTEC_SAI_VERSION = 1.7.1-1
export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb export CENTEC_SAI = libsai_$(CENTEC_SAI_VERSION)_$(PLATFORM_ARCH).deb
$(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI) $(CENTEC_SAI)_URL = https://github.com/CentecNetworks/sonic-binaries/raw/master/$(PLATFORM_ARCH)/sai/$(CENTEC_SAI)

View File

@ -5,11 +5,11 @@ from setuptools import setup
os.listdir os.listdir
setup( setup(
name='24x2c', name='sonic_platform',
version='1.1', version='1.0',
description='Module to initialize centec e530-24x2c platforms', description='Module to initialize centec e530-24x2c platforms',
packages=['24x2c'], packages=['sonic_platform'],
package_dir={'24x2c': '24x2c/classes'}, package_dir={'sonic_platform': 'sonic_platform'},
) )

View File

@ -0,0 +1,3 @@
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
from . import platform

View File

@ -0,0 +1,203 @@
#!/usr/bin/env python
#
# Name: chassis.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
import os
import re
import collections
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.eeprom import Eeprom
from .fan_drawer import FanDrawer
from .thermal import Thermal
from .sfp import Sfp
from .psu import Psu
from sonic_py_common import device_info
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 1
NUM_THERMAL = 1
NUM_PSU = 2
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2c", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
_port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
# Initialize EEPROM
self._eeprom = Eeprom()
# Initialize FAN
for i in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(i)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
# Initialize THERMAL
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
# Initialize SFP
for port_cfg in _port_cfgs:
sfp = Sfp(int(port_cfg.index))
self._sfp_list.append(sfp)
# Initialize PSU
for index in range(0, NUM_PSU):
psu = Psu(index + 1)
self._psu_list.append(psu)
##############################################
# Device methods
##############################################
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_number_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
##############################################
# Chassis methods
##############################################
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
"""
return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
return (None, None)
def get_change_event(self, timeout=2000):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
ret_dict = {"sfp": port_dict}
return ret, ret_dict
def get_num_psus(self):
return len(self._psu_list)
def get_psu(self, psu_index):
return self._psu_list[psu_index]

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Name: eeprom.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_eeprom import eeprom_tlvinfo
import binascii
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/dev/mtd3"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.open_eeprom()
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
value = str((tlv[2] << 24) | (tlv[3] << 16) |
(tlv[4] << 8) | tlv[5])
value += str(tlv[6:6 + tlv[1]])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
break
tlv_index += eeprom[tlv_index+1] + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def base_mac_addr(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(TlvInfoDecoder, self).switchaddrstr(e)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict

View File

@ -0,0 +1,186 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_PATH = "/sys/class/hwmon/hwmon1/"
FAN_MAX_PWM = 255
FAN_FAN_PWM = "pwm{}"
FAN_FAN_INPUT = "fan{}_input"
FAN_MAX_RPM = 9000
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
FanBase.__init__(self)
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 Exception:
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
return direction
def get_speed(self):
"""
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
"""
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return int(speed)
def get_target_speed(self):
"""
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
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
# fan_target_sysfs_path = self.__search_file_by_name(
# FAN_PATH, fan_target_sysfs_name)
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
# return target
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return speed
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
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
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
fan_target_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_target_sysfs_name)
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
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: always True
"""
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_index]
return fan_name
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: always True
"""
return True
def get_status(self):
"""
Retrieves the status of the FAN
Returns:
bool: always True
"""
return True

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
########################################################################
# Centec E530 24x2c
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
from .fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CENTEC_FANS_PER_FANTRAY = 3
class FanDrawer(FanDrawerBase):
"""Centec E530 24x2c Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
self.fantrayindex = fantray_index
for i in range(CENTEC_FANS_PER_FANTRAY):
self._fan_list.append(Fan(fantray_index, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
#
# Name: platform.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2C
#
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Psu(PsuBase):
"""Centec Platform-specific PSU class"""
def __init__(self, index):
self._index = index
self._fan_list = []
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
module = imp.load_source("psuutil", module_file)
psu_util_class = getattr(module, "PsuUtil")
self._psuutil = psu_util_class()
def _get_psuutil(self):
return self._psuutil
def get_presence(self):
return self._get_psuutil().get_psu_presence(self._index)
def get_powergood_status(self):
return self._get_psuutil().get_psu_status(self._index)

View File

@ -0,0 +1,102 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.sfp_base import SfpBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Sfp(SfpBase):
"""
Platform-specific sfp class
Unimplemented methods:
- get_model
- get_serial
- get_status
- get_transceiver_info
- get_transceiver_bulk_status
- get_transceiver_threshold_info
- get_reset_status
- get_rx_los
- get_tx_fault
- get_tx_disable_channel
- get_power_override
- get_temperature
- get_voltage
- get_tx_bias
- get_rx_power
- get_tx_power
- tx_disable_channel
- set_power_override
"""
def __init__(self, index):
self._index = index
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
module = imp.load_source("sfputil", module_file)
sfp_util_class = getattr(module, "SfpUtil")
self._sfputil = sfp_util_class()
def get_id(self):
return self._index
def get_name(self):
return "Ethernet{}".format(self._index)
def get_lpmode(self):
return False
def set_lpmode(self, lpmode):
return False
def get_tx_disable(self):
return False
def tx_disable(self, tx_disable):
return False
def reset(self):
pass
def clear_interrupt(self):
return False
def get_interrupt_file(self):
return None
def _get_sfputil(self):
return self._sfputil
def get_presence(self):
return self._get_sfputil().get_presence(self._index)
def get_transceiver_info(self):
return self._get_sfputil().get_transceiver_info_dict(self._index)
def get_transceiver_bulk_status(self):
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
def get_transceiver_threshold_info(self):
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
def get_transceiver_change_event(self, timeout):
return self._get_sfputil().get_transceiver_change_event(timeout)

View File

@ -0,0 +1,118 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
def __init__(self, thermal_index):
self.index = thermal_index
self.high_threshold = float(112)
# Add thermal name
self.THERMAL_NAME_LIST.append("SENSOR-1")
# Set hwmon path
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
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)
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_temp = self.__read_txt_file(temp_file_path)
temp = float(raw_temp)/1000
return float("{:.3f}".format(temp))
def __set_threshold(self, file_name, temperature):
temp_file_path = os.path.join(self.hwmon_path, file_name)
try:
with open(temp_file_path, 'w') as fd:
fd.write(str(temperature))
return True
except IOError:
return False
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_input".format(self.ss_index)
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return self.high_threshold
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
self.high_threshold = float(temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
return os.path.isfile(temp_file_path)
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if not self.get_presence():
return False
return True

View File

@ -0,0 +1 @@
obj-m := centec_e530_24x2q_platform.o

View File

@ -0,0 +1,13 @@
[Unit]
Description=Centec modules init
After=local-fs.target
Before=syncd.service
[Service]
Type=oneshot
ExecStart=-/etc/init.d/platform-modules-e530-24x2q start
ExecStop=-/etc/init.d/platform-modules-e530-24x2q stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
from setuptools import setup
os.listdir
setup(
name='sonic_platform',
version='1.0',
description='Module to initialize centec e530-24x2q platforms',
packages=['sonic_platform'],
package_dir={'sonic_platform': 'sonic_platform'},
)

View File

@ -0,0 +1,3 @@
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
from . import platform

View File

@ -0,0 +1,203 @@
#!/usr/bin/env python
#
# Name: chassis.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
import os
import re
import collections
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.eeprom import Eeprom
from .fan_drawer import FanDrawer
from .thermal import Thermal
from .sfp import Sfp
from .psu import Psu
from sonic_py_common import device_info
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 1
NUM_THERMAL = 1
NUM_PSU = 2
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
raise
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
port_config_file = "/".join([platform_path, "E530-24x2q", "port_config.ini"])
try:
f = open(port_config_file)
except:
raise
for line in f:
line.strip()
if re.search('^#', line) is not None:
Port_cfg = collections.namedtuple('Port_cfg', line.split()[1:])
break
f.close()
f = open(port_config_file)
_port_cfgs = [Port_cfg(*tuple((line.strip().split())))
for line in f if re.search('^#', line) is None]
f.close()
# Initialize EEPROM
self._eeprom = Eeprom()
# Initialize FAN
for i in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(i)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
# Initialize THERMAL
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
# Initialize SFP
for port_cfg in _port_cfgs:
sfp = Sfp(int(port_cfg.index))
self._sfp_list.append(sfp)
# Initialize PSU
for index in range(0, NUM_PSU):
psu = Psu(index + 1)
self._psu_list.append(psu)
##############################################
# Device methods
##############################################
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_number_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
##############################################
# Chassis methods
##############################################
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
"""
return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
return (None, None)
def get_change_event(self, timeout=2000):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
ret_dict = {"sfp": port_dict}
return ret, ret_dict
def get_num_psus(self):
return len(self._psu_list)
def get_psu(self, psu_index):
return self._psu_list[psu_index]

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Name: eeprom.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_eeprom import eeprom_tlvinfo
import binascii
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/dev/mtd3"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.open_eeprom()
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
value = str((tlv[2] << 24) | (tlv[3] << 16) |
(tlv[4] << 8) | tlv[5])
value += str(tlv[6:6 + tlv[1]])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
break
tlv_index += eeprom[tlv_index+1] + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def base_mac_addr(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(TlvInfoDecoder, self).switchaddrstr(e)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict

View File

@ -0,0 +1,186 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_PATH = "/sys/class/hwmon/hwmon1/"
FAN_MAX_PWM = 255
FAN_FAN_PWM = "pwm{}"
FAN_FAN_INPUT = "fan{}_input"
FAN_MAX_RPM = 9000
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
FanBase.__init__(self)
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 Exception:
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
return direction
def get_speed(self):
"""
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
"""
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return int(speed)
def get_target_speed(self):
"""
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
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
# fan_target_sysfs_path = self.__search_file_by_name(
# FAN_PATH, fan_target_sysfs_name)
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
# return target
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return speed
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
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
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
fan_target_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_target_sysfs_name)
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
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: always True
"""
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_index]
return fan_name
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: always True
"""
return True
def get_status(self):
"""
Retrieves the status of the FAN
Returns:
bool: always True
"""
return True

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
########################################################################
# Centec E530 24x2q
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
from .fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CENTEC_FANS_PER_FANTRAY = 3
class FanDrawer(FanDrawerBase):
"""Centec E530 24x2q Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
self.fantrayindex = fantray_index
for i in range(CENTEC_FANS_PER_FANTRAY):
self._fan_list.append(Fan(fantray_index, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
#
# Name: platform.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-24X2Q
#
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Psu(PsuBase):
"""Centec Platform-specific PSU class"""
def __init__(self, index):
self._index = index
self._fan_list = []
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
module = imp.load_source("psuutil", module_file)
psu_util_class = getattr(module, "PsuUtil")
self._psuutil = psu_util_class()
def _get_psuutil(self):
return self._psuutil
def get_presence(self):
return self._get_psuutil().get_psu_presence(self._index)
def get_powergood_status(self):
return self._get_psuutil().get_psu_status(self._index)

View File

@ -0,0 +1,102 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.sfp_base import SfpBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Sfp(SfpBase):
"""
Platform-specific sfp class
Unimplemented methods:
- get_model
- get_serial
- get_status
- get_transceiver_info
- get_transceiver_bulk_status
- get_transceiver_threshold_info
- get_reset_status
- get_rx_los
- get_tx_fault
- get_tx_disable_channel
- get_power_override
- get_temperature
- get_voltage
- get_tx_bias
- get_rx_power
- get_tx_power
- tx_disable_channel
- set_power_override
"""
def __init__(self, index):
self._index = index
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
module = imp.load_source("sfputil", module_file)
sfp_util_class = getattr(module, "SfpUtil")
self._sfputil = sfp_util_class()
def get_id(self):
return self._index
def get_name(self):
return "Ethernet{}".format(self._index)
def get_lpmode(self):
return False
def set_lpmode(self, lpmode):
return False
def get_tx_disable(self):
return False
def tx_disable(self, tx_disable):
return False
def reset(self):
pass
def clear_interrupt(self):
return False
def get_interrupt_file(self):
return None
def _get_sfputil(self):
return self._sfputil
def get_presence(self):
return self._get_sfputil().get_presence(self._index)
def get_transceiver_info(self):
return self._get_sfputil().get_transceiver_info_dict(self._index)
def get_transceiver_bulk_status(self):
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
def get_transceiver_threshold_info(self):
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
def get_transceiver_change_event(self, timeout):
return self._get_sfputil().get_transceiver_change_event(timeout)

View File

@ -0,0 +1,118 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
def __init__(self, thermal_index):
self.index = thermal_index
self.high_threshold = float(112)
# Add thermal name
self.THERMAL_NAME_LIST.append("SENSOR-1")
# Set hwmon path
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
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)
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_temp = self.__read_txt_file(temp_file_path)
temp = float(raw_temp)/1000
return float("{:.3f}".format(temp))
def __set_threshold(self, file_name, temperature):
temp_file_path = os.path.join(self.hwmon_path, file_name)
try:
with open(temp_file_path, 'w') as fd:
fd.write(str(temperature))
return True
except IOError:
return False
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_input".format(self.ss_index)
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return self.high_threshold
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
self.high_threshold = float(temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
return os.path.isfile(temp_file_path)
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if not self.get_presence():
return False
return True

View File

@ -0,0 +1 @@
obj-m := centec_e530_48s4x_platform.o

View File

@ -0,0 +1,13 @@
[Unit]
Description=Centec modules init
After=local-fs.target
Before=syncd.service
[Service]
Type=oneshot
ExecStart=-/etc/init.d/platform-modules-e530-48s4x start
ExecStop=-/etc/init.d/platform-modules-e530-48s4x stop
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
from setuptools import setup
os.listdir
setup(
name='sonic_platform',
version='1.0',
description='Module to initialize centec e530-48s4x platforms',
packages=['sonic_platform'],
package_dir={'sonic_platform': 'sonic_platform'},
)

View File

@ -0,0 +1,3 @@
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
from . import platform

View File

@ -0,0 +1,173 @@
#!/usr/bin/env python
#
# Name: chassis.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.eeprom import Eeprom
from .fan_drawer import FanDrawer
from .thermal import Thermal
from .sfp import Sfp
from .psu import Psu
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 1
NUM_THERMAL = 1
NUM_PORT = 52
NUM_PSU = 2
class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
# Initialize EEPROM
self._eeprom = Eeprom()
# Initialize FAN
for i in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(i)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
# Initialize THERMAL
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
# Initialize SFP
for index in range(0, NUM_PORT):
sfp = Sfp(index)
self._sfp_list.append(sfp)
# Initialize PSU
for index in range(0, NUM_PSU):
psu = Psu(index + 1)
self._psu_list.append(psu)
##############################################
# Device methods
##############################################
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_number_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
##############################################
# Chassis methods
##############################################
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
"""
return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
return (None, None)
def get_change_event(self, timeout=2000):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
ret_dict = {"sfp": port_dict}
return ret, ret_dict
def get_num_psus(self):
return len(self._psu_list)
def get_psu(self, psu_index):
return self._psu_list[psu_index]

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Name: eeprom.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_eeprom import eeprom_tlvinfo
import binascii
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/dev/mtd3"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.open_eeprom()
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
value = str((tlv[2] << 24) | (tlv[3] << 16) |
(tlv[4] << 8) | tlv[5])
value += str(tlv[6:6 + tlv[1]])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
break
tlv_index += eeprom[tlv_index+1] + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def base_mac_addr(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(TlvInfoDecoder, self).switchaddrstr(e)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict

View File

@ -0,0 +1,186 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_PATH = "/sys/class/hwmon/hwmon1/"
FAN_MAX_PWM = 255
FAN_FAN_PWM = "pwm{}"
FAN_FAN_INPUT = "fan{}_input"
FAN_MAX_RPM = 9000
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
FanBase.__init__(self)
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 Exception:
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
return direction
def get_speed(self):
"""
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
"""
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return int(speed)
def get_target_speed(self):
"""
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
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
# fan_target_sysfs_path = self.__search_file_by_name(
# FAN_PATH, fan_target_sysfs_name)
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
# return target
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return speed
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
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
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
fan_target_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_target_sysfs_name)
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
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: always True
"""
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_index]
return fan_name
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: always True
"""
return True
def get_status(self):
"""
Retrieves the status of the FAN
Returns:
bool: always True
"""
return True

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
########################################################################
# Centec E530 48s4x
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
from .fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CENTEC_FANS_PER_FANTRAY = 4
class FanDrawer(FanDrawerBase):
"""Centec E530 48s4x Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
self.fantrayindex = fantray_index
for i in range(CENTEC_FANS_PER_FANTRAY):
self._fan_list.append(Fan(fantray_index, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
#
# Name: platform.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48S4X
#
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Psu(PsuBase):
"""Centec Platform-specific PSU class"""
def __init__(self, index):
self._index = index
self._fan_list = []
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
module = imp.load_source("psuutil", module_file)
psu_util_class = getattr(module, "PsuUtil")
self._psuutil = psu_util_class()
def _get_psuutil(self):
return self._psuutil
def get_presence(self):
return self._get_psuutil().get_psu_presence(self._index)
def get_powergood_status(self):
return self._get_psuutil().get_psu_status(self._index)

View File

@ -0,0 +1,102 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.sfp_base import SfpBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Sfp(SfpBase):
"""
Platform-specific sfp class
Unimplemented methods:
- get_model
- get_serial
- get_status
- get_transceiver_info
- get_transceiver_bulk_status
- get_transceiver_threshold_info
- get_reset_status
- get_rx_los
- get_tx_fault
- get_tx_disable_channel
- get_power_override
- get_temperature
- get_voltage
- get_tx_bias
- get_rx_power
- get_tx_power
- tx_disable_channel
- set_power_override
"""
def __init__(self, index):
self._index = index
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "sfputil.py"])
module = imp.load_source("sfputil", module_file)
sfp_util_class = getattr(module, "SfpUtil")
self._sfputil = sfp_util_class()
def get_id(self):
return self._index
def get_name(self):
return "Ethernet{}".format(self._index)
def get_lpmode(self):
return False
def set_lpmode(self, lpmode):
return False
def get_tx_disable(self):
return False
def tx_disable(self, tx_disable):
return False
def reset(self):
pass
def clear_interrupt(self):
return False
def get_interrupt_file(self):
return None
def _get_sfputil(self):
return self._sfputil
def get_presence(self):
return self._get_sfputil().get_presence(self._index)
def get_transceiver_info(self):
return self._get_sfputil().get_transceiver_info_dict(self._index)
def get_transceiver_bulk_status(self):
return self._get_sfputil().get_transceiver_dom_info_dict(self._index)
def get_transceiver_threshold_info(self):
return self._get_sfputil().get_transceiver_dom_threshold_info_dict(self._index)
def get_transceiver_change_event(self, timeout):
return self._get_sfputil().get_transceiver_change_event(timeout)

View File

@ -0,0 +1,118 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Thermal contains an implementation of SONiC Platform Base API and
# provides the thermal device status which are available in the platform
#
#############################################################################
import os
import os.path
try:
from sonic_platform_base.thermal_base import ThermalBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Thermal(ThermalBase):
"""Platform-specific Thermal class"""
THERMAL_NAME_LIST = []
CPUBOARD_SS_PATH = "/sys/class/hwmon/hwmon1"
def __init__(self, thermal_index):
self.index = thermal_index
self.high_threshold = float(112)
# Add thermal name
self.THERMAL_NAME_LIST.append("SENSOR-1")
# Set hwmon path
self.ss_index, self.hwmon_path = 1, self.CPUBOARD_SS_PATH
self.ss_key = self.THERMAL_NAME_LIST[self.index - 1]
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)
def __get_temp(self, temp_file):
temp_file_path = os.path.join(self.hwmon_path, temp_file)
raw_temp = self.__read_txt_file(temp_file_path)
temp = float(raw_temp)/1000
return float("{:.3f}".format(temp))
def __set_threshold(self, file_name, temperature):
temp_file_path = os.path.join(self.hwmon_path, file_name)
try:
with open(temp_file_path, 'w') as fd:
fd.write(str(temperature))
return True
except IOError:
return False
def get_temperature(self):
"""
Retrieves current temperature reading from thermal
Returns:
A float number of current temperature in Celsius up to nearest thousandth
of one degree Celsius, e.g. 30.125
"""
temp_file = "temp{}_input".format(self.ss_index)
return self.__get_temp(temp_file)
def get_high_threshold(self):
"""
Retrieves the high threshold temperature of thermal
Returns:
A float number, the high threshold temperature of thermal in Celsius
up to nearest thousandth of one degree Celsius, e.g. 30.125
"""
return self.high_threshold
def set_high_threshold(self, temperature):
"""
Sets the high threshold temperature of thermal
Args :
temperature: A float number up to nearest thousandth of one degree Celsius,
e.g. 30.125
Returns:
A boolean, True if threshold is set successfully, False if not
"""
self.high_threshold = float(temperature)
return True
def get_name(self):
"""
Retrieves the name of the thermal device
Returns:
string: The name of the thermal device
"""
return self.THERMAL_NAME_LIST[self.index]
def get_presence(self):
"""
Retrieves the presence of the PSU
Returns:
bool: True if PSU is present, False if not
"""
temp_file = "temp{}_input".format(self.ss_index)
temp_file_path = os.path.join(self.hwmon_path, temp_file)
return os.path.isfile(temp_file_path)
def get_status(self):
"""
Retrieves the operational status of the device
Returns:
A boolean value, True if device is operating properly, False if not
"""
if not self.get_presence():
return False
return True

View File

@ -8,16 +8,92 @@
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/irq.h>
#include <asm/types.h>
#include <asm/io.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio.h>
#define SEP(XXX) 1 #define SEP(XXX) 1
#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_))
#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_))
#if SEP("defines") #if SEP("defines")
#define CTC_GPIO_BASE 496
int xirq_gpio_0 = 0;
int xirq_gpio_1 = 0;
int xirq_gpio_6 = 0; /* add for E530_48S4X EPLD INT0*/
int xirq_gpio_7 = 0; /* add for E530_48S4X EPLD INT1*/
int xirq_gpio_15 = 0;
#define IS_INVALID_PTR(_PTR_) ((_PTR_ == NULL) || IS_ERR(_PTR_))
#define IS_VALID_PTR(_PTR_) (!IS_INVALID_PTR(_PTR_))
#define SFP_NUM 4 #define SFP_NUM 4
#define PORT_NUM (48+SFP_NUM) #define PORT_NUM (48+SFP_NUM)
#endif #endif
#if SEP("ctc:pinctl")
u8 ctc_gpio_set(u8 gpio_pin, u8 val)
{
gpio_set_value_cansleep(gpio_pin + CTC_GPIO_BASE, val);
return 0;
}
u8 ctc_gpio_get(u8 gpio_pin)
{
return gpio_get_value_cansleep(gpio_pin + CTC_GPIO_BASE);
}
u8 ctc_gpio_direction_config(u8 gpio_pin, u8 dir,u8 default_out)
{
return dir ? gpio_direction_input(gpio_pin + CTC_GPIO_BASE)
: gpio_direction_output(gpio_pin + CTC_GPIO_BASE,default_out);
}
static void ctc_pincrtl_init(void)
{
/* configure mgmt-phy reset-pin output on product, mgmt-phy release must before this */
ctc_gpio_direction_config(4, 0, 1);
/* configure power-up pin output on product */
ctc_gpio_direction_config(6, 0, 0);
/* configure phy interrupt pin input */
ctc_gpio_direction_config(0, 1, 0);
ctc_gpio_direction_config(1, 1, 0);
/* configure phy reset-pin output, for release phy */
ctc_gpio_direction_config(5, 0, 1);
return;
}
static void ctc_irq_init(void)
{
struct device_node *xnp;
for_each_node_by_type(xnp, "ctc-irq")
{
if (of_device_is_compatible(xnp, "centec,ctc-irq"))
{
xirq_gpio_0 = irq_of_parse_and_map(xnp, 0);
printk(KERN_INFO "ctc-irq GPIO0 IRQ is %d\n", xirq_gpio_0);
xirq_gpio_1 = irq_of_parse_and_map(xnp, 1);
printk(KERN_INFO "ctc-irq GPIO1 IRQ is %d\n", xirq_gpio_1);
xirq_gpio_15 = irq_of_parse_and_map(xnp, 2);
printk(KERN_INFO "ctc-irq GPIO15 IRQ is %d\n", xirq_gpio_15);
}
}
return;
}
#endif
#if SEP("i2c:smbus") #if SEP("i2c:smbus")
static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value) static int e530_48t4x_p_smbus_read_reg(struct i2c_client *client, unsigned char reg, unsigned char* value)
{ {
@ -967,6 +1043,9 @@ static int e530_48t4x_p_init(void)
printk(KERN_ALERT "install e530_48t4x_p board dirver...\n"); printk(KERN_ALERT "install e530_48t4x_p board dirver...\n");
ctc_irq_init();
ctc_pincrtl_init();
ret = e530_48t4x_p_init_i2c_master(); ret = e530_48t4x_p_init_i2c_master();
if (ret != 0) if (ret != 0)
{ {

View File

@ -5,11 +5,11 @@ from setuptools import setup
os.listdir os.listdir
setup( setup(
name='48t4x_p', name='sonic_platform',
version='1.1', version='1.0',
description='Module to initialize centec e530-48t4x-p platforms', description='Module to initialize centec e530-48t4x-p platforms',
packages=['48t4x_p'], packages=['sonic_platform'],
package_dir={'48t4x_p': '48t4x_p/classes'}, package_dir={'sonic_platform': 'sonic_platform'},
) )

View File

@ -0,0 +1,3 @@
__all__ = ["platform", "chassis", "sfp", "eeprom", "psu", "thermal", "fan", "fan_drawer"]
from . import platform

View File

@ -0,0 +1,173 @@
#!/usr/bin/env python
#
# Name: chassis.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_platform_base.chassis_base import ChassisBase
from sonic_platform.eeprom import Eeprom
from .fan_drawer import FanDrawer
from .thermal import Thermal
from .sfp import Sfp
from .psu import Psu
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
NUM_FAN_TRAY = 1
NUM_THERMAL = 1
NUM_PORT = 52
NUM_PSU = 2
class Chassis(ChassisBase):
def __init__(self):
ChassisBase.__init__(self)
# Initialize EEPROM
self._eeprom = Eeprom()
# Initialize FAN
for i in range(NUM_FAN_TRAY):
fandrawer = FanDrawer(i)
self._fan_drawer_list.append(fandrawer)
self._fan_list.extend(fandrawer._fan_list)
# Initialize THERMAL
for index in range(0, NUM_THERMAL):
thermal = Thermal(index)
self._thermal_list.append(thermal)
# Initialize SFP
for index in range(0, NUM_PORT):
sfp = Sfp(index)
self._sfp_list.append(sfp)
# Initialize PSU
for index in range(0, NUM_PSU):
psu = Psu(index + 1)
self._psu_list.append(psu)
##############################################
# Device methods
##############################################
def get_name(self):
"""
Retrieves the name of the chassis
Returns:
string: The name of the chassis
"""
return self._eeprom.modelstr()
def get_presence(self):
"""
Retrieves the presence of the chassis
Returns:
bool: True if chassis is present, False if not
"""
return True
def get_model(self):
"""
Retrieves the model number (or part number) of the chassis
Returns:
string: Model/part number of chassis
"""
return self._eeprom.part_number_str()
def get_serial(self):
"""
Retrieves the serial number of the chassis
Returns:
string: Serial number of chassis
"""
return self._eeprom.serial_number_str()
def get_status(self):
"""
Retrieves the operational status of the chassis
Returns:
bool: A boolean value, True if chassis is operating properly
False if not
"""
return True
##############################################
# Chassis methods
##############################################
def get_base_mac(self):
"""
Retrieves the base MAC address for the chassis
Returns:
A string containing the MAC address in the format
'XX:XX:XX:XX:XX:XX'
"""
return self._eeprom.base_mac_addr()
def get_serial_number(self):
"""
Retrieves the hardware serial number for the chassis
Returns:
A string containing the hardware serial number for this chassis.
"""
return self._eeprom.serial_number_str()
def get_system_eeprom_info(self):
"""
Retrieves the full content of system EEPROM information for the chassis
Returns:
A dictionary where keys are the type code defined in
OCP ONIE TlvInfo EEPROM format and values are their corresponding
values.
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
"""
return self._eeprom.system_eeprom_info()
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
Returns:
A tuple (string, string) where the first element is a string
containing the cause of the previous reboot. This string must be
one of the predefined strings in this class. If the first string
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
to pass a description of the reboot cause.
"""
return (None, None)
def get_change_event(self, timeout=2000):
"""
Returns a nested dictionary containing all devices which have
experienced a change at chassis level
Args:
timeout: Timeout in milliseconds (optional). If timeout == 0,
this method will block until a change is detected.
Returns:
(bool, dict):
- True if call successful, False if not;
- A nested dictionary where key is a device type,
value is a dictionary with key:value pairs in the
format of {'device_id':'device_event'},
where device_id is the device ID for this device and
device_event,
status='1' represents device inserted,
status='0' represents device removed.
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
indicates that fan 0 has been removed, fan 2
has been inserted and sfp 11 has been removed.
"""
ret, port_dict = self._sfp_list[0].get_transceiver_change_event(timeout)
ret_dict = {"sfp": port_dict}
return ret, ret_dict
def get_num_psus(self):
return len(self._psu_list)
def get_psu(self, psu_index):
return self._psu_list[psu_index]

View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
#
# Name: eeprom.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
#
try:
from sonic_eeprom import eeprom_tlvinfo
import binascii
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/dev/mtd3"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.open_eeprom()
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (eeprom[9] << 8) | eeprom[10]
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ eeprom[tlv_index + 1]]
code = "0x%02X" % (tlv[0])
if tlv[0] == self._TLV_CODE_VENDOR_EXT:
value = str((tlv[2] << 24) | (tlv[3] << 16) |
(tlv[4] << 8) | tlv[5])
value += str(tlv[6:6 + tlv[1]])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
break
tlv_index += eeprom[tlv_index+1] + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def base_mac_addr(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(TlvInfoDecoder, self).switchaddrstr(e)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2].decode('ascii')
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict

View File

@ -0,0 +1,186 @@
#!/usr/bin/env python
#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the fan status which are available in the platform
#
#############################################################################
import math
import os.path
try:
from sonic_platform_base.fan_base import FanBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
FAN_PATH = "/sys/class/hwmon/hwmon1/"
FAN_MAX_PWM = 255
FAN_FAN_PWM = "pwm{}"
FAN_FAN_INPUT = "fan{}_input"
FAN_MAX_RPM = 9000
FAN_NAME_LIST = ["FAN-1", "FAN-2", "FAN-3", "FAN-4"]
class Fan(FanBase):
"""Platform-specific Fan class"""
def __init__(self, fan_tray_index, fan_index=0):
self.fan_index = fan_index
self.fan_tray_index = fan_tray_index
FanBase.__init__(self)
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 Exception:
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
return direction
def get_speed(self):
"""
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
"""
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return int(speed)
def get_target_speed(self):
"""
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
# fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
# fan_target_sysfs_path = self.__search_file_by_name(
# FAN_PATH, fan_target_sysfs_name)
# fan_target_pwm = self.__read_txt_file(fan_target_sysfs_path) or 0
# target = math.ceil(float(fan_target_pwm) * 100 / FAN_MAX_PWM)
# return target
speed = 0
fan_speed_sysfs_name = "fan{}_input".format(self.fan_index+1)
fan_speed_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_speed_sysfs_name)
fan_speed_rpm = self.__read_txt_file(fan_speed_sysfs_path) or 0
speed = math.ceil(float(fan_speed_rpm) * 100 / FAN_MAX_RPM)
return speed
def get_speed_tolerance(self):
"""
Retrieves the speed tolerance of the fan
Returns:
An integer, the percentage of variance from target speed which is
considered tolerable
"""
return 10
def set_speed(self, speed):
"""
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
fan_target_sysfs_name = "pwm{}".format(self.fan_index+1)
fan_target_sysfs_path = self.__search_file_by_name(
FAN_PATH, fan_target_sysfs_name)
return self.__write_txt_file(fan_target_sysfs_path, int(pwm))
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: always True
"""
return True
def get_name(self):
"""
Retrieves the name of the device
Returns:
string: The name of the device
"""
fan_name = FAN_NAME_LIST[self.fan_index]
return fan_name
def get_presence(self):
"""
Retrieves the presence of the FAN
Returns:
bool: always True
"""
return True
def get_status(self):
"""
Retrieves the status of the FAN
Returns:
bool: always True
"""
return True

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
########################################################################
# Centec E530 48t4x-p
#
# Module contains an implementation of SONiC Platform Base API and
# provides the Fan-Drawers' information available in the platform.
#
########################################################################
try:
from sonic_platform_base.fan_drawer_base import FanDrawerBase
from .fan import Fan
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
CENTEC_FANS_PER_FANTRAY = 3
class FanDrawer(FanDrawerBase):
"""Centec E530 48t4x-p Platform-specific Fan class"""
def __init__(self, fantray_index):
FanDrawerBase.__init__(self)
self.fantrayindex = fantray_index
for i in range(CENTEC_FANS_PER_FANTRAY):
self._fan_list.append(Fan(fantray_index, i))
def get_name(self):
"""
Retrieves the fan drawer name
Returns:
string: The name of the device
"""
return "FanTray{}".format(self.fantrayindex)

View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
#
# Name: platform.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs for Centec E530-48T4X-P
#
try:
from sonic_platform_base.platform_base import PlatformBase
from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Platform(PlatformBase):
def __init__(self):
PlatformBase.__init__(self)
self._chassis = Chassis()

View File

@ -0,0 +1,45 @@
#!/usr/bin/env python
from __future__ import print_function
import imp
import os
try:
from sonic_platform_base.psu_base import PsuBase
from sonic_py_common import device_info
except ImportError as e:
raise ImportError("%s - required module not found" % e)
USR_SHARE_SONIC_PATH = "/usr/share/sonic"
HOST_DEVICE_PATH = USR_SHARE_SONIC_PATH + "/device"
CONTAINER_PLATFORM_PATH = USR_SHARE_SONIC_PATH + "/platform"
class Psu(PsuBase):
"""Centec Platform-specific PSU class"""
def __init__(self, index):
self._index = index
self._fan_list = []
if os.path.isdir(CONTAINER_PLATFORM_PATH):
platform_path = CONTAINER_PLATFORM_PATH
else:
platform = device_info.get_platform()
if platform is None:
return
platform_path = os.path.join(HOST_DEVICE_PATH, platform)
module_file = "/".join([platform_path, "plugins", "psuutil.py"])
module = imp.load_source("psuutil", module_file)
psu_util_class = getattr(module, "PsuUtil")
self._psuutil = psu_util_class()
def _get_psuutil(self):
return self._psuutil
def get_presence(self):
return self._get_psuutil().get_psu_presence(self._index)
def get_powergood_status(self):
return self._get_psuutil().get_psu_status(self._index)

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