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

yes it does thanks much

Capture

1 Like

Hi @Hudra would it be possible to add fq_codel support for nss sqm?

I'm not deeply familiar with nss internals, so I might be missing something here. But I briefly looked into sqm-scripts-nss, and there seems to be a fundamental limitation:

"No marking or traffic classification is currently possible, this also means that DSCP squashing does not work"

QoSmate's core value is the combination of DSCP-based traffic classification + shaping... not just bufferbloat control. Since NSS currently can't honor DSCP markings or provide multiple priority queues, we'd lose most of what makes QoSmate useful.

I would say this is outside QoSmate's scope for now. If nss drivers add classification support in the future, happy to revisit.

I guess for pure bufferbloat control without prioritization, sqm-scripts-nss works well as a standalone solution.

1 Like

I tried couple of scripts lately and i found one that works great but introduced some random stutters so could someone help me out regarding this one? I use it together with HTB qdisc and Qosmate config and works great but still experience some issues with the script itself, probably cause its optimized for call of duty and not apex, also i play wired so might need to change cs6 to cs5 or ef? Thanks in advance

#!/bin/ash -x
IPT="iptables"
iptmark="iptables"
##ipset for streming sites.they are bening filled by dnsmasq
ipset create streaming hash:ip
ipset create usrcdn hash:ip
ipset create bulk hash:ip
ipset create latsens hash:ip

#flush mangle table
$IPT -t mangle -F PREROUTING
#Clear interface dscp marks, we don't trust ISP marks(also to use our own marks).
$IPT -t mangle -A PREROUTING -i wan -j DSCP --set-dscp 0
########################################

#Latency Sensitive (gaming/voip)
########################################
##Latency Sensitive
$IPT -t mangle -A PREROUTING -p icmp -j DSCP --set-dscp-class CS6 ##dscp tag for ping packets
$IPT -t mangle -A PREROUTING -m set --match-set latsens src -j DSCP --set-dscp-class CS6 ## set dscp tag for our Latency Sensitive (latsens) ipset
$IPT -t mangle -A PREROUTING -p tcp -m conntrack --ctorigsrc 192.168.1.161 -m multiport ! --ports 80,443,8080 -j DSCP --set-dscp-class CS6 -m comment --comment "PS4" #i don't have PS4, change the ip according to your ip setting.
####Latency Sensitive Ports####
sport00="3074"
sport4="9305:9308"
sport16="3478:3479"
dport00="3074:3075,3478:3479,3658:3659,9305:9308"
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport00 -j DSCP --set-dscp-class CS6
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport4 -j DSCP --set-dscp-class AF41
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport16 -j DSCP --set-dscp-class AF41
$IPT -t mangle -A PREROUTING -p udp -m multiport --dport $dport00 -j DSCP --set-dscp-class CS6
$IPT -t mangle -N dscp_mark > /dev/null 2>&1
$IPT -t mangle -F dscp_mark

#check if POSTROUTING already exits then jumps to our tables if not, add them
$IPT -t mangle -L POSTROUTING -n | grep dscp_mark || $IPT -t mangle -A POSTROUTING -o br-lan -j dscp_mark
iptmark() {
$IPT -t mangle -A dscp_mark "$@"
}
#A robust 2 rules to detect realtime traffic
iptmark -p udp -m hashlimit --hashlimit-name udp_high_prio --hashlimit-above 100/sec --hashlimit-burst 50 --hashlimit-mode srcip,srcport,dstip,dstport -j CONNMARK --set-mark 0x55 -m comment --comment "connmark for udp"

#unmarked UDP streams with small packets get CS6
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 22,25,53,67,68,123,143,161,162,514,80,443,8080 -m connbytes --connbytes 0:940 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 137,442,444,445,446,447 -m connbytes --connbytes 0:940 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
#large udp streams like video call get AF41
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 22,25,53,67,68,123,143,161,162,514,80,443,8080 -m connbytes --connbytes 940:1500 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class AF21 -m comment --comment "large udp connection gets AF21"
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 137,442,444,445,446,447 -m connbytes --connbytes 940:1500 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
#DNS traffic both udp and tcp
iptmark -p udp -m multiport --port 53 -j DSCP --set-dscp-class CS6 -m comment --comment "DNS udp"
#NTP
iptmark -p udp -m multiport --port 123 -j DSCP --set-dscp-class CS6 -m comment --comment "NTP udp"
#High priority ipset, i use for pubgM
iptmark ! -p udp -m set --match-set latsens src,dst -j DSCP --set-dscp-class CS6 -m comment --comment "latency sensitive ipset" ## set dscp tag for Latency Sensitive (latsens) ipset,udp
iptmark -p tcp -m set --match-set latsens src,dst -j DSCP --set-dscp-class CS6 -m comment --comment "latency sensitive ipset" ## set dscp tag for Latency Sensitive (latsens) ipset
###########
##Browsing
###########

#medium priority for browsing
iptmark -p tcp -m multiport --ports 80,443 -j DSCP --set-dscp-class CS3 -m comment --comment "Browsing at CS3"
##################
#TCP SYN,ACK flows
##################
#Make sure ACK,SYN packets get priority (to avoid upload speed limiting our download speed)
iptmark -p tcp --tcp-flags ALL ACK -m length --length :128 -j DSCP --set-dscp-class CS3
iptmark -p tcp --tcp-flags ALL SYN -m length --length :666 -j DSCP --set-dscp-class CS3
#Small packet is probably interactive or flow control
iptmark -m dscp ! --dscp 24 -m dscp ! --dscp 18 -m dscp ! --dscp 34 -m dscp ! --dscp 40 -m dscp ! --dscp 48 -m length --length 0:500 -j DSCP --set-dscp-class CS3
#Small packet connections: multi purpose (don't harm since not maxed out)
iptmark -m dscp ! --dscp 24 -m dscp ! --dscp 18 -m dscp ! --dscp 34 -m dscp ! --dscp 40 -m dscp ! --dscp 48 -m connbytes --connbytes 0:250 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS3
########################################

#Streaming Media (videos/audios)
########################################
#Known video streams sites like netflix
iptmark -m set --match-set streaming src,dst -j DSCP --set-dscp-class AF41 -m comment --comment "video audio stream ipset"
#known usrcdn like google or akamai
iptmark -m set --match-set usrcdn src,dst -j DSCP --set-dscp-class AF21 -m comment --comment "usrcdn ipset"
#########################################

#Background Traffic (Bulk/file transfer)
#########################################
#bulk traffic ipset, like windows udates and steam updates/downloads
iptmark -p tcp -m set --match-set bulk src,dst -j DSCP --set-dscp-class CS1 -m comment --comment "bulk traffic ipset"
iptmark -p udp -m set --match-set bulk src,dst -j DSCP --set-dscp-class CS1 -m comment --comment "bulk traffic ipset"
iptmark -p tcp -m connbytes --connbytes 350000: --connbytes-dir both --connbytes-mode bytes -m dscp --dscp-class CS3 -j DSCP --set-dscp-class CS1 -m comment --comment "Downgrade CS3 to CS1 for bulk tcp traffic"

This is all iptables based. modern OpenWrt uses nftables. I think there's a compatibility layer where it converts the iptables commands to nftables ones, but in general you're better off writing nftables rules.

I don't have time to help convert this unfortunately. And it's kinda hard to figure out what causes the issues you're having without some real hands on testing.

I understand it, didn't write it myself, its from a 2021 post, thank you though.

Could someone help me set up some basic Qosmate custom rules for gaming? Im new to this so i dont really know how to properly set it up, i mainly play one game, and that is apex on pc.

I cant seem to get a custom DSCP to work on ingress (incoming traffic).
Can someone provide an example on what a custom rule should look like, so that a custom DSCP works on ingress ?
is dnsmasq-full needed?

What do you mean by "custom DSCP"?

Did you read through the README? All differences between custom rules and inline rules are described there, including their respective use cases and examples.

You most likely used custom rules and those do not write the DSCP value into conntrack on egress, which is why it is not restored on ingress.

You only need dnsmasq-full if you want to use domain-based prioritization... this is also explained in the README.

Unfortunately, I don’t play Apex myself, so I can’t give you the exact ports. However, here’s an excerpt from the Geomate README. This is how I would look for the gaming ports:

Finding Game Ports and Protocols

There are several ways to identify the correct ports and protocols for your games:

  1. Using QoSmate (Recommended)
  • Install QoSmate on your router
  • Start your game and play normally
  • In LuCI, go to QoSmate's "Connections" tab
  • Filter the list by your gaming device's IP
  • Sort by "AVG BPS" or "AVG PPS" in descending order
  • Look for UDP connections with consistent traffic
  • Gaming traffic typically shows constant activity
  • Note both source and destination ports
  1. Alternative Methods
  • Use Wireshark for detailed packet analysis
  • Use tcpdump on the router
  • Check game documentation or community forums
  1. Understanding Port Types
  • Some games use fixed ports, others use port ranges
  • Examples:
    • Call of Duty: Source Port 3074 (fixed)
    • Fortnite: Destination Ports 9000-9100 (range)
  1. Configuring Ports in Geomate
  • Use the identified ports in your geo filter settings
  • Usually, the UDP port with highest consistent traffic is your main gaming port
  • Only configure the port that remains constant
    • If source port is always the same (like CoD's 3074), use that
    • If destination port range is consistent (like Fortnite's 9000-9100), use that
  • You don't need to configure both source and destination ports
  • Port ranges are supported (e.g., '9000-9100')

I`m new to using nftables so i probably used rules that do not write the DSCP value into conntrack on egress, i used chatgpt.
That`s why i asked for an example of a correct rule that works.

That’s why I pointed you to the README. You’ll find working rules there.

I have looked through that, but i can`t figure out which one is the rule that i need to use.
Could you please provide me with an example of e working Custom Rule that writes the DSCP value into conntrack on egress?

This isn’t meant to be rude, but the answer is right in front of you.
Here’s a direct quote from the section of the README I linked earlier:

1. Custom Rules (Full Table)

Custom Rules create a completely separate nftables table (qosmate_custom) where you can use independent chains, hooks, and priorities.

Advantages:

  • Define custom hooks (input, output, ingress, forward, postrouting) and priorities
  • Completely separate from QoSmate's main logic

Disadvantages:

  • No QoSmate Integration: Custom rules bypass some of QoSmate's core features:
    • No automatic DSCP conntrack writing
    • No priority map integration (necessary when using HFSC, Hybrid and HTB)
    • Washing has to be done manually (at least when using non CAKE root qdisc)
  • More Complex Setup: Requires understanding of nftables table/chain/hook/priority structure

2. Inline Rules (Integrated)

Inline Rules are directly integrated into QoSmate's main dscptag chain, running at the same hook and priority as QoSmate's core logic. They are inserted right before the user defined rules which means they can be overwritten by user-defined rules.

Advantages:

  • Automatic DSCP conntrack writing/restoring !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  • Priority map integration (Only necessary when using HFSC, Hybrid and HTB)
  • Washing functionality
  • No need to define tables, chains, or hooks

Disadvantages:

  • Cannot use custom hooks/priorities or define custom chain structures

Which of the two modes writes the DSCP value into conntrack according to the README (I even highlighted it for you)?

Hello all, sorry for the stupid question. Should I choose eth1 or pppoe_wan for my interface?

You have to set pppoe-wan

1 Like

Sorry but why?

Pppoe-wan is the virtual interface, eth1 is the physical port.

Isnt it better to apply the shaper on the physical device?

Or thats some pppoe specific advice?

Since I’m building my own OpenWRT firmware I’ve followed the README instructions on how to build qosmate and the respective luci package.

The packages compiled successfully, but then the bandwidth capping wasn’t working. Then I saw an error about missing jq package. I had to go back and select it manually, and now it works. So perhaps the Makefile is missing this dependency?

Another topic: in the instruction on cloning the repos I think it’s missing && after mkdir. As it is, the cloning doesn’t happen.

One question: I’m not a developer, I’m just a curious user, so pardon my lack of knowledge, but when I tried to update the local copy of the qosmate and luci-app-qosmate with git pull, I get this error: fatal: Need to specify how to reconcile divergent branches. How do I solve this?

1 Like

Depending on what scheduler is selected (HFSC, HTB) i’ve noticed fq_codel’s quantum is different - is there a reason for that? It’s either 300 or 3000, might have even seen it as 1514.