Custom QoS Script Issue

Hello all,

First, I have built a custom script for my main routers to serve our home for years now. First was a tomato based firmware and the current one is Padavan in which I made a script based on my tomato config. It works well at achieving my goal. 50mbit 20mbit up with my QoS script uses 70-80% CPU on my cheap asus router. Now our plan is going to be upgraded in a few months from 50mbit to 100/40 and concerns about CPU of router is imminent and need to buy a new router.
So got TP-Link C2 AC900 v3 and hooked up OpenWRT and installed SQM. However that does not achieve my goal. Have a on-demand bandwidth when I want to stream on Youtube or Facebook. So I updated my QoS script for OpenWRT with IFB and IPTABLES.

Packages:

opkg install tc kmod-sched-core kmod-sched kmod-ifb kmod-ipt-ipopt iptables-mod-ipopt

My QoS Script (set to run during firewall change event)

# Updated: 12062019t0749
# OpenWRT Custom QoS Script
# Reference: https://openwrt.org/docs/guide-user/network/traffic-shaping/packet.scheduler
# Based on: https://wiki.gentoo.org/wiki/Traffic_shaping
# Migrating code to be compatible with OpenWRT

### ============================= ###
### ===== IFB SCRIPT SIMPLE ===== ###
### ============================= ###
### Features:                     ###
### - 2 Class Ingress             ###
### - Improve performance         ###
### ============================= ###
############### Edit parameters here! ####################
# Download and upload speed in KiloBITS. Speedtest speed should be provided as script will calculate overhead for you.
# Plan: Globe at Home 2499 @ 50mbps down / 20mbps up
DOWNLOAD=50400
UPLOAD=20200
################# DO NOT EDIT BELOW! ######################
ext=$(uci get network.wan.ifname)  # Get active WAN interface
ext_ingress=ifb0
# ext_mtu=$(cat /sys/class/net/$ext/mtu)  # Get MTU of WAN
logger 'Initializing...'

logger 'Clearing queue disciplines and iptables.. Please wait.'
sed -n 's/ *\(.*\):.*/\1/p' /proc/net/dev | while read INTERFACE; do
  tc qdisc del dev $INTERFACE root >&- 2>&-
  tc qdisc del dev $INTERFACE ingress >&- 2>&-
done
iptables -t mangle -F
iptables -t mangle -X


# Create ingress on external interface
logger 'Creating ingress interface'
tc qdisc add dev $ext handle ffff: ingress
ip link set ifb0 up
tc filter add dev $ext parent ffff: protocol all u32 match u32 0 0 action mirred egress redirect dev ifb0


logger 'Setting parameters'
DOWNLOAD=$((DOWNLOAD*96/100))
UPLOAD=$((UPLOAD*92/100))
logger 'Setting QoS with Download of ${DOWNLOAD}kbit and Upload of ${UPLOAD}kbit'

# DOWNLOAD QOS
logger 'Setting up download qos..'
tc qdisc add dev ifb0 root handle 1: htb default 11
tc class add dev ifb0 parent 1: classid 1:1 htb rate ${DOWNLOAD}kbit
tc class add dev ifb0 parent 1:1 classid 1:10 htb rate $((DOWNLOAD*4/10))kbit ceil ${DOWNLOAD}kbit
tc class add dev ifb0 parent 1:1 classid 1:11 htb rate $((DOWNLOAD*6/10))kbit ceil ${DOWNLOAD}kbit

tc qdisc add dev ifb0 parent 1:10 handle 10: fq_codel ecn
tc qdisc add dev ifb0 parent 1:11 handle 11: fq_codel ecn

# Filter HTTPS
tc filter add dev ifb0 parent 1: protocol ip u32 match ip protocol 6 0xff match ip sport 443 0xffff flowid 1:10


## UPLOAD QOS
logger 'Setting up upload qos..'
UMAX=$((UPLOAD-600))
tc qdisc add dev $ext root handle 1: htb default 12
tc class add dev $ext parent 1: classid 1:1 htb rate ${UPLOAD}kbit
tc class add dev $ext parent 1:1 classid 1:10 htb rate 600kbit
tc class add dev $ext parent 1:1 classid 1:11 htb rate 12400kbit ceil ${UMAX}kbit
tc class add dev $ext parent 1:1 classid 1:12 htb rate $((UMAX-12500))kbit ceil ${UMAX}kbit

tc qdisc add dev $ext parent 1:10 handle 10: fq_codel quantum 300 noecn
tc qdisc add dev $ext parent 1:11 handle 11: fq_codel quantum 300 noecn
tc qdisc add dev $ext parent 1:12 handle 12: fq_codel quantum 300 noecn

tc filter add dev $ext parent 1: protocol ip u32 match ip protocol 1 0xff flowid 1:10 # ICMP
tc filter add dev $ext parent 1: protocol ip u32 match ip protocol 6 0xff match u8 0x05 0x0f at 0 match u16 0x0000 0xffc0 at 2 match u8 0x10 0xff at 33 flowid 1:10 # ACK
tc filter add dev $ext parent 1: protocol ip u32 match ip tos 0xE0 0xff match ip protocol 11 0xff flowid 1:10 # TOS VOIP
tc filter add dev $ext parent 1: protocol ip u32 match ip tos 0xB8 0xff match ip protocol 11 0xff flowid 1:10 # TOS VOIP

tc filter add dev $ext parent 1: protocol ip handle 1 fw flowid 1:10
tc filter add dev $ext parent 1: protocol ip handle 2 fw flowid 1:11
tc filter add dev $ext parent 1: protocol ip handle 3 fw flowid 1:12


## Routing packets ##
logger 'Setting ip tables'
iptables -t mangle -N upload_chain
iptables -t mangle -A POSTROUTING -o $ext -j upload_chain

iptables -t mangle -A upload_chain -p udp -m multiport --dport 1024:65535 -m length --length :256 -j MARK --set-mark 1
iptables -t mangle -A upload_chain -p tcp -m multiport --dport 1024:65535 -m length --length :60 -j MARK --set-mark 1

# IP Match
iptables -t mangle -A upload_chain -s 192.168.1.110 -p tcp --dport 1935 -j MARK --set-mark 2

# TOS
iptables -t mangle -A upload_chain -m tos --tos Minimize-Delay -j MARK --set-mark 1
iptables -t mangle -A upload_chain -m tos --tos Minimize-Cost -j MARK --set-mark 2
iptables -t mangle -A upload_chain -m tos --tos Maximize-Throughput -j MARK --set-mark 3

exit 0


# Troubleshoot:
# iptables -t mangle -vnL
# tc qdisc show dev ifb0
# tc qdisc show dev eth2.2

My problem lies in IFB interface. I created 2 class 1 being specifically for HTTPS which makes sure services such as Youtube or Netflix won't experience problem while someone downloads. When someone downloads on say Steam or even P2P then YouTube or Netflix will just be at 8mbit at most which is I believe my ISP-side of things.

Therefore my goal is:
HTTPS(WWW, Youtube, Netflix, etc) uses class id 1:10 with 40% guaranteed BW at full capacity.
then rest on 60% guaranteed BW. with class id 1:11 being default.

No drops on ICMP when on full load while maintaining 40% CPU
I am at wits end. Any suggestions will be of great help.

Additional Info:
Internet type: GPON
Download: 50mbps
Upload: 20mbps

Edit: Forgot to add openwrt build: OpenWrt SNAPSHOT r10263-bc47285cb3
Router: TP-LINK C2 AC900 V3

this is your problem?

filtering by tcp-criteria is unfit for most (and your) purpose.
what you need is per-host fair-queueing.
try with a stock config and luci-app-sqm, instantiate a instance of piece_of_cake on your wan interface (or pppoe-interface if existant)....

1 Like

Hey thanks for your reply!
Yup been using SQM for that very purpose! Been good to me on download side of things.

Since you mentioned it an idea struck me. SQM is indeed what I would need for fair-queue. Will I be able to say manipulate the built-in script in away to also have a class for specific port (eg. 1935) with it's own egress rate? Not sure if this was done but the DSCP guide in the forum blew me away.

Since my script has a class specific for streaming service 1935 with rate 70% ceil 100% of BW. I am assuming there should be an equivalent. But then ingress and egress goes hand-in-hand for it to work no?

Thanks

no.
cake has internal service-classes but to modify them you'd have to change source. maybe one of the available diffserve modes suits your needs?

fwiw you rarely really need anything more than fairness, especially at 100mbps+

you can use iptables to change dscp on egress to put your traffic in classes, but not on ingress (because ifb runs before iptables).
but a cake feature to also apply the outgoing class assigments on the return traffic (ingress) has been commited upstream.

Ok thanks for the reply!

So based on what you have suggested I have a possible picture of what can be done for my goal.

  1. Instead of filtering ports using tc will use SQM method - which makes sense if client 1 is watching netflix while client 2 is downloading gives both fair 50% BW.
  2. Egress - Since SQM is active sensitive packets will get prioritized by default and fair share shape is active.
  3. Egress - For me to achieve a custom class for my port 1935 for streaming I would use iptables to manipulate dscp. I am assuming basing on this MAN page: https://dl.lochnair.net/Bufferbloat/Cake/tc-cake.8.html I should set port 1935 to the appropriate DSCP, which in my case is the VIDEO dscp which gets 50% of total BW when active. That's using Layer_cake or Diffserv4
  4. Egress - In essense I don't need to specify UDP and TCP port length to be on top of the class since it is already built-in in Cake.

I believe this is the route I should be going for? Feel free to correct me as I would be testing this in a few hours. Any more feedback is appreciated.

sounds good

feedback i forgot before:
your router is not overpowered for sqm, if you also run other stuff (vpn,nas,...) you will probably see performance degradation somewhere.

Yup notice that it's hitting 70-80% CPU on full load both ingress and egress. If I set my GPON modem to bridge and let the OpenWRT to do the PPPoE router would crash at some point. But for now DHCP with modem works well. Even with 97% for Download and 95% Upload. But of course no headroom left.

Thinking about either Linksys EA6350 V3 or Asus RT-AC58U both with 4 cores qualcomm cpu at same price range $80 in my country.
https://wikidevi.com/wiki/ASUS_RT-AC58U
https://wikidevi.com/wiki/Linksys_EA6350_v3
Guess that should make me set even if I go with 200/80

Avoid the ASUS RT-AC58U, 128 MB RAM is not sufficient for two ath10k radios (ath10k/ ath10k-ct do need a lot of RAM), the EA6350v3 (and most other ipq40xx devices) comes with 256 MB RAM instead and should be much better (only problem there is making sure to get a v3 device).

2 Likes

Thanks will take note of that. I canvassed through retailers and they all only have the EA6350v3. The price range is within my comfortable budget range $50 - $120.
It became imperative when ISP inform us about rollout of their internet plans being updated (from 50 to 100) have to be ready with the jump.

My TP-Link C2 AC900 currently serves as a router on 2nd floor was thinking maybe the hardware of it is abit powerful than the Asus RT-N12+ one. So I was tinkering with the QoS maybe I can set it as a gateway instead making them swap roles.

In any case if EA6350v1 or v2 is going to be sold here it'll be imported (bootleg) and cost around $250 according to the supplier.

Thanks again.

for that kind of money, you can get either a x86 mini-pc (low power/space requirements) or an slightly dated small-ish workstation (overpowered).

1 Like