Basic DSA VLAN setup script

It took me a bit of reading up to set up VLANs on DSA, so I thought i'd share a little script I whipped up to make things easier. The scope is intentionally limited: it just handles the VLAN side of things. That being said, in my experience it's the most complex part of setting up e.g. a guest network.

What this script does:

  • Set up a default VLAN if undefined, and migrate your LAN interface to the new device (br-lan.1 or switch.1). The latter is crucial, since not doing so would render your device inaccessible over the LAN.
  • Define a custom, named VLAN through a series of prompts, with some explanations and examples with the right port notation. (The script enforces naming, but this is not mandatory for OpenWrt. It does help to keep the overview though.)
  • Check whether ports defined in the new VLAN are used in the default (LAN) VLAN and alert the user if so, since the primary VLAN ID (PVID) needs to be set in that case.
  • Make a backup of /etc/config/network in /tmp/, in case you need to restore things (gone with a reboot!).

What this script does not do:

  • Set up an interface to use the extra VLAN(s). This is rather trivial (e.g. you configure an interface br-lan.10 if you defined a VLAN on the br-lan device with VID 10).
  • Save you from yourself if you do not bother reading the warnings or setting a PVID.

With that in mind: enjoy.


# Script to set VLANs and migrate LAN interface to default VLAN if unset


# Variables. br-lan and switch are mutually exclusive.
[ -d /sys/class/net/br-lan ] && _BRIDGEDEV="br-lan"
[ -d /sys/class/net/switch ] && _BRIDGEDEV="switch"
_PORTLIST="$(uci get network.@device[0].ports)"				# Populate interface list

# Backup config.
cp /etc/config/network /tmp/network.backup

# Create LAN VLAN (VID 1) if not present, and include all ports by default.
if [ "$(uci -q get network.lan_vlan)" ]
	echo -e ":: LAN VLAN already defined. Skipping.\n"
	uci set network.lan_vlan='bridge-vlan'
	uci set network.lan_vlan.device="$_BRIDGEDEV"
	uci set network.lan_vlan.vlan='1'
	for i in $_PORTLIST ; do uci add_list network.lan_vlan.ports=$i ; done
uci commit network

# Migrate LAN interface.
uci set network.lan.device="$_BRIDGEDEV.1"

# Custom user defined VLANs
echo -e ":: Enter the \e[34mVLAN name\e[0m, e.g. 'guest'.\n"

echo -e "\n:: Provide a space separated \e[34mlist of ports\e[0m to include in your VLAN.\n   Use the names as listed in the default VLAN. Notation:\n
     lan1        untagged
     lan1:u*     untagged, primary VLAN ID ('PVID'). \e[31mMandatory\e[0m if same port is used in another VLAN!
     lan1:t      tagged

   E.g.: lan0:u* lan2 lan3

   Hit 'Enter' to process the list. Do not forget to modify the default\n   VLAN and specify the PVID for ports you are using in multiple VLANs.\n"

echo -e "\n:: Enter the \e[34mVLAN ID\e[0m. 1 is reserved for the default VLAN. Use e.g. 10 for a\n   guest VLAN, 20 for an additional VLAN, 30, 40, ... for subsequent VLANs etc.\n"
read _VLAN_ID

echo -e "\n:: Adding new $_VLAN_NAME VLAN...\n"
uci set network."$_VLAN_NAME"='bridge-vlan'
uci set network."$_VLAN_NAME".device="$_BRIDGEDEV"
uci set network."$_VLAN_NAME".vlan="$_VLAN_ID"
for i in $_VLAN_PORTLIST ; do uci add_list network."$_VLAN_NAME".ports=$i ; done

# Port check: are ports already in use in default VLAN? If so, prompt.
for i in $_VLAN_PORTLIST ; do uci get network.lan_vlan.ports|grep -q ${i%%:*} && echo -e ":: \e[31mWARNING:\e[0m port ${i%%:*} is already in use in LAN VLAN! Please set the PVID." ; done
echo -e "\n"

# Save and quit.
uci commit network
echo ":: Done."