Skip to content

Switch Rules (ACL)

For the impatient: drop traffic from a specific source at wire speed.

# Drop all traffic from IP 192.168.1.100 on ether2 (hardware-level)
/interface/ethernet/switch/rule/add switch=switch1 ports=ether2 \
src-address=192.168.1.100/32 new-dst-ports=""
# Rate limit a MAC address to 10Mbps
/interface/ethernet/switch/rule/add switch=switch1 ports=ether2 \
src-mac-address=AA:BB:CC:DD:EE:FF/FF:FF:FF:FF:FF:FF rate=10M
# Block guest VLAN 10 from accessing internal network
/interface/ethernet/switch/rule/add switch=switch1 ports=ether3 \
vlan-id=10 dst-address=192.168.0.0/16 new-dst-ports=""

Verify with:

/interface/ethernet/switch/rule/print
# Ensure no rules show 'invalid' status
Overview diagram

What this does: Switch rules provide hardware-level packet filtering that operates at wire speed, without CPU involvement. They can match on Layer 2 (MAC), Layer 3 (IP), and Layer 4 (TCP/UDP ports) header fields to drop, redirect, rate limit, or modify packets.

When to use this:

  • Blocking traffic at hardware level (faster than firewall)
  • Rate limiting specific hosts or traffic types
  • Redirecting traffic to CPU for captive portals
  • Port mirroring specific traffic patterns
  • VLAN manipulation based on source MAC
  • Hardware-level QoS and traffic shaping

Prerequisites:

  • Device with compatible switch chip (QCA8337, Atheros8327, 88E6xxx series)
  • Understanding of which ports belong to which switch chip
  • For VLAN matchers: bridge with vlan-filtering=yes and hardware offloading enabled

Hardware Requirement

Switch rules only work on devices with supported switch chips. CHR, CCR (non-switching models), and x86 have no switch chip and cannot use these features. Use /interface/ethernet/switch/print to check if your device supports rules.

Check which switch chip your device has and its capabilities:

/interface/ethernet/switch/print

Example output:

0 name="switch1" type="QCA8337" ...

Not all chips support rules. See the Compatibility Matrix below.

Step 2: Understand Rule Processing diagram

Rules are processed in order (first match wins):

  • Rules are evaluated top-to-bottom
  • First matching rule triggers; subsequent rules ignored
  • A rule without actions = accept the packet
  • new-dst-ports="" (empty) = drop the packet

Drop all traffic from a specific IP address:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
src-address=192.168.1.100/32 \
mac-protocol=ip \
new-dst-ports=""

Check that rules are valid and active:

/interface/ethernet/switch/rule/print

Expected output:

# SWITCH PORTS ... NEW-DST-PORTS
0 switch1 ether2

Rules marked invalid indicate configuration errors or unsupported matchers for your chip.

Common Scenarios diagram

Scenario: Block Inter-VLAN Traffic (Hardware)

Section titled “Scenario: Block Inter-VLAN Traffic (Hardware)”

Prevent VLAN 10 from reaching the 192.168.20.0/24 network:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
vlan-id=10 \
dst-address=192.168.20.0/24 \
mac-protocol=ip \
new-dst-ports=""

VLAN Matchers Requirement

VLAN-based matching requires:

  1. Bridge with vlan-filtering=yes
  2. Ports with hardware offloading enabled (check for “H” flag)

Limit a specific IP to 10Mbps ingress:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
src-address=192.168.1.50/32 \
mac-protocol=ip \
rate=10M

Note: Rate limiting only works in the first 32 rule slots on most chips.

Limit a specific device regardless of IP:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
src-mac-address=64:D1:54:D9:27:E6/FF:FF:FF:FF:FF:FF \
rate=10M

Scenario: Redirect HTTP to CPU (Captive Portal)

Section titled “Scenario: Redirect HTTP to CPU (Captive Portal)”

Send all HTTP traffic to CPU for captive portal processing:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2,ether3,ether4 \
protocol=tcp \
dst-port=80 \
mac-protocol=ip \
redirect-to-cpu=yes

Only allow specific MACs on a port:

# Add allowed MAC to host table
/interface/ethernet/switch/host/add switch=switch1 \
ports=ether6 \
mac-address=4C:5E:0C:00:00:01
# Drop traffic from unknown MACs
/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether6 \
src-mac-addr-state=sa-not-found \
new-dst-ports=""

Mirror only HTTP traffic to a monitoring port:

# Set mirror target port
/interface/ethernet/switch/set switch1 mirror-target=ether5
# Mirror HTTP traffic
/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
protocol=tcp \
dst-port=80 \
mac-protocol=ip \
mirror=yes

Assign VLAN based on source MAC (for device authentication):

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether7 \
src-mac-address=A4:12:6D:77:94:43/FF:FF:FF:FF:FF:FF \
new-vlan-id=200

Note: new-vlan-id only supported on Atheros8316 and 88E6393X chips.

Drop spanning tree BPDUs to prevent topology manipulation:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether1 \
dst-mac-address=01:80:C2:00:00:00/FF:FF:FF:FF:FF:FF \
new-dst-ports=""

Rewrite VLAN priority for VoIP traffic:

/interface/ethernet/switch/rule/add switch=switch1 \
ports=ether2 \
protocol=udp \
dst-port=5060 \
mac-protocol=ip \
new-vlan-priority=6

Note: new-vlan-priority supported on Atheros8327, QCA8337, and Atheros8316.

Confirm your switch rules are working:

/interface/ethernet/switch/rule/print

Expected: Rules listed without invalid flag.

/interface/ethernet/switch/rule/print stats

