The Cisco trunk is up. VLANs 10 and 20 are allowed. Yet the Linux host cannot ping its gateway. The clue is in the host’s ARP request: it carries a VLAN 20 tag, while the gateway is on VLAN 10.
This lab follows that mismatch from a working baseline to a failed ping and a verified repair. A host capture shows the VLAN tag; the Cisco MAC table shows where the frames arrived. Everything runs on one Linux VM with a locally available Cisco IOL Layer 2 image, with no separate mini PC.
Lab setup and measured evidence
Containerlab’s host link connects Cisco Ethernet0/1 to a temporary Linux interface named plvlan0. The VM creates an 802.1Q VLAN subinterface on that link. On SW1, Ethernet0/1 is a trunk that allows VLANs 10 and 20. Only Vlan10 has an IP address: it is the switch virtual interface (SVI) that serves as the VLAN 10 gateway. The 192.0.2.0/24 range is reserved for documentation.
- Linux VM: Ubuntu 26.04.1 LTS, kernel 7.0.0-38-generic, iproute2 6.19.0, tcpdump 4.99.6.
- Lab platform: Containerlab 0.79.0 and Docker 29.8.2.
- Cisco node:
vrnetlab/cisco_iol:L2-17.18.02;show versionreported IOS XE 17.18.2. - Address plan: Linux
192.0.2.10/24; switchVlan10at192.0.2.1/24.
The measurements below show VLAN tagging and reachability in this virtual lab. The Cisco image stays local and is not included with the lab files.
Build the topology
Save the following as linux-cisco-vlan.clab.yml in a new lab directory. The host:plvlan0 endpoint creates a Linux-side link without involving the VM’s management interface. Use the exact locally installed image tag, or substitute your own tested IOL-L2 tag.
name: linux-cisco-vlan
topology:
nodes:
sw1:
kind: cisco_iol
type: L2
image: vrnetlab/cisco_iol:L2-17.18.02
startup-config: sw1.partial.cfg
links:
- endpoints: ["sw1:e0/1", "host:plvlan0"]Save this as sw1.partial.cfg beside the topology. On this tested IOL-L2 image, the trunk encapsulation had to be set to dot1q before switchport mode trunk; otherwise IOS rejected trunk mode while encapsulation was Auto. VTP transparent mode keeps the VLAN definitions in the startup configuration.
hostname SW1
!
vtp mode transparent
!
vlan 10
name LAB-CLIENT
vlan 20
name LAB-MISMATCH
!
interface Ethernet0/1
description TO-LINUX-HOST-PLVLAN0
switchport trunk encapsulation dot1q
switchport mode trunk
switchport trunk allowed vlan 10,20
no shutdown
!
interface Vlan10
description LAB-CLIENT-GATEWAY
ip address 192.0.2.1 255.255.255.0
no shutdownRun the following commands on the Linux lab VM from the new lab directory. They check that the Cisco image is available, validate and deploy the topology, then create and enable the host’s VLAN 10 subinterface:
docker image inspect vrnetlab/cisco_iol:L2-17.18.02 --format "{{.RepoTags}}"
containerlab validate -t linux-cisco-vlan.clab.yml
containerlab deploy -t linux-cisco-vlan.clab.yml
sudo ip link add link plvlan0 name plvlan0.10 type vlan id 10
sudo ip addr add 192.0.2.10/24 dev plvlan0.10
sudo ip link set plvlan0.10 upWait for the IOL node to finish booting and for spanning tree to forward VLAN 10. A probe during startup may fail. Establish the baseline once the switch shows the trunk and SVI up. This lab runs separately from other Containerlab topologies.
To run the Cisco checks, open a second terminal on the Linux lab VM and attach to SW1’s console:
docker attach clab-linux-cisco-vlan-sw1Press Enter to display the prompt. Run show interfaces trunk and show ip interface brief there. To detach from the console, press Ctrl+P followed by Ctrl+Q.
Establish the VLAN 10 baseline
First, confirm that the host subinterface reports vlan protocol 802.1Q id 10. On SW1, show interfaces trunk reports Ethernet0/1 as 802.1q trunking, with VLANs 10 and 20 allowed and forwarding. The gateway interface, Vlan10, is up/up at 192.0.2.1. With those checks complete, the host receives five ping replies out of five:
ip -d link show plvlan0.10
# vlan protocol 802.1Q id 10
ping -I plvlan0.10 -c 5 -W 2 192.0.2.1
# 5 packets transmitted, 5 received, 0% packet lossBefore repeating the ping, start a capture in another terminal on the Linux lab VM:
sudo tcpdump -eni plvlan0 -nnCapture on plvlan0 so the output can show the 802.1Q tag. Keep the capture running while you send the ping, then stop it with Ctrl+C. Use the same capture command during the VLAN 20 test.
The baseline capture on plvlan0, the parent interface beneath the VLAN subinterface, shows requests and replies tagged as VLAN 10. This excerpt comes from the measured capture:
06:54:41.941186 ... ethertype 802.1Q (0x8100), vlan 10, ethertype IPv4, 192.0.2.10 > 192.0.2.1: ICMP echo request
06:54:41.942399 ... ethertype 802.1Q (0x8100), vlan 10, ethertype IPv4, 192.0.2.1 > 192.0.2.10: ICMP echo replyIntroduce the mismatch: VLAN 20
Move the same host IP address from the VLAN 10 subinterface to a VLAN 20 subinterface. Keep the switch configuration as it is: the trunk still permits both VLANs, and the gateway remains on VLAN 10.
sudo ip addr del 192.0.2.10/24 dev plvlan0.10
sudo ip link add link plvlan0 name plvlan0.20 type vlan id 20
sudo ip addr add 192.0.2.10/24 dev plvlan0.20
sudo ip link set plvlan0.20 up
ip -d link show plvlan0.20
ping -I plvlan0.20 -c 4 -W 1 192.0.2.1The host now reports vlan protocol 802.1Q id 20. The ping returns zero replies from four packets and reports Destination Host Unreachable. To locate the fault, compare the host’s ARP request with the switch’s MAC table:
06:55:11.655088 ... ethertype 802.1Q (0x8100), vlan 20, ethertype ARP, Request who-has 192.0.2.1 tell 192.0.2.10
SW1# show mac address-table dynamic vlan 20
Vlan Mac Address Type Ports
20 aac1.abb0.0d5d DYNAMIC Et0/1ARP asks for the MAC address associated with an IP address on the local network. Here, the host asks for 192.0.2.1 on VLAN 20. SW1 learns the host’s MAC address on Ethernet0/1 in VLAN 20, confirming that the frames reached the switch in that VLAN. But 192.0.2.1 belongs to Vlan10, and there is no Vlan20 gateway to answer the request. Without an ARP reply, the host cannot send the ICMP echo request, which explains its absence from the fault capture.
Restore VLAN 10 and verify recovery
Return the address to the VLAN 10 subinterface and remove the temporary VLAN 20 subinterface:
sudo ip addr del 192.0.2.10/24 dev plvlan0.20
sudo ip addr add 192.0.2.10/24 dev plvlan0.10
sudo ip link del plvlan0.20
ping -I plvlan0.10 -c 5 -W 2 192.0.2.1The recovery check returns five replies out of five with 0% packet loss. A clean redeployment from the saved topology and startup configuration also returns five out of five. After that boot, SW1 shows VLANs 10 and 20 active, Ethernet0/1 trunking, and Vlan10 up/up. This second boot verifies that the saved configuration reproduces the working baseline.
Use the same checks on your own trunk
- Start at Linux:
ip -d link showconfirms the VLAN ID;ip addrandip route getconfirm address and egress interface. - Read the Cisco trunk:
show interfaces trunkdistinguishes operational trunking, allowed VLANs, active VLANs, and forwarding VLANs. - Check the destination VLAN:
show vlan briefandshow ip interface brieflocate the gateway interface;show mac address-table dynamic vlan 20can prove frames arrived in the unexpected VLAN. - Capture at the parent link:
sudo tcpdump -eni plvlan0 -nnshows the 802.1Q tag in this virtual link. Compare captures with host configuration and switch state; host-side offloads can affect what a capture displays.
For wider Cisco-only trunk faults, see Troubleshooting VLAN and Trunk Problems on Cisco Switches. For capture basics, use tcpdump for Network Engineers.
What the evidence proves
In this lab, the host capture identifies the VLAN 20 tag, the switch MAC table confirms arrival in VLAN 20, and the gateway interface places the destination in VLAN 10. Together, those checks explain the failed ping and the successful repair. The test covers one host link and one virtual switch; throughput, multiple switches, real NIC offload behavior, and physical trunks were outside its scope.