LFCE 24 🐧 VLAN Configuration with 802.1Q
The previous chapter established the concepts: VLAN tags are four-byte headers that separate broadcast domains on a shared physical link, and Linux presents each VLAN as a virtual interface. This chapter is the configuration sequence. It covers the kernel module that provides 802.1Q support, the ip link commands that create and verify VLAN interfaces, the persistence mechanisms for the three major network managers, and the stacking pattern that places VLANs on top of bonds and bridges.
The distinction between a VLAN that works in a running kernel and one that survives a reboot is the central concern. ip link add creates an interface that disappears on restart. nmcli, Netplan, and systemd-networkd write the same configuration to files that are applied at boot. The running configuration is verified with ip -d link show; the persistent configuration is verified by rebooting.
Key point: The VLAN interface inherits the parent’s MTU by default. Tagged frames add four bytes, which can cause fragmentation or drops if the path MTU is exactly the parent’s MTU. The parent interface must be up before the VLAN interface can transmit, and the switch port must be configured as a trunk (802.1Q) if the host is expected to send and receive tagged frames .
Why 802.1Q configuration requires explicit steps
The module-loading problem.
Linux supports 802.1Q through the 8021q kernel module. On many distributions, the module loads automatically when the first VLAN interface is created. On minimal systems, it may not. The modprobe 8021q command ensures the module is present before configuration begins, and writing 8021q to /etc/modules-load.d/8021q.conf (or /etc/modules on older systems) makes it load at boot . Without the module, ip link add type vlan fails with an error about an unknown link type.
The parent-interface problem.
A VLAN interface is a child of a physical interface. The parent must be up before the VLAN can pass traffic. A common mistake is to create the VLAN interface, assign an address, and bring it up while the parent remains down. The VLAN interface appears in ip link but cannot transmit because the underlying physical link is inactive. The correct sequence brings up the parent first, then creates and configures the VLAN .
The switch-configuration problem.
A Linux host sending tagged frames expects the switch port to accept tags. If the switch port is configured as an access port for a single VLAN, it strips tags on ingress and sends untagged frames on egress. The host’s tagged frames are either dropped or assigned to the native VLAN. The switch port must be a trunk that allows the VLAN IDs the host is configured to use. The host configuration and the switch configuration must match, and the host side cannot compensate for a switch that is not passing the tags .
a. Creating and verifying VLAN interfaces
The ip link add command creates a VLAN interface. The link parameter names the parent, the name parameter sets the interface name, and the type vlan with id specifies the VLAN ID.
# Ensure the 8021q module is loaded
modprobe 8021q
lsmod | grep 8021q
# Bring up the parent interface first
ip link set eth0 up
# Create VLAN 100 on eth0
ip link add link eth0 name eth0.100 type vlan id 100
# Verify the VLAN association
ip -d link show eth0.100
# Output includes: vlan protocol 802.1Q id 100
# Assign an IP address and bring up the VLAN interface
ip addr add 192.168.100.1/24 dev eth0.100
ip link set eth0.100 up
The -d flag in ip -d link show displays the VLAN ID and protocol. Without it, the output looks like a normal interface and the VLAN association is invisible. The output vlan protocol 802.1Q id 100 confirms that the interface is tagged with VLAN 100 .
Multiple VLANs can be created on the same parent. Each is an independent interface with its own address and routing entries. Traffic sent on eth0.100 is tagged with 100; traffic on eth0.200 is tagged with 200. The physical interface carries both tagged streams, and the switch separates them based on the tags .
# Create a second VLAN on the same parent
ip link add link eth0 name eth0.200 type vlan id 200
ip addr add 192.168.200.1/24 dev eth0.200
ip link set eth0.200 up
# List all VLAN interfaces
ip link show type vlan
To inspect the tags on the wire, tcpdump on the parent interface with the -e flag shows the Ethernet headers, including the 802.1Q tag. The vlan filter restricts the capture to tagged frames .
# Capture tagged frames on the parent
tcpdump -i eth0 -e -n vlan
b. Persistent configuration across network managers
The ip commands modify the running kernel only. Persistence requires the distribution’s network manager. The three most common mechanisms are NetworkManager (nmcli), Netplan, and systemd-networkd.
NetworkManager creates a VLAN connection with type vlan, the parent interface with dev, and the VLAN ID with id. The connection profile is automatically applied at boot.
# Create VLAN 100 on eth0 with a static address
nmcli connection add \
type vlan \
con-name "vlan100" \
dev eth0 \
id 100 \
ipv4.method manual \
ipv4.addresses "192.168.100.1/24"
# Activate the connection
nmcli connection up "vlan100"
# Verify
nmcli connection show "vlan100"
ip -d link show eth0.100
The con-name can be any descriptive string; the interface name is generated from the parent and VLAN ID unless ifname is specified. NetworkManager handles the interface creation, the tagging, and the IP assignment in a single persistent profile .
Netplan uses a vlans section in the YAML configuration. The VLAN is defined with an id and a link to the parent interface. The parent is defined in the ethernets section, typically without an address if it is a pure trunk.
# /etc/netplan/01-vlans.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: false
vlans:
eth0.100:
id: 100
link: eth0
addresses:
- 192.168.100.1/24
Apply with netplan apply. The VLAN interface is created at boot by the backend renderer (systemd-networkd or NetworkManager, depending on the renderer setting) .
systemd-networkd uses a .netdev file to define the VLAN and a .network file to assign the address. The .netdev specifies the kind (vlan) and the ID. The .network file for the parent attaches the VLAN.
# /etc/systemd/network/10-vlan100.netdev
[NetDev]
Name=vlan100
Kind=vlan
[VLAN]
Id=100
# /etc/systemd/network/20-eth0.network
[Match]
Name=eth0
[Network]
VLAN=vlan100
# /etc/systemd/network/30-vlan100.network
[Match]
Name=vlan100
[Network]
Address=192.168.100.1/24
Restart systemd-networkd to apply. The .netdev file creates the interface, and the .network files attach it to the parent and assign the address .
c. Stacking VLANs on bonds and bridges
VLANs are frequently stacked on top of bonds for redundancy or bridges for virtualization. The configuration pattern is the same: the bond or bridge is the parent, and the VLAN interface is created on top of it.
# Create a bond first (active-backup)
ip link add bond0 type bond mode active-backup miimon 100
ip link set eth0 master bond0
ip link set eth1 master bond0
ip link set bond0 up
# Create a VLAN on the bond
ip link add link bond0 name bond0.100 type vlan id 100
ip addr add 10.10.0.1/24 dev bond0.100
ip link set bond0.100 up
The bond carries tagged frames, and the VLAN interface provides the untagged view for the kernel. If the bond fails over from eth0 to eth1, the VLAN interface remains up because the bond remains up. This is the standard pattern for servers that need both link redundancy and network segmentation .
For bridges, the VLAN interface can be enslaved to the bridge, or the bridge itself can be VLAN-aware. The simpler pattern is to create the VLAN interface and attach it to the bridge as a port. The bridge then forwards frames for that VLAN between the VLAN interface and other ports.
# Create a bridge
ip link add name br0 type bridge
ip link set br0 up
# Create a VLAN interface on a physical parent
ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up
# Attach the VLAN interface to the bridge
ip link set eth0.100 master br0
The bridge does not need to be VLAN-aware in this pattern because the VLAN tagging is handled by the VLAN interface before the frames reach the bridge. The bridge sees untagged frames on eth0.100 and forwards them to other ports in the same bridge .
Complete Example Session
# ============================================
# PART 1: LOAD THE 8021Q MODULE
# ============================================
modprobe 8021q
lsmod | grep 8021q
# Make it persistent
echo "8021q" > /etc/modules-load.d/8021q.conf
# ============================================
# PART 2: BRING UP THE PARENT INTERFACE
# ============================================
ip link set eth0 up
ip link show eth0
# The parent must be UP before the VLAN can transmit
# ============================================
# PART 3: CREATE THE VLAN INTERFACE
# ============================================
ip link add link eth0 name eth0.100 type vlan id 100
# ============================================
# PART 4: VERIFY THE VLAN ASSOCIATION
# ============================================
ip -d link show eth0.100
# Output includes: vlan protocol 802.1Q id 100
# ============================================
# PART 5: ASSIGN ADDRESS AND BRING UP
# ============================================
ip addr add 192.168.100.1/24 dev eth0.100
ip link set eth0.100 up
# ============================================
# PART 6: CREATE A SECOND VLAN
# ============================================
ip link add link eth0 name eth0.200 type vlan id 200
ip addr add 192.168.200.1/24 dev eth0.200
ip link set eth0.200 up
# ============================================
# PART 7: INSPECT TAGGED TRAFFIC
# ============================================
tcpdump -i eth0 -e -n vlan
# Frames show 802.1Q tags with VLAN IDs 100 and 200
# ============================================
# PART 8: PERSIST WITH NMCLI
# ============================================
nmcli connection add type vlan con-name vlan100 dev eth0 id 100 \
ipv4.method manual ipv4.addresses "192.168.100.1/24"
nmcli connection up vlan100
nmcli connection show vlan100
# ============================================
# PART 9: STACK VLAN ON A BOND
# ============================================
ip link add bond0 type bond mode active-backup miimon 100
ip link set eth0 master bond0
ip link set eth1 master bond0
ip link set bond0 up
ip link add link bond0 name bond0.100 type vlan id 100
ip addr add 10.10.0.1/24 dev bond0.100
ip link set bond0.100 up
# ============================================
# PART 10: VERIFY PERSISTENCE AFTER REBOOT
# ============================================
# After reboot:
ip link show type vlan
ip -d link show eth0.100
# The VLAN interface should reappear with the same ID
The ten parts demonstrate the complete configuration lifecycle: module loading, parent interface preparation, VLAN creation, verification, address assignment, traffic inspection, persistence with nmcli, and stacking on a bond. The critical verification is ip -d link show, which confirms the VLAN ID association.
Quick Reference
VLAN Configuration Commands
| Task | Command |
|---|---|
| Load module | modprobe 8021q |
| Create VLAN | ip link add link eth0 name eth0.100 type vlan id 100 |
| Verify VLAN | ip -d link show eth0.100 |
| Assign IP | ip addr add <addr>/<prefix> dev eth0.100 |
| Bring up | ip link set eth0.100 up |
| Delete VLAN | ip link delete eth0.100 |
| Capture tags | tcpdump -i eth0 -e -n vlan |
Persistence Methods
| System | Method | Key Parameters |
|---|---|---|
| NetworkManager | nmcli connection add type vlan | dev, id, ipv4.method |
| Netplan | YAML vlans: section | id, link, addresses |
| systemd-networkd | .netdev + .network files | Kind=vlan, Id, VLAN= |
Stacking Patterns
| Parent | VLAN Command | Use Case |
|---|---|---|
| Physical NIC | ip link add link eth0 name eth0.100 ... | Direct trunk to switch |
| Bond | ip link add link bond0 name bond0.100 ... | Redundancy + segmentation |
| Bridge | ip link set eth0.100 master br0 | Virtualization |
Best Practices
✅ Do This:
# Load the module before configuration
modprobe 8021q # ✅
# Bring up the parent before creating the VLAN
ip link set eth0 up # ✅
# Verify the VLAN ID with ip -d
ip -d link show eth0.100 # ✅
# Assign the IP to the VLAN interface
ip addr add 192.168.100.1/24 dev eth0.100 # ✅
# Persist with the network manager
nmcli connection add type vlan ... # ✅
# Stack VLANs on bonds for redundancy
ip link add link bond0 name bond0.100 type vlan id 100 # ✅
❌ Don’t Do This:
# Create a VLAN on a down parent
ip link add link eth0 name eth0.100 type vlan id 100 # ❌ if eth0 down
# Assign an IP to the parent in a trunk configuration
ip addr add 192.168.1.1/24 dev eth0 # ❌
# Assume the VLAN works without switch trunk configuration
# The switch must allow the VLAN ID # ❌
# Use vconfig (deprecated)
vconfig add eth0 100 # ❌
# Forget to verify the VLAN ID after creation
ip link show eth0.100 # Does not show VLAN ID # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| VLAN interface cannot transmit | Parent interface is down | ip link set eth0 up |
| VLAN ID not shown | Used ip link show instead of ip -d | ip -d link show eth0.100 |
| Traffic dropped by switch | Switch port not configured as trunk | Configure trunk allowing the VLAN |
| VLAN lost after reboot | ip link add is not persistent | Use nmcli, Netplan, or systemd-networkd |
| Tagged frames not visible in tcpdump | VLAN offload hides tags | Disable offload or capture on parent with -e |
| MTU issues | Tag adds 4 bytes | Adjust MTU if path MTU is tight |
Real-World Examples
1. Create a VLAN
ip link add link eth0 name eth0.100 type vlan id 100
2. Verify VLAN ID
ip -d link show eth0.100 | grep vlan
3. Assign IP to VLAN
ip addr add 192.168.100.1/24 dev eth0.100
4. Create multiple VLANs
ip link add link eth0 name eth0.100 type vlan id 100
ip link add link eth0 name eth0.200 type vlan id 200
5. Persist with nmcli
nmcli connection add type vlan con-name vlan100 dev eth0 id 100 ipv4.addresses 192.168.100.1/24
6. Persist with Netplan
vlans:
eth0.100:
id: 100
link: eth0
addresses: [192.168.100.1/24]
7. Stack VLAN on bond
ip link add link bond0 name bond0.100 type vlan id 100
8. Capture tagged traffic
tcpdump -i eth0 -e -n vlan
9. Delete a VLAN
ip link delete eth0.100
10. Check module loaded
lsmod | grep 8021q
Visual
The Configuration Sequence
┌──────────────────────────────────────────────────────────────┐
│ VLAN CONFIGURATION ORDER │
│ │
│ Step 1: Load module │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ modprobe 8021q │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 2: Bring up parent │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ip link set eth0 up │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 3: Create VLAN │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ip link add link eth0 name eth0.100 type vlan id 100 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 4: Verify │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ip -d link show eth0.100 → vlan id 100 │ │
│ └────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 5: Assign IP and bring up │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ip addr add ... dev eth0.100; ip link set eth0.100 up │ │
│ └────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
Persistence Decision
┌──────────────────────────────────────────────────────────────┐
│ CHOOSING A PERSISTENCE METHOD │
│ │
│ Which distribution? │
│ │ │
│ ├── RHEL/CentOS/Fedora │
│ │ └── nmcli connection add type vlan │
│ │ │
│ ├── Ubuntu (Netplan) │
│ │ └── YAML vlans: section + netplan apply │
│ │ │
│ └── Arch/other systemd-networkd │
│ └── .netdev + .network files │
│ │
│ All three create the same result: │
│ - VLAN interface exists after boot │
│ - Correct VLAN ID │
│ - IP address assigned │
└──────────────────────────────────────────────────────────────┘
VLAN on Bond Stacking
┌──────────────────────────────────────────────────────────────┐
│ VLAN ON BOND: REDUNDANCY + SEGMENTATION │
│ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ bond0.100 (10.10.0.1/24) ← VLAN interface │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ bond0 (no IP) ← Trunk (tagged frames) │ │
│ │ ┌────────┐ ┌────────┐ │ │
│ │ │ eth0 │ │ eth1 │ ← Physical slaves │ │
│ │ └────────┘ └────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ If eth0 fails, bond0 fails over to eth1. │
│ bond0.100 remains up; the VLAN ID is preserved. │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Kernel module | 8021q |
| Create VLAN | ip link add link <parent> name <parent>.<id> type vlan id <id> |
| Verify VLAN | ip -d link show <vlan> |
| Persistence (RHEL) | nmcli connection add type vlan |
| Persistence (Ubuntu) | Netplan vlans: section |
| Persistence (systemd) | .netdev + .network files |
| Parent requirement | Must be up before VLAN |
| Switch requirement | Trunk port allowing the VLAN ID |
| Stacking | VLAN on bond or bridge for redundancy/segmentation |
Key takeaways:
- The 8021q module must be loaded. On some systems it loads automatically; on others,
modprobe 8021qis required. Make it persistent by writing it to/etc/modules-load.d/. - The parent interface must be up. A VLAN interface on a down parent appears in
ip linkbut cannot transmit. Bring up the parent first, then create the VLAN . ip -d link showis the verification command. Without the-dflag, the VLAN ID is invisible. The outputvlan protocol 802.1Q id 100confirms the association .- Persistence depends on the network manager.
nmclifor RHEL, Netplan for Ubuntu, and systemd-networkd files for Arch. Each writes the configuration to disk and applies it at boot . - The switch port must be a trunk. The host sends tagged frames, and the switch must be configured to accept them. An access port strips tags and cannot carry multiple VLANs .
- VLANs stack on bonds and bridges. The bond provides redundancy, and the VLAN provides segmentation. The configuration pattern is the same: the bond or bridge is the parent, and the VLAN interface is created on top of it .
Remember: VLAN configuration is a sequence of dependencies. The module must be loaded. The parent must be up. The VLAN interface must be created with the correct ID. The IP address belongs on the VLAN interface, not the parent. The switch must be configured to match. And the configuration must be persisted through the network manager, or it disappears on reboot. Verify each step with ip -d link show and tcpdump, and the tagged traffic will flow as configured.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!