$linuxjunkies
>

Bufferbloat-Free Networking with CAKE

Fix bufferbloat on Linux using CAKE qdisc with tc, including autorate-ingress for variable links, persistent systemd configuration, and latency verification.

AdvancedUbuntuDebianFedoraArch12 min readUpdated June 7, 2026

Before you start

  • Root or sudo access on the Linux host acting as the network gateway or direct modem connection
  • Linux kernel 4.19 or later (kernel 5.18+ recommended for autorate-ingress)
  • iproute2 with CAKE support installed
  • Knowledge of your WAN interface name (find it with: ip route show default)

Bufferbloat silently ruins interactive network performance: gaming latency spikes during downloads, video calls stutter while a file uploads, SSH becomes sluggish. The root cause is oversized in-flight queues at your bottleneck link. CAKE (Common Applications Kept Enhanced) is the current gold-standard queuing discipline in the Linux kernel that solves this with a single, well-reasoned configuration. Combined with autorate-ingress, it handles traffic shaping in both directions without needing a separate router firmware. This guide walks through deploying CAKE on a Linux host or router with tc, explains the knobs that matter, and shows how to verify the fix with real latency tests.

What CAKE Actually Does

CAKE is a queuing discipline (qdisc) implemented in the Linux kernel (mainline since 4.19). It combines:

  • AQM (Active Queue Management) via COBALT (CoDel + BLUE), dropping or ECN-marking packets before the queue grows unmanageable.
  • FQ (Flow Queuing) — each flow gets its own sub-queue, preventing a bulk transfer from starving interactive traffic.
  • Traffic shaping — you tell CAKE your link rate; it keeps the queue at the bottleneck rather than upstream in your ISP's equipment.
  • Overhead compensation — CAKE accounts for ATM cell tax, PPPoE headers, VLAN tags, so it shapes at the correct layer.

The key insight: bufferbloat lives in the queue ahead of your bottleneck. By shaping slightly below your line rate, CAKE owns the queue and keeps it tiny.

Prerequisites and Package Installation

CAKE is built into the kernel as a module. The tc userspace tool needs to be recent enough to know about it.

Debian / Ubuntu

sudo apt update
sudo apt install iproute2 iputils-ping

On Ubuntu 22.04+ and Debian 12, iproute2 already supports CAKE. Confirm with:

tc qdisc add dev lo root cake 2>&1 | grep -v 'File exists'
tc qdisc del dev lo root 2>/dev/null

Fedora / RHEL 9 / Rocky 9

sudo dnf install iproute tc-extra

On RHEL 9 derivatives, sch_cake may need enabling:

sudo modprobe sch_cake
echo 'sch_cake' | sudo tee /etc/modules-load.d/cake.conf

Arch Linux

sudo pacman -S iproute2

The module is already present in linux and linux-lts kernel packages.

Step 1 — Measure Your Real Line Rate

CAKE must shape below your actual throughput, not your advertised speed. Run a speed test under load using speedtest-cli or iperf3 against a nearby server. Record both upload and download in Mbit/s. A conservative starting point is 95% of the measured value — this guarantees CAKE, not your ISP, owns the queue.

sudo apt install speedtest-cli   # Debian/Ubuntu
speedtest-cli --simple

Output will vary; note the Download and Upload figures. Subtract about 5% from each for your shaping targets.

Step 2 — Apply CAKE to Egress (Upload)

Egress — traffic leaving your machine toward the ISP — is straightforward. Replace eth0 with your WAN interface name and 50mbit with 95% of your measured upload speed.

sudo tc qdisc replace dev eth0 root cake bandwidth 50mbit diffserv4 nat wash ack-filter split-gso

