| |

LFCE 24 🐧 VLAN Configuration with 802.1Q

⏱️ Estimated read: 13 min | |

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

TaskCommand
Load modulemodprobe 8021q
Create VLANip link add link eth0 name eth0.100 type vlan id 100
Verify VLANip -d link show eth0.100
Assign IPip addr add <addr>/<prefix> dev eth0.100
Bring upip link set eth0.100 up
Delete VLANip link delete eth0.100
Capture tagstcpdump -i eth0 -e -n vlan

Persistence Methods

SystemMethodKey Parameters
NetworkManagernmcli connection add type vlandev, id, ipv4.method
NetplanYAML vlans: sectionid, link, addresses
systemd-networkd.netdev + .network filesKind=vlan, Id, VLAN=

Stacking Patterns

ParentVLAN CommandUse Case
Physical NICip link add link eth0 name eth0.100 ...Direct trunk to switch
Bondip link add link bond0 name bond0.100 ...Redundancy + segmentation
Bridgeip link set eth0.100 master br0Virtualization

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

PitfallWhy It HappensFix
VLAN interface cannot transmitParent interface is downip link set eth0 up
VLAN ID not shownUsed ip link show instead of ip -dip -d link show eth0.100
Traffic dropped by switchSwitch port not configured as trunkConfigure trunk allowing the VLAN
VLAN lost after rebootip link add is not persistentUse nmcli, Netplan, or systemd-networkd
Tagged frames not visible in tcpdumpVLAN offload hides tagsDisable offload or capture on parent with -e
MTU issuesTag adds 4 bytesAdjust 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

ItemValue
Kernel module8021q
Create VLANip link add link <parent> name <parent>.<id> type vlan id <id>
Verify VLANip -d link show <vlan>
Persistence (RHEL)nmcli connection add type vlan
Persistence (Ubuntu)Netplan vlans: section
Persistence (systemd).netdev + .network files
Parent requirementMust be up before VLAN
Switch requirementTrunk port allowing the VLAN ID
StackingVLAN on bond or bridge for redundancy/segmentation

Key takeaways:

  • The 8021q module must be loaded. On some systems it loads automatically; on others, modprobe 8021q is 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 link but cannot transmit. Bring up the parent first, then create the VLAN .
  • ip -d link show is the verification command. Without the -d flag, the VLAN ID is invisible. The output vlan protocol 802.1Q id 100 confirms the association .
  • Persistence depends on the network manager. nmcli for 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.


Was this helpful?


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!