Expected: Counters incrementing for matching traffic.

/interface/ethernet/switch/print

Shows chip type and whether rules are supported.

Check 4: Verify VLAN Filtering (for VLAN rules)

Section titled “Check 4: Verify VLAN Filtering (for VLAN rules)”
/interface/bridge/print

Expected: vlan-filtering=yes on relevant bridge.

SymptomCauseSolution
Rules show “invalid”Matcher not supported by chipRemove unsupported matcher; check chip capabilities
Rule not matching trafficWrong port specifiedVerify which ports belong to switch chip
ARP broken after adding ruleRule matches all protocols (v7.17+)Add mac-protocol=ip (or 0x0800)
VLAN matcher not workingVLAN filtering disabledEnable vlan-filtering=yes on bridge
Rate limiting not workingRule not in first 32 slotsMove rate-limiting rules to top of list
Traffic leaking during rule changeNormal hardware behaviorPlan rule changes during maintenance windows
Rule works but CPU still processesWrong action parameterUse redirect-to-cpu vs copy-to-cpu appropriately
New VLAN ID not appliedChip doesn’t support actionOnly Atheros8316 and 88E6393X support new-vlan-id

Critical: RouterOS 7.17+ ACL Behavior Change

Section titled “Critical: RouterOS 7.17+ ACL Behavior Change”

Before v7.17, a rule like this only matched IP traffic:

# This USED to work, now blocks ARP too!
/interface/ethernet/switch/rule/add ports=ether2 dst-address=192.168.20.0/24 new-dst-ports=""

After v7.17, it matches ALL traffic including ARP, breaking connectivity.

Fix: Always explicitly set mac-protocol:

/interface/ethernet/switch/rule/add ports=ether2 mac-protocol=ip \
dst-address=192.168.20.0/24 new-dst-ports=""

When ACL rules are modified (added, removed, disabled, enabled, or reordered), existing rules become inactive briefly. This can cause packet leakage.

Mitigations:

  • Plan rule changes during maintenance windows
  • Use firewall rules as a backup safety net
  • Batch rule changes when possible

Common Mistakes

  • Forgetting mac-protocol=ip - Blocks ARP and breaks connectivity (v7.17+)
  • Using VLAN matchers without vlan-filtering - Rules won’t match
  • Exceeding rule table limits - Rules silently fail or become invalid
  • Expecting rule stats on all chips - Not all chips support counters
  • Mixing IPv4 and IPv6 matchers - Cannot combine in same rule
  • Rate limiting beyond slot 32 - Rate limiting only works in first 32 rule slots
FeatureQCA8337Atheros8327MT7621RTL836788E6393X
Rule table92 rules92 rulesNoNo256+ rules
Rate limitingYes (slot 1-32)Yes (slot 1-32)NoNoYes
new-vlan-idNoNoNoNoYes
new-vlan-priorityYesYesNoNoYes
redirect-to-cpuYesYesNoNoYes
mirror actionYesYesNoNoYes
IPv6 matchersNoNoNoNoYes
Rule countersLimitedLimitedN/AN/AYes

Devices by switch chip:

ChipDevices
QCA8337hEX (RB750Gr2), cAP ac, hAP ac
Atheros8327RB2011, RB3011
MT7621hEX v3 (RB750Gr3), hAP ac2, hAP ac3
RTL8367RB4011, RB5009
88E6393XCRS305, CRS309, CRS317, CRS326, CRS328
CommandRequired ArgsOptional ArgsNotes
/interface/ethernet/switch/rule/addswitchall matchers, all actionsCreate ACL rule
/interface/ethernet/switch/rule/print-stats, detailShow rules
/interface/ethernet/switch/rule/remove[find] or .id-Delete rule
/interface/ethernet/switch/rule/set[find] or .idany propertyModify rule
/interface/ethernet/switch/rule/move.id, destination-Reorder rules
/interface/ethernet/switch/rule/disable[find] or .id-Disable rule
/interface/ethernet/switch/rule/enable[find] or .id-Enable rule
PropertyTypeDescription
portsport listIngress ports to match (empty = all switch ports)
switchstringSwitch chip name
src-mac-addressMAC/MaskSource MAC address
dst-mac-addressMAC/MaskDestination MAC address
mac-protocolenum/hexEthernet type (ip, arp, ipv6, vlan, or hex like 0x0800)
vlan-id0-4095VLAN ID (requires vlan-filtering=yes)
vlan-headerpresent/not-presentMatch tagged/untagged frames
vlan-priority0-7VLAN priority (802.1p)
PropertyTypeDescription
src-addressIPv4/CIDRSource IP address (cannot mix with IPv6)
dst-addressIPv4/CIDRDestination IP address
src-address6IPv6/MaskSource IPv6 address (88E6xxx only)
dst-address6IPv6/MaskDestination IPv6 address
protocolenum/numberIP protocol (tcp, udp, icmp, or 0-255)
dscp0-63DSCP value
traffic-class0-255IPv6 traffic class
flow-label0-1048575IPv6 flow label
PropertyTypeDescription
src-port0-65535Source TCP/UDP port
dst-port0-65535Destination TCP/UDP port
PropertyTypeDescription
new-dst-portsport listOverride destination; empty = drop
redirect-to-cpuyes/noSend packet to CPU (not forwarded)
copy-to-cpuyes/noCopy packet to CPU (also forwarded)
mirroryes/noCopy to mirror-target port
rateintegerRate limit in bits/second (first 32 rules only)
new-vlan-id0-4095Rewrite VLAN ID (limited chip support)
new-vlan-priority0-7Rewrite VLAN priority