redzilla
Performance

QoS for Real: DSCP, Queues & Shaping

QoS doesn’t create bandwidth: it decides who suffers when it runs out. Mark well, queue well, smooth the bursts — that’s the whole science, and a bucket of tokens explains it.

≈ 11 min read

The ticket came in on a Monday: "phone calls break up whenever someone uploads backups". The link graph showed a serene 40% average utilization, and the manager asked — quite reasonably — what the 100 Mbps he paid for was doing. Here's the catch: averages are measured in minutes, congestion happens in milliseconds. One 30 ms burst that fills the egress queue is enough to make a voice packet miss its appointment. That's where QoS comes in, and let's get one thing straight up front: QoS doesn't add a single bit to your link. It's triage.

QoS doesn't manufacture bandwidth

Think of a hospital emergency room. Triage doesn't build operating rooms or hire doctors: it decides who goes first when there isn't enough for everyone. QoS is exactly that for a network interface: when more packets arrive than the wire can carry, somebody has to wait in the queue — or get dropped — and QoS picks who takes the hit. Nothing more, and nothing less.

Two uncomfortable truths follow. One: without congestion, QoS does nothing. With an empty queue, the packet marked as gold and the packet marked as coal leave equally fast; your elegant policy is pure decoration. Two: if the link is congested around the clock, QoS is anesthesia, not a cure — voice will sound pristine while everything else starves, and the real fix is more bandwidth. QoS earns its keep in the middle ground: links that have plenty on average but suffer microbursts. Which is exactly where 90% of real networks live.

DSCP: the sticker on the packet's forehead

To discriminate with any sense, you first have to label. The IPv4 header carries a byte that was born as "Type of Service" and is now the DiffServ field: its top 6 bits are the DSCP (Differentiated Services Code Point) and the remaining 2 are ECN, which is a different movie. Six bits give you 64 possible values, but in practice four of them pay the rent:

The ToS byte in the IP header: 6 DSCP bits holding 101110 (EF, 46) plus 2 ECN bits ToS / DiffServ byte of the IPv4 header example: a voice packet marked EF 1 0 1 1 1 0 0 0 DSCP = 101110 = 46 (EF) 6 bits: the packet's class ECN (2 bits) full byte = 10111000 = 0xB8 — the "tos 0xb8" tcpdump shows you
DSCP rides in the top 6 bits of the ToS byte. EF = 46 in decimal, 0xB8 if you read the whole byte.
ClassDSCPBinaryToS byteUse it for
EF461011100xB8RTP voice: small, sacred, delay-sensitive
AF41341000100x88interactive video (video calls, telepresence)
CS000000000x00best effort: web, mail, almost everything
CS180010000x20scavenger: backups, updates, the expendable stuff

EF (Expedited Forwarding) is for traffic that would rather die than arrive late: voice. AF41 gives interactive video a bandwidth guarantee without the voice-grade VIP pass. CS0 is the ordinary citizen. And CS1 — the scavenger class — is the most underrated item in the catalog: mark your backups and OS updates with it and they can hog the entire link at 3 AM, yet yield every last bit the moment somebody else needs it. Sometimes the best QoS isn't promoting voice: it's demoting the backup.

To see the marking live, a tcpdump is all you need: the ToS byte shows up on every packet.

router — is voice arriving marked?
$ sudo tcpdump -n -v -c1 udp portrange 16384-32767
IP (tos 0xb8, ttl 63, id 4211, offset 0, proto UDP (17), length 200)
    10.1.20.14.16402 > 10.1.9.7.16388: UDP, length 172

That tos 0xb8 is EF wearing a different haircut: 46 shifted two bits left (46 × 4 = 184 = 0xB8). All the conversions between DSCP, ToS, binary and class names — with the 21 standard classes — live in the DSCP / QoS calculator.

In IPv6 the field is called Traffic Class, but it's the same byte with the same layout: 6 DSCP bits plus 2 for ECN. Everything in this guide applies unchanged.

The boundary: trust or remark

Anyone can slap on a sticker. If your policy says "EF goes first", nothing stops a PC with a "gaming-optimized" network driver from marking its packets EF and cutting in line ahead of your phones. That's why every serious network defines a trust boundary: at the access port you decide whether to believe incoming marks or rewrite them. Corporate IP phone? Trusted. User laptop? Thanks for playing: everything to CS0, and if it carries known voice or video traffic, you re-mark it yourself with an ACL. From the edge inward nobody classifies again: the mark is trusted, period — deep inspection in the core is expensive; misplaced trust is far more so.

And here's the part people forget: the mark alone is decoration. The dirty work is done by queues. A proper switch or router sorts each packet by DSCP into a different queue: EF into the priority queue (served ahead of everything, with a policer on top so voice can never eat the whole link), AF41 into a queue with guaranteed bandwidth, CS0 into the common pool, CS1 gets the crumbs. The mark is the diagnosis; the queue is the treatment.

Your QoS ends where your network ends. ISPs almost always rewrite or ignore DSCP at their edge, so marking EF buys you zero priority across the Internet — only inside your LAN, your private WAN or your SD-WAN. If a provider sells you "end-to-end QoS" over the public Internet, ask them to show it to you in a tcpdump on the far side.

The bucket of tokens: how "how much may pass" gets measured

Marking and queuing sort the line; you still need the doorman who measures the flow. Nearly every platform uses the same mechanism: the token bucket. It works like an arcade: transmitting 1 bit costs 1 token. Tokens drip into the bucket at a constant rate — the CIR, your committed rate — and the bucket has a maximum size, Bc. When the bucket is full, new tokens spill over and are lost: there is no infinite savings account. Packet arrives and tokens are there? It sails through. No tokens? That's where the doorman's personality comes in — more on that in a moment.

With round, verified numbers: CIR of 1 Mbps and Bc of 8,000 bits. The refill interval is Tc = Bc ÷ CIR = 8,000 ÷ 1,000,000 = 8 ms, which means 125 refills per second of 8,000 bits each — multiply them and you get exactly the CIR back. And since the bucket never holds more than Bc, the maximum instantaneous burst is Bc: 8,000 bits, about 1,000 bytes in one go.

Token bucket: the CIR fills the bucket with tokens, the bucket size is Bc, and departing packets spend tokens The token bucket — CIR 1 Mbps, Bc 8,000 bits CIR = 1 Mbps refills tokens at a steady rate tokens = bits Bc = 8,000 bits bucket full: extra tokens are lost packet a packet of N bits spends N tokens Tc = Bc ÷ CIR = 8,000 ÷ 1,000,000 = 8 ms → 125 refills/s → max burst = Bc
Tc = Bc ÷ CIR = 8 ms → 125 refills per second. The bucket size (Bc) sets the maximum instantaneous burst.

The bucket is what makes real life bearable: traffic is never flat, and Bc defines how much burst you forgive without breaking the average. Now — what happens when traffic arrives and the tokens are gone? Two philosophies:

  • Policing — the scissors. Excess is dropped or re-marked to a worse class, on the spot. No queue, no added delay, no memory. Brutal but cheap.
  • Shaping — the funnel. Excess is queued and waits for tokens. Nothing is lost (while the queue holds), but the price is delay: the burst comes out ironed flat at the CIR.

Same burst, different fates: 20,000 bits arrive at once with a full bucket. The policer lets 8,000 through (the tokens on hand) and cuts 12,000. The shaper passes the same 8,000 immediately and queues the other 12,000, which drain over the next 12 ms (12,000 ÷ 1,000,000). Everything arrives — just later.

Policing clips the peaks of a burst above the CIR; shaping queues them and the same burst leaves smoothed but later Policing — the scissors excess gets cut (drop or remark) Shaping — the funnel excess waits in a queue and leaves later CIR this gets cut t → 280 pass · 100 are cut (of 380) CIR the excess leaves later t → all 380 pass · the price: delay
The same 380-unit burst: policing clips whatever pokes above the CIR; shaping smooths it and delivers it later.

When to use which? Police what you receive: at the inbound edge, so no customer or branch exceeds its contract. Shape what you send toward a slower link or a contracted CIR: better to let your own queue decide what waits — with your priorities — than to let the far-side policer chop blindly. TCP, on top of that, handles delay far better than loss: every policer drop means a retransmission and a window collapse. You can play with the parameters — CIR, Bc, Tc, and whether your burst fits — in the token bucket calculator.

If you bought 100 Mbps from your ISP, shape your own egress to about 95% of it. It sounds like donating 5 Mbps, but it's the opposite: congestion now happens inside YOUR device, where per-class queues exist and voice leaves first — not in the provider's policer, which cuts without ever looking at the DSCP.

Jitter buffer: buying order with latency

Even with perfect marking and shaping, the network never delivers on a clock. Voice needs one: a codec with a 20 ms ptime emits one packet every 20 ms sharp — 50 per second — and the listener needs them played back on exactly that beat. The variation between arrivals is jitter, and the remedy is the jitter buffer: a waiting room that holds freshly arrived packets a moment and hands them to the codec on a metronome. The trick is that this order is bought with latency — every millisecond of buffer is one more millisecond of delay in the conversation. The practical sizing rule: 2 × the measured jitter. Let's run the full budget:

  1. You measure the actual jitter toward the PBX: 20 ms. The call uses a ptime of 20 ms (one voice packet every 20 ms).
  2. Buffer = 2 × jitter = 2 × 20 = 40 ms. In depth: 40 ÷ 20 = 2 packets sitting in the waiting room.
  3. Mouth-to-ear budget: network 50 ms + buffer 40 ms + codec 15 ms + packetization (ptime) 20 ms = 125 ms.
  4. ITU-T G.114 puts the comfort limit at 150 ms one-way: 125 ≤ 150 → a fluid conversation, with 25 ms to spare.
  5. Cross-check: if jitter climbs to 40 ms, the buffer grows to 80 ms and the total to 165 ms — over the limit, and the walkie-talkie effect kicks in, with both parties talking over each other. Jitter charges you twice: it scrambles arrivals and inflates the buffer.

That's the deep reason to mark voice EF and give it a priority queue: it's not about the megabits (a call weighs almost nothing), it's about keeping jitter down so the buffer can stay small. Size the buffer and the mouth-to-ear budget with the jitter buffer calculator, and get the real per-call bandwidth — headers and all — from the VoIP calculator.

Video: reserve by percentile, not by average

Video is the elephant in the QoS room: a single camera can outweigh your entire phone system. Its bitrate depends on resolution, frame rate, codec and quality (bits per pixel), and the big lever is the codec: at comparable quality, H.265 asks for roughly half of what H.264 does. A 1080p30 stream at 0.1 bpp works out to 1920 × 1080 × 30 × 0.1 ≈ 6.2 Mbps in H.264 and ≈ 3.1 Mbps in H.265. Estimate yours — with your resolutions and quality targets — in the video bitrate calculator.

The detail that breaks networks: that figure is an average, and modern video is variable-rate. Static scene, barely anything; someone walks past the camera or an I-frame lands, and the bitrate jumps to 2 or 3 times the average for a few hundred milliseconds. If you sized the AF41 queue from the average, every spike arrives precisely when the guarantee runs out — and the video pixelates exactly at the interesting moment. Reserve by percentile (the p95 of the measured bitrate, not the datasheet), and let shaping absorb whatever pokes above it.

The short recipe

Serious QoS is four moves: confirm the congestion is real (in milliseconds, not 5-minute averages), mark at the edge and remark whatever you don't control, give each class a queue with a real guarantee, and smooth your egress before someone else's policer chops it. Start today: check with tcpdump whether your voice leaves the building marked EF — it takes a minute, and the answer is usually half the diagnosis.

Tools to practice with