77from contextlib import contextmanager
88import datetime
99
10-
1110try :
1211 import threading
12+ import time
1313 import copy
1414 import sys
1515 import re
3434
3535class DomInfoUpdateTask (threading .Thread ):
3636 DOM_INFO_UPDATE_PERIOD_SECS = 60
37+ DOM_WAIT_PORT_INITIALIZATION_POLL_SECS = 60
38+ DOM_WAIT_PORT_INIT_TIMEOUT_SECS = 300
3739 DIAG_DB_UPDATE_TIME_AFTER_LINK_CHANGE = 1
3840 DOM_PORT_CHG_OBSERVER_TBL_MAP = [
3941 {'APPL_DB' : 'PORT_TABLE' , 'FILTER' : ['flap_count' ]},
@@ -198,6 +200,52 @@ def post_port_pm_info_to_db(self, logical_port_name, port_mapping, table, stop_e
198200 else :
199201 return xcvrd .SFP_EEPROM_NOT_READY
200202
203+ def wait_port_initialization (self , timeout_secs ):
204+ logical_port_set = set (self .port_mapping .logical_port_list )
205+
206+ dom_wait_time_end = datetime .datetime .now () + datetime .timedelta (seconds = timeout_secs )
207+
208+ while not self .task_stopping_event .is_set () and logical_port_set :
209+ time .sleep (self .DOM_WAIT_PORT_INITIALIZATION_POLL_SECS )
210+
211+ for logical_port_name in list (logical_port_set ):
212+ # Get the asic to which this port belongs
213+ asic_index = self .port_mapping .get_asic_id_for_logical_port (logical_port_name )
214+ if asic_index is None :
215+ self .log_warning ("Got invalid asic index for {}, ignored" .format (logical_port_name ))
216+ logical_port_set .remove (logical_port_name )
217+ continue
218+
219+ physical_port_list = self .port_mapping .get_logical_to_physical (logical_port_name )
220+ if not physical_port_list :
221+ self .log_warning ("Failed to find physical port for lport {}" .format (logical_port_name ))
222+ logical_port_set .remove (logical_port_name )
223+ continue
224+
225+ physical_port = physical_port_list [0 ]
226+ if not self .xcvrd_utils .get_transceiver_presence (physical_port ):
227+ logical_port_set .remove (logical_port_name )
228+ continue
229+
230+ # Read the CMIS state machine's SW state from the DB
231+ sw_status_tbl = self .xcvr_table_helper .get_status_sw_tbl (asic_index )
232+ cmis_state = xcvrd .get_cmis_state_from_state_db (logical_port_name , sw_status_tbl )
233+
234+ if cmis_state is None :
235+ logical_port_set .remove (logical_port_name )
236+ continue
237+
238+ if cmis_state in xcvrd .CMIS_TERMINAL_STATES :
239+ logical_port_set .remove (logical_port_name )
240+ continue
241+
242+ if logical_port_set :
243+ self .log_debug ("wait_port_initialization() still waiting for {} ports to be initialized" .format (logical_port_set ))
244+ if datetime .datetime .now () > dom_wait_time_end :
245+ break
246+
247+ return logical_port_set
248+
201249 def task_worker (self ):
202250 self .log_notice ("Start DOM monitoring loop" )
203251 sel , asic_context = port_event_helper .subscribe_port_config_change (self .namespaces )
@@ -207,20 +255,16 @@ def task_worker(self):
207255 self .on_port_update_event ,
208256 port_tbl_map = self .DOM_PORT_CHG_OBSERVER_TBL_MAP )
209257
210- # Set the periodic db update time
211- dom_info_update_periodic_secs = self .DOM_INFO_UPDATE_PERIOD_SECS
212-
213- # Adding dom_info_update_periodic_secs to allow xcvrd to initialize ports
214- # before starting the periodic update
215- next_periodic_db_update_time = datetime . datetime . now () + datetime . timedelta ( seconds = dom_info_update_periodic_secs )
216- is_periodic_db_update_needed = False
258+ # Wait for all PORTs to be initialized
259+ remaining_ports = self .wait_port_initialization ( self . DOM_WAIT_PORT_INIT_TIMEOUT_SECS )
260+ if remaining_ports :
261+ self . log_error ( "wait_port_initialization() timed out after {} seconds, remaining ports: {}" . format (
262+ self . DOM_WAIT_PORT_INIT_TIMEOUT_SECS , remaining_ports ))
263+ else :
264+ self . log_notice ( "All ports are in CMIS terminal state, start DOM monitoring" )
217265
218266 # Start loop to update dom info in DB periodically and handle port change events
219267 while not self .task_stopping_event .is_set ():
220- # Check if periodic db update is needed
221- if next_periodic_db_update_time <= datetime .datetime .now ():
222- is_periodic_db_update_needed = True
223-
224268 # Handle port change event from main thread
225269 port_event_helper .handle_port_config_change (sel , asic_context , self .task_stopping_event , self .port_mapping , self .helper_logger , self .on_port_config_change )
226270
@@ -244,10 +288,6 @@ def task_worker(self):
244288 self .log_notice ("Stop event generated during DOM monitoring loop" )
245289 break
246290
247- if not is_periodic_db_update_needed :
248- # If periodic db update is not needed, skip the rest of the loop
249- continue
250-
251291 # Get the first logical port name since it corresponds to the first subport
252292 # of the breakout group
253293 logical_port_name = logical_ports [0 ]
@@ -324,12 +364,6 @@ def task_worker(self):
324364 self .log_warning ("Got exception {} while processing pm info for port {}, ignored" .format (repr (e ), logical_port_name ))
325365 continue
326366
327- # Set the periodic db update time after all the ports are processed
328- if is_periodic_db_update_needed :
329- next_periodic_db_update_time = datetime .datetime .now () + \
330- datetime .timedelta (seconds = dom_info_update_periodic_secs )
331- is_periodic_db_update_needed = False
332-
333367 self .log_notice ("Stop DOM monitoring loop" )
334368
335369 def run (self ):
0 commit comments