A Linux virtual network interface is a network device whose packet input and output are supplied by software rather than by a dedicated hardware port. It still has the same Linux identity as a physical interface: an interface index, a name, link state, statistics, and, when the device type permits them, MAC and IP addresses. What changes between virtual-interface types is the object at the other end and whether they exchange Ethernet frames or IP packets.
Prerequisites
Linux Networking defines network namespaces, network devices, interface addresses, routes, and the rtnetlink API used by
ip.
Choose by the other endpoint
Classify a virtual interface by the object that receives data transmitted through it. The following table identifies that endpoint and the unit passed across the boundary:
| Interface type | Other endpoint | Unit transferred | Main use |
|---|---|---|---|
| veth pair | The peer network interface, often in another network namespace | Ethernet frame | Connect two Linux network stacks |
| bridge | One or more member interfaces plus the host’s own attachment | Ethernet frame | Join interfaces into one Layer-2 segment |
| dummy | No peer or forwarding engine | No useful external transmission path | Hold host-side addresses and interface-scoped state |
| TUN | A file descriptor owned by a userspace process | IP packet | Userspace routing and VPN software |
| TAP | A file descriptor owned by a userspace process | Ethernet frame | Virtual machines and userspace Ethernet processing |
All five appear as network devices, but they are related rather than interchangeable. A veth is a two-ended cable, a bridge is a forwarding object with member ports, and TUN/TAP hands packets or frames to a process.
veth pairs connect network namespaces
A veth pair is two connected virtual Ethernet interfaces. Linux always creates both endpoints together. A frame transmitted on one endpoint is received on the other; if either endpoint is down, the pair’s link state is down.
This example creates a namespace named red, then creates veth-host in the
initial namespace and its peer eth0 directly inside red:
sudo ip netns add red
sudo ip link add veth-host type veth peer name eth0 netns red
sudo ip link set dev veth-host up
sudo ip -n red link set dev lo up
sudo ip -n red link set dev eth0 upveth-host and eth0 are separate network devices with separate interface
indices. The peer relation carries frames between them; it does not
merge the two namespaces’ addresses or routes. A process in red sees eth0
and lo, while a process in the initial namespace sees veth-host.
Linux bridges join Ethernet interfaces
A Linux bridge is a kernel implementation of an Ethernet bridge, the Layer-2 device defined by IEEE 802.1Q. It learns which source MAC addresses arrive on each member port and records them in a forwarding database (FDB). For a unicast frame whose destination MAC is in the FDB, the bridge transmits the frame through the recorded port. Unknown unicast, broadcast, and relevant multicast traffic is flooded to the eligible ports.
Attach a veth endpoint to a bridge
The diagram shows the two different objects in a container-style topology.
The veth pair carries a frame across the namespace boundary; cni0 chooses
which bridge port or host attachment receives that frame.
The following commands add a bridge and make the existing veth-host
interface one of its member ports:
sudo ip link add name cni0 type bridge
sudo ip link set dev veth-host master cni0
sudo ip link set dev cni0 updev veth-host selects the interface being changed. master cni0 stores its
membership in the bridge. The operation does not turn the veth into a bridge:
frames still cross the veth pair first and are then submitted to the bridge
through the host-side member port.
The bridge device is also the host attachment
Linux exposes cni0 itself as a network interface as well as maintaining its
member-port set and FDB. Assigning an address to cni0 attaches the host IP
stack to that bridged Ethernet segment:
sudo ip address add 192.0.2.1/24 dev cni0
sudo ip -n red address add 192.0.2.2/24 dev eth0For a connection from 192.0.2.2 to 192.0.2.1, the namespace emits an
Ethernet frame through eth0; the peer veth-host receives it and submits it
to the bridge; the destination MAC identifies the bridge’s host attachment;
the host IP stack then performs local IP and socket delivery. For a destination
behind another member port, the FDB selects that port instead.
The address on cni0 does not make the bridge an IP router. Bridging chooses
an output port from Ethernet state. Routing is a later host-IP operation used
when the host accepts a frame addressed to itself and must forward the enclosed
IP packet to another network; that requires appropriate routes and IP
forwarding to be enabled.
Dummy interfaces hold host-side state without a peer
A dummy interface is a network device with no peer, member ports, hardware queue, or userspace file descriptor. It can own interface addresses and interface-scoped configuration, but it does not connect those addresses to an Ethernet segment or another namespace.
sudo ip link add name service0 type dummy
sudo ip address add 192.0.2.10/32 dev service0
sudo ip link set dev service0 upThis is the smaller device type when the requirement is only a host-owned address with a lifetime independent of a physical NIC. An empty bridge can also own an address, but with no member ports its FDB has nothing to forward. Choose a bridge when Ethernet-like ports may join the segment; choose dummy when no Layer-2 segment exists.
TAP and TUN interfaces
TUN/TAP is a Linux driver that connects a kernel network interface to file descriptors opened by a userspace process. TUN and TAP share the same creation API but expose different units to the process:
| Device | Kernel presents | Userspace reads and writes | Can be a bridge port |
|---|---|---|---|
| TUN | A Layer-3 point-to-point-style interface | IP packets | No |
| TAP | An Ethernet interface with a MAC address | Ethernet frames | Yes |
Create the interface through /dev/net/tun
The caller opens the TUN/TAP character device and uses TUNSETIFF to create or
attach to a network interface. This abridged function creates vpn0; its
caller owns the returned descriptor and must keep reading and writing it:
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
int open_tun(void) {
int fd = open("/dev/net/tun", O_RDWR);
struct ifreq ifr = {0};
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, "vpn0", IFNAMSIZ - 1);
ioctl(fd, TUNSETIFF, &ifr);
return fd;
}IFF_TUN selects IP packets; replacing it with IFF_TAP selects Ethernet
frames. IFF_NO_PI removes the driver’s four-byte packet-information prefix,
so each read or write buffer begins with the IP or Ethernet header described
in the table. Production code must check failures from open and ioctl.
Creating or attaching the interface requires CAP_NET_ADMIN unless ownership
and persistence have been configured by a privileged process.
The descriptor directions are defined from the userspace process’s point of view:
| Process operation | Kernel interpretation | Next step |
|---|---|---|
read(fd, buffer, size) | Take a packet or frame that Linux transmitted through the TUN/TAP interface | The process tunnels, emulates, filters, or otherwise handles it |
write(fd, buffer, size) | Inject a packet or frame as input received on the TUN/TAP interface | Linux performs ingress processing, routing, bridging, or local delivery |
By default, closing the last descriptor removes the interface and its routes.
TUNSETPERSIST changes that lifetime so the interface remains without an open
descriptor; another privileged operation must then remove it.
TUN in a userspace VPN
The upper row follows a plaintext IP packet selected by a route through tun0.
The lower row follows the reverse direction after the VPN process receives and
decrypts an encrypted transport packet.
On outbound traffic, Linux queues the IP packet on tun0; the VPN process
reads it, encrypts it, and sends the ciphertext through a separate TCP or UDP
socket. On inbound traffic, the process receives ciphertext through that
transport socket, decrypts it, and writes the recovered IP packet to the TUN
descriptor. Linux then treats it as input received on tun0. The TUN packet
and the encrypted transport packet are different buffers at different layers.
TAP in a virtual machine
The virtual NIC presented to a guest and the backend used to enter the host network are separate parts of a virtual-machine network path. The frontend may look like virtio-net or an emulated Ethernet card to the guest. After the guest driver submits a frame to that frontend, QEMU must pass the frame to a host backend.
A TAP backend gives QEMU a file descriptor whose other endpoint is one host
Ethernet interface, such as tap0. The two directions have complementary
meanings:
| Direction | QEMU operation | Linux operation |
|---|---|---|
| Guest to host | QEMU obtains an Ethernet frame from the virtual NIC and calls write(tap_fd, frame, size) | The TAP driver submits the frame as input received on tap0; a bridge can then forward it from that member port |
| Host to guest | Linux transmits a frame through tap0 and queues it on the TAP descriptor | QEMU calls read(tap_fd, frame, size) and presents the frame as input received by the guest’s virtual NIC |
TAP is a direct fit because the descriptor is a dedicated Ethernet-frame queue.
The driver also supports multiple queues, while QEMU can combine TAP with
vnet_hdr metadata for checksum and segmentation offload. QEMU can also use
vhost, which moves much of the virtio packet-processing path from QEMU into the
host kernel.
A veth backend requires a packet-socket adapter
TAP is not the only possible host backend. An emulator could bind an
AF_PACKET socket—a Linux socket that sends and receives raw Layer-2
frames—to veth-qemu, one endpoint of a veth pair. Its peer, veth-bridge,
would be the bridge member port.
For guest-to-host traffic, the emulator sends the frame through the packet
socket on veth-qemu. That is transmission on veth-qemu, so the veth driver
delivers it as input on its peer, veth-bridge; the bridge sees the frame arrive
through the veth-bridge member port. In the reverse direction, a frame
transmitted by the bridge through veth-bridge arrives as input on veth-qemu,
where the packet socket can deliver it to the emulator.
This design adds a second network device and a general-purpose packet socket. Packet sockets can observe traffic also processed by the host network stack and can receive copies of locally generated outgoing frames, so the emulator must isolate the endpoint and distinguish the traffic it owns. TAP instead defines one network device whose frame queue terminates directly at the emulator’s file descriptor. This API shape, together with multiqueue and vhost integration, explains why TAP is QEMU’s standard Linux Ethernet backend; it is not a kernel restriction that prevents an emulator from using veth. QEMU also supports other backends, including AF_XDP, a Linux API for userspace packet I/O through queues attached to a network interface.
Why containers normally use veth instead of TUN or TAP
A container and its host share one Linux kernel, even when their processes occupy different network namespaces. A veth pair can therefore transfer frames between their two kernel network stacks directly. No userspace process is needed in the middle.
A virtual machine has a separate guest kernel. Its emulator must therefore join the guest-facing virtual NIC to some host-side backend: TAP is the direct Linux backend, while a packet-socket design can adapt a host interface such as veth. A userspace VPN uses TUN when its process needs to read, encrypt, transport, and reinject IP packets. The endpoints that must exchange packets, and whether one endpoint is a userspace process, determine the interface and API.
Sources
- Linux
ip-link(8)for virtual-link creation and the device types exposed by iproute2. - Linux
veth(4)for paired creation, packet transfer, link state, and namespace placement. - Linux kernel Ethernet bridge documentation for IEEE 802.1Q forwarding, the FDB, member ports, and the Netlink interface.
- Linux kernel TUN/TAP documentation for
/dev/net/tun,TUNSETIFF, descriptor lifetime, and packet formats. - Linux
packet(7)for raw Layer-2 sockets, interface binding, outgoing-frame copies, and transmission semantics. - QEMU network emulation documentation and network options for the separation between guest NIC frontends and TAP, AF_XDP, socket, and other host backends.
See also
- Linux Networking for the network-device, address, route, and rtnetlink model shared by physical and virtual interfaces.
- Linux Namespaces for creation, membership, and lifetime of the isolation boundary that veth pairs commonly connect.
- QEMU and Virtio for the guest side of the TAP frame handoff.