When running high-density Linux container clusters (Docker, Podman, LXC) or virtual network namespaces, connecting multiple guest environments directly to the physical underlying local area network (LAN) is a frequent requirement. While standard Linux bridge devices and MACVLAN interfaces are common solutions, both present specific operational challenges in enterprise environments.
MACVLAN assigns an entirely unique Media Access Control (MAC) address to each virtual interface. In enterprise data centres and cloud hosting environments, network switches enforce port-security policies that restrict the number of MAC addresses per physical Ethernet port, or Wi-Fi access points actively drop multi-MAC traffic. To solve this limitation, the Linux kernel provides the IPVLAN driver. IPVLAN creates multiple virtual network interfaces that share the single, physical MAC address of the parent NIC while maintaining independent, unique IP addresses. This tutorial explains how to create, configure, and manage IPVLAN interfaces in Linux using ip link in both L2 and L3 operational modes.
IPVLAN Operational Modes: L2 vs L3 Explained
The Linux IPVLAN driver operates in two distinct modes, depending on how you wish traffic to be routed across the network:
- IPVLAN Mode L2 (Layer 2): In L2 mode, the virtual sub-interfaces behave similarly to a bridge. Each child interface shares the physical parent’s MAC address, but handles its own ARP (Address Resolution Protocol) broadcasts and DHCP negotiation. Packets sent between child interfaces on the same parent are switched internally within the Linux kernel, while external traffic is switched on the local broadcast domain.
- IPVLAN Mode L3 (Layer 3): In L3 mode, the parent interface acts as an internal Layer 3 router. The virtual sub-interfaces do not process Layer 2 broadcasts or ARP requests (the parent NIC answers ARP requests for all assigned child IPs). L3 mode delivers superior performance and scalability in large container deployments, although all child interfaces must reside on routed subnets rather than a shared Layer 2 broadcast segment.
Prerequisites and Kernel Module Verification
The IPVLAN driver is compiled into most modern Linux kernels (kernel 3.19 or later). Before creating interfaces, verify that the ipvlan module is loaded:
# Check if the ipvlan kernel module is loaded
lsmod | grep ipvlan
# If not present, load the module into the active kernel
sudo modprobe ipvlan
# Ensure the module automatically loads on boot
echo "ipvlan" | sudo tee -a /etc/modules-load.d/ipvlan.conf
Step 1: Create an IPVLAN Interface in L2 Mode
In this example, assume your primary physical Ethernet adapter is named eth0, and you want to create a child interface named ipvl0 attached to it:
# Create an IPVLAN sub-interface in L2 mode
sudo ip link add link eth0 name ipvl0 type ipvlan mode l2
Assign a unique static IP address from your local physical subnet to the child interface and bring the link state up:
# Assign an IP address to the IPVLAN interface
sudo ip addr add 192.168.1.150/24 dev ipvl0
# Bring the interface online
sudo ip link set ipvl0 up
Verify that the interface is active and inspect its hardware properties:
# Inspect the interface status and MAC address
ip link show dev ipvl0
You will observe that ipvl0 has the exact same MAC address as eth0, ensuring switch port-security limits are never triggered.
Step 2: Create an IPVLAN Interface in L3 Mode
If you are routing traffic across isolated network namespaces or routed container networks, create an IPVLAN device using L3 mode:
# Create an IPVLAN sub-interface in L3 mode
sudo ip link add link eth0 name ipvl1 type ipvlan mode l3
# Assign a routed IP address to the L3 child device
sudo ip addr add 10.100.1.10/24 dev ipvl1
# Bring the link up
sudo ip link set ipvl1 up
Step 3: Move an IPVLAN Interface into a Network Namespace
One of the primary use cases for IPVLAN is isolating container network stacks. You can create an independent network namespace and assign the IPVLAN device directly to it:
# 1. Create a new network namespace named 'testns'
sudo ip netns add testns
# 2. Move the IPVLAN child interface into the new namespace
sudo ip link set ipvl0 netns testns
# 3. Configure the interface inside the namespace
sudo ip netns exec testns ip addr add 192.168.1.150/24 dev ipvl0
sudo ip netns exec testns ip link set ipvl0 up
sudo ip netns exec testns ip link set lo up
# 4. Add the default gateway inside the isolated namespace
sudo ip netns exec testns ip route add default via 192.168.1.1 dev ipvl0
# 5. Test external network connectivity from inside the namespace
sudo ip netns exec testns ping -c 3 1.1.1.1
Configuring IPVLAN Flag Modes (bridge vs private vs vepa)
IPVLAN supports secondary flag modes that govern how child interfaces communicate with one another:
bridge(Default): Child interfaces attached to the same parent can communicate directly with one another through the internal kernel switch.private: Child interfaces are strictly isolated. No child can communicate with any other child on the same parent NIC, even if they reside on the same IP subnet.vepa(Virtual Ethernet Port Aggregator): Traffic between children is reflected out to the external physical switch, requiring the physical switch to support hairpinned switching (802.1Qbg).
# Example: Create an IPVLAN device with private isolation
sudo ip link add link eth0 name ipvl-priv type ipvlan mode l2 private
How to Monitor and Delete IPVLAN Interfaces
To inspect active IPVLAN devices and their assigned parent links:
# Display all link details including IPVLAN type metadata
ip -d link show type ipvlan
# Inspect interface traffic statistics
ip -s link show dev ipvl0
When the interface is no longer required, take down the link and remove it from the kernel:
# Bring the link down
sudo ip link set ipvl0 down
# Delete the IPVLAN interface
sudo ip link del ipvl0