Motivation
Applying some type of queuing to your Internet uplink can greatly help with bufferbloat, a phenomenon that adds increasing latency as the link becomes saturated. The easiest of these to configure on RouterOS is CAKE, but there are a lot of options to consider and not much guidance from the official docs.
In this article, I will explain this seemingly simple configuration:
/queue type
add kind=cake \
name=cake-rx \
cake-diffserv=besteffort \
cake-flowmode=dual-dsthost \
cake-rtt-scheme=regional \
cake-nat=yes
add kind=cake \
name=cake-tx \
cake-ack-filter=filter \
cake-diffserv=besteffort \
cake-flowmode=dual-srchost \
cake-rtt-scheme=regional \
cake-nat=yes
/queue simple
add name=queue1 \
max-limit=256M/24M \
queue=cake-rx/cake-tx \
target=ether1
This yields low latency increases under load here.
Speed Limits
I’m not going to cover the configuration in the order given above, because the most important setting is near the end: the max-limit
on the simple queue. I’m currently getting a connection from my ISP which their marketing department claims to give “Download speeds up to 300 Mbps!” And, yes, on a speed test without CAKE enabled, I can peak up into the 350 Mbit/sec range. Problem is, latency becomes terrible.
My ISP doesn’t make any claims about upload speed, but similar tests show a burst speed limit of around 26 Mbit/sec here.
Why do I limit it, then? Easy: because if I go any higher than this, my excess latency numbers start increasing to worrying levels. I’m willing to give up my burst rates to get more predictable latency.
You will almost certainly have to adjust these values to match your own local Internet performance. I suggest testing with CAKE disabled to get a baseline, then set these values a ~10% lower than what’s reported. Keep reducing them stepwise until you get your excess latency down into the single-digit milliseconds range. There’s no especially good reason to shoot for an ideal zero, but if you can afford the peak speed loss, why not?
It is possible to use a single CAKE queue for both transmit and receive, but I’ve chosen to make use of the cake-flowmode
parameter to give different behavior for sending versus receiving.
There is one additional important detail you have to keep in mind: the bandwidth limits are given from the target interface’s perspective, not that of your client. We are used to specifying asymmetric Internet bandwidths like these in terms of the client perspective, but that will give you an upside-down view of the way RouterOS queues work. WinBox will tell you that my “Target Upload” speed is 256M and my “Target Download” speed is 24M, which feels wrong until you realize that when I download something to my client computer, I do so by making the WAN interface upload that traffic to my client.
Interface and Address Targeting
The simple queue we’re attaching the CAKE shaper to needs to know which flows it should apply to. You don’t want it throttling your LAN’s 10G backbone, and there’s likely no need to shape local WiFi separately from outbound Internet traffic. It is for this reason that my setting above targets my WAN interface, shown here as the common ether1
default.
For a typical home Internet gateway, you do not want to set a dst
address value instead of or in addition to the target
interface. RouterOS isn’t flexible enough to let you target everything but the LAN by address rules alone, for instance. Targeting the WAN interface is simpler.
ACK Filtering
The purpose of the cake-ack-filter=filter
setting on the cake-tx
queue is to reduce the overhead of TCP ACK packets by removing ones not strictly necessary. TCP was designed with symmetric network speeds in mind, but with modern 10:1 or worse splits, it becomes important to reduce unnecessary upload traffic. My nominal 300/20 connection is 15:1, and even under the more stringent speed limits I assign above, it’s still running at a nearly 11:1 ratio.
If you’re lucky enough to have a symmetric Internet link, you might not need this.
If you’re like me from about a year ago, when Xfinity was giving me a 100/5 connection — 20:1! — you might need to set it to ack-filter-aggressive
to get the best results.
We do this on the cake-tx
side alone because in typical cases, we can only control what we send to remote TCP/IP stacks, not what they do in turn. There are exceptions to this, as with a site-to-site WireGuard tunnel where the queue is applied to the decrypted end of the tunnel,1 but even in that case ACK filtering has its most useful effect on the narrow side of an asymmetric pipe. Consequently, the best strategy is to do this ACK filtering on each peer’s Tx side alone, improving the remote site’s Rx queuing from afar.
Round-Trip Time
The cake-rtt-scheme=regional
setting may surprise you. Why not set it to “internet
”?
The reason is that these are heuristic values based on general assumptions. What “internet
” actually means in this context is a 100 ms ping time, as if we still lived in a world where you could reasonably be contacting servers across the globe regularly.
CDNs changed this. Even if you live outside the US and are regularly making heavy use of Silicon Valley services, there’s a good chance that your clients are actually connecting to a CDN datacenter somewhere on your continent. If you live in the US, the chance of your traffic going off-shore is increasingly small as services consolidate into CDNs and top-tier hosting providers.
With my ISP’s unloaded ping time of around 25 ms, I chose the “regional” mode, which sets the RTT to 30 ms, the closest match I could achieve without resorting to the custom “rtt
” option.
Best-Effort Diffserv
Differentiated services is the practice of setting marks on various types of data flows, to allow the router to give preferential service to certain types of traffic. A common scheme is to give VoIP calls first-priority access to the bandwidth, then video conferencing, then gaming, and then to dump everything else into a bulk-download bucket.
The key problem with this concept is that it depends on being able to reliably identify the flows, which is increasingly impossible in today’s all-CDN HTTPS-everywhere world. In the name of privacy and performance, all flows now look identical at the RouterOS level, making it all but impossible to mark them reliably.
Thus my choice to tell CAKE to try its best without any hints from me. It works well in my testing.
Enabling any of the diffserv*
options without actually applying the related markers burns CPU time to no useful end.
NAT
CAKE has a mode for accommodating NAT addressing, cake-nat=yes
in RouterOS-speak. If you use NAT, enable this. If not, then don’t.
Fast-Tracking
For all of the above to take effect, you must modify the default “fasttrack” rule in the RouterOS firewall. Fast-tracking causes flows to bypass the CPU, which is bad for CAKE since it is implemented by the Linux kernel and thus runs purely on the router’s CPU. You have several paths out of this trap:
Disable it. This is fine for testing, but be sure your testing is complete before calling it good.
Remove it. Do this only if the router you’re applying this CAKE shaping to doesn’t need fast-tracking for LAN traffic.
Retarget it. Because I am the sort to run LAN-only
iperf3
tests across my router’s bridge, I prefer leaving this rule enabled but changed:/ip/firewall/filter add action=fasttrack-connection chain=forward \ connection-state=established,related \ comment="fasttrack LAN traffic only" \ out-interface=!ether1 \ in-interface-list=LAN \ hw-offload=yes
This allows CAKE to take effect for Internet traffic without affecting traffic crossing the router’s LAN-side bridge.
As of RouterOS 7.18, you can also do fast-tracking on the IPv6 side.
A fresh installation will have a default rule similar to the one above, so you will want to apply the same modification you made for IPv4 to it. For instance, if you prefer to take option 3 above like I do, then you need to make parallel out-interface=!etherN
and in-interface-list=LAN
exceptions to the IPv6 side.
If instead you are upgrading an existing router to 7.18+, the key rule won’t exist yet, so you will need to add it:
/ipv6 firewall filter
add action=fasttrack-connection chain=forward \
connection-state=established,related \
comment="fasttrack LAN traffic only" \
out-interface=!ether1 \
in-interface-list=LAN \
place=before=0
As of this writing, there doesn’t appear to be an hw-offload=yes
flag for the IPv6 firewall.
We add this rule at the start of the firewall chain to match how defconf does it for IPv4: once a given flow is marked as needing fast-tracking, it should bypass all the other rules since that flow has ipso facto made it through the firewall rules.
Failing to make these adjustments can lead to a difficult-to-debug problem in testing where your bufferbloat tests are great one day and terrible the next. What is likely happening here is that your client is ping-ponging between IPv4 and IPv6 addresses for the server based on round-robin DNS behaviors, and that this is in turn affecting the queue’s ability to do the job you gave it by creating a hidden toggle for fast-track mode.
Testing
I currently prefer the Cloudflare speed test for verifying CAKE effectiveness, for a couple of reasons.
First, it is known to prefer IPv6, which can spotlight the misconfiguration covered in the prior section.
Second, the service is on a sound financial basis. Cloudflare makes plenty of money, and that amount increases as a function of the number of potential customers who see their network performing well.
The main problem with this test is that it doesn’t give a simple letter grade and excess latency value like the famous Waveform test does. It gives only absolute values, requiring you to subtract them and decide if that delta is low enough:
The +7 ms we see on the loaded download test is also fine. As stated above, anything down in the single digits difference is good enough for nearly all practical purposes. What we’re after here is avoiding tens or hundreds of milliseconds of excess latency, not a sacrifice of top-end performance for little gain.
While this simplicity does make the Waveform test more popular, I’ve lately caught them reporting terrible results here back-to-back with excellent results from Cloudflare, even though it has given me an A+ on the queue configuration above in the past. Either my ISP is messing with Waveform in a way they wouldn’t dare attempt with a giant like Cloudflare, or the free ride is coming to an end. I favor the latter explanation because I never understood how Waveform made more money as a function of tests offered.2
A third option is Flent, but that’s far from easy to set up, and harder still to interpret its results properly.
References
Dave Taht’s thread “some quick comments on configuring cake” on the MikroTik forum is well worth reading.
License
This work is © 2024-2025 by Warren Young and is licensed under CC BY-NC-SA 4.0
- ^ Otherwise, CAKE’s ACK filtering can have no effect since WireGuard is a UDP protocol, and any TCP headers inside the tunnel are encrypted.
- ^ Yes, I see their Amazon affiliate links, but how many people run a test, get a bad result, and then go buy a new router via one of those links? I’m reasonably certain that my readers here want a fix using the router they already have, and I see no reason to believe RouterOS adherents are unique in this regard.
Attachments:
- cf-bb-test-latency.png [download] added by tangent on 2025-08-13 11:04:32. [details]