Skip to content

Commit c910855

Browse files
committed
Fix Led
1 parent 4bbdf0c commit c910855

File tree

1 file changed

+100
-60
lines changed
  • sonic-ledd/scripts

1 file changed

+100
-60
lines changed

sonic-ledd/scripts/ledd

+100-60
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import sys
1010

1111
from sonic_py_common import daemon_base
1212
from sonic_py_common import multi_asic
13-
#from sonic_py_common.interface import backplane_prefix, inband_prefix, recirc_prefix
1413
from swsscommon import swsscommon
1514

1615
#============================= Constants =============================
@@ -34,56 +33,59 @@ SELECT_TIMEOUT = 1000
3433

3534
LEDUTIL_LOAD_ERROR = 1
3635
LEDUTIL_RUNTIME_ERROR = 2
36+
LEDD_SELECT_ERROR = 3
3737

38-
MAX_FRONT_PANEL_PORTS = 64+1
38+
MAX_FRONT_PANEL_PORTS = 256
3939

4040
class Port():
4141
PORT_UP = "up" # All subports are up
4242
PORT_DOWN = "down" # All subports are down
43+
PORT_OP_FIELD = "netdev_oper_status"
4344

4445
def __init__(self, name, index, state, subport, role):
4546
self._name = name
4647
self._index = index
4748
self._state = state
4849
self._subport = subport
4950
self._role = role
50-
self.is_front_panel_port = multi_asic.is_front_panel_port(name, role)
51+
52+
def __str__(self):
53+
return "Port(name={}, index={}, state={}, subport={}, role={})".format(
54+
self._name, self._index, self._state, self._subport, self._role)
5155

5256
def isFrontPanelPort(self):
53-
return self.is_front_panel_port
57+
return multi_asic.is_front_panel_port(self._name, self._role)
5458
class FrontPanelPorts:
55-
def __init__(self, namespaces):
56-
# {port-index, list of logical ports}
57-
self.fp_port_list = [set() for _ in range(MAX_FRONT_PANEL_PORTS)]
59+
def __init__(self, fp_list, up_subports, logical_pmap, led_ctrl):
5860
# {port-index, total subports oper UP}
59-
self.fp_port_up_subports = [0] * MAX_FRONT_PANEL_PORTS
60-
self.logical_port_mapping = {}
61-
self.port_obs = PortStateObserver()
61+
self.fp_port_up_subports = up_subports
62+
# {port-index, list of logical ports}
63+
self.fp_port_list = fp_list
64+
self.logical_port_mapping = logical_pmap
65+
self.led_control = led_ctrl
66+
67+
def initPortLeds(self):
68+
"""
69+
Initialize the port LEDs based on the current state of the front panel ports
70+
"""
71+
for index in range(MAX_FRONT_PANEL_PORTS):
72+
if len(self.fp_port_list[index]) > 0:
73+
name = next(iter(self.fp_port_list[index]))
74+
if self.areAllSubportsUp(name):
75+
self.updatePortLed(name, Port.PORT_UP)
76+
else:
77+
self.updatePortLed(name, Port.PORT_DOWN)
6278

63-
for namespace in namespaces:
64-
port_cfg_table = self.port_obs.getDatabseTable("CONFIG_DB", swsscommon.CFG_PORT_TABLE_NAME, namespace)
65-
port_st_table = self.port_obs.getDatabseTable("STATE_DB", swsscommon.STATE_PORT_TABLE_NAME, namespace)
66-
for key in port_cfg_table.getKeys():
67-
_, pcfg = port_cfg_table.get(key)
68-
_, pstate = port_st_table.get(key)
69-
pcfg_dict = dict(pcfg)
70-
pstate_dict = dict(pstate)
71-
p = Port(key,
72-
int(pcfg_dict['index']),
73-
pstate_dict.get('oper_status', Port.PORT_DOWN),
74-
pcfg_dict.get('subport', 0),
75-
pcfg_dict.get('role', None))
76-
self.logical_port_mapping[key] = p
77-
print("name={} index={} state={} subport={} role={}".format(p._name, p._index, p._state, p._subport, p._role))
78-
#print("port list = {}".format(self.fp_port_list))
79-
self.fp_port_list[p._index].add(key)
80-
if p._state == Port.PORT_UP:
81-
self.fp_port_up_subports[p._index] += 1
79+
def updatePortLed(self, port_name, port_state):
80+
try:
81+
self.led_control.port_link_state_change(port_name, port_state)
82+
except Exception as e:
83+
sys.exit(LEDUTIL_RUNTIME_ERROR)
8284

8385
def getPort(self, name):
8486
if name in self.logical_port_mapping:
8587
port = self.logical_port_mapping[name]
86-
return port if port.isFrontPanelPort() else None
88+
return port
8789
return None
8890

8991
def areAllSubportsUp(self, name):
@@ -106,15 +108,20 @@ class FrontPanelPorts:
106108
return 0
107109

108110
def updatePortState(self, port_name, port_state):
109-
assert port_state in [Port.PORT_UP, Port.PORT_DOWN]
110-
port = self.getPort(port_name)
111-
if port:
112-
if port_state == Port.PORT_UP:
113-
self.fp_port_up_subports[port._index] = max(1 + self.fp_port_up_subports[port._index],
114-
self.getTotalSubports(port._index))
115-
else:
116-
self.fp_port_up_subports[port._index] = min(0, self.fp_port_up_subports[port._index] - 1)
117-
port._state = port_state
111+
"""
112+
Return True if the port state has changed, False otherwise
113+
"""
114+
assert port_state in [Port.PORT_UP, Port.PORT_DOWN]
115+
port = self.getPort(port_name)
116+
if port and port_state != port._state:
117+
if port_state == Port.PORT_UP:
118+
self.fp_port_up_subports[port._index] = min(1 + self.fp_port_up_subports[port._index],
119+
self.getTotalSubports(port._index))
120+
else:
121+
self.fp_port_up_subports[port._index] = max(0, self.fp_port_up_subports[port._index] - 1)
122+
port._state = port_state
123+
return True
124+
return False
118125

119126
class PortStateObserver:
120127
def __init__(self):
@@ -154,49 +161,82 @@ class PortStateObserver:
154161
if fvp:
155162
if key in ["PortConfigDone", "PortInitDone"]:
156163
return None
157-
if op == "SET" and "oper_status" in fvp_dict:
158-
fvp_dict = dict(fvp)
159-
return (key, fvp_dict["oper_status"])
160164

161-
return None
165+
fvp_dict = dict(fvp)
166+
if op == "SET" and Port.PORT_OP_FIELD in fvp_dict:
167+
return (key, fvp_dict[Port.PORT_OP_FIELD])
162168

169+
return None
163170

164171
class DaemonLedd(daemon_base.DaemonBase):
165172
def __init__(self):
166173
daemon_base.DaemonBase.__init__(self, SYSLOG_IDENTIFIER)
167174

175+
if multi_asic.is_multi_asic():
176+
# Load the namespace details first from the database_global.json file.
177+
swsscommon.SonicDBConfig.initializeGlobalConfig()
178+
168179
# Load platform-specific LedControl module
169180
try:
170-
self.led_control = self.load_platform_util(LED_MODULE_NAME, LED_CLASS_NAME)
181+
led_control = self.load_platform_util(LED_MODULE_NAME, LED_CLASS_NAME)
171182
except Exception as e:
172183
self.log_error("Failed to load ledutil: %s" % (str(e)), True)
173184
sys.exit(LEDUTIL_LOAD_ERROR)
174185

175-
if multi_asic.is_multi_asic():
176-
# Load the namespace details first from the database_global.json file.
177-
swsscommon.SonicDBConfig.initializeGlobalConfig()
178186

179187
# Initialize the PortStateObserver
180188
self.portObserver = PortStateObserver()
181189

182190
# subscribe to all the front panel ports namespaces
183191
namespaces = multi_asic.get_front_end_namespaces()
184192
self.portObserver.subscribePortTable(namespaces)
185-
self.fp_ports = FrontPanelPorts(namespaces)
186193

187-
def updatePortLed(self, port_name, port_state):
188-
self.log_notice("Updating LED for port %s to state %s" % (port_name, port_state))
189-
self.led_control(port_name, port_state)
194+
# Discover the front panel ports
195+
fp_plist, fp_ups, lmap = self.findFrontPanelPorts(namespaces)
196+
self.fp_ports = FrontPanelPorts(fp_plist, fp_ups, lmap, led_control)
197+
198+
# Initialize the port LEDs color
199+
self.fp_ports.initPortLeds()
200+
201+
def findFrontPanelPorts(self, namespaces):
202+
# {port-index, list of logical ports}
203+
fp_port_list = [set() for _ in range(MAX_FRONT_PANEL_PORTS)]
204+
# {port-index, total subports oper UP}
205+
fp_port_up_subports = [0] * MAX_FRONT_PANEL_PORTS
206+
logical_port_mapping = {}
207+
208+
for namespace in namespaces:
209+
port_cfg_table = self.portObserver.getDatabseTable("CONFIG_DB", swsscommon.CFG_PORT_TABLE_NAME, namespace)
210+
port_st_table = self.portObserver.getDatabseTable("STATE_DB", swsscommon.STATE_PORT_TABLE_NAME, namespace)
211+
for key in port_cfg_table.getKeys():
212+
_, pcfg = port_cfg_table.get(key)
213+
_, pstate = port_st_table.get(key)
214+
pcfg_dict = dict(pcfg)
215+
pstate_dict = dict(pstate)
216+
p = Port(key,
217+
int(pcfg_dict['index']),
218+
pstate_dict.get(Port.PORT_OP_FIELD, Port.PORT_DOWN), # Current oper state
219+
pcfg_dict.get('subport', 0),
220+
pcfg_dict.get('role', None))
221+
if p.isFrontPanelPort():
222+
logical_port_mapping[key] = p
223+
self.log_notice("$$$ Port = {}".format(p))
224+
#print("port list = {}".format(self.fp_port_list))
225+
fp_port_list[p._index].add(key)
226+
if p._state == Port.PORT_UP:
227+
fp_port_up_subports[p._index] += 1
228+
return fp_port_list, fp_port_up_subports, logical_port_mapping
190229

191230
def processPortStateChange(self, port_name, port_state):
192231
if self.fp_ports.getPort(port_name):
193232
# Update the port state for front panel ports
194-
self.fp_ports.updatePortState(port_name, port_state)
195-
if self.fp_ports.areAllSubportsUp(port_name):
196-
self.updatePortLed(port_name, Port.PORT_UP)
197-
else:
198-
self.updatePortLed(port_name, Port.PORT_DOWN)
199-
233+
if self.fp_ports.updatePortState(port_name, port_state):
234+
if self.fp_ports.areAllSubportsUp(port_name):
235+
state = Port.PORT_UP
236+
else:
237+
state = Port.PORT_DOWN
238+
self.log_notice("Setting Port %s LED state change for %s" % (port_name, state))
239+
self.fp_ports.updatePortLed(port_name, state)
200240
# Run daemon
201241
def run(self):
202242
state, event = self.portObserver.getSelectEvent()
@@ -212,10 +252,10 @@ class DaemonLedd(daemon_base.DaemonBase):
212252
portEvent = self.portObserver.getPortTableEvent(event)
213253
if portEvent:
214254
self.log_notice("Received PORT table event: key=%s, state=%s" % (portEvent[0], portEvent[1]))
255+
self.processPortStateChange(portEvent[0], portEvent[1])
215256

216257
return 0
217258

218-
219259
def main():
220260
# Parse options if provided
221261
if len(sys.argv) > 1:
@@ -236,11 +276,11 @@ def main():
236276

237277
ledd = DaemonLedd()
238278

239-
# Listen indefinitely for changes to the PORT table in the Application DB's
279+
# Listen indefinitely for port oper status changes
240280
while True:
241281
if 0 != ledd.run():
242282
print("ledd.run() failed... Exiting")
243-
sys.exit(LEDUTIL_RUNTIME_ERROR)
283+
sys.exit(LEDD_SELECT_ERROR)
244284

245285
if __name__ == '__main__':
246286
main()

0 commit comments

Comments
 (0)