Prioritization with SQM QoS

I have a Linksys router (with openwrt) connected to my provider's modem ... on this Linksys I have SQM QoS to improve the bufferbloat and I have set the download and upload speed values ​​with the maximum that I want to give to this Linsys (and to all devices connected to it) ... now I have a problem: how can I give priority to a device connected to the linksys using SQM QoS? I hope I was clear enough in the description

SQM with CAKE is all about fairness among devices or flows, but not favoritism.

1 Like

Qos over nftables make by bandwith

This is a bit outside of sqm's scope....
sqm offers 2 scripts, layercake.qos/cake and simple.qos/fq_codel that implement different priority tiers based on DSCP marking of packets. That still leaves the problem of appropriately marking packets to get the desired effects.

obviously i can't install the normal QoS package as well because it would conflict with SQM QoS, right?

You can install qos-scripts and sqm-scripts concurrently, but on a given interface only one of the two can be active (IIRC if you configure both an say eth0 only the one that is instantiated second becomes active). On recent snapshots there is qosify, which can do a lot in regards to filtering, and for egress packets the normal firewall GUI can be used to set specific DSCPs depending on things like local and remote IP addresses and ports (for ingress this typically does not work, as the traffic shaper runs before iptables had access to the packets).

That said, often strict prioritization of a device is not as important as avoiding to starve a specific device, and for that sqm-scripts (or rather cake) offer per-internal-IP-isolation which equitable shares the available capacity between all active internal hosts. To illustrate:

  1. 1 active host -> 100%
  2. 2 capacity seeking hosts each -> 50% + 50% (generically 100/N for N active hosts)
  3. 1 fixed rate flow and 2 capacity seeking (say 10% of capacity) -> 10% + (100-10)/2 -> 45% + 45%

This works great for a number of use-cases, but falls short if explicitly unfair sharing is required, say in 3 if the fixed-rate flow requires more than the "fair capacity share" like a 8Mbps Twitch upload stream on a link with 10 Mbps upload capacity... (which requires a more DIY approach of tailoring a QoS script for these requirements).

@ldir has an example script here that can do that, but it's...gotten a lot more complicated since the last time I looked at it. I'm using an older version of it that works well for my purposes (some traffic gets sent to bulk due to ipsets, game consoles have their non-download traffic bumped to the voice tin due to my limited upload bandwidth). Stripped down to just a few rules:

#!/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.
    # */
 
    ipt -t mangle -A QOS_MARK_${IFACE} -m set --match-set gameset dst -j DSCP --set-dscp-class AF41
    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

    ipt -t mangle -A QOS_MARK_${IFACE} -p tcp -s 192.168.1.8 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class AF41
    ipt -t mangle -A QOS_MARK_${IFACE} -p udp -s 192.168.1.8 -m multiport --dports 1024:65535 -j DSCP --set-dscp-class AF41
    
    ipt -A QOS_MARK_${IFACE} -t mangle -j CONNMARK --set-dscpmark 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 problem SHOULD not be there because sqm is configured on the router's WAN port (WAN port connected to my provider's router), while the QoS I have to configure for the 4 LAN ports of the router…right?

This is all about sharing of the WAN capacity (in this example), the LAN ports typically live on a switch and hence there is no QoS active for traffic between the LAN ports.

That is, I can not set a priority between the various LAN ports?

I think some managed switches offer per-port-QoS, but the typical built in switches do not. You can try to build an elaborate QoS hierarchy/pyramid based on internal IP addresses and maybe MAC addresses as well, but that is not something I ever did, so can hardly offer advice.
BUT what I want to recommend is to keep prioritization to the absolute minimum you need. That is I would only implement rules/special cases if I could actually measure that rule improving the quality of experience.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.