Tune a Linux RED Queue with tc red
A tail-drop queue lets a burst of TCP flows lose packets together, then back off together, a sawtooth that tc red exists to break up. This guide configures a Random Early Detection (RED) queuing discipline with tc, inspects the resulting thresholds and counters, and removes the test qdisc without guessing what it changed. RED starts marking or dropping packets before a queue reaches its hard limit, avoiding that synchronised retransmission burst in the first place.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
This guide matches the installed tc-red(8) documentation from iproute2 6.1.0 and the tc binary on the test system. Option availability and output can differ with another iproute2 release, so check the local help on the machine you're actually changing. Allow about 10 minutes for a read-only inspection and a little longer for a controlled test. You need:
- Root privileges, or
CAP_NET_ADMIN, for qdisc changes. - The interface name and a maintenance window if it carries production traffic.
- An existing classful parent if you use the parent-based example below.
Checkpoint
The following commands only inspect the system and do not change traffic handling.
tc -V
tc qdisc add red help
tc qdisc show dev <INTERFACE>
tc class show dev <INTERFACE>
Replace <INTERFACE> with a real device such as enp0s31f6. The help command is deliberately phrased as an add request with help tacked on; tc prints the RED grammar without creating a qdisc. In iproute2 6.1.0 the advertised form is limit BYTES [min BYTES] [max BYTES] avpkt BYTES, followed by optional burst, adaptive, probability, bandwidth, ECN and qevent settings.
Understand the four queue values
RED works off an exponentially weighted moving average, not the instantaneous queue length. A suitably sized burst value keeps that average below min more readily during short bursts. Once the average passes min, the probability of action rises linearly until it reaches max. The actual queue can still keep growing regardless, so limit is the hard byte ceiling underneath all of it.
The manpage defaults are easy to overlook:
mindefaults to one third ofmax.maxdefaults to one quarter oflimitand should be at least twicemin.probabilitydefaults to0.02, a maximum 2% early-mark or early-drop chance.avpktis a packet-size estimate in bytes, used withburstto work out the average's time constant.bandwidthhelps calculate the average after idle time. It does not shape the interface.
For a first test, make all four queue-related values explicit. The values below come straight from the local manpage's own example: a 400,000-byte hard limit, thresholds at 30,000 and 90,000 bytes, and a 1,000-byte average packet estimate.
Choose how RED handles congestion
Without ecn, RED deals with an eligible packet by dropping it once its probability says to act. With ecn, an ECN-capable packet is marked instead, right up to the hard limit, while non-ECN traffic can still be early-dropped. That's usually the less disruptive choice when the hosts and the rest of the path support ECN, but it's not a guarantee every eligible packet gets marked rather than dropped.
harddropforces a drop once the average is abovemax, even in ECN mode.nodropkeeps traffic that would otherwise be marked but isn't ECN-capable, which can let the queue grow, so don't add it casually.adaptivemakes the probability dynamic, aiming for an average queue roughly halfway betweenminandmax; the local manpage records it as available from Linux 3.3.
Checkpoint
Decide whether you want ECN, and record the current qdisc output before changing anything. If the interface already has a root qdisc, do not replace it just to try RED.
Attach RED below an existing class
This is the safer operational shape, since it leaves the root qdisc and other classes untouched. The parent must already exist: the read-only tc class show command above should show the class you intend to use, such as 1:1.
Warning
The next command changes packet queuing and needs elevation. Use a test interface or a known maintenance window, and substitute the interface and parent only after checking them.
sudo tc qdisc add dev <INTERFACE> parent 1:1 handle 10: red \
limit 400000 min 30000 max 90000 avpkt 1000 \
burst 55 ecn adaptive bandwidth 10Mbit
The handle 10: identifies this qdisc, it is not a bandwidth setting. burst 55 controls how quickly the real queue influences the moving average, it is not a packet limit either. The bandwidth value is only used for idle-time calculations, and it must describe the interface's actual rate.
Verify the attachment and collect statistics:
sudo tc qdisc show dev <INTERFACE>
sudo tc -s qdisc show dev <INTERFACE>
Expected output includes a RED qdisc beneath the chosen parent, with the configured handle and options. The statistics form adds packet and byte counters. Counters can sit at zero on an idle interface, that's not evidence the qdisc failed to attach.
Test without replacing the root qdisc
Generate or observe traffic that actually traverses the class containing RED, then run the statistics command again. Don't flood a production link just to make the counters move. RED is a queue management policy, not a traffic generator or a shaper, so it can't create congestion for you and it can't enforce 10Mbit on the interface either way.
With ECN enabled, early action can show up as marks rather than drops for ECN-capable traffic. Non-ECN packets can still be dropped before the hard limit, and at the hard limit itself, packets are dropped regardless of ECN. If counters don't change, check the parent, the direction of traffic, and whether the class is receiving packets at all.
Remove the test qdisc
Removal is another elevated, service-affecting operation. Confirm that handle 10: is actually the RED qdisc you added, then delete that exact qdisc:
sudo tc qdisc show dev <INTERFACE>
sudo tc qdisc del dev <INTERFACE> parent 1:1 handle 10:
tc qdisc show dev <INTERFACE>
After deletion, the parent returns to its normal child or default behaviour. Do not use a guessed tc qdisc replace ... root command as an undo step, the previous root qdisc, handle and parameters are system-specific. If you changed a root qdisc instead of a class, restore the exact configuration you recorded before the change.
Common mistakes
- No such file or directory, or an invalid parent: the parent class doesn't exist on that interface. Check
tc class showand use its exact class ID. - RED never marks: the moving average may never have crossed
min, or traffic may not be passing through the selected class. Check counters and thresholds before touching probability. - Too many drops during a burst: review
burst,avpkt,minandmaxtogether. Raisinglimitalone only changes the hard ceiling, not the average calculation. - ECN is not visible: only ECN-capable packets are marked. Non-ECN packets can still be early-dropped unless
nodropis set. - Traffic rate didn't change: that's expected. RED manages queue pressure, it doesn't shape bandwidth.
Done means
- Grammar confirmed:
tc qdisc add red helpshows the local option grammar. - Baseline recorded: the parent class and existing qdisc were noted before the change.
- Attachment verified: the RED qdisc is visible with
tc qdisc show, and its counters were checked with-s. - Behaviour documented: ECN, hard-drop behaviour, thresholds and bandwidth assumptions are written down for this interface.
- Removal ready: the exact test qdisc can be removed with its known parent and handle.