DSCP bad QoS with HTB
DSCP bad QoS with HTB
About
This page tries to describe a way to prioritize traffic by using DSCP tags. The DiffServ Code Point is a field in the IP header that allows you to classify traffic. DSCP is meant to be administered in a per-hop-bad way, allowing each router on a path to determine how each traffic class should be prioritized. The solution described in this document is built around the Hierarchical Token Bucket queuing algorithm in RouterOS, dividing the 64 possible DSCP code values into the 8 queues available. This solution also utilizes the tree-bad queuing, in order to have a parent queue do bandwidth control, with sub-queues for each possible DSCP value.
The actual queuing is done as per this table:
Name Precendence DSCP Range HTB Priority
Routine (default)000 (0)000000(0) – 000111 (7)8
Priority001 (1)001000 (8) – 001111 (15)7
Immediate010( (2)010000 (16) – 010111 (23)6
Flash011 (3)011000 (24) – 011111 (31)5
Flash Override100 (4)100000 (32) – 100111 (39)4
Critical101 (5)101000 (40) – 101111 (47)3
Internetwork Control110 (6)111000 (48) – 110111 (55)2
Network Control111 (7)111000 (56) – 111111 (63)1
This solution has been tested on RB450, RB600 and RB1000 using any 3.x interface.
DSCP marking/mangling
In order to match DSCP values in your queues, it is necessary to mark the packets using firewall mangling. This is best done with this command:
:for x from 0 to 63 do={/ip firewall mangle add action=mark-packet chain=postrouting \
comment=("dscp_" . $x . "_eth") disabled=no dscp=$x new-packet-mark=("dscp_" . $x . "_eth") passthrough=no}
This command creates 64 lines under /ip firewall mangle, that simply marks each packet with a DSCP value to be procesd later.
Having that done, it's time to move on to the actual queues.
Set up the queue tree
The next example assumes that ether1 is the wan interface, and your available bandwidth is 5Mbit/s.
/queue tree
cubitaadd burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=5000000 name=ether1 \
parent=ether1 queue=default
#prio8
:
for z from 0 to 7 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("routine_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=8 queue=ethernet-default}
#prio7
:for z from 8 to 15 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("priority_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=7 queue=ethernet-default}
#prio 6
:for z from 16 to 23 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("immediate_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=6 queue=ethernet-default}
疯神封魔传
#prio 5
:for z from 24 to 31 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("flash_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=5 queue=ethernet-default}
#prio 4
:for z from 32 to 39 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("flash_override_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=4 queue=ethernet-default}
#prio 3
:for z from 40 to 47 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("critical_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=3 queue=ethernet-default}
#prio 2
:for z from 48 to 55 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("intercon_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=2 queue=ethernet-default}
#prio 1韩语一对一培训
:for z from 56 to 63 do={/queue tree add burst-limit=0 burst-threshold=0 burst-time=0s disabled=no limit-at=0 max-limit=0 \
name=("netcon_" . $z . "_ether1") packet-mark=("dscp_" . $z . "_eth") parent=ether1 priority=1 queue=ethernet-default}
Remarks
This solution is the most flexible solution I could come up with. It is built around the philosophy that highest DSCP marking is rved first. The actual shaping of the interface could be moved to a simple queue in order to be able to police differently on upstream and downstream, but I prefer to shape in both ends of a circuit, so when you have different upload and download speed, you should shape in according to the upload speed.
Further Refinements by BrotherDust
质量管理信息系统
Using the former script as a starting point, I have devid the following script:
#Set interface here
:global outboundInterface "ether1"
英语四六级报名网址
#Set bandwidth of the interface (remember, this is for OUTGOING)
:global interfaceBandwidth 0
#Set where in the chain the packets should be mangled
:global mangleChain postrouting
#Don't mess with the. They t the parameters for what is to follow
:global queueName ("qos_" . $outboundInterface)
:global qosClass [:toarray "netcon,intercon,critical,flash_override,flash,immedate,priority,routine"] :global qosIndex 64
#Set up mangle rules for all 64 DSCP marks
#This is different in that the highest priority packets are mangled first.
:for indexA from 63 to 0 do={
/ip firewall mangle add \
action=mark-packet \
chain=$mangleChain \
comment=("dscp_" . $indexA) \
disabled=no \
dscp=$indexA \
new-packet-mark=("dscp_" . $indexA) \
passthrough=no
}
小学生法制教育内容#Add a ba queue to the queue tree for the outbound interface
/queue tree add \
max-limit=$interfaceBandwidth \
name=$queueName \
parent=$outboundInterface \
priority=1
#Set up queues in queue tree for all 64 class, subdivided by 8.
:
for indexA from=0 to=7 do={
:local subClass ([:pick $qosClass $indexA] . "_" . $outboundInterface)
英文翻译/queue tree add \
name=$subClass \
parent=$queueName \
priority=($indexA+1) \
queue=ethernet-default
:for indexB from=0 to=7 do={
:t qosIndex ($qosIndex-1)
/queue tree add \
简单的英语自我介绍name=($subClass . "_" . $indexB) \
茶杯的英文
parent=$subClass \
priority=($indexB+1) \
packet-mark=("dscp_" . $qosIndex) \
queue=ethernet-default
}
}
Set the variables accordingly on the globals, paying attention to the comments. This script creates an even more granular priority structure by creating 64 different priorities subdivided by 8 master priorities. So, this is what it will look like this under interface queues when you enter it in the console:
Some usage notes:
1. Remember! The way that this script is t up by default is such that it will only work with outgoing traffic. It's best practices (in my opinion) to keep it t up that way as doing it for incoming traffic would be redundant.
2. If this going to be applied to more than one interface, cut the script up so that it doesn't make the mangle rules again.
3. Bandwidth parameter need not be t. It's just for if you have an interface with fixed bandwidth or you you want to limit that interface. If it is t it must be in bits per cond. I have not yet tested this on a wireless interface becau the rates are unstable and I want them to be as fast as possible.
iji
Updated on 20090604: I changed the script slightly to rever the mangling chain. Now highest priority packets are procesd first. Probably not going to make a huge difference. But we'll e.
Updated on 20100514: In respon to the comments below: OSPF packets with DSCP tag 48 do not get priority 8 globally; rather, they get priority 8 inside of a priority 2 queue. This script creates an extremely granular queue structure to work with. Most people do not need this level of granularity. For the most part they will delete the queues that aren't needed.
Comment on difference between this solution and first solution
Plea note that the DSCP tagging strategy here is completely different from that of the first script. Plea consider if this fits within your current QoS tup before applying it. For instance, RouterOS automatically tags dynamic routing with DSCP value 48, and following this script, routing updates will have priority 8, which is the lowest priority. In practical network tup, I suggest you only handle the DSCP codes that you know your network is using. My current mangle tup script looks like this:
/ip firewall mangle add action=mark-packet chain=postrouting comment=dscp.0 disabled=no \ dscp=0 new-packet-mark=dscp.0 passthrough=no
/ip firewall mangle add action=mark-packet chain=postrouting comment=dscp.46 disabled=no \
dscp=46 new-packet-mark=dscp.46 passthrough=no
/ip firewall mangle add action=mark-packet chain=postrouting comment=dscp.48 disabled=no \ dscp=48 new-packet-mark=dscp.48 passthrough=no
:for x from 1 to 45 do={/ip firewall mangle add action=mark-packet chain=postrouting \ comment=dscp.1-45 disabled=no dscp=$x her passthrough=no}
/ip firewall mangle add action=mark-packet chain=postrouting comment=dscp.47 disabled=no \ dscp=47 her passthrough=no
:for x from 49 to 63 do={/ip firewall mangle add action=mark-packet chain=postrouting \ comment=dscp.49-63 disabled=no dscp=$x her passthrough=no}
This basically gives you four markings:
•dscp.0 for packets that have no DSCP tags
•dscp.46 for EF packets (my VoIP traffic)
•dscp.48 for routing updates
•her for all other DSCP values
I am then able to asmble a queue tree where unmarked packets have the lowest priority, followed her, dscp.46 and dscp.48, under the philosophy that routing updates should always be prioritized highest - without them, nothing works, then VoIP, other prioritized packets and lowest of all, non-marked packets.