uif: creating untagged (VLAN) network subinterfaces in Linux
Table of Contents
uif.Untagged subinterfaces: why? #
Linux has a very comprehensive Layer-2 networking model.
One thing I’ve always found slight slightly annoying in Linux, though, is the inability to create network subinterfaces that demultiplex and multiplex untagged traffic only (no VLAN). This is possible in some switches and routers, which cleanly models how untagged and VLAN tagged traffic is handled by the system.
This also has some undesirable side-effects:
- When using bridges with
vlan_filtering=0, it’s not possible to only bridge untagged traffic without using L2 ACLs. - Programs that deal with network packets via RAW sockets, or higher level
libraries such as
libpcap(e.g.tcpdump,wireshark), need to manually discard tagged packets if they are only interested in untagged traffic (e.g. using PCAP filters).
Any chance we can leverage 🐝 eBPF to hack something out?
Introducing uif #
uif is as small tool to create (emulate) untagged network subinterfaces
in Linux. These interfaces receive and send untagged (no VLAN) traffic only,
much like VLAN subinterfaces do. It uses eBPF.
uif enables us to:
- Restrict bridging and learning to untagged traffic only on bridges with
vlan_filtering=0. - Restrict traffic ingested by applications sniffing on interfaces to untagged traffic only.
- Make them compatible with TC/TCX BPF programs.
- Have them modeled as a subinterface, with its own
ifindex, etc.
How to use it? #
To create an untagged subinterface eth0.ut over eth0:
../output/uif create eth0
eth0.ut can now be managed using standard Linux tools (e.g. ip), as any
other network device.
As with a VLAN subinterface, if you want IP connectivity for untagged traffic,
IP addresses will (now) need to be added to the eth0.ut instead of eth0.
How does it work? #
uif creates a VLAN 0 subinterface over the target interface with the name
<iface>.ut, and it attaches two small 🐝 eBPF TCX programs on the ingress
and egress paths of <iface>.
These programs push a VLAN 0 tag on ingress and pop the VLAN 0 tag on egress
respectively, to make sure untagged traffic is muxed/demuxed to <iface>.ut
correctly.
Because of the place where TCX eBPF hooks execute, programs such as tcpdump
and wireshark work as expected, transparently, seeing all untagged and
tagged unmodified traffic on <iface>, and only untagged traffic in
<iface>.ut.
Compatibility with VLAN 0 priority tagging #
Since VLAN 0 is (ab)used as a means to mux/demux to/from the main interface,
VLAN 0 priority tagging
is not supported on <iface>.
Next steps #
Some network switches use VLAN 1 for untagged traffic.
It’s possible to sacrifice VLAN 1, or any other VLAN ID for that matter, to “emulate” the untagged subinterface. Most of the work is already done in vlan1 branch. The remaining bit is to - likely - modify the VLAN tag value within the BPF program at load time, instead of recompiling the program on every execution.
Final remarks #
Full disclosure, while writing this puff I realised someone had been using a similar trick using plain TC commands here. The approach is similar, but using eBPF TCX hooks make it easier and more compatible with other eBPF programs.
