Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the way to check port type of RJ45 port #2249

Merged
merged 22 commits into from
Jul 28, 2022
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
40 changes: 23 additions & 17 deletions scripts/intfutil
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@ import os
import re
import sys

from natsort import natsorted
from tabulate import tabulate
from utilities_common import constants
from utilities_common import multi_asic as multi_asic_util
from utilities_common.intf_filter import parse_interface_in_filter
from sonic_py_common.interface import get_intf_longname

# mock the redis for unit test purposes #
try:
if os.environ["UTILITIES_UNIT_TESTING"] == "2":
Expand All @@ -20,13 +13,23 @@ try:
sys.path.insert(0, modules_path)
sys.path.insert(0, tests_path)
import mock_tables.dbconnector
from mock_platform_sfputil.mock_platform_sfputil import mock_platform_sfputil_helper
mock_platform_sfputil_helper()
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
import mock_tables.mock_multi_asic
mock_tables.dbconnector.load_namespace_config()

except KeyError:
pass

from natsort import natsorted
from tabulate import tabulate
from utilities_common import constants
from utilities_common import multi_asic as multi_asic_util
from utilities_common.intf_filter import parse_interface_in_filter
from utilities_common.platform_sfputil_helper import is_rj45_port, RJ45_PORT_TYPE
from sonic_py_common.interface import get_intf_longname

# ========================== Common interface-utils logic ==========================


Expand All @@ -49,7 +52,7 @@ PORT_RMT_ADV_SPEEDS = 'rmt_adv_speeds'
PORT_INTERFACE_TYPE = 'interface_type'
PORT_ADV_INTERFACE_TYPES = 'adv_interface_types'
PORT_TPID = "tpid"
OPTICS_TYPE_RJ45 = 'RJ45'
OPTICS_TYPE_RJ45 = RJ45_PORT_TYPE
PORT_LINK_TRAINING = 'link_training'
PORT_LINK_TRAINING_STATUS = 'link_training_status'

Expand Down Expand Up @@ -161,10 +164,10 @@ def appl_db_port_status_get(appl_db, intf_name, status_type):
if status is None:
return "N/A"
if status_type == PORT_SPEED and status != "N/A":
optics_type = state_db_port_optics_get(appl_db, intf_name, PORT_OPTICS_TYPE)
optics_type = port_optics_get(appl_db, intf_name, PORT_OPTICS_TYPE)
status = port_speed_parse(status, optics_type)
elif status_type == PORT_ADV_SPEEDS and status != "N/A" and status != "all":
optics_type = state_db_port_optics_get(appl_db, intf_name, PORT_OPTICS_TYPE)
optics_type = port_optics_get(appl_db, intf_name, PORT_OPTICS_TYPE)
speed_list = status.split(',')
new_speed_list = []
for s in natsorted(speed_list):
Expand All @@ -181,7 +184,7 @@ def state_db_port_status_get(db, intf_name, field):
if not status:
return "N/A"
if field in [PORT_RMT_ADV_SPEEDS] and status not in ["N/A", "all"]:
optics_type = state_db_port_optics_get(db, intf_name, PORT_OPTICS_TYPE)
optics_type = port_optics_get(db, intf_name, PORT_OPTICS_TYPE)
speed_list = status.split(',')
new_speed_list = []
for s in natsorted(speed_list):
Expand All @@ -198,7 +201,7 @@ def port_oper_speed_get(db, intf_name):
if oper_speed is None or oper_speed == "N/A" or oper_status != "up":
return appl_db_port_status_get(db, intf_name, PORT_SPEED)
else:
optics_type = state_db_port_optics_get(db, intf_name, PORT_OPTICS_TYPE)
optics_type = port_optics_get(db, intf_name, PORT_OPTICS_TYPE)
return port_speed_parse(oper_speed, optics_type)

def port_oper_speed_get_raw(db, intf_name):
Expand All @@ -211,14 +214,17 @@ def port_oper_speed_get_raw(db, intf_name):
speed = db.get(db.APPL_DB, PORT_STATUS_TABLE_PREFIX + intf_name, PORT_SPEED)
return speed

