Help on DSCP marking for gaming + SQM

Hi guys,

I'm very new to OpenWRT, and I'm trying to figure out how I can use it to prioritize my game traffic. I'm not entirely sure how to set up what I want, and I'm hoping you can help me.

My Setup
I'm in Montreal using Videotron's coaxial cable internet. The modem is connected to my Archer c7 v2 router which I've flashed with OpenWRT.
I'm wired through a cat7 cable and other devices (phones, wife's laptop etc) are on wifi.

What I have already tried
I've installed the SQM software and have 1 instance of it running on my WAN interface on "cake" and "layer_cake.qos". I get A+ in all ratings on dslreport so I'm assuming it's working.
However, I play Street Fighter and it's super sensitive to jitter. As good as SQM is, I still get small spikes randomly, and that completely screws up how my character looks on my opponent's side.

What I'm trying
I figured perhaps prioritizing my game packets might work better.
But I'm not sure if I did it correctly, and if I still need SQM once the markings are in place.
What I've added to the firewall rules are written below, they are mostly taken from other threads I was able to find, and I added the ones for street fighter.

My Questions

  1. do I still need to keep SQM turned on if the markings are done correctly? and if it's not right, how can I mark my gaming packets correctly?
  2. I really mostly care about out-going packets, are those the ones with "dports" commands? and if so, are the ports number the same as the ones used on my machine for incoming packets?
  3. If none of this works, is there a way to prioritize my wired connection over wifi? I've tried searching for this solution, but all I've seen is that SQM doesn't work like that. However I'm wondering if that's possible via DSCP markings since I already gave my machine a static IP.

thank you guys for reading through my noob questions.

iptables -t mangle -N dscp_mark
ip6tables -t mangle -N dscp_mark
iptables -t mangle -F dscp_mark
ip6tables -t mangle -F dscp_mark

iptables -t mangle -A FORWARD -j dscp_mark
ip6tables -t mangle -A FORWARD -j dscp_mark

## icmp gets CS5
iptables -t mangle -A dscp_mark  -p icmp -j DSCP --set-dscp-class CS5
ip6tables -t mangle -A dscp_mark -p icmpv6 -j DSCP --set-dscp-class CS5

## valve games use these ports (at least)

iptables -t mangle -A dscp_mark  -p udp --sport 27000:27200 -j DSCP --set-dscp-class CS5
ip6tables -t mangle -A dscp_mark -p udp --sport 27000:27200 -j DSCP --set-dscp-class CS5

iptables -t mangle -A dscp_mark  -p udp --dport 27000:27200 -j DSCP --set-dscp-class CS5
ip6tables -t mangle -A dscp_mark -p udp --dport 27000:27200 -j DSCP --set-dscp-class CS5

## SFV gets CS6

iptables -t mangle -A dscp_mark  -p udp --sport 30840:30859 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark  -p udp --sport 30840:30859 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark -p udp --sport 30870:30879 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p udp --sport 30870:30879 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark  -p udp --dport 30840:30859 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark  -p udp --dport 30840:30859 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark -p udp --dport 30870:30879 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p udp --dport 30870:30879 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark  -p tcp --sport 20002:20002 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p tcp --sport 20002:20002 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark  -p tcp --sport 30840:30870 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p tcp --sport 30840:30870 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark  -p tcp --dport 20002:20002 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p tcp --dport 20002:20002 -j DSCP --set-dscp-class CS6

iptables -t mangle -A dscp_mark  -p tcp --dport 30840:30870 -j DSCP --set-dscp-class CS6
ip6tables -t mangle -A dscp_mark -p tcp --dport 30840:30870 -j DSCP --set-dscp-class CS6

First of all, what is your contractual WAN speed? The Archer c7 hardware limits out routing around 150-200 MBit/s, significantly less with SQM enabled - while cable internet often implies considerably more than that. Make sure that your hardware isn't becoming more of a bottleneck than the plain connection would be.

I'm on a 120/35 connection, I've limited it to 90/25.

if course it's possible... but as you mention... it requires a way to distinguish between the two... like staticip/s + vlsm or static>dynamic mac rulesets...

the much simpler way to handle that is just mark all clients something general and 'special' clients/traffic in an expedited manner... exclude/downgrade bulky stuff coming from the expedited vlsm range / mac list and you have yourself something decent... all depends how much time / effort you have to learn / test / think etc. etc.

what you posted above does not (wholistically) address the bidirectional aspects mentioned from where you got it... this will be a major factor in what you can achieve...

essentially all games are going to use UDP for their control packets. So an easy way to get approximately what you want is to mark all packets CS0 followed by marking all udp packets from your game machine as CS6.

As long as you don't do something that generates a ton of UDP while on the same machine while you're playing, it'll work well and won't require knowing specific port numbers which might change etc.

1 Like

i see, are there rules I can add to mark incoming packets? Would that solve the bidirectional aspect of things?

that sounds good. do you happen to know how to mark packet from a particular IP or MAC address? I have no idea what I need to type in the rules to do that.

Also, I've heard marking packets as EF as opposed to CS5/CS6 might be better for gaming packets since it's lower latency and less jitter. I'm not sure if that's the case.

No, the actual diffserve code point (dscp) does not carry information. It is the per hop behaviour (PHB) that you need and that is independent of
the actual dscp. Sure, there are a few dscps that are traditionally used, but in this case you need to pick dscps that map to the desired tins in cake. EF will map in the highest priprity tin in both diffserv3 and diffserv4 IIRC, so per se is not a terrible choice. But not any better than CS6, which ends up in exactly the same tin... Please note in diffserve4 CS3 will get you into the second highest tin which gets up to 50% of availale bandwidth at heightened priority, while the highest will only get you 25%, which depending on yor access speed might not be enough for your game.

EDIT: fixed some typos.

Blockquote No, the actual diffserve code point (dscp) does not carry imformation. It is the per job behaviour (PHB) that you need and that is independent of
the actual dscp.

Thanks for the info. Does that mean I need to configure something in the PHB? I really have no clue what and how to do it, do you mind giving me some hints on how to do so?

No, if you use a ready-made system like cake's diffserve modes, you simply pick a DSCP that gets mapped into the priority tier you want your packets to reside in, independent of potential other definitions how that specific DSCP should be treated...
Diffserve really separates the DSCPs which can be (with some limits) used how ever you want (which is a concession to reality, ISPs using DSCPs for traffic engineering/steering already use their existing DSCP meanings and are unlikely to change these just because the IETF should decide so) from the Per Hop Behavior (PHB, excuse the typo above) which are more description of use cases for differential treatment which often also propose a DSCP to use incase non is on use.
But here, if your game is happy with 25% of your internet access rate, EF or CS6 are decent choices for layer_cake.qos (which defaults to diffserv3), if 25% is too little, but 50% would do you should IMHO target the second higherst priority tier in diffserv4, for which CS3 should work.

Yes, marking alone rarely helps. you need something from clogging up the over-sized and under-managed buffers of your cable modem/router, so some sort of shaper will be necessary.

Honestly, ports (above ~1000) are ephemeral and might change tomorrow (and can be re-mapped internally by the NAT engine), so I think simply up-prioritizing all traffic to/from a specific internal host might be a safer bet, okay, maybe restrict it to UDP (most games use UDP for time critical data) and you are set.

Can be done, but is not that easy...

I would say don't do that, at least linux ping can be instructed to set its own TOS byte value, so you can change the "DSCP" from the command line (well, DSCPs are 6 bit, while the TOS byte is 8 bit, so you need to convert things, but it remains without that rule you can use ping to probe the latency in any priority tier, with that rule only in the tier CS5 maps into). IMHO hard mapping of ICMP/ping is okay during testing but probably does not belong into a hard rule set, unless you have DSCP sensitive switches in your network, in which case things might be different, but you would know that :wink:

So I would try something like:

GAMINGIP=127.0.0.1 # replace by real address
iptables -t mangle -A POSTROUTING -p udp -d ${GAMINGIP} -j DSCP --set-dscp-class EF
iptables -t mangle -A POSTROUTING -p udp -s ${GAMINGIP} -j DSCP --set-dscp-class EF

to simply move all traffic from the gaming host to cake's highest priority tier, with your 90/25 speed that will be 22.5/6.26 Mbps, and @dlakelan has recently data showing gaming traffic to stay well below 2Mbps, so that might all you need to do for the upload.

If you feel exceptionally risky, you can switch cake to pure precedence (using the precedence keyword) in which case there is no limit to the high priority tier, but gaming traffic can then fully starve everything else....

1 Like

that's very helpful! thank you so much!
I've set up the tagging of UDP packets for my machine like you suggested with the IP field being my local static ip assigned by the router.
My game doesn't use up too much bandwidth, and I'm going to give pure precedence a try. I'm supposing that I switch "cake" to "precedence" in the 'qdisc' option right?

so my sqm file looks like this:

config queue 'eth1'
        option debug_logging '0'
        option verbosity '5'
        option upload '25000'
        option script 'layer_cake.qos'
        option interface 'eth0.2'
        option download '90000'
        option linklayer 'ethernet'
        option qdisc_advanced '0'
        option overhead '44'
        option qdisc 'precedence'
        option enabled '1'
        option eqdisc_opts 'nat dual-srchost diffserv4'

Also a weird problem I've been facing is that if I continue to ping google or my isp, I see a large increase in jitter and overall average ping in bursts of 4-5 second segments (sometimes more) whenever there's video or voice traffic, and that's been detrimental to my games. I thought SQM was going to combat that, so I really don't know what is going on. I've called my ISP several times and they've sent different technicians over the past few months to check both my connection and servers around the area and everything's fine. So I'm not sure if setting my SQM instance over my WAN interface is not doing anything? and to be honest I'm a total noob in networking, so I'm really thankful for these insightful answers you've been giving me.

Almost, piece_of_cake and layer_cake silently ignore the qdisc parameter. You need to replace

        option eqdisc_opts 'nat dual-srchost diffserv4'

with

        option eqdisc_opts 'nat dual-srchost precedence'

But keep in mind precedence is dangerous. I would start with diffserv4...

Also you can use tc -s qdisc to see cake's traffic and latency counters. If the egress cake instance with diffserv4 or diffserve3 has a peak deleav stat (pk_delay) not far from say 5 ms and the average delay av_delay stays below 2ms, I think this is as good as it gets. Wifi for example often introduces jitter in the 4ms range....
But by all means try it out

Show the output of tc -s qdisc there we might see something relevant in the timing stats. But I take it that you see periods of 4-5 seconds of increased ping, but from what value does the ping RTT start our (unloaded) and what values does it reach during those epochs?

Start with diffserv4, your connection is way faster than the minimum so this is safer and will have no difference in quality.

Zoom by default tags its packets CS7 which is probably similar for other video conferencing apps. If you use diffserv4 try tagging all packets at CS0 all UDP at CS4 and UDP from your game machine at CS6. Do the rules in that order.

1 Like

I think ZOOM only does this for payed instances where the administrator activated that?

Could be, I only see what my wife's instance does which is a university paid account. In any case the suggested iptables rules should play nicely.

the output of my tc -s qdisc looks like this with 'presedence'
some times with no notable traffic the ping would still spike which is the main reason I called my ISP, but they tried a variety of tests over the past 2 months and saw no problem. So Im going to try what @dlakelan suggested and make everything else low priority.

qdisc noqueue 0: dev lo root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc fq_codel 0: dev eth0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn
 Sent 523050429 bytes 4882486 pkt (dropped 0, overlimits 0 requeues 2)
 backlog 0b 0p requeues 2
  maxpacket 1514 drop_overlimit 0 new_flow_count 3 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc fq_codel 0: dev eth1 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 4Mb ecn
 Sent 2899054134 bytes 2384151 pkt (dropped 0, overlimits 0 requeues 4)
 backlog 0b 0p requeues 4
  maxpacket 1514 drop_overlimit 0 new_flow_count 4 ecn_mark 0
  new_flows_len 0 old_flows_len 0
qdisc noqueue 0: dev br-lan root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev eth1.1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc cake 8025: dev eth0.2 root refcnt 2 bandwidth 25Mbit precedence dual-srchost nat nowash no-ack-filter split-gso rtt 100.0ms noatm overhead 44
 Sent 167553 bytes 775 pkt (dropped 0, overlimits 92 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 8768b of 4Mb
 capacity estimate: 25Mbit
 min/max network layer size:           28 /    1500
 min/max overhead-adjusted size:       72 /    1544
 average network hdr offset:           13

                  Tin 0        Tin 1        Tin 2        Tin 3        Tin 4        Tin 5        Tin 6        Tin 7
  thresh         25Mbit    21875Kbit    19140Kbit    16748Kbit    14654Kbit    12822Kbit    11219Kbit     9817Kbit
  target          5.0ms        5.0ms        5.0ms        5.0ms        5.0ms        5.0ms        5.0ms        5.0ms
  interval      100.0ms      100.0ms      100.0ms      100.0ms      100.0ms      100.0ms      100.0ms      100.0ms
  pk_delay        418us          0us          0us          0us          0us        204us         10us          6us
  av_delay         53us          0us          0us          0us          0us          5us          0us          0us
  sp_delay         16us          0us          0us          0us          0us          5us          0us          0us
  backlog            0b           0b           0b           0b           0b           0b           0b           0b
  pkts              742            0            0            0            0           27            4            2
  bytes          150058            0            0            0            0        16539          872           84
  way_inds            0            0            0            0            0            0            0            0
  way_miss           97            0            0            0            0            4            2            1
  way_cols            0            0            0            0            0            0            0            0
  drops               0            0            0            0            0            0            0            0
  marks               0            0            0            0            0            0            0            0
  ack_drop            0            0            0            0            0            0            0            0
  sp_flows            2            0            0            0            0            0            2            1
  bk_flows            1            0            0            0            0            0            0            0
  un_flows            0            0            0            0            0            0            0            0
  max_len          2189            0            0            0            0         1392          264           42
  quantum           762          667          584          511          447          391          342          300

qdisc ingress ffff: dev eth0.2 parent ffff:fff1 ----------------
 Sent 276682 bytes 1171 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wlan1 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc noqueue 0: dev wlan0 root refcnt 2
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
qdisc cake 8026: dev ifb4eth0.2 root refcnt 2 bandwidth 90Mbit besteffort triple-isolate nonat wash no-ack-filter split-gso rtt 100.0ms noatm overhead 44
 Sent 293076 bytes 1171 pkt (dropped 0, overlimits 162 requeues 0)
 backlog 0b 0p requeues 0
 memory used: 17856b of 4500000b
 capacity estimate: 90Mbit
 min/max network layer size:           46 /    1500
 min/max overhead-adjusted size:       90 /    1544
 average network hdr offset:           14

                  Tin 0
  thresh         90Mbit
  target          5.0ms
  interval      100.0ms
  pk_delay        107us
  av_delay         22us
  sp_delay          5us
  backlog            0b
  pkts             1171
  bytes          293076
  way_inds            0
  way_miss          109
  way_cols            0
  drops               0
  marks               0
  ack_drop            0
  sp_flows            1
  bk_flows            1
  un_flows            0
  max_len          1514
  quantum          1514

Blockquote try tagging all packets at CS0 all UDP at CS4 and UDP from your game machine at CS6. Do the rules in that order.

I'm going to try that because some times with just background processes my ping would still spike, I originally thought that was due to an overloaded hop somewhere, but my ISPs have been checking and saw no problem.

is the command to tag everything like this:

iptables -t mangle -A dscp_mark --set-dscp-class CS0

Yes that's the command... I'm looking up cake diffserv4 you might want to tag the "other UDP" something different from CS4... Hold on.

Ok based on the manual

I suggest the other UDP tagged AF41

2 Likes

There is no traffic in the high precedence tins yet....