I'm running OpenWRT from a 19.07 snapshot with three cherrypicked commits from master for savedscp-mark (1aad1d17ed8bee2a22d235980a6c80b6dc1b74e0, dba5a01358d98cf5a83826f1890f9aa31a49a4d4, and 4bc02a421fbdf2b69e856dbe2829b2685deca8c1).
I'm using a slightly modified version of the sqm-scripts my_layer_cake.qos that @ldir had linked in another thread. The only notable changes are that the ctinfo arguments needed changed ("0xfc000000 0x01000000" instead of "0xfc000000/0x01000000") and the contents of the QOS_MARK_${IFACE} chain:
#!/bin/sh
# Cero3 Shaper
# A cake shaper and AQM solution that allows several diffserv marking schemes
# for ethernet gateways
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# Copyright (C) 2012-5 Michael D. Taht, Toke Høiland-Jørgensen, Sebastian Moeller
#sm: TODO pass in the cake diffserv keyword
. ${SQM_LIB_DIR}/defaults.sh
QDISC=cake
# Default traffic classication is passed in INGRESS_CAKE_OPTS and EGRESS_CAKE_OPTS, defined in defaults.sh now
egress() {
SILENT=1 $TC qdisc del dev $IFACE root
$TC qdisc add dev $IFACE root handle cacf: $( get_stab_string ) cake \
bandwidth ${UPLINK}kbit $( get_cake_lla_string ) ${EGRESS_CAKE_OPTS} ${EQDISC_OPTS}
# put an action on the egress interface to set DSCP from the stored connmark.
# this seems counter intuitive but it ensures once the mark is set that all
# subsequent egress packets have the same stored DSCP avoiding iptables rules
# to mark every packet, ctinfo does it for us and then CAKE is happy using the
# DSCP
$TC filter add dev $IFACE protocol all prio 10 u32 match u32 0 0 action \
ctinfo dscp 0xfc000000 0x01000000
}
ingress() {
SILENT=1 $TC qdisc del dev $IFACE handle ffff: ingress
$TC qdisc add dev $IFACE handle ffff: ingress
SILENT=1 $TC qdisc del dev $DEV root
[ "$IGNORE_DSCP_INGRESS" -eq "1" ] && INGRESS_CAKE_OPTS="$INGRESS_CAKE_OPTS besteffort"
[ "$ZERO_DSCP_INGRESS" -eq "1" ] && INGRESS_CAKE_OPTS="$INGRESS_CAKE_OPTS wash"
$TC qdisc add dev $DEV root handle cace: $( get_stab_string ) cake \
bandwidth ${DOWNLINK}kbit $( get_cake_lla_string ) ${INGRESS_CAKE_OPTS} ${IQDISC_OPTS}
$IP link set dev $DEV up
# redirect all IP packets arriving in $IFACE to ifb0
# set DSCP from conntrack mark
$TC filter add dev $IFACE parent ffff: protocol all prio 10 u32 \
match u32 0 0 action \
ctinfo dscp 0xfc000000 0x01000000 \
mirred egress redirect dev $DEV
# Configure iptables chain to mark packets
ipt -t mangle -N QOS_MARK_${IFACE}
# Change DSCP of relevant hosts/packets
# and save the DSCP to the connmark using savedscp
#From sched_cake.c:
# /* Further pruned list of traffic classes for four-class system:
# *
# * Latency Sensitive (CS7, CS6, EF, VA, CS5, CS4)
# * Streaming Media (AF4x, AF3x, CS3, AF2x, TOS4, CS2, TOS1)
# * Best Effort (CS0, AF1x, TOS2, and those not specified)
# * Background Traffic (CS1)
# *
# * Total 4 traffic classes.
# */
#and for diffserv8:
# /* Pruned list of traffic classes for typical applications:
# *
# * Network Control (CS6, CS7)
# * Minimum Latency (EF, VA, CS5, CS4)
# * Interactive Shell (CS2, TOS1)
# * Low Latency Transactions (AF2x, TOS4)
# * Video Streaming (AF4x, AF3x, CS3)
# * Bog Standard (CS0 etc.)
# * High Throughput (AF1x, TOS2)
# * Background Traffic (CS1)
# *
# * Total 8 traffic classes.
# */
# iptables -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.2 -m comment --comment "Testing to see if ctinfo is working" -j DSCP --set-dscp-class AF41
# iptables -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.2 -m comment --comment "Testing to see if ctinfo is working" -j DSCP --set-dscp-class AF41
# Template for small packets (test)
# ipt -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.152 -m multiport --dports 80,443 -m connbytes --connbytes-dir both --connbytes-mode avgpkt --connbytes 0:1200 -m comment --comment "Elijah's Switch DSCP" -j DSCP --set-dscp-class ${GAMING_CLASS}
#
GAMING_CLASS=AF41 #was CS3
ipt -t mangle -A QOS_MARK_${IFACE} -m set --match-set gameset dst -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -t mangle -A QOS_MARK_${IFACE} -m comment --comment "Match bulk traffic" -m set --match-set bulkset dst -j DSCP --set-dscp-class CS1
#Mike Wii U
ipt -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.3 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.3 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
#Hayden Wii U
ipt -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.4 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.4 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
#Hayden Switch
ipt -t mangle -A QOS_MARK_${IFACE} -m comment --comment "DSCP for Hayden's Switch" -p tcp -s 192.168.1.166 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.166 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
#Elijah Switch
ipt -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.152 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.152 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class ${GAMING_CLASS}
ipt -A QOS_MARK_${IFACE} -t mangle -j CONNMARK --savedscp-mark 0xfc000000/0x01000000
# Send unmarked connections to the marking chain
# top 6 bits are DSCP, LSB is DSCP is valid flag
# ipt -t mangle -A PREROUTING -i $IFACE -m connmark --mark 0x00000000/0x01000000 -g QOS_MARK_${IFACE}
ipt -t mangle -A POSTROUTING -o $IFACE -m connmark --mark 0x00000000/0x01000000 -g QOS_MARK_${IFACE}
#you could just send every packet to the marking chain and update the stored DSCP for every packet
#which should work for dynamic type marking but at a cpu cost
}
sqm_prepare_script() {
do_modules
verify_qdisc $QDISC "cake" || return 1
}
The filters seem to be enabled:
root@OpenWrt:~# tc -s -d filter show dev eth0
filter parent cacf: protocol all pref 10 u32 chain 0
filter parent cacf: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
filter parent cacf: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
match 00000000/00000000 at 0
action order 1: ctinfo zone 0 pipe
index 1 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 4197 sec DSCP set 0 error 0 CPMARK set 0
Action statistics:
Sent 25791675 bytes 192671 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
root@OpenWrt:~#
root@OpenWrt:~# tc -s -d filter show dev eth0 egress
filter parent ffff: protocol all pref 10 u32 chain 0
filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
match 00000000/00000000 at 0
action order 1: ctinfo zone 0 pipe
index 2 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 4208 sec used 0 sec DSCP set 0 error 0 CPMARK set 0
Action statistics:
Sent 720870953 bytes 553321 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
action order 2: mirred (Egress Redirect to device ifb4eth0) stolen
index 1 ref 1 bind 1 installed 4208 sec used 0 sec
Action statistics:
Sent 720870953 bytes 553321 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
Notable there is that DSCP set is "0". Which leads me to where I suspect the root of the problem is:
Chain PREROUTING (policy ACCEPT 30039 packets, 20M bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 141 packets, 12177 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 29802 packets, 20M bytes)
pkts bytes target prot opt in out source destination
2880 161K TCPMSS tcp -- any eth0.2 anywhere anywhere tcp flags:SYN,RST/SYN /* !fw3: Zone wan MTU fixing */ TCPMSS clamp to PMTU
Chain OUTPUT (policy ACCEPT 165 packets, 22561 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 29967 packets, 20M bytes)
pkts bytes target prot opt in out source destination
0 0 QOS_MARK_eth0 all -- any eth0 anywhere anywhere [goto] connmark match 0x0/0x1000000
Chain QOS_MARK_eth0 (1 references)
pkts bytes target prot opt in out source destination
0 0 DSCP tcp -- any any Lotus.lan anywhere /* Testing to see if ctinfo is working */ DSCP set 0x22
0 0 DSCP udp -- any any Lotus.lan anywhere /* Testing to see if ctinfo is working */ DSCP set 0x22
0 0 DSCP tcp -- any any Mike_WiiU.lan anywhere multiport dports !www,https /* Michael's Wii U DSCP */ DSCP set 0x22
0 0 DSCP udp -- any any Mike_WiiU.lan anywhere multiport dports !80,https /* Michael's Wii U DSCP */ DSCP set 0x22
0 0 DSCP tcp -- any any Hayden_WiiU.lan anywhere multiport dports !www,https /* Hayden's Wii U DSCP */ DSCP set 0x22
0 0 DSCP udp -- any any Hayden_WiiU.lan anywhere multiport dports !80,https /* Hayden's Wii U DSCP */ DSCP set 0x22
0 0 DSCP tcp -- any any Haydens_Switch.lan anywhere multiport dports !www,https /* Hayden's Switch DSCP */ DSCP set 0x22
0 0 DSCP udp -- any any Haydens_Switch.lan anywhere multiport dports !80,https /* Hayden's Switch DSCP */ DSCP set 0x22
0 0 CONNMARK all -- any any anywhere anywhere CONNMARK DSCP set 0xfc000000/0x1000000
What caught my eye is that the only rule in POSTROUTING looks like it is being skipped. I tried leaving out the connmark match in the last rule (so it would be 'ipt -t mangle -A POSTROUTING -o $IFACE -g QOS_MARK_${IFACE}' and the result is the same. I added my PC to the list of rules just so I should always have some traffic that would be matched.
I'm at a loss as to where to go from here, so I'll take a break and hopefully someone more experienced can point me in the right direction.
Thanks.
EDIT April 27, 2020 - Updated script because some users have found this thread and it isn't compatible with some sqm-script changes.