Home / Alt manpages / tc-pie(8)

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

Tune a Linux Interface Queue with the PIE AQM

PIE watches queuing delay build up and starts dropping or marking packets before the queue turns into the multi-second lag known as bufferbloat. This guide configures the PIE active queue management (AQM) algorithm on one Linux interface, reads its delay and drop statistics, and removes the test configuration cleanly. The examples match iproute2 6.1.0, installed here as package version 6.1.0-1ubuntu6.4.

Allow about fifteen minutes. You need the tc command, the interface name, and root privileges for changes. A root qdisc affects traffic on that interface, so use a maintenance window for a busy link. This guide uses a placeholder interface and does not assume a particular NIC exists.

1. Check the installed command

Start with read-only checks. These don't need elevated privileges on a normal installation:

$ tc -V
tc utility, iproute2-6.1.0, libbpf 1.3.0
$ ip -br link
lo               UNKNOWN        127.0.0.1/8 ::1/128
IFACE_NAME       UP             192.0.2.10/24

Replace IFACE_NAME with the real interface from your own output, not lo. If the name isn't obvious, confirm it against your network configuration before touching the queue.

Checkpoint

Record the current root qdisc before replacing it.

$ tc -s qdisc show dev IFACE_NAME
qdisc fq_codel 0: root refcnt 2 limit 10240p ...

Your qdisc, counters and formatting will differ. Save this output somewhere outside the command line: it's the best clue for restoring the previous setup if PIE turns out to be unsuitable.

2. Understand what PIE will change

PIE estimates the dequeue rate and uses the estimated delay to adjust a drop probability. Packets can then be dropped or, with ECN enabled, marked instead. It aims to keep queue delay near a target while keeping link utilisation up. It is not a bandwidth shaper, it does not impose a rate limit.

  • Queue limit: 1000 packets by default.
  • Target delay: 15ms by default.
  • Probability update interval: 15ms by default.
  • Alpha and beta: default 2 and 20 in the example output.
  • ECN, byte mode, dequeue-rate estimator: all disabled unless requested.

Treat these as this iproute2/kernel implementation's documented defaults, not as universal defaults on every older or newer system. The limit is in packets unless bytemode is selected: byte mode scales the drop probability by packet size, it does not turn the limit into a byte limit. The dequeue-rate estimator uses Little's law to calculate delay and adds an average dequeue rate to the statistics.

3. Apply a conservative PIE configuration

This is the first state-changing step. sudo tc qdisc replace swaps the interface's root qdisc, which can alter latency, drops and connectivity for anything using that link. Confirm the interface name twice, and make sure you have console or other recovery access if this interface carries your current connection.

$ DEV=IFACE_NAME
$ sudo tc qdisc replace dev "$DEV" root pie limit 1000 target 15ms tupdate 15ms noecn nobytemode no_dq_rate_estimator

There's no need to spell out defaults, but doing so makes a copied configuration easier to review later. alpha and beta are left out here because the documented values are normally fine for a first test; if you do set them, the manpage specifies a range of 0 to 32 for each.

Checkpoint

Ask the kernel to show the resulting qdisc.

$ tc qdisc show dev "$DEV"
qdisc pie 8001: root refcnt 2 limit 1000p target 15.0ms tupdate 15.0ms alpha 2 beta 20

Handle and time formatting can differ. Check that the qdisc kind is pie, the interface is the one you selected, and the requested limit and target are present.

4. Read PIE statistics

Use the statistics form once the interface has actually carried some traffic:

$ sudo tc -s qdisc show dev "$DEV"
qdisc pie 8001: root refcnt 2 limit 1000p target 15.0ms tupdate 15.0ms alpha 2 beta 20
 Sent 123456 bytes 1200 pkt (dropped 3, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  prob 0.001234 delay 9000us
  pkts_in 1200 overlimit 0 dropped 3 maxq 24 ecn_mark 0
  • delay is reported in microseconds.
  • prob is the current drop or mark probability.
  • dropped counts packets dropped by the qdisc.
  • ecn_mark counts ECN marks when ECN is enabled.

Values are workload-dependent. A zero counter is not proof PIE is broken; it may just mean the link hasn't built a queue yet. Take a short observation period and compare several readings. A rising backlog or delay means offered traffic is exceeding what the link can currently dequeue. PIE can react to that queue, but it cannot create link capacity or fix a duplex, driver or physical-layer problem.

5. Enable ECN only when the path supports it

ECN swaps dropping for marking on the probability-controlled portion of the algorithm, but only if both end hosts and the path actually handle ECN correctly. Test it with the applications and peers that use this link; do not flip it on in production just because the option exists.

$ sudo tc qdisc replace dev "$DEV" root pie limit 1000 target 15ms tupdate 15ms ecn
$ sudo tc -s qdisc show dev "$DEV"
qdisc pie 8001: root refcnt 2 limit 1000p target 15.0ms tupdate 15.0ms alpha 2 beta 20 ecn
 ... ecn_mark 0

An initial ecn_mark of zero is normal. If you actually want dropping rather than marking, set noecn explicitly. PIE's manpage notes that beyond 10 percent, packets are dropped according to the probability even in ECN mode, so ECN is not a promise that every congested packet gets marked instead of dropped.

6. Try byte mode or the dequeue estimator deliberately

These options answer different questions, so change one at a time. Use bytemode when packet sizes vary and you want proportional treatment by byte:

$ sudo tc qdisc replace dev "$DEV" root pie limit 1000 target 20ms tupdate 30ms bytemode
$ tc qdisc show dev "$DEV"
qdisc pie 8001: root refcnt 2 limit 1000p target 20.0ms tupdate 32.0ms alpha 2 beta 20 bytemode

The displayed update interval may be normalised by the implementation, as in the manpage's own example, so verify the actual output rather than assuming your requested text comes back unchanged.

Use dq_rate_estimator when you want PIE to calculate delay from a dequeue-rate estimate instead:

$ sudo tc qdisc replace dev "$DEV" root pie dq_rate_estimator
$ sudo tc -s qdisc show dev "$DEV"
qdisc pie 8001: root refcnt 2 limit 1000p target 15.0ms tupdate 15.0ms alpha 2 beta 20
 ... prob 0.000092 delay 22200us avg_dq_rate 12145996

Counters, handle and rate here are illustrative and will change on your host. Don't stack options just to make the command look thorough; change one behaviour, watch the statistics, then decide on the next.

7. Remove PIE or restore the previous qdisc

Do this when the test ends, or immediately if the link starts behaving badly. Deleting the root qdisc lets the kernel fall back to its normal device setup, but it does not restore a custom qdisc you replaced earlier:

$ sudo tc qdisc del dev "$DEV" root
$ tc qdisc show dev "$DEV"
qdisc noqueue 0: root refcnt 2

The exact post-delete qdisc depends on the device. If your checkpoint showed a managed qdisc such as fq_codel, restore it with the configuration your host's network manager actually uses rather than guessing: a manually restored qdisc can be overwritten on link restart, reboot or network-manager reload.

For a persistent setup, put the reviewed command into whatever network configuration system owns the interface, then test restart and rollback separately. The tc commands above are runtime changes only; they don't create a persistent configuration file.

Done means

  • Baseline recorded: you identified the real interface and noted its original root qdisc.
  • Attachment confirmed: tc qdisc show shows PIE attached to the intended interface.
  • Statistics checked: delay, probability, drops and, where relevant, ECN marks were reviewed with tc -s qdisc show.
  • Options justified: ECN, byte mode or the dequeue estimator were enabled only for a stated reason.
  • Next step decided: you know whether to keep the runtime test, restore the previous qdisc, or remove PIE entirely.