Skip to content

Commit 13ce4b6

Browse files
authored
[show][config] fix show mux status health field; add support for hwmode functionality to toggle mux, check mux direction for Y cable (sonic-net#1467)
This PR fixes the show mux status "health" field. There is also support for new commands for muxcable show muxcable hwmode muxdirection sudo config muxcable hwmode state active all which can check the muxdirection and toggle the mux direction directly through eeprom What I did Fixed the show mux status health field Also added these new commands vdahiya@BN9-0101-0301-01UT0:~$ show muxcable hwmode muxdirection Port Direction ----------- ----------- Ethernet0 active Ethernet4 active Ethernet8 active Ethernet12 active Ethernet16 active vdahiya@BN9-0101-0301-01UT0:~$ sudo config muxcable hwmode state active all Muxcables at all ports will be changed to active state. Continue? [y/N]: y Success in toggling port Ethernet0 to active Success in toggling port Ethernet4 to active Success in toggling port Ethernet8 to active Success in toggling port Ethernet12 to active Success in toggling port Ethernet16 to active Signed-off-by: vaibhav-dahiya <[email protected]>
1 parent f78e7ce commit 13ce4b6

File tree

5 files changed

+716
-77
lines changed

5 files changed

+716
-77
lines changed

config/muxcable.py

+213-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
CONFIG_SUCCESSFUL = 100
1717
CONFIG_FAIL = 1
1818

19+
VENDOR_NAME = "Credo"
20+
VENDOR_MODEL = "CAC125321P2PA0MS"
1921

2022
# Helper functions
2123

@@ -146,7 +148,7 @@ def mode(state, port, json_output):
146148

147149
if per_npu_statedb[asic_index] is not None:
148150
y_cable_asic_table_keys = port_table_keys[asic_index]
149-
logical_key = "MUX_CABLE_TABLE"+"|"+port
151+
logical_key = "MUX_CABLE_TABLE|{}".format(port)
150152
if logical_key in y_cable_asic_table_keys:
151153
port_status_dict = {}
152154
lookup_statedb_and_update_configdb(
@@ -188,11 +190,13 @@ def mode(state, port, json_output):
188190

189191
sys.exit(CONFIG_SUCCESSFUL)
190192

193+
191194
@muxcable.group(cls=clicommon.AbbreviationGroup)
192195
def prbs():
193196
"""Enable/disable PRBS mode on a port"""
194197
pass
195198

199+
196200
@prbs.command()
197201
@click.argument('port', required=True, default=None, type=click.INT)
198202
@click.argument('target', required=True, default=None, type=click.INT)
@@ -209,6 +213,7 @@ def enable(port, target, mode_value, lane_map):
209213
click.echo("PRBS config sucessful")
210214
sys.exit(CONFIG_SUCCESSFUL)
211215

216+
212217
@prbs.command()
213218
@click.argument('port', required=True, default=None, type=click.INT)
214219
@click.argument('target', required=True, default=None, type=click.INT)
@@ -223,6 +228,7 @@ def disable(port, target):
223228
click.echo("PRBS disable sucessful")
224229
sys.exit(CONFIG_SUCCESSFUL)
225230

231+
226232
@muxcable.group(cls=clicommon.AbbreviationGroup)
227233
def loopback():
228234
"""Enable/disable loopback mode on a port"""
@@ -244,6 +250,7 @@ def enable(port, target, lane_map):
244250
click.echo("loopback config sucessful")
245251
sys.exit(CONFIG_SUCCESSFUL)
246252

253+
247254
@loopback.command()
248255
@click.argument('port', required=True, default=None, type=click.INT)
249256
@click.argument('target', required=True, default=None, type=click.INT)
@@ -257,3 +264,208 @@ def disable(port, target):
257264
sys.exit(CONFIG_FAIL)
258265
click.echo("loopback disable sucessful")
259266
sys.exit(CONFIG_SUCCESSFUL)
267+
268+
269+
@muxcable.group(cls=clicommon.AbbreviationGroup)
270+
def hwmode():
271+
"""Configure muxcable hardware directly"""
272+
pass
273+
274+
275+
@hwmode.command()
276+
@click.argument('state', metavar='<operation_status>', required=True, type=click.Choice(["active", "standby"]))
277+
@click.argument('port', metavar='<port_name>', required=True, default=None)
278+
def state(state, port):
279+
"""Configure the muxcable mux state {active/standby}"""
280+
281+
per_npu_statedb = {}
282+
transceiver_table_keys = {}
283+
transceiver_dict = {}
284+
285+
# Getting all front asic namespace and correspding config and state DB connector
286+
287+
namespaces = multi_asic.get_front_end_namespaces()
288+
for namespace in namespaces:
289+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
290+
per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
291+
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
292+
293+
transceiver_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
294+
per_npu_statedb[asic_id].STATE_DB, 'TRANSCEIVER_INFO|*')
295+
296+
if port is not None and port != "all":
297+
click.confirm(('Muxcable at port {} will be changed to {} state. Continue?'.format(port, state)), abort=True)
298+
logical_port_list = platform_sfputil_helper.get_logical_list()
299+
if port not in logical_port_list:
300+
click.echo("ERR: This is not a valid port, valid ports ({})".format(", ".join(logical_port_list)))
301+
sys.exit(CONFIG_FAIL)
302+
303+
asic_index = None
304+
if platform_sfputil is not None:
305+
asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
306+
if asic_index is None:
307+
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
308+
# is fully mocked
309+
import sonic_platform_base.sonic_sfp.sfputilhelper
310+
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
311+
if asic_index is None:
312+
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
313+
sys.exit(CONFIG_FAIL)
314+
315+
if platform_sfputil is not None:
316+
physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(port)
317+
318+
if not isinstance(physical_port_list, list):
319+
click.echo(("ERR: Unable to locate physical port information for {}".format(port)))
320+
sys.exit(CONFIG_FAIL)
321+
if len(physical_port_list) != 1:
322+
click.echo("ERR: Found multiple physical ports ({}) associated with {}".format(
323+
", ".join(physical_port_list), port))
324+
sys.exit(CONFIG_FAIL)
325+
326+
transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
327+
per_npu_statedb[asic_index].STATE_DB, 'TRANSCEIVER_INFO|{}'.format(port))
328+
329+
vendor_value = get_value_for_key_in_dict(transceiver_dict[asic_index], port, "manufacturer", "TRANSCEIVER_INFO")
330+
model_value = get_value_for_key_in_dict(transceiver_dict[asic_index], port, "model", "TRANSCEIVER_INFO")
331+
332+
""" This check is required for checking whether or not this port is connected to a Y cable
333+
or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
334+
TODO: this should be removed once their is support for multiple vendors on Y cable"""
335+
336+
if vendor_value != VENDOR_NAME or model_value != VENDOR_MODEL:
337+
click.echo("ERR: Got invalid vendor value and model for port {}".format(port))
338+
sys.exit(CONFIG_FAIL)
339+
340+
physical_port = physical_port_list[0]
341+
342+
logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical()
343+
344+
logical_port_list_per_port = logical_port_list_for_physical_port.get(physical_port, None)
345+
346+
""" This check is required for checking whether or not this logical port is the one which is
347+
actually mapped to physical port and by convention it is always the first port.
348+
TODO: this should be removed with more logic to check which logical port maps to actual physical port
349+
being used"""
350+
351+
if port != logical_port_list_per_port[0]:
352+
click.echo("ERR: This logical Port {} is not on a muxcable".format(port))
353+
sys.exit(CONFIG_FAIL)
354+
355+
import sonic_y_cable.y_cable
356+
read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
357+
if read_side == False or read_side == -1:
358+
click.echo(("ERR: Unable to get read_side for the cable port {}".format(port)))
359+
sys.exit(CONFIG_FAIL)
360+
361+
mux_direction = sonic_y_cable.y_cable.check_mux_direction(physical_port)
362+
if mux_direction == False or mux_direction == -1:
363+
click.echo(("ERR: Unable to get mux direction for the cable port {}".format(port)))
364+
sys.exit(CONFIG_FAIL)
365+
366+
if int(read_side) == 1:
367+
if state == "active":
368+
res = sonic_y_cable.y_cable.toggle_mux_to_torA(physical_port)
369+
elif state == "standby":
370+
res = sonic_y_cable.y_cable.toggle_mux_to_torB(physical_port)
371+
click.echo("Success in toggling port {} to {}".format(port, state))
372+
elif int(read_side) == 2:
373+
if state == "active":
374+
res = sonic_y_cable.y_cable.toggle_mux_to_torB(physical_port)
375+
elif state == "standby":
376+
res = sonic_y_cable.y_cable.toggle_mux_to_torA(physical_port)
377+
click.echo("Success in toggling port {} to {}".format(port, state))
378+
379+
if res == False:
380+
click.echo("ERR: Unable to toggle port {} to {}".format(port, state))
381+
sys.exit(CONFIG_FAIL)
382+
383+
elif port == "all" and port is not None:
384+
385+
click.confirm(('Muxcables at all ports will be changed to {} state. Continue?'.format(state)), abort=True)
386+
logical_port_list = platform_sfputil_helper.get_logical_list()
387+
388+
rc = True
389+
for port in logical_port_list:
390+
if platform_sfputil is not None:
391+
physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(port)
392+
393+
asic_index = None
394+
if platform_sfputil is not None:
395+
asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
396+
if asic_index is None:
397+
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
398+
# is fully mocked
399+
import sonic_platform_base.sonic_sfp.sfputilhelper
400+
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
401+
if asic_index is None:
402+
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
403+
404+
if not isinstance(physical_port_list, list):
405+
click.echo(("ERR: Unable to locate physical port information for {}".format(port)))
406+
continue
407+
408+
if len(physical_port_list) != 1:
409+
click.echo("ERR: Found multiple physical ports ({}) associated with {}".format(
410+
", ".join(physical_port_list), port))
411+
continue
412+
413+
transceiver_dict[asic_index] = per_npu_statedb[asic_index].get_all(
414+
per_npu_statedb[asic_index].STATE_DB, 'TRANSCEIVER_INFO|{}'.format(port))
415+
vendor_value = transceiver_dict[asic_index].get("manufacturer", None)
416+
model_value = transceiver_dict[asic_index].get("model", None)
417+
418+
""" This check is required for checking whether or not this port is connected to a Y cable
419+
or not. The check gives a way to differentiate between non Y cable ports and Y cable ports.
420+
TODO: this should be removed once their is support for multiple vendors on Y cable"""
421+
422+
if vendor_value != VENDOR_NAME or model_value != VENDOR_MODEL:
423+
continue
424+
425+
physical_port = physical_port_list[0]
426+
427+
logical_port_list_for_physical_port = platform_sfputil_helper.get_physical_to_logical()
428+
429+
logical_port_list_per_port = logical_port_list_for_physical_port.get(physical_port, None)
430+
431+
""" This check is required for checking whether or not this logical port is the one which is
432+
actually mapped to physical port and by convention it is always the first port.
433+
TODO: this should be removed with more logic to check which logical port maps to actual physical port
434+
being used"""
435+
436+
if port != logical_port_list_per_port[0]:
437+
continue
438+
439+
import sonic_y_cable.y_cable
440+
read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
441+
if read_side == False or read_side == -1:
442+
click.echo(("ERR: Unable to get read side for the cable port {}".format(port)))
443+
rc = False
444+
continue
445+
446+
mux_direction = sonic_y_cable.y_cable.check_mux_direction(physical_port)
447+
if mux_direction == False or mux_direction == -1:
448+
click.echo(("ERR: Unable to get mux direction for the cable port {}".format(port)))
449+
rc = False
450+
continue
451+
452+
if int(read_side) == 1:
453+
if state == "active":
454+
res = sonic_y_cable.y_cable.toggle_mux_to_torA(physical_port)
455+
elif state == "standby":
456+
res = sonic_y_cable.y_cable.toggle_mux_to_torB(physical_port)
457+
click.echo("Success in toggling port {} to {}".format(port, state))
458+
elif int(read_side) == 2:
459+
if state == "active":
460+
res = sonic_y_cable.y_cable.toggle_mux_to_torB(physical_port)
461+
elif state == "standby":
462+
res = sonic_y_cable.y_cable.toggle_mux_to_torA(physical_port)
463+
click.echo("Success in toggling port {} to {}".format(port, state))
464+
465+
if res == False:
466+
rc = False
467+
click.echo("ERR: Unable to toggle port {} to {}".format(port, state))
468+
469+
if rc == False:
470+
click.echo("ERR: Unable to toggle one or more ports to {}".format(state))
471+
sys.exit(CONFIG_FAIL)

0 commit comments

Comments
 (0)