2018-08-12 14:39:20 -05:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
2018-09-14 02:54:08 -05:00
|
|
|
# Copyright (C) 2018 Inventec, Inc.
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
import os
|
|
|
|
import time
|
|
|
|
import syslog
|
|
|
|
import re
|
|
|
|
from sonic_sfp.bcmshell import bcmshell
|
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
|
2018-08-12 14:39:20 -05:00
|
|
|
# =====================================================================
|
|
|
|
# global variable init
|
|
|
|
# =====================================================================
|
2018-09-14 02:54:08 -05:00
|
|
|
# port object
|
|
|
|
PORT_LIST = []
|
|
|
|
# object is to execute bcm shell command
|
|
|
|
BCM_SHELL = None
|
|
|
|
SHELL_READY = False
|
|
|
|
# port status that is auto update by chip in data ram
|
|
|
|
STATUS_RX = 1<<0
|
|
|
|
STATUS_TX = 1<<1
|
2018-08-12 14:39:20 -05:00
|
|
|
# define data ram address
|
|
|
|
PORT_DATA_OFFSET_ADDR = 0xA0
|
2018-09-14 02:54:08 -05:00
|
|
|
# define board type
|
|
|
|
INV_MAGNOLIA = "SONiC-Inventec-d6254qs"
|
|
|
|
INV_REDWOOD = "SONiC-Inventec-d7032-100"
|
|
|
|
INV_CYPRESS = "SONiC-Inventec-d7054"
|
|
|
|
INV_MAPLE = "SONiC-Inventec-d6556"
|
|
|
|
INV_SEQUOIA = ""
|
|
|
|
BOARD_TPYE = ""
|
|
|
|
EAGLE_CORE = []
|
2018-08-12 14:39:20 -05:00
|
|
|
# define port data for bit streaming
|
|
|
|
BIT_LINK = None
|
|
|
|
BIT_FAULT = None
|
|
|
|
BIT_TX = None
|
|
|
|
BIT_RX = None
|
|
|
|
BIT_SPEED0 = None
|
|
|
|
BIT_SPEED1 = None
|
|
|
|
# define port speed
|
|
|
|
SPEED_100G = 100
|
|
|
|
SPEED_40G = 40
|
|
|
|
SPEED_25G = 25
|
|
|
|
SPEED_10G = 10
|
|
|
|
|
|
|
|
|
|
|
|
# =====================================================================
|
|
|
|
# class object
|
|
|
|
# =====================================================================
|
2018-09-14 02:54:08 -05:00
|
|
|
class Port():
|
|
|
|
|
|
|
|
port_num = None
|
|
|
|
name = None
|
|
|
|
bcm_id = None
|
|
|
|
led_up = None
|
|
|
|
s_addr = None
|
|
|
|
write2_up = None
|
|
|
|
led_index = None
|
|
|
|
link_status = None
|
|
|
|
speed = None
|
|
|
|
|
|
|
|
def write_data_ram(self, data):
|
|
|
|
BCM_SHELL.cmd("setreg CMIC_LEDUP{0}_DATA_RAM({1}) {2}".format(self.write2_up, self.led_index, data))
|
|
|
|
|
|
|
|
def read_data_ram(self):
|
|
|
|
r_string = BCM_SHELL.run("getreg CMIC_LEDUP{0}_DATA_RAM({1})".format(self.led_up, self.s_addr))
|
|
|
|
for line in r_string.split("\n"):
|
|
|
|
re_obj = re.search(r"\<DATA\=(?P<data>.+)\>", line)
|
2018-08-12 14:39:20 -05:00
|
|
|
if re_obj is not None:
|
2018-09-14 02:54:08 -05:00
|
|
|
#syslog.syslog(syslog.LOG_DEBUG, "Read Led({0}) data_ram({1}): {2}".format(self.up, addr, re_obj.group("data")))
|
2018-08-12 14:39:20 -05:00
|
|
|
return int(re_obj.group("data"), 16)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# =====================================================================
|
|
|
|
# Function
|
|
|
|
# =====================================================================
|
2018-09-14 02:54:08 -05:00
|
|
|
def _remap_registers(fp):
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
content = fp.readlines()
|
|
|
|
fp.close()
|
|
|
|
err = False
|
|
|
|
|
|
|
|
for line in content:
|
|
|
|
try:
|
|
|
|
BCM_SHELL.cmd(line.rstrip())
|
|
|
|
except Exception, e:
|
|
|
|
err = True
|
|
|
|
syslog.syslog(syslog.LOG_ERR, "remap register abnormal: {0}".format(str(e)))
|
|
|
|
|
|
|
|
if not err:
|
2018-09-14 02:54:08 -05:00
|
|
|
syslog.syslog(syslog.LOG_INFO, "remap Led registers successfully")
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
def _board_init():
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
global BOARD_TPYE
|
|
|
|
global BIT_LINK
|
|
|
|
global BIT_FAULT
|
|
|
|
global BIT_TX
|
|
|
|
global BIT_RX
|
|
|
|
global BIT_SPEED0
|
|
|
|
global BIT_SPEED1
|
|
|
|
global EAGLE_CORE
|
|
|
|
global TOTAL_SCAN_BITS
|
|
|
|
global SYNC_S
|
|
|
|
global SYNC_P
|
|
|
|
|
|
|
|
cmd = "uname -n"
|
|
|
|
platform = os.popen(cmd).read()
|
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
if platform.rstrip() == INV_MAGNOLIA:
|
|
|
|
BOARD_TPYE = "inventec_d6254qs"
|
|
|
|
BIT_RX = 1<<0 #0x01
|
|
|
|
BIT_TX = 1<<1 #0x02
|
|
|
|
BIT_SPEED1 = 1<<4 #0x10
|
|
|
|
BIT_LINK = 1<<7 #0x80
|
|
|
|
fp = open('/usr/share/sonic/device/x86_64-inventec_d6254qs-r0/led_proc_init.soc', "r")
|
|
|
|
_remap_registers(fp)
|
|
|
|
|
|
|
|
elif platform.rstrip() == INV_REDWOOD:
|
2018-08-12 14:39:20 -05:00
|
|
|
BOARD_TPYE = "inventec_d7032q28b"
|
|
|
|
BIT_RX = 1<<0 #0x01
|
|
|
|
BIT_TX = 1<<1 #0x02
|
|
|
|
BIT_SPEED0 = 1<<3 #0x08
|
|
|
|
BIT_SPEED1 = 1<<4 #0x10
|
|
|
|
BIT_FAULT = 1<<6 #0x40
|
|
|
|
BIT_LINK = 1<<7 #0x80
|
|
|
|
EAGLE_CORE = [66, 100]
|
2018-09-14 02:54:08 -05:00
|
|
|
fp = open('/usr/share/sonic/device/x86_64-inventec_d7032q28b-r0/led_proc_init.soc', "r")
|
|
|
|
_remap_registers(fp)
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
elif platform.rstrip() == INV_CYPRESS:
|
|
|
|
BOARD_TPYE = "inventec_d7054q28b"
|
|
|
|
BIT_LINK = 1<<0 #0x01
|
|
|
|
BIT_FAULT = 1<<1 #0x02
|
|
|
|
BIT_SPEED0 = 1<<2 #0x04
|
|
|
|
EAGLE_CORE = [66, 100]
|
|
|
|
|
|
|
|
elif platform.rstrip() == INV_SEQUOIA:
|
|
|
|
BOARD_TPYE = "inventec_d7264q28b"
|
2018-09-14 02:54:08 -05:00
|
|
|
|
|
|
|
elif platform.rstrip() == INV_MAPLE:
|
|
|
|
BOARD_TPYE = "inventec_d6556"
|
|
|
|
fp = open('/usr/share/sonic/device/x86_64-inventec_d6556-r0/led_proc_init.soc', "r")
|
|
|
|
_remap_registers(fp)
|
|
|
|
#led process: m0 led process that is controlled by linkscan_led_fw.bin and custom_led.bin
|
|
|
|
syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE))
|
|
|
|
exit(0)
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
else:
|
|
|
|
BOARD_TPYE = "not found"
|
2018-09-14 02:54:08 -05:00
|
|
|
syslog.syslog(syslog.LOG_ERR, "Found device: {0}".format(BOARD_TPYE))
|
|
|
|
exit(0)
|
2018-08-12 14:39:20 -05:00
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
syslog.syslog(syslog.LOG_INFO, "Found device: {0}".format(BOARD_TPYE))
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
def _lookup_led_index(p):
|
|
|
|
|
|
|
|
index = 0
|
|
|
|
if BOARD_TPYE == "inventec_d6254qs":
|
|
|
|
if 0 <= p.port_num <= 47:
|
|
|
|
index = p.port_num + (p.port_num / 4)
|
|
|
|
p.write2_up = 0
|
|
|
|
elif 48 <= p.port_num <= 71:
|
|
|
|
index = p.port_num - 48
|
|
|
|
p.write2_up = 1
|
|
|
|
if p.led_up == 0:
|
|
|
|
p.s_addr = p.port_num * 2
|
|
|
|
elif p.led_up == 1:
|
|
|
|
p.s_addr = (p.port_num - 36) * 2
|
|
|
|
|
|
|
|
elif BOARD_TPYE == "inventec_d7032q28b":
|
|
|
|
p.write2_up = 0
|
|
|
|
index = p.port_num
|
|
|
|
if 0 <= p.port_num <= 7:
|
|
|
|
p.s_addr = p.port_num * 8
|
|
|
|
elif 8 <= p.port_num <= 23:
|
|
|
|
p.s_addr = (p.port_num - 8) * 8
|
|
|
|
elif 24 <= p.port_num <= 31:
|
|
|
|
p.s_addr = (p.port_num - 16) * 8
|
|
|
|
|
|
|
|
else:
|
|
|
|
p.write2_up = p.led_up
|
|
|
|
for port in PORT_LIST:
|
|
|
|
if p.bcm_id == port.bcm_id:
|
|
|
|
break
|
|
|
|
if p.led_up == port.led_up:
|
|
|
|
index += 1
|
|
|
|
|
|
|
|
return PORT_DATA_OFFSET_ADDR + index
|
|
|
|
|
|
|
|
|
|
|
|
def _update_port_list(only_update):
|
|
|
|
|
|
|
|
global PORT_LIST
|
|
|
|
number = 0
|
|
|
|
count = 0
|
|
|
|
|
|
|
|
content = BCM_SHELL.run("ps")
|
|
|
|
for line in content.split("\n"):
|
|
|
|
re_obj = re.search(r"(?P<port_name>(xe|ce)\d+)\(\s*(?P<bcm_id>\d+)\)\s+(?P<link>(up|down|!ena)).+\s+(?P<speed>\d+)G", line)
|
|
|
|
if re_obj is not None:
|
|
|
|
if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
|
|
|
|
if only_update:
|
|
|
|
PORT_LIST[number].link_status = re_obj.group("link")
|
|
|
|
else:
|
|
|
|
# create port object while first time
|
|
|
|
port_obj = Port()
|
|
|
|
port_obj.port_num = number
|
|
|
|
port_obj.name = re_obj.group("port_name")
|
|
|
|
port_obj.bcm_id = int(re_obj.group("bcm_id"))
|
|
|
|
port_obj.link_status = re_obj.group("link")
|
|
|
|
port_obj.speed = int(re_obj.group("speed"))
|
|
|
|
PORT_LIST.append(port_obj)
|
|
|
|
number += 1
|
|
|
|
|
|
|
|
if not only_update:
|
|
|
|
content = BCM_SHELL.run("led status")
|
|
|
|
for line in content.split("\n"):
|
|
|
|
re_obj = re.search(r"(?P<bcm_id>\d+).+(?P<led_up>\d)\:", line)
|
|
|
|
if re_obj is not None:
|
|
|
|
if int(re_obj.group("bcm_id")) not in EAGLE_CORE:
|
|
|
|
PORT_LIST[count].led_up = int(re_obj.group("led_up"))
|
|
|
|
PORT_LIST[count].led_index = _lookup_led_index(PORT_LIST[count])
|
|
|
|
count += 1
|
|
|
|
|
|
|
|
if number is not count:
|
|
|
|
PORT_LIST = []
|
|
|
|
syslog.syslog(syslog.LOG_ERR, "The amount of port is not match")
|
|
|
|
|
2018-08-12 14:39:20 -05:00
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
|
|
|
|
def sync_bcmsh_socket():
|
|
|
|
|
|
|
|
global BCM_SHELL
|
|
|
|
global SHELL_READY
|
|
|
|
waitSyncd = True
|
|
|
|
retryCount = 0
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
while waitSyncd:
|
2018-09-14 02:54:08 -05:00
|
|
|
time.sleep(10)
|
2018-08-12 14:39:20 -05:00
|
|
|
try:
|
|
|
|
BCM_SHELL = bcmshell()
|
2018-09-14 02:54:08 -05:00
|
|
|
BCM_SHELL.run("Echo")
|
2018-08-12 14:39:20 -05:00
|
|
|
waitSyncd = False
|
|
|
|
except Exception, e:
|
2018-09-14 02:54:08 -05:00
|
|
|
print "{0}, Retry times({1})".format(str(e),retryCount)
|
|
|
|
#syslog.syslog(syslog.LOG_DEBUG, "{0}, Retry times({1})".format(str(e),retryCount))
|
2018-08-12 14:39:20 -05:00
|
|
|
retryCount += 1
|
2018-09-14 02:54:08 -05:00
|
|
|
|
|
|
|
syslog.syslog(syslog.LOG_INFO, "bcmshell socket create successfully")
|
|
|
|
|
|
|
|
if SHELL_READY is False:
|
|
|
|
SHELL_READY = True
|
|
|
|
return
|
|
|
|
elif SHELL_READY is True:
|
|
|
|
update_led_status()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_led_status():
|
|
|
|
|
|
|
|
led_thread = True # True/False (gate to turn on/off)
|
|
|
|
reset_sec = 2
|
|
|
|
count_down = 0
|
|
|
|
queue_active = []
|
|
|
|
port_data = None
|
|
|
|
s_byte = None
|
|
|
|
|
|
|
|
|
|
|
|
# thread for keeping update port status in data ram
|
|
|
|
while led_thread:
|
|
|
|
try:
|
|
|
|
if count_down == 0:
|
|
|
|
queue_active = []
|
|
|
|
_update_port_list(1)
|
|
|
|
for port in PORT_LIST:
|
|
|
|
if port.link_status == "up":
|
|
|
|
queue_active.append(port)
|
2018-08-12 14:39:20 -05:00
|
|
|
else:
|
2018-09-14 02:54:08 -05:00
|
|
|
port_data = 0
|
|
|
|
port.write_data_ram(port_data)
|
|
|
|
count_down = reset_sec
|
|
|
|
else:
|
|
|
|
for port in queue_active:
|
|
|
|
port_data = 0
|
2018-08-12 14:39:20 -05:00
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
if BOARD_TPYE == "inventec_d6254qs":
|
|
|
|
s_byte = port.read_data_ram()
|
|
|
|
if s_byte&STATUS_RX:
|
|
|
|
port_data |= BIT_RX
|
|
|
|
if s_byte&STATUS_TX:
|
|
|
|
port_data |= BIT_TX
|
|
|
|
port_data |= BIT_LINK
|
|
|
|
|
|
|
|
elif BOARD_TPYE == "inventec_d7032q28b":
|
|
|
|
s_byte = port.read_data_ram()
|
|
|
|
if s_byte&STATUS_RX:
|
|
|
|
port_data |= BIT_RX
|
|
|
|
if s_byte&STATUS_TX:
|
|
|
|
port_data |= BIT_TX
|
|
|
|
if port.speed == SPEED_100G:
|
|
|
|
port_data |= BIT_SPEED0
|
|
|
|
port_data |= BIT_SPEED1
|
|
|
|
elif port.speed == SPEED_40G:
|
|
|
|
port_data |= BIT_SPEED1
|
|
|
|
elif port.speed == SPEED_25G:
|
|
|
|
port_data |= BIT_SPEED0
|
|
|
|
else:
|
|
|
|
pass
|
|
|
|
port_data |= BIT_LINK
|
|
|
|
|
|
|
|
elif BOARD_TPYE == "inventec_d7054q28b":
|
|
|
|
if port.speed != SPEED_100G and port.speed != SPEED_25G:
|
|
|
|
port_data |= BIT_SPEED0
|
|
|
|
|
|
|
|
# write data to update data ram for specific port
|
|
|
|
port.write_data_ram(port_data)
|
|
|
|
|
|
|
|
time.sleep(0.5)
|
|
|
|
count_down -= 1
|
2018-08-12 14:39:20 -05:00
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
except Exception, e:
|
|
|
|
syslog.syslog(syslog.LOG_WARNING, "{0}".format(str(e)))
|
|
|
|
sync_bcmsh_socket()
|
2018-08-12 14:39:20 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
def debug_print():
|
|
|
|
|
|
|
|
for port in PORT_LIST:
|
|
|
|
output = ""
|
|
|
|
output += "name:{0} | ".format(port.name)
|
|
|
|
output += "port_num:{0} | ".format(port.port_num)
|
|
|
|
output += "bcm_id:{0} | ".format(port.bcm_id)
|
|
|
|
output += "link_status:{0} | ".format(port.link_status)
|
|
|
|
output += "speed:{0} | ".format(port.speed)
|
|
|
|
output += "led_up:{0} | ".format(port.led_up)
|
|
|
|
output += "s_addr:{0} | ".format(port.s_addr)
|
|
|
|
output += "write2_up:{0} | ".format(port.write2_up)
|
|
|
|
output += "led_index:{0} | ".format(port.led_index)
|
|
|
|
print output
|
2018-08-12 14:39:20 -05:00
|
|
|
|
2018-09-14 02:54:08 -05:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
|
|
syslog.openlog("led_proc", syslog.LOG_PID, facility=syslog.LOG_DAEMON)
|
|
|
|
|
|
|
|
sync_bcmsh_socket()
|
|
|
|
_board_init()
|
|
|
|
_update_port_list(0)
|
|
|
|
#debug_print()
|
|
|
|
update_led_status()
|
|
|
|
|
|
|
|
syslog.closelog()
|