VLAN and Bonds and Bridges in NetworkManager

Over the last decade, NetworkManager has become one of the most widespread network managing solution. Only recently I managed to get my own homelab setup for one of my hypervisors with bonds, vlans and bridges working. Network Bonds to establish backup links, over which I have a default bridge and two separated network bridge adapters, both on their own VLAN. Like this I can transparently connect certain guests into separated networks, all from the hypervisor.

My setup looks like the following:

           -------
---eth0---|       |------------------------------- br0        (192.168.0.50/24)
          | Bond0 |---- vlan.homelab (id=100) ---- br-homelab (192.168.100.24/24)
---eth1---|       |---- vlan.iot (id=201) -------- br-iot     (172.16.87.2/22)
           -------

On this hypervisor I have now three bridge adapters at my disposal:

  • br0 is the default network with no VLAN
  • br-homelab is my homelab network on VLAN 100
  • br-iot is the separated IoT VLAN because they need to be sandboxed

While there are a couple of tutorials available online describing how to achieve this using nmcli commands, I find the configuration files more descriptive for a sysadmin. Therefore this blog post, so you can use them as a template.

If you start from scratch, you might want to use the nmtui utility and create the interfaces therein. Keep the following things in mind:

  1. The Bond is the parent for the default bridge and all vlan interfaces
  2. Bridge adapters go behind a VLAN device or directly behind the bond device

Configuration files

All of the following configuration files must be placed in /etc/NetworkManager/system-connections, owner root:root and file permissions 0400 or 0600 (only root should be able to read), otherwise NetworkManager will refuse to use them.

Let’s start first with the Ethernet adapters and the bond:

# wired1.nncommection
[connection]
id=eth0
permissions=
interface-name=eth0
slave-type=bond
master=bond0
type=ethernet
# wired2.nncommection
[connection]
id=eth1
permissions=
interface-name=eth1
slave-type=bond
master=bond0
type=ethernet
# bond0.nncommection
[connection]
id=bond0
permissions=
interface-name=bond0
type=bond
autoconnect-ports=1
controller=br0
port-type=bridge
[bond]
mode=active-backup
miimon=100

Now let’s configure the default bridge. I have a static IPv4 address and use IPv6 auto-config with one static server address. The 2001:DB8::/32 prefix is not my actual prefix, but pref RFC3849 the prefix for documentation purposes. You also see a neat trick - IPv4 addresses like 192.168.0.50 fit perfectly in a /64 subnet by using ::192:168:0:50 as suffix. If you want to remember the IP addresses of your servers, this is one strategy you can use.

# br0.nmconnection
[connection]
id=br0
permissions=
interface-name=br0
type=bridge
[ipv4]
method=manual
address1=192.168.0.50/24
dns=192.168.0.1
[ipv6]
method=auto
address1=2001:DB8:::192:168:0:50/64
[bridge]
stp=false
forward-delay=15

This should already give you basic connectivity. Next come the VLAN interfaces and their bridges.

# vlan_homelab.nmconnection
[connection]
id=vlan.homelab
type=vlan
controller=br-homelab
interface-name=vlan.homelab
port-type=bridge

[ethernet]

[vlan]
flags=1
id=100
parent=bond0

[bridge-port]
# br_homelab.nmconnection
[connection]
id=br-homelab
type=bridge
autoconnect-ports=1
interface-name=br-homelab

[ethernet]

[bridge]
stp=false

[ipv4]
method=auto

[ipv6]
addr-gen-mode=default
method=auto

[proxy]

And the configuration for the IoT VLAN works then in the same way.

Last tips

While working, I needed to see if I get VLAN packages into the system and found the following tcpdump commands useful:

tcpdump -i bond0 -nn -e  vlan               # check for VLAN packages on the bond
tcpdump -i eth0 'vlan 100'                  # listen for vlan packages from id=100 at the eth0 interface

Happy hacking!