Inter-VLAN Routing with Router-on-a-Stick on Cisco IOS XE

When you don't have a Layer 3 switch, router-on-a-stick provides inter-VLAN routing via a single physical link split into subinterfaces. Learn when this design is appropriate, how to configure subinterfaces, and why it's a bandwidth bottleneck.

Router-on-a-Stick (ROAS) is a routing design where a single physical link between a switch and a router carries traffic for multiple VLANs. The router creates subinterfaces (one per VLAN) on that physical port, each subinterface tagged with a different VLAN ID via 802.1Q. When a host in VLAN 10 needs to reach a host in VLAN 20, the packet goes from the switch to the router's VLAN 10 subinterface, the router routes it, and sends it back on the VLAN 20 subinterface. Router-on-a-Stick was standard before Layer 3 switches were affordable. Today it's used in smaller deployments or labs, but it's a significant bandwidth bottleneck: all inter-VLAN traffic flows through a single link, constraining throughput to that link's capacity.

When to Use Router-on-a-Stick

Appropriate scenarios: - Lab environments: You have a switch without routing capability and a Cisco router available - Small remote sites: A single ISR (Integrated Services Router) provides WAN connectivity and inter-VLAN routing - Budget constraints: No Layer 3 switch in the rack; existing router becomes the VLAN router - Temporary routing: You need inter-VLAN routing during a switch upgrade

Not appropriate for: - High-traffic environments: All inter-VLAN traffic passes through one link (typically 1 Gbps max) - Large deployments: Scales poorly with many VLANs - Redundancy: Single point of failure (if the router goes down, inter-VLAN routing stops)

How Router-on-a-Stick Works

A standard physical interface carries one VLAN. Router-on-a-Stick uses subinterfaces to carry multiple VLANs on the same physical link:

  • Physical link: Gi0/0/0 (1 Gbps) connects the router to the switch
  • Switch trunk: The switch port is configured as a trunk, carrying all VLANs on that link
  • Subinterfaces: Router creates Gi0/0/0.10, Gi0/0/0.20, Gi0/0/0.30 (one per VLAN)
  • 802.1Q tagging: Each subinterface is encapsulated with a VLAN tag
  • Routing happens per subinterface: Traffic between VLANs routes through the physical link at the IP layer

Traffic flow example (Host in VLAN 10 sends packet to Host in VLAN 20):

  1. Host A (VLAN 10, 10.10.10.10) sends packet to Host B (VLAN 20, 10.10.20.20)
  2. Host A's ARP request resolves to the default gateway (10.10.10.254, router's VLAN 10 SVI)
  3. Host A sends packet to the router via Gi0/0/0.10 (tagged with VLAN 10)
  4. Router receives on Gi0/0/0.10, looks at routing table
  5. Router sees destination 10.10.20.20 is on Gi0/0/0.20 (VLAN 20)
  6. Router sends packet out Gi0/0/0.20 (tagged with VLAN 20)
  7. Switch receives VLAN 20 tagged frame on the trunk, forwards to Host B's port

All inter-VLAN traffic goes down the same physical link—a critical bottleneck.

Configuring Router-on-a-Stick (R1-GW in Lab)

Step 1: Create Subinterface for VLAN 10 (Users)

R1-GW(config)# interface Gi0/0/0.10
R1-GW(config-subif)# description VLAN 10 Users Subinterface
R1-GW(config-subif)# encapsulation dot1q 10
R1-GW(config-subif)# ip address 10.10.10.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit

Key commands: - encapsulation dot1q 10: Tags all traffic on this subinterface with VLAN 10 - ip address 10.10.10.254 255.255.255.0: Gateway address for VLAN 10 - no shutdown: Enables the subinterface

Step 2: Create Subinterface for VLAN 20 (Servers)

R1-GW(config)# interface Gi0/0/0.20
R1-GW(config-subif)# description VLAN 20 Servers Subinterface
R1-GW(config-subif)# encapsulation dot1q 20
R1-GW(config-subif)# ip address 10.10.20.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit

Step 3: Create Subinterface for VLAN 30 (Management)

R1-GW(config)# interface Gi0/0/0.30
R1-GW(config-subif)# description VLAN 30 Management Subinterface
R1-GW(config-subif)# encapsulation dot1q 30
R1-GW(config-subif)# ip address 10.10.30.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit

Step 4: Create Subinterface for VLAN 40 (Voice)

R1-GW(config)# interface Gi0/0/0.40
R1-GW(config-subif)# description VLAN 40 Voice Subinterface
R1-GW(config-subif)# encapsulation dot1q 40
R1-GW(config-subif)# ip address 10.10.40.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit

Step 5: Create Subinterface for VLAN 50 (Guest)

R1-GW(config)# interface Gi0/0/0.50
R1-GW(config-subif)# description VLAN 50 Guest Subinterface
R1-GW(config-subif)# encapsulation dot1q 50
R1-GW(config-subif)# ip address 10.10.50.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit

Step 6: Create Subinterface for VLAN 99 (Native)

R1-GW(config)# interface Gi0/0/0.99
R1-GW(config-subif)# description VLAN 99 Native Subinterface
R1-GW(config-subif)# encapsulation dot1q 99 native
R1-GW(config-subif)# ip address 10.10.99.254 255.255.255.0
R1-GW(config-subif)# no shutdown
R1-GW(config-subif)# exit
R1-GW(config)# end

Note: encapsulation dot1q 99 native marks this subinterface as handling untagged traffic (the native VLAN). See the Troubleshooting section for why this matters.

Step 7: Configure the Physical Interface

The physical interface must be up for subinterfaces to work:

R1-GW(config)# interface Gi0/0/0
R1-GW(config-if)# description Trunk to CORE-SW1
R1-GW(config-if)# no shutdown
R1-GW(config-if)# exit
R1-GW(config)# end

Don't assign an IP address to the physical interface—subinterfaces handle all IP routing.

Step 8: Configure the Switch Trunk Port

On CORE-SW1, configure the port connecting to R1-GW as a trunk:

CORE-SW1(config)# interface Gi1/0/5
CORE-SW1(config-if)# switchport trunk encapsulation dot1q
CORE-SW1(config-if)# switchport mode trunk
CORE-SW1(config-if)# switchport nonegotiate
CORE-SW1(config-if)# switchport trunk allowed vlan 10,20,30,40,50,99
CORE-SW1(config-if)# switchport trunk native vlan 99
CORE-SW1(config-if)# description Trunk to R1-GW
CORE-SW1(config-if)# no shutdown
CORE-SW1(config-if)# end

This port now carries all VLANs to the router.

Verification

Check Subinterfaces on Router

R1-GW# show ip interface brief | include Gi0/0/0
Interface                  IP-Address      OK? Method Status    Protocol
Gi0/0/0                    unassigned      YES unset  up        up
Gi0/0/0.10                 10.10.10.254    YES manual up        up
Gi0/0/0.20                 10.10.20.254    YES manual up        up
Gi0/0/0.30                 10.10.30.254    YES manual up        up
Gi0/0/0.40                 10.10.40.254    YES manual up        up
Gi0/0/0.50                 10.10.50.254    YES manual up        up
Gi0/0/0.99                 10.10.99.254    YES manual up        up