def state_db_port_optics_get(state_db, intf_name, type):
def port_optics_get(state_db, intf_name, type):
"""
Get optic type info for port
"""
full_table_id = PORT_TRANSCEIVER_TABLE_PREFIX + intf_name
optics_type = state_db.get(state_db.STATE_DB, full_table_id, type)
if optics_type is None:
return "N/A"
if is_rj45_port(intf_name):
stephenxs marked this conversation as resolved.
Show resolved Hide resolved
return OPTICS_TYPE_RJ45
else:
return "N/A"
return optics_type

def merge_dicts(x,y):
Expand Down Expand Up @@ -325,13 +331,13 @@ def po_speed_dict(po_int_dict, appl_db):
# If no speed was returned, append None without format
po_list.append(None)
else:
optics_type = state_db_port_optics_get(appl_db, value[0], PORT_OPTICS_TYPE)
optics_type = port_optics_get(appl_db, value[0], PORT_OPTICS_TYPE)
interface_speed = port_speed_parse(interface_speed, optics_type)
po_list.append(interface_speed)
elif len(value) > 1:
for intf in value:
temp_speed = port_oper_speed_get_raw(appl_db, intf)
optics_type = state_db_port_optics_get(appl_db, intf, PORT_OPTICS_TYPE)
optics_type = port_optics_get(appl_db, intf, PORT_OPTICS_TYPE)
temp_speed = int(temp_speed) if temp_speed else 0
agg_speed_list.append(temp_speed)
interface_speed = sum(agg_speed_list)
Expand Down Expand Up @@ -477,7 +483,7 @@ class IntfStatus(object):
config_db_vlan_port_keys_get(self.combined_int_to_vlan_po_dict, self.front_panel_ports_list, key),
appl_db_port_status_get(self.db, key, PORT_OPER_STATUS),
appl_db_port_status_get(self.db, key, PORT_ADMIN_STATUS),
state_db_port_optics_get(self.db, key, PORT_OPTICS_TYPE),
port_optics_get(self.db, key, PORT_OPTICS_TYPE),
appl_db_port_status_get(self.db, key, PORT_PFC_ASYM_STATUS)))

for po, value in self.portchannel_speed_dict.items():
Expand Down
75 changes: 38 additions & 37 deletions scripts/sfpshow
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ from natsort import natsorted
from sonic_py_common.interface import front_panel_prefix, backplane_prefix, inband_prefix, recirc_prefix
from sonic_py_common import multi_asic
from tabulate import tabulate
from utilities_common import multi_asic as multi_asic_util

# Mock the redis DB for unit test purposes
try:
Expand All @@ -27,12 +26,17 @@ try:
sys.path.insert(0, modules_path)
sys.path.insert(0, test_path)
import mock_tables.dbconnector
from mock_platform_sfputil.mock_platform_sfputil import mock_platform_sfputil_helper
mock_platform_sfputil_helper()
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
import mock_tables.mock_multi_asic
mock_tables.dbconnector.load_namespace_config()
except KeyError:
pass

from utilities_common import multi_asic as multi_asic_util
from utilities_common.platform_sfputil_helper import is_rj45_port, RJ45_PORT_TYPE

# TODO: We should share these maps and the formatting functions between sfputil and sfpshow
QSFP_DATA_MAP = {
'model': 'Vendor PN',
Expand Down Expand Up @@ -215,8 +219,6 @@ QSFP_DD_DOM_VALUE_UNIT_MAP = {
'voltage': 'Volts'
}

RJ45_PORT_TYPE = 'RJ45'


def display_invalid_intf_eeprom(intf_name):
output = intf_name + ': SFP EEPROM Not detected\n'
Expand All @@ -231,7 +233,6 @@ def display_invalid_intf_presence(intf_name):


class SFPShow(object):

def __init__(self, intf_name, namespace_option, dump_dom=False):
super(SFPShow, self).__init__()
self.db = None
Expand Down Expand Up @@ -394,63 +395,63 @@ class SFPShow(object):
output = ''

sfp_info_dict = state_db.get_all(state_db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface_name))
if sfp_info_dict['type'] == RJ45_PORT_TYPE:
output = 'SFP EEPROM is not applicable for RJ45 port\n'
if sfp_info_dict:
if sfp_info_dict['type'] == RJ45_PORT_TYPE:
output = 'SFP EEPROM is not applicable for RJ45 port\n'
else:
output = 'SFP EEPROM detected\n'
sfp_info_output = self.convert_sfp_info_to_output_string(sfp_info_dict)
output += sfp_info_output

if dump_dom:
sfp_type = sfp_info_dict['type']
dom_info_dict = state_db.get_all(state_db.STATE_DB, 'TRANSCEIVER_DOM_SENSOR|{}'.format(interface_name))
dom_output = self.convert_dom_to_output_string(sfp_type, dom_info_dict)
output += dom_output
else:
output = 'SFP EEPROM detected\n'
sfp_info_output = self.convert_sfp_info_to_output_string(sfp_info_dict)
output += sfp_info_output

if dump_dom:
sfp_type = sfp_info_dict['type']
dom_info_dict = state_db.get_all(state_db.STATE_DB, 'TRANSCEIVER_DOM_SENSOR|{}'.format(interface_name))
dom_output = self.convert_dom_to_output_string(sfp_type, dom_info_dict)
output += dom_output
if is_rj45_port(interface_name):
stephenxs marked this conversation as resolved.
Show resolved Hide resolved
output = 'SFP EEPROM is not applicable for RJ45 port\n'
else:
output = "SFP EEPROM Not detected\n"

return output

@multi_asic_util.run_on_multi_asic
def get_eeprom(self):
if self.intf_name is not None:
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name))
if presence:
self.intf_eeprom[self.intf_name] = self.convert_interface_sfp_info_to_cli_output_string(
self.db, self.intf_name, self.dump_dom)
else:
self.intf_eeprom[self.intf_name] = "SFP EEPROM Not detected\n"
self.intf_eeprom[self.intf_name] = self.convert_interface_sfp_info_to_cli_output_string(
self.db, self.intf_name, self.dump_dom)
else:
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
for i in port_table_keys:
interface = re.split(':', i, maxsplit=1)[-1].strip()
if interface and interface.startswith(front_panel_prefix()) and not interface.startswith((backplane_prefix(), inband_prefix(), recirc_prefix())):
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface))
if presence:
self.intf_eeprom[interface] = self.convert_interface_sfp_info_to_cli_output_string(
self.db, interface, self.dump_dom)
else:
self.intf_eeprom[interface] = "SFP EEPROM Not detected\n"
self.intf_eeprom[interface] = self.convert_interface_sfp_info_to_cli_output_string(
self.db, interface, self.dump_dom)

def convert_interface_sfp_presence_state_to_cli_output_string(self, state_db, interface_name):
sfp_info_dict = state_db.get_all(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(interface_name))
if sfp_info_dict:
output = 'Present'
else:
output = 'Not present'
return output


@multi_asic_util.run_on_multi_asic
def get_presence(self):
port_table = []

if self.intf_name is not None:
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(self.intf_name))
if presence:
port_table.append((self.intf_name, 'Present'))
else:
port_table.append((self.intf_name, 'Not present'))
presence_string = self.convert_interface_sfp_presence_state_to_cli_output_string(self.db, self.intf_name)
port_table.append((self.intf_name, presence_string))
else:
port_table_keys = self.db.keys(self.db.APPL_DB, "PORT_TABLE:*")
for i in port_table_keys:
key = re.split(':', i, maxsplit=1)[-1].strip()
if key and key.startswith(front_panel_prefix()) and not key.startswith((backplane_prefix(), inband_prefix(), recirc_prefix())):
presence = self.db.exists(self.db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(key))
if presence:
port_table.append((key, 'Present'))
else:
port_table.append((key, 'Not present'))
presence_string = self.convert_interface_sfp_presence_state_to_cli_output_string(self.db, key)
port_table.append((key, presence_string))

self.table += port_table

Expand Down
39 changes: 15 additions & 24 deletions sfputil/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import click
import sonic_platform
import sonic_platform_base.sonic_sfp.sfputilhelper
from sonic_platform_base.sfp_base import SfpBase
from swsscommon.swsscommon import SonicV2Connector
from natsort import natsorted
from sonic_py_common import device_info, logger, multi_asic
Expand Down Expand Up @@ -291,27 +292,16 @@ def is_sfp_present(port_name):
return bool(presence)


# Below defined two flavors of functions to determin whether a port is a RJ45 port.
# They serve different types of SFP utilities. One type of SFP utility consume the
# info stored in the STATE_DB, these utilities shall call 'is_rj45_port_from_db'
# to judge the port type. Another type of utilities will call the platform API
# directly to access SFP, for them shall use 'is_rj45_port_from_api'.
def is_rj45_port_from_db(port_name, db):
intf_type = db.get(db.STATE_DB, 'TRANSCEIVER_INFO|{}'.format(port_name), 'type')
return intf_type == RJ45_PORT_TYPE


def is_rj45_port_from_api(port_name):
stephenxs marked this conversation as resolved.
Show resolved Hide resolved
physical_port = logical_port_to_physical_port_index(port_name)
sfp = platform_chassis.get_sfp(physical_port)

try:
port_type = sfp.get_transceiver_info()['type']
port_types = platform_chassis.get_port_or_cage_type(physical_port)
return SfpBase.SFP_PORT_TYPE_BIT_RJ45 == port_types
except NotImplementedError:
click.echo("Not able to judge the port type due to get_transceiver_info not implemented!", err=True)
sys.exit(ERROR_NOT_IMPLEMENTED)
pass

return port_type == RJ45_PORT_TYPE
return False


def skip_if_port_is_rj45(port_name):
stephenxs marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -725,6 +715,7 @@ def presence(port):

logical_port_list = [port]

logical_port_list = natsort.natsorted(logical_port_list)
for logical_port_name in logical_port_list:
ganged = False
i = 1
Expand Down Expand Up @@ -843,7 +834,7 @@ def fetch_error_status_from_state_db(port, state_db):
sorted_ports = natsort.natsorted(status)
output = []
for port in sorted_ports:
if is_rj45_port_from_db(port, state_db):
if is_rj45_port_from_api(port):
description = "N/A"
else:
statestring = status[port].get('status')
Expand Down Expand Up @@ -1226,12 +1217,12 @@ def download_firmware(port_name, filepath):
def run(port_name, mode):
"""Run the firmware with default mode=1"""

skip_if_port_is_rj45(port_name)
stephenxs marked this conversation as resolved.
Show resolved Hide resolved

if not is_sfp_present(port_name):
click.echo("{}: SFP EEPROM not detected\n".format(port_name))
sys.exit(EXIT_FAIL)

skip_if_port_is_rj45(port_name)

status = run_firmware(port_name, int(mode))
if status != 1:
click.echo('Failed to run firmware in mode={}! CDB status: {}'.format(mode, status))
Expand All @@ -1245,12 +1236,12 @@ def run(port_name, mode):
def commit(port_name):
"""Commit the running firmware"""

skip_if_port_is_rj45(port_name)
stephenxs marked this conversation as resolved.
Show resolved Hide resolved

if not is_sfp_present(port_name):
click.echo("{}: SFP EEPROM not detected\n".format(port_name))
sys.exit(EXIT_FAIL)

skip_if_port_is_rj45(port_name)

status = commit_firmware(port_name)
if status != 1:
click.echo('Failed to commit firmware! CDB status: {}'.format(status))
Expand All @@ -1267,12 +1258,12 @@ def upgrade(port_name, filepath):

physical_port = logical_port_to_physical_port_index(port_name)

skip_if_port_is_rj45(port_name)

if not is_sfp_present(port_name):
click.echo("{}: SFP EEPROM not detected\n".format(port_name))
sys.exit(EXIT_FAIL)

skip_if_port_is_rj45(port_name)

show_firmware_version(physical_port)

status = download_firmware(port_name, filepath)
Expand Down Expand Up @@ -1303,12 +1294,12 @@ def upgrade(port_name, filepath):
def download(port_name, filepath):
"""Download firmware on the transceiver"""

skip_if_port_is_rj45(port_name)

if not is_sfp_present(port_name):
click.echo("{}: SFP EEPROM not detected\n".format(port_name))
sys.exit(EXIT_FAIL)

skip_if_port_is_rj45(port_name)

start = time.time()
status = download_firmware(port_name, filepath)
if status == 1:
Expand Down
Loading