The complaint that started this was specific: "the call keeps freezing." Not the internet is slow, not Netflix buffers, just the call freezing for two seconds at a time, always when someone else in the house started doing something. That is the signature of a queue filling up somewhere, and on a home line the somewhere is almost always the upstream buffer in your own router.
We are a household that streams everything. Two people working from home on video calls, a games console pulling a 40GB update whenever it feels like it, a couple of 4K streams in the evening, a NAS doing offsite backup overnight, and the usual background hum of phones and a doorbell and whatever the thermostat talks to. None of that is unusual now. What is unusual is expecting it all to coexist on an asymmetric domestic connection without someone's call turning into a slideshow.
So I finally sat down and did QoS properly, rather than the half-hearted version I had been running for years. Here is what worked and what was a waste of an evening.
The problem is bufferbloat, not bandwidth
The first thing to be honest about: we have plenty of bandwidth. The line is fast enough. The problem is latency under load, and that comes from bufferbloat. When you saturate the uplink, packets pile up in a buffer waiting to be sent, and that buffer can hold a second or more of data. A video call needs its packets delivered in tens of milliseconds. If they are sat behind a backup upload in a fat queue, the call freezes, no matter how much total throughput you have.
You can see it without any fancy tooling. Start a big upload, then in another terminal:
ping -i 0.2 1.1.1.1
Idle, I was seeing about 12ms. With the NAS backup running, that climbed to 600–900ms and sat there. That is your call freezing, measured. Nine hundred milliseconds of latency is not a bandwidth problem, it is a queueing problem, and you fix queueing problems with smarter queues.
CAKE did most of the work
I run OpenWrt on the router that matters, so the answer was the SQM package and the cake qdisc with the piece_of_cake.qos script. CAKE is a modern queue management system that, broadly, keeps the buffer short and shares the link fairly between flows. The crucial part is that it has to be the bottleneck. If your ISP's equipment is the thing filling its buffer, your router managing its own queue achieves nothing, so you deliberately set CAKE's rate a little below your real line rate. That moves the congestion point into your router, where you control it.
The settings that mattered:
# /etc/config/sqm via LuCI, the values that count
download rate: 95% of measured down
upload rate: 90% of measured up
queue disc: cake
script: piece_of_cake.qos
I set upload to 90% rather than 95% because uplink is where the pain is on an asymmetric line, and the small sacrifice in peak upload speed buys back the latency. After enabling it the same ping-under-load test stayed under about 25ms with the backup running flat out. That single change fixed the frozen-call complaint, and I could have stopped there.
Prioritising by intent, not by device
CAKE alone gets you fair sharing, which is most of the win. But "fair" treats a backup upload and a video call as equals, and they are not. The call is latency-sensitive and low-bandwidth. The backup is the opposite: it wants throughput and does not care about a few hundred milliseconds. So the next step was telling the network what to favour.
The clean way to do this is DSCP marking. The idea is that you tag latency-sensitive traffic so CAKE's diffserv mode can put it in a faster tin. CAKE supports a diffserv4 mode that respects these marks. The honest difficulty is that most consumer apps do not mark their traffic usefully, and you should not trust marks coming in from the internet, so you do the marking yourself at the edge based on what you know.
A few rules covered ninety percent of it:
- The NAS backup job: marked as bulk (CS1), so it yields to everything.
- The work laptops' known video-call ports and the SIP handset: marked for low latency.
- Everything else: left at best effort, which is the sensible default.
I deliberately did not try to write a rule for every device and every app. That way lies a config you cannot maintain and will not remember the logic of in six months. Mark the two things that obviously want bulk treatment, mark the two things that obviously want low latency, leave the rest to CAKE's fairness, and you have captured most of the value for a fraction of the fuss.
What I did not bother with
I did not buy a faster line. The line was never the issue. I did not install a separate hardware QoS box, because OpenWrt on the router I already had does this perfectly well. And I did not try to police every device's total bandwidth with per-client caps, which is tempting and almost always a mistake: it makes the network feel worse for everyone in exchange for a tidy-looking graph. Capping a device to "be fair" just means it is slow even when nobody else is using anything.
The thing I keep relearning is that on a home network the bottleneck is rarely capacity and almost always the queue in front of the capacity. Once you accept that, the fix is small, cheap and durable. The console can pull its 40GB update in the background, the backup can run all night, and the call no longer freezes when someone opens YouTube. Nobody has complained since, which on a home network is the only metric that counts.