Skip to content

Instantly share code, notes, and snippets.

@Bert-Proesmans
Last active January 25, 2024 06:18
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save Bert-Proesmans/c411825380af25facba6070921eb08b0 to your computer and use it in GitHub Desktop.
Save Bert-Proesmans/c411825380af25facba6070921eb08b0 to your computer and use it in GitHub Desktop.
Mikrotik Routerboard QOS script
# Creation Date: November 3, 2018
:local Version "2.0"
:local LASTUPDATE "05/10/2019"
# Tested with RouterOS 6.43.4
#
# Mikrotik script to implement QoS on internet connections.
# The script makes use of Address Lists, Firewall rules (Mangle) for connection tagging, and Queue Trees.
# The script will remove applied rules from previous runs before applying.
#
# All data rates are expressed in bits/second.
# All accumulated data is expressed in bytes.
# You can use k,M,G to shorthand kilo (1000), mega(1000000) and giga(1000000000).
#
# Example usage:
# 1. Change the arguments indicated by '##CHANGEME';
# 2. Upload the script to RouterOS hardware through sftp;
# 3. The script is automatically executed on connection close;
# 3.1 Check the logs for possible errors
# WARN; Most of the time this approach doesn't work because of unknown reasons..
# 4. You can manually execute the script by running the '/import filename=XX' command inside the terminal.
# 5. Update your Firewall default accept rules to not immediately FastTrack the connection. Manipulation rules
# are not applied on FastTracked connections and removing the flag is not possible.
# I have 2 accept rules before FastTrack-ing:
# * Accept when Connection-bytes: 0-2M (Little traffic)
# * Accept when Connection-rate: 0-150k (Slow traffic)
#
# NOTE(18/06/2019); When using '/import' command, make sure to use the FULL PATH. Check '/file print' for
# exact information about files on your Routerboard system. Tab completion works as well.
#
# WARN(23/06/2019): UPDATE YOUR FILTER RULES to keep 'normal' accepting data while under the TRAFFIC_BIG threshold (eg 2M).
# To achieve this your can duplicate the rule with comment `defconf: accept established,related, untracked` with `Connection Bytes`
# set to 0-2M.
# The FastTrack rule MUST come after the mentioned one.
# The default non-FastTrack rule MUST come after the FastTrack rule.
#
# NOTE(04/10/2019): Correctly filtering VOIP traffic is réééally tough!
#
# This is the interface to run the QOS on. This is the edge interface before traffic leaves your MikroTik towards the internet.
# It can be a physical interface, or a virtual interface like PPOE.
## CHANGEME
:local QOSINTERFACE "Scarlet PPoE"
# The interface that bridges the ports of your local network.
## CHANGEME
:local LANBRIDGE "bridge LAN"
# Adjust speeds to match 90-98% of the download and upload rate for the outbound connection.
## CHANGEME
:local PCQDOWNLOAD "40M"
:local PCQUPLOAD "6M"
## This is the name of this script. Use it to distinguish it from other QOS scripts running.
## This is used as identifier within comments, can be changed if required.
:local TREE "SPPP"
## Priority levels
# A = realtime priority
# This includes CS5 and up
# LEVEL_A_UP - LEVEL_A_DOWN
# B = normal priority
# This includes CS1 and up
# LEVEL_B_UP - LEVEL_B_DOWN
# C = bulk priority
# This includes best effort and high bandwidth connections
# LEVEL_C_UP - LEVEL_C_DOWN
###############################################################################
# Collect IP ranges for important services ##
#
###############################################################################
/ipv6 firewall address-list
# Reset
:foreach i in=[find list="games"] do={
remove $i
}
add address=2801:1b:6000::/48 comment="LoL (Europe)" list=games
add address=2a04:82c0::/29 comment="LoL (Europe)" list=games
add address=2804:3ec0::/32 comment="LoL (Europe)" list=games
# NOTE; IPV4
/ip firewall address-list
# Reset
:foreach i in=[find list="games"] do={
remove $i
}
# Riot League of Legends
# Ports
# 5000 - 5500 UDP
# 8393 - 8400 TCP
# 80 TCP
# 443 TCP
# AS6507
add address=8.23.24.0/23 comment="League of Legends West" list=games
add address=43.229.64.0/22 comment="League of Legends West" list=games
add address=43.229.64.0/24 comment="League of Legends West" list=games
add address=43.229.65.0/24 comment="League of Legends West" list=games
add address=43.229.66.0/24 comment="League of Legends West" list=games
add address=43.229.67.0/24 comment="League of Legends West" list=games
add address=45.7.36.0/24 comment="League of Legends West" list=games
add address=45.7.39.0/24 comment="League of Legends West" list=games
add address=45.250.208.0/22 comment="League of Legends West" list=games
add address=66.151.33.0/24 comment="League of Legends West" list=games
add address=103.219.128.0/22 comment="League of Legends West" list=games
add address=103.240.224.0/24 comment="League of Legends West" list=games
add address=103.240.225.0/24 comment="League of Legends West" list=games
add address=103.240.226.0/23 comment="League of Legends West" list=games
add address=104.160.128.0/19 comment="League of Legends West" list=games
add address=104.160.128.0/20 comment="League of Legends West" list=games
add address=104.160.134.0/24 comment="League of Legends West" list=games
add address=104.160.135.0/24 comment="League of Legends West" list=games
add address=104.160.136.0/24 comment="League of Legends West" list=games
add address=104.160.139.0/24 comment="League of Legends West" list=games
add address=104.160.141.0/24 comment="League of Legends West" list=games
add address=104.160.142.0/24 comment="League of Legends West" list=games
add address=104.160.143.0/24 comment="League of Legends West" list=games
add address=104.160.144.0/24 comment="League of Legends West" list=games
add address=104.160.145.0/24 comment="League of Legends West" list=games
add address=104.160.146.0/24 comment="League of Legends West" list=games
add address=104.160.147.0/24 comment="League of Legends West" list=games
add address=104.160.148.0/24 comment="League of Legends West" list=games
add address=104.160.149.0/24 comment="League of Legends West" list=games
add address=104.160.152.0/21 comment="League of Legends West" list=games
add address=104.160.153.0/24 comment="League of Legends West" list=games
add address=104.160.154.0/24 comment="League of Legends West" list=games
add address=104.160.155.0/24 comment="League of Legends West" list=games
add address=104.160.156.0/24 comment="League of Legends West" list=games
add address=110.45.191.0/24 comment="League of Legends West" list=games
add address=117.52.75.0/24 comment="League of Legends West" list=games
add address=117.52.76.0/22 comment="League of Legends West" list=games
add address=117.52.101.0/24 comment="League of Legends West" list=games
add address=138.0.12.0/22 comment="League of Legends West" list=games
add address=138.0.12.0/24 comment="League of Legends West" list=games
add address=138.0.13.0/24 comment="League of Legends West" list=games
add address=138.0.14.0/24 comment="League of Legends West" list=games
add address=138.0.15.0/24 comment="League of Legends West" list=games
add address=162.249.72.0/22 comment="League of Legends West" list=games
add address=162.249.76.0/22 comment="League of Legends West" list=games
add address=162.249.79.0/24 comment="League of Legends West" list=games
add address=182.162.120.0/21 comment="League of Legends West" list=games
add address=185.40.64.0/22 comment="League of Legends West" list=games
add address=192.64.168.0/24 comment="League of Legends West" list=games
add address=192.64.169.0/24 comment="League of Legends West" list=games
add address=192.64.170.0/24 comment="League of Legends West" list=games
add address=192.64.171.0/24 comment="League of Legends West" list=games
add address=192.64.172.0/24 comment="League of Legends West" list=games
add address=192.64.173.0/24 comment="League of Legends West" list=games
add address=192.64.174.0/24 comment="League of Legends West" list=games
add address=192.64.175.0/24 comment="League of Legends West" list=games
# Steam ports
# Ports
# 27015-27030 UDP+TCP
# 80 TCP
# 443 TCP
# AS32590
add address=146.66.152.0/23 comment="Steam Europe" list=games
add address=146.66.154.0/24 comment="Steam Europe" list=games
add address=146.66.155.0/24 comment="Steam Europe" list=games
add address=146.66.156.0/23 comment="Steam Europe" list=games
add address=146.66.158.0/23 comment="Steam Europe" list=games
add address=185.25.180.0/23 comment="Steam Europe" list=games
add address=185.25.182.0/24 comment="Steam Europe" list=games
add address=185.25.183.0/24 comment="Steam Europe" list=games
add address=155.133.224.0/23 comment="Steam Europe" list=games
add address=155.133.227.0/24 comment="Steam Europe" list=games
add address=155.133.228.0/23 comment="Steam Europe" list=games
add address=155.133.230.0/23 comment="Steam Europe" list=games
add address=155.133.232.0/24 comment="Steam Europe" list=games
add address=155.133.233.0/24 comment="Steam Europe" list=games
add address=155.133.234.0/24 comment="Steam Europe" list=games
add address=155.133.235.0/24 comment="Steam Europe" list=games
add address=155.133.236.0/23 comment="Steam Europe" list=games
add address=155.133.238.0/24 comment="Steam Europe" list=games
add address=155.133.239.0/24 comment="Steam Europe" list=games
add address=155.133.240.0/23 comment="Steam Europe" list=games
add address=155.133.242.0/23 comment="Steam Europe" list=games
add address=155.133.244.0/24 comment="Steam Europe" list=games
add address=155.133.245.0/24 comment="Steam Europe" list=games
add address=155.133.246.0/23 comment="Steam Europe" list=games
add address=155.133.248.0/24 comment="Steam Europe" list=games
add address=155.133.249.0/24 comment="Steam Europe" list=games
add address=155.133.250.0/24 comment="Steam Europe" list=games
add address=155.133.252.0/24 comment="Steam Europe" list=games
add address=155.133.253.0/24 comment="Steam Europe" list=games
add address=155.133.254.0/24 comment="Steam Europe" list=games
add address=155.133.255.0/24 comment="Steam Europe" list=games
# Blizzard (Overwatch)
# Ports
# ANY? UDP+TCP
# 80 TCP
# 443 TCP
# AS57976
add address=5.42.160.0/20 comment="Blizzard Europe" list=games
add address=5.42.176.0/20 comment="Blizzard Europe" list=games
add address=37.244.15.0/24 comment="Blizzard Europe" list=games
add address=37.244.16.0/24 comment="Blizzard Europe" list=games
add address=37.244.17.0/24 comment="Blizzard Europe" list=games
add address=37.244.18.0/24 comment="Blizzard Europe" list=games
add address=37.244.19.0/24 comment="Blizzard Europe" list=games
add address=37.244.20.0/24 comment="Blizzard Europe" list=games
add address=37.244.21.0/24 comment="Blizzard Europe" list=games
add address=37.244.22.0/24 comment="Blizzard Europe" list=games
add address=37.244.23.0/24 comment="Blizzard Europe" list=games
add address=37.244.24.0/24 comment="Blizzard Europe" list=games
add address=37.244.25.0/24 comment="Blizzard Europe" list=games
add address=37.244.26.0/24 comment="Blizzard Europe" list=games
add address=37.244.27.0/24 comment="Blizzard Europe" list=games
add address=37.244.28.0/24 comment="Blizzard Europe" list=games
add address=37.244.29.0/24 comment="Blizzard Europe" list=games
add address=37.244.30.0/23 comment="Blizzard Europe" list=games
add address=37.244.32.0/24 comment="Blizzard Europe" list=games
add address=37.244.33.0/24 comment="Blizzard Europe" list=games
add address=37.244.34.0/24 comment="Blizzard Europe" list=games
add address=37.244.35.0/24 comment="Blizzard Europe" list=games
add address=37.244.36.0/23 comment="Blizzard Europe" list=games
add address=37.244.38.0/24 comment="Blizzard Europe" list=games
add address=37.244.40.0/22 comment="Blizzard Europe" list=games
add address=37.244.44.0/22 comment="Blizzard Europe" list=games
add address=37.244.48.0/24 comment="Blizzard Europe" list=games
add address=37.244.49.0/24 comment="Blizzard Europe" list=games
add address=37.244.50.0/24 comment="Blizzard Europe" list=games
add address=37.244.52.0/23 comment="Blizzard Europe" list=games
add address=37.244.54.0/24 comment="Blizzard Europe" list=games
add address=37.244.55.0/24 comment="Blizzard Europe" list=games
add address=37.244.56.0/23 comment="Blizzard Europe" list=games
add address=37.244.58.0/23 comment="Blizzard Europe" list=games
add address=37.244.60.0/22 comment="Blizzard Europe" list=games
add address=185.60.112.0/23 comment="Blizzard Europe" list=games
add address=185.60.114.0/23 comment="Blizzard Europe" list=games
add address=137.221.64.0/19 comment="Blizzard Europe" list=games
add address=137.221.64.0/24 comment="Blizzard Europe" list=games
add address=137.221.68.0/24 comment="Blizzard Europe" list=games
add address=137.221.69.0/24 comment="Blizzard Europe" list=games
add address=137.221.70.0/24 comment="Blizzard Europe" list=games
add address=137.221.71.0/24 comment="Blizzard Europe" list=games
add address=137.221.72.0/24 comment="Blizzard Europe" list=games
add address=137.221.73.0/24 comment="Blizzard Europe" list=games
add address=137.221.74.0/24 comment="Blizzard Europe" list=games
add address=137.221.75.0/24 comment="Blizzard Europe" list=games
add address=137.221.76.0/24 comment="Blizzard Europe" list=games
add address=137.221.77.0/24 comment="Blizzard Europe" list=games
add address=137.221.78.0/24 comment="Blizzard Europe" list=games
add address=137.221.79.0/24 comment="Blizzard Europe" list=games
add address=137.221.80.0/24 comment="Blizzard Europe" list=games
add address=137.221.81.0/24 comment="Blizzard Europe" list=games
add address=137.221.82.0/24 comment="Blizzard Europe" list=games
add address=137.221.83.0/24 comment="Blizzard Europe" list=games
add address=137.221.84.0/24 comment="Blizzard Europe" list=games
add address=137.221.85.0/24 comment="Blizzard Europe" list=games
add address=137.221.86.0/24 comment="Blizzard Europe" list=games
add address=137.221.96.0/22 comment="Blizzard Europe" list=games
add address=137.221.100.0/22 comment="Blizzard Europe" list=games
add address=137.221.104.0/22 comment="Blizzard Europe" list=games
###############################################################################
# Mangle Rules to tag traffic
#
# DSCP conversion table
# NOTE: Not all DS field values are used!
# -> Try to fill the list with actually used tags. Also because they override any other connection
# marking!
#
# | DSCP Name | DS Field Value (Dec) | IP Precedence (Description)
# -----------------------------------------------------------------------
# | CS0 | 0 | 0: Best Effort
# | CS1, AF11-13 | 8,10,12,14 | 1: Priority (Class 1)
# | CS2, AF21-23 | 16,18,20,22 | 2: Immediate (Class 2)
# | CS3, AF31-33 | 24,26,28,30 | 3: Flash - mainly used for voice signaling(Class 3)
# | CS4, AF41-43 | 32,34,36,38 | 4: Flash Override (Class 4)
# | CS5, EF | 40,46 | 5: Critical - mainly used for voice RTP
# | CS6 | 48 | 6: Internetwork Control
# | CS7 | 56 | 7: Network Control
###############################################################################
# NOTE; Connection-rate and Connection-bytes are reset. Care must be taken to not assign higher priority when a lower priority has been assigned!
# NOTE; The rules are mostly applied in pre- and postrouting, so connections to/from the router itself are subject as well!
/ip firewall mangle
# Reset
:foreach i in=[find where comment~("autoconf:" . $TREE)] do={
remove $i
}
add action=log chain=notes comment=("autoconf:" . $TREE . " Start of QoS tree. Last update on " . $LASTUPDATE)
# WARN; Connection-rate is a value updated per second. Make sure to prevent falling back from *-big to * connections doesn't happen!
# Seperate rules need to be created to transform the general marker back into the specific mark!
add action=mark-connection chain=prerouting connection-mark="OTHER_BIG" new-connection-mark="BIG_MARKER" comment=("autoconf:" . $TREE . " BIG PERSISTENT")
add action=mark-connection chain=prerouting connection-mark="HTTP_BIG" new-connection-mark="BIG_MARKER" comment=("autoconf:" . $TREE . " BIG PERSISTENT")
# Mark all leftover TCP traffic.
add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="OTHER" protocol=tcp comment=("autoconf:" . $TREE . " OTHER")
# Mark all leftover UDP traffic.
add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="OTHER" protocol=udp comment=("autoconf:" . $TREE . " OTHER")
# Mark VOIP and VOIP like traffic. WARN; This is icky ground, because a lot of different traffic could be caught with these rules (like torrenting)!
## RTP (port range too broad, so it's kept as example)
# add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="VOIP" connection-rate=0-100k port=10000-20000 protocol=udp comment=("autoconf:" . $TREE . " VOIP")
## Discord
add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="VOIP" connection-rate=0-100k port=55000-65000 protocol=udp comment=("autoconf:" . $TREE . " VOIP")
# NOTE; Validate general BIG_MARKER back into subcategories.
add action=mark-connection chain=prerouting connection-mark="BIG_MARKER" new-connection-mark="OTHER_BIG" connection-rate=0-100k port=55000-65000 protocol=udp comment=("autoconf:" . $TREE . " VOIP")
# Mark all new HTTP(s) connections with "HTTP" if they have not previously been marked as "HTTP_BIG".
# NOTE; This HTTP mark also tries to target QUIC traffic (UDP on HTTP common ports)
add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="HTTP" protocol=tcp port=80,81,443,444,554,8000,8080,8409 comment=("autoconf:" . $TREE . " HTTP")
add action=mark-connection chain=prerouting connection-mark="!BIG_MARKER" new-connection-mark="HTTP" protocol=udp port=80,81,443,444,554,8000,8080,8409 comment=("autoconf:" . $TREE . " QUIC")
# NOTE; Validate general BIG_MARKER back into subcategories
add action=mark-connection chain=prerouting connection-mark="BIG_MARKER" new-connection-mark="HTTP_BIG" protocol=tcp port=80,81,443,444,554,8000,8080,8409 comment=("autoconf:" . $TREE . " HTTP")
add action=mark-connection chain=prerouting connection-mark="BIG_MARKER" new-connection-mark="HTTP_BIG" protocol=udp port=80,81,443,444,554,8000,8080,8409 comment=("autoconf:" . $TREE . " QUIC")
# Catch big traffic
# ..everything non-tagged above 1MB.
add action=mark-connection chain=prerouting connection-mark="OTHER" new-connection-mark="OTHER_BIG" connection-bytes=1M-0 protocol=tcp comment=("autoconf:" . $TREE . " OTHER BIG")
# ..VOIP traffic that keeps a sustained rate above 200kb after 1MB (~4 seconds).
add action=mark-connection chain=prerouting connection-mark="VOIP" new-connection-mark="OTHER_BIG" connection-rate=200k-0 connection-bytes=1M-0 protocol=udp comment=("autoconf:" . $TREE . " OTHER BIG")
# ..HTTP connections above 2MB: heavy web resources.
# NOTE; HTTP1/1.1 clients open multiple connections for a single web page, it's hard to punish heavy webpages this way!
# HTTP2/3(QUIC) attempt to multiplex requests across already open connections, so traffic shaping by connection becomes easier for us.
add action=mark-connection chain=prerouting connection-mark="HTTP" new-connection-mark="HTTP_BIG" connection-bytes=2M-0 protocol=tcp comment=("autoconf:" . $TREE . " HTTP BIG")
add action=mark-connection chain=prerouting connection-mark="HTTP" new-connection-mark="HTTP_BIG" connection-bytes=2M-0 protocol=udp comment=("autoconf:" . $TREE . " QUIC")
# Defined game servers.
# NOTE; Override connection-mark. Only when the filter conditions can be expressed to match the traffic exactly!
add action=mark-connection chain=prerouting new-connection-mark="GAMES" dst-address-list=games comment=("autoconf:" . $TREE . " GAMES")
# DNS requests.
# WARN; Mark in pre- and postrouting because DNS is sent out by the router (itself) too.
# NOTE; Override connection-mark.
add action=mark-connection chain=prerouting new-connection-mark="DNS" protocol=udp port=53 comment=("autoconf:" . $TREE . " DNS")
add action=mark-connection chain=postrouting new-connection-mark="DNS" protocol=udp port=53 comment=("autoconf:" . $TREE . " DNS")
# ICMP
# NOTE; Override connection-mark.
add action=mark-connection chain=prerouting new-connection-mark="ICMP" protocol=icmp comment=("autoconf:" . $TREE . " ICMP")
add action=mark-connection chain=postrouting new-connection-mark="ICMP" protocol=icmp comment=("autoconf:" . $TREE . " ICMP")
# WINBOX
# The connection to the router on the specified port, which should get IP control priority.
# NOTE; Override connection-mark.
add action=mark-connection chain=input new-connection-mark="ICMP" protocol=tcp port=8291 comment=("autoconf:" . $TREE . " WINBOX")
# Set priority tags inside the packets.
add action=set-priority chain=postrouting connection-mark="VOIP" new-priority=6 comment=("autoconf:" . $TREE)
add action=change-dscp chain=postrouting connection-mark="VOIP" new-dscp=48 comment=("autoconf:" . $TREE)
add action=set-priority chain=postrouting connection-mark="DNS" new-priority=6 comment=("autoconf:" . $TREE)
add action=change-dscp chain=postrouting connection-mark="DNS" new-dscp=48 comment=("autoconf:" . $TREE)
add action=set-priority chain=postrouting connection-mark="ICMP" new-priority=6 comment=("autoconf:" . $TREE)
add action=change-dscp chain=postrouting connection-mark="ICMP" new-dscp=48 comment=("autoconf:" . $TREE)
## ACK Packets
# NOTE; ACKs are just flagged packets on a TCP connection. No connection-mark can be set/used.
add action=set-priority chain=postrouting new-priority=6 protocol=tcp tcp-flags=ack packet-size=0-123 comment=("autoconf:" . $TREE)
add action=change-dscp chain=postrouting new-dscp=48 protocol=tcp tcp-flags=ack packet-size=0-123 comment=("autoconf:" . $TREE)
## DSCP comes from the client indicating priority. The provided information will always overrule any other configuration!
add action=set-priority chain=postrouting dscp=46 new-priority=6 comment=("autoconf:" . $TREE)
add action=set-priority chain=postrouting dscp=48 new-priority=6 comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting protocol=tcp tcp-flags=ack new-packet-mark="ACK_D" packet-size=0-123 in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting protocol=tcp tcp-flags=ack new-packet-mark="ACK_U" packet-size=0-123 in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="DNS" new-packet-mark="DNS_D" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="DNS" new-packet-mark="DNS_U" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="ICMP" new-packet-mark="ICMP_D" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="ICMP" new-packet-mark="ICMP_U" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="VOIP" new-packet-mark="VOIP_D" packet-size=0-260 in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="VOIP" new-packet-mark="VOIP_U" packet-size=0-260 in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="GAMES" new-packet-mark="GAMES_D" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="GAMES" new-packet-mark="GAMES_U" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="HTTP" new-packet-mark="HTTP_D" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="HTTP" new-packet-mark="HTTP_U" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="HTTP_BIG" new-packet-mark="HTTP_D_BIG" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="HTTP_BIG" new-packet-mark="HTTP_U_BIG" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="OTHER" new-packet-mark="OTHER_D" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting connection-mark="OTHER" new-packet-mark="OTHER_U" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
# Give packet lowest priority if no othe rule matched. (This includes BIG_MARKER connections!)
add action=mark-packet chain=prerouting new-packet-mark="OTHER_D_BIG" in-interface=($QOSINTERFACE) passthrough=no comment=("autoconf:" . $TREE)
add action=mark-packet chain=prerouting new-packet-mark="OTHER_U_BIG" in-interface=($LANBRIDGE) passthrough=no comment=("autoconf:" . $TREE)
###############################################################################
# HTB Queue Tree is a unidirectional queue.
# The queue works on outbound interfaces, so eth1 (public interface) is for upload
# and eth2 (private interface) is for download.
#
# Notes:
# priority means 'drop packets' WHEN needed.
# When limit-at=0 priority starts when max-limit is reached.
# When limit-at=123 priority starts when limit-at is reached.
#
# The priority option applies to CHILDREN not parents. Parent is for setting
# overall limits. Therefore use limit-at and max-limit on the children if
# you want more granularity.
#
# max-limit must always be set or priority will not happen.
#
# Tips for TCP (not VoIP) SOHO network:
# limit-at = Total bandwidth / max hosts
# max-limit = Total bandwidth / min hosts
#
###############################################################################
/queue type
# Reset all custom queue types (even types NOT created by this script!)
:foreach i in=[find] do= {
:do {
remove $i
} on-error={}
}
# Red queues shape bittorrent traffic better (high amount of connections with spiked start)
add kind=red name=red-download red-avg-packet=1500 red-burst=10 red-limit=40 red-max-threshold=40
add kind=red name=red-upload red-avg-packet=1500 red-burst=5 red-limit=20 red-max-threshold=20 red-min-threshold=5
add kind=sfq name=default-sfq sfq-perturb=5 sfq-allot=1514
# Update default PCQ queues for per IP
set [find where name="pcq-download-default"] pcq-classifier=dst-address pcq-rate=($PCQDOWNLOAD) pcq-total-limit=25000
set [find where name="pcq-upload-default"] pcq-classifier=src-address pcq-rate=($PCQUPLOAD) pcq-total-limit=25000
##
/queue tree
# Reset
:foreach i in=[find where (name~("^".$TREE) || parent~("^".$TREE))] do={
remove $i
}
add name=($TREE . "_TOTAL_UP") parent=($QOSINTERFACE) max-limit=($PCQUPLOAD) queue=default
add name=($TREE . "_TOTAL_DOWN") parent=($LANBRIDGE) max-limit=($PCQDOWNLOAD) queue=default
add name="ACK_U" parent=($TREE . "_TOTAL_UP") packet-mark="ACK_U" limit-at=1500k max-limit=($PCQUPLOAD) priority=1 queue=default
add name="ACK_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="ACK_D" limit-at=4M max-limit=($PCQDOWNLOAD) priority=1 queue=default
add name="VOIP_U" parent=($TREE . "_TOTAL_UP") packet-mark="VOIP_U" limit-at=1500k max-limit=($PCQUPLOAD) priority=2 queue=default
add name="VOIP_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="VOIP_D" limit-at=4M max-limit=($PCQDOWNLOAD) priority=2 queue=default
add name="GAMES_U" parent=($TREE . "_TOTAL_UP") packet-mark="GAMES_U" limit-at=1500k max-limit=($PCQUPLOAD) priority=3 queue=default-sfq
add name="GAMES_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="GAMES_D" limit-at=4M max-limit=($PCQDOWNLOAD) priority=3 queue=default
add name="DNS_U" parent=($TREE . "_TOTAL_UP") packet-mark="DNS_U" limit-at=1500k max-limit=($PCQUPLOAD) priority=4 queue=default
add name="DNS_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="DNS_D" limit-at=4M max-limit=($PCQDOWNLOAD) priority=4 queue=default
add name="ICMP_U" parent=($TREE . "_TOTAL_UP") packet-mark="ICMP_U" limit-at=1500k max-limit=($PCQUPLOAD) priority=5 queue=default
add name="ICMP_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="ICMP_D" limit-at=4M max-limit=($PCQDOWNLOAD) priority=5 queue=default
add name="HTTP_U" parent=($TREE . "_TOTAL_UP") packet-mark="HTTP_U" limit-at=100k max-limit=($PCQUPLOAD) priority=6 queue=pcq-upload-default
add name="HTTP_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="HTTP_D" limit-at=250k max-limit=($PCQDOWNLOAD) priority=6 queue=pcq-download-default
add name="HTTP_U_BIG" parent=($TREE . "_TOTAL_UP") packet-mark="HTTP_U_BIG" limit-at=100k max-limit=($PCQUPLOAD) priority=7 queue=pcq-upload-default
add name="HTTP_D_BIG" parent=($TREE . "_TOTAL_DOWN") packet-mark="HTTP_D_BIG" limit-at=250k max-limit=($PCQDOWNLOAD) priority=7 queue=pcq-download-default
add name="OTHER_U" parent=($TREE . "_TOTAL_UP") packet-mark="OTHER_U" limit-at=100k max-limit=($PCQUPLOAD) priority=8 queue=red-upload
add name="OTHER_D" parent=($TREE . "_TOTAL_DOWN") packet-mark="OTHER_D" limit-at=250k max-limit=($PCQDOWNLOAD) priority=8 queue=red-download
add name="OTHER_U_BIG" parent=($TREE . "_TOTAL_UP") packet-mark="OTHER_U_BIG" limit-at=100k max-limit=($PCQUPLOAD) priority=8 queue=red-upload
add name="OTHER_D_BIG" parent=($TREE . "_TOTAL_DOWN") packet-mark="OTHER_D_BIG" limit-at=250k max-limit=($PCQDOWNLOAD) priority=8 queue=red-download
@vuducdong
Copy link

Will you have a new update for 2020 or 2021? Thank for sharing.

@Bert-Proesmans
Copy link
Author

Will you have a new update for 2020 or 2021? Thank for sharing.

I reread this file some weeks ago and noticed that the configuration isn't 100% correct with its assumptions. I'll certainly revisit at a later date when i'll do an iteration on my internal network setup.

@vuducdong
Copy link

Will you have a new update for 2020 or 2021? Thank for sharing.

I reread this file some weeks ago and noticed that the configuration isn't 100% correct with its assumptions. I'll certainly revisit at a later date when i'll do an iteration on my internal network setup.

OK, I'm looking forward to seeing a more perfect version.

@mrfalcon93
Copy link

Interesting, I`m waiting for last update too
good job 👍

@santasimos
Copy link

Hello guys, im trying to import this script but i cant seem to figure out how.
I got the file with /tool fetch but i cant import

Can anybody help me?
thnx

@machl
Copy link

machl commented Jan 23, 2021

@santasimos this should work as well:
Go to WinBox -> System -> Scripts -> create New Script -> copy paste code to the Source field -> Run Script

@Bert-Proesmans
Copy link
Author

Hello guys, im trying to import this script but i cant seem to figure out how.
I got the file with /tool fetch but i cant import

Can anybody help me?
thnx

WARN; This is not really designed to "run and be done". You'll have to understand a bit about firewall filter, firewall mangle, and queue trees.

Are you using Winbox?

  1. Upload script; Tab "Files" > button "Upload.."
  2. Open terminal; Tab "New Terminal"
  3. Run script: /import filename=[filename here]

Tab completion should work for filenames in step 3. Take note that some rules require non-fasttracked traffic so you'll have to change any fasttracking rules you have in the firewall (Tab IP > button Firewall) section. I tried to explain it inside the script comments.

@santasimos
Copy link

Hello guys, im trying to import this script but i cant seem to figure out how.
I got the file with /tool fetch but i cant import
Can anybody help me?
thnx

WARN; This is not really designed to "run and be done". You'll have to understand a bit about firewall filter, firewall mangle, and queue trees.

Are you using Winbox?

  1. Upload script; Tab "Files" > button "Upload.."
  2. Open terminal; Tab "New Terminal"
  3. Run script: /import filename=[filename here]

Tab completion should work for filenames in step 3. Take note that some rules require non-fasttracked traffic so you'll have to change any fasttracking rules you have in the firewall (Tab IP > button Firewall) section. I tried to explain it inside the script comments.

Yes i'm using winbox.I tried everything.
i did reset config and tried to import, i downgrade my firmware to 6.43.4,
I can see the script on tab "Files" but when Im trying to restore an error comes file not found
I have the RB2011UAS-2HnD

@Bert-Proesmans
Copy link
Author

@santasimos you're probably not using the full path to the upload script.
The approach provided by @machi is a bit more intuitive so that's worth a try.

Each line is basically a command so you could also copy-paste the parts you need inside the terminal window itself. Please, do make a backup first if this is not a test setup.

@santasimos
Copy link

santasimos commented Jan 23, 2021

@santasimos you're probably not using the full path to the upload script.
The approach provided by @machi is a bit more intuitive so that's worth a try.

Each line is basically a command so you could also copy-paste the parts you need inside the terminal window itself. Please, do make a backup first if this is not a test setup.

Well i tried that also but nothing happens
So now i did a reset config and i'm adding peace by peace the script maybe its the only way
Thanks for your help

@stefan-matic
Copy link

Model: CRS125-24G-1S
Firmware: 6.48
Firmware type: ar9344

Uploaded the script via winbox and executed in terminal:

/import file-name=gaming-qos.rsc
expected end of command (line 79 column 25)

Any idea if it's because of the new version or should I try running the script differently? The sftp method didn't work for me. I also don't have any fasttrack rules.

@Bert-Proesmans
Copy link
Author

Any idea if it's because of the new version or should I try running the script differently? The sftp method didn't work for me. I also don't have any fasttrack rules.

Not sure. It's hard to pinpoint exactly what goes wrong. If there are line ending issues the line number reported isn't even correct.
A tedious but workable way is to run the commands around line 79 manually. Maybe there have been scripting changes introduced in newer RouterOS versions, but that's just a guess at this point.

@iahmedelbarbary
Copy link

Thanks for this script i readed it well, I took many rules from your script, work 💯 Thanks
I have 3 questions
1- Dose src address = in interface ?, if i dont use in interface and replaced with src address is that ok
2- Should i add Max Limit in Parents ?
3- I want your openion about select in mark packet rules: Mark packet= no-mark
Is this way is perfect ? What is ur openion about selecting no-mark?

@Bert-Proesmans
Copy link
Author

Bert-Proesmans commented Feb 12, 2021

Hi @iahmedelbarbary! You chose the best way to learn.

1- Dose src address = in interface ?, if i dont use in interface and replaced with src address is that ok

You can substitute the src address and subnet with the interface in Mangle. It should work fine.

2- Should i add Max Limit in Parents ?

Depends on your use case. I've set the Max Limit for this configuration at the max bandwidth. Keep in mind that this configuration is written for a very simple use case; 1 WAN interface and 4 bridged LAN interfaces.
Say for example you want to use 2 WAN interfaces or split up your NATted internal network, the existence of a set max-limit and which value will be important.

3- I want your openion about select in mark packet rules: Mark packet= no-mark

In a technical sense; no-mark is also a mark to indicate packets that were not specifically marked. If your intention is to mark no-marked packets that would be wasting resources. A queue tree record accepts no-mark as a filter.
Considering that you're asking about marking packets versus marking connections; marking packets individually becomes a fairly CPU intensive process because you indicate to evaluate more data. Depending on your hardware specs and desirable bandwidth you could work with packet-marks directly without a problem.

@vuducdong
Copy link

Dear, Bert-Proesmans

how to combine this QoS with Load blancing 2 WAN (using PCC)?

Best regards,

@iahmedelbarbary
Copy link

iahmedelbarbary commented Feb 13, 2021

Hi @iahmedelbarbary! You chose the best way to learn.
Hi Bert-Proesmans Thanks for answer 🙏
No.1: is clear
No.2: i have 3 wan, Local IP TV, In for pubg game only and In from loadblance. i will post a photo about my understaning of qos, Could you see my senario and tell me if it ok or need anything?
No.3: its very clear now about mark packet, what about of using this way on mark connection like this way
add action=mark-connection chain=prerouting connection-mark=no-mark
connection-state=new dst-address-list="silkroad online"
Is this senario good or not good ?

No.4: you were very clear about order of your mangle rules all mark connection then all mark packet. what about my senario using mark routing to pubg Dst address list what is the best order for mark routing is: mark con then mark packet then mark routing ?
Or all mark conn the same and mark routing before ?
I am confused about the best order in mangle could you make it simple to me please ?

Thanks alot.

@Bert-Proesmans
Copy link
Author

@vuducdong, @iahmedelbarbary, sorry but I haven't actually done multiple uplink interfaces before.

@iahmedelbarbary on first look your queue setup looks ok.

add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address-list="silkroad online"

This marks all new connections matching your destination address list with no-mark. All new connections initially start out with "no-mark", which's indicated by an empty field underneath IP > Firewall > Connections [Connection Mark] table. Only when using connection filters you have an option called "no-mark" to make a visual distinction between empty field and configured field. Both are the same thing.
Your rule effectively does nothing, unless you desired to unmark a connection again after a mangle rule above it that might have selected too broad. (This can happen if you want to mark all connections except the ones matching 2 or more address lists, or my HTTP->HTTP_BIG rules in the config, for example.)

you were very clear about order of your mangle rules all mark connection then all mark packet. what about my senario using mark routing to pubg Dst address list what is the best order for mark routing is: mark con then mark packet then mark routing ?

I haven't used routing policies yet but you can in fact only set a "routing-mark" at 'Mangle Prerouting' (Or "Mangle Output" but let's consider we're explicitly working in forward and physical interfaces). "packet-mark" can be set in both 'Mangle Prerouting' and 'Mangle Postrouting'.

Your confusion is justified because in the limited scope of connection mangling both "routing-mark" and "connection-mark" serve the same purpose; they are simply filtering properties. Outside of the firewall; Queue Trees filter exactly on "packet-mark", routing policies filter exactly on "routing-mark" and the connection tracker makes "connection-mark" persistent.

There isn't really a conceptual hierarchy, just make sure to be consistent. I personally chose "connection-mark" because they persist. You'll have to set "routing-mark" for each packet. Keep in mind that the firewall DOES inspect each non-fast-path PACKET, we just build up our rules to spend as little time PER PACKET to keep a high bandwidth.
So for upload initiated traffic, you assign "connection-mark" filtered on DST-address, then assign "routing-mark" filtered on "connection-mark" within the same prerouting chain. Connection marking persists so the routing mark rule works for all directions of traffic. "packet-mark" can happen before or after "routing-mark" or even inside the 'Mangle Postrouting' (depends on your virtual interfaces, router services, and necessary firewall rules).

@iahmedelbarbary
Copy link

iahmedelbarbary commented Feb 16, 2021

Thanks for your answer.

@iahmedelbarbary, sorry but I haven't actually done multiple uplink interfaces before.
I think its too easy i will write rules with mark routing in the other quote
@iahmedelbarbary on first look your queue setup looks ok.

Thanks Bert realy Thanks you helped me so much i really apreciate that.

add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address-list="silkroad online"

This marks all new connections matching your destination address list with no-mark. All new connections initially start out with "no-mark", which's indicated by an empty field underneath IP > Firewall > Connections [Connection Mark] table. Only when using connection filters you have an option called "no-mark" to make a visual distinction between empty field and configured field. Both are the same thing.
Your rule effectively does nothing, unless you desired to unmark a connection again after a mangle rule above it that might have selected too broad. (This can happen if you want to mark all connections except the ones matching 2 or more address lists, or my HTTP->HTTP_BIG rules in the config, for example.)
its very clear

you were very clear about order of your mangle rules all mark connection then all mark packet. what about my senario using mark routing to pubg Dst address list what is the best order for mark routing is: mark con then mark packet then mark routing ?

I haven't used routing policies yet but you can in fact only set a "routing-mark" at 'Mangle Prerouting' (Or "Mangle Output" but let's consider we're explicitly working in forward and physical interfaces). "packet-mark" can be set in both 'Mangle Prerouting' and 'Mangle Postrouting'.
i use simple rules for this
/ip firewall mangle
add action=mark-connection chain=prerouting connection-mark=no-mark connection-state=new dst-address-list=silkroad new-connection-mark=pubg passthrough=yes src-address-list=Allowed_Users
add action=mark-packet chain=prerouting connection-mark=silkroad new-packet-mark="silkroad DW" passthrough=yes src-address-list=!Allowed_Users
add action=mark-packet chain=prerouting connection-mark=silkroad new-packet-mark="silkroad UP" passthrough=yes src-address-list=Allowed_Users
add action=mark-routing chain=prerouting comment="Add silkroad to mark rounting" connection-mark=silkroad dst-address-list=silkroad new-routing-mark=pubg passthrough=yes src-address-list=Allowed_Users
add action=accept chain=prerouting comment="Add pubg to mark rounting" connection-mark=silkroad dst-address-list=pubg src-address-list=Allowed_Users

/ip route
add comment=pubg distance=1 gateway=192.168.8.1 routing-mark=silkroad
This is the best way to mark routing i found but i have a mangle question here
You made your script mark packet down then up in all ur srcipt. do you think the best way is to let down go to queue first ?
I mean if i made up is first so up go to queue first is that good or dw first ? What is the best way

Your confusion is justified because in the limited scope of connection mangling both "routing-mark" and "connection-mark" serve the same purpose; they are simply filtering properties. Outside of the firewall; Queue Trees filter exactly on "packet-mark", routing policies filter exactly on "routing-mark" and the connection tracker makes "connection-mark" persistent.

I will read more about this

There isn't really a conceptual hierarchy, just make sure to be consistent. I personally chose "connection-mark" because they persist. You'll have to set "routing-mark" for each packet. Keep in mind that the firewall DOES inspect each non-fast-path PACKET, we just build up our rules to spend as little time PER PACKET to keep a high bandwidth.
So for upload initiated traffic, you assign "connection-mark" filtered on DST-address, then assign "routing-mark" filtered on "connection-mark" within the same prerouting chain. Connection marking persists so the routing mark rule works for all directions of traffic. "packet-mark" can happen before or after "routing-mark" or even inside the 'Mangle Postrouting' (depends on your virtual interfaces, router services, and necessary firewall rules).
This is clear

I have 4 quesions about queue tree, mangle
1-Your script says i have to make a parent for every interface un bridged or 1 parent for all interface under bridge1 So i have 5 VLAN OUT Un bridged on port OUT when select parnt is port OUT for all internet was not good under 5 VLAN
What is the best way to make it ? Does make parent for every VLAN out or use global for 1 parent download for all 5 VLAN ??
2- Does all limit at in all childs under 1 parent must be = max limit ???
3- I readed many things about {global} in queue tree, Should i use 1 Parent for all with parent=global and add all under this parent up and down or to make parent for every interface?
4- packet size, you made packet size of voip 0-260 will mark packet in queue, how could i detect packet size? Does this packet size is permanent ?? like from 0-260 is voip and 260-520 this is other thing could you explain it please ?
Thanks Bert realy you are truly professional

@Bert-Proesmans
Copy link
Author

Bert-Proesmans commented Feb 20, 2021

You made your script mark packet down then up in all ur srcipt. do you think the best way is to let down go to queue first ?
I mean if i made up is first so up go to queue first is that good or dw first ? What is the best way

Packet marks for upload and download specifically are most of the time not necessary. The reason I did it in this specific configuration is that the direction of packets into Queue Trees confused me at the beginning. The correct approach, or at least the closest approximation for this simple configuration (in MY opinion), is to mark packets without other filters than Connection Mark. I would approach this differently if I get to redo the configuration.

1-Your script says i have to make a parent for every interface un bridged or 1 parent for all interface under bridge1 So i have 5 VLAN OUT Un bridged on port OUT when select parnt is port OUT for all internet was not good under 5 VLAN
What is the best way to make it ? Does make parent for every VLAN out or use global for 1 parent download for all 5 VLAN ??

So yes, you shape download traffic with trees that have a LAN interface as a parent. In your case, you have multiple WAN interfaces. Bridging is not an option because you don't want layer-2 switching between the interfaces.
Here you want to start marking packets for upload/download specifically.
What you do in that situation is start using a tree with parent=global for download traffic, and keep separate trees on your WAN interfaces for upload shaping.
parent=global is a queue for all traffic passing through the router and is (probably) enforced before interface queues. You'll see traffic flowing through both global and interface queues. Any packet that isn't matched by a rule underneath parent=global will not be shaped. So in simple terms, mark packets normally, and have post routing rules to mark the same packets with a WAN-specific mark.
eg;

[Mangle]
action=mark-packet chain=prerouting connection-mark=PUBG new-packet-mark=PUBG passthrough=no
action=mark-packet chain=postrouting packet-mark=PUBG new-packet-mark=PUBG_WAN out-interface=PUBG passthrough=no
[Queue Tree]
add name=FOR_DOWNLOAD parent=global max-limit=1M queue=default
add name=WAN_PUBG parent=PUBG max-limit=1M queue=default
add name="PUBG_DOWN" parent=FOR_DOWNLOAD packet-mark="PUBG" limit-at=1M priority=1 <-- Traffic coming from any WAN shaped down accross all LAN interfaces
add name="PUBG_UP" parent=WAN_PUBG packet-mark="PUBG_WAN" limit-at=1M priority=1 <-- Upload traffic through PUBG WAN interface

You can then individually shape traffic per LAN interface as well, using your VLANs as a parent.

2- Does all limit at in all childs under 1 parent must be = max limit ???

Depends on your configuration and your actual bandwidths passing the router. Overprovisioning bandwidth isn't anything new, many do this. BUT, if you have maximum saturation of each type of traffic you'll want to make sure the SUM of limit-at is below max-limit of the parent. Otherwise, the lowest priority queues will become starved.

3- I readed many things about {global} in queue tree, Should i use 1 Parent for all with parent=global and add all under this parent up and down or to make parent for every interface?

See answer to the first question. Basically, parent=global can be combined with interface-specific queues. Just imagine two filters behind each other before leaving the interface.

4- packet size, you made packet size of voip 0-260 will mark packet in queue, how could i detect packet size? Does this packet size is permanent ?? like from 0-260 is voip and 260-520 this is other thing could you explain it please ?

Correctly tagging VOIP traffic is just really hard without application support. The connection (could have) variable bitrate so the packet sizes vary and the port ranges are big. What I configured was an approximation.
It's better to properly do QOS tagging within your operating system or VOIP application and use the DSCP priority fields to classify low bandwidth, low latency connections like VOIP. Sadly the OS or application configuration is not always manageable, you don't control the devices on a hotspot for example, so you can only 'have a good approximation' in this case.

Related; For low latency applications you want to prevent buffer bloat, that's why you put max-limit on WAN interfaces to a value that you're guaranteed to get. In Belgium for example, you should probably go to 80% and lower of your advertised bandwidth to have an optimal approximation. Depends on your service level agreement with your provider of course.

@iahmedelbarbary
Copy link

You made your script mark packet down then up in all ur srcipt. do you think the best way is to let down go to queue first ?
I mean if i made up is first so up go to queue first is that good or dw first ? What is the best way

Packet marks for upload and download specifically are most of the time not necessary. The reason I did it in this specific configuration is that the direction of packets into Queue Trees confused me at the beginning. The correct approach, or at least the closest approximation for this simple configuration (in MY opinion), is to mark packets without other filters than Connection Mark. I would approach this differently if I get to redo the configuration.

Why you can't edit it ???

1-Your script says i have to make a parent for every interface un bridged or 1 parent for all interface under bridge1 So i have 5 VLAN OUT Un bridged on port OUT when select parnt is port OUT for all internet was not good under 5 VLAN
What is the best way to make it ? Does make parent for every VLAN out or use global for 1 parent download for all 5 VLAN ??

So yes, you shape download traffic with trees that have a LAN interface as a parent. In your case, you have multiple WAN interfaces. Bridging is not an option because you don't want layer-2 switching between the interfaces.
Here you want to start marking packets for upload/download specifically.
What you do in that situation is start using a tree with parent=global for download traffic, and keep separate trees on your WAN interfaces for upload shaping.
its very very very clear
parent=global is a queue for all traffic passing through the router and is (probably) enforced before interface queues. You'll see traffic flowing through both global and interface queues. Any packet that isn't matched by a rule underneath parent=global will not be shaped. So in simple terms, mark packets normally, and have post routing rules to mark the same packets with a WAN-specific mark.
eg;

[Mangle]
action=mark-packet chain=prerouting connection-mark=PUBG new-packet-mark=PUBG passthrough=no
action=mark-packet chain=postrouting packet-mark=PUBG new-packet-mark=PUBG_WAN out-interface=PUBG passthrough=no
[Queue Tree]
add name=FOR_DOWNLOAD parent=global max-limit=1M queue=default
add name=WAN_PUBG parent=PUBG max-limit=1M queue=default
add name="PUBG_DOWN" parent=FOR_DOWNLOAD packet-mark="PUBG" limit-at=1M priority=1 <-- Traffic coming from any WAN shaped down accross all LAN interfaces
add name="PUBG_UP" parent=WAN_PUBG packet-mark="PUBG_WAN" limit-at=1M priority=1 <-- Upload traffic through PUBG WAN interface

why you marked the the upload in postrouting and not marked on prerouting or forward ?
all what i know about post is that used to mark the connection too and this is the last chance to mark the connection ever before leaving the mangle, when you use post with pre that mean double QOS yo can do with it 2 QOS, so why you use for down pre and for u post ? why you don't make it pre like DW ?

You can then individually shape traffic per LAN interface as well, using your VLANs as a parent.

i will test this way to see what is the best global or every interface as a parent, very clear

2- Does all limit at in all childs under 1 parent must be = max limit ???

Depends on your configuration and your actual bandwidths passing the router. Overprovisioning bandwidth isn't anything new, many do this. BUT, if you have maximum saturation of each type of traffic you'll want to make sure the SUM of limit-at is below max-limit of the parent. Otherwise, the lowest priority queues will become starved.

in my case is too hard to understand this because i pass local ip tv through the PPPOE servers so i have to give it a priority, i have 100Mps internet, i set in parent 1000M every each of internet mark packets in queue tree set max 100M, in mark packet ip tv in queue tree i set 900M Max and 900M Limit is this way is right or i have to edit it ?
or should i make a new parent with global as parent for only ip tv ???

3- I readed many things about {global} in queue tree, Should i use 1 Parent for all with parent=global and add all under this parent up and down or to make parent for every interface?

See answer to the first question. Basically, parent=global can be combined with interface-specific queues. Just imagine two filters behind each other before leaving the interface.

yes i think to much realy too much about this abelities of queue really Bert

4- packet size, you made packet size of voip 0-260 will mark packet in queue, how could i detect packet size? Does this packet size is permanent ?? like from 0-260 is voip and 260-520 this is other thing could you explain it please ?

Correctly tagging VOIP traffic is just really hard without application support. The connection (could have) variable bitrate so the packet sizes vary and the port ranges are big. What I configured was an approximation.
It's better to properly do QOS tagging within your operating system or VOIP application and use the DSCP priority fields to classify low bandwidth, low latency connections like VOIP. Sadly the OS or application configuration is not always manageable, you don't control the devices on a hotspot for example, so you can only 'have a good approximation' in this case.

i tested your way its very powerfull i tested it very well, your script is full of the most interesting rules i ever met and the way to mark the big marker and except connection from it its very very interesting you are trully PRO

Related; For low latency applications you want to prevent buffer bloat, that's why you put max-limit on WAN interfaces to a value that you're guaranteed to get. In Belgium for example, you should probably go to 80% and lower of your advertised bandwidth to have an optimal approximation. Depends on your service level agreement with your provider of course.
understood and clear


i have 3 questions about DSCP and Set priority
1- these 2 options ( DSCP and Set priority) are splitted ? so i can set priroty for any mark conn? does it effective alove ?
2- Change DSCP is effective alone ?
3- set priority the hgih priority is no.7 ? so if i set priority 7 for dns and icmp and changed them DSCP To 63 and set to DSCP 63 priority 7, is this way right?
Thanks Bert

@Bert-Proesmans
Copy link
Author

Why you can't edit it ???

Don't fix what isn't broken. It's like a principle in ICT meaning; don't put effort into changing something when the benefit is negligible or unknown because there is always a chance you break something in the process. Honestly, keeping the full mental model of networking inside my head requires a lot of effort. Even though I did all this before, it still requires me to look up many implementation details. Combine this with multiple responsibilities for a recipe of very slow progress and headache. ;)

Specifically marking for upload/download becomes interesting with multiple uplinks so the configuration is not wrong, just overcomplicated for this specific use case.

why you marked the the upload in postrouting and not marked on prerouting or forward ?

Because you can only filter on out-interface in post-routing.

when you use post with pre that mean double QOS yo can do with it 2 QOS, so why you use for down pre and for u post ? why you don't make it pre like DW ?

Not sure what you mean with "DW".
Ok, try to think about the routing features on a basic level again. Mangle doesn't do QOS, Mangle doesn't dictate upload or download traffic. The thing mangle does is manipulating packet data crossing the routing plane.
Queue trees do QOS, and the parent interface over tree rules dictate upload/download traffic.

There is no double QOS because there are packet mark rules in pre- and post routing. BUT there is potential for double QOS when you use parent=global as a queue tree. Keep in mind that parent=global queue affects ALL packets passing the routing plane as part of the post routing step in packet flow. So a rule underneath parent=global and parent=WAN with the same packet-mark filter will result in packets going out of WAN to be shaped twice (by both trees).
The packet-mark in post routing is there to simply skip the global queue. In practice, an assumption is made that the routing capacity of the device is a multiple of your interface bandwidth. If your routing capacity is 4Gbps and you have 2 fully saturated 1Gbps links you'll need to start using more shaping records underneath parent=global to guarantee a minimum service level. (Or reduce the amount of processing your packet flow requires because that has an impact on routing capacity as well). Note that ethernet links are duplex, so a saturated 1Gbps link results in 2Gbps packet flow.

in my case is too hard to understand this because i pass local ip tv through the PPPOE servers so i have to give it a priority, i have 100Mps internet, i set in parent 1000M every each of internet mark packets in queue tree set max 100M, in mark packet ip tv in queue tree i set 900M Max and 900M Limit is this way is right or i have to edit it ?
or should i make a new parent with global as parent for only ip tv ???

I'm considering the picture your provided of your queues in an earlier reply. I'm a bit confused about your configuration now.
From your description, I understand you have one WAN interface that's PPOE (4 - In) and you want to split its download traffic into LAN (5 - OUT) and IPTV (???). Is that correct? What about upload bandwidth, it looks like you get 7 Mbps?
What's connected on (1 - IP TV), is that a VLAN interface as a child of (4 - In)?

If you want to do (static) pre-allocation shaping you don't need a parent=global tree, just split your download bandwidth across both interfaces so the SUM of max-limit results is 100Mbps or below. (This is simple if you only route between 1 WAN and a few internal interfaces.)
If you want to maximize download bandwidth usage on WAN over both internal interfaces you need a parent=global tree as far as I know.
The max-limit for parent=global is a bit of a tricky question because it depends on how heavy your configuration is. You can use the test sheets provided by Mikrotik as baseline guidance. What you did by setting max-limit to a high value and work with individual max-limit per packet mark is an ok middle ground (I think).

I'll answer your other questions at another time.

@cufre
Copy link

cufre commented Oct 4, 2022

hi, if i had 2 wan, which is the best way for adapt you script ? thank you in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment