An nftables based service for applying DSCP classifications to connections, compatible with OpenWrt's firewall4 for dynamically setting DSCP packet marks (this only works in OpenWrt 22.03 and above).
This should be used in conjunction with layer-cake SQM queue with ctinfo configured to restore DSCP on the device ingress. The nft-dscpclassify rules use the last 8 bits of the conntrack mark (0x000000ff).
The service supports three modes for classifying and DSCP marking connections.
The service will first attempt to classify new connections using rules specified by the user in the config file.
These follow a similar syntax to the OpenWrt firewall config and can match upon source/destination ports and IPs, firewall zones etc.
The service can be configured to apply the DSCP mark supplied by a non WAN originating client.
This function ignores CS6 and CS7 classes to avoid abuse from inappropriately configed LAN clients such as IoT devices.
Connections that do not match a pre-specified rule will be dynamically classified by the service via three mechanisms:
- Multi-threaded client port detection for detecting P2P traffic
- These connections are classified as Low Effort (LE) by default and therefore prioritised below Best Effort traffic when using the layer-cake qdisc.
- Multi-connection service detection for identifying high-throughput downloads from services such as Steam/Windows Update
- These connections are classified as High-Throughput (AF13) by default and therefore have a higher drop probability than regular traffic in the Best Effort layer-cake tin.
The service will respect DSCP classification stored by an external service in a connection's conntrack bits, this could include services such as netifyd.
To install the dscpclassify service via command line you can use the following:
mkdir -p "/etc/dscpclassify.d"
[ -f "/etc/config/dscpclassify" ] && mv /etc/config/dscpclassify /etc/config/dscpclassify.bak
rm -f /etc/dscpclassify.d/main.nft
rm -f /etc/hotplug.d/iface/21-dscpclassify
rm -f /etc/init.d/dscpclassify
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/etc/config/dscpclassify -P /etc/config
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/etc/dscpclassify.d/main.nft -P /etc/dscpclassify.d
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/etc/hotplug.d/iface/21-dscpclassify -P /etc/hotplug.d/iface
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/etc/init.d/dscpclassify -P /etc/init.d
chmod +x "/etc/init.d/dscpclassify"
/etc/init.d/dscpclassify enable
/etc/init.d/dscpclassify start
Ingress DSCP marking requires the SQM queue setup script 'layer_cake_ct.qos' and the package 'kmod-sched-ctinfo'.
To install these via command line you can use the following:
opkg update
opkg install kmod-sched-ctinfo
rm -f /usr/lib/sqm/layer_cake_ct.qos
rm -f /usr/lib/sqm/layer_cake_ct.qos.help
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/usr/lib/sqm/layer_cake_ct.qos -P /usr/lib/sqm
wget https://raw.githubusercontent.com/amteza/dscpclassify/main/usr/lib/sqm/layer_cake_ct.qos.help -P /usr/lib/sqm
The user rules in '/etc/config/dscpclassify' use the same syntax as OpenWrt's firewall config, the 'class' option is used to specified the desired DSCP.
A working default configuration is provided with the service.
The service supports the following global classification options:
Config option | Description | Type | Default |
---|---|---|---|
class_bulk | The class applied to threaded bulk clients | string | le |
class_high_throughput | The class applied to threaded high-throughput services | string | af13 |
client_hints | Adopt the DSCP class supplied by a non-WAN client (this exludes CS6 and CS7 classes to avoid abuse) | boolean | 1 |
threaded_client_min_bytes | The total bytes before a threaded client port (i.e. P2P) is classified as bulk | uint | 10000 |
threaded_service_min_bytes | The total bytes before a threaded service's connection is classed as high-throughput | uint | 1000000 |
wmm | When enabled the service will mark LAN bound packets with DSCP values respective of WMM (RFC-8325) | boolean | 1 |
Below is an example user rule:
config rule
option name 'DNS'
list proto 'tcp'
list proto 'udp'
list dest_port '53'
list dest_port '853'
list dest_port '5353'
option class 'cs5'
The OpenWrt firewall syntax is outlined here https://openwrt.org/docs/guide-user/firewall/firewall_configuration
The 'layer_cake_ct.qos' queue setup script must be selected for your wan device in SQM setup:
Below is a tested working SQM config for use with the service:
Config parameter | Value |
---|---|
qdisc_advanced | '1' |
squash_dscp | '0' |
squash_ingress | '0' |
qdisc_really_really_advanced | '1' |
iqdisc_opts | 'nat dual-dsthost ingress diffserv4' |
eqdisc_opts | 'nat dual-srchost ack-filter diffserv4' |
script | 'layer_cake_ct.qos' |