Skip to content

Commit ab39059

Browse files
authored
[xcvrd] Fix y_cable state updates from 'failure' to 'unknown' on error conditions/events (sonic-net#129)
* [xcvrd] Fix y_cable state update to unknown on erroraneous events This PR provides the support for replacing the state DB updates from 'failure' to 'unknown' in case there is an error event in the functioning of Y cable What is the motivation for this PR? the schema agreed upon with linkmgr and orchagent interaction with xcvrd, is that if there is an error event xcvrd need to fill the state DB with 'unknown' as the state value rather than 'failure', this PR handles that How did you do it? identified error scenario's in the code and made the changes Signed-off-by: vaibhav-dahiya <[email protected]>
1 parent 5d74356 commit ab39059

File tree

1 file changed

+178
-76
lines changed

1 file changed

+178
-76
lines changed

sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py

+178-76
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,19 @@
4444
SFP_STATUS_ERR_BAD_CABLE
4545
}
4646

47+
Y_CABLE_STATUS_NO_TOR_ACTIVE = 0
48+
Y_CABLE_STATUS_TORA_ACTIVE = 1
49+
Y_CABLE_STATUS_TORB_ACTIVE = 2
50+
51+
y_cable_switch_state_values = {
52+
Y_CABLE_STATUS_NO_TOR_ACTIVE,
53+
Y_CABLE_STATUS_TORA_ACTIVE,
54+
Y_CABLE_STATUS_TORB_ACTIVE
55+
}
56+
4757
# Find out the underneath physical port list by logical name
58+
59+
4860
def logical_port_name_to_physical_port_list(port_name):
4961
if port_name.startswith("Ethernet"):
5062
if y_cable_platform_sfputil.is_logical_port(port_name):
@@ -69,123 +81,194 @@ def _wrapper_get_presence(physical_port):
6981
def delete_port_from_y_cable_table(logical_port_name, y_cable_tbl):
7082
y_cable_tbl._del(logical_port_name)
7183

84+
# Delete port from Y cable status table
85+
def delete_port_from_y_cable_command_table(logical_port_name, y_cable_command_tbl):
86+
y_cable_command_tbl._del(logical_port_name)
87+
88+
def update_table_mux_status_for_response_tbl(table_name, status, logical_port_name):
89+
fvs = swsscommon.FieldValuePairs([('response', status)])
90+
table_name.set(logical_port_name, fvs)
91+
92+
93+
def update_table_mux_status_for_statedb_port_tbl(table_name, status, read_side, active_side, logical_port_name):
94+
fvs = swsscommon.FieldValuePairs([('state', status),
95+
('read_side', str(read_side)),
96+
('active_side', str(active_side))])
97+
table_name.set(logical_port_name, fvs)
98+
99+
100+
def y_cable_toggle_mux_torA(physical_port):
101+
update_status = y_cable.toggle_mux_to_torA(physical_port)
102+
if update_status is True:
103+
return 1
104+
else:
105+
helper_logger.log_warning(
106+
"Error: Could not toggle the mux for port {} to torA write eeprom failed".format(physical_port))
107+
return -1
108+
109+
110+
def y_cable_toggle_mux_torB(physical_port):
111+
update_status = y_cable.toggle_mux_to_torB(physical_port)
112+
if update_status is True:
113+
return 2
114+
else:
115+
helper_logger.log_warning(
116+
"Error: Could not toggle the mux for port {} to torB write eeprom failed".format(physical_port))
117+
return -1
118+
72119

73-
def update_tor_active_side(read_side, status, logical_port_name):
120+
def update_tor_active_side(read_side, state, logical_port_name):
74121
physical_port_list = logical_port_name_to_physical_port_list(
75122
logical_port_name)
76123

77124
if len(physical_port_list) == 1:
78125

79126
physical_port = physical_port_list[0]
80-
if int(read_side) == 1:
81-
if status == "active":
82-
y_cable.toggle_mux_to_torA(physical_port)
83-
return 1
84-
elif status == "standby":
85-
y_cable.toggle_mux_to_torB(physical_port)
86-
return 2
87-
elif int(read_side) == 2:
88-
if status == "active":
89-
y_cable.toggle_mux_to_torB(physical_port)
90-
return 2
91-
elif status == "standby":
92-
y_cable.toggle_mux_to_torA(physical_port)
93-
return 1
94-
95-
# TODO: Should we confirm that the mux was indeed toggled?
127+
if _wrapper_get_presence(physical_port):
128+
if int(read_side) == 1:
129+
if state == "active":
130+
return y_cable_toggle_mux_torA(physical_port)
131+
elif state == "standby":
132+
return y_cable_toggle_mux_torB(physical_port)
133+
elif int(read_side) == 2:
134+
if state == "active":
135+
return y_cable_toggle_mux_torB(physical_port)
136+
elif state == "standby":
137+
return y_cable_toggle_mux_torA(physical_port)
138+
139+
# TODO: Should we confirm that the mux was indeed toggled?
140+
141+
else:
142+
helper_logger.log_warning(
143+
"Error: Could not establish presence for Y cable port {} while trying to toggle the mux".format(logical_port_name))
144+
return -1
145+
96146
else:
97147
# Y cable ports should always have
98148
# one to one mapping of physical-to-logical
99149
# This should not happen
100150
helper_logger.log_warning(
101-
"Error: Retreived multiple ports for a Y cable table".format(logical_port_name))
151+
"Error: Retreived multiple ports for a Y cable table port {} while trying to toggle the mux".format(logical_port_name))
102152
return -1
103153

104154

105155
def update_appdb_port_mux_cable_response_table(logical_port_name, asic_index, appl_db):
156+
157+
status = None
158+
y_cable_response_tbl = {}
159+
160+
y_cable_response_tbl[asic_index] = swsscommon.Table(
161+
appl_db[asic_index], "MUX_CABLE_RESPONSE_TABLE")
106162
physical_port_list = logical_port_name_to_physical_port_list(
107163
logical_port_name)
108164

109165
if len(physical_port_list) == 1:
110166

111167
physical_port = physical_port_list[0]
112168
if _wrapper_get_presence(physical_port):
113-
status = None
114-
y_cable_response_tbl = {}
115-
read_side = y_cable.check_read_side(physical_port)
116-
y_cable_response_tbl[asic_index] = swsscommon.Table(
117-
appl_db[asic_index], swsscommon.APP_MUX_CABLE_RESPONSE_TABLE_NAME)
118169

119-
if not read_side:
120-
status = 'failure'
121-
122-
fvs = swsscommon.FieldValuePairs([('status', status)])
123-
y_cable_response_tbl[asic_index].set(logical_port_name, fvs)
170+
read_side = y_cable.check_read_side(physical_port)
171+
if read_side is None:
124172

173+
status = 'unknown'
174+
update_table_mux_status_for_response_tbl(y_cable_response_tbl[asic_index], status, logical_port_name)
125175
helper_logger.log_warning(
126-
"Error: Could not get read side for mux cable port probe failed {}".format(logical_port_name))
176+
"Error: Could not get read side for mux cable port probe command logical port {} and physical port {}".format(logical_port_name, physical_port))
127177
return
128178

129179
active_side = y_cable.check_active_linked_tor_side(physical_port)
130-
if not active_side:
131-
status = 'failure'
132180

133-
fvs = swsscommon.FieldValuePairs([('status', status)])
134-
y_cable_response_tbl[asic_index].set(logical_port_name, fvs)
181+
if active_side is None:
135182

183+
status = 'unknown'
184+
update_table_mux_status_for_response_tbl(y_cable_response_tbl[asic_index], status, logical_port_name)
136185
helper_logger.log_warning(
137-
"Error: Could not get active side for mux cable port probe failed {}".format(logical_port_name))
186+
"Error: Could not get active side for mux cable port probe command logical port {} and physical port {}".format(logical_port_name, physical_port))
138187
return
139188

140189
if read_side == active_side and (active_side == 1 or active_side == 2):
141190
status = 'active'
142191
elif read_side != active_side and (active_side == 1 or active_side == 2):
143192
status = 'standby'
144193
else:
145-
status = 'inactive'
146-
194+
status = 'unknown'
195+
helper_logger.log_warning(
196+
"Error: Could not get state for mux cable port probe command logical port {} and physical port {}".format(logical_port_name, physical_port))
147197

148-
fvs = swsscommon.FieldValuePairs([('status', status)])
198+
update_table_mux_status_for_response_tbl(y_cable_response_tbl[asic_index], status, logical_port_name)
149199

150-
y_cable_response_tbl[asic_index].set(logical_port_name, fvs)
151200
else:
201+
202+
status = 'unknown'
203+
update_table_mux_status_for_response_tbl(y_cable_response_tbl[asic_index], status, logical_port_name)
152204
helper_logger.log_warning(
153-
"Error: Could not establish presence for Y cable port {}".format(logical_port_name))
205+
"Error: Could not establish presence for Y cable port {} while responding to command probe".format(logical_port_name))
154206
else:
155207
# Y cable ports should always have
156208
# one to one mapping of physical-to-logical
157209
# This should not happen
210+
211+
status = 'unknown'
212+
update_table_mux_status_for_response_tbl(y_cable_response_tbl[asic_index], status, logical_port_name)
158213
helper_logger.log_warning(
159-
"Error: Retreived multiple ports for a Y cable port {}".format(logical_port_name))
214+
"Error: Retreived multiple ports for a Y cable port {} while responding to command probe".format(logical_port_name))
215+
160216

161-
def update_statedb_port_mux_status_table(logical_port_name, mux_config_tbl):
217+
def read_y_cable_and_update_statedb_port_tbl(logical_port_name, mux_config_tbl):
162218
physical_port_list = logical_port_name_to_physical_port_list(
163219
logical_port_name)
164220

221+
read_side = None
222+
active_side = None
223+
status = None
165224
if len(physical_port_list) == 1:
166225

167226
physical_port = physical_port_list[0]
168227
if _wrapper_get_presence(physical_port):
169228
read_side = y_cable.check_read_side(physical_port)
229+
if read_side is None:
230+
read_side = active_side = -1
231+
update_table_mux_status_for_statedb_port_tbl(
232+
mux_config_tbl, "unknown", read_side, active_side, logical_port_name)
233+
helper_logger.log_error(
234+
"Error: Could not establish the read side for Y cable port {}".format(logical_port_name))
235+
return
236+
170237
active_side = y_cable.check_active_linked_tor_side(physical_port)
171-
if read_side == active_side:
238+
if active_side is None or active_side not in y_cable_switch_state_values:
239+
read_side = active_side = -1
240+
update_table_mux_status_for_statedb_port_tbl(
241+
mux_config_tbl, "unknown", read_side, active_side, logical_port_name)
242+
helper_logger.log_error(
243+
"Error: Could not establish the active side for Y cable port {}".format(logical_port_name))
244+
return
245+
246+
if read_side == active_side and (active_side == 1 or active_side == 2):
172247
status = 'active'
173-
elif active_side == 0:
174-
status = 'inactive'
175-
else:
248+
elif read_side != active_side and (active_side == 1 or active_side == 2):
176249
status = 'standby'
250+
else:
251+
status = 'unknown'
252+
helper_logger.log_warning(
253+
"Error: Could not establish the active status for Y cable port {}".format(logical_port_name))
254+
255+
update_table_mux_status_for_statedb_port_tbl(
256+
mux_config_tbl, status, read_side, active_side, logical_port_name)
257+
return
177258

178-
fvs = swsscommon.FieldValuePairs([('status', status),
179-
('read_side', str(read_side)),
180-
('active_side', str(active_side))])
181-
mux_config_tbl.set(logical_port_name, fvs)
182259
else:
260+
read_side = active_side = -1
261+
update_table_mux_status_for_statedb_port_tbl(
262+
mux_config_tbl, "unknown", read_side, active_side, logical_port_name)
183263
helper_logger.log_warning(
184264
"Error: Could not establish presence for Y cable port {}".format(logical_port_name))
185265
else:
186266
# Y cable ports should always have
187267
# one to one mapping of physical-to-logical
188268
# This should not happen
269+
read_side = active_side = -1
270+
update_table_mux_status_for_statedb_port_tbl(
271+
mux_config_tbl, "unknown", read_side, active_side, logical_port_name)
189272
helper_logger.log_warning(
190273
"Error: Retreived multiple ports for a Y cable port {}".format(logical_port_name))
191274

@@ -202,26 +285,29 @@ def check_identifier_presence_and_update_mux_table_entry(state_db, port_tbl, y_c
202285
# Convert list of tuples to a dictionary
203286
mux_table_dict = dict(fvs)
204287
if "mux_cable" in mux_table_dict:
205-
y_cable_asic_table = y_cable_tbl.get(asic_index, None)
206-
if y_cable_presence[0] is True and y_cable_asic_table is not None:
207-
# fill in the newly found entry
208-
update_statedb_port_mux_status_table(
209-
logical_port_name, y_cable_tbl[asic_index])
288+
val = mux_table_dict.get("mux_cable", None)
289+
if val == "true":
210290

211-
else:
212-
# first create the state db y cable table and then fill in the entry
213-
y_cable_presence[:] = [True]
214-
namespaces = multi_asic.get_front_end_namespaces()
215-
for namespace in namespaces:
216-
asic_id = multi_asic.get_asic_index_from_namespace(
217-
namespace)
218-
state_db[asic_id] = daemon_base.db_connect(
219-
"STATE_DB", namespace)
220-
y_cable_tbl[asic_id] = swsscommon.Table(
221-
state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
222-
# fill the newly found entry
223-
update_statedb_port_mux_status_table(
224-
logical_port_name, y_cable_tbl[asic_index])
291+
y_cable_asic_table = y_cable_tbl.get(asic_index, None)
292+
if y_cable_presence[0] is True and y_cable_asic_table is not None:
293+
# fill in the newly found entry
294+
read_y_cable_and_update_statedb_port_tbl(
295+
logical_port_name, y_cable_tbl[asic_index])
296+
297+
else:
298+
# first create the state db y cable table and then fill in the entry
299+
y_cable_presence[:] = [True]
300+
namespaces = multi_asic.get_front_end_namespaces()
301+
for namespace in namespaces:
302+
asic_id = multi_asic.get_asic_index_from_namespace(
303+
namespace)
304+
state_db[asic_id] = daemon_base.db_connect(
305+
"STATE_DB", namespace)
306+
y_cable_tbl[asic_id] = swsscommon.Table(
307+
state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
308+
# fill the newly found entry
309+
read_y_cable_and_update_statedb_port_tbl(
310+
logical_port_name, y_cable_tbl[asic_index])
225311

226312

227313
def check_identifier_presence_and_delete_mux_table_entry(state_db, port_tbl, asic_index, logical_port_name, y_cable_presence, delete_change_event):
@@ -402,7 +488,7 @@ def task_worker(self):
402488
# Connect to STATE_DB and APPL_DB and get both the HW_MUX_STATUS_TABLE info
403489
appl_db, state_db, status_tbl, y_cable_tbl = {}, {}, {}, {}
404490
y_cable_tbl_keys = {}
405-
mux_cable_command_tbl = {}
491+
mux_cable_command_tbl, y_cable_command_tbl = {}, {}
406492

407493
sel = swsscommon.Select()
408494

@@ -416,6 +502,8 @@ def task_worker(self):
416502
appl_db[asic_id], swsscommon.APP_HW_MUX_CABLE_TABLE_NAME)
417503
mux_cable_command_tbl[asic_id] = swsscommon.SubscriberStateTable(
418504
appl_db[asic_id], swsscommon.APP_MUX_CABLE_COMMAND_TABLE_NAME)
505+
y_cable_command_tbl[asic_id] = swsscommon.Table(
506+
appl_db[asic_id], swsscommon.APP_MUX_CABLE_COMMAND_TABLE_NAME)
419507
state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace)
420508
y_cable_tbl[asic_id] = swsscommon.Table(
421509
state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME)
@@ -454,29 +542,38 @@ def task_worker(self):
454542

455543
fvp_dict = dict(fvp)
456544

457-
if "status" in fvp_dict:
458-
# got a status change
459-
new_status = fvp_dict["status"]
545+
if "state" in fvp_dict:
546+
# got a state change
547+
new_status = fvp_dict["state"]
460548
(status, fvs) = y_cable_tbl[asic_index].get(port)
461549
if status is False:
462550
helper_logger.log_warning("Could not retreive fieldvalue pairs for {}, inside state_db table {}".format(
463551
port, y_cable_tbl[asic_index]))
464552
continue
465553
mux_port_dict = dict(fvs)
466-
old_status = mux_port_dict.get("status")
554+
old_status = mux_port_dict.get("state")
467555
read_side = mux_port_dict.get("read_side")
468556
prev_active_side = mux_port_dict.get("active_side")
469557
# Now if the old_status does not match new_status toggle the mux appropriately
470558
if old_status != new_status:
471559
active_side = update_tor_active_side(
472560
read_side, new_status, port)
473-
fvs_updated = swsscommon.FieldValuePairs([('status', new_status),
561+
if active_side == -1:
562+
new_status = 'unknown'
563+
564+
fvs_updated = swsscommon.FieldValuePairs([('state', new_status),
474565
('read_side',
475566
read_side),
476567
('active_side', str(active_side))])
477568
y_cable_tbl[asic_index].set(port, fvs_updated)
478-
# nothing to do since no status change
479569
else:
570+
# nothing to do since no status change
571+
active_side = prev_active_side
572+
fvs_updated = swsscommon.FieldValuePairs([('state', new_status),
573+
('read_side',
574+
read_side),
575+
('active_side', str(active_side))])
576+
y_cable_tbl[asic_index].set(port, fvs_updated)
480577
helper_logger.log_warning("Got a change event on that does not toggle the TOR active side for port {} status {} active linked side = {} ".format(
481578
port, old_status, prev_active_side))
482579
else:
@@ -486,14 +583,19 @@ def task_worker(self):
486583
(port_m, op_m, fvp_m) = mux_cable_command_tbl[asic_index].pop()
487584
if fvp_m:
488585

586+
if port_m not in y_cable_tbl_keys[asic_index]:
587+
continue
588+
489589
fvp_dict = dict(fvp_m)
490590

491591
if "command" in fvp_dict:
492-
#check if xcvrd got a probe command
592+
593+
# check if xcvrd got a probe command
493594
probe_identifier = fvp_dict["command"]
494595

495596
if probe_identifier == "probe":
496597
update_appdb_port_mux_cable_response_table(port_m, asic_index, appl_db)
598+
delete_port_from_y_cable_command_table(port_m, y_cable_command_tbl[asic_index])
497599

498600
def task_run(self):
499601
self.task_thread = threading.Thread(target=self.task_worker)

0 commit comments

Comments
 (0)