Most readers of this blog will probably have upgraded an IOS on a Cisco switch or router already. Most of them will have done this using TFTP for the binary after erasing the existing IOS image, e.g.

Switch#delete flash:c3560-ipbasek9-mz.122-58.SE2.bin
Switch#copy tftp:// flash:c3560-ipbasek9-mz.150-1.SE.bin

And reload. The end. While the above works, it’s actually inefficiently and taking risks.

Types of releases
While taking the latest IOS right away may seem a good idea at first sight, there are some points to consider: are you looking for new features, or bug fixes? As with the above example, you would be making a jump from version 12.2(58) to 15.0(1). While this will introduce a lot of new features, it will also introduce a lot of new bugs.
Small releases only contain bug fixes. For example, upgrading from 15.0(1)SE to 15.0(1)SE3 will include many bug fixes. It’s therefore often better to wait out a new mayor release until some of these bugfix-releases are available. Be sure to read the release notes.

Checksum verification
Another thing that is usually forgotten is a checksum verification to see if the IOS isn’t corrupted. The IOS has a build-in command for this:

Switch#verify /md5 flash:c3560-ipservicesk9-mz.150-2.SE5.bin f73e32e66719fb48b11c849deee958e1

This will compare the md5 hash with a given one in the command. The original hash can be found on the Cisco website on the IOS download page, or by using a tool for this, for example WinMD5.

Proper boot flag
Uploading a new IOS doesn’t mean the router will use it automatically. It will follow the boot path:

Switch#show boot | include BOOT
BOOT path-list      : flash:/c3560-ipservicesk9-mz.150-2.SE5.bin

If it can’t find the file specified here, it will look for any .bin file on the flash and load the first one it finds. If you erase the old IOS before uploading a new one, the new IOS is the only one on flash and will be loaded. Still, it’s better to set the proper boot path:

Switch(config)#boot system flash:/c3560-ipservicesk9-mz.150-2.SE5.bin

Archive download
The copy command isn’t the only one to upload a new IOS. There’s a specific command to do an IOS upgrade:

Switch(config)#archive download-sw tftp://

Note that it will require a .tar file, available from the Cisco website. The .tar file will automatically be unpacked. The command will also automatically change the boot path after a successful download and verify the IOS image by downloading the image two or three times and comparing the md5 checksums.

Internal copy
For a 3750 switch stack, the master switch will automatically push the newest IOS to the members of the stack as long as the IOS is in the same tree, e.g. it will automatically upgrade members from IOS 15.0(1)SE to 15.0(1)SE3 if the master has been upgraded to 15.0(1)SE3, but it will not do this between mayor versions like from 12.2(58) to 15.0(1).
However, once a file is present on one of the stack members, it can be copied to the other ones fast:

Switch(config)#copy flash3:c3750-ipbasek9-mz.150-2.SE5.bin flash2:c3750-ipbasek9-mz.150-2.SE5.bin

The above copies the IOS from the third stack member to the second stack member. It saves time and bandwidth.

Secure Copy Protocol
This one really comes in handy over WAN links and through some firewalls. TFTP uses UDP and has no concept of windowing so if latency increases, transfer speed of the new IOS will drop quickly.

A TCP-based transfer protocol will be able to use windowing. An obvious choice comes to mind: FTP. However, FTP will explicitly need to be opened on a firewall between the download server and the Cisco device and some firewalls can’t see the random high port used for transfer in the data negotiation. Switches may also have ACLs that can’t change according to the FTP data port being used.

So this is where Secure Copy Protocol (SCP) comes into play: it tunnels a file transfer through SSH, which is often already opened on firewalls, and doesn’t use a random high port. It also takes advantage of TCP windowing. Finetuning of TCP parameters prior to downloading the IOS is recommended:

Switch(config)#ip tcp window-size 65535
Switch(config)#ip tcp selective-ack

The default window size is about 8kB. Selective Acknowledgements make the transfer more resilient to packet loss by still acknowledging part of a packet stream that still reached the receiver. Also, since SCP works through SSH, you can use the following command to define a source interface:

Switch(config)#ip ssh source-interface Loopback0

And finally, the actual install command:

Switch#archive download-sw scp://scpuser@

The user needs to be included in the command, the password will be asked after executing it. As a download server any SCP-capable server will do. A Debian Linux will support SCP out of the box, for example. By creating a specific user for SCP, e.g. ‘scpuser’, you can use the home folder (/home/scpuser/) as file share while still limiting access to other parts of the Linux system. At the same time, you can easily upload files to the download server using software such as WinSCP.

The most important limitation is that you need a fairly recent IOS already running before SCP works. For the 3560 and 3750 series you need version 15.0(2)SE1 or higher.