Configuring IGMP Snooping on Linux Bridge: Tame Multicast Flooding in Virtual Switches

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Problem Statement: When Multicast Turns Into Uncontrolled Broadcast

During an off-peak backup window last quarter, our monitoring fired an unexpected alert. Three KVM guests hosting Postgres read replicas suddenly registered p99 latency spikes jumping from 4ms to over 280ms, alongside a steady 4% packet drop rate. Guest metrics revealed the culprit: these VMs were grinding through roughly 65,000 packets per second that had nothing to do with database queries.

Tracing the traffic led to an IPTV test stream and a three-node Corosync cluster sharing the same host bridge (br0). By default, a standard Linux software bridge acts like a dumb hub with multicast frames. It lacks Layer 3 awareness out of the box. Unless configured otherwise, the kernel treats incoming multicast traffic as unknown Layer 2 frames, blindly flooding them out every single active bridge port.

In virtualized production environments, that behavior causes immediate headaches:

  • CPU exhaustion: Every virtual NIC (vnet* / tap) triggers software interrupts in its guest kernel just to inspect and discard irrelevant frames.
  • Bandwidth saturation: High-throughput streams—like a 400 Mbps camera feed or heavy storage heartbeats—eat into shared 10GbE and 25GbE host uplinks.
  • Security risks: Sensitive multicast payloads leak to untrusted tenant VMs residing on the same Layer 2 segment.

Core Concepts: How IGMP Snooping Tames the Bridge

The bridge needs to know who actually asked for the traffic before forwarding it.

What is IGMP Snooping?

Hosts use IGMP (Internet Group Management Protocol) to tell upstream routers which multicast groups they want to receive. IGMP snooping brings that intelligence down to Layer 2. The bridge passively inspects these control messages as they pass through its ports.

Once snooping is turned on, the Linux kernel builds a Multicast Database (MDB). When VM-A emits an IGMP Join for group 239.1.1.1, the kernel links VM-A’s tap interface (say, vnet1) to that multicast IP. When data packets head for 239.1.1.1, the bridge forwards them strictly to vnet1. Uninterested VMs never see a single frame.

The Critical Role of the IGMP Querier

Snooping cannot work without regular status checks. Hosts announce their intent with an initial IGMP Join, but they renew memberships only when asked by periodic "IGMP General Query" packets. In enterprise data centers, a dedicated core switch or multicast router generates these queries. On an isolated virtualization host, however, an upstream querier often does not exist.

Without ongoing queries, group memberships in the bridge MDB time out (typically after 260 seconds). Once expired, the bridge falls back to flooding mode. Fortunately, the Linux kernel includes an internal IGMP querier that you can turn on directly inside the bridge.

Hands-on Practice: Step-by-Step Bridge Configuration

Here is how to audit, configure, and verify IGMP snooping using standard iproute2 and bridge utilities.

1. Inspecting the Current Bridge State

Start by checking your target bridge device (we will use br0):

# Display detailed bridge attributes
ip -d link show br0

Search for the mcast_snooping and mcast_querier flags in the output text. You can also inspect the sysfs trees directly:

cat /sys/class/net/br0/bridge/multicast_snooping
cat /sys/class/net/br0/bridge/multicast_querier

A value of 0 means disabled; 1 means active.

2. Enabling IGMP Snooping on the Bridge

Turn on snooping using the ip command:

sudo ip link set dev br0 type bridge mcast_snooping 1

Even with snooping active, older kernels may still flood unregistered multicast groups (addresses with no active subscribers) across all ports. You can lock this down by turning off multicast flooding on ports assigned to non-multicast workloads:

# Prevent flood of unregistered multicast on a specific VM tap
sudo bridge link set dev vnet0 mcast_flood off

3. Activating the Built-in IGMP Querier

If your hypervisor runs on an isolated VLAN without an upstream router sending periodic IGMP queries, turn on the bridge’s internal querier:

sudo ip link set dev br0 type bridge mcast_querier 1

You should also verify the IGMP version. Linux defaults to IGMPv3 on modern kernels, but you can explicitly match your application tier:

# Explicitly enforce IGMPv3
sudo ip link set dev br0 type bridge mcast_igmp_version 3

On our KVM hosts running mixed Ubuntu and RHEL guests, turning on the querier immediately cut idle tap interface packet rates from 65,000 pps down to baseline background levels (under 10 pps).

4. Verifying the Multicast Forwarding Database (MDB)

When subscriber apps come online, inspect the bridge MDB table:

sudo bridge mdb show

You will see output similar to this:

dev br0 port vnet1 grp 239.255.255.250 temp
dev br0 port vnet3 grp 224.0.0.251 temp

In this scenario, vnet1 listens to SSDP discovery (239.255.255.250), while vnet3 picks up mDNS (224.0.0.251). Other virtual ports on br0 receive none of this traffic.

5. Testing Traffic Isolation with tcpdump

To verify the fix under load, launch two concurrent shell sessions on the hypervisor:

# Terminal 1: Monitor non-subscriber interface
sudo tcpdump -nn -i vnet0 ip multicast

# Terminal 2: Monitor subscriber interface
sudo tcpdump -nn -i vnet1 ip multicast

Push a quick test payload to an arbitrary multicast group using socat:

# Emit a test UDP payload to 239.1.1.1:5000
socat - UDP-DATAGRAM:239.1.1.1:5000,ip-multicast-ttl=2 <<< "Multicast Ping"

If the port mapping works, Terminal 2 records the packet while Terminal 1 stays clean.

6. Making the Configuration Persistent

Runtime changes made with ip and bridge vanish after a system restart. Always persist your bridge parameters through your distro’s networking stack.

On systems running systemd-networkd, define these attributes in your bridge .netdev file (e.g., /etc/systemd/network/10-br0.netdev):

[NetDev]
Name=br0
Kind=bridge

[Bridge]
IGMPSnooping=true
IGMPQuerier=true
IGMPVersion=3

Reload network configurations without rebooting:

sudo systemctl restart systemd-networkd

On systems configured with Netplan (Ubuntu), edit /etc/netplan/01-netcfg.yaml:

network:
  version: 2
  bridges:
    br0:
      interfaces: [eth0]
      parameters:
        stp: false
        forward-delay: 0

Older Netplan releases lack native parameters for mcast_querier. You can bridge this gap with an exec-up script or a minimal systemd oneshot unit:

# /etc/systemd/system/bridge-querier.service
[Unit]
Description=Set bridge IGMP querier
After=network.target

[Service]
Type=oneshot
ExecStart=/sbin/ip link set dev br0 type bridge mcast_querier 1

[Install]
WantedBy=multi-user.target

Conclusion

Multicast is efficient for one-to-many delivery, but an unmanaged Linux bridge quickly turns it into a disruptive broadcast flood. Flipping on IGMP snooping and the built-in querier gives you the granular traffic isolation of an enterprise hardware switch with zero extra software licenses.

Take five minutes to audit your bridges with ip -d link show and bridge mdb show. Keeping multicast packets strictly on designated switchports frees guest CPU cycles, stabilizes replication latency, and prevents cross-tenant packet leakage across your hypervisors.

Share: