Skip to content

Commit 4f5bbbe

Browse files
authored
[show][config] cli support for firmware upgrade on Y-Cable (sonic-net#1528) (sonic-net#1558)
* [show][config] cli support for firmware upgrade on Y-Cable (sonic-net#1528) Summary: This PR provides the support for adding CLI commands for activatie, download, upgrade firmware on the Y-cable In particular these Cli commands are supported: sudo config muxcable firmware download Ethernet0 sudo config muxcable firmware rollback Ethernet0 sudo config muxcable firmware download ~/AEC_WYOMING_B52Yb0_MS_0.6_20201218.bin Ethernet0 Signed-off-by: vaibhav-dahiya [email protected] What I did Added the support for firmware upgrade CLI on Y cable How I did it added the changes in sonic-utilities/show and sonic-utilities/config by changing the muxcable.py Signed-off-by: vaibhav-dahiya <[email protected]>
1 parent a5b5285 commit 4f5bbbe

File tree

3 files changed

+423
-4
lines changed

3 files changed

+423
-4
lines changed

config/muxcable.py

+233-2
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ def setswitchmode(state, port):
487487
namespaces = multi_asic.get_front_end_namespaces()
488488
for namespace in namespaces:
489489
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
490-
per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
490+
per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
491491
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
492492

493493
if port is not None and port != "all":
@@ -549,11 +549,11 @@ def setswitchmode(state, port):
549549
click.echo("ERR: This logical Port {} is not on a muxcable".format(port))
550550
sys.exit(CONFIG_FAIL)
551551

552+
import sonic_y_cable.y_cable
552553
if state == "auto":
553554
mode = sonic_y_cable.y_cable.SWITCHING_MODE_AUTO
554555
elif state == "manual":
555556
mode = sonic_y_cable.y_cable.SWITCHING_MODE_MANUAL
556-
import sonic_y_cable.y_cable
557557
result = sonic_y_cable.y_cable.set_switching_mode(physical_port, mode)
558558
if result == False:
559559
click.echo(("ERR: Unable to set switching mode for the cable port {}".format(port)))
@@ -632,3 +632,234 @@ def setswitchmode(state, port):
632632
if rc == False:
633633
click.echo("ERR: Unable to set switching mode one or more ports to {}".format(state))
634634
sys.exit(CONFIG_FAIL)
635+
636+
637+
def get_per_npu_statedb(per_npu_statedb, port_table_keys):
638+
639+
# Getting all front asic namespace and correspding config and state DB connector
640+
641+
namespaces = multi_asic.get_front_end_namespaces()
642+
for namespace in namespaces:
643+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
644+
# replace these with correct macros
645+
per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
646+
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
647+
648+
port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
649+
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')
650+
651+
652+
def get_physical_port_list(port):
653+
654+
physical_port_list = []
655+
if platform_sfputil is not None:
656+
physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(port)
657+
658+
asic_index = None
659+
if platform_sfputil is not None:
660+
asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
661+
if asic_index is None:
662+
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
663+
# is fully mocked
664+
import sonic_platform_base.sonic_sfp.sfputilhelper
665+
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
666+
if asic_index is None:
667+
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
668+
669+
if not isinstance(physical_port_list, list):
670+
click.echo(("ERR: Unable to locate physical port information for {}".format(port)))
671+
sys.exit(CONFIG_FAIL)
672+
673+
if len(physical_port_list) != 1:
674+
click.echo("ERR: Found multiple physical ports ({}) associated with {}".format(
675+
", ".join(physical_port_list), port))
676+
sys.exit(CONFIG_FAIL)
677+
678+
return (physical_port_list, asic_index)
679+
680+
681+
def perform_download_firmware(physical_port, fwfile, port):
682+
import sonic_y_cable.y_cable
683+
result = sonic_y_cable.y_cable.download_firmware(physical_port, fwfile)
684+
if result == sonic_y_cable.y_cable.FIRMWARE_DOWNLOAD_SUCCESS:
685+
click.echo("firmware download successful {}".format(port))
686+
return True
687+
else:
688+
click.echo("firmware download failure {}".format(port))
689+
return False
690+
691+
692+
def perform_activate_firmware(physical_port, port):
693+
import sonic_y_cable.y_cable
694+
result = sonic_y_cable.y_cable.activate_firmware(physical_port)
695+
if result == sonic_y_cable.y_cable.FIRMWARE_ACTIVATE_SUCCESS:
696+
click.echo("firmware activate successful for {}".format(port))
697+
return True
698+
else:
699+
click.echo("firmware activate failure for {}".format(port))
700+
return False
701+
702+
703+
def perform_rollback_firmware(physical_port, port):
704+
import sonic_y_cable.y_cable
705+
result = sonic_y_cable.y_cable.rollback_firmware(physical_port)
706+
if result == sonic_y_cable.y_cable.FIRMWARE_ROLLBACK_SUCCESS:
707+
click.echo("firmware rollback successful {}".format(port))
708+
return True
709+
else:
710+
click.echo("firmware rollback failure {}".format(port))
711+
return False
712+
713+
714+
@muxcable.group(cls=clicommon.AbbreviationGroup)
715+
def firmware():
716+
"""Configure muxcable firmware command"""
717+
pass
718+
719+
720+
@firmware.command()
721+
@click.argument('fwfile', metavar='<firmware_file>', required=True)
722+
@click.argument('port', metavar='<port_name>', required=True, default=None)
723+
def download(fwfile, port):
724+
"""Config muxcable firmware download"""
725+
726+
per_npu_statedb = {}
727+
y_cable_asic_table_keys = {}
728+
port_table_keys = {}
729+
730+
get_per_npu_statedb(per_npu_statedb, port_table_keys)
731+
732+
if port is not None and port != "all":
733+
734+
physical_port_list = []
735+
physical_port_list, asic_index = get_physical_port_list(port)
736+
physical_port = physical_port_list[0]
737+
if per_npu_statedb[asic_index] is not None:
738+
y_cable_asic_table_keys = port_table_keys[asic_index]
739+
logical_key = "MUX_CABLE_TABLE|{}".format(port)
740+
if logical_key in y_cable_asic_table_keys:
741+
perform_download_firmware(physical_port, fwfile, port)
742+
743+
else:
744+
click.echo("this is not a valid port present on mux_cable".format(port))
745+
sys.exit(CONFIG_FAIL)
746+
else:
747+
click.echo("there is not a valid asic table for this asic_index".format(asic_index))
748+
sys.exit(CONFIG_FAIL)
749+
750+
elif port == "all" and port is not None:
751+
752+
rc = CONFIG_SUCCESSFUL
753+
for namespace in namespaces:
754+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
755+
for key in port_table_keys[asic_id]:
756+
port = key.split("|")[1]
757+
758+
physical_port_list = []
759+
(physical_port_list, asic_index) = get_physical_port_list(port)
760+
761+
physical_port = physical_port_list[0]
762+
763+
status = perform_download_firmware(physical_port, fwfile, port)
764+
765+
if status is not True:
766+
rc = CONFIG_FAIL
767+
768+
sys.exit(rc)
769+
770+
771+
@firmware.command()
772+
@click.argument('port', metavar='<port_name>', required=True, default=None)
773+
def activate(port):
774+
"""Config muxcable firmware activate"""
775+
776+
per_npu_statedb = {}
777+
y_cable_asic_table_keys = {}
778+
port_table_keys = {}
779+
780+
get_per_npu_statedb(per_npu_statedb, port_table_keys)
781+
782+
if port is not None and port != "all":
783+
784+
physical_port_list = []
785+
(physical_port_list, asic_index) = get_physical_port_list(port)
786+
physical_port = physical_port_list[0]
787+
if per_npu_statedb[asic_index] is not None:
788+
y_cable_asic_table_keys = port_table_keys[asic_index]
789+
logical_key = "MUX_CABLE_TABLE|{}".format(port)
790+
if logical_key in y_cable_asic_table_keys:
791+
perform_activate_firmware(physical_port, port)
792+
793+
else:
794+
click.echo("this is not a valid port present on mux_cable".format(port))
795+
sys.exit(CONFIG_FAIL)
796+
else:
797+
click.echo("there is not a valid asic table for this asic_index".format(asic_index))
798+
sys.exit(CONFIG_FAIL)
799+
800+
elif port == "all" and port is not None:
801+
802+
rc = CONFIG_SUCCESSFUL
803+
for namespace in namespaces:
804+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
805+
for key in port_table_keys[asic_id]:
806+
port = key.split("|")[1]
807+
808+
physical_port_list = []
809+
810+
(physical_port_list, asic_index) = get_physical_port_list(port)
811+
physical_port = physical_port_list[0]
812+
status = perform_activate_firmware(physical_port, port)
813+
814+
if status is not True:
815+
rc = CONFIG_FAIL
816+
817+
sys.exit(rc)
818+
819+
820+
@firmware.command()
821+
@click.argument('port', metavar='<port_name>', required=True, default=None)
822+
def rollback(port):
823+
"""Config muxcable firmware rollback"""
824+
825+
port_table_keys = {}
826+
y_cable_asic_table_keys = {}
827+
per_npu_statedb = {}
828+
829+
get_per_npu_statedb(per_npu_statedb, port_table_keys)
830+
831+
if port is not None and port != "all":
832+
833+
physical_port_list = []
834+
(physical_port_list, asic_index) = get_physical_port_list(port)
835+
physical_port = physical_port_list[0]
836+
if per_npu_statedb[asic_index] is not None:
837+
y_cable_asic_table_keys = port_table_keys[asic_index]
838+
logical_key = "MUX_CABLE_TABLE|{}".format(port)
839+
if logical_key in y_cable_asic_table_keys:
840+
perform_rollback_firmware(physical_port, port)
841+
842+
else:
843+
click.echo("this is not a valid port present on mux_cable".format(port))
844+
sys.exit(CONFIG_FAIL)
845+
else:
846+
click.echo("there is not a valid asic table for this asic_index".format(asic_index))
847+
sys.exit(CONFIG_FAIL)
848+
849+
elif port == "all" and port is not None:
850+
851+
rc = CONFIG_SUCCESSFUL
852+
for namespace in namespaces:
853+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
854+
for key in port_table_keys[asic_id]:
855+
port = key.split("|")[1]
856+
857+
physical_port_list = []
858+
(physical_port_list, asic_index) = get_physical_port_list(port)
859+
physical_port = physical_port_list[0]
860+
status = perform_rollback_firmware(physical_port, port)
861+
862+
if status is not True:
863+
rc = CONFIG_FAIL
864+
865+
sys.exit(rc)

show/muxcable.py

+106-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from natsort import natsorted
99
from sonic_py_common import multi_asic
1010
from swsscommon import swsscommon
11-
from swsssdk import ConfigDBConnector
11+
from swsscommon.swsscommon import ConfigDBConnector
1212
from tabulate import tabulate
1313
from utilities_common import platform_sfputil_helper
1414

@@ -660,7 +660,7 @@ def switchmode(port):
660660
namespaces = multi_asic.get_front_end_namespaces()
661661
for namespace in namespaces:
662662
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
663-
per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
663+
per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=False, namespace=namespace)
664664
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
665665

666666
if port is not None:
@@ -821,3 +821,107 @@ def switchmode(port):
821821
click.echo(tabulate(body, headers=headers))
822822
if rc == False:
823823
sys.exit(EXIT_FAIL)
824+
825+
826+
def get_firmware_dict(physical_port, target, side, mux_info_dict):
827+
828+
import sonic_y_cable.y_cable
829+
result = sonic_y_cable.y_cable.get_firmware_version(physical_port, target)
830+
831+
if result is not None and isinstance(result, dict):
832+
mux_info_dict[("version_{}_active".format(side))] = result.get("version_active", None)
833+
mux_info_dict[("version_{}_inactive".format(side))] = result.get("version_inactive", None)
834+
mux_info_dict[("version_{}_next".format(side))] = result.get("version_next", None)
835+
836+
else:
837+
mux_info_dict[("version_{}_active".format(side))] = "N/A"
838+
mux_info_dict[("version_{}_inactive".format(side))] = "N/A"
839+
mux_info_dict[("version_{}_next".format(side))] = "N/A"
840+
841+
842+
@muxcable.group(cls=clicommon.AbbreviationGroup)
843+
def firmware():
844+
"""Show muxcable firmware command"""
845+
pass
846+
847+
848+
@firmware.command()
849+
@click.argument('port', metavar='<port_name>', required=True, default=None)
850+
def version(port):
851+
"""Show muxcable firmware version"""
852+
853+
port_table_keys = {}
854+
y_cable_asic_table_keys = {}
855+
per_npu_statedb = {}
856+
physical_port_list = []
857+
858+
# Getting all front asic namespace and correspding config and state DB connector
859+
860+
namespaces = multi_asic.get_front_end_namespaces()
861+
for namespace in namespaces:
862+
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
863+
# replace these with correct macros
864+
per_npu_statedb[asic_id] = swsscommon.SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
865+
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)
866+
867+
port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
868+
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')
869+
870+
if port is not None:
871+
872+
logical_port_list = platform_sfputil_helper.get_logical_list()
873+
874+
if port not in logical_port_list:
875+
click.echo(("ERR: Not a valid logical port for muxcable firmware {}".format(port)))
876+
sys.exit(CONFIG_FAIL)
877+
878+
asic_index = None
879+
if platform_sfputil is not None:
880+
asic_index = platform_sfputil_helper.get_asic_id_for_logical_port(port)
881+
if asic_index is None:
882+
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
883+
# is fully mocked
884+
import sonic_platform_base.sonic_sfp.sfputilhelper
885+
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
886+
if asic_index is None:
887+
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
888+
889+
if platform_sfputil is not None:
890+
physical_port_list = platform_sfputil_helper.logical_port_name_to_physical_port_list(port)
891+
892+
if not isinstance(physical_port_list, list):
893+
click.echo(("ERR: Unable to locate physical port information for {}".format(port)))
894+
sys.exit(CONFIG_FAIL)
895+
896+
if len(physical_port_list) != 1:
897+
click.echo("ERR: Found multiple physical ports ({}) associated with {}".format(
898+
", ".join(physical_port_list), port))
899+
sys.exit(CONFIG_FAIL)
900+
901+
mux_info_dict = {}
902+
physical_port = physical_port_list[0]
903+
if per_npu_statedb[asic_index] is not None:
904+
y_cable_asic_table_keys = port_table_keys[asic_index]
905+
logical_key = "MUX_CABLE_TABLE|{}".format(port)
906+
import sonic_y_cable.y_cable
907+
read_side = sonic_y_cable.y_cable.check_read_side(physical_port)
908+
if logical_key in y_cable_asic_table_keys:
909+
if read_side == 1:
910+
get_firmware_dict(physical_port, 1, "self", mux_info_dict)
911+
get_firmware_dict(physical_port, 2, "peer", mux_info_dict)
912+
get_firmware_dict(physical_port, 0, "nic", mux_info_dict)
913+
click.echo("{}".format(json.dumps(mux_info_dict, indent=4)))
914+
elif read_side == 2:
915+
get_firmware_dict(physical_port, 2, "self", mux_info_dict)
916+
get_firmware_dict(physical_port, 1, "peer", mux_info_dict)
917+
get_firmware_dict(physical_port, 0, "nic", mux_info_dict)
918+
click.echo("{}".format(json.dumps(mux_info_dict, indent=4)))
919+
else:
920+
click.echo("Did not get a valid read_side for muxcable".format(port))
921+
sys.exit(CONFIG_FAIL)
922+
923+
else:
924+
click.echo("this is not a valid port present on mux_cable".format(port))
925+
sys.exit(CONFIG_FAIL)
926+
else:
927+
click.echo("there is not a valid asic table for this asic_index".format(asic_index))

0 commit comments

Comments
 (0)