Mikrotik CHR - shaper local peering/international traffic split

Local peering traffic is cheap and fast, international transit is not. A subscriber on a 5 Mbit plan can usually be given far more bandwidth towards local exchanges without costing anything extra.


This guide splits the two on a MikroTik CHR: an address list defines the peering networks, mangle marks the packets that belong to them, and two simple queues shape each direction with its own limit.


How the Split Works


The logic is three steps. An address list holds the local peering prefixes. Mangle marks any connection to or from those prefixes and stamps its packets with pkt_bg. Two simple queues then match on the packet mark: everything marked goes into the fast local queue, everything left unmarked falls into the international queue.


Build the Peering Address List


Add the local prefixes to an address list named BG_PEERING:

/ip firewall address-list
add address=87.121.121.4 list=BG_PEERING


Whole networks are added the same way, one entry per prefix:

add address=87.121.0.0/16 list=BG_PEERING


For a real deployment the list is best generated from the prefixes learned at the exchange and imported as a script, so it stays in sync when peers change.


Mark the Peering Traffic


Three mangle rules do the work. The first two mark the connection in both directions, the third stamps every packet of that connection:

/ip firewall mangle
add chain=forward action=mark-connection connection-state=new connection-mark=no-mark dst-address-list=BG_PEERING new-connection-mark=conn_bg passthrough=yes comment="BG Peering: Inbound"
add chain=forward action=mark-connection connection-state=new connection-mark=no-mark src-address-list=BG_PEERING new-connection-mark=conn_bg passthrough=yes comment="BG Peering: Outbound"
add chain=forward action=mark-packet connection-mark=conn_bg new-packet-mark=pkt_bg passthrough=no comment="BG Peering: Packet Mark"


connection-state=new and connection-mark=no-mark are what keep this cheap: the address list is only consulted for the first packet of a connection, and every packet after that is matched by the connection mark alone. passthrough=no on the last rule stops the traversal as soon as the packet is marked.


Create the Cake Queue Types


Cake is not in the default queue type list, so the two types have to be created first:

/queue type
add name=cake-upload kind=cake cake-diffserv=diffserv4 cake-nat=yes
add name=cake-download kind=cake cake-diffserv=diffserv4 cake-nat=yes


cake-nat=yes matters when the CHR is doing NAT, because without it every flow appears to come from the same public address and the per-flow fairness collapses.


Create the Simple Queues


Two queues for the same target address, separated only by the packet mark:

/queue simple
add name="192.168.11.13_INT" target=192.168.11.13/32 packet-marks=no-mark max-limit=5M/10M queue=cake-upload/cake-download
add name="192.168.11.13_BG" target=192.168.11.13/32 packet-marks=pkt_bg max-limit=20M/20M queue=cake-upload/cake-download


The subscriber gets 5/10 Mbit internationally and 20/20 Mbit towards the peering networks. max-limit is written as upload/download.


Simple queues are evaluated top to bottom and the first match wins, so any catch-all queue placed above these two will swallow the traffic before it reaches them. The two limits are also independent, which means the host can pull 10 Mbit international and 20 Mbit local at the same time. If the access port cannot carry the sum, put both queues under a parent queue set to the port speed.


FastTrack Bypasses the Queues


FastTrack skips mangle and queues entirely. If the default action=fasttrack-connection rule is present in the filter chain, the split will look correct in the configuration and do nothing to the traffic.


Either remove the FastTrack rule, or exclude the peering connections from it:

/ip firewall filter
set [find action=fasttrack-connection] connection-mark=no-mark


Verify the Split


Check that the mangle rules are actually counting packets:

/ip firewall mangle print stats


Then watch both queues while the subscriber generates traffic. A download from a peering host should fill the _BG queue, anything else the _INT queue:

/queue simple print stats interval=1


If the _BG counter stays at zero, the address list does not contain the address being tested, or FastTrack is still handling the connection.


Conclusion


The same three rules serve every subscriber on the router. Only the pair of simple queues is per customer, so a new plan means two queue entries and nothing else, and the peering list can grow without touching the shaping at all.