Berik Ashimov // senior.it.engineer
Download CV
POSTS / MIKROTIK

CAKE on RouterOS 7: Killing Bufferbloat Without a QoS Degree

// series · MikroTik RouterOS 7 Guide part 9 of 35
  1. ... 6 earlier
  2. IKEv2 on RouterOS 7: Certificates, Mode-Config, and the Profile/Proposal/Policy Maze
  3. IPv6 on RouterOS 7 Without Fear: Prefix Delegation, RA, and a Firewall That Holds
  4. CAKE on RouterOS 7: Killing Bufferbloat Without a QoS Degree
  5. Multi-WAN on RouterOS 7: Recursive Failover, PCC Load Balancing, and When ECMP Is Enough
  6. Policy-Based Routing on RouterOS 7: Tables First, Marks Second
  7. ... 24 later
view the full series →

Your internet is not slow. Your internet is bloated. When someone starts a backup upload and video calls turn to slideshow, bandwidth isn’t the problem — a 500 Mbps line has plenty. The problem is that a bulk transfer fills a deep buffer somewhere (usually in your ISP’s modem), and every packet behind it — including your call’s — waits in that queue. Latency goes from 15 ms idle to 300+ ms under load. That’s bufferbloat, and it’s why “we upgraded to gigabit and Teams still stutters.”

For years, fixing this on RouterOS meant hand-built queue trees with PCQ and a weekend of tuning. RouterOS 7 ships CAKE — the same qdisc the OpenWrt world has used to solve this for a decade — and it turns the weekend into fifteen minutes. One queue type, a bandwidth number, done. There is exactly one trap, and it’s called fasttrack. We’ll get there.

Bufferbloat 101

Queues exist to absorb bursts. The failure mode is queues that are too deep and dumb: FIFO buffers holding hundreds of milliseconds of packets, drained strictly in order. TCP is designed to fill any buffer it finds — it speeds up until packets drop, and a deep buffer delays that signal by whole seconds. Result: throughput looks great, latency is destroyed, and every interactive flow (VoIP, games, SSH, DNS) suffers for the benefit of a download that wouldn’t have noticed 20 ms more delay.

The fix has two parts, and CAKE does both:

  1. Shape below the bottleneck. You can’t manage a queue you don’t own. By limiting the router to slightly less than the ISP line rate, the queue forms in your router (smart) instead of the modem (dumb).
  2. Manage the queue well. CAKE combines fair queuing across flows (one greedy transfer can’t starve others) with AQM (mild early dropping/marking keeps TCP honest before delay accumulates).

Measure before you touch anything: run the Waveform bufferbloat test (waveform.com/tools/bufferbloat) and note idle vs loaded latency. A grade of C or worse means everything below will produce a visible improvement.

Queue Types in RouterOS 7

/queue type defines algorithms; simple queues and queue trees are attachment points that use them. The inventory: pfifo/bfifo (dumb buffers), red, sfq, pcq (the classic RouterOS per-user fairness workhorse), fq-codel (modern fairness + AQM, no shaper of its own), and cake — fq_codel’s descendant with an integrated shaper, diffserv awareness, NAT awareness, and ACK filtering. If you’re building new QoS on RouterOS 7 there is very little reason to reach past CAKE.

Two CAKE instances, one per direction — download shaping wants slightly different treatment than upload:

Terminal window
/queue type
add name=cake-down kind=cake cake-diffserv=besteffort cake-nat=yes \
cake-rtt-scheme=internet cake-ack-filter=none
add name=cake-up kind=cake cake-diffserv=besteffort cake-nat=yes \
cake-rtt-scheme=internet cake-ack-filter=ack-filter

Parameter rundown, in order of how much they matter:

  • cake-nat=yes — the sleeper. CAKE’s per-host fairness looks at IP addresses; post-NAT, all your LAN traffic shares the router’s WAN address and fairness collapses to nothing. cake-nat=yes makes CAKE peek into conntrack and use real internal hosts. On any NATed edge router this should always be on.
  • cake-diffserv — how much CAKE trusts DSCP marks: besteffort (ignore them), diffserv3, diffserv4, diffserv8 (3/4/8 priority tins). On a home/office WAN where inbound DSCP is whatever the internet felt like sending, besteffort is the honest choice. If you deliberately mark traffic (VoIP phones, mangle rules), diffserv4 gives marked traffic its own tin. Pair with cake-wash=yes to scrub inherited marks after queuing.
  • cake-ack-filter=ack-filter — on the upload queue only. On asymmetric lines (DOCSIS, DSL), floods of TCP ACKs from downloads can choke the thin upstream. The filter thins redundant ACKs. ack-filter-aggressive exists; plain ack-filter is the safe setting. Pointless on symmetric fiber, harmless too.
  • cake-rtt-scheme=internet — tunes AQM for ~100 ms paths, the right default for a WAN. (datacentre and friends exist for other environments, or set cake-rtt explicitly.)
  • cake-overhead / cake-overhead-scheme / cake-mpu / cake-atm — per-packet link-layer overhead compensation (PPPoE, ATM, DOCSIS). Setting the scheme for your access tech makes shaping accurate at small packet sizes; skipping it just means shaving your bandwidth number slightly more.

