Skip to content

Inter-VLAN Routing

Inter-VLAN routing is the process of forwarding IP traffic between separate VLANs. In RouterOS 7, this is achieved by creating VLAN interfaces on a VLAN-aware bridge — each VLAN interface acts as a Layer 3 gateway (analogous to an SVI on Cisco IOS) and receives an IP address that becomes the default gateway for hosts in that VLAN.

Routing between VLANs is automatic once:

  1. The bridge has VLAN filtering enabled and VLAN table entries configured.
  2. Each VLAN has a corresponding VLAN interface with an IP address.
  3. Firewall forward rules permit the desired inter-VLAN traffic.

RouterOS supports two common inter-VLAN routing topologies:

A dedicated router handles Layer 3 while a separate switch handles Layer 2 VLAN switching. The switch trunks all VLANs to a single router interface; the router creates a VLAN subinterface for each VLAN.

Use this when the MikroTik device is a pure L2 switch (no routing desired on the switch) or when a central router handles policy for multiple downstream switches.

The same MikroTik device acts as both the VLAN switch and the inter-VLAN router. VLAN interfaces are created on top of the bridge, giving the CPU a Layer 3 presence in each VLAN. This is the most common configuration for RouterBOARD and CRS devices.

A /interface vlan with interface=<bridge-name> attaches a Layer 3 interface to a specific VLAN carried by that bridge. For the bridge CPU port to participate in a VLAN, the bridge itself must appear in the VLAN table’s tagged list for that VLAN.

┌─────────────────────────┐
│ RouterOS CPU │
│ vlan10 vlan20 vlan30 │
│ .1/24 .1/24 .1/24 │
└─────────────┬───────────┘
│ br1 (bridge, tagged member of VLANs 10,20,30)
┌─────────────┴───────────┐
│ br1 bridge │
│ ether1(trunk) │
│ ether2(access VLAN10) │
│ ether3(access VLAN20) │
│ ether4(access VLAN30) │
└─────────────────────────┘
/interface bridge
add name=br1 vlan-filtering=no

Start with vlan-filtering=no — enable it only after the VLAN table and interfaces are ready.

/interface bridge port
# Trunk port — accepts only tagged frames
add bridge=br1 interface=ether1 frame-types=admit-only-vlan-tagged ingress-filtering=yes
# Access ports — untagged frames assigned to a specific VLAN via PVID
add bridge=br1 interface=ether2 pvid=10 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes
add bridge=br1 interface=ether3 pvid=20 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes
add bridge=br1 interface=ether4 pvid=30 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes

The bridge (br1) must appear in the tagged list so the CPU can send and receive tagged frames for each VLAN — required for VLAN interface operation.

/interface bridge vlan
add bridge=br1 vlan-ids=10 tagged=br1,ether1 untagged=ether2
add bridge=br1 vlan-ids=20 tagged=br1,ether1 untagged=ether3
add bridge=br1 vlan-ids=30 tagged=br1,ether1 untagged=ether4
/interface vlan
add interface=br1 name=vlan10 vlan-id=10
add interface=br1 name=vlan20 vlan-id=20
add interface=br1 name=vlan30 vlan-id=30
/ip address
add address=192.168.10.1/24 interface=vlan10
add address=192.168.20.1/24 interface=vlan20
add address=192.168.30.1/24 interface=vlan30
/interface bridge set br1 vlan-filtering=yes

At this point, hosts in each VLAN can reach their gateway and traffic between VLANs is routed by the CPU (subject to firewall policy).

A separate DHCP server and pool is needed for each VLAN. The DHCP server binds to the VLAN interface, so it only responds to requests arriving on that VLAN.

/ip pool
add name=pool-vlan10 ranges=192.168.10.100-192.168.10.199
add name=pool-vlan20 ranges=192.168.20.100-192.168.20.199
add name=pool-vlan30 ranges=192.168.30.100-192.168.30.199
/ip dhcp-server
add name=dhcp-vlan10 interface=vlan10 address-pool=pool-vlan10 lease-time=1d
add name=dhcp-vlan20 interface=vlan20 address-pool=pool-vlan20 lease-time=1d
add name=dhcp-vlan30 interface=vlan30 address-pool=pool-vlan30 lease-time=1d
/ip dhcp-server network
add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=192.168.10.1
add address=192.168.20.0/24 gateway=192.168.20.1 dns-server=192.168.20.1
add address=192.168.30.0/24 gateway=192.168.30.1 dns-server=1.1.1.1,8.8.8.8

By default, RouterOS routes traffic between VLANs without restriction. If your firewall has a default-deny forward policy, you must explicitly permit the inter-VLAN flows you want.