All subinterfaces are up/up. The physical interface Gi0/0/0 is also up/up (it's Layer 1 active because the cable is plugged in).

View Subinterface Details

R1-GW# show interfaces Gi0/0/0.10
GigabitEthernet0/0/0.10 is up, line protocol is up (connected)
  Hardware is Gigabit Ethernet, address is aabb.cc00.0300 (bia aabb.cc00.0300)
  Description: VLAN 10 Users Subinterface
  Internet address is 10.10.10.254/24
  MTU 1500 bytes, BW 1000000 Kbit/sec
  Encapsulation ARPA, loopback not set
  Keepalive set (10 sec)
  ARP type: ARPA, ARP Timeout 04:00:00
  Last input 0:00:03, output 0:00:01, output hang never
  Last clearing of "show interface" counters 12:45:22
  Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
  Queueing strategy: fifo
  Output queue: 0/40 (size/max)
  5 minute input rate 45 bits/sec, 0 packets/sec
  5 minute output rate 23 bits/sec, 0 packets/sec
     156 packets input, 12456 bytes, 0 no buffer
     Received 45 broadcasts, 0 runts, 0 giants
     Input errors: 0, CRC: 0, frame: 0, overrun: 0, ignored: 0
     7856 packets output, 123456 bytes, 0 underruns
     Output errors: 0, collisions: 0, interface resets: 0

Key observations: - Encapsulation ARPA: Uses standard IP addressing (not Ethernet broadcast) - Internet address: 10.10.10.254/24 (gateway for VLAN 10) - Input/output rates: Shows inter-VLAN traffic flowing through this subinterface

Check Routing Table

R1-GW# show ip route | include "10.10"
      10.0.0.0/8 is variably subnetted, 7 subnets, 2 masks
C        10.10.10.0/24 is directly connected, GigabitEthernet0/0/0.10
L        10.10.10.254/32 is local, GigabitEthernet0/0/0.10
C        10.10.20.0/24 is directly connected, GigabitEthernet0/0/0.20
L        10.10.20.254/32 is local, GigabitEthernet0/0/0.20
C        10.10.30.0/24 is directly connected, GigabitEthernet0/0/0.30
L        10.10.30.254/32 is local, GigabitEthernet0/0/0.30
C        10.10.40.0/24 is directly connected, GigabitEthernet0/0/0.40
L        10.10.40.254/32 is local, GigabitEthernet0/0/0.40
C        10.10.50.0/24 is directly connected, GigabitEthernet0/0/0.50
L        10.10.50.254/32 is local, GigabitEthernet0/0/0.50
C        10.10.99.0/24 is directly connected, GigabitEthernet0/0/0.99
L        10.10.99.254/32 is local, GigabitEthernet0/0/0.99

Each VLAN subnet is directly connected via its subinterface.

Verify Trunk on Switch

CORE-SW1# show interfaces Gi1/0/5 switchport | include "Operational\|Allowed\|Pruning\|Trunking"
Operational Mode              : trunk
Trunking Native Mode VLAN      : 99
Trunking VLANs Enabled         : 10,20,30,40,50,99
Pruning VLANs Enabled          : 2-1001

The trunk is active and allowing VLANs 10-50 and 99.

Testing Inter-VLAN Routing

Ping from VLAN 10 Host to VLAN 20 Host

Host A in VLAN 10 (10.10.10.100):

C:\> ping 10.10.20.100
Pinging 10.10.20.100 with 32 bytes of data:
Reply from 10.10.20.100: bytes=32 time=15ms TTL=63
Reply from 10.10.20.100: bytes=32 time=14ms TTL=63
Reply from 10.10.20.100: bytes=32 time=15ms TTL=63
Reply from 10.10.20.100: bytes=32 time=14ms TTL=63

Ping statistics for 10.10.20.100:
    Sent = 4, Received = 4, Lost = 0%

Successful! TTL is 63 (sent as 64 from Host A, decremented once by the router).

Trace Route from VLAN 10 to VLAN 20

C:\> tracert 10.10.20.100
Tracing route to 10.10.20.100 over a maximum of 30 hops:

  1   10.10.10.254 [router's VLAN 10 SVI]
  2   10.10.20.100 [destination host]

Trace complete.

Two hops: 1. Gateway (10.10.10.254 on R1-GW) 2. Destination (10.10.20.100 on the server)

View Inter-VLAN Traffic on Router

R1-GW# show interfaces Gi0/0/0.10 | include "packets\|bytes"
  156 packets input, 12456 bytes
  7856 packets output, 123456 bytes

R1-GW# show interfaces Gi0/0/0.20 | include "packets\|bytes"
  234 packets input, 45678 bytes
  3456 packets output, 56789 bytes

Both subinterfaces show traffic (input and output packets), confirming inter-VLAN routing is active.

Router-on-a-Stick Bandwidth Limitations

Router-on-a-Stick has a critical limitation: all inter-VLAN traffic traverses a single physical link. If that link is 1 Gbps and you have heavy communication between VLANs, you'll hit the link's throughput limit.

Example: - VLAN 10 (users) and VLAN 20 (servers) send 2 Gbps of traffic between them - The 1 Gbps link between the switch and router becomes the bottleneck - Only 1 Gbps can cross; 1 Gbps is dropped - Users experience slow server access

Layer 3 switching (via SVIs) has no bottleneck: All inter-VLAN traffic is routed in hardware at line rate—no shared link.

For example, on CORE-SW1 (9300): - VLAN 10 to VLAN 20 traffic: Routed in hardware at 10+ Gbps - No single link is the bottleneck - Per-VLAN throughput is not limited by router-on-a-stick constraints

Troubleshooting Router-on-a-Stick Issues

Symptom 1: Subinterface Is down/down

Symptom: Gi0/0/0.10 is down, line protocol is down

Cause (Priority 1): Physical interface is down.

Check:

R1-GW# show interfaces Gi0/0/0
GigabitEthernet0/0/0 is administratively down, line protocol is down

If the physical interface is administratively down, subinterfaces can't be up.

Fix:

R1-GW(config)# interface Gi0/0/0
R1-GW(config-if)# no shutdown
R1-GW(config-if)# end

Cause (Priority 2): Physical interface has no cable or is notconnect.

Check:

R1-GW# show interfaces status | include Gi0/0/0
Interface        Status       VLAN       Duplex Speed Type
Gi0/0/0          notconnect   routed     auto   auto  10/100/1000BaseTX

Fix: Plug in the cable from the switch trunk port.

Cause (Priority 3): Switch trunk port is disabled or not a trunk.

Check on switch:

CORE-SW1# show interfaces Gi1/0/5 status
Interface        Status       VLAN       Duplex Speed Type
Gi1/0/5          notconnect   1          auto   auto  10/100/1000BaseTX

Port is in VLAN 1 (access mode), not trunk.

Fix on switch:

CORE-SW1(config)# interface Gi1/0/5
CORE-SW1(config-if)# switchport mode trunk
CORE-SW1(config-if)# switchport trunk allowed vlan 10,20,30,40,50,99
CORE-SW1(config-if)# no shutdown
CORE-SW1(config-if)# end

Verify on router:

R1-GW# show interfaces Gi0/0/0 status
GigabitEthernet0/0/0 is up, line protocol is up (connected)

Subinterfaces should now be up/up.

Symptom 2: Host in VLAN 10 Can't Ping Host in VLAN 20

Symptom: ping 10.10.20.100 from VLAN 10 host times out or fails.

Cause (Priority 1): Subinterface doesn't exist or is down.

Check on router:

R1-GW# show ip interface brief | grep Gi0/0/0.20
Gi0/0/0.20                 10.10.20.254    YES manual down     down

The subinterface is down. Follow Symptom 1 troubleshooting above.

Cause (Priority 2): Host doesn't have VLAN 10 subinterface IP as default gateway.

Check on host:

C:\> ipconfig
...
Default Gateway   : 10.10.10.1

Default gateway is 10.10.10.1, but router's VLAN 10 SVI is 10.10.10.254. Either: - Configure DHCP to assign 10.10.10.254 as gateway, or - Manually set gateway to 10.10.10.254

Cause (Priority 3): Switch trunk port doesn't allow VLAN 20.

Check on switch:

CORE-SW1# show interfaces Gi1/0/5 switchport | include "Allowed"
Trunking VLANs Enabled         : 10,20,30,40,50,99

VLAN 20 is allowed (should be fine).

If VLAN 20 is not allowed:

CORE-SW1(config)# interface Gi1/0/5
CORE-SW1(config-if)# switchport trunk allowed vlan add 20
CORE-SW1(config-if)# end

Symptom 3: Native VLAN Traffic Doesn't Route Correctly

Symptom: Hosts in VLAN 99 (native) can't communicate with other VLANs, even though the subinterface exists.

Cause: The native VLAN subinterface is configured without native keyword in the encapsulation.

Incorrect:

interface Gi0/0/0.99
 encapsulation dot1q 99
 ip address 10.10.99.254 255.255.255.0

This creates a subinterface that only receives tagged VLAN 99 traffic, not untagged traffic.

Correct:

interface Gi0/0/0.99
 encapsulation dot1q 99 native
 ip address 10.10.99.254 255.255.255.0

The native keyword tells the subinterface to accept untagged traffic (native VLAN).

Fix:

R1-GW(config)# interface Gi0/0/0.99
R1-GW(config-subif)# encapsulation dot1q 99 native
R1-GW(config-subif)# end

Verify:

R1-GW# show interfaces Gi0/0/0.99 | include "Encapsulation"
Encapsulation ARPA

(The output doesn't explicitly show "native," but the configuration is there.)

Test native VLAN routing:

C:\> ping 10.10.30.100
Reply from 10.10.30.100

Key Takeaways

  • Router-on-a-Stick uses subinterfaces to carry multiple VLANs on one physical link: Each subinterface is encapsulated with a specific VLAN ID via encapsulation dot1q {vlan-id}.
  • All inter-VLAN traffic is bottlenecked by the single physical link: If that link is 1 Gbps, inter-VLAN throughput is capped at 1 Gbps, regardless of how many VLANs exist.
  • Catalyst 9000 Series with SVIs is superior for performance: Hardware-based routing in SVIs provides line-rate inter-VLAN switching with no bandwidth constraints.
  • Router-on-a-Stick is still useful in small labs and branch offices: When a Layer 3 switch isn't available, it provides inter-VLAN routing via an existing router.
  • Native VLAN subinterface requires the native keyword: Otherwise, it won't accept untagged traffic, breaking communication for native VLAN hosts.

Read next

© 2025 Ping Labz. All rights reserved.