Systemd Networking
systemd-networkd should be the future. That being said it is somewhat arcane to say the least.
The desire: Create a BONDED LAG, and attach a bunch of bridged VLANs to it.
The script below should create a folder /tmp/systemd-networkd and dump all the needed configuration. Despite what I continually read, order does not seem to be important. This works on Debian Bullseye. I built this because I keep rebuilding my LAB KVM/QEMU server, and typing in all these files is tedious at best. This used to be about 15 or so lines in /etc/network/interfaces. This ranks right up there with using m4 to compile sendmail.cf. The more layers of obfuscation the better.
NOTE TO SYSTEMD DEVELOPERS:
I get the drop a file to configure idea. Makes sense for a number of things. Not so much with networking. This is like the RedHat sysconfig/network-scripts only worse. The fan-out here is outrageous. I could actually write a script using iproute2 and accomplish this with a fraction of the effort. I should be able to trivially define a VLAN on any interface, building a stack up from the physical interfaces:
From 15 lines to 18 Files to create 4 bridged vlans
[root@nas-7] /nas-3/admin/install/systemd-networkd<351>ls /tmp/systemd-network/ bond1.1099.netdev bond1.1100.network bond1.1102.netdev bond1.netdev br0.1099.network br0.1101.netdev br0.1102.network bond1.1099.network bond1.1101.netdev bond1.1102.network bond1.network br0.1100.netdev br0.1101.network br0.netdev bond1.1100.netdev bond1.1101.network bond1.br0.network br0.1099.netdev br0.1100.network br0.1102.netdev br0.network [root@nas-7] /nas-3/admin/install/systemd-networkd<354>iflist Interface |IP Address |Broadcast |Point-Point|Netmask | ----------|----------------|-------------|-----------|-------------| lo |127.0.0.1/8 | | |255.0.0.0 | eth0 | | | | | eth1 | | | | | eth2 | | | | | eth3 | | | | | bond1 | | | | | br0.1099 |10.29.99.254/24 |10.29.99.255 | |255.255.255.0| br0.1100 |10.29.100.254/24|10.29.100.255| |255.255.255.0| br0.1101 |10.29.101.254/24|10.29.101.255| |255.255.255.0| br0.1102 |10.29.102.254/24|10.29.102.255| |255.255.255.0| br0 |10.29.0.9/24 |10.29.0.255 | |255.255.255.0| bond1.1099| | | | | bond1.1100| | | | | bond1.1101| | | | | bond1.1102| | | | |
I suggest you remove all the other networking cruft:
- apt-get -y purge ifupdown network-manager avahi-daemon . . .
I hacked in “line” for a line_edit binary I wrote/use if it can't find it. Might give you grief, just comment out the cmd_ok at the bottom and manually move the files if it doesn't fly. There are surely some issues with this, I have done a file-by-file comparison, seems to be pretty close. Not sure if LLDP should be on the bridge or the physical with a bond or whatever. The setup seems to match my working manual configs almost to the letter. I haven't fully verified any of this from scratch, as there are some manual additions to some of the working files. It should produce working output.
Hack up the variables at the top of the script to meet your needs.
#!/bin/sh # # Script: create_network # # Create the necessary files for systemd to create bridged vlan interfaces # against a LAG or an interface. Not super pretty # # Last Modified: 2023-04-06 16:09:48 # Pick A scenario: # To LAG multiple interfaces use these two BRIDGE_DEV="bond1" BOND_IFACES="eth0 eth1 eth2 eth3" # -- OR -- # To just use a single interface for the bridge #BRIDGE_DEV="eth0" # BRIDGE_PREFIX="br0" VLAN_LIST="1099 1100 1101 1102" # Bind addresses as desired to the various bridges, front end of variable should match prefix # Format is BRIDGE_VLAN_WORD br0__address="10.29.0.13/24" br0__gateway="10.29.0.1" br0_1099_address="10.29.99.253/24" br0_1100_address="10.29.100.253/24" br0_1101_address="10.29.101.253/24" br0_1102_address="10.29.102.253/24" br0_1102_gateway="10.29.102.1" # Some default cruft to the primary bridge interface DOMAIN_LIST="i.ksmith.com i.cfns.net ksmith.com cfns.net" DNS_LIST="10.29.0.30 10.29.1.20 10.29.0.1" # Salt and pepper TMP_FOLDER=/tmp/systemd-network NETWORK_FOLDER=/etc/systemd/network #---------------------------------------------------------------------- # CMD_OK # Run command with confirmation #---------------------------------------------------------------------- cmd_ok() { echo "$1" if [ -x /usr/local/bin/line_edit ] then ok=`line_edit 1 -u -p "OK (Y/N)? "` else /bin/echo "OK (Y/N)?" && ok=`line` fi case "$ok" in Y) eval "$1" ;; N) : ;; esac } #---------------------------------------------------------------------- # CREATE_BASE #---------------------------------------------------------------------- create_base() { cat - <<EOF_BASE > /$TMP_FOLDER/$base.network # # File: $base.network # [Match] Name=$base [Network] Bridge=$bridge LLDP=true EmitLLDP=true EOF_BASE } #---------------------------------------------------------------------- # CREATE_BOND #---------------------------------------------------------------------- create_bond() { cat - <<EOF_BOND_NETDEV > $TMP_FOLDER/$base.netdev # # $base.netdev # [NetDev] Name=$base Description=Primary LAN LAG Kind=bond [Bond] Mode=802.3ad EOF_BOND_NETDEV ( echo "#" echo "# $base.network" echo "#" echo "[Match]" for iface in $BOND_IFACES do echo "Name=$iface" done echo "" echo "[Network]" echo "Bond=$base" ) > $TMP_FOLDER/$base.network cat - <<EOF_BASE > /$TMP_FOLDER/$base.${BRIDGE_PREFIX}.network # # File: $base.${BRIDGE_PREFIX}.network # [Match] Name=$base [Network] Bridge=$bridge LLDP=true EmitLLDP=true EOF_BASE } #---------------------------------------------------------------------- # CREATE_BRIDGE #---------------------------------------------------------------------- create_bridge() { cat - <<EOF_BRIDGE_NETDEV > $TMP_FOLDER/$bridge.netdev [NetDev] Name=$bridge Kind=bridge EOF_BRIDGE_NETDEV cat - <<EOF_BRIDGE_NETWORK > $TMP_FOLDER/$bridge.network [Match] Name=$bridge [Network] EOF_BRIDGE_NETWORK eval "address=\$${BRIDGE_PREFIX}_${vlan_id}_address" [ "$address" != "" ] && echo "Address=$address" >> $TMP_FOLDER/$bridge.network eval "gateway=\$${BRIDGE_PREFIX}_${vlan_id}_gateway" [ "$gateway" != "" ] && echo "Gateway=$gateway" >> $TMP_FOLDER/$bridge.network # DNS/DOMAIN only on primary bridge ? if [ "$vlan_id" = "" ] then echo "Domains=$DOMAIN_LIST" >> $TMP_FOLDER/$bridge.network for dns in $DNS_LIST do echo "DNS=$dns" >> $TMP_FOLDER/$bridge.network done fi } #---------------------------------------------------------------------- # CREATE_VLAN #---------------------------------------------------------------------- create_vlan() { # First the Device definition cat - <<EOF_VLAN_NETDEV > $TMP_FOLDER/$base.$vlan_id.netdev # # $base.$vlan_id.netdev # [NetDev] Name=$base.$vlan_id Kind=vlan [VLAN] Id=$vlan_id EOF_VLAN_NETDEV # Then the Network definition cat - <<EOF_VLAN_NETWORK > $TMP_FOLDER/$base.$vlan_id.network # # $base.$vlan_id.network # [Match] Name=$base.$vlan_id [Network] Bridge=$bridge EOF_VLAN_NETWORK } #---------------------------------------------------------------------- # MAIN #---------------------------------------------------------------------- arg="$1" rm -rf $TMP_FOLDER mkdir $TMP_FOLDER || exit 255 vlan_id= for base in $BRIDGE_DEV do bridge=$BRIDGE_PREFIX case "$base" in bond*) create_bond ; base_path=$TMP_FOLDER/$base.${BRIDGE_PREFIX}.network ;; eth*) create_base ; base_path=$TMP_FOLDER/$base.network ;; esac create_bridge for vlan_id in $VLAN_LIST do bridge=$BRIDGE_PREFIX.$vlan_id echo "VLAN=$base.$vlan_id" >> $base_path create_vlan $vlan_id bridge="$BRIDGE_PREFIX.$vlan_id" create_bridge done done echo "" ls $TMP_FOLDER echo "" echo "" cmd="mv $NETWORK_FOLDER $NETWORK_FOLDER.old" cmd="$cmd && cp -va $TMP_FOLDER $NETWORK_FOLDER" cmd_ok "$cmd"