Simple Queue vs Queue Tree

Simple queues are the five-minute path: one object, both directions, attach and go. Queue trees attach per-interface via mangle marks, scale better on multi-hundred-megabit lines, and let CAKE’s own cake-bandwidth do the shaping. Start simple; move to a tree if CPU or complexity demands it.

The simple queue version — target is your LAN subnet, max-limit is upload/download at 85–90% of measured line rate:

Terminal window
/queue simple
add name=wan-cake target=10.0.10.0/24 max-limit=90M/450M \
queue=cake-up/cake-down comment="CAKE bufferbloat shaper"

That’s genuinely it — for the queue half. The max-limit shaper forms the queue in the router and CAKE manages it. Don’t be greedy with the numbers: at 100% of line rate the modem’s buffer still engages and you’ve built an elaborate no-op. Start at 85%, verify, creep upward while the grade holds.

The queue tree version, for when you want CAKE’s integrated shaper and lower overhead:

Terminal window
/queue tree
add name=up parent=ether1 queue=cake-up-shaped
add name=down parent=bridge-lan queue=cake-down-shaped
/queue type
add name=cake-up-shaped kind=cake cake-bandwidth=90M cake-nat=yes \
cake-ack-filter=ack-filter cake-rtt-scheme=internet
add name=cake-down-shaped kind=cake cake-bandwidth=450M cake-nat=yes \
cake-rtt-scheme=internet

Parenting down on the LAN bridge (rather than a global mangle construction) is the pragmatic way to shape “download” — traffic egressing toward the LAN. Purists note that shaping ingress is always approximate; practitioners note that it works.

The Fasttrack Conflict

Here is where every first attempt dies. The RouterOS default firewall contains:

Terminal window
/ip firewall filter
add chain=forward action=fasttrack-connection connection-state=established,related \
hw-offload=yes comment="defconf: fasttrack"

Fasttracked packets bypass the Linux queuing layer almost entirely — simple queues and queue trees never see them. You’ll add your beautiful CAKE queue, run a speed test, and watch the queue counters sit at zero while latency stays bloated. Nothing is broken; the packets are taking the express lane around your queue.

You have three options, in descending order of QoS purity:

Terminal window
# Option 1: disable fasttrack entirely — all traffic is queueable
/ip firewall filter set [find action=fasttrack-connection] disabled=yes
# Option 2: keep fasttrack for LAN-to-LAN or other traffic you never queue,
# but exclude WAN-bound traffic from it
/ip firewall filter
add chain=forward action=accept connection-state=established,related \
out-interface-list=WAN place-before=[find action=fasttrack-connection] \
comment="bypass fasttrack for WAN (CAKE needs to see this)"
add chain=forward action=accept connection-state=established,related \
in-interface-list=WAN place-before=[find action=fasttrack-connection] \
comment="bypass fasttrack from WAN"

Option 3 is “keep fasttrack and accept that QoS only applies to new/unmatched flows” — which is to say, not an option.

The cost is real: fasttrack exists because it massively cuts per-packet CPU. Without it, a RB4011/RB5009-class device shapes several hundred megabits with CAKE comfortably; an aging hEX will top out far lower. Check /system resource print CPU load during a speed test — if you’re pegged, CAKE at your line rate needs newer hardware, or you shape only upload and accept partial wins. And note the same bypass logic applies to IPsec earlier in this series — fasttrack is the recurring villain of “RouterOS feature silently not seeing traffic.”

Verifying

Counters first — prove CAKE is actually in the path:

Terminal window
/queue simple print stats
# bytes/packets climbing during a speed test = traffic is being queued
# stuck at zero = fasttrack is still eating it
/queue tree print stats # if you went the tree route
/tool torch interface=ether1 # watch real throughput vs your max-limit

Then the actual test: back to Waveform’s bufferbloat test. Before CAKE, a typical cable line shows +5 ms idle → +200 ms under load, grade C or D. After: load-added latency in the +0–10 ms range and an A grade. That “+5 ms under full load” number is the entire point of this article. Run it at different times of day — if evening grades sag, your ISP’s actual delivered rate sags too, and your max-limit/cake-bandwidth needs to sit below the worst-case line rate (or you accept the compromise).

For continuous verification, ping 1.1.1.1 in one terminal while a speed test runs in another is the poor man’s monitor: the ping should barely move when the transfer starts.

Closing Thoughts

CAKE is the rare QoS technology where the honest advice is “turn it on and stop tuning.” The complete recipe: two kind=cake queue types with cake-nat=yes (ack-filter on upload), one simple queue at ~85–90% of line rate, fasttrack disabled or bypassed for WAN traffic, verified with a bufferbloat test and non-zero queue counters.

Resist the urge to build diffserv8 trees with per-service mangle marks on day one. Flow fairness alone — every flow gets its share, no flow monopolizes the buffer — solves 95% of perceived congestion on a typical network. Add DSCP tins later if a real requirement (a call center, a latency-critical app) shows up in your measurements. Measurement-driven, like the multi-WAN failover we cover next — where the same fasttrack and mangle machinery reappears in a different costume.

// share