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

From my experience, if you already have stable low ping on wired connection & no packet loss, focus on reducing system latency to enhance your gaming. This includes updating drivers, overclocking hardware, getting a faster GPU, calculating total latency from the game server to display each frame on your monitor, enabling NVIDIA Reflex, using 1ms blur reduction in competitive games (note: this might add a slight 8ms lag, but will improves enemy visibility). Enable both VSync and G-Sync in your GPU control panel (disable in-game VSync). Tools can help identify and address DPC latency spikes. Lowering system latency significantly improved my gaming experience.

I had tried this idea with counter strike 2 game for days even increased/decreased ping using netem but eventually I figured that low ping with max bandwidth is better. What actually made a huge difference is when I added certain gaming parameters when launching CS2 from Steam I started getting easier kills and literally started ditching bullets lol

2 Likes

I encountered a problem and I would like your help.
My ISP provides me with a dual-stack connection, meaning both IPv4 and IPv6, and I’m trying to use bandwidth limiting rules via nftables with Qosmate.

Example of the rules:

chain forward {
    type filter hook forward priority 0; policy accept;
    
    # Limit download with burst allowance
    ip daddr 192.168.1.126 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip daddr 192.168.1.138 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip daddr 192.168.1.111 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip daddr 192.168.1.200 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip daddr 192.168.1.101 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    
    # Limit upload with burst allowance
    ip saddr 192.168.1.126 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip saddr 192.168.1.138 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip saddr 192.168.1.111 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip saddr 192.168.1.200 limit rate over 500 kbytes/second burst 500 kbytes counter drop
    ip saddr 192.168.1.191 limit rate over 500 kbytes/second burst 500 kbytes counter drop
}

However, I noticed that these rules only work when IPv4 is active and IPv6 is disabled. When I perform a speed test on the Speedtest website, the speed doesn’t go beyond 4 Mbps.
But when both IPv6 and IPv4 are active, the speed test shows the total bandwidth I configured in Qosmate, which is 110/50 Mbps. This suggests that IPv6 is bypassing the rules in the table.

No reason, why these would not work. However, these might not actually achieve what you want to achieve, in that they only restrict traffic to/from 192.168.1.100 and not all traffic to/from the host computer that also uses 192.168.1.100 on one of its interfaces. So this explicitly does not handle IPv6...
If you need a single catch all/most rule, maybe use ethernet MAC addresses.

2 Likes

@moeller 0 I had to edit and write my question for a good understanding.

Thank you for the explanation, moeller0! It’s now clear that my rules are only limiting traffic for specific IPv4 addresses and not affecting IPv6 traffic. I also understand that the rules are limiting traffic only for the specific IPs I defined, and not for all traffic from the device.

I will try using MAC addresses, as you suggested, to ensure that the bandwidth limitation is applied to all traffic, both IPv4 and IPv6, regardless of the IP used.

Thanks again for the help!

1 Like

Make sure the devices you want to control do not randomise their MAC addresses.

1 Like

and I made this rule and it worked, but only for uploading. I'm not an expert in tables. Could you help me with my mistake?

chain forward {
type filter hook forward priority 0; policy accept;

# Limit download with burst allowance
ether daddr E8:9C:XX:XX:XX:XX limit rate over 500 kbytes/second burst 500 kbytes counter drop

# Limit upload based on MAC
ether saddr E8:9C:XX:XX:XX:XX limit rate over 625 kbytes/second burst 625 kbytes counter drop
}

I never used that functionality, so all I could do is google and present my google results, I am sure it will be more efficient to cut the middleman (me) out :wink:

1 Like

SQM and Hardware Offloading aim at the same goal (high throughput with low latency), but reach it with opposite strategies:

SQM uses powerful hardware to optimally utilize a really slow connection.
Hardware Offloading uses slow hardware to optimally utilize a very fast connection.

Enabling Hardware Offloading on powerful hardware with really slow connection is going to make your Internet connection sluggish with very high latency.
(For a really slow connection Hardware Offloading has no use.)

Putting SQM on slow hardware with a very fast connection is going to make your Internet connection sluggish with very low throughput.
(For a really fast connection SQM has no use and just caps throughput.)

So what you need is depending on your hardware power and your WAN connection speed.

Respectfully, queue management makes sense when ever a meaningful queue develops. That happens if the aggregate ingress rate for an egress port exceeds that port's egress rate for long enough.
Note how this description is independent of absolute egress rate? Bufferbloat can happen both at low and high rates and its remedies are the same (albeit often harder to achieve at high rates).

Hardware offload is IMHO an orthogonal issue, as one can also use hardware offloading for the costly component in SQM, the traffic shaper... (but that capability is not widely available, and many offloads are tailored to allow higher throughput with less CPU cost).

2 Likes

How do I downgrade to previous version? latest version doesn't track CS5 packets at all

Which version do you mean, and which issue are you referring to exactly? Please elaborate.

I am looking for version prior to the arrival of ā€œstatisticā€ tab

The problem i have is that actual Cod game packets have been prioritized as CS0 while CS5 was classified to destination port of 3074 instead. It is super strange

My network environment:

Vlan10
Ipv 4 and 6
Router wrt32x
Version 24.10.00

The introduction of the statistics feature did not change a single line in the qosmate backend (main script, init script, etc.), so I can't imagine that it would have caused any changes on your end.

Please show me the following output (all of them) and make sure you use the "Preformatted text </> " button for logs, scripts, configs and general console output.
grafik:

ubus call system board
/etc/init.d/qosmate check_version
/etc/init.d/qosmate status
cat /etc/config/qosmate
ifstatus wan | grep -e device
cat /etc/init.d/qosmate | grep -A 3 "QOSMATE_BASE_URL="

Issue Description

  1. What's the problem? (Be specific)
  2. When did it start? (After an update, configuration change, etc.)
  3. Can you reliably reproduce the issue?
  4. What have you tried to resolve it?
root@OpenWrt:~# ubus call system board
{
        "kernel": "6.6.73",
        "hostname": "OpenWrt",
        "system": "ARMv7 Processor rev 1 (v7l)",
        "model": "Linksys WRT32X",
        "board_name": "linksys,wrt32x",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "24.10.0",
                "revision": "r28427-6df0e3d02a",
                "target": "mvebu/cortexa9",
                "description": "OpenWrt 24.10.0 r28427-6df0e3d02a",
                "builddate": "1738624177"
        }
}
root@OpenWrt:~# /etc/init.d/qosmate check_version
Backend versions:
  Current version: 0.5.62
  Latest version: 0.5.62
Frontend versions:
  Current version: 1.0.25
  Latest version: 1.0.25

QoSmate is up to date.
root@OpenWrt:~# /etc/init.d/qosmate status
==== qosmate Status ====
qosmate autostart is enabled.
qosmate service is enabled.
Traffic shaping is active on the egress interface (eth0).
Traffic shaping is active on the ingress interface (ifb-eth0).
==== Overall Status ====
qosmate is currently active and managing traffic shaping.
==== Current Settings ====
Upload rate: 100000 kbps
Download rate: 100000 kbps
Game traffic upload: 15400 kbps
Game traffic download: 15400 kbps
Queue discipline: CAKE (Root qdisc)
==== 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 8007: dev eth0 root refcnt 9 bandwidth 100Mbit diffserv4 dual-srchost                                                                                                                                                              nat wash no-ack-filter split-gso rtt 100ms noatm overhead 38 mpu 84
 Sent 4504960 bytes 6936 pkt (dropped 0, overlimits 8245 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 33420b of 5000000b
 capacity estimate: 100Mbit
 min/max network layer size:           16 /    1500
 min/max overhead-adjusted size:       84 /    1538
 average network hdr offset:           22

                   Bulk  Best Effort        Video        Voice
  thresh       6250Kbit      100Mbit       50Mbit       25Mbit
  target            5ms          5ms          5ms          5ms
  interval        100ms        100ms        100ms        100ms
  pk_delay          0us         21us         89us          0us
  av_delay          0us          7us         17us          0us
  sp_delay          0us          1us          2us          0us
  backlog            0b           0b           0b           0b
  pkts                0         5660         1276            0
  bytes               0      3318582      1186378            0
  way_inds            0           45            9            0
  way_miss            0          142           58            0
  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           19            0            0
  bk_flows            0            1            1            0
  un_flows            0            0            0            0
  max_len             0        18264         1514            0
  quantum           300         1514         1514          762

qdisc ingress ffff: dev eth0 parent ffff:fff1 ----------------
 Sent 4195557 bytes 6923 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev lan4 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev lan3 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev lan2 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev lan1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wan root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev AISVLAN root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev AISVLAN.10 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 fq_codel 0: dev pppoe-wan root refcnt 2 limit 10240p flows 1024 quantum 15                                                                                                                                                             14 target 5ms interval 100ms memory_limit 4Mb ecn drop_batch 64
 Sent 785960 bytes 7078 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 8008: dev ifb-eth0 root refcnt 2 bandwidth 100Mbit diffserv4 dual-dst                                                                                                                                                             host nat wash ingress no-ack-filter split-gso rtt 100ms noatm overhead 38 mpu 84                                                                                                                                                             
 Sent 4287949 bytes 6919 pkt (dropped 3, overlimits 9062 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 856Kb of 5000000b
 capacity estimate: 100Mbit
 min/max network layer size:           50 /    1508
 min/max overhead-adjusted size:       88 /    1546
 average network hdr offset:           14

                   Bulk  Best Effort        Video        Voice
  thresh       6250Kbit      100Mbit       50Mbit       25Mbit
  target            5ms          5ms          5ms          5ms
  interval        100ms        100ms        100ms        100ms
  pk_delay          0us       1.33ms          0us          0us
  av_delay          0us       1.11ms          0us          0us
  sp_delay          0us          3us          0us          0us
  backlog            0b           0b           0b           0b
  pkts                0         6922            0            0
  bytes               0      4292411            0            0
  way_inds            0           53            0            0
  way_miss            0          207            0            0
  way_cols            0            0            0            0
  drops               0            3            0            0
  marks               0            0            0            0
  ack_drop            0            0            0            0
  sp_flows            0           13            0            0
  bk_flows            0            1            0            0
  un_flows            0            0            0            0
  max_len             0         1522            0            0
  quantum           300         1514         1514          762


==== Nftables Ruleset (dscptag) ====
        chain dscptag {
                type filter hook forward priority filter; policy accept;
                iif "lo" accept
                meta l4proto udp ct original proto-src { 6881-6889, 51413 } coun                                                                                                                                                             ter packets 0 bytes 0 jump mark_cs1
                meta l4proto udp ct original proto-dst { 6881-6889, 51413 } coun                                                                                                                                                             ter packets 0 bytes 0 jump mark_cs1
                meta l4proto tcp ct original proto-dst { 6881-6889, 51413 } coun                                                                                                                                                             ter packets 0 bytes 0 jump mark_cs1
                meta length < 100 tcp flags ack add @xfst4ack { ct id . ct direc                                                                                                                                                             tion limit rate over 500000/second burst 5 packets } counter packets 0 bytes 0 j                                                                                                                                                             ump drop995
                meta length < 100 tcp flags ack add @fast4ack { ct id . ct direc                                                                                                                                                             tion limit rate over 50000/second burst 5 packets } counter packets 0 bytes 0 ju                                                                                                                                                             mp drop95
                meta length < 100 tcp flags ack add @med4ack { ct id . ct direct                                                                                                                                                             ion limit rate over 5000/second burst 5 packets } counter packets 69 bytes 2896                                                                                                                                                              jump drop50
                meta length < 100 tcp flags ack add @slow4ack { ct id . ct direc                                                                                                                                                             tion limit rate over 5000/second burst 5 packets } counter packets 35 bytes 1468                                                                                                                                                              jump drop50
                meta l4proto udp ip dscp > cs2 add @udp_meter { ct id . ct direc                                                                                                                                                             tion limit rate over 450/second burst 5 packets } counter packets 0 bytes 0 ip d                                                                                                                                                             scp set cs0 counter packets 0 bytes 0
                meta l4proto udp ip6 dscp > cs2 add @udp_meter { ct id . ct dire                                                                                                                                                             ction limit rate over 450/second burst 5 packets } counter packets 0 bytes 0 ip6                                                                                                                                                              dscp set cs0 counter packets 0 bytes 0
                meta l4proto tcp ct bytes < 6250000 jump mark_500ms
                meta l4proto tcp ct bytes > 125000000 jump mark_10s
                meta l4proto tcp ip dscp != cs1 add @slowtcp { ct id . ct direct                                                                                                                                                             ion limit rate 150/second burst 150 packets } ip dscp set af42 counter packets 1                                                                                                                                                             405 bytes 670218
                meta l4proto tcp ip6 dscp != cs1 add @slowtcp { ct id . ct direc                                                                                                                                                             tion limit rate 150/second burst 150 packets } ip6 dscp set af42 counter packets                                                                                                                                                              1038 bytes 667070
                ip saddr 192.168.8.219 udp dport != { 80, 443 } ip dscp set cs5                                                                                                                                                              counter packets 0 bytes 0 comment "ipv4_Game_Console_Outbound"
                meta priority set ip dscp map @priomap counter packets 2449 byte                                                                                                                                                             s 963844
                meta priority set ip6 dscp map @priomap counter packets 3580 byt                                                                                                                                                             es 2975280
                ct mark set ip dscp | 0x80 counter packets 2449 bytes 963844
                ct mark set ip6 dscp | 0x80 counter packets 3580 bytes 2975280
        }
}

==== Custom Rules Table Status ====
Custom rules table (qosmate_custom) is not active or doesn't exist.
root@OpenWrt:~# cat /etc/config/qosmate

config global 'global'
        option enabled '1'

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

config advanced 'advanced'
        option PRESERVE_CONFIG_FILES '1'
        option WASHDSCPUP '1'
        option WASHDSCPDOWN '1'
        option BWMAXRATIO '20'
        option UDP_RATE_LIMIT_ENABLED '1'
        option TCP_UPGRADE_ENABLED '1'
        option UDPBULKPORT '51413,6881-6889'
        option TCPBULKPORT '51413,6881-6889'
        option NFT_HOOK 'forward'
        option NFT_PRIORITY '0'

config hfsc 'hfsc'
        option LINKTYPE 'ethernet'
        option OH '44'
        option gameqdisc 'pfifo'
        option nongameqdisc 'fq_codel'
        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 COMMON_LINK_PRESETS 'ethernet'
        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'

config rule
        option name 'Game_Console_Outbound'
        option proto 'udp'
        list dest_port '!=80'
        list dest_port '!=443'
        option class 'cs5'
        option counter '1'
        option enabled '1'
        option trace '0'
        list src_ip '192.168.8.219'

config rule
        option name 'Game_Console_Inbound'
        option proto 'udp'
        option dest_ip '192.168.1.228'
        list src_port '!=80'
        list src_port '!=443'
        option class 'cs5'
        option counter '1'
        option enabled '0'

root@OpenWrt:~# ifstatus wan | grep -e device
        "l3_device": "pppoe-wan",
        "device": "AISVLAN.10",
root@OpenWrt:~# cat /etc/init.d/qosmate | grep -A 3 "QOSMATE_BASE_URL="

here is what you have asked. 


The problem is, my gaming packets haven't been classified as CS5
I had no proble mwith Flint 2 router at my house. On the other hand, i have problem with wrt32x at my wife house

I am trying to make packets get classified as CS5 again

Edit: i was not sure if it was somthing to do with Vlan10

It was the only different network envroinment between my wife house and my house
Mine have no vlan10 required.
my wife's, on the other hand, require vlan10

Ok, that would have been an important detail from the start, that it basically works for you, but now you're at your wife's house and it simply doesn’t work on a different router.

  1. You didn’t provide any output here:
cat /etc/init.d/qosmate | grep -A 3 "QOSMATE_BASE_URL="

Looking at your config, you’ve used eth0, even though the output of:

shows otherwise. I’d try using pppoe-wan instead.

Also your rules have different gaming device ip's:

Anyone with FTTP care to share settings that have worked for them? I feel like the combination of this script and my connection don't mix well with BO6. As soon as i switch to my old netduma R2 which runs HTB + something, although i still get bad matches, the difference is night and day.

@antonk

Sorry for the late reply. I only recently had a bit of time to think through the entire update process and take a brief look at the implementation of adblock-lean.

In general using tags and releases wouldn't be a problem at all. If you'd like, I can go ahead and create an initial tag/release.

What would be really cool and also quite practical is, if we could support flexible update mechanisms similar to adblock-lean. Updates based on tags/releases, master/snapshot, and also by branch. Supporting branches would be particularly important since there's a legacy branch that remains compatible with older openwrt and nftables versions.

The update channel should automatically switch, for example when a user installs with the -v snapshot flag and they get notified whenever master moves forward. This would be extremely useful for testing.

Would I then need to create a tag/release for both the backend and the luci app each time? Likely using the same tag, even if, for instance, nothing has changed on the frontend?

Probably yes, otherwise we'll need to think of some other mechanism to verify compatibility between the front-end and the back-end. Maybe even merge the 2 repo's in 1? This would be convenient because then you don't need to do 2 releases in 2 repos, and we only fetch from one repo and the version is guaranteed to match.

The only downside (I can see) is that if one day you'll want to include qosmate package in the OpenWrt packages repo, you'll probably have to re-split the source repo's (as normally the luci front-end has its own package), or perhaps make separate clone but split repo's for the front-end and the back-end and create the PR's based on that (but maybe there are smarter ways to manage this which I'm unaware of).

Edit: another downside of merging the repo's is that automatic update from pre-change qosmate versions will still be fetching the front-end from the front-end repo, but that can be dealt with.

1 Like

I’ve thought about that as well but the ultimate goal to eventually become an official openwrt package. That’s definitely on my agenda for the next few months. The idea is to clean up a few things and prepare the project for that. Having a stable branch would be really useful for this kind of development, so I can make preparations in the master branch while keeping a reliable version available.

Creating two tags and releases isn't a big deal, I guess. Maybe I can even automate some of that with GitHub workflows in the future.