Grouping VLAN interfaces into a list simplifies rule management:

/interface list
add name=VLAN
add name=WAN
/interface list member
add list=VLAN interface=vlan10
add list=VLAN interface=vlan20
add list=VLAN interface=vlan30
# add WAN interface here as appropriate
/ip firewall filter
# Allow established and related connections
add chain=forward action=accept connection-state=established,related comment="Allow established"
# Drop invalid connections
add chain=forward action=drop connection-state=invalid comment="Drop invalid"
# Example: allow Users (VLAN10) to reach Servers (VLAN20)
add chain=forward action=accept src-address=192.168.10.0/24 dst-address=192.168.20.0/24 comment="Users->Servers"
# Example: isolate Guest (VLAN30) from internal VLANs
add chain=forward action=drop src-address=192.168.30.0/24 dst-address=192.168.10.0/24 comment="Block Guest->Users"
add chain=forward action=drop src-address=192.168.30.0/24 dst-address=192.168.20.0/24 comment="Block Guest->Servers"
# Allow all VLANs to reach the internet
add chain=forward action=accept in-interface-list=VLAN out-interface-list=WAN comment="VLANs to WAN"

Traffic destined for the router itself (DNS, DHCP, WinBox, SSH) traverses the input chain, not forward. Allow only the services you need from each VLAN:

/ip firewall filter
add chain=input action=accept in-interface=vlan10 protocol=udp dst-port=53 comment="DNS from Users"
add chain=input action=accept in-interface=vlan10 protocol=tcp dst-port=22 comment="SSH from Users"
add chain=input action=drop in-interface=vlan30 comment="Drop all input from Guest"

On supported CRS3xx, CRS5xx, CCR2116, and CCR2216 platforms, inter-VLAN routing can be offloaded to the switch ASIC, bypassing the CPU for data-plane forwarding and dramatically increasing throughput.

  • RouterOS v7 with L3 Hardware Offloading support for your platform.
  • VLAN-aware bridge correctly configured (as above).
  • VLAN interfaces and routes must be compatible with L3HW constraints — certain features (NAT, connection tracking, some firewall rules) force traffic to the CPU path.
/interface ethernet switch
set switch1 l3-hw-offloading=yes

The switch name (switch1) may differ by model — use /interface ethernet switch print to identify the correct switch.

/interface ethernet switch print detail

Look for l3-hw-offloading: yes and monitor CPU utilization under traffic load. Traffic forwarded in hardware will not increment CPU counters.

ApproachRouting PathSuitable For
SVI on bridge (RouterBOARD)CPULow-to-medium bandwidth, general-purpose routers
Router-on-a-stickCPU + single uplinkDedicated router with separate switch
CRS L3 Hardware OffloadSwitch ASICHigh-throughput east-west traffic on supported CRS platforms

SVI-style on bridge (CPU routing): The most common deployment. All inter-VLAN packets traverse the CPU. Suitable for typical office or home lab throughput. CPU utilization increases linearly with inter-VLAN traffic volume. Works on all RouterBOARD and CCR platforms — no special hardware required.

Router-on-a-stick: Also CPU-routed. Traffic between VLANs must traverse the trunk link twice (once inbound, once outbound), halving effective uplink bandwidth for east-west flows. Best for scenarios where a central policy router needs to enforce complex firewall rules for multiple downstream switches, or when using a platform with no bridge support.

CRS L3 hardware offloading: On CRS3xx, CRS5xx, CCR2116, and CCR2216, inter-VLAN traffic can be forwarded entirely in switch silicon. CPU handles only control-plane traffic and exception flows. This is the correct choice when inter-VLAN throughput exceeds what the CPU can sustain.

  • General MikroTik router (hEX, RB4011, CCR): Use SVI-style on bridge. L3HW is not available; CPU routing is the only path.
  • CRS3xx/CRS5xx as core switch: Use SVI-style on bridge with L3HW enabled. This delivers line-rate inter-VLAN routing without CPU involvement for bulk traffic.
  • MikroTik router + separate managed switch: Use router-on-a-stick when you want a clear separation between Layer 2 (switch) and Layer 3 (router) responsibilities, or when the switch cannot act as an inter-VLAN router.

Check the bridge VLAN table: Each VLAN’s tagged list must include the bridge itself (br1). Without this, the CPU has no Layer 3 presence in that VLAN and cannot route packets destined for the VLAN interface.

/interface bridge vlan print

Confirm that tagged=br1 appears for every VLAN that has a VLAN interface.

Verify VLAN interface state:

/interface vlan print
/ip address print

Both the VLAN interface and its IP address must show R (running). A VLAN interface that is down typically indicates the parent bridge is down or VLAN filtering is misconfigured.

