9e19a9a7cf
Why I did it Adding platform support for centec v682-48y8c and v682-48x8c. V682-48y8c switch has 48 SFP+ (1G/10G/25G) ports, 8 QSFP28 (40G/100G) ports on CENTEC TsingMa.MX. V682-48y8c is different from V682-48y8c_d in that: transceiver is managed by cpu smbus rather than TsingMa.MX i2c bus. port led is managed by mcu inside TsingMa.MX. fan, psu, sensors, leds are managed by cpu smbus other than the cpu board vendor's close sourse driver. V682-48x8c switch has 48 SFP+ (1G/10G) ports, 8 QSFP28 (40G/100G) ports on CENTEC TsingMa.MX. CPU used in v682-48y8c and v682-48x8c is Intel(R) Xeon(R) CPU D-1527. How I did it Modify related code in platform and device directory. Upgrade centec sai to v1.9. upgrade python to python3 and kernel version to 5.0 for V682-48y8c_d. How to verify it Build centec amd64 sonic image, verify platform functions (port, sfp, led etc) on centec v682-48y8c and v682-48x8c board. Co-authored-by: shil <shil@centecnetworks.com>
215 lines
6.1 KiB
Python
215 lines
6.1 KiB
Python
#!/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
|
|
from subprocess import Popen
|
|
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 = {
|
|
32 : 0,
|
|
33 : 1,
|
|
34 : 2,
|
|
35 : 3,
|
|
0 : 4,
|
|
4 : 5,
|
|
8 : 6,
|
|
12 : 7,
|
|
16 : 8,
|
|
20 : 9,
|
|
24 : 10,
|
|
28 : 11,
|
|
40 : 12,
|
|
44 : 13,
|
|
48 : 14,
|
|
52 : 15,
|
|
56 : 16,
|
|
60 : 17,
|
|
64 : 18,
|
|
68 : 19,
|
|
72 : 20,
|
|
73 : 21,
|
|
74 : 22,
|
|
75 : 23,
|
|
232: 24,
|
|
233: 25,
|
|
234: 26,
|
|
235: 27,
|
|
200: 28,
|
|
204: 29,
|
|
208: 30,
|
|
212: 31,
|
|
216: 32,
|
|
220: 33,
|
|
224: 34,
|
|
228: 35,
|
|
160: 36,
|
|
164: 37,
|
|
168: 38,
|
|
172: 39,
|
|
176: 40,
|
|
180: 41,
|
|
184: 42,
|
|
188: 43,
|
|
192: 44,
|
|
193: 45,
|
|
194: 46,
|
|
195: 47,
|
|
120: 48,
|
|
121: -1,
|
|
122: -1,
|
|
123: -1,
|
|
124: 49,
|
|
125: -1,
|
|
126: -1,
|
|
127: -1,
|
|
80 : 50,
|
|
81 : -1,
|
|
82 : -1,
|
|
83 : -1,
|
|
84 : 51,
|
|
85 : -1,
|
|
86 : -1,
|
|
87 : -1,
|
|
240: 52,
|
|
241: -1,
|
|
242: -1,
|
|
243: -1,
|
|
244: 53,
|
|
245: -1,
|
|
246: -1,
|
|
247: -1,
|
|
280: 54,
|
|
281: -1,
|
|
282: -1,
|
|
283: -1,
|
|
284: 55,
|
|
285: -1,
|
|
286: -1,
|
|
287: -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, "V682-48y8c", "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 = [5, 5]
|
|
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 >= 48 else self.LED_MODE_UP[0]
|
|
else:
|
|
return self.LED_MODE_DOWN[1] if port_idx >= 48 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:
|
|
cmd = 'i2cset -y 0 0x36 0x2 0x5'
|
|
Popen(cmd, shell=True)
|
|
DBG_PRINT("init system led to normal")
|
|
cmd = 'i2cset -y 0 0x36 0x3 0x1'
|
|
Popen(cmd, shell=True)
|
|
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))
|