Skip to content

Commit b6f7c2b

Browse files
authored
[sfputil] Add loopback sub-command for debugging and module diagnosti… (#3369)
* [sfputil] Add loopback sub-command for debugging and module diagnostic control Signed-off-by: xinyu <xinyu0123@gmail.com> * [sfputil] Correct and update the reference of sfputil debug loopback command Signed-off-by: xinyu <xinyu0123@gmail.com> --------- Signed-off-by: xinyu <xinyu0123@gmail.com>
1 parent 1f94444 commit b6f7c2b

3 files changed

Lines changed: 115 additions & 0 deletions

File tree

doc/Command-Reference.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
* [CMIS firmware version show commands](#cmis-firmware-version-show-commands)
4848
* [CMIS firmware upgrade commands](#cmis-firmware-upgrade-commands)
4949
* [CMIS firmware target mode commands](#cmis-firmware-target-mode-commands)
50+
* [CMIS debug](#cmis-debug)
51+
* [CMIS debug loopback](#cmis-debug-loopback)
5052
* [DHCP Relay](#dhcp-relay)
5153
* [DHCP Relay show commands](#dhcp-relay-show-commands)
5254
* [DHCP Relay clear commands](#dhcp-relay-clear-commands)
@@ -3094,6 +3096,31 @@ Example of the module supporting target mode
30943096
Target Mode set to 1
30953097
```
30963098

3099+
## CMIS debug
3100+
3101+
### CMIS debug loopback
3102+
3103+
This command is the standard CMIS diagnostic control used for troubleshooting link and performance issues between the host switch and transceiver module.
3104+
3105+
**sfputil debug loopback**
3106+
3107+
- Usage:
3108+
```
3109+
sfputil debug loopback PORT_NAME LOOPBACK_MODE
3110+
3111+
Set the loopback mode
3112+
host-side-input: host side input loopback mode
3113+
host-side-output: host side output loopback mode
3114+
media-side-input: media side input loopback mode
3115+
media-side-output: media side output loopback mode
3116+
none: disable loopback mode
3117+
```
3118+
3119+
- Example:
3120+
```
3121+
admin@sonic:~$ sfputil debug loopback Ethernet88 host-side-input
3122+
```
3123+
30973124
## DHCP Relay
30983125

30993126
### DHCP Relay show commands

sfputil/main.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,5 +1888,50 @@ def get_overall_offset_sff8472(api, page, offset, size, wire_addr):
18881888
return page * PAGE_SIZE + offset + PAGE_SIZE_FOR_A0H
18891889

18901890

1891+
# 'debug' subgroup
1892+
@cli.group()
1893+
def debug():
1894+
"""Module debug and diagnostic control"""
1895+
pass
1896+
1897+
1898+
# 'loopback' subcommand
1899+
@debug.command()
1900+
@click.argument('port_name', required=True, default=None)
1901+
@click.argument('loopback_mode', required=True, default="none",
1902+
type=click.Choice(["none", "host-side-input", "host-side-output",
1903+
"media-side-input", "media-side-output"]))
1904+
def loopback(port_name, loopback_mode):
1905+
"""Set module diagnostic loopback mode
1906+
"""
1907+
physical_port = logical_port_to_physical_port_index(port_name)
1908+
sfp = platform_chassis.get_sfp(physical_port)
1909+
1910+
if is_port_type_rj45(port_name):
1911+
click.echo("{}: This functionality is not applicable for RJ45 port".format(port_name))
1912+
sys.exit(EXIT_FAIL)
1913+
1914+
if not is_sfp_present(port_name):
1915+
click.echo("{}: SFP EEPROM not detected".format(port_name))
1916+
sys.exit(EXIT_FAIL)
1917+
1918+
try:
1919+
api = sfp.get_xcvr_api()
1920+
except NotImplementedError:
1921+
click.echo("{}: This functionality is not implemented".format(port_name))
1922+
sys.exit(ERROR_NOT_IMPLEMENTED)
1923+
1924+
try:
1925+
status = api.set_loopback_mode(loopback_mode)
1926+
except AttributeError:
1927+
click.echo("{}: Set loopback mode is not applicable for this module".format(port_name))
1928+
sys.exit(ERROR_NOT_IMPLEMENTED)
1929+
1930+
if status:
1931+
click.echo("{}: Set {} loopback".format(port_name, loopback_mode))
1932+
else:
1933+
click.echo("{}: Set {} loopback failed".format(port_name, loopback_mode))
1934+
sys.exit(EXIT_FAIL)
1935+
18911936
if __name__ == '__main__':
18921937
cli()

tests/sfputil_test.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1510,3 +1510,46 @@ def test_load_port_config(self, mock_is_multi_asic):
15101510

15111511
mock_is_multi_asic.return_value = False
15121512
assert sfputil.load_port_config() == True
1513+
1514+
@patch('sfputil.main.is_port_type_rj45', MagicMock(return_value=False))
1515+
@patch('sfputil.main.platform_chassis')
1516+
@patch('sfputil.main.platform_sfputil', MagicMock(is_logical_port=MagicMock(return_value=1)))
1517+
@patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=1))
1518+
def test_debug_loopback(self, mock_chassis):
1519+
mock_sfp = MagicMock()
1520+
mock_api = MagicMock()
1521+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
1522+
mock_sfp.get_presence.return_value = True
1523+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api)
1524+
1525+
runner = CliRunner()
1526+
mock_sfp.get_presence.return_value = False
1527+
result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'],
1528+
["Ethernet0", "host-side-input"])
1529+
assert result.output == 'Ethernet0: SFP EEPROM not detected\n'
1530+
mock_sfp.get_presence.return_value = True
1531+
1532+
mock_sfp.get_xcvr_api = MagicMock(side_effect=NotImplementedError)
1533+
result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'],
1534+
["Ethernet0", "host-side-input"])
1535+
assert result.output == 'Ethernet0: This functionality is not implemented\n'
1536+
assert result.exit_code == ERROR_NOT_IMPLEMENTED
1537+
1538+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api)
1539+
result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'],
1540+
["Ethernet0", "host-side-input"])
1541+
assert result.output == 'Ethernet0: Set host-side-input loopback\n'
1542+
assert result.exit_code != ERROR_NOT_IMPLEMENTED
1543+
1544+
mock_api.set_loopback_mode.return_value = False
1545+
result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'],
1546+
["Ethernet0", "none"])
1547+
assert result.output == 'Ethernet0: Set none loopback failed\n'
1548+
assert result.exit_code == EXIT_FAIL
1549+
1550+
mock_api.set_loopback_mode.return_value = True
1551+
mock_api.set_loopback_mode.side_effect = AttributeError
1552+
result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'],
1553+
["Ethernet0", "none"])
1554+
assert result.output == 'Ethernet0: Set loopback mode is not applicable for this module\n'
1555+
assert result.exit_code == ERROR_NOT_IMPLEMENTED

0 commit comments

Comments
 (0)