Check firewall forward rules: If a default-deny forward policy exists, add explicit accept rules for the inter-VLAN flows you need. Test with firewall temporarily disabled to isolate:

/ip firewall filter print stats

Look for rules with rising packets counters to identify where traffic is being dropped.

  • Confirm the DHCP server is bound to the correct VLAN interface (interface=vlan10), not the bridge.
  • Confirm the VLAN table has untagged=<port> for access ports and correct pvid on those bridge ports.
  • Verify frame-types=admit-only-untagged-and-priority-tagged on access ports — mismatched frame type settings cause DHCP discover packets to be dropped at ingress.
/interface bridge port print where bridge=br1
/ip dhcp-server print

If CPU load remains high despite L3HW being enabled, verify:

# Confirm L3HW is enabled on the switch chip
/interface ethernet switch print detail
# Check L3HW settings (RouterOS 7.6+)
/interface ethernet switch l3hw-settings print
# Verify routes are not suppressed from HW candidacy
/ip route print detail where suppress-hw-offload=yes

A common cause is the bridge interface missing from the VLAN table’s tagged list — routes for that VLAN are installed but cannot be offloaded because the hardware has no L3 entry for the VLAN.

When a dedicated MikroTik router serves as the inter-VLAN gateway for a separate downstream switch, configure VLAN interfaces on the router’s uplink interface rather than on a bridge:

# On the router — ether1 is the trunk link to the switch
/interface vlan
add interface=ether1 name=to-sw-vlan10 vlan-id=10
add interface=ether1 name=to-sw-vlan20 vlan-id=20
add interface=ether1 name=to-sw-vlan30 vlan-id=30
/ip address
add address=192.168.10.1/24 interface=to-sw-vlan10
add address=192.168.20.1/24 interface=to-sw-vlan20
add address=192.168.30.1/24 interface=to-sw-vlan30

The downstream switch must trunk VLANs 10, 20, and 30 on the port connected to the router.

The following is a self-contained three-VLAN configuration for a single MikroTik device acting as both VLAN switch and inter-VLAN router:

  • ether1 — WAN uplink
  • ether2 — trunk to downstream switch (VLANs 10, 20, 30)
  • ether3 — access port, VLAN 10 (Users)
  • ether4 — access port, VLAN 20 (Servers)
  • ether5 — access port, VLAN 30 (Guest)
# Bridge
/interface bridge
add name=br1 vlan-filtering=no
# Ports
/interface bridge port
add bridge=br1 interface=ether2 frame-types=admit-only-vlan-tagged ingress-filtering=yes
add bridge=br1 interface=ether3 pvid=10 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes
add bridge=br1 interface=ether4 pvid=20 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes
add bridge=br1 interface=ether5 pvid=30 frame-types=admit-only-untagged-and-priority-tagged ingress-filtering=yes
# VLAN table
/interface bridge vlan
add bridge=br1 vlan-ids=10 tagged=br1,ether2 untagged=ether3
add bridge=br1 vlan-ids=20 tagged=br1,ether2 untagged=ether4
add bridge=br1 vlan-ids=30 tagged=br1,ether2 untagged=ether5
# VLAN interfaces (gateways)
/interface vlan
add interface=br1 name=vlan10 vlan-id=10
add interface=br1 name=vlan20 vlan-id=20
add interface=br1 name=vlan30 vlan-id=30
# IP addressing
/ip address
add address=192.168.10.1/24 interface=vlan10
add address=192.168.20.1/24 interface=vlan20
add address=192.168.30.1/24 interface=vlan30
# DHCP pools
/ip pool
add name=pool-vlan10 ranges=192.168.10.100-192.168.10.199
add name=pool-vlan20 ranges=192.168.20.100-192.168.20.199
add name=pool-vlan30 ranges=192.168.30.100-192.168.30.199
/ip dhcp-server
add name=dhcp-vlan10 interface=vlan10 address-pool=pool-vlan10 lease-time=1d
add name=dhcp-vlan20 interface=vlan20 address-pool=pool-vlan20 lease-time=1d
add name=dhcp-vlan30 interface=vlan30 address-pool=pool-vlan30 lease-time=1d
/ip dhcp-server network
add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=192.168.10.1
add address=192.168.20.0/24 gateway=192.168.20.1 dns-server=192.168.20.1
add address=192.168.30.0/24 gateway=192.168.30.1 dns-server=1.1.1.1
# Enable VLAN filtering (do this last)
/interface bridge set br1 vlan-filtering=yes
# Default route (if WAN is ether1)
/ip route
add dst-address=0.0.0.0/0 gateway=<wan-gateway>