MikroTik Solutions

CAKE Configuration
Login

CAKE Configuration

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 \
    total-queue=default

This yields low latency increases under load here.

Speed Limits

The single most important setting is near the end: the max-limit on the simple queue. At the time I came up with this configuration, my ISP’s marketing department claimed “Download speeds up to 300 Mbps!” for my chosen service, and yes, on a speed test without CAKE enabled, I could peak into the 350 Mbit/sec range. Problem is, latency became terrible.

My ISP did not make any claims about that service option’s upload speed, but similar tests showed a burst speed limit of around 26 Mbit/sec.

Why did I limit it as you see, then? Easy: because if I went any higher than this, my excess latency numbers started increasing to worrying levels. I decided 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 ~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.

It is possible to use a single CAKE queue for both transmit and receive, but because I chose to make use of the cake-flowmode parameter to give different behavior for sending versus receiving, we have to split the configuration accordingly.

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. If you look under Queues → queue1 → Statistics in WinBox under full load, the “Target Upload” speed for the above configuration should be around 256M and “Target Download” speed around 24M, which feels backwards until you realize that when you download something to one of the router’s clients, you do so by making the WAN interface upload that traffic to the client. Since the queue is affecting the WAN interface — and it alone — its perspective is what matters here.

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 350/25 connection is 14:1, and even under the more stringent speed limits I assigned above, it approaches 11:1.

If you’re lucky enough to have a symmetric Internet link, you might not need this.

At one point, Xfinity was giving me a 100/5 connection — 20:1! — where ack-filter-aggressive might have been necessary to get the best results.

This is another reason I chose to split the queue into Rx/Tx halves. Other than the basic flow-control mechanisms built into TCP, we can only control our sending rate, not that of remote TCP/IP stacks, which we perceive as receiving rate. 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 but are regularly making heavy use of the major Internet services headquartered along our west coast, from California up through Washington state, there’s a good chance that your clients are actually connecting to a CDN datacenter somewhere on your own continent. Likewise, those living in the US have a decreasing likelihood of traffic going off-shore even with “foreign” services as they 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, flows are becoming indistinguishable at the RouterOS level.

With no way to mark distinct flow types reliably, I chose 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.

Total Statistics

The total-queue=default setting allows this queue’s statistics to contribute to Queues → queue1 → Total Statistics in WinBox as well as the per-queue Statistics tab. The sparse documentation for this mode offers no clue why this is the case, but I have verified it here on RouterOS 7.21rc4.

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:

  1. Disable it. This is fine for testing, but be sure your testing is complete before calling it good.

  2. Remove it. Do this only if the router you’re applying this CAKE shaping to doesn’t need fast-tracking for LAN traffic.

  3. 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:

+2 ms under load = no bufferbloat

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

The thread “some quick comments on configuring cake” is well worth reading. It was started by Dave Taht, a significant contributor to CAKE, since deceased. Some of the advice above came from him. He will be missed.

License

This work is © 2024-2026 by Warren Young and is licensed under CC BY-NC-SA 4.0


  1. ^ Otherwise, CAKE’s ACK filtering can have no effect since WireGuard is a UDP protocol, and any TCP headers inside the tunnel are encrypted.
  2. ^ 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: