@@ -10,7 +10,6 @@ import sys
10
10
11
11
from sonic_py_common import daemon_base
12
12
from sonic_py_common import multi_asic
13
- #from sonic_py_common.interface import backplane_prefix, inband_prefix, recirc_prefix
14
13
from swsscommon import swsscommon
15
14
16
15
#============================= Constants =============================
@@ -34,56 +33,59 @@ SELECT_TIMEOUT = 1000
34
33
35
34
LEDUTIL_LOAD_ERROR = 1
36
35
LEDUTIL_RUNTIME_ERROR = 2
36
+ LEDD_SELECT_ERROR = 3
37
37
38
- MAX_FRONT_PANEL_PORTS = 64 + 1
38
+ MAX_FRONT_PANEL_PORTS = 256
39
39
40
40
class Port ():
41
41
PORT_UP = "up" # All subports are up
42
42
PORT_DOWN = "down" # All subports are down
43
+ PORT_OP_FIELD = "netdev_oper_status"
43
44
44
45
def __init__ (self , name , index , state , subport , role ):
45
46
self ._name = name
46
47
self ._index = index
47
48
self ._state = state
48
49
self ._subport = subport
49
50
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 )
51
55
52
56
def isFrontPanelPort (self ):
53
- return self .is_front_panel_port
57
+ return multi_asic .is_front_panel_port ( self . _name , self . _role )
54
58
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 ):
58
60
# {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 )
62
78
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 )
82
84
83
85
def getPort (self , name ):
84
86
if name in self .logical_port_mapping :
85
87
port = self .logical_port_mapping [name ]
86
- return port if port . isFrontPanelPort () else None
88
+ return port
87
89
return None
88
90
89
91
def areAllSubportsUp (self , name ):
@@ -106,15 +108,20 @@ class FrontPanelPorts:
106
108
return 0
107
109
108
110
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
118
125
119
126
class PortStateObserver :
120
127
def __init__ (self ):
@@ -154,49 +161,82 @@ class PortStateObserver:
154
161
if fvp :
155
162
if key in ["PortConfigDone" , "PortInitDone" ]:
156
163
return None
157
- if op == "SET" and "oper_status" in fvp_dict :
158
- fvp_dict = dict (fvp )
159
- return (key , fvp_dict ["oper_status" ])
160
164
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 ])
162
168
169
+ return None
163
170
164
171
class DaemonLedd (daemon_base .DaemonBase ):
165
172
def __init__ (self ):
166
173
daemon_base .DaemonBase .__init__ (self , SYSLOG_IDENTIFIER )
167
174
175
+ if multi_asic .is_multi_asic ():
176
+ # Load the namespace details first from the database_global.json file.
177
+ swsscommon .SonicDBConfig .initializeGlobalConfig ()
178
+
168
179
# Load platform-specific LedControl module
169
180
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 )
171
182
except Exception as e :
172
183
self .log_error ("Failed to load ledutil: %s" % (str (e )), True )
173
184
sys .exit (LEDUTIL_LOAD_ERROR )
174
185
175
- if multi_asic .is_multi_asic ():
176
- # Load the namespace details first from the database_global.json file.
177
- swsscommon .SonicDBConfig .initializeGlobalConfig ()
178
186
179
187
# Initialize the PortStateObserver
180
188
self .portObserver = PortStateObserver ()
181
189
182
190
# subscribe to all the front panel ports namespaces
183
191
namespaces = multi_asic .get_front_end_namespaces ()
184
192
self .portObserver .subscribePortTable (namespaces )
185
- self .fp_ports = FrontPanelPorts (namespaces )
186
193
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
190
229
191
230
def processPortStateChange (self , port_name , port_state ):
192
231
if self .fp_ports .getPort (port_name ):
193
232
# 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 )
200
240
# Run daemon
201
241
def run (self ):
202
242
state , event = self .portObserver .getSelectEvent ()
@@ -212,10 +252,10 @@ class DaemonLedd(daemon_base.DaemonBase):
212
252
portEvent = self .portObserver .getPortTableEvent (event )
213
253
if portEvent :
214
254
self .log_notice ("Received PORT table event: key=%s, state=%s" % (portEvent [0 ], portEvent [1 ]))
255
+ self .processPortStateChange (portEvent [0 ], portEvent [1 ])
215
256
216
257
return 0
217
258
218
-
219
259
def main ():
220
260
# Parse options if provided
221
261
if len (sys .argv ) > 1 :
@@ -236,11 +276,11 @@ def main():
236
276
237
277
ledd = DaemonLedd ()
238
278
239
- # Listen indefinitely for changes to the PORT table in the Application DB's
279
+ # Listen indefinitely for port oper status changes
240
280
while True :
241
281
if 0 != ledd .run ():
242
282
print ("ledd.run() failed... Exiting" )
243
- sys .exit (LEDUTIL_RUNTIME_ERROR )
283
+ sys .exit (LEDD_SELECT_ERROR )
244
284
245
285
if __name__ == '__main__' :
246
286
main ()
0 commit comments