Concepts / TCP performance

TCP performance

Quality of service

Also called QoS, traffic classes, priority queueing, DiffServ

Deciding which traffic waits when a link is full: classify it, then schedule the queue, voice first.

QoS changes nothing on an idle link; it decides who waits when there is a queue. Packets are classified, often by their DSCP mark, and a scheduler serves the classes: strict priority for voice, guaranteed shares for the rest. It only works where the queue forms, so a router in front of a slower line shapes a little under the line's rate to keep the queue in its own hands. Marks are trusted only from known sources and cleared at the border.

How QoS works, step by step

A link sends one packet at a time. When packets arrive faster than the link can send them, the rest wait in a queue, and when the queue is full, new arrivals are dropped. QoS does not make a link faster. It decides who waits and who is dropped when there is a queue. On an idle link it does nothing at all.

  1. Classify. The router sorts each packet into a class: by its mark, by address and port, or by the interface it came in on.
  2. Mark. The class is written into the packet so routers further on can sort it cheaply. In IPv4 and IPv6 that is the 6-bit DSCP field (DiffServ, RFC 2474), the top of the old type-of-service byte. Common values: EF 46 for voice, AF41 34 for video, CS1 8 for bulk that may wait, 0 for everything else. On Ethernet, a VLAN tag carries a 3-bit priority too. A mark is only a request: each network decides whether to trust it, and most of the internet ignores it.
  3. Queue and schedule. Each class gets its own queue. A scheduler decides which queue sends next: strict priority for voice, guaranteed shares for business traffic, the rest for best effort. A cap on the priority class keeps it from starving everyone else.
  4. Manage the queue. Instead of waiting for a queue to overflow, active queue management (RED, CoDel) drops or ECN-marks a few packets early, so TCP senders slow down before delay builds up.
  5. Shape or police. A shaper holds traffic to a rate by delaying the excess in a queue. A policer drops whatever exceeds the rate, with no queue.

Step 3 only works where packets actually wait. A router with a gigabit port in front of an 8 Mbit/s modem never queues anything; the modem does, in arrival order. So the router shapes a little below the line's rate. It becomes the bottleneck, and the queue comes home, where its scheduler can sort it.

What it looks like on a Linux machine

In the QoS lab a phone and a laptop share an 8 Mbit/s line. The phone marks its pings EF: ping -Q 0xb8 sets the whole byte, and 46 × 4 = 184 = 0xb8. Idle, a ping takes about 10 ms. During the laptop's iperf3 upload it takes hundreds of milliseconds, because the modem's queue is full of upload packets.

Linux does QoS with tc. The fix is an HTB shaper at 7.5 Mbit/s with two classes, and a filter that sends EF packets to the first:

tc qdisc replace dev modemLink root handle 1: htb default 20
tc class replace dev modemLink parent 1: classid 1:1 htb rate 7500kbit
tc class replace dev modemLink parent 1:1 classid 1:10 htb rate 1mbit ceil 1mbit prio 0
tc class replace dev modemLink parent 1:1 classid 1:20 htb rate 6500kbit ceil 7500kbit prio 1
tc filter replace dev modemLink parent 1: protocol ip prio 1 u32 match ip dsfield 0xb8 0xfc flowid 1:10

The mask 0xfc compares only the six DSCP bits and ignores the two ECN bits. Voice is served first, up to 1 Mbit/s; everything else shares the rest and borrows up to 7.5 Mbit/s when voice is quiet. tc -s class show dev modemLink counts what each class sent and dropped, and the phone's ping falls back to near 10 ms while the upload runs. Under the same shaper, without any marks, fair queueing (sfq, or fq_codel, the default queue on most systemd-based distributions) gives each flow its own small queue, which already keeps a ping quick behind a bulk upload.

What goes wrong, and how you see it

Priority where the queue is not. A priority queue on a fast port changes nothing, and tc -s qdisc shows its backlog at zero. Find the bottleneck first.

Bufferbloat. A deep queue in a modem adds hundreds of milliseconds under load while losing nothing. Ping during an upload shows it; shaping plus fq_codel or CAKE fixes it.

Marks that vanish. A switch or provider that does not trust DSCP rewrites it to 0. A capture on each side shows tos 0xb8 going in and tos 0x0 coming out.

Policing that hurts TCP. A policer drops bursts, TCP halves its window at each drop, and throughput saw-tooths with many retransmissions. A shaper delivers the same rate smoothly.

A priority class that starves the rest. Uncapped strict priority lets one misbehaving device mark everything EF and take the link.

Questions people ask

Does QoS increase bandwidth? No. It decides who gets the bandwidth there is when there is not enough.

What is DSCP 46? Expedited Forwarding (RFC 3246), the class for voice: low delay, low jitter, low loss.

What delay does voice need? ITU-T G.114 recommends under 150 ms one way. Jitter and loss matter as much, which is why voice gets its own queue.

See it on real machines

Learn it on real machines.

Every lab is a small network of real Linux machines in your browser. Start with a free account: Google or email, no card.

Open this lab