Traffic Policer and Rate Limiting
Traffic Policer and Rate Limiting
Section titled “Traffic Policer and Rate Limiting”RouterOS provides fine-grained traffic rate limiting through the combination of Firewall Mangle (classification) and Queue Tree (enforcement). This two-stage approach lets you identify specific traffic flows with packet marks, then apply bandwidth caps, guaranteed rates, burst allowances, and priorities through a hierarchical queue structure.
Overview
Section titled “Overview”Traffic policing in RouterOS uses two subsystems working together:
- Firewall Mangle — classifies packets by assigning connection marks and packet marks. Mangle does not enforce any rate by itself; it only labels traffic for downstream processing.
- Queue Tree — enforces bandwidth policy. Queue Tree reads the packet marks assigned by Mangle and applies rate limits, priorities, and burst behavior.
This separation of classification from enforcement is the core RouterOS QoS design. You can reclassify traffic without touching your queue structure, and vice versa.
Sub-menus
Section titled “Sub-menus”/ip firewall mangle/queue tree/queue typeFastTrack Caveat
Section titled “FastTrack Caveat”Queue Tree (and Simple Queue) only processes packets that pass through the normal packet path. Traffic accelerated by the FastTrack connection tracker bypasses the queue subsystem entirely. If your QoS rules appear to have no effect, disable FastTrack for the affected connections or add a Mangle rule that prevents FastTrack from accelerating marked traffic.
# Exclude LAN traffic from FastTrack so QoS rules apply/ip firewall filteradd chain=forward action=fasttrack-connection connection-state=established,related \ src-address=!192.168.88.0/24 dst-address=!192.168.88.0/24 comment="FastTrack WAN-to-WAN only"Marking Traffic with Mangle
Section titled “Marking Traffic with Mangle”Mangle rules assign symbolic labels to packets. The standard pattern is to mark the connection first, then mark packets belonging to that connection. This two-step approach ensures that reply packets (which have reversed src/dst) also receive the correct mark.
Connection Mark then Packet Mark
Section titled “Connection Mark then Packet Mark”/ip firewall mangle
# Step 1: mark new connections matching the target trafficadd chain=forward connection-state=new src-address=192.168.88.0/24 \ action=mark-connection new-connection-mark=lan_up_conn passthrough=yes \ comment="Mark new LAN upload connections"
# Step 2: mark all packets belonging to those connectionsadd chain=forward connection-mark=lan_up_conn \ action=mark-packet new-packet-mark=lan_up_pkt passthrough=no \ comment="Mark LAN upload packets"Passthrough Behavior
Section titled “Passthrough Behavior”The passthrough parameter controls whether a packet continues matching subsequent Mangle rules after the current rule fires.
passthrough | Effect |
|---|---|
yes | Packet continues to next rule. Use when further classification is needed. |
no | Packet stops matching Mangle rules after this rule. Use on the final packet-mark rule to avoid redundant processing. |
Set passthrough=no on your final mark-packet rule to avoid re-processing packets that already have a mark.
Correct Chain Selection
Section titled “Correct Chain Selection”| Traffic type | Chain | Direction |
|---|---|---|
| Traffic passing through the router | forward | Both |
| Traffic generated by the router itself | output | Outbound only |
| Upload (LAN → WAN) classification | prerouting or forward | — |
| Download (WAN → LAN) classification | forward or postrouting | — |
For most LAN/WAN rate-limiting scenarios, use the forward chain. Use prerouting only when you need to mark before routing decisions.
Queue Tree Rate Limiting
Section titled “Queue Tree Rate Limiting”Queue Tree is a hierarchical bandwidth enforcement system based on HTB (Hierarchical Token Bucket). Each queue entry can set a guaranteed minimum rate (limit-at), a normal cap (max-limit), and optionally allow bursting above the cap.
Key Parameters
Section titled “Key Parameters”| Parameter | Description |
|---|---|
parent | Parent queue or interface. Defines where in the hierarchy this queue sits. |
packet-mark | The Mangle packet mark this queue applies to. |
limit-at | Guaranteed minimum rate (CIR). Traffic up to this rate is always served. |
max-limit | Normal maximum rate. Traffic is capped at this rate under sustained load. |
burst-limit | Peak rate allowed during burst. Must be ≥ max-limit. |
burst-threshold | Average rate trigger. Burst is active while average rate stays below this value. |
burst-time | Averaging window in seconds. Controls how quickly burst allowance is consumed. |
priority | Queue priority (1=highest, 8=lowest). Higher-priority queues are served first. |
queue | Queue discipline type (e.g., default, a PCQ type). |
Basic Rate Limit Example
Section titled “Basic Rate Limit Example”Limit a specific host to 10 Mbps download and 5 Mbps upload:
/ip firewall mangle
# Mark download packets (WAN → host)add chain=forward connection-state=new in-interface=ether1 dst-address=192.168.88.50 \ action=mark-connection new-connection-mark=host50_dl_conn passthrough=yesadd chain=forward connection-mark=host50_dl_conn \ action=mark-packet new-packet-mark=host50_dl passthrough=no
# Mark upload packets (host → WAN)add chain=forward connection-state=new out-interface=ether1 src-address=192.168.88.50 \ action=mark-connection new-connection-mark=host50_ul_conn passthrough=yesadd chain=forward connection-mark=host50_ul_conn \ action=mark-packet new-packet-mark=host50_ul passthrough=no
/queue tree
# Download: cap at 10M, guarantee 2Madd name=host50-dl parent=global packet-mark=host50_dl \ limit-at=2M max-limit=10M priority=5
# Upload: cap at 5M, guarantee 1Madd name=host50-ul parent=global packet-mark=host50_ul \ limit-at=1M max-limit=5M priority=5Burst Above the Rate Limit
Section titled “Burst Above the Rate Limit”Burst allows traffic to temporarily exceed max-limit up to burst-limit. This is useful for web browsing and interactive traffic where short spikes feel faster to users, while the sustained average stays within policy.
How Burst Works
Section titled “How Burst Works”RouterOS tracks a rolling average of the queue’s throughput over the burst-time window:
- If
average-rate < burst-threshold→ traffic may flow up toburst-limit - If
average-rate ≥ burst-threshold→ rate is capped atmax-limit - When utilization drops, the average falls below
burst-thresholdagain and burst re-activates
Setting burst-threshold=0 disables burst entirely.
Burst Configuration Example
Section titled “Burst Configuration Example”Allow a 20 Mbps burst for up to ~8 seconds of a 16-second window before falling back to the 10 Mbps normal cap:
/queue treeadd name=host50-dl-burst parent=global packet-mark=host50_dl \ limit-at=2M \ max-limit=10M \ burst-limit=20M \ burst-threshold=8M \ burst-time=16s \ priority=5Burst parameter guidelines:
burst-thresholdshould be set belowmax-limit(e.g., 80% ofmax-limit) for the burst to activate on idle-then-active flowsburst-timecontrols the averaging window; shorter windows (8–16s) allow more frequent short bursts; longer windows (30–60s) suit fewer but longer burstsburst-limitshould be set to the maximum your uplink can deliver to a single user
Drop vs Mark vs Throttle
Section titled “Drop vs Mark vs Throttle”RouterOS provides three distinct mechanisms for handling excess traffic. Choosing the right one depends on your intent.
Drop (Firewall Filter)
Section titled “Drop (Firewall Filter)”Use /ip firewall filter with action=drop to discard packets entirely. This is a security and policy tool, not a QoS tool. Use it to:
- Block forbidden applications or protocols
- Enforce hard access restrictions
- Contain abuse or DDoS sources
/ip firewall filteradd chain=forward src-address=10.0.0.5 action=drop comment="Block abusive host"Do not use drop for bandwidth shaping. Drop causes TCP retransmissions and poor user experience. When you want slower traffic rather than blocked traffic, use a queue.
Mark (Mangle DSCP / Priority)
Section titled “Mark (Mangle DSCP / Priority)”Use Mangle action=change-dscp or action=set-priority to tag packets with a class-of-service label. The mark itself does not consume or delay any bandwidth — it is a signal to downstream systems.
Use marking to:
- Signal QoS priority to upstream ISP or downstream devices
- Differentiate traffic classes before applying Queue Tree priority queues
- Tag VoIP or real-time traffic for preferential treatment
/ip firewall mangle
# Tag VoIP traffic with DSCP EF (Expedited Forwarding = 46)add chain=forward protocol=udp dst-port=5060,10000-20000 \ action=change-dscp new-dscp=46 passthrough=yes comment="Mark VoIP DSCP EF"
# Set internal priority for VoIP (priority 1 = highest)add chain=forward protocol=udp dst-port=5060,10000-20000 \ action=set-priority new-priority=1 passthrough=noThrottle / Shape (Queue Tree or Simple Queue)
Section titled “Throttle / Shape (Queue Tree or Simple Queue)”Throttling is the act of enforcing a rate limit. RouterOS throttles traffic by placing it in a queue and releasing it at the configured rate. Use Queue Tree (or Simple Queue) to:
- Cap bandwidth for specific hosts, subnets, or traffic types
- Guarantee minimum rates for critical services
- Apply priority scheduling between traffic classes
# Prioritize VoIP over bulk traffic using Queue Tree/queue treeadd name=voip parent=global packet-mark=voip_pkt priority=1 max-limit=2Madd name=bulk parent=global packet-mark=bulk_pkt priority=8 max-limit=50MDecision Summary
Section titled “Decision Summary”| Goal | Tool | Action |
|---|---|---|
| Block traffic entirely | Firewall Filter | action=drop |
| Signal class of service | Mangle | action=change-dscp / action=set-priority |
| Cap bandwidth / slow down | Queue Tree or Simple Queue | max-limit, limit-at |
| Prioritize one flow over another | Queue Tree | priority (1=highest) |
Per-IP Rate Limiting with PCQ
Section titled “Per-IP Rate Limiting with PCQ”Per Connection Queue (PCQ) automatically creates dynamic sub-queues per classifier value (e.g., per source IP or destination IP). This provides fair bandwidth sharing across many clients without manually creating a queue entry for each IP address.
How PCQ Works
Section titled “How PCQ Works”PCQ uses a single queue type that internally subdivides traffic by the configured classifier. Each substream gets up to pcq-rate bandwidth. If total offered load exceeds the parent max-limit, all active substreams are throttled proportionally.
| Parameter | Description |
|---|---|
pcq-classifier | Field used to distinguish substreams (src-address, dst-address, src-port, dst-port, or combinations) |
pcq-rate | Maximum rate per substream (per IP). Set to 0 for unlimited (fair-share only). |
pcq-limit | Per-substream packet buffer size |
pcq-total-limit | Total packet buffer across all substreams |
PCQ Per-IP Rate Limit Setup
Section titled “PCQ Per-IP Rate Limit Setup”Limit each LAN client to 10 Mbps download and 5 Mbps upload, sharing a 100 Mbps / 50 Mbps link:
# Step 1: Define PCQ queue types/queue typeadd name=pcq-dl-10M kind=pcq pcq-classifier=dst-address pcq-rate=10Madd name=pcq-ul-5M kind=pcq pcq-classifier=src-address pcq-rate=5M
# Step 2: Mark download and upload packets in Mangle/ip firewall mangle
# Download: WAN → LAN (destination is the LAN subnet)add chain=forward in-interface=ether1 dst-address=192.168.88.0/24 \ action=mark-packet new-packet-mark=lan_dl passthrough=no \ comment="Mark download packets"
# Upload: LAN → WAN (source is the LAN subnet)add chain=forward out-interface=ether1 src-address=192.168.88.0/24 \ action=mark-packet new-packet-mark=lan_ul passthrough=no \ comment="Mark upload packets"
# Step 3: Apply PCQ queues via Queue Tree/queue treeadd name=LAN-Download parent=global packet-mark=lan_dl \ queue=pcq-dl-10M max-limit=100M comment="100M shared, 10M per IP"add name=LAN-Upload parent=global packet-mark=lan_ul \ queue=pcq-ul-5M max-limit=50M comment="50M shared, 5M per IP"With this configuration:
- Each LAN client gets up to 10 Mbps download and 5 Mbps upload
- If the link is under-utilized, clients can use up to their per-IP cap
- The total shared pool is capped at 100 Mbps / 50 Mbps
PCQ with No Per-IP Cap (Fair Share Only)
Section titled “PCQ with No Per-IP Cap (Fair Share Only)”Set pcq-rate=0 to remove the per-IP cap and allow PCQ to only enforce fairness — all active clients share the total bandwidth equally:
/queue typeadd name=pcq-dl-fair kind=pcq pcq-classifier=dst-address pcq-rate=0add name=pcq-ul-fair kind=pcq pcq-classifier=src-address pcq-rate=0
/queue treeadd name=LAN-Download-Fair parent=global packet-mark=lan_dl \ queue=pcq-dl-fair max-limit=100Madd name=LAN-Upload-Fair parent=global packet-mark=lan_ul \ queue=pcq-ul-fair max-limit=50MSimple Queue vs Queue Tree
Section titled “Simple Queue vs Queue Tree”Both tools enforce bandwidth, but they serve different use cases.
| Feature | Simple Queue | Queue Tree |
|---|---|---|
| Configuration effort | Low — target by address/interface directly | Higher — requires Mangle marks |
| Scalability | Sequential scan; slower with many rules | HTB hierarchy; scales better |
| Hierarchical shaping | Limited | Full parent/child class support |
| Per-IP via PCQ | Supported | Supported |
| Priority queuing | Limited | Full priority scheduling |
| Typical use case | Quick per-host caps, small networks | Class-based QoS, ISP deployments |
Use Simple Queue for straightforward per-host or per-subnet limits in small deployments. Use Queue Tree when you need traffic class hierarchies, priority scheduling, or advanced burst/PCQ configurations.
Complete Example: Class-Based QoS
Section titled “Complete Example: Class-Based QoS”The following example implements a three-class QoS policy on a 100 Mbps WAN link:
- VoIP (UDP 5060 + RTP): priority 1, guaranteed 5 Mbps
- Interactive (HTTPS, DNS, SSH): priority 3, up to 80 Mbps
- Bulk (HTTP, file transfers): priority 8, up to 50 Mbps
# --- Mangle: classify traffic ---/ip firewall mangle
# VoIP connectionsadd chain=forward connection-state=new protocol=udp dst-port=5060,10000-20000 \ action=mark-connection new-connection-mark=voip_conn passthrough=yesadd chain=forward connection-mark=voip_conn \ action=mark-packet new-packet-mark=voip_pkt passthrough=no
# Interactive (HTTPS, DNS, SSH)add chain=forward connection-state=new protocol=tcp dst-port=443,22 \ action=mark-connection new-connection-mark=interactive_conn passthrough=yesadd chain=forward connection-state=new protocol=udp dst-port=53 \ action=mark-connection new-connection-mark=interactive_conn passthrough=yesadd chain=forward connection-mark=interactive_conn \ action=mark-packet new-packet-mark=interactive_pkt passthrough=no
# Bulk — everything elseadd chain=forward connection-state=new \ action=mark-connection new-connection-mark=bulk_conn passthrough=yesadd chain=forward connection-mark=bulk_conn \ action=mark-packet new-packet-mark=bulk_pkt passthrough=no
# --- Queue Tree: enforce policy ---/queue tree
# Root: total WAN capadd name=WAN-Total parent=global max-limit=100M
# VoIP: guaranteed 5M, max 10M, priority 1add name=VoIP parent=WAN-Total packet-mark=voip_pkt \ limit-at=5M max-limit=10M priority=1
# Interactive: up to 80M, priority 3add name=Interactive parent=WAN-Total packet-mark=interactive_pkt \ max-limit=80M priority=3
# Bulk: up to 50M, priority 8 (gets leftover bandwidth)add name=Bulk parent=WAN-Total packet-mark=bulk_pkt \ max-limit=50M priority=8Troubleshooting
Section titled “Troubleshooting”Queue rules have no effect
- Verify FastTrack is not accelerating the affected connections. Check
/ip firewall connectionfor thefasttrackflag. - Confirm the Mangle rules are matching: check counters with
/ip firewall mangle print stats. - Ensure the
packet-markname in Queue Tree exactly matches the name in Mangle.
Burst not activating
- Check that
burst-thresholdis set belowmax-limit(a common misconfiguration is setting threshold above max-limit, which means the burst condition is never met under normal load). - Verify
burst-limit > max-limit. - Monitor the queue’s average rate with
/queue tree monitor.
PCQ not limiting per IP
- Confirm
pcq-classifiermatches the traffic direction (dst-addressfor download,src-addressfor upload). - Check that
pcq-rateis non-zero if a per-IP cap is required. - Verify the Queue Tree entry references the correct PCQ type name.
Wrong traffic being marked
- Add
passthrough=noto finalmark-packetrules to prevent packets from matching multiple mark rules. - Process more specific rules before general catch-all rules in the Mangle chain.
- Use
/ip firewall mangle print statsto confirm which rules are matching.