linuxlab.io
Tutorials▾
  • Linux & networking
    File system, processes, TCP/IP, BGP and OSPF
    →
  • Terraform & IaC
    HCL, state, plan/apply on a LocalStack sandbox
    →
  • Git & GitHub
    Object model, plumbing, branching, GitHub Actions
    →
All tutorials →
PricingAboutSign inCreate account
/
  • Introduction
  • Lessons
  • How it works
  • Simulator
  • Knowledge base
  • Interview prep
Index
Categories
All entries
Footer
linuxlab-TutorialsPricingAboutPrivacy & cookies
Copyright © 2026 LinuxLab. All rights reserved.
home/linux/kb/Networking: L2 / L3/linux-bridge

kb/network-l2-l3 ── Networking: L2 / L3 ── intermediate

Linux Bridge: Software Switch

A bridge is a software L2 switch in the Linux kernel. It learns MACs in the FDB and forwards frames between interfaces. It underpins the Docker default network, KVM bridge, and libvirt. With vlan_filtering it emulates a managed switch.

view as markdownaka: bridge, br0, brctl, linux-bridge

What a bridge is

A bridge behaves like an L2 switch: it accepts [[ethernet-frame|Ethernet frames]] on one port, reads the dst-MAC, looks it up in the FDB (forwarding DB), and sends the frame to the right port. If the MAC is unknown, it floods to all ports except the source.

Unlike routing (L3), a bridge does not rewrite addresses or inspect IP headers. This is transparent L2 forwarding.

Why you need it in Linux

  • Docker - the bridge network driver creates docker0 and connects containers through [[veth-pair|veth pairs]]
  • KVM/libvirt - VMs have tap interfaces attached to a bridge
  • VLAN-aware bridge - replaces a full managed switch in software-defined data centers
  • Container labs (containerlab, mininet) - isolated topologies
  • Network namespaces - connecting netns to each other is done through bridge + veth

Creating a bridge

bash
# Create
ip link add br0 type bridge
ip link set br0 up
# Add interfaces
ip link set eth0 master br0
ip link set eth1 master br0
# IP on the bridge itself (for management)
ip addr add 192.168.1.1/24 dev br0

After this, eth0 and eth1 become slave ports: their own IP addresses lose meaning, and everything works through br0.

FDB: forwarding database

The bridge learns MAC addresses the same way a physical switch does:

bash
$ bridge fdb show
aa:bb:cc:11:22:33 dev eth0 master br0
aa:bb:cc:44:55:66 dev eth1 master br0
33:33:00:00:00:01 dev br0 self permanent

Entries fall into three kinds:

  • dynamic - learned from passing traffic, expire after 300 s (bridge_fdb_aging)
  • static - added manually or by an application, do not expire
  • permanent - system entries (multicast, local MAC)

VLAN-aware bridge

The classic bridge is a single [[broadcast-domain|broadcast domain]]. A bridge with vlan_filtering=1 behaves like a managed switch with [[vlan-and-trunk|VLANs]]:

bash
# Enable VLAN filtering
ip link set br0 type bridge vlan_filtering 1
# eth0 - access port in VLAN 10
bridge vlan add dev eth0 vid 10 pvid untagged
bridge vlan del dev eth0 vid 1
# eth1 - trunk with VLAN 10 and 20
bridge vlan add dev eth1 vid 10 tagged
bridge vlan add dev eth1 vid 20 tagged
# Verify
bridge vlan show

One bridge handles many VLANs and ports of different types.

STP: Spanning Tree Protocol

If a bridge forms a loop (two bridges connected in both directions), broadcasts circulate forever and the network collapses. STP (802.1D) detects loops and blocks one of the ports:

bash
ip link set br0 type bridge stp_state 1

By default, Linux has STP disabled. It is not needed in Docker or KVM where the topology is fixed. At the boundary with a physical network, enable it.

Multicast and IGMP snooping

A bridge without snooping floods multicast to all ports (like broadcast). With IGMP snooping it tracks group subscriptions and sends only to interested ports:

bash
ip link set br0 type bridge mcast_snooping 1

This matters when the bridge has many ports and heavy multicast traffic (video streaming, Avahi, Bonjour).

Docker bridge: under the hood

What Docker does on docker run:

  1. Creates a pair veth0a (in the host netns) and veth0b (in the container netns)
  2. veth0b is renamed to eth0 inside the container
  3. veth0a is attached to the docker0 bridge
  4. The container gets an IP from the docker0 subnet
  5. An iptables NAT rule on the host handles outbound traffic

This gives containers L2 connectivity to each other (through docker0) and L3 connectivity to the outside (through NAT).

OVS: the alternative

Open vSwitch is a more advanced replacement for the Linux bridge: OpenFlow, per-port QoS, finer VLAN control. It is installed separately (apt install openvswitch-switch). For straightforward tasks the vanilla bridge is cheaper and simpler.

When something goes wrong

  • Containers cannot ping each other - check that both interfaces have master br0 and that bridge fdb shows their MACs
  • Slow performance - confirm that the MTU is the same on the bridge and all slave interfaces
  • Multicast is slow - enable mcast_snooping
  • Network died after connecting two bridges - you have a loop; enable STP
  • VLAN does not work - you forgot vlan_filtering=1 on the bridge, or the PVID does not match on both ports
  • net.bridge.bridge-nf-call-iptables=1 loads the CPU - the bridge is proxying traffic into iptables; this is often disabled for container networks

§ команды

bash
ip link add br0 type bridge

Create a bridge. Modern replacement for the deprecated 'brctl addbr'.

bash
ip link set eth0 master br0

Attach eth0 as a slave port to br0.

bash
bridge link show

List all ports in all bridges with their state (forwarding/blocking).

bash
bridge fdb show br br0

Show the FDB table: which MACs have been learned and on which port.

bash
bridge vlan show

Show VLAN assignments on the ports of a vlan-aware bridge.

bash
ip -d link show br0

-d prints bridge parameters: stp_state, vlan_filtering, ageing_time.

§ см. также

  • veth-pairveth pairA veth pair is two linked virtual Ethernet interfaces. Whatever enters one end exits the other. It is the basic building block of all Linux container networks.
  • mac-addressMAC AddressMAC address is a 48-bit hardware identifier for a network interface, written as `aa:bb:cc:dd:ee:ff`. It is unique within an L2 segment and is used in [[ethernet-frame]] for L2 addressing.
  • vlan-and-trunkVLAN: 802.1Q Virtual LAN and Trunk PortsVLAN logically splits one physical switch into multiple L2 segments. The 802.1Q tag adds 4 bytes to an Ethernet frame with a VLAN ID (12 bits, up to 4094 VLANs). Trunk = multiple VLANs on a port, access = one.
Footer
linuxlab-
Copyright © 2026 LinuxLab. All rights reserved.
Tutorials
Pricing
About
Privacy & cookies