Reducing Bufferbloat on Linux Egress with HTB and fq_codel
Learn how to combine a token‑bucket shaper with the fq_codel scheduler to keep latency low for interactive traffic while respecting a fixed egress rate.
29 Nov 2025, 00:37 UTC

The Latency Spike Problem
You have a gigabit uplink, but interactive services such as SSH or video calls become sluggish whenever a large backup starts. The root cause is often bufferbloat: the network interface queues too many packets, adding latency without increasing throughput.
Why Shaping Alone Isn't Enough
Traffic shaping with a token bucket (e.g., HTB) caps the egress rate to match a downstream link or ISP limit. This prevents bursts from overflowing a remote buffer, but the shaper’s own queue can still grow large if the incoming traffic exceeds the shaped rate for extended periods, leading to queuing delay on the local host.
Adding Fair Queuing and CoDel
Packet scheduling decides which queued packet transmits next. Fair Queuing (FQ) splits bandwidth among active flows so a single high‑volume TCP stream cannot starve others. Combining FQ with an Active Queue Management algorithm like CoDel monitors the time packets spend in the queue; when the minimum delay exceeds a target, CoDel drops packets from the front of the queue to signal senders to slow down before the buffer fills completely.
Example Configuration: HTB Root with fq_codel Leaf
The following commands create a Hierarchical Token Bucket (HTB) that limits the interface to 200 Mbps and attaches an fq_codel qdisc to the default class for latency control. Run these with root privileges on the target system.
# 1. Install the HTB and fq_codel modules if not present (usually built‑in)
# 2. Add a root HTB qdisc
tc qdisc add dev eth0 root handle 1: htb default 10
# 3. Define the overall bandwidth ceiling
tc class add dev eth0 parent 1: classid 1:1 htb rate 200mbit
# 4. Leaf class for regular traffic (inherits the rate)
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 200mbit ceil 200mbit
# 5. Attach fq_codel to manage queue latency and fairness
tc qdisc add dev eth0 parent 1:10 handle 10: fq_codel limit 1000 target 5ms interval 100ms
Verification and Practical Checks
After applying the configuration, inspect the qdisc statistics to confirm the shaper and scheduler are active:
tc -s qdisc show dev eth0
Look for the fq_codel block; the drops counter should increase when the link is congested, indicating CoDel is actively managing delay. You can also run a throughput test with iPerf3 while pinging the host from another machine to observe latency; the ping round‑trip time should stay low (e.g., < 10 ms) even when the iPerf3 sender is transmitting at the shaped rate.
Trade‑offs and Limitations
- Setting the HTB rate significantly below the physical link capacity will under‑utilize available bandwidth.
- Hierarchical HTB structures add per‑packet classification overhead; deep trees can increase CPU usage on the network processor.
- If the fq_codel
targetis set too low, the algorithm may drop packets prematurely for some TCP implementations, potentially reducing throughput. - The
limitparameter (maximum queue length) must be tuned to the interface’s buffer size; too small a limit causes unnecessary drops, too large a limit reduces CoDel’s responsiveness.
Closing Action
If you notice latency spikes during bulk transfers, start by applying an fq_codel qdisc directly to the egress interface to control queue delay. When you also need to enforce a strict bandwidth ceiling (e.g., matching an ISP contract), place an HTB shaper above the fq_codel leaf as shown above. Verify the setup with the tc -s qdisc show command and simple latency‑under‑load tests before deploying to production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.