DSCP Classify - a service for applying DSCP to connections

cake will ignore the ECN setting in the GUI and always use ECN if the packets have either ECT(0) or ECT(1) set. (Or cake is already in emergency drop mode or the respective flow triggered cake's BLUE mode which IIRC drops hard).

1 Like

It's not committed to develop yet.


That’s what I also suggested in my thread as new users could get confused if their static marks are overwritten when wmm is enabled.

One thing that always comes to my mind when i think about dscpclassify is: do you inted to make a luci app for dscpclassify? Or could it maybe be integrated into the luci firewall?

Setting dscp through luci firewall would probably already work with your script. I have to try that…



yes it would be a great idea if by luci we could put it as hudra suggests but I think the work would be long?
if we could integrate our dscpclassify parameters like in my thread

it would be christmas for the first time in such a short time :sweat_smile:

yes exactly :wink:

I will wait for your last merge to update the script,

@Hudra yes I also have the same little problem as you the counter seems to be blocked especially for twitch1

 ip saddr tcp dport 1935 counter packets 1 bytes 60 goto ct_set_cs3 comment "twitch1"

Actually, I don’t have any problem, maybe you misunderstood something:

In this post I just wanted to make clear that I think it would be better to disable the option wmm by default. But I was too slow as @yelreve already fixed it in his repository.

If you are referring to my thread where I asked why my counters are not increasing by much when the option “counter” is set here is your answer:

So, if you have 1 packet in your counter it probably works and you won’t ever see counters increasing for every packet. Only for every flow… at least unless there is an option to use counters from conntrack but I don’t know if this is possible.


I've updated the main branch now with the negative matching ability, I took it one step further to allow mixing both negative and positive matches on a single rule (though probably a fairly niche use case).

@Dopam-IT_1987 I think your config in thread Sharing dscpclassify configuration on OpenWrt should now work as expected with the main code branch. :slight_smile:

It also includes the auto-merge tweak for sets with intervals.

@Hudra you're correct, the rule counters only count matched connections (not every packet in the connection).


may i ask what negative matching mean ??

It allows you to write a rule which would match everything except the entries you've specified with an '!'.
For example the below would match all tcp/udp connections that did not have a destination port of 443 or 80.

config rule
	option name 'Not HTTP'
	list proto		'tcp'
	list proto		'udp'
	list dest_port	'!443'
	list dest_port	'!80'
	option class 'cs4'

is it the same as writing nowash in iqdisc_opts and eqdisc_opts right ??
what if i only wash on egress ?

In SQM setup those two parameters correspond to the following options

Squash DSCP on inbound packets (ingress) = squash_dscp
Ignore DSCP on ingress = squash_ingress

You're correct, setting squash_dscp to 0 (allow) is equivalent to nowash in iqdisc_opts.

Enabling squash/wash has the effect of making cake overwrite the DSCP to 0 after passing through the tc qdisc, however DSCP classify would re-apply it from the conntrack for lan bound packets.

squash_ingress doesn't seem to actually do anything in my testing this morning. *Edit: per @moeller0's note below this is because I'm specifying a diffserv in my qdisc_opts.

Washing on WAN egress via eqdisc_opts would make sure your DSCPs are all set to CS0 when sent to your ISP after passing through the qdisc - that could be beneficial depending on how your ISP handles different DSCP marks.


This will configure the ingress qdisc to use besteffort instead of the default diffserv3. However the i/eqdisc opts will still override this*. The goal here is to simply ignore DSCPs by treating all DSCPs identical and avoid busywork, by first re-setting DSCPs and then still sort packets into the different tins (where all will end up in the besteffort tin once the DSCP has been changed to 0 anyways, so the sorting is useless work).

The way tc parses cake's options means that for any "class" of parameters the latest "wins", so with a sequence of diffserv3 ... besteffort ... diffserv4, diffserv4 will be selected.
Without any over-ride options configured the outcome is going to be:
squash_ingress = TRUE: diffserv3 ... besteffort` -> besteffort squash_ingress = FALSE: diffserv3 ...` -> diffserv3


I just checked, diffserv8 actually sorts AF11-3 into tin 1 while besteffort resides in tin 2, while diffserv3/4 treat AF11-3 exactly like CS0. So not sure how to concisely describe that, but "prioritised amongst Best Effort" seems not intuitive to say, priority <= besteffort, no?

1 Like

Update 2023-02-13:

  • The service config file now supports specifying the number of connections required to classify a client or service as threaded (i.e. P2P/multi connection Steam downloads).
  • Refactored the code to support service reloads using the current snapshot build nft binaries (versions >1.0.2)

i just tried installing this from your intstuctions but unsure if its setup correctly?

service starts but displays the following:

active with no instances

Is there a way to check if its working properly?

 nft -f "/etc/dscpclassify.d/main.nft"
/etc/dscpclassify.d/main.nft:38:1-44: Error: File not found: /tmp/etc/dscpclassify-pre.include
include "/tmp/etc/dscpclassify-pre.include"
/etc/dscpclassify.d/main.nft:124:1-45: Error: File not found: /tmp/etc/dscpclassify-post.include
include "/tmp/etc/dscpclassify-post.include"

could this be root cause?

I suspect it is in fact working for you :slight_smile: That shell message would be generated by the status check I introduced for correctly handling service reload, line of code responsible below:
service dscpclassify status 2>/dev/null

I'll supress this in a quick commit to avoid confusion (I'd already supressed stderr).

