Skip to content

DSCP and Queue Tree Integration

DSCP (Differentiated Services Code Point) is a 6-bit field in the IP header that carries a traffic class marking. RouterOS can classify incoming packets by DSCP value, translate those values into packet marks, and route them into a Queue Tree HTB hierarchy — giving you a standards-based QoS policy that interoperates with enterprise switches, IP phones, and carrier networks.

Queue Tree itself does not read DSCP directly. The integration requires two steps:

  1. Mangle — match packets by dscp value and assign a packet-mark.
  2. Queue Tree — route each packet-mark into a child queue with the appropriate HTB priority and rate limits.

DSCP remarking (rewriting the DSCP field on egress) is optional but useful when you want to enforce a consistent marking policy toward the WAN.

The Differentiated Services standard defines several per-hop behaviour (PHB) classes. The values below are the most common in practice.

ClassDSCP NameDecimalBinaryTypical Use
Expedited ForwardingEF46101110VoIP, interactive video
Assured Forwarding 4xAF41/42/4334/36/38Video conferencing
Assured Forwarding 3xAF31/32/3326/28/30Business applications
Assured Forwarding 2xAF21/22/2318/20/22Transactional data
Assured Forwarding 1xAF11/12/1310/12/14Bulk elastic traffic
Class Selector 6CS648Network control (OSPF, BGP)
Class Selector 7CS756Highest-priority control
Best EffortBE / CS00000000Default, unmarked traffic

RouterOS accepts a list of DSCP values in a single dscp= matcher, so AF41/42/43 can be matched in one rule.


Step 1: Classify Traffic by DSCP in Mangle

Section titled “Step 1: Classify Traffic by DSCP in Mangle”

Mangle rules read the DSCP field from each packet and assign a packet-mark. Use passthrough=no once you have matched the packet to prevent lower-priority rules from overwriting the mark.

/ip firewall mangle
# Network control (CS6/CS7) — routing protocols, management
add chain=forward dscp=48,56 \
action=mark-packet new-packet-mark=pm-net-ctrl passthrough=no \
comment="CS6/CS7 network control"
# EF — VoIP, interactive sessions
add chain=forward dscp=46 \
action=mark-packet new-packet-mark=pm-ef passthrough=no \
comment="EF expedited forwarding"
# AF4x — video conferencing
add chain=forward dscp=34,36,38 \
action=mark-packet new-packet-mark=pm-af4 passthrough=no \
comment="AF4x video"
# AF3x — business-critical applications
add chain=forward dscp=26,28,30 \
action=mark-packet new-packet-mark=pm-af3 passthrough=no \
comment="AF3x transactional"
# AF2x — general data
add chain=forward dscp=18,20,22 \
action=mark-packet new-packet-mark=pm-af2 passthrough=no \
comment="AF2x general"
# AF1x — bulk elastic (backups, updates)
add chain=forward dscp=10,12,14 \
action=mark-packet new-packet-mark=pm-af1 passthrough=no \
comment="AF1x bulk elastic"
# Best Effort / catch-all — unmarked or CS0
add chain=forward \
action=mark-packet new-packet-mark=pm-be passthrough=no \
comment="Best effort / unclassified"

Rule order matters. Mangle rules are evaluated top to bottom. Place specific DSCP matches above the catch-all. Using passthrough=no on each rule ensures subsequent rules do not overwrite the mark.

FastTrack note. FastTracked connections bypass the mangle chain entirely. If you shape traffic from devices or subnets where FastTrack is active, disable it for those flows first.


Step 2: Build the Queue Tree HTB Hierarchy

Section titled “Step 2: Build the Queue Tree HTB Hierarchy”

Attach a parent queue to the WAN interface to set the total upload ceiling. Each child queue maps one packet-mark to an HTB class with a priority and rate guarantee.

/queue tree
# Parent — total upload cap on WAN interface (adjust to your link speed)
add name=UP-TOTAL parent=ether1 max-limit=100M \
comment="Total WAN upload shaping"
# Network control — small guarantee, unrestricted access
add name=UP-NET-CTRL parent=UP-TOTAL packet-mark=pm-net-ctrl \
limit-at=2M max-limit=20M priority=1 \
comment="CS6/CS7 routing and management"
# EF — VoIP and interactive
add name=UP-EF parent=UP-TOTAL packet-mark=pm-ef \
limit-at=5M max-limit=30M priority=2 \
comment="EF voice and interactive"
# AF4x — video conferencing
add name=UP-AF4 parent=UP-TOTAL packet-mark=pm-af4 \
limit-at=10M max-limit=50M priority=3 \
comment="AF4x video conferencing"
# AF3x — business applications
add name=UP-AF3 parent=UP-TOTAL packet-mark=pm-af3 \
limit-at=10M max-limit=60M priority=4 \
comment="AF3x business apps"
# AF2x — general data
add name=UP-AF2 parent=UP-TOTAL packet-mark=pm-af2 \
limit-at=5M max-limit=70M priority=5 \
comment="AF2x general data"
# AF1x — bulk elastic
add name=UP-AF1 parent=UP-TOTAL packet-mark=pm-af1 \
limit-at=2M max-limit=50M priority=7 \
comment="AF1x bulk elastic"
# Best effort — catch-all
add name=UP-BE parent=UP-TOTAL packet-mark=pm-be \
limit-at=2M max-limit=100M priority=8 \
comment="Best effort unclassified"

