Use pfifo_fast When You Need a Simple Priority Queue
pfifo_fast is already running on most of your interfaces right now, quietly, with no entry in tc qdisc ls to prove it. This guide shows you a safe way to inspect an interface queue, understand what pfifo_fast actually does with packet priority, and restore it after a test. The installed reference here is iproute2 6.1.0-1ubuntu6.4. Allow about ten minutes for inspection, longer if you're changing a production interface.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide assumes a Linux shell and the iproute2 package. Reading queue settings is normally unprivileged; replacing or deleting a qdisc changes packet handling and normally needs elevated privileges. Pick your real interface name, such as IFACE=enp0s31f6, only after checking it.
1. Identify the interface and current queue
Start with read-only commands. None of these alter networking:
$ ip -details link show
$ IFACE='enp0s31f6'
$ ip -details link show dev "$IFACE"
$ tc qdisc show dev "$IFACE"
- Look for
qlenin theipoutput. - Look for a named root qdisc in the
tcoutput. - Do not copy
enp0s31f6blindly: interface names differ between machines.
Checkpoint
You have the right interface name and have recorded its current qdisc. If it carries production traffic, stop here until you have a maintenance window and a rollback command.
2. Understand what pfifo_fast actually does
pfifo_fast is a three-band first-in, first-out queue, not three queues drained in parallel. Packets land in one of the three bands based on their Type of Service bits or assigned priority, using the same general mapping described for the classful tc-prio qdisc.
- Highest band first, always. The queue services the highest-priority band with traffic waiting, so a lower band can sit idle while a higher one stays busy.
- That's a policy decision, not a guarantee. It can keep interactive traffic responsive, but it can also starve lower-priority traffic under sustained load. Treat the mapping as a choice, not proof that any particular application gets a particular band.
Each band is sized from the interface's txqueuelen. When a band fills up, further packets are dropped rather than queued, so changing txqueuelen changes the capacity of all three bands at once, not one separately:
$ ip link show dev "$IFACE"
2: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> ... qdisc ... qlen 1000
Exact flags, line number and qdisc depend on the host. The checkpoint that matters is the interface's current queue length, not this particular number.
3. Know when pfifo_fast is already present
The manpage describes pfifo_fast as the automatic default qdisc for a newly created interface. Attach a different qdisc and it pre-empts that default; remove the attached qdisc and the automatic pfifo_fast queue quietly returns.
That default has an awkward diagnostic quirk: it does not maintain statistics and does not appear in tc qdisc ls. An empty or unhelpful tc qdisc show is not proof the interface has no transmit queue. Cross-check with ip -details link show dev "$IFACE", and remember other devices may deliberately be running fq_codel, noqueue or something else entirely.
4. Attach pfifo_fast explicitly for a controlled test
Only do this on an interface you're authorised to reconfigure. The command replaces the root qdisc, so it can change latency and packet handling immediately, and it may disrupt traffic while the kernel applies the change:
$ sudo tc qdisc replace dev "$IFACE" root pfifo_fast
No success output here, so check the exit status and inspect the interface directly:
$ printf 'tc status: %s\n' "$?"
tc status: 0
$ tc qdisc show dev "$IFACE"
qdisc pfifo_fast 8001: root refcnt 2 bands 3 priomap ...
Output formatting and the handle can vary; what matters is a successful command and a root qdisc identified as pfifo_fast. Permission denied means use sudo only with an approved maintenance plan. Unknown qdisc means check the installed tc and kernel support before trying a different spelling.
5. Restore the automatic behaviour
Deleting the explicitly attached root qdisc is the documented undo for step 4. It is still a live network change, so run it only when the interface can tolerate the transition:
$ sudo tc qdisc del dev "$IFACE" root
$ printf 'tc status: %s\n' "$?"
tc status: 0
$ ip -details link show dev "$IFACE"
$ tc qdisc show dev "$IFACE"
After deletion the interface's automatic default is free to return, but do not assume that means the same queue policy as before: another service, network manager or container tool may attach a different qdisc again. Re-run both inspection commands and compare against the record from step 1.
Common traps
- Assuming the default is active: being the documented default doesn't mean it's running. An explicitly attached qdisc pre-empts it.
- Expecting statistics from the default: the manpage says the automatic
pfifo_fastdoesn't maintain them or show up intc qdisc lsat all. - Calling the bands simultaneous: they're not. Higher-priority traffic is served first while lower bands wait.
- Tuning
txqueuelencasually: it changes how many packets each band can hold on a busy host, and can alter drops and latency. - Treating the queue as a fix: it's not a substitute for measuring your traffic classification and finding the real bottleneck. Its usefulness depends on packet priority and actual load.
Done means
- Interface and queue recorded: you identified the real interface and noted its qdisc and
txqueuelen. - Three-band behaviour understood: you can explain the strict-priority behaviour and its starvation risk.
- Capacity link understood: you know each band's capacity follows
txqueuelen. - Change made safely: a live qdisc was changed only with an approved rollback plan.
- Result verified: you checked with
tc qdisc showandip -details link show. - Rollback tested: you can remove an explicit root qdisc and re-check whether the automatic default returned.