Skip to content

Commit bf9c07c

Browse files
authored
Add target mode to sfputil firmware (#3002)
* Add target mode to sfputil firmware * Remove duplicate code * Address review comments 1. Add int range to CLI arg 2. update port name to error messages * Add UT cases for sfputil * Update sfputil_test.py * Update Command-Reference.md Add CMIS firmware upgrade command * Update Command-Reference.md * Update main.py * Update Command-Reference.md * Update Command-Reference.md
1 parent 0e43e4d commit bf9c07c

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed

doc/Command-Reference.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
* [Console config commands](#console-config-commands)
4040
* [Console connect commands](#console-connect-commands)
4141
* [Console clear commands](#console-clear-commands)
42+
* [CMIS firmware upgrade](#cmis-firmware-upgrade)
43+
* [CMIS firmware version show commands](#cmis-firmware-version-show-commands)
44+
* [CMIS firmware upgrade commands](#cmis-firmware-upgrade-commands)
45+
* [CMIS firmware target mode commands](#cmis-firmware-target-mode-commands)
4246
* [DHCP Relay](#dhcp-relay)
4347
* [DHCP Relay show commands](#dhcp-relay-show-commands)
4448
* [DHCP Relay clear commands](#dhcp-relay-clear-commands)
@@ -206,6 +210,7 @@
206210

207211
| Version | Modification Date | Details |
208212
| --- | --- | --- |
213+
| v8 | Oct-09-2023 | Add CMIS firmware upgrade commands |
209214
| v7 | Jun-22-2023 | Add static DNS show and config commands |
210215
| v6 | May-06-2021 | Add SNMP show and config commands |
211216
| v5 | Nov-05-2020 | Add document for console commands |
@@ -2785,6 +2790,138 @@ Optionally, you can clear with a remote device name by specifying the `-d` or `-
27852790
27862791
Go Back To [Beginning of the document](#) or [Beginning of this section](#console)
27872792
2793+
## CMIS firmware upgrade
2794+
2795+
### CMIS firmware version show commands
2796+
2797+
The sfputil command shows the current major and minor versions of active/inactive firmware, running Image details. The output may vary based on the single vs dual bank supported modules.
2798+
2799+
**sfputil show fwversion**
2800+
2801+
- Usage:
2802+
```
2803+
sfputil show fwversion PORT_NAME
2804+
```
2805+
2806+
- Example:
2807+
```
2808+
admin@sonic:~$ sfputil show fwversion Ethernet180
2809+
Image A Version: 0.3.5
2810+
Image B Version: 0.3.5
2811+
Factory Image Version: 0.0.0
2812+
Running Image: A
2813+
Committed Image: A
2814+
Active Firmware: 0.3.5
2815+
Inactive Firmware: 0.3.5
2816+
```
2817+
2818+
### CMIS firmware upgrade commands
2819+
2820+
The sfputil commands are used to download/upgrade firmware on transciver modules. The download/upgrade actually happens using set of CMIS CDB commands. The module may replace the exisiting image or copy into the inactive bank of the module. The host issues a download complete CDB command when the entire firmware image has been written to LPL or EPL pages. Each steps can be verified using the 'sfputil show fwversion PORT_NAME'
2821+
2822+
**sfputil firmware download**
2823+
2824+
This command is used for downloading firmware tp upgrade the transciever module.
2825+
2826+
- Usage:
2827+
```
2828+
sfputil firmware download PORT_NAME FILE_PATH
2829+
```
2830+
2831+
- Example:
2832+
```
2833+
admin@sonic:~$ sfputil firmware download Ethernet180 AEC_Camano_YCable__0.3.6_20230905.bin
2834+
CDB: Starting firmware download
2835+
Downloading ... [####################################] 100%
2836+
CDB: firmware download complete
2837+
Firmware download complete success
2838+
Total download Time: 0:01:55.731397
2839+
2840+
admin@sonic:~$ sfputil show fwversion Ethernet180
2841+
Image A Version: 0.3.5
2842+
Image B Version: 0.3.6
2843+
Factory Image Version: 0.0.0
2844+
Running Image: A
2845+
Committed Image: A
2846+
Active Firmware: 0.3.5
2847+
Inactive Firmware: 0.3.6
2848+
```
2849+
**sfputil firmware run**
2850+
2851+
This command is used to start and run a downloaded image. This command transfers control from the currently running firmware to a new firmware.
2852+
2853+
- Usage:
2854+
```
2855+
sfputil firmware run PORT_NAME
2856+
```
2857+
2858+
- Example:
2859+
```
2860+
admin@sonic:~$ sfputil firmware run Ethernet180
2861+
Running firmware: Non-hitless Reset to Inactive Image
2862+
Firmware run in mode=0 success
2863+
2864+
admin@sonic:~$ sfputil show fwversion Ethernet180
2865+
Image A Version: 0.3.5
2866+
Image B Version: 0.3.6
2867+
Factory Image Version: 0.0.0
2868+
Running Image: B
2869+
Committed Image: A
2870+
Active Firmware: 0.3.6
2871+
Inactive Firmware: 0.3.5
2872+
```
2873+
2874+
**sfputil firmware commit**
2875+
2876+
This command to commit the running image so that the module will boot from it on future boots.
2877+
2878+
- Usage:
2879+
```
2880+
sfputil firmware commit PORT_NAME
2881+
```
2882+
2883+
- Example:
2884+
```
2885+
admin@sonic:~$ sfputil firmware commit Ethernet180
2886+
Firmware commit successful
2887+
2888+
admin@sonic:~$ sfputil show fwversion Ethernet180
2889+
Image A Version: 0.3.5
2890+
Image B Version: 0.3.6
2891+
Factory Image Version: 0.0.0
2892+
Running Image: B
2893+
Committed Image: B
2894+
Active Firmware: 0.3.6
2895+
Inactive Firmware: 0.3.5
2896+
```
2897+
2898+
### CMIS firmware target mode commands
2899+
2900+
This command is vendor-specific and supported on the modules to set the target mode to perform remote firmware upgrades. The target modes can be set as 0 (local- E0), 1 (remote end E1), or 2 (remote end E2). Depending on the mode set, the remote or local end will respond to CDB/I2C commands from host's E0 end. After setting the target mode, we can use **sfputil** firmware upgrade commands, will be executed on the module for which target mode is set.
2901+
2902+
Example of the module supporting target mode
2903+
2904+
![RMT_UPGRD](https://github.com/AnoopKamath/sonic-utilities_remote_upgrade/assets/115578705/c3b0bb62-eb14-4b05-b0a8-96b8c082455a)
2905+
2906+
**sfputil firmware target**
2907+
2908+
- Usage:
2909+
```
2910+
sfputil firmware target [OPTIONS] PORT_NAME TARGET
2911+
2912+
Select target end for firmware download
2913+
0-(local)
2914+
2915+
1-(remote-A)
2916+
2917+
2-(remote-B)
2918+
```
2919+
2920+
- Example:
2921+
```
2922+
admin@sonic:~$ sfputil firmware target Ethernet180 1
2923+
Target Mode set to 1
2924+
```
27882925
27892926
## DHCP Relay
27902927

sfputil/main.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,6 +1526,43 @@ def version():
15261526
"""Display version info"""
15271527
click.echo("sfputil version {0}".format(VERSION))
15281528

1529+
# 'target' subcommand
1530+
@firmware.command()
1531+
@click.argument('port_name', required=True, default=None)
1532+
@click.argument('target', type=click.IntRange(0, 2), required=True, default=None)
1533+
def target(port_name, target):
1534+
"""Select target end for firmware download 0-(local) \n
1535+
1-(remote-A) \n
1536+
2-(remote-B)
1537+
"""
1538+
physical_port = logical_port_to_physical_port_index(port_name)
1539+
sfp = platform_chassis.get_sfp(physical_port)
1540+
1541+
if is_port_type_rj45(port_name):
1542+
click.echo("{}: This functionality is not applicable for RJ45 port".format(port_name))
1543+
sys.exit(EXIT_FAIL)
1544+
1545+
if not is_sfp_present(port_name):
1546+
click.echo("{}: SFP EEPROM not detected\n".format(port_name))
1547+
sys.exit(EXIT_FAIL)
1548+
1549+
try:
1550+
api = sfp.get_xcvr_api()
1551+
except NotImplementedError:
1552+
click.echo("{}: This functionality is currently not implemented for this module".format(port_name))
1553+
sys.exit(ERROR_NOT_IMPLEMENTED)
1554+
1555+
try:
1556+
status = api.set_firmware_download_target_end(target)
1557+
except AttributeError:
1558+
click.echo("{}: This functionality is not applicable for this module".format(port_name))
1559+
sys.exit(ERROR_NOT_IMPLEMENTED)
1560+
1561+
if status:
1562+
click.echo("Target Mode set to {}". format(target))
1563+
else:
1564+
click.echo("Target Mode set failed!")
1565+
sys.exit(EXIT_FAIL)
15291566

15301567
if __name__ == '__main__':
15311568
cli()

tests/sfputil_test.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,3 +967,36 @@ def test_update_firmware_info_to_state_db(self, mock_chassis):
967967
mock_sfp.get_transceiver_info_firmware_versions.return_value = ['a.b.c', 'd.e.f']
968968

969969
sfputil.update_firmware_info_to_state_db("Ethernet0")
970+
971+
@patch('sfputil.main.platform_chassis')
972+
@patch('sfputil.main.logical_port_to_physical_port_index', MagicMock(return_value=1))
973+
def test_target_firmware(self, mock_chassis):
974+
mock_sfp = MagicMock()
975+
mock_api = MagicMock()
976+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api)
977+
mock_sfp.get_presence.return_value = True
978+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
979+
mock_api.set_firmware_download_target_end.return_value = 1
980+
runner = CliRunner()
981+
result = runner.invoke(sfputil.cli.commands['firmware'].commands['target'], ["Ethernet0", "2"])
982+
assert result.output == 'Target Mode set to 2\n'
983+
assert result.exit_code == 0
984+
985+
mock_sfp.get_presence.return_value = False
986+
result = runner.invoke(sfputil.cli.commands['firmware'].commands['target'], ["Ethernet0", "2"])
987+
assert result.output == 'Ethernet0: SFP EEPROM not detected\n\n'
988+
989+
mock_sfp.get_presence.return_value = True
990+
mock_sfp.get_xcvr_api = MagicMock(side_effect=NotImplementedError)
991+
result = runner.invoke(sfputil.cli.commands['firmware'].commands['target'], ["Ethernet0", "2"])
992+
assert result.output == 'Ethernet0: This functionality is currently not implemented for this module\n'
993+
assert result.exit_code == ERROR_NOT_IMPLEMENTED
994+
995+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api)
996+
mock_sfp.get_presence.return_value = True
997+
mock_api.set_firmware_download_target_end.return_value = 0
998+
result = runner.invoke(sfputil.cli.commands['firmware'].commands['target'], ["Ethernet0", "1"])
999+
assert result.output == 'Target Mode set failed!\n'
1000+
assert result.exit_code == EXIT_FAIL
1001+
1002+

0 commit comments

Comments
 (0)