Repeat with a mirrored download tree attached to the LAN interface or global-in:

/queue tree
# Parent — total download cap
add name=DOWN-TOTAL parent=global-in max-limit=300M \
comment="Total WAN download shaping"
add name=DOWN-NET-CTRL parent=DOWN-TOTAL packet-mark=pm-net-ctrl \
limit-at=2M max-limit=50M priority=1
add name=DOWN-EF parent=DOWN-TOTAL packet-mark=pm-ef \
limit-at=10M max-limit=80M priority=2
add name=DOWN-AF4 parent=DOWN-TOTAL packet-mark=pm-af4 \
limit-at=30M max-limit=150M priority=3
add name=DOWN-AF3 parent=DOWN-TOTAL packet-mark=pm-af3 \
limit-at=20M max-limit=200M priority=4
add name=DOWN-AF2 parent=DOWN-TOTAL packet-mark=pm-af2 \
limit-at=10M max-limit=200M priority=5
add name=DOWN-AF1 parent=DOWN-TOTAL packet-mark=pm-af1 \
limit-at=5M max-limit=150M priority=7
add name=DOWN-BE parent=DOWN-TOTAL packet-mark=pm-be \
limit-at=5M max-limit=300M priority=8

The table below shows a recommended default mapping between DSCP PHB classes and RouterOS queue tree priorities.

DSCP ClassPacket MarkQueue PriorityNotes
CS6/CS7pm-net-ctrl1Routing protocols; should never be queued
EFpm-ef2VoIP; latency-sensitive, low volume
AF4xpm-af43Video conferencing
AF3xpm-af34Business-critical apps
AF2xpm-af25General interactive traffic
AF1xpm-af17Bulk elastic flows
CS0 / unclassifiedpm-be8Default

Priority operates between siblings only. HTB priority does not affect limit-at guarantees. A high-priority queue (1) is served first only when the parent’s total capacity is exhausted, not before lower-priority queues have received their guaranteed limit-at.


DSCP remarking rewrites the DSCP field in outbound packets. Use this to:

  • Enforce a consistent policy toward the WAN (strip elevated markings from untrusted LAN hosts).
  • Translate internal marks to carrier-expected values.
/ip firewall mangle
# Preserve EF mark on egress — already correctly marked
add chain=postrouting out-interface=ether1 packet-mark=pm-ef \
action=change-dscp new-dscp=46 \
comment="Keep EF on egress"
# Remark video conferencing traffic
add chain=postrouting out-interface=ether1 packet-mark=pm-af4 \
action=change-dscp new-dscp=34 \
comment="Canonicalize to AF41"
# Strip elevated markings from bulk traffic (police untrusted hosts)
add chain=postrouting out-interface=ether1 packet-mark=pm-be \
action=change-dscp new-dscp=0 \
comment="Clear DSCP for best-effort"

Use postrouting for remarking. The postrouting chain runs after routing decisions, just before the packet leaves the router — the correct point for egress policy enforcement.


Check that mangle rules are matching:

/ip firewall mangle print stats

Each rule should show increasing bytes/packets for traffic hitting that DSCP class.

Check queue rates and drops:

/queue tree print stats

Key fields: rate (current throughput), dropped (packets lost due to full queue), borrows (packets above limit-at using spare parent capacity).

Watch a class in real time:

/queue tree print stats interval=1 where name~"EF"

In ISP or multi-tenant deployments, you may want both DSCP-class priority and per-user fairness within each class. Use PCQ as the inner queue type on the leaf queue entries.

/queue type
add name=pcq-ef-down kind=pcq pcq-classifier=dst-address pcq-rate=0
/queue tree
add name=DOWN-EF parent=DOWN-TOTAL packet-mark=pm-ef \
queue=pcq-ef-down limit-at=10M max-limit=80M priority=2

With pcq-rate=0, the EF class distributes the available 80 Mbps equally across all active subscribers sending EF-marked traffic. See HTB ISP Tiered Bandwidth for a full multi-tier PCQ example.


Queue shows 0 bytes despite DSCP-marked traffic

Section titled “Queue shows 0 bytes despite DSCP-marked traffic”
  • Confirm the DSCP value on ingress packets: use /tool sniffer or packet capture to inspect the IP header DSCP field.
  • Some devices clear DSCP in transit. If packets arrive with DSCP 0, add a mangle rule to re-mark them by port or address before the DSCP-classification rules.
  • Verify mangle is in the correct chain (forward for transit traffic; input for traffic destined to the router itself).
  • The DSCP-marking device (IP phone, PC, switch) may not be setting DSCP. Check device QoS settings.
  • FastTrack is bypassing the mangle chain. Run /ip firewall connection print where fasttrack=yes to identify fast-tracked flows.
  • Priority only matters when the parent max-limit is reached. If the link is not congested, all queues run freely regardless of priority.
  • Confirm the EF mangle rule is above the catch-all in the rules list.