CAKE w/ Adaptive Bandwidth [August 2022 to March 2024]

The "CAKE w/ Adaptive Bandwitdh" project builds on nearly a year of effort by many experts on this forum. For details concerning its early development, see this archived thread: CAKE w/ Adaptive Bandwidth [Historic]

This topic can serve as a place to continue the discussion for all projects:

We are happy to post links to other implementations.

Prior discussion: CAKE w/ Adaptive Bandwidth [Historic: October 2021 to September 2022]


We are pleased to announce an initial release of cake-autorate, a script that controls the latency for links with varying speeds, such as LTE, cable modems, and Starlink connections where the capacity varies by time of day, or even from second to second.

The cake-autorate script continually monitors receive and transmit load and the latency to known hosts in order to automatically adjust the CAKE algorithm's parameters to maximize bandwidth while keeping latency low.

For convenience, an installer script is available ( that installs all the packages and files required for cake-autorate. For more details about cake-autorate, or to find the installer script, visit the Github repository at:

Update: CAKE-autorate 1.1.0 - 28Sep2022 available

Implemented several new features such as:

  • Switch default pinger binary to fping - it was identified that using concurrent instances of iputils-ping resulted in drift between ICMP requests, and fping solves this because it offers round robin pinging to multiple reflectors with tightly controlled timing between requests
  • Generalised pinger functions to support wrappers for different ping binaries - fping and iputils-ping now specifically supported and handled, and new ping binaries can easily be added by including appropriate wrapper functions.
  • Generalised code to work with one way delays (OWDs) from RTTs in preparation to use ICMP type 13 requests
  • Only use capacity estimate on bufferbloat detection where the adjusted shaper rate based thereon would exceed the minimum configured shaper rate (avoiding the situation where e.g. idle load on download during upload-related bufferbloat would cause download shaper rate to get punished all the way down to the minimum)
  • Stall detection and handling
  • Much better log file handling including defaulting to logging, supporting logging even when running from console, log file rotation on configured time elapsed or configured bytes written to


Damn! i search for that since a long time and today you release that script. I'm glad and impress i can look for videos without to manually select minimum resolution. I have a A+ all the time now on waveforme bufferbloat test page, BUT i realize that my isp is shaping my 4g connection to 2,5mbps. Without you script my bandwith can go to 50000 mbps with lots of bufferbloat

My config is on movistar chile with an quectel ec25 modem.
Low 1000kbps
Base 25000kbps
Hight 50000kbps

With that script result, can i make denunciation for a excessive shaping ?
I have a directional 12dbi antenna to the only tower like at 5 km far. The at+csq returns me 28,99.
I apply the ttl=65 to make sure that they are not detect me as computer

All datas i can send to you :wink:


I have experienced Vodafone UK selectively throttling 4G in dependence upon port number, but this can be circumvented with the use of a VPN.

Have you tried the script yet? It is pretty easy to set up and may need some configuring to optimize it for your connection. You can indeed control how aggressively it adapts the rate up or down in dependence on the monitored load and latency.

Yes i did test it, i read the script config entirely. For me agressivity parametter seems to be a bit boring to adjust and i dont know how it will impact the connection.

Interesting. Did that make any appreciable difference? From reading up about this I understand that there is some speculation that certain mobile providers look at TTL to determine what sort of device is connected. I had imagined they went with IMEI though. Perhaps it is a mixture of the two?

See e.g. this OpenWrt thread: Bypass ISP Block with TTL

Certainly in my case passing through a VPN makes a big difference in terms of circumventing throttling to 10Mbit/s on ports 80 and 443. So this makes me wonder about other measures like tweaking the TTL.

@patrakov what do you know about this? Would you expect a Huawei B818-263 operating in bridge mode to reduce the TTL by 1? Any way I can test that?

I see on my wan:

(tos 0x0, ttl 64, id 14885, offset 0, flags [DF], proto TCP (6), length 211)

I wonder if increasing TTL to 65 would make any difference? Hmm.

I have no idea how Huawei B818-263 operates in bridge mode. It might have been implemented not as a true bridge, but as IP Passthrough, where the device still acts as a router, by not claiming the IP assigned by the ISP, but routing it downstream (and thus decreasing the TTL). In fact, some firmware versions on other Ethernet-connected 4G modems have separate "IP passthrough" and "Bridge" modes.

1 Like

The IMEI check catches using an unauthorized modem instead of a phone on phone-only plans. The TTL check catches unauthorized sharing of the connection (e.g. over WiFi) via an authorized phone on the same kind of plans.

1 Like

I'm not sure if ttl do something. I just tried it. The things is not bad for anonimise.
I would test if they put concurrent TCP connections limits, but i dont remember where i saw how to do that.

I just want to test with national reflectors. Because i think my isp is agregating to much to the international. Maybe add a lot of bufferbloat on the frontiere :wink:

National reflectors are obviously not the good way for me. because of the high international aggregation. it gives me more speed nationally but when navigating internationally it gives me more Bufferbloat.

an important indication "do set some ingress /egress shaping in sqm cake/piece_of_cake either ifb4 interface wil be set to DOWN and cake-autorate will not start."

other question as i'm LTE4g connection i'm not sur what tu configure in linklayer adaptation in sqm config.

There is a problem however with selecting international reflectors, international paths can be quite variable and it might be wasteful to throttle all traffic down to X Mbps even though the only path affected to one of the international reflectors might not actually be used by any of your applications. Yes, by design autorate does not care where along a path you encounter congestion, but for things like shaping for a known variable-rate link like LTE selecting reflectors as close to the other side of that link seems the best approach. (If you select sufficiently variable international reflectors that only share the LTE link as common path and use a rule where you only throttle down if all reflectors indicate congestion you essentially just found a more complicated way to sample just on the other side of the LTE link).
However, if you already know that all/most of your traffic goes to a few specific locations (potentially far away) AND you can find reliable reflectors close to these locations, it can make sense to use such a curated remote reflector set, so autorate will try to control for the "full" path, but you need to accept that this might well result in staying considerably below the (still latency-conserving) throughput you could achieve to/from other servers.

You are not alone in that, specific encapsulations are hard to empirically deduce post hoc.
However LTE seems to use less overhead than real ethernet and overestimating the per-packet-overhead is generally benign (unless you want to saturate your link with small packets, but you likely run into CPU issues before the wrong overhead is going to lead to noticeable throughput loss).
Most importantly however, getting the overhead wrong results either in less throughput than possible or higher latency, but autorate will try to give you the highest throughput that does not cause too high a latency increase anyway, so the exact overhead number does matter even less than usually.

thanks for the information, so i will use local reflectors and i find oficial speedtest servers of my isp so i will be able to watch for national network issues and if not international network issues.

But this morning i saw like a bug i don't understand.
when i

  • stop sqm i have some jitter and like 10mbps
  • start sqm with no shaper i have the same stats
  • activate sqm shaper with no cake_autorate same stats
  • start cake_autorate , the test mesure ping and jitter but fail to connect to download mesurment.
  • stop cake_autorate keeping sqm shaping the test mesure ping and jitter but fail to connect to download mesurment.

any idea ? maybe they are bad reflectors :confused:

Od, you should at least, even with the baddest of bad reflectors your 1000 Kbps minimum rate as configured for cake-autorate... (sure that 1000 is a gross rate, so the goodput will be lower).

You could test with a static sqm set to 1000Kbps whether this looks different?

Which rate did you set, the minimum 1000Kbps rate or the 25000Kbps base rate?

I had changes to real contract value for the

  • 128kbps for the min
  • 37mbps max
  • 25 mbps arbitrary for the base
    i put 37000kbpsin the sqm shaping

now i tried with

  • 1000kbps for the min, which makes the speedtest works
  • 37mbps max
  • 7 mbps which is the medium national value published by this isp
    let 37000kbpsin the sqm shaping

but the result test is never much higher than the min.
debug indicates me :
DEBUG Connection idle. Enforcing minimum shaper rates.
the idle value is
connection_active_thr_kbps=200 #

What is your average ping to the reflectors? The cake-autorate defaults are pretty aggressive so we may need to loosen these up a bit.

Could you please enable output logging and post some data here or on pastebin? So start cake-autorate in terminal and then start speed test and post data here?

movistar spedtest servers
santiago "" 
21 packets transmitted, 21 received, 0% packet loss, time 20025ms
rtt min/avg/max/mdev = 56.966/89.634/185.993/33.873 ms

punta arena ""
60 packets transmitted, 58 received, 3% packet loss, time 59220ms
rtt min/avg/max/mdev = 65.233/124.185/285.724/55.508 ms

talca ""
41 packets transmitted, 40 received, 2% packet loss, time 40100ms
rtt min/avg/max/mdev = 47.009/116.940/392.027/73.933 ms

concepcion "" 
27 packets transmitted, 25 received, 7% packet loss, time 26180ms
rtt min/avg/max/mdev = 32.509/94.049/197.877/41.839 ms

temuco ""
40 packets transmitted, 39 received, 2% packet loss, time 39133ms
rtt min/avg/max/mdev = 36.318/66.327/101.320/15.920 ms

full log :
config :

1 Like

In the script it mentions cake-dual-ifb as a solution to VPN and cake. Could someones please explain how this would work.

Currently I have wireguard routing 1 IP address through VPN PBR. I works very well but CAKE see it as just 1 stream. Is this a solution to that?

1 Like

Sure - the idea is this:

Basically two IFBs are created, one for upload (ingress from br-lan/br-guest) and one for download (egress from br-lan/br-guest). LAN-LAN traffic is passed over. CAKE is applied on those two IFBs and since this is at the LAN stage we don't have to worry about encrypted and unencrypted flows.

Details with installation instructions are here:

If you don't care about DSCPs, then you can probably ignore the below. And frankly just using CAKE w/ besteffort seems to get 90% out of the 100% of the available benefit for many use cases anyway. The value of DSCPs to tin traffic appropriately become more important for lower bandwidth connections (sub 10Mbit/s).

As an optional extra (likely not needed for many use cases): I am presently working on getting DSCPs set up for this use case in the following way (which reflects my personal preference for using DSCPs): namely you set DSCPs in client devices on upload (e.g. in Windows using powershell for a given application) and then the router records the DSCP identified from outgoing upload packets and restores those in respect of incoming download packets based on flow tracking capability in linux.

I also have another solution to this problem here:

This works differently in respect of the ifb-dl: namely, it creates an IFB that combines ingress traffic from the WAN and VPN by skipping over the packets in WAN with the source address being equal to the WireGuard peer.

Finally I have an outline for a predominantly nftables based solution here:

Which to use will depend on your specific requirements and preferences. Personally I favour the first approach but one drawback is that custom DSCPs cannot readily be set in respect of upload because I don't think I can get nftables to adjust the DSCPs in time for the br-lan/br-guest ingress to include the modified DSCPs. If that was really wanted then a hybrid of the first and third approach could be created in which we have nftables create the download IFB from br-lan and br-guest and tc create the upload IFB from br-lan/br-guest egress.

Sorry to give so many options but better to spell them out I think and let users decide which to go for. Please let me know if you have any questions at all and happy to answer in this thread.

@rosbeef I will analyse your data shortly.

1 Like

Today i put All my reflectors to isp speedtest national servers. Remember i'm on an lte at+csq 28 quality connection with lot of saturation between 18:00 and 01:30

During the day i test bandwith with no sqm i have 70mbps so i put max dl shaper to 70000

I tried to play with

delay_trh_ms : i understand that the higher is the value the more useless is autorate script, right? Because it don't care about jitter inferior to this value.
I have more bandwith but more jitter incase of saturated link.

I put connection_active_thr_kbps to 50 as i observe that with no users active bandwith consumsion is 35kbps

I don't understand if i have to put higher or lower value in monitor_achieved_rates_interval_ms for a 12mbps link.

Next params for a next day :wink:

Here is a plot of your data:

Basically we can see that delay_thr_ms is way too low for your connection. It probably should be something like 50 or 75. Leave monitor_achieved_rates_interval_ms at default but try this:

# bufferbloat is detected when (bufferbloat_detection_thr) samples
# out of the last (bufferbloat detection window) samples are delayed
bufferbloat_detection_window=8  # number of samples to retain in detection window
bufferbloat_detection_thr=4     # number of delayed samples for bufferbloat detection

And please re-run and paste new data.