Key options explained:

  • bandwidth 50mbit — your shaping rate. Use mbit, kbit, or gbit.
  • diffserv4 — four-tin DiffServ scheduling: Bulk, Best Effort, Video, Voice. Matches most real-world DSCP markings.
  • nat — makes flow isolation work correctly behind NAT by looking up the pre-NAT address.
  • wash — strips incoming DSCP markings before forwarding (prevents abuse by upstream hosts).
  • ack-filter — suppresses redundant TCP ACKs on the upload path, recovering bandwidth for asymmetric links.
  • split-gso — splits GSO superpackets before queuing so CAKE's flow isolation and AQM act on real packet sizes.

For a PPPoE connection add overhead compensation:

sudo tc qdisc replace dev eth0 root cake bandwidth 50mbit diffserv4 nat wash ack-filter split-gso overhead 8 pppoe-vcmux

For VDSL with PTM framing (common in Europe) use overhead 8 ptm. For plain Ethernet use overhead 0 ethernet. CAKE's overhead keyword has several named presets — run man tc-cake for the full list.

Step 3 — Handle Ingress (Download) with autorate-ingress

Ingress is harder: packets arrive before you can shape them. The solution is to redirect all incoming traffic to a virtual ifb (Intermediate Functional Block) interface and apply CAKE there, effectively giving you an egress hook on the inbound stream.

Load the IFB module and bring up the interface

sudo modprobe ifb
sudo ip link add name ifb0 type ifb
sudo ip link set ifb0 up

Redirect ingress to ifb0

sudo tc qdisc add dev eth0 handle ffff: ingress
sudo tc filter add dev eth0 parent ffff: matchall action mirred egress redirect dev ifb0

Apply CAKE to ifb0 with ingress mode

sudo tc qdisc replace dev ifb0 root cake bandwidth 450mbit diffserv4 nat ingress wash split-gso

Note the ingress keyword — it tells CAKE which direction the traffic flows for correct flow isolation and the ack-filter (which applies on the opposite interface for ACKs). Replace 450mbit with 95% of your measured download speed.

If your line speed varies — mobile connections, VDSL under rain fade — static bandwidth settings leave you either over-shaping (wasted capacity) or under-shaping (bufferbloat returns). The autorate-ingress option tells CAKE to measure actual throughput and reduce its rate automatically when queuing is detected. Pair it with a conservative maximum:

sudo tc qdisc replace dev ifb0 root cake bandwidth 450mbit autorate-ingress diffserv4 nat ingress wash split-gso

autorate-ingress requires kernel 5.18+. It only works on the ingress path. The bandwidth parameter becomes the ceiling, not a fixed target.

Step 4 — Persist with a systemd Service

tc rules are lost on reboot. A simple systemd service applies them after the interface is up. Create /etc/systemd/system/cake-qos.service:

sudo tee /etc/systemd/system/cake-qos.service <<'EOF'
[Unit]
Description=CAKE QoS shaping
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/cake-qos.sh
ExecStop=/usr/local/sbin/cake-qos-stop.sh

[Install]
WantedBy=multi-user.target
EOF

Create /usr/local/sbin/cake-qos.sh (replace values to match your setup):

sudo tee /usr/local/sbin/cake-qos.sh <<'EOF'
#!/usr/bin/env bash
WAN=eth0
UPLOAD=50mbit
DOWNLOAD=450mbit

modprobe ifb
ip link add name ifb0 type ifb 2>/dev/null || true
ip link set ifb0 up

tc qdisc del dev "$WAN" root 2>/dev/null
tc qdisc replace dev "$WAN" root cake bandwidth "$UPLOAD" diffserv4 nat wash ack-filter split-gso

tc qdisc del dev "$WAN" ingress 2>/dev/null
tc qdisc add dev "$WAN" handle ffff: ingress
tc filter add dev "$WAN" parent ffff: matchall action mirred egress redirect dev ifb0

tc qdisc del dev ifb0 root 2>/dev/null
tc qdisc replace dev ifb0 root cake bandwidth "$DOWNLOAD" autorate-ingress diffserv4 nat ingress wash split-gso
EOF
sudo chmod +x /usr/local/sbin/cake-qos.sh
sudo tee /usr/local/sbin/cake-qos-stop.sh <<'EOF'
#!/usr/bin/env bash
tc qdisc del dev eth0 root 2>/dev/null
tc qdisc del dev eth0 ingress 2>/dev/null
tc qdisc del dev ifb0 root 2>/dev/null
ip link del ifb0 2>/dev/null
EOF
sudo chmod +x /usr/local/sbin/cake-qos-stop.sh
sudo systemctl daemon-reload
sudo systemctl enable --now cake-qos.service

Step 5 — Verify It's Working

Confirm the qdiscs are in place:

tc -s qdisc show dev eth0
tc -s qdisc show dev ifb0

You should see cake as the root qdisc on both, with incrementing statistics after traffic flows.

Run a real bufferbloat test. The most reliable method is load-induced latency: ping a nearby host while running a saturating download and upload simultaneously.

# Terminal 1 — continuous ping
ping -i 0.1 8.8.8.8

# Terminal 2 — saturate upload + download simultaneously
iperf3 -c iperf.he.net -t 30 -R &
iperf3 -c iperf.he.net -t 30

Without CAKE, ping latency during load often jumps to 200–2000 ms. With CAKE correctly configured and shaped slightly below line rate, you should see latency increase by no more than 5–20 ms above idle baseline.

The Waveform Bufferbloat Test is a useful browser-based alternative that grades your connection A–F and shows latency-under-load figures.

Troubleshooting

  • CAKE not recognized by tc: Your iproute2 is too old or sch_cake module isn't loaded. Run modprobe sch_cake and retry. On RHEL, ensure the tc-extra or iproute-tc package is installed.
  • Throughput drops too much: Your bandwidth target is set too low. Raise it to 97–98% of measured speed and retest. Also check that split-gso is active — without it, CAKE sees 64 KB superpackets and shapes incorrectly.
  • Latency is still high under load: You may have the wrong interface. Find your WAN interface with ip route show default. Also confirm traffic actually passes through CAKE by checking the tc -s packet counters increase.
  • autorate-ingress kernel version: The autorate-ingress keyword requires kernel 5.18+. Check with uname -r. On older kernels, remove that keyword and use a static bandwidth.
  • IFB interface missing after reboot: Ensure ifb is in /etc/modules-load.d/ or is loaded by your service script before the ip link add command.
tested on:Ubuntu 24.04Debian 12Fedora 40Arch rolling

Frequently asked questions

Why shape to 95% of my line rate instead of 100%?
CAKE must own the bottleneck queue. If you shape at exactly 100%, bursts momentarily exceed the rate and the queue forms upstream at your ISP's hardware, where you have no control. The 5% headroom ensures the queue always forms inside CAKE.
Does CAKE work on a regular desktop, or only on a dedicated router?
It works on any Linux machine that is the bottleneck — typically the machine directly connected to the modem. On a desktop behind a home router, CAKE on your desktop only shapes that one machine's traffic, not the whole household. For whole-network coverage you need CAKE on the router.
What is autorate-ingress and when should I use it?
autorate-ingress makes CAKE dynamically lower its rate limit when it detects queue growth, then recover when the link clears. It is most useful on LTE, VDSL, or cable connections where throughput varies with signal conditions. It requires Linux 5.18+ and only applies to ingress-direction CAKE instances.
Will CAKE affect my maximum throughput?
Slightly, by design. You lose the 5% headroom you gave up to own the queue. In exchange, interactive latency under load drops dramatically. On a 500 Mbit link that 25 Mbit ceiling is irrelevant for most workloads.
How do I choose between diffserv4, diffserv8, and besteffort?
diffserv4 is right for most setups: it maps real-world DSCP values into four tins (Bulk, Best Effort, Video, Voice) with appropriate priorities. Use diffserv8 only if you generate and fully trust DSCP markings across your network. besteffort disables tin prioritisation entirely and is only appropriate when you want pure flow fairness with no DSCP treatment.

Related guides