QoSmate: (Yet Another) Quality of Service Tool for OpenWrt

It's very worth it for some people. Some people get 1000ms increase in latency under download etc... Other people their ISP already handles latency well, so maybe doesn't matter.

So it is useful…maybe @Hudra have it in mind for this.

Is it possible to select prio bin without setting/changing original dscp?

for HFSC you can directly set the prio bin in nftables and it will obey that setting if you do it in the right place... (you gotta do it after the existing code that maps from dscp to prio) but for cake it has a fixed mapping from dscp to bin.

1 Like

What sorta connection you got? Fiber FTTH. Bet you already read docs and still confused then try this..

Install ethtool & tcpdump-mini packages.

ip -details link show pppoe-wan
ethtool eth1
ethtool -k eth1
tcpdump -i eth1 -e -n
tcpdump -i pppoe-wan -e -c 10

edit commands according to your setup.

Copy paste the result in text file and upload it on ChatGPT and ask questions. Result may not be 100% accurate but it'll give you head start.

New Feature Preview: Autorate (Dynamic Bandwidth Adjustment)

Hey everyone,

I wanted to share a new feature I've been working on that some of you have requested before.

I recently moved to a new house and unfortunately only have cable internet here... a downgrade from the FTTH I had before. Over the past weeks, I've experienced intermittent connection issues. A technician confirmed that there's a damaged cable somewhere in the neighborhood that probably becomes unstable during extreme cold or wet weather conditions. When this happens, my bandwidth drops significantly and I get bufferbloat, even with QoSmate running.

My options were either to set my bandwidth very conservatively low (which I didn't want), or to implement something that adapts dynamically. So I decided to build an Autorate feature for QoSmate.

I took inspiration from existing projects like cake-autorate and sqm-autorate.... great projects that I want to acknowledge here. However, since those are designed specifically for CAKE, and QoSmate supports multiple root qdiscs (HFSC, HTB, Hybrid, CAKE), I needed/wanted to build something that works with all of them.

Due to time constraints, I decided to implement a simpler version that covers the basic functionality I needed. It's probably not as feature-complete as the dedicated autorate projects, but it gets the job done for my use case.

How it works:

  • Measures latency by pinging configurable reflector servers
  • Learns a baseline latency (your connection's "unloaded" state)
  • Decreases bandwidth when latency rises above a threshold (indicating congestion)
  • Increases bandwidth cautiously when latency is stable and link is under load
  • Works with all supported qdisc types (CAKE, HFSC, HTB, Hybrid)

Usage:

For most users, it should be as simple as:

  1. Enable "Dynamic Bandwidth (Autorate)" in Settings
  2. That's it... the defaults should work for most scenarios

Detailed configuration options are available under Advanced → Autorate Settings if you want to fine-tune the behavior.

Full documentation is in the README: Autorate Documentation

How to try it:

The feature is currently in the autorate branch. To test it:

/etc/init.d/qosmate update -i -v branch=autorate

Clear your browser cache (and restart browser) to ensure the LuCI loads the new settings.

After updating, enable it via LuCI or:

uci set qosmate.autorate.enabled='1'
uci commit qosmate
service qosmate restart

I've done some basic testing and it works well for my setup. However, I haven't had time for:

  • Long-term stability tests
  • Performance/resource usage analysis
  • Graphical visualization of latency and bandwidth adjustments over time

A nice future addition could be a LuCI statistics page showing how the rates adapt in real-time, but that's beyond what I could implement with my current time constraints. If anyone is interested in contributing something like this, or wants to run more thorough tests on their own setup, that would be really helpful!

I plan to merge this into the main branch once I've received some feedback and am confident everything works well. If you try it out, I'd love to hear your experiences... whether it's suggestions, feature requests, or criticism. I'm open to all of it!

My own connection has stabilized for now, and once the ground thaws in a few weeks, they'll hopefully dig up and replace the faulty cable. But I figured this feature could be useful for others with variable connections.

Cheers!

Edit: I’ve just added a simple autorate tab to the statistics ui to better visualize autorate behavior.

8 Likes

Amazing. Question for you, how do you adjust the rate with HFSC and other non-cake qdiscs. cake has the option to adjust its parameters using tc, but I thought HFSC you had to actually drop the old qdisc and insert a new one. Does that cause a brief spike of packet loss? or did you come up with another method that doesn't do packet loss?

1 Like

Turns out you can actually use tc class change to modify hfsc and htb class parameters in-place, so there's no need to tear down and rebuild the qdisc and there seems to be no packet loss at all.
For HFSC it looks something like this:

tc class change dev $DEV parent 1: classid 1:1 hfsc ls m2 ${RATE}kbit ul m2 ${RATE}kbit
tc class change dev $DEV parent 1:1 classid 1:11 hfsc rt m1 ${BURST}kbit d ${DUR}ms m2 ${GAMERATE}kbit

I also pipe all class changes through tc -batch (although probably not necessary) so they get applied atomically. Same approach works for htb and hybrid. For cake I just use the standard tc qdisc change.

5 Likes

SWEET, thanks for looking into that. QoSmate has SO many features now. very impressed.

3 Likes

Thanks! I’m honestly sometimes surprised myself how much it has grown.

Hi there, I am new and trying to get this set up on Flint 3. Am I right in assuming that since the Nft service is X, QoSmate won't work properly? Is there a way to apply the HFSC settings to all connections (not just gaming ones)?

Yes, exactly... you’ve identified that correctly. Let me take a wild guess: you’re using the original GL.iNet firmware (or an OpenWrt fork), which likely still relies on iptables rather than its successor nftables (which Qosmate uses).
To figure that out you could show me the output of:

service qosmate status

How did you come to the conclusion that HFSC is only applied to gaming connections? To better understand how HFSC and its classes work, I’d refer you to the README.
If you have any further questions after that, I’d be happy to discuss them with you.

Thank you I will look at the readme. Yes I believe you are correct - output is below:

==== qosmate Status ====
qosmate autostart is enabled.
qosmate global:enabled is true.
Traffic shaping (CAKE) is active on the egress interface (eth0).
Traffic shaping (CAKE) is active on the ingress interface (ifb-eth0).

==== Current Settings ====
Upload rate: 450000 kbps
Download rate: 450000 kbps
Game traffic upload: 67900 kbps
Game traffic download: 67900 kbps
Queue discipline: CAKE (Root qdisc)

==== Version Information ====
Backend versions:
  Update channel: release
  Current version: 1.8.0
  Latest version: 1.8.0
Frontend versions:
  Update channel: release
  Current version: 1.8.0
  Latest version: 1.8.0

QoSmate components 'BACKEND FRONTEND' are up to date.

==== System Information ====
{
        "kernel": "5.4.213",
        "hostname": "GL-BE9300",
        "system": "ARMv8 Processor rev 4",
        "model": "GL.iNet BE9300, Inc. IPQ5332/AP-MI01.6",
        "board_name": "qcom,ipq5332-ap-mi01.6",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "23.05-SNAPSHOT",
                "revision": "",
                "target": "ipq53xx/generic",
                "description": "OpenWrt 23.05-SNAPSHOT "
        }
}

==== Health Check ====
status=service:enabled;nft:failed;tc:ok;config:ok;packages:ok;BACKEND_integrity:                                                                                                                                                             ok;FRONTEND_integrity:ok;;errors=1

==== Flow Offloading Check ====
Flow offloading is disabled (compatible with qosmate).

==== WAN Interface Information ====
        "l3_device": "eth0",
        "device": "eth0",

==== QoSmate Configuration ====

config global 'global'
        option enabled '1'

config settings 'settings'
        option WAN 'eth0'
        option DOWNRATE '450000'
        option UPRATE '450000'
        option ROOT_QDISC 'cake'

config advanced 'advanced'
        option PRESERVE_CONFIG_FILES '1'
        option WASHDSCPUP '1'
        option WASHDSCPDOWN '1'
        option BWMAXRATIO '20'
        option UDP_RATE_LIMIT_ENABLED '0'
        option TCP_UPGRADE_ENABLED '1'
        option TCP_DOWNPRIO_INITIAL_ENABLED '1'
        option TCP_DOWNPRIO_SUSTAINED_ENABLED '1'
        option MSS '536'
        option NFT_HOOK 'forward'
        option NFT_PRIORITY '0'
        option MAX_CONNECTIONS '0'
        option COMMON_LINK_PRESETS 'ethernet'

config hfsc 'hfsc'
        option gameqdisc 'netem'
        option nongameqdisc 'cake'
        option nongameqdiscoptions 'besteffort ack-filter'
        option MAXDEL '24'
        option PFIFOMIN '5'
        option PACKETSIZE '450'
        option netemdelayms '30'
        option netemjitterms '7'
        option netemdist 'normal'
        option pktlossp 'none'
        option netem_direction 'both'

config cake 'cake'
        option PRIORITY_QUEUE_INGRESS 'diffserv4'
        option PRIORITY_QUEUE_EGRESS 'diffserv4'
        option HOST_ISOLATION '1'
        option NAT_INGRESS '1'
        option NAT_EGRESS '1'
        option ACK_FILTER_EGRESS 'auto'
        option AUTORATE_INGRESS '0'

config custom_rules 'custom_rules'

==== Package Status ====
All required packages are installed.

==== Detailed Technical Information ====
Traffic Control (tc) Queues:
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 cake 1: dev eth0 root refcnt 5 bandwidth 450Mbit diffserv4 dual-srchost na                                                                                                                                                             t wash no-ack-filter split-gso rtt 100ms noatm overhead 40 mpu 84
 Sent 536883314 bytes 2059745 pkt (dropped 0, overlimits 160593 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 107904b of 15140Kb
 capacity estimate: 450Mbit
 min/max network layer size:           28 /    1500
 min/max overhead-adjusted size:       84 /    1540
 average network hdr offset:           14

                   Bulk  Best Effort        Video        Voice
  thresh      28125Kbit      450Mbit      225Mbit   112500Kbit
  target            5ms          5ms          5ms          5ms
  interval        100ms        100ms        100ms        100ms
  pk_delay          0us         17us         14us         13us
  av_delay          0us          6us          2us          7us
  sp_delay          0us          2us          2us          4us
  backlog            0b           0b           0b           0b
  pkts                0      2056066          143         3536
  bytes               0    536223562        67342       592410
  way_inds            0       214126            0            0
  way_miss            0        39265            1            9
  way_cols            0            0            0            0
  drops               0            0            0            0
  marks               0            0            0            0
  ack_drop            0            0            0            0
  sp_flows            0            6            0            1
  bk_flows            0            1            0            0
  un_flows            0            0            0            0
  max_len             0        32762         1426          487
  quantum           858         1514         1514         1514

qdisc ingress ffff: dev eth0 parent ffff:fff1 ----------------
 Sent 5640232538 bytes 5399520 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev eth1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wifi0 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wifi1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wifi2 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 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 noqueue 0: dev wlan0 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wlan1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wlan2 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc cake 8031: dev ifb-eth0 root refcnt 2 bandwidth 450Mbit diffserv4 dual-dst                                                                                                                                                             host nat wash ingress no-ack-filter split-gso rtt 100ms noatm overhead 40 mpu 84                                                                                                                                                             
 Sent 5725285985 bytes 5399434 pkt (dropped 71, overlimits 2851251 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 2584832b of 15140Kb
 capacity estimate: 450Mbit
 min/max network layer size:           46 /    1500
 min/max overhead-adjusted size:       86 /    1540
 average network hdr offset:           14

                   Bulk  Best Effort        Video        Voice
  thresh      28125Kbit      450Mbit      225Mbit   112500Kbit
  target            5ms          5ms          5ms          5ms
  interval        100ms        100ms        100ms        100ms
  pk_delay          0us        214us          0us         86us
  av_delay          0us         35us          0us          6us
  sp_delay          0us          5us          0us          3us
  backlog            0b           0b           0b           0b
  pkts                0      5398167            0         1338
  bytes               0   5725302166            0        80280
  way_inds            0       582186            0            0
  way_miss            0        45088            0            1
  way_cols            0            0            0            0
  drops               0           71            0            0
  marks               0            2            0            0
  ack_drop            0            0            0            0
  sp_flows            0            5            0            1
  bk_flows            0            1            0            0
  un_flows            0            0            0            0
  max_len             0        68130            0           60
  quantum           858         1514         1514         1514


==== Nftables Ruleset (dscptag) ====
# Warning: table ip filter is managed by iptables-nft, do not touch!
# Warning: table ip nat is managed by iptables-nft, do not touch!

==== Custom Rules Table Status ====
Custom rules table (qosmate_custom) is not active or doesn't exist.

==== Inline Rules Status ====
No inline rules configured.

No chance, this uses nftables.
Check extra time

nft --version
ip6tables --version

upgrading to current OpenWrt release will likely work though, I don't know about your hardware if there's something that would prevent it, but if you find an official firmware build for it, then it will likely work. However you'd probably want to not keep settings, and then re-set-up your whole router again. Take a backup of the GL-inet settings so you can refer to them though.

I've got a few gl-inet devices in service and I always just install OpenWrt first thing.

Here is the output:

root@GL-BE9300:~# nft --version
nftables v1.0.8 (Old Doc Yak #2)
root@GL-BE9300:~# ip6tables --version
ip6tables v1.8.8 (nf_tables)

Is the recently added cake_mq to 25.12 going to be supported soon or does it already work?

2 Likes

Strange.

Is eth0 your WAN interface? Does it even exist?

Please run

nft -c -f /usr/share/nftables.d/ruleset-post/dscptag.nft

only defect in histogram is exces voice traffic. Probably some bulk download slipped in your rules

This will not improve your gaming, actually single threaded solutions are better for online gaming.

2 Likes

And you say that based on what?

Not trying to be an ass, just curious.