Starting with OpenWrt 21, a specific list of chipsets starting using DSA (Distributed Switch Architecture) from the Linux kernel instead of swconfig. This significantly changes the way switches and vlan are handled in OpenWrt, and therefore system configurations cannot always be migrated.
Trying to run sysupgrade on a chipset that is changing from swconfig to DSA may result in the program aborting with the message below (if the configs cannot be converted).
Config cannot be migrated from swconfig to DSA Image check failed
For those who want to deploy the latest OpenWrt version , a fresh install is required.
This article will take you through backing up and identifying your customizations so they can be recreated after the upgrade.
Overview
Our general approach will be to:
- Identify all customizations (packages and conf files)
- Backup all customizations, download to the local host
- Run sysupgrade to go to the latest OpenWrt version, without saving any old configurations
- Make minimal changes to restore original LAN networking CIDR block
- Make minimal changes to restore wireless settings
- Reinstall the previously installed packages
- Apply any other customizations
I’m going to assume ssh into your OpenWrt device is enabled and you have logged in as root (same credentials used for the LuCI web interface).
If you want to use serial access instead, read my article here.
Identify router hardware
The current version of the firmware can be determined using:
cat /etc/banner cat /tmp/sysinfo/board_name cat /tmp/sysinfo/model
Use this information when choosing the correct sysupgrade binary and also for validating that the upgrade was successful.
Identify user-installed packages
Identify any custom packages that need to be reinstalled after the upgrade.
The listuserpackages.awk script will list which packages have been user installed by checking for a timestamp after the initial flash.
cat << "EOF" > /tmp/listuserpackages.awk #!/usr/bin/awk -f BEGIN { ARGV[ARGC++] = "/usr/lib/opkg/status" cmd="opkg info busybox | grep '^Installed-Time: '" cmd | getline FLASH_TIME close(cmd) FLASH_TIME=substr(FLASH_TIME,17) } /^Package:/{PKG= $2} /^Installed-Time:/{ INSTALLED_TIME= $2 # Find all packages installed after FLASH_TIME if ( INSTALLED_TIME > FLASH_TIME ) { cmd="opkg whatdepends " PKG " | wc -l" cmd | getline WHATDEPENDS close(cmd) # If nothing depends on the package, it is installed by user if ( WHATDEPENDS == 3 ) print PKG } } EOF # run script, save in /etc directory chmod +x /tmp/listuserpackages.awk /tmp/listuserpackages.awk /usr/lib/opkg/status > /etc/opkg-beforeupgrade
This file is saved in /etc, because we will be backing up that entire directory in the below sections.
Identify custom configurations not in /etc
In the next section we will backup the entire /etc directory, so let’s check the list of configuration files that a normal sysupgrade would have preserved to make sure they all fall under that directory structure:
1. Content of files in ‘keep.d’ (that are not already in /etc)
cat /lib/upgrade/keep.d/* | grep -v /etc
2. Files listed in ‘syupgrade.conf’ (that are not already in /etc)
cat /etc/sysupgrade.conf | grep -v /etc
3. Files listed by opkg as configuration files (that are not already in /etc)
opkg list-changed-conffiles | grep -v /etc
ACTION: Probably none, but add any custom files not already in /etc into that directory so they can be backed up in the next section.
Backup all files, download locally
# backup all files in /etc cd /etc tar cvfz /tmp/etc.tar.gz *
The same as you used ssh to get a terminal into OpenWrt, you can use scp/pscp.exe from your host machine to grab this file from the OpenWrt router.
# from linux host scp -oHostKeyAlgorithms=+ssh-rsa root@myOpenWrtHostOrIPAddress:/tmp/etc.tar.gz . # from window host pscp.exe -scp root@myOpenWrtHostOrIPAddress:/tmp/etc.tar.gz .
This provides you with a local copy of your current OpenWrt config files. Although it cannot be automatically applied after the upgrade, it will give you a starting point for manually reintroducing your customizations.
Download the latest sysupgrade image
We will still download the latest sysupgrade binary (not the factory install used for fresh installs), but instead of asking sysupgrade to preserve the configuration, we will instead use a flag to tell it not to preserve the old configuration.
You will need to download the latest sysupgrade binary that is compatible with your hardware chipset. The easiest way is to use the firmware selector available here as shown below, use the value of “/tmp/sysinfo/model” from the earlier section as a starting point.
But you can also browse the releases download site and manually choose the sysupgrade binary for your chipset. Or you can choose a bleeding-edge snapshot version from the download site.
If the router does not have public internet access, you could use either scp or tftp as described here to copy it to the router.
Download the identified sysupgrade binary to the /tmp directory, which is a temporary RAM disk.
# ideally, your free memory is 2x the sysupgrade binary size free -m # necessary packages for using wget cd /tmp opkg update opkg install wget ca-bundle ca-certificates # package name for <=19 opkg install libustream-openssl # download sysupgrade binary (avoid --no-check-certificate) wget https://downloads.openwrt.org/releases/22.03.1/targets/mvebu/cortexa9/openwrt-22.03.1-mvebu-cortexa9-linksys_wrt1900acs-squashfs-sysupgrade.bin
There is a full script to verify the checksum if you wanted to be extra diligent.
Run sysupgrade without preserving configuration
WARNING: Your network settings will all be reset after this is executed, your router will not be available via wireless and the lan CIDR will be reset to the default 192.168.1.1. You should have a wired connection or serial access before running this command.
Run sysupgrade with the latest binary image now located in /tmp. We will run in forced mode (-F) without saving the configuration (-n).
sysupgrade -F -n -v /tmp/openwrt-22.03.1-mvebu-cortexa9-linksys_wrt1900acs-squashfs-sysupgrade.bin
The system will reboot and you will need to give it a minute and then ssh back in. Upon entry, you should see a new version embedded in the banner “OpenWrt xx.yy.zz”.
BusyBox v1.35.0 (2022-10-07 23:34:56 UTC) built-in shell (ash) _______ ________ __ | |.-----.-----.-----.| | | |.----.| |_ | - || _ | -__| || | | || _|| _| |_______|| __|_____|__|__||________||__| |____| |__| W I R E L E S S F R E E D O M ----------------------------------------------------- OpenWrt 22.03.1, r19777-2853b6d652
For security reasons, change the router password immediately upon first login.
passwd
Network changes
The first thing you will notice is that the network configuration is different. Under DSA, there is ‘br-lan’ bridge that contains all your interfaces.
# show all bridges and their interfaces brctl show # show interfaces ip a
If your OpenWrt was originally on a non-default CIDR block (not 192.168.1.1), make that your first change.
sed -i 's/192.168.1.1/192.168.x.1/' /etc/config/network # restart network OR (reboot -d 0) # either way, connection will be lost /etc/init.d/network restart
Additional changes can be done via Luci later.
Luci web interface
Pointing your browser at http://192.168.x.1/cgi-bin/luci should get you to the Luci web interface.
Login with ‘root’ and the password you set earlier.
The bottom of the Luci web page should show the message, “Powered by LuCI openwrt-xx.yy” showing the target release.
Validate opkg connectivity and basic user packages
Validate that opkg can reach its remote repository, which proves out our ability to reach the internet upstream.
Then install the ‘diff’ and ‘watch’ utilities, along with the new Attended Upgrade menu for the CLI and luci so that future patching is streamlined.
# smoke test opkg update # optional basic utilities: diff and watch opkg install diffutils procps-ng-watch # new attended sysupgrade for CLI/luci opkg upgrade auc luci-app-attendedsysupgrade
Reinstall custom user packages
The locally downloaded backup has a file “opkg-beforeupgrade” where we saved a list of the user installed packages. We can reinstall them by placing this file back on the router in /tmp and running the command below.
cat /tmp/opkg-beforeupgrade | xargs opkg install
The collected errors will be shown at the bottom. More than likely you will get a few ‘Cannot install package xxxxx’, which could be a result of the package no longer being available on the newer OpenWrt kernel. The package may no longer be available or had a name change. For example, “libustream-openssl” in 19.x became “libustream-ssl” and “libustream-tls” in newer versions.
And where a new conf file created, you will be warned and the newer one will be created as ‘/etc/config/<filename>-opkg’. You will need to manually review and merge these files.
Enable Wireless from luci
From the luci web interface, go to Network > Wireless, and your network interfaces will be disabled.
Press “Edit” on each wireless network interface, and set the SSID name, Encryption (e.g. WPA2-PSK) and key. Then press “Save”. These values can be found on your local backup at “config/wireless”.
Once done with all wireless interfaces, press “Save & Apply”. Then press “Enable” for each wireless interface.
You should then be able to see your wireless SSID from any wireless client (e.g. laptop, phone)..
Apply other customizations
This gives you a baseline, but if you had custom routes, firewall rules, dnsmasq settings, etc. then you should start looking at the “etc.tar.gz” we downloaded and manually recreating all these configurations.
REFERENCES
openwrt forums, required switch and switch_vlan so wan gets DHCP from upstream
OpenWrt, upgrading to 21.x which includes DSA
OpenWrt, DSA (distributed switch architecture) tutorial change from older swdist
OneMarcFifty on youtube, VLANs in OpenWrt 21
OpenWrt forums, network settings got my 22.x working with new DSA
github, Attended sysupgrade server
OpenWrt snapshot binaries download site
OpenWrt, avoid upgrading core packages with opkg
OpenWrt forums, set password from CLI
OpenWrt firmware selector for ACSv2
OpenWrt CVE known vulnerabilities in current versions
NOTES:
Do you have a musl libraries or uClibc?
ls -l /lib | grep libc
Example /etc/config/network for 22.x on Linksys WRT1900ACv2 (Cobra)
onfig interface 'loopback' option device 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0' config globals 'globals' option ula_prefix 'fda6:b9c6:92d7::/48' config device option name 'br-lan' option type 'bridge' list ports 'lan1' list ports 'lan2' list ports 'lan3' list ports 'lan4' config interface 'lan' option device 'br-lan' option proto 'static' option ipaddr '192.168.1.1' option netmask '255.255.255.0' option ip6assign '60' config device option name 'wan' option macaddr '64:28:f0:07:1c:ea' config interface 'wan' option device 'wan' option proto 'dhcp' config interface 'wan6' option device 'wan' option proto 'dhcpv6'
example /etc/config/wireless for 22.x on Linksys WRT1900ACv2 (Cobra)
config wifi-device 'radio0' option type 'mac80211' option path 'soc/soc:pcie/pci0000:00/0000:00:01.0/0000:01:00.0' option channel '36' option band '5g' option htmode 'VHT80' option country 'US' option cell_density '0' config wifi-iface 'default_radio0' option device 'radio0' option network 'lan' option mode 'ap' option ssid 'OpenWrt' option macaddr '40:48:f0:05:1c:f1' option encryption 'psk2' option key 'myfakepassword' config wifi-device 'radio1' option type 'mac80211' option path 'soc/soc:pcie/pci0000:00/0000:00:02.0/0000:02:00.0' option channel '1' option band '2g' option htmode 'HT20' option country 'US' option cell_density '0' config wifi-iface 'default_radio1' option device 'radio1' option network 'lan' option mode 'ap' option macaddr '40:48:f0:05:1c:f1' option ssid 'OpenWrt5' option encryption 'psk2' option key 'myfakepassword5'
example /etc/config/network for 22.x on TP-Link Archer C7 v4
config interface 'loopback' option device 'lo' option proto 'static' option ipaddr '127.0.0.1' option netmask '255.0.0.0' config globals 'globals' option ula_prefix 'fe4a:dd17:f80f::/48' config device option name 'br-lan' option type 'bridge' list ports 'eth0.1' config interface 'lan' option device 'br-lan' option proto 'static' option ipaddr '192.168.1.1' option netmask '255.255.255.0' option ip6assign '60' config device option name 'eth0.2' option macaddr '0d:90:64:62:f1:13' config interface 'wan' option device 'eth0.2' option proto 'dhcp' config interface 'wan6' option device 'eth0.2' option proto 'dhcpv6' config switch option name 'switch0' option reset '1' option enable_vlan '1' config switch_vlan option device 'switch0' option vlan '1' option ports '2 3 4 5 0t' config switch_vlan option device 'switch0' option vlan '2' option ports '1 0t'
example /etc/config/wireless for 22.x on TP-Link Archer C7 v4
config wifi-device 'radio0' option type 'mac80211' option path 'pci0000:00/0000:00:00.0' option channel '36' option band '5g' option htmode 'VHT80' config wifi-iface 'default_radio0' option device 'radio0' option network 'lan' option mode 'ap' option encryption 'psk2' option key 'myfakepassword5' option ssid 'OpenWrt5' config wifi-device 'radio1' option type 'mac80211' option path 'platform/ahb/18100000.wmac' option channel '1' option band '2g' option htmode 'HT20' config wifi-iface 'default_radio1' option device 'radio1' option encryption 'psk2' option key 'myfakepassword' option ssid 'OpenWrt' option network 'lan' option mode 'ap'