6

I'm experimenting with Linux bridges and vlan filtering but I'm having a few problems.

What I have is a VM with a trunk (tagged frames) that arrives on ens19. What I want to do is connect this port to a linux bridge and on this bridge have "virtual" interfaces which are labelled on the vlan I need with a complete TCP/IP stack behind it (that of the host).

For my experiments I'm limiting myself to vlan 3 and 5 but the idea is that it should be easy to extend. The use won't seem huge because it could be replaced by sub-interfaces of ens19. But later on the interest that I will connect the ens19 port with a gretap interface to circulate several vlan on a tunnel.

I've done tests with dummy and tap interfaces but it doesn't work given the nature of these interfaces, it seems to me. I tested with a br0.3 sub-interface but here my client receives the ARP reply but the PING never receives an ICMP reply ...

ip link add name br0 type bridge vlan_filtering 1
ip link set dev br0 up
ip link add link br0 name br0.3 type vlan id 3
ip link set dev ens19 master br0
ip link set ens19 up
ip link set dev br0 up
ip link set dev br0.3 up
ip addr add 10.3.0.106/22 dev br0.3

CLIENT PING > impossible to timeout when br0.3 is up

CLIENT ARP : OK

CLIENT ICMP : NOK

br0 dump

1 Answers1

8

Dumb bridge

With the current setup, no traffic pass: everything is filtered by the VLAN-aware bridge because by default it uses VLAN 1 on all ports and on its bridge self interface. When a frame with VLAN ID 3 arrives or is emitted, as it doesn't match the filter, it's dropped.

To get the current experiment working, just set back the bridge as a "dumb" bridge:

ip link set dev br0 type bridge vlan_filtering 0

Now tagged traffic on ens19 will arrive (tagged) on br0 (if not forwarded elsewhere), will be untagged through br0.3 and reach the routing stack (eg: as type IPv4, ARP or IPv6). Non-tagged traffic if any will also reach the routing stack through br0. Any other VLAN-tagged traffic will be dropped because there's nothing that will claim it: the routing stack itself doesn't understand VLANs.

The bridge will forward VLAN-tagged frames, without considering the meaning of the VLAN IDs, which can cause issues if the same MAC address is used on multiple VLANs. This might confuse the handling of the forwarding database on the bridge or cause duplicates or loops to appear on further equipments, etc.

So indeed a VLAN-aware bridge is preferred.


VLAN-aware bridge

If the bridge has to play a neutral role and the goal is to easily create new per-VLAN ports and even more, to change VLANs on ports without having to delete and recreate an interface (as is needed with VLAN sub-interfaces), then indeed a VLAN-aware bridge is useful. In this configuration, while it's still possible to use VLAN sub-interfaces on top of br0, it can be avoided. One can instead use a veth pair for each such VLAN: one as bridge port, one as interface communicating with the routing stack (that's one use case of veth not involving network namespaces at all).

br0 itself doesn't have to be used for routing, except maybe if using it as management if there's no other physical interface (than ens19) available. Below the setup starts with complete lockdown of any port added including br0 itself by also setting vlan_default_pvid 0 (instead of getting the default Port VLAN ID 1 for everything). This also allows to set immediately bridge ports UP without risking leaks during configuration since by default nothing can pass.

Configuring VLANs on the VLAN-aware bridge uses the bridge vlan command with the newer rtnetlink(7) kernel API. The obsolete brctl command can't do this, because the older kernel API (or /sys) doesn't provide the features for this.

OP's case becomes in successive steps:

  • creation and trunk link

    The bridge should be assigned its own (and unique) MAC address so it doesn't inherit by default the lowest MAC address available on bridge ports, which could change over time: the veth method below might make the bridge change MAC address over time when new VLANs are added, which isn't a real problem for this method, but could affect the VLAN sub-interface method if used conjointly, or affect br0's use when having an IP address itself. On recent systemd-based systems, this is already done by systemd whatever the network manager involved, even if this behavior is unwanted, if it detects a new virtual Ethernet-like interface created without stating its MAC address.

    ip link add name br0 address 12:34:56:78:9a:bc up type bridge vlan_filtering 1 vlan_default_pvid 0
    ip link set dev ens19 up master br0
    
  • optional: have br0 still use VLAN 1 (untagged) transmitted through ens19 (tagged), for example for management:

    bridge vlan add vid 1 dev ens19
    bridge vlan del vid 1 dev br0 self pvid untagged
    

    The bridge interface itself requires the additional self keyword when configuring it.

  • add VLANs on ens19 (VLAN IDs 3 and 5 here):

    bridge vlan add vid 3 dev ens19
    bridge vlan add vid 5 dev ens19
    

    Or if ens19 is to be considered the uplink trunk port, just add all other VLANs on it:

    bridge vlan add vid 2-4094 dev ens19
    

    Use -compressvlans to display back what's on it or there will be 4093 lines of single entries displayed.

    bridge -compressvlans vlan show dev ens19
    

Now the same overall result can be achieved with:

  • either a VLAN sub-interface on top of br0 (using VLAN ID 3 here)

    If the bridge interface (here) or bridge port (next bullet) doesn't have the VLAN ID added to it, no such traffic will pass when the bridge is set as a VLAN-aware bridge.

    The VLAN ID has to be added, still tagged, to br0:

    bridge vlan add vid 3 dev br0 self
    

    As above, all could be added in advance just once:

    bridge vlan add vid 2-4094 dev br0 self
    

    Then the usual VLAN sub-interface is added on top of it:

    ip link add link br0 name br0.3 up type vlan id 3
    ip addr add 10.3.0.106/22 dev br0.3
    

    Changing the VLAN ID associated with the interface (and in common setups to the IP LAN 10.3.0.0/22) requires to delete the sub-interface and recreate a new one with a different VLAN ID: the type vlan interface can't be reconfigured.

  • or a pair of veth interfaces (using VLAN ID 5 here)

    pvid untagged plays the same role as using a VLAN sub-interface: untags from the bridge to the port, tags from the port to the bridge. Only one VLAN ID can be the PVID (and here it's the single VLAN ID in use).

    ip link add name vlan5 up type veth peer name br0vlan5
    ip link set br0vlan5 up master br0
    bridge vlan add vid 5 dev br0vlan5 pvid untagged
    ip addr add 10.3.4.106/22 dev vlan5
    

    Except the chosen names in examples reflect the VLAN ID so this would cause human confusion, the associated VLAN ID can be changed (almost) on the fly (changing it here from 5 to 6):

    bridge vlan del vid 5 dev br0vlan5
    bridge vlan add vid 6 dev br0vlan5 pvid untagged
    

    And if not having already configured all VLANs on ens19, change it there too:

    bridge vlan del vid 5 dev ens19
    bridge vlan add vid 6 dev ens19
    
A.B
  • 6,306