SQM cake: traffic prioritisation

In general, the basic settings for cake (and fq_codel) in OpenWrt's SQM do exactly this, without the need to worry about prioritization. (The basic settings work great on my home router, even at crummy 7 mbps DSL rates.)

We recommend you configure SQM as described in the Howto and let it run for a week or so. If it's working well and you are happy, you can spend time on other projects.

If those settings don't work well enough, you'll have specific information you can bring back to the forum to ask for help. Good luck!

1 Like


I've been running SQM with cake for many months now but I've only just got around to commenting.

I have found when torrenting especially, web browsing slows down and feels less responsive. This seems to be when the torrent client is taking most of the bandwidth. To me, it seems like browsing isn't being given enough bandwidth in this scenario.

I have setup cake and SQM as per the wiki, including using all the advanced options to ensure per host fairness.

Question, are you trying to run the torrent client and the web browser on the same computer?
If no, the per-internal-IP fairness modes that cake offers might help your use case. Other than that you can always try to use the torrent clients build in rate limiting as well. Torrenting tends to use many parallel flows and hence will be happy with cake's default flow-fair queueing, but that is one of the reasons why cake grew the IP fairness modes as well. And just to explicitly state this, in IP fairness mode, cake will first share equitably between all concurrently active internal IP addresses but then for all traffic to/from each internal IP it will also implement per-flow-fairness, which typically works pretty well. The one common use-case where per-flow fairness is sub-optimal is really torrenting, since it naturally uses many flows and is typically considered to be low priority, but strict per-flow fairness gets the low-priority bandwidth scavenger aspect wrong...

As a final comment, you could also just try to to use one of cake's dscp modes and "simply" dscp mark torrent packets as low priority, but that is harder than it seems and typically harder than simply run the torrents on a different machine (given e.G. the low price of a raspberry pi that can easily serve as torrent endpoint).

I am trying to torrent and use the web browser on the same client, indeed. I've already set up per-internal-IP fairness which works in most cases, except this one.

How might I mark torrent packets as low priority?

So there is no way with cake to ensure that the browsing is always given priority, or more bandwidth than other users of the connection, even if it's just a megabit or two dedicated to browsing?

If torrenting is already given low priority, I am bemused why browsing then slows down?

Is it possible to see how different applications and IPs are sorted into the queue, in real time? How does cake determine which applications are low and high priority?

Should I also be using the additional diffserv4? I am using diffserv3 at present which I believe is the default, would this help?

My setup is as follows, does this look okay?

As I tried to explain, then all the torrent flows compete directly with your browsing flows, and fair queuing will on average give more bandwidth to the total of all torrent flows. That is the expected behavior.
There are possible solutions to this issue, from using bandwidth throttling in the torrent client over trying to use network namespaces to let the torrents run with a different IP address to using DSCP marking for the torrent traffic. So here is a question, what operating system are you using, and are your torrents mainly downloading or uploading?

For egress that is relatively easy, but for ingress traffic that is considerably harder, hard enough that solutions to that issue spawned long threas in this forum, like https://forum.openwrt.org/t/ultimate-sqm-settings-layer-cake-dscp-marks-new-script/53209/147.

Yes and no, cake can not really understand your intent or priorities, the best it can do is to honor DSCP markings in the packets to sort them into a handfull of different priority tiers, but yu are left with the challenge of applying these marks before cake actually handles the packets.

Becase all that cake sees are differet flows, and it tries to treat all of the equally, torrents win over brosing not because torrent flows get more bandwidth that browsing flows, but simply because you most likely will have a shipload of torrents compete against a few handful of browsing related flows.
Thinking this over, you could also try to limit the number of concurrent torrent flows to something sane, then cake should do the right thing out of the box.

It just maps different DSCPs into its different iers and services these tiers with different priorities. Your task is to make sure packets carry the correct dscp marks to be sorted into the desired priority tier.

Unlikely, in your case I would recommend to simply mark the torrent packets such that they end up in the low priority tier, and keep browsing in the normal priority tier. The difference between diffserv3 and diffserv4 is that the latter has an additional "even higher priority" tier...

But to use these, you would need to switch to layer_cake.qos, as piece_of_cake.qos should default to no diffserve tiering.

I dont want to steal the OPs thread but, i have been wondering just about this.
If you use diffserv4 for example, traffic goes into different tins by default. Why and how?

Simply by cake's internel DSCP to priority tier mapping from sch_cake.c:

static const u8 diffserv4[] = {
        0, 2, 0, 0, 2, 0, 0, 0,
        1, 0, 0, 0, 0, 0, 0, 0,
        2, 0, 2, 0, 2, 0, 2, 0,
        2, 0, 2, 0, 2, 0, 2, 0,
        3, 0, 2, 0, 2, 0, 2, 0,
        3, 0, 0, 0, 3, 0, 3, 0,
        3, 0, 0, 0, 0, 0, 0, 0,
        3, 0, 0, 0, 0, 0, 0, 0,
static const u8 diffserv3[] = {
        0, 0, 0, 0, 2, 0, 0, 0,
        1, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 2, 0, 2, 0,
        2, 0, 0, 0, 0, 0, 0, 0,
        2, 0, 0, 0, 0, 0, 0, 0,

/*      List of known Diffserv codepoints:
 *      Least Effort (CS1)
 *      Best Effort (CS0)
 *      Max Reliability & LLT "Lo" (TOS1)
 *      Max Throughput (TOS2)
 *      Min Delay (TOS4)
 *      LLT "La" (TOS5)
 *      Assured Forwarding 1 (AF1x) - x3
 *      Assured Forwarding 2 (AF2x) - x3
 *      Assured Forwarding 3 (AF3x) - x3
 *      Assured Forwarding 4 (AF4x) - x3
 *      Precedence Class 2 (CS2)
 *      Precedence Class 3 (CS3)
 *      Precedence Class 4 (CS4)
 *      Precedence Class 5 (CS5)
 *      Precedence Class 6 (CS6)
 *      Precedence Class 7 (CS7)
 *      Voice Admit (VA)
 *      Expedited Forwarding (EF)
 *      Total 25 codepoints.
/*      List of traffic classes in RFC 4594:
 *              (roughly descending order of contended priority)
 *              (roughly ascending order of uncontended throughput)
 *      Network Control (CS6,CS7)      - routing traffic
 *      Telephony (EF,VA)         - aka. VoIP streams
 *      Signalling (CS5)               - VoIP setup
 *      Multimedia Conferencing (AF4x) - aka. video calls
 *      Realtime Interactive (CS4)     - eg. games
 *      Multimedia Streaming (AF3x)    - eg. YouTube, NetFlix, Twitch
 *      Broadcast Video (CS3)
 *      Low Latency Data (AF2x,TOS4)      - eg. database
 *      Ops, Admin, Management (CS2,TOS1) - eg. ssh
 *      Standard Service (CS0 & unrecognised codepoints)
 *      High Throughput Data (AF1x,TOS2)  - eg. web traffic
 *      Low Priority Data (CS1)           - eg. BitTorrent

 *      Total 12 traffic classes.


tatic int cake_config_diffserv4(struct Qdisc *sch)
/*  Further pruned list of traffic classes for four-class system:
 *          Latency Sensitive  (CS7, CS6, EF, VA, CS5, CS4)
 *          Streaming Media    (AF4x, AF3x, CS3, AF2x, TOS4, CS2, TOS1)
 *          Best Effort        (CS0, AF1x, TOS2, and those not specified)
 *          Background Traffic (CS1)
 *              Total 4 traffic classes.


static int cake_config_diffserv3(struct Qdisc sch)
Simplified Diffserv structure with 3 tins.

  •          Low Priority            (CS1)
  •          Best Effort
  •          Latency Sensitive       (TOS4, VA, EF, CS6, CS7)


Some applications set DSCPs by default and hence map into cake's different priority tiers. For ingress/download things get trickier as many ISPs actually change DSCP on route (as they are entitled to, DSCPs are unfortunately not considered to be end-to-end stable), so the mix of ingress DCSPs most likely will not tell you much about the sender's intent.... Also as I tried to indicate, changng the DSCPs of incoming packets is hard, as cake sees the packets before iptables does and hence any marking requires tc and lots od swearing.
Or ask @ldir nicely as he has an immensely clever method to sort of copy the DSCPs from a flows outgoing packts to its incoming packets, before cake processes them, which reduces the problem to how to set egress/upload DSCPs, and there iptables can be your friend.

1 Like

Thank you, i knew about the different classes but not how it assigns tins without any manual intervention, i guess its tagged on the way, and im not using "wash" on ingress


So I setup diffserv3.

I have started a torrent client on another computer and I'm seeing similar issues with slow browsing.

tc -s -d qdisc show
qdisc noqueue 0: dev lo root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn 
 Sent 20515729705 bytes 112861783 pkt (dropped 0, overlimits 0 requeues 2) 
 backlog 0b 0p requeues 2
  maxpacket 1514 drop_overlimit 0 new_flow_count 17 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc fq_codel 0: dev eth1 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn 
 Sent 204332376253 bytes 175796827 pkt (dropped 0, overlimits 0 requeues 17) 
 backlog 0b 0p requeues 17
  maxpacket 1506 drop_overlimit 0 new_flow_count 33 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc noqueue 0: dev br-lan root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev eth1.1 root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0
qdisc cake 805e: dev eth0.2 root refcnt 2 bandwidth 7700Kbit diffserv3 dual-srchost nat nowash no-ack-filter split-gso rtt 100.0ms noatm overhead 34 
 Sent 24572699 bytes 266195 pkt (dropped 18, overlimits 143253 requeues 0) 
 backlog 0b 0p requeues 0
 memory used: 107136b of 4Mb
 capacity estimate: 7700Kbit
 min/max network layer size:           16 /    1500
 min/max overhead-adjusted size:       50 /    1534
 average network hdr offset:           14

                   Bulk  Best Effort        Voice
  thresh      481248bit     7700Kbit     1925Kbit
  target         37.9ms        5.0ms        9.5ms
  interval      132.9ms      100.0ms      104.5ms
  pk_delay          0us        465us          1us
  av_delay          0us         44us          0us
  sp_delay          0us          9us          0us
  backlog            0b           0b           0b
  pkts                0       266224            1
  bytes               0     24576667           42
  way_inds            0        20729            0
  way_miss            0         1554            1
  way_cols            0            0            0
  drops               0           18            0
  marks               0            0            0
  ack_drop            0            0            0
  sp_flows            0           79            1
  bk_flows            0            2            0
  un_flows            0            0            0
  max_len             0         1514           42
  quantum           300          300          300

qdisc ingress ffff: dev eth0.2 parent ffff:fff1 ---------------- 
 Sent 537126791 bytes 419024 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0
qdisc fq_codel 0: dev pppoe-wan root refcnt 2 limit 10240p flows 1024 quantum 1518 target 5.0ms interval 100.0ms memory_limit 4Mb ecn 
 Sent 3442539588 bytes 30678502 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0
  maxpacket 0 drop_overlimit 0 new_flow_count 0 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc cake 805f: dev ifb4eth0.2 root refcnt 2 bandwidth 53Mbit diffserv3 dual-dsthost nat wash ingress no-ack-filter split-gso rtt 100.0ms noatm overhead 34 
 Sent 509201817 bytes 394234 pkt (dropped 24583, overlimits 724076 requeues 0) 
 backlog 257962b 207p requeues 0
 memory used: 563456b of 4Mb
 capacity estimate: 53Mbit
 min/max network layer size:           46 /    1500
 min/max overhead-adjusted size:       80 /    1534
 average network hdr offset:           14

                   Bulk  Best Effort        Voice
  thresh       3312Kbit       53Mbit    13250Kbit
  target          5.5ms        5.0ms        5.0ms
  interval      100.5ms      100.0ms      100.0ms
  pk_delay          0us       87.8ms         27us
  av_delay          0us       21.4ms          0us
  sp_delay          0us        3.9ms          0us
  backlog            0b      257962b           0b
  pkts                0       419023            1
  bytes               0    542993067           60
  way_inds            0        15467            0
  way_miss            0         2006            1
  way_cols            0            0            0
  drops               0        24583            0
  marks               0            0            0
  ack_drop            0            0            0
  sp_flows            0           44            1
  bk_flows            0           54            0
  un_flows            0            0            0
  max_len             0         1514           60
  quantum           300         1514          404

It seems to me that the issue is that all traffic is ending up in the best effort queue, is this supposed to happen?

Again, if you don't add the DSCP tags to your packets, then cake has no knowledge on the priority of said packets and will thus throw them into the best effort queue. So yes, this is supposed to happen with your current settings.

As already mentioned, tagging outgoing packets is easy. This can be done with the torrent client itself if it supports it, or with some iptables rules on the router. This should allow you to shape your uploads very easily. However, incoming packets are a pain. You cannot force the torrent client at the other side of the connection to tag them properly, and even if you do, ISPs can change these tags while in transit.

Normally it isn't possible to use iptables to tag incoming packets for SQM, since the packets will hit SQM before they hit iptables. However, there are some complex workarounds for this, but it's quite difficult to set up (properly).

1 Like

Okay but then why have the queues at all if most people can't use them without a lot of extra setup?

I would have thought it wouldn't be difficult to distinguish between browsing and downloading and stick them in different queues, I've obviously not understood the point in having the diffserv configuration.

sqm / qos has always been notoriously complex from a configuration standpoint...

having openwrt handle the complexities within cake and leave you to simply dcsp-tag is about as simple as it gets...

as with all things openwrt... to maintain flexibility across all environments... 'tag-this' needs to be done at a command line / lower level than common setup options... this is due to the various ways sqm can be instantiated, the various underlying network topology / interface setup and tc/queue directionality / dcsp honouring behaviour...

that said, a few iptables mark rules and some possible ip/vlan/route specifities on a client are not exactly complex...

something else to keep in mind is;

  • many mid/high level switches can also set your dcsp tags for you before reaching openwrt...
  • many clients allow additional logical ips/ranges or vlan tagging of certain traffic, so you dont necessarily need another client
  • as mentioned above... many host-os's/applications allow you to assign the correct dcsp tags on your client

in summary, the variety at the network level coupled with the constraints at the sqm/router/protocol level make automating / 'simplifying' such things much further than they currently are, mean one would have to dictate to the user how their network should be setup... and this is not the openwrt philisophy...

1 Like

Wash I believe will first use the DSCP to select the appropriate priority tier and then remap that dscp to zero. The idea is to be able to not leak DSCPs, if you do not want to interpret DSCPs at all, just use the besteffort keyword...

1 Like

DSCP 0 ist the default marling and that will map into cake's Best Effort priority tin, so unless you take special care to mark relevant packets differently, all/most packets in Best Effort is the expected outcome.

Well, the egress cake stats look fine (peak delay 465µs), but ion ingress things look less rosy (peak delay 87.8ms, which probably is noticeable (no not all packets will be delayed by that amount but that indicates delay varuations up to 84ms on top of the base RTT and that can be noticeable.).

I wonder why the per-internal-IP address isolation did not work though, as if the torrents are on another computer with a different IP address they should interfere much less.
But what is your true internet access link speed?

To make such things possible. If we knew a way to make them easy as well, we would have, but ATM possible is all we can offer.

Well, cake uses two ideas that typically help a lot, it prioritizes sparse flows (flows that do not actually accumulate packets in the queue) which is typical for interactive flows like gamin/web browsing. And it allows to separate the traffic of different machines so that one can isolate offending traffic easier. BUT for ingress traffic, and I assume you use torrents to download stuff, cake sits on the wrong end of the bottleneck, if the flows are not responsive enough packets will accumulate in the typically over-sized and under-managed upstream buffers and you will encounter latency under load.
You could try to further reduce the shaping rate for ingress traffic, which sometimes helps to reduce the issue a bit, or simply try to reign in the offending application, by either setting bandwidth limits and/or if pssible restrict the number of concurrent flows/torrents.
I do not use torrents myself and hence have little first hand experience in how to properly configure a torrent client.

But I know one issue is that bittorrent tries to be a good internet citizen and tries to stay out of the way of more important traffic, but does so by measuring induced delay, and I believe it will throttle when seeing >= 100 ms latency increase, but cake target's for 5ms of acceptable standing queue, so bittorrents µTP protocol might constantly do the wrong thing for the right reasons...

@moeller0 I'm on VDSL2 synced at 64199Kbps down and 7999Kbps up. I'm using PPPoE for BT in the UK.

53000 is what I have set in the down for cake and 7700 up, so I would have thought I'm way below running into any kind of bloat issues, I could probably set it a lot higher.

I posted my config above, please do let me know if it looks okay to you?

Layer cake + DSCP marking works brilliantly once it's set up.

It's certainly not trivial though. I have three SQM instances running and 600 lines of firewall script to classify (and reclassify) packets using DSCP tags based on many different criteria using the flexibility of iptables, ipsets, and dnsmasq. Once a packet has been (re)classified, the DSCP tag is associated with its connection using connmark, and the tags are applied to all packets on that connection before they are shaped by SQM. I can do this for incoming traffic because I've split my SQM between the WAN interface and the LAN interfaces like this:

If you can't split the upload/download SQM in this way you can't prioritize incoming traffic, because the packets hit SQM before iptables, so you don't have an opportunity to apply the DSCP tags. I think there's another approach using virtual interfaces (veth's), but I don't know much about that.

To be honest I doubt I would have made the effort if I hadn't been stuck at home for months under COVID-19 lockdown :rofl:


As to my original question, is tagging web browsing traffic not possible? Surely tagging anything using ports 80 and 443 should be quite trivial.