OpenWrt: upgrading to latest version when chipset migrated to DSA support

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

OpenWrt, converting to DSA

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'