Skip to content

Commit a8f3b04

Browse files
committed
Delay DOM polling until all ports are initialized
Signed-off-by: Prince George <[email protected]>
1 parent d74bc9b commit a8f3b04

File tree

1 file changed

+56
-22
lines changed

1 file changed

+56
-22
lines changed

sonic-xcvrd/xcvrd/dom/dom_mgr.py

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
from contextlib import contextmanager
88
import datetime
99

10-
1110
try:
1211
import threading
12+
import time
1313
import copy
1414
import sys
1515
import re
@@ -34,6 +34,8 @@
3434

3535
class 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

Comments
 (0)