You can manually check if the service has started successfully and created the dscpclassify firewall table by running:
nft list table inet dscpclassify

Commit Improve manual service config reload messaging. · jeverley/dscpclassify@d5d20b0 (github.com) pushed to address this, @rspierz let me know of any further observations on your end.

great looks like it is working.

I added one rule so far for webex, although i dont think its perfect yet

config rule
	option name 'Webex video/audio'
	option proto 'udp'
	option dest_port '9000'
	option dest_port '5004'
	list dest_ip ''
        list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	list dest_ip ''
	option class 'af41'

although since my webex meetings are over vpn. I dont think its working as all my flows are going to best effort with a little going to voice probably for phone wifi calling.

qdisc cake 8008: dev ifb4eth1 root refcnt 2 bandwidth 925Mbit diffserv4 dual-dsthost nat nowash ingress no-ack-filter split-gso rtt 100ms noatm overhead 46 mpu 84 
 Sent 13977533038 bytes 15296305 pkt (dropped 25, overlimits 14670169 requeues 0) 
 backlog 0b 0p requeues 0
 memory used: 1326784b of 15140Kb
 capacity estimate: 925Mbit
 min/max network layer size:           46 /    1500
 min/max overhead-adjusted size:       92 /    1546
 average network hdr offset:           14

                   Bulk  Best Effort        Video        Voice
  thresh      57812Kbit      925Mbit   462500Kbit   231250Kbit
  target            5ms          5ms          5ms          5ms
  interval        100ms        100ms        100ms        100ms
  pk_delay          0us         24us          0us         12us
  av_delay          0us          4us          0us          2us
  sp_delay          0us          0us          0us          2us
  backlog            0b           0b           0b           0b
  pkts                0     15284746            0        11584
  bytes               0  13976366196            0      1204692
  way_inds            0      2938299            0            0
  way_miss            0        79658            0            2
  way_cols            0            0            0            0
  drops               0           25            0            0
  marks               0            0            0            0
  ack_drop            0            0            0            0
  sp_flows            0            1            0            1
  bk_flows            0            1            0            0
  un_flows            0            0            0            0
  max_len             0         1514            0          104
  quantum          1514         1514         1514         1514

Is the VPN on your client device or router? OpenWrt won't be able to see packet destinations/ports within a VPN connection established from a client device.