-
Notifications
You must be signed in to change notification settings - Fork 650
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
Add transceiver info CLI support to show output from TRANSCEIVER_INFO for ZR #2630
Changes from 5 commits
df6d587
9e2e3e2
0c219ac
2bb4eec
686603e
b6aa0e0
df975e1
2a73595
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ 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 utilities_common.sfp_helper import covert_application_advertisement_to_output_string | ||
from utilities_common.sfp_helper import QSFP_DATA_MAP | ||
from utilities_common.sfp_helper import QSFP_DATA_MAP, CMIS_DATA_MAP | ||
from tabulate import tabulate | ||
|
||
# Mock the redis DB for unit test purposes | ||
|
@@ -280,8 +280,26 @@ class SFPShow(object): | |
units) | ||
return output | ||
|
||
# Convert sfp info in DB to cli output string | ||
def convert_sfp_info_to_output_string(self, sfp_info_dict): | ||
# Convert cmis sfp info in DB to cli output string | ||
def convert_cmis_sfp_info_to_output_string(self, sfp_info_dict): | ||
indent = ' ' * 8 | ||
output = '' | ||
|
||
sorted_cmis_data_map_keys = sorted(CMIS_DATA_MAP, key=CMIS_DATA_MAP.get) | ||
for key in sorted_cmis_data_map_keys: | ||
if key == 'cable_type': | ||
output += '{}{}: {}\n'.format(indent, sfp_info_dict['cable_type'], sfp_info_dict['cable_length']) | ||
elif key == 'cable_length': | ||
pass | ||
elif key == 'application_advertisement': | ||
output += covert_application_advertisement_to_output_string(indent, sfp_info_dict) | ||
else: | ||
output += '{}{}: {}\n'.format(indent, CMIS_DATA_MAP[key], sfp_info_dict[key]) | ||
|
||
return output | ||
|
||
# Convert non cmis sfp info in DB to cli output string | ||
def convert_non_cmis_sfp_info_to_output_string(self, sfp_info_dict): | ||
indent = ' ' * 8 | ||
output = '' | ||
|
||
|
@@ -420,7 +438,10 @@ class SFPShow(object): | |
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) | ||
if 'cmis_rev' in sfp_info_dict: | ||
sfp_info_output = self.convert_cmis_sfp_info_to_output_string(sfp_info_dict) | ||
else: | ||
sfp_info_output = self.convert_non_cmis_sfp_info_to_output_string(sfp_info_dict) | ||
output += sfp_info_output | ||
|
||
if dump_dom: | ||
|
@@ -587,6 +608,23 @@ def eeprom(port, dump_dom, namespace): | |
sfp.get_eeprom() | ||
sfp.display_eeprom() | ||
|
||
# 'eeprom' subcommand | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i thought this "info" does not come under as subcommand of 'eeprom' since we will remove 'eeprom' command in future? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this is a typo in comment. I have corrected it now. |
||
|
||
@cli.command() | ||
@click.option('-p', '--port', metavar='<port_name>', help="Display SFP EEPROM data for port <port_name> only") | ||
@click.option('-n', '--namespace', default=None, help="Display interfaces for specific namespace") | ||
def info(port, namespace): | ||
if port and multi_asic.is_multi_asic() and namespace is None: | ||
try: | ||
namespace = multi_asic.get_namespace_for_port(port) | ||
except Exception: | ||
display_invalid_intf_eeprom(port) | ||
sys.exit(1) | ||
|
||
sfp = SFPShow(port, namespace) | ||
sfp.get_eeprom() | ||
sfp.display_eeprom() | ||
|
||
# 'presence' subcommand | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -215,6 +215,46 @@ | |
EVM % 100.0 100.0 100.0 N/A N/A N/A N/A N/A N/A | ||
""" | ||
|
||
test_cmis_eeprom_output = """\ | ||
Ethernet48: SFP EEPROM detected | ||
Active Firmware: 61.20 | ||
Active application selected code assigned to host lane 1: 1 | ||
Active application selected code assigned to host lane 2: 1 | ||
Active application selected code assigned to host lane 3: 1 | ||
Active application selected code assigned to host lane 4: 1 | ||
Active application selected code assigned to host lane 5: 1 | ||
Active application selected code assigned to host lane 6: 1 | ||
Active application selected code assigned to host lane 7: 1 | ||
Active application selected code assigned to host lane 8: 1 | ||
Application Advertisement: 400GAUI-8 C2M (Annex 120E) - Host Assign (0x1) - 400ZR, DWDM, amplified - Media Assign (0x1) | ||
400GAUI-8 C2M (Annex 120E) - Host Assign (0x1) - 400ZR, Single Wavelength, Unamplified - Media Assign (0x1) | ||
100GAUI-2 C2M (Annex 135G) - Host Assign (0x55) - 400ZR, DWDM, amplified - Media Assign (0x1) | ||
CMIS Rev: 4.1 | ||
Connector: LC | ||
Encoding: N/A | ||
Extended Identifier: Power Class 8 (20.0W Max) | ||
Extended RateSelect Compliance: N/A | ||
Host Lane Count: 8 | ||
Identifier: QSFP-DD Double Density 8X Pluggable Transceiver | ||
Inactive Firmware: 161.10 | ||
Length Cable Assembly(m): 0.0 | ||
Media Interface Technology: 1550 nm DFB | ||
Media Lane Count: 1 | ||
Module Hardware Rev: 1.1 | ||
Nominal Bit Rate(100Mbs): 0 | ||
Specification Compliance: sm_media_interface | ||
Supported Max Laser Frequency: 196100 | ||
Supported Max TX Power: 4.0 | ||
Supported Min Laser Frequency: 191300 | ||
Supported Min TX Power: -22.9 | ||
Vendor Date Code(YYYY-MM-DD Lot): 2021-11-19 | ||
Vendor Name: Acacia Comm Inc. | ||
Vendor OUI: 7c-b2-5c | ||
Vendor PN: DP04QSDD-E20-001 | ||
Vendor Rev: A | ||
Vendor SN: 214455197 | ||
""" | ||
|
||
test_sfp_eeprom_dom_all_output = """\ | ||
Ethernet0: SFP EEPROM detected | ||
Application Advertisement: N/A | ||
|
@@ -464,6 +504,12 @@ def test_qsfp_dd_eeprom_adv_app(self): | |
print(result.output) | ||
assert result.output == test_qsfp_dd_eeprom_adv_app_output | ||
|
||
def test_cmis_info(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["info"], ["Ethernet48"]) | ||
assert result.exit_code == 0 | ||
assert result.output == test_cmis_eeprom_output | ||
|
||
def test_rj45_eeprom(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["eeprom"], ["Ethernet36"]) | ||
|
@@ -545,6 +591,12 @@ def test_qsfp_dd_pm_with_ns(self): | |
expected = "Ethernet0: Transceiver performance monitoring not applicable" | ||
assert result_lines == expected | ||
|
||
def test_cmis_sfp_info_with_ns(self): | ||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["info"], ["Ethernet48 -n asic0"]) | ||
assert result.exit_code == 0 | ||
assert "\n".join([ l.rstrip() for l in result.output.split('\n')]) == test_cmis_eeprom_output | ||
|
||
def test_sfp_eeprom_all(self): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need to add test_cmis_info_all testcase for "show int tran info"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added a testcase now. |
||
runner = CliRunner() | ||
result = runner.invoke(show.cli.commands["interfaces"].commands["transceiver"].commands["eeprom"]) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,43 @@ | |
'application_advertisement': 'Application Advertisement' | ||
} | ||
|
||
CMIS_DATA_MAP = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CMIS_DATA_MAP seems to be just a super set of QSFP_DATA_MAP. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, have modified based on this now. |
||
'model': 'Vendor PN', | ||
'vendor_oui': 'Vendor OUI', | ||
'vendor_date': 'Vendor Date Code(YYYY-MM-DD Lot)', | ||
'manufacturer': 'Vendor Name', | ||
'vendor_rev': 'Vendor Rev', | ||
'serial': 'Vendor SN', | ||
'type': 'Identifier', | ||
'ext_identifier': 'Extended Identifier', | ||
'ext_rateselect_compliance': 'Extended RateSelect Compliance', | ||
'cable_length': 'cable_length', | ||
'cable_type': 'Length', | ||
'nominal_bit_rate': 'Nominal Bit Rate(100Mbs)', | ||
'specification_compliance': 'Specification Compliance', | ||
'encoding': 'Encoding', | ||
'connector': 'Connector', | ||
'application_advertisement': 'Application Advertisement', | ||
'host_lane_count': 'Host Lane Count', | ||
'media_lane_count': 'Media Lane Count', | ||
'active_apsel_hostlane1': 'Active application selected code assigned to host lane 1', | ||
'active_apsel_hostlane2': 'Active application selected code assigned to host lane 2', | ||
'active_apsel_hostlane3': 'Active application selected code assigned to host lane 3', | ||
'active_apsel_hostlane4': 'Active application selected code assigned to host lane 4', | ||
'active_apsel_hostlane5': 'Active application selected code assigned to host lane 5', | ||
'active_apsel_hostlane6': 'Active application selected code assigned to host lane 6', | ||
'active_apsel_hostlane7': 'Active application selected code assigned to host lane 7', | ||
'active_apsel_hostlane8': 'Active application selected code assigned to host lane 8', | ||
'media_interface_technology': 'Media Interface Technology', | ||
'hardware_rev': 'Module Hardware Rev', | ||
'cmis_rev': 'CMIS Rev', | ||
'active_firmware': 'Active Firmware', | ||
'inactive_firmware': 'Inactive Firmware', | ||
'supported_max_tx_power': 'Supported Max TX Power', | ||
'supported_min_tx_power': 'Supported Min TX Power', | ||
'supported_max_laser_freq': 'Supported Max Laser Frequency', | ||
'supported_min_laser_freq': 'Supported Min Laser Frequency' | ||
} | ||
|
||
def covert_application_advertisement_to_output_string(indent, sfp_info_dict): | ||
key = 'application_advertisement' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like, convert_cmis_sfp_info_to_output_string and convert_non_cmis_sfp_info_to_output_string have quite some code in common.
would it better to combine them into one function to reuse the code more?
something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, addressed this now