Home / Alt manpages / tc-fq_codel(8)

  • tc-fq_codel(8)
  • Admin command
  • linux

Reduce Queueing Delay with tc fq_codel

fq_codel exists because a single fat queue lets one greedy flow drown out everything else on the link. This guide puts fq_codel on a Linux interface, shows how to read its live counters, and gives you a recovery path if the change does not suit the link. It combines per-flow fair queuing with CoDel delay management, so busy flows are far less likely to dominate the interface.

Allow about 15 minutes, including a short observation period. You need the tc command from the iproute2 package and root for changes. These examples were checked with iproute2 6.1.0-1ubuntu6.4, whose utility reports iproute2-6.1.0. Replace eth0 with the interface that actually carries your traffic.

Checkpoint

This guide changes the live root qdisc. Do it during a maintenance window if the interface carries a production connection. Keep an existing network-management configuration handy, because deleting or replacing a qdisc can affect latency, packet drops and shaping immediately.

1. Identify the interface and current qdisc

Use an ordinary, read-only shell to find the interface and its current queueing discipline:

$ ip -br link
$ tc qdisc show dev eth0

The first command gives you the interface name. The second may show noqueue, fq_codel or another qdisc; record that output before you change anything. If a traffic shaper, VM manager or network service already owns the interface, make the change through that system's configuration rather than fighting it with a one-off command.

On the installed machine, an existing FQ_CoDel queue reports fields such as limit 10240p, flows 1024, quantum 1514, target 5ms, interval 100ms, memory_limit 32Mb and ecn. Yours may differ.

2. Apply the default FQ_CoDel queue

Replacing the root qdisc is an elevated operation and can interrupt or reorder how traffic is queued. Set a shell variable first, then run the command with sudo:

DEV=eth0
sudo tc qdisc replace dev "$DEV" root fq_codel

This uses the documented defaults: a 10,240-packet hard queue limit, 1,024 flow slots, a 1,514-byte fair-queuing quantum, a 5 ms target, a 100 ms interval, a 32 MB memory limit and ECN marking on. Both the packet and byte limits apply, and whichever gives the lower effective capacity controls the queue.

FQ_CoDel hashes packets into flow slots. Hashing is stochastic, so two flows can share a slot, but packets within a flow stay FIFO, which avoids deliberately reordering that flow. A newer flow can get service before an older one; that is not an unlimited priority scheme.

Checkpoint

Verify the installed qdisc before generating traffic:

$ sudo tc qdisc show dev eth0
qdisc fq_codel 8002: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64

Handle and reference count can vary. Check for qdisc fq_codel and the settings, not one exact handle.

Use the statistics form after a transfer, download or other representative workload:

$ sudo tc -s qdisc show dev eth0
qdisc fq_codel 8002: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5ms interval 100ms memory_limit 32Mb ecn drop_batch 64
 Sent 428514 bytes 2269 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  maxpacket 256 drop_overlimit 0 new_flow_count 0 ecn_mark 0
  • backlog is packets waiting right now.
  • dropped is the qdisc's total drops, while drop_overlimit counts only drops caused by hitting a limit.
  • ecn_mark counts packets marked for ECN.

A zero counter straight after installation is normal, not proof the queue will never build. Run the same command before and after a known workload, and read the counters against the link's normal traffic pattern: a rising drop count can mean sustained congestion, a queue limit too small for the workload, or a downstream bottleneck this interface cannot fix on its own.

4. Tune only a measured requirement

For a first deployment, leave the defaults alone. The manpage describes target as the acceptable minimum standing or persistent queue delay, and interval keeps that measured minimum fresh; it should sit around the worst-case round-trip time through the bottleneck. Both are latency decisions, not universal speed settings.

If measurement justifies a smaller queue and a shorter observed delay, apply explicit values:

sudo tc qdisc replace dev "$DEV" root fq_codel \
    limit 2000 target 3ms interval 40ms

This keeps the other defaults, including ECN. limit is packets, not bytes. Do not copy these numbers just because they appear in an example: too low a limit drops bursts, too short an interval gives CoDel too little time to observe and react to the path.

To disable ECN marking explicitly, add noecn. That is a compatibility decision: marking lets ECN-capable endpoints react without a drop, but equipment along the path must handle ECN correctly for that to pay off. Do not assume noecn is safer just because it is more familiar.

5. Undo the live change safely

There is no generic undo command that reconstructs the qdisc you replaced. Use the output saved in step 1 and the configuration manager that normally owns the interface. If you intentionally want to remove the root qdisc and accept the system fallback, run:

sudo tc qdisc del dev "$DEV" root
sudo tc qdisc show dev "$DEV"

Warning

Deletion is service-disrupting. It may leave the interface on a fallback such as noqueue, and it will not restore a previous TBF, CAKE, HTB or vendor-managed configuration. Restore the recorded qdisc using its own documented configuration, then verify again with tc qdisc show.

Done means

  • Correct interface identified and its original qdisc recorded.
  • sudo tc qdisc show dev eth0 reports fq_codel after the change.
  • tc -s qdisc checked during representative traffic, and the counters understood.
  • target, interval and limit left at defaults unless measurement justified tuning.
  • Restoration path known: which configuration owner and recorded command brings back the previous queue.