Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 109 additions & 5 deletions config/muxcable.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,14 +277,52 @@ def lookup_statedb_and_update_configdb(db, per_npu_statedb, config_db, port, sta
port_status_dict[port_name] = 'OK'

def update_configdb_pck_loss_data(config_db, port, val):
fvs = {}
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable name fvs is unclear. Consider using a more descriptive name like field_values or config_fields to improve code readability.

Copilot uses AI. Check for mistakes.
configdb_state = get_value_for_key_in_config_tbl(config_db, port, "state", "MUX_CABLE")
fvs["state"] = configdb_state
ipv4_value = get_value_for_key_in_config_tbl(config_db, port, "server_ipv4", "MUX_CABLE")
fvs["server_ipv4"] = ipv4_value
ipv6_value = get_value_for_key_in_config_tbl(config_db, port, "server_ipv6", "MUX_CABLE")
fvs["server_ipv6"] = ipv6_value
soc_ipv4_value = get_optional_value_for_key_in_config_tbl(config_db, port, "soc_ipv4", "MUX_CABLE")
if soc_ipv4_value is not None:
fvs["soc_ipv4"] = soc_ipv4_value
cable_type = get_optional_value_for_key_in_config_tbl(config_db, port, "cable_type", "MUX_CABLE")
if cable_type is not None:
fvs["cable_type"] = cable_type
prober_type_val = get_optional_value_for_key_in_config_tbl(config_db, port, "prober_type", "MUX_CABLE")
if prober_type_val is not None:
fvs["prober_type"] = prober_type_val

fvs["pck_loss_data_reset"] = val
try:
config_db.set_entry("MUX_CABLE", port, {"state": configdb_state,
"server_ipv4": ipv4_value, "server_ipv6": ipv6_value,
"pck_loss_data_reset": val})
config_db.set_entry("MUX_CABLE", port, fvs)
except ValueError as e:
ctx = click.get_current_context()
ctx.fail("Invalid ConfigDB. Error: {}".format(e))


def update_configdb_prober_type(config_db, port, val):
fvs = {}
configdb_state = get_value_for_key_in_config_tbl(config_db, port, "state", "MUX_CABLE")
fvs["state"] = configdb_state
ipv4_value = get_value_for_key_in_config_tbl(config_db, port, "server_ipv4", "MUX_CABLE")
fvs["server_ipv4"] = ipv4_value
ipv6_value = get_value_for_key_in_config_tbl(config_db, port, "server_ipv6", "MUX_CABLE")
fvs["server_ipv6"] = ipv6_value
soc_ipv4_value = get_optional_value_for_key_in_config_tbl(config_db, port, "soc_ipv4", "MUX_CABLE")
if soc_ipv4_value is not None:
fvs["soc_ipv4"] = soc_ipv4_value
cable_type = get_optional_value_for_key_in_config_tbl(config_db, port, "cable_type", "MUX_CABLE")
if cable_type is not None:
fvs["cable_type"] = cable_type
pck_loss_data = get_optional_value_for_key_in_config_tbl(config_db, port, "pck_loss_data_reset", "MUX_CABLE")
if pck_loss_data is not None:
fvs["pck_loss_data_reset"] = pck_loss_data

fvs["prober_type"] = val
try:
config_db.set_entry("MUX_CABLE", port, fvs)
except ValueError as e:
ctx = click.get_current_context()
ctx.fail("Invalid ConfigDB. Error: {}".format(e))
Expand Down Expand Up @@ -381,6 +419,73 @@ def mode(db, state, port, json_output):
sys.exit(CONFIG_SUCCESSFUL)


# 'muxcable' command ("config muxcable probertype hardware/software <port|all>")
@muxcable.command()
@click.argument('probertype', metavar='<operation_status>', required=True, type=click.Choice(["hardware", "software"]))
@click.argument('port', metavar='<port_name>', required=True, default=None)
@clicommon.pass_db
def probertype(db, probertype, port):
"""Config muxcable probertype"""

port = platform_sfputil_helper.get_interface_name(port, db)

port_table_keys = {}
y_cable_asic_table_keys = {}
per_npu_configdb = {}
per_npu_statedb = {}

# Getting all front asic namespace and correspding config and state DB connector

namespaces = multi_asic.get_front_end_namespaces()
for namespace in namespaces:
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
# replace these with correct macros
per_npu_configdb[asic_id] = ConfigDBConnector(use_unix_socket_path=True, namespace=namespace)
per_npu_configdb[asic_id].connect()
per_npu_statedb[asic_id] = SonicV2Connector(use_unix_socket_path=True, namespace=namespace)
per_npu_statedb[asic_id].connect(per_npu_statedb[asic_id].STATE_DB)

port_table_keys[asic_id] = per_npu_statedb[asic_id].keys(
per_npu_statedb[asic_id].STATE_DB, 'MUX_CABLE_TABLE|*')

if port is not None and port != "all":

asic_index = None
if platform_sfputil is not None:
asic_index = platform_sfputil.get_asic_id_for_logical_port(port)
if asic_index is None:
# TODO this import is only for unit test purposes, and should be removed once sonic_platform_base
# is fully mocked
import sonic_platform_base.sonic_sfp.sfputilhelper
asic_index = sonic_platform_base.sonic_sfp.sfputilhelper.SfpUtilHelper().get_asic_id_for_logical_port(port)
if asic_index is None:
click.echo("Got invalid asic index for port {}, cant retreive mux status".format(port))
sys.exit(CONFIG_FAIL)

if per_npu_statedb[asic_index] is not None:
y_cable_asic_table_keys = port_table_keys[asic_index]
logical_key = "MUX_CABLE_TABLE|{}".format(port)
if logical_key in y_cable_asic_table_keys:
update_configdb_prober_type(per_npu_configdb[asic_index], port, probertype)
sys.exit(CONFIG_SUCCESSFUL)
else:
click.echo("this is not a valid port {} present on mux_cable".format(port))
sys.exit(CONFIG_FAIL)
else:
click.echo("there is not a valid asic asic-{} table for this asic_index".format(asic_index))
sys.exit(CONFIG_FAIL)

elif port == "all" and port is not None:

for namespace in namespaces:
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
for key in port_table_keys[asic_id]:
logical_port = key.split("|")[1]
update_configdb_prober_type(per_npu_configdb[asic_id], logical_port, probertype)

sys.exit(CONFIG_SUCCESSFUL)


# 'muxcable' command ("config muxcable kill-radv <enable|disable> ")
@muxcable.command(short_help="Kill radv service when it is meant to be stopped, so no good-bye packet is sent for ceasing To Be an Advertising Interface")
@click.argument('knob', metavar='<feature_knob>', required=True, type=click.Choice(["enable", "disable"]))
Expand All @@ -396,8 +501,7 @@ def kill_radv(db, knob):
mux_lmgrd_cfg_tbl = config_db.get_table("MUX_LINKMGR")
config_db.mod_entry("MUX_LINKMGR", "SERVICE_MGMT", {"kill_radv": "True" if knob == "enable" else "False"})


#'muxcable' command ("config muxcable packetloss reset <port|all>")
# 'muxcable' command ("config muxcable packetloss reset <port|all>")
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment formatting is inconsistent. There should be a space after the '#' character to match the formatting style used elsewhere in the file.

Copilot uses AI. Check for mistakes.
@muxcable.command()
@click.argument('action', metavar='<action_name>', required=True, type=click.Choice(["reset"]))
@click.argument('port', metavar='<port_name>', required=True, default=None)
Expand Down
42 changes: 23 additions & 19 deletions show/muxcable.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ def create_table_dump_per_port_status(db, print_data, muxcable_info_dict, muxcab
print_data.append(print_port_data)


def create_table_dump_per_port_config(db ,print_data, per_npu_configdb, asic_id, port, is_dualtor_active_active):
def create_table_dump_per_port_config(db, print_data, per_npu_configdb, asic_id, port):
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function signature has been simplified by removing the is_dualtor_active_active parameter, but this change should be documented or the function should have a docstring explaining the new behavior and parameter expectations.

Copilot uses AI. Check for mistakes.

port_list = []
port_name = platform_sfputil_helper.get_interface_alias(port, db)
Expand All @@ -564,17 +564,25 @@ def create_table_dump_per_port_config(db ,print_data, per_npu_configdb, asic_id,
cable_type = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id], port, "cable_type", "MUX_CABLE")
if cable_type is not None:
port_list.append(cable_type)
else:
port_list.append("")
Comment on lines +567 to +568
Copy link

Copilot AI Sep 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The consistent handling of optional fields by appending empty strings is good for formatting, but consider using a constant for the empty string value to make the intention clearer and easier to maintain.

Copilot uses AI. Check for mistakes.
soc_ipv4_value = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id], port, "soc_ipv4", "MUX_CABLE")
if soc_ipv4_value is not None:
port_list.append(soc_ipv4_value)
is_dualtor_active_active[0] = True
else:
port_list.append("")
soc_ipv6_value = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id], port, "soc_ipv6", "MUX_CABLE")
if soc_ipv6_value is not None:
if cable_type is None:
port_list.append("")
if soc_ipv4_value is None:
port_list.append("")
port_list.append(soc_ipv6_value)
else:
port_list.append("")
prober_type_value = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id],
port, "prober_type", "MUX_CABLE")
if prober_type_value is not None:
port_list.append(prober_type_value)
else:
port_list.append("software")

print_data.append(port_list)


Expand All @@ -597,6 +605,11 @@ def create_json_dump_per_port_config(db, port_status_dict, per_npu_configdb, asi
soc_ipv6_value = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id], port, "soc_ipv6", "MUX_CABLE")
if soc_ipv6_value is not None:
port_status_dict["MUX_CABLE"]["PORTS"][port_name]["SERVER"]["soc_ipv6"] = soc_ipv6_value
prober_type_value = get_optional_value_for_key_in_config_tbl(per_npu_configdb[asic_id],
port, "prober_type", "MUX_CABLE")
if prober_type_value is not None:
port_status_dict["MUX_CABLE"]["PORTS"][port_name]["SERVER"]["prober_type"] = prober_type_value


def get_tunnel_route_per_port(db, port_tunnel_route, per_npu_configdb, per_npu_appl_db, per_npu_asic_db, asic_id, port):

Expand Down Expand Up @@ -861,21 +874,16 @@ def config(db, port, json_output):
else:
print_data = []
print_peer_tor = []
is_dualtor_active_active = [False]


create_table_dump_per_port_config(db, print_data, per_npu_configdb, asic_id, port, is_dualtor_active_active)
create_table_dump_per_port_config(db, print_data, per_npu_configdb, asic_id, port)

headers = ['SWITCH_NAME', 'PEER_TOR']
peer_tor_data = []
peer_tor_data.append(switch_name)
peer_tor_data.append(peer_switch_value)
print_peer_tor.append(peer_tor_data)
click.echo(tabulate(print_peer_tor, headers=headers))
if is_dualtor_active_active[0]:
headers = ['port', 'state', 'ipv4', 'ipv6', 'cable_type', 'soc_ipv4', 'soc_ipv6']
else:
headers = ['port', 'state', 'ipv4', 'ipv6']
headers = ['port', 'state', 'ipv4', 'ipv6', 'cable_type', 'soc_ipv4', 'soc_ipv6', 'prober_type']
click.echo(tabulate(print_data, headers=headers))

sys.exit(CONFIG_SUCCESSFUL)
Expand Down Expand Up @@ -911,23 +919,19 @@ def config(db, port, json_output):
else:
print_data = []
print_peer_tor = []
is_dualtor_active_active = [False]

for namespace in namespaces:
asic_id = multi_asic.get_asic_index_from_namespace(namespace)
for port in natsorted(port_mux_tbl_keys[asic_id]):
create_table_dump_per_port_config(db, print_data, per_npu_configdb, asic_id, port, is_dualtor_active_active)
create_table_dump_per_port_config(db, print_data, per_npu_configdb, asic_id, port)

headers = ['SWITCH_NAME', 'PEER_TOR']
peer_tor_data = []
peer_tor_data.append(switch_name)
peer_tor_data.append(peer_switch_value)
print_peer_tor.append(peer_tor_data)
click.echo(tabulate(print_peer_tor, headers=headers))
if is_dualtor_active_active[0]:
headers = ['port', 'state', 'ipv4', 'ipv6', 'cable_type', 'soc_ipv4', 'soc_ipv6']
else:
headers = ['port', 'state', 'ipv4', 'ipv6']
headers = ['port', 'state', 'ipv4', 'ipv6', 'cable_type', 'soc_ipv4', 'soc_ipv6', 'prober_type']
click.echo(tabulate(print_data, headers=headers))

sys.exit(CONFIG_SUCCESSFUL)
Expand Down
2 changes: 2 additions & 0 deletions tests/mock_tables/config_db.json
Original file line number Diff line number Diff line change
Expand Up @@ -1942,12 +1942,14 @@
},
"MUX_CABLE|Ethernet4": {
"state": "auto",
"prober_type": "software",
"server_ipv4": "10.3.1.1",
"server_ipv6": "e801::46",
"soc_ipv6": "e801::47"
},
"MUX_CABLE|Ethernet8": {
"state": "active",
"prober_type": "hardware",
"server_ipv4": "10.4.1.1",
"server_ipv6": "e802::46"
},
Expand Down
Loading
Loading