IOL vs IOSv in Containerlab: Which Image Passed Each Lab Test

Built in my home lab: twelve Containerlab tests decide IOL, IOL-L2 or IOSv-L2. IOSv-L2 won dynamic DHCP snooping and 802.1X; IOL-L2 won IPSG, RA Guard and SPAN.

Use IOL for routed labs, and choose between IOL-L2 and IOSv-L2 by the switching feature, because neither switch image passed every test. Built in my home lab on Containerlab, twelve feature labs split cleanly: IOSv-L2 learned dynamic DHCP snooping bindings, ran DAI with DHCP clients and completed wired EAP-TLS, while IOL-L2 passed IP Source Guard with a static binding, cut rogue IPv6 RAs from 15/15 to 0/15 and fed a SPAN port that Zeek could see. Use ASAv or FTDv only when the lab needs that firewall.

These results are for the exact builds below (IOL and IOL-L2 on IOS XE 17.18.2, IOSv-L2 15.2 from 2020; some people call it vIOS). A command that parses is only the start: every row below sent allowed and forbidden traffic before it counted.

Lab diagram: A decision tree built in my home lab from tested results picks a Cisco virtual image by the behavior the lab must prove. ASAv is verified for RADIUS AAA with a successful test aaa-server, but a VPN data tunnel was not tested. IOL is verified for uRPF, NTP auth, SNMPv3, TACACS+ and Flexible NetFlow; IOSv-L2 for dynamic snooping, DAI, EAP-TLS with Filter-Id and critical VLAN; IOL-L2 for static-binding IPSG, RA and DHCPv6 Guard, PVLAN ICMP, BPDU Guard and SPAN. FTDv is a candidate only because its HA pair never formed, and storm-control has no verified build because both switch parsers rejected it.

IOL vs IOSv-L2: which image passed each feature test

"Verified" means the lab exercised the behavior, including its control or recovery. "Qualified" narrows what worked. Each row gives the result and its practical limit. These are results on the builds I tested, not a claim about every Cisco image, physical switch or later release.

Feature or lab goal Image that passed Result and practical limit
Routed asymmetric-path and uRPF exercise IOL: verified uRPF strict vs loose: strict return-path checking lost 5/5 legitimate pings with five added RPF drops; loose restored ping and HTTP 200. allow-default was required for the tested default-route case.
NTP authentication and bad-key diagnosis IOL: qualified NTP authentication: the wrong key produced bad_auth Invalid_NAK; the control selected an authenticated peer, but the IOL NTP client never synced its local clock in the observation windows.
SNMPv3 authPriv, engine-ID break and repair IOL: verified SNMPv3 traps and informs: SHA/AES128 polling broke after the engine-ID change and recovered after the user was recreated; three authPriv traps were decrypted. Informs were not delivery-tested.
TACACS+ login, command authorization and local fallback IOL: verified TACACS+ device administration: show permit, configure deny and accounting worked; restoring local EXEC and command fallback recovered fresh SSH and console access with the server stopped.
Flexible NetFlow v9 export and collector-source fault IOL: verified Flexible NetFlow: the wrong exporter source gave zero accepted flows; the fix gave 12 flows, 1,239,588 bytes and 1,473 packets. Cache tuning commands had parser limits.
Dynamic DHCP snooping binding for a DAI lab IOSv-L2: verified for learning DAI and IP Source Guard: IOSv-L2 learned a dynamic binding; IOL-L2 delivered the lease but left its dynamic table empty. Cisco's own IOL-L2 test only checks that rogue DHCP is blocked on untrusted ports, not that the binding table fills. This is not a complete DHCP-server enforcement comparison.
DAI with DHCP clients and a static-host ARP ACL exception IOSv-L2: verified; IOL-L2 also works with a static binding Same DAI lab: eight forged replies reached the unprotected client, zero with DAI; an ARP ACL restored static-host pings 4/4. Replies carrying the real client IP and MAC from another port still passed.
IP Source Guard with a deliberate static source binding IOL-L2: verified Same DAI lab: valid UDP arrived 8/8 and spoofed UDP 0/8; IOSv-L2 blocked both the valid and the spoofed traffic, including with a static binding. The command is ip source binding, not ip source-binding.
IPv6 RA Guard IOL-L2: verified RA Guard and DHCPv6 Guard: rogue RAs went from 15/15 received to 0/15, with legitimate RAs still passing; IOSv-L2 rejected attaching the interface policy. Fragmentation and evasion were untested.
DHCPv6 Guard, crafted server Advertise filtering IOL-L2: qualified Same RA Guard lab: 15/15 control Advertises arrived and 0/15 guarded ones did; IOSv-L2 accepted the policy syntax but passed all 15. Client DNS changes and other DHCPv6 messages were not tested.
Private VLAN gateway access and isolated-host ping tests IOL-L2: qualified Private VLANs: gateway pings passed 3/3, isolated-peer pings failed, removing the mapping broke gateway access and restoring it recovered it. IOSv-L2 got a CLI probe only; some frames crossed capture points.
BPDU Guard trip and manual recovery IOL-L2: verified BPDU Guard lab: a captured rogue-bridge BPDU matched err-disabled bpduguard; manual recovery restored 5/5 pings. No physical loop or timed recovery was tested.
Storm-control rates, enforcement and counters No verified choice among these builds Storm control: IOL-L2 and IOSv-L2 both rejected the percentage, pps, bps, action and verification commands. There is no enforcement proof, and another installed image is not an automatic fallback.
Wired EAP-TLS and VLAN authorization IOSv-L2: worked in this build FreeRADIUS dynamic VLAN assignment: fresh EAP-TLS sessions completed and VLAN 20 was restored with bidirectional 3/3 forwarding. Neither run shows IOL-L2 failing every 802.1X case.
RADIUS-selected per-user local ACL IOSv-L2: verified Filter-Id = "BLOCK-WEB.in" denied TCP 80 and permitted TCP 8080 and ICMP; removing it permitted TCP 80 and restoring it blocked it again. Downloading ACL text from RADIUS was untested.
RADIUS server-dead critical VLAN versus explicit reject VLAN IOSv-L2: verified RADIUS server unreachable: stopping the server selected VLAN 50, an explicit Access-Reject selected VLAN 60 and restoration selected VLAN 20; active VLAN probes passed 3/3 in both directions. Fixed timing was not established.
SPAN visibility for Zeek L2 evidence IOL-L2: verified Without SPAN, Zeek missed six rogue DHCP replies and three false ARPs that reached the client; restoring SPAN produced two custom notices. Mirroring gave visibility, not prevention.
ASA firewall, NAT, IPsec and RADIUS AAA exercise ASAv: verified ASAv: verified for IKEv2 site-to-site and identity NAT (ASA LAN-to-LAN IKEv2), and for RADIUS authentication against FreeRADIUS, including wrong-password, wrong-NAS and wrong-secret faults (ASA AAA for VPN); AAA success there was not a data tunnel. Boot notes in ASAv in Containerlab.
FMC-managed Threat Defense policy and deployment FTDv FTDv: verified for a single FMC-managed FTD (FMC REST API deploy). My FTDv HA attempt never formed a pair, so HA is not verified. For FTD without FMC, see FTDv with local FDM.

Cisco's CML documentation lists SPAN and Private VLANs as unsupported on IOSvL2, and lists 802.1X only as passthrough. The EAP-TLS result is what this build did, not a Cisco-supported feature. Cisco's IOL-L2 notes cover the DHCP snooping test mentioned in the table.

Two of those results, straight from the lab output. IOSv-L2 learned the DHCP client's binding dynamically:

02:00:00:44:00:10   10.144.0.100     3593        dhcp-snooping   144   GigabitEthernet0/2
Total number of bindings: 1

On IOL-L2, the RA Guard capture counts (rogue RA, legitimate RA, DHCPv6 Advertise) show the receiver H1 got none of the 15 rogue RAs, while the capture on the attacker H2 shows all 15 it sent:

iol-guarded-H1.pcap | 0 | 3 | 0
iol-guarded-H2.pcap | 15 | 3 | 0

Three traps when an image accepts the command

A populated status display is not a forwarding test. IOSv-L2 displayed an active IPSG address while blocking the valid control traffic. Its DHCPv6 Guard syntax also loaded without blocking the crafted messages. For protection features, send an allowed control and a forbidden test, then capture at both ends.

A working variant needs its prerequisite in the label. The IOL-L2 IPSG result used a static source binding because dynamic snooping learning failed. The IOSv-L2 ACL result selected an existing local ACL by Filter-Id; it did not download ACL text from RADIUS. The PVLAN result verified ICMP isolation, not complete frame confidentiality. Those distinctions decide whether you can repeat the exercise.

Installed is a separate claim from working. A parser accepting a command, a status display and an installed image are all separate from verified forwarding. ASAv and FTDv were present as images on the lab host, but the inventory behind this post did not log in to either appliance or test forwarding. The ASAv and FTDv rows rest on the labs they link to, and only on what those labs tested.

💡
Test the forbidden case before you trust an image PingLabz Pro unlocks all 68 browser labs, 500 CCNA practice questions and two timed mock exams for $59/year or $7.99/month.

Exact builds tested

Tags, interface maps and boot gotchas are in Cisco images in Containerlab. The results above came from these builds:

Name used here Image tag Guest version
IOL vrnetlab/cisco_iol:17.18.02 IOS XE 17.18.2
IOL-L2 vrnetlab/cisco_iol:L2-17.18.02 IOS XE 17.18.2
IOSv-L2 vrnetlab/cisco_vios:L2-20200929 IOS 15.2(20200924:215240)
ASAv vrnetlab/cisco_asav:9-24-1 Not checked in this inventory
FTDv vrnetlab/cisco_ftdv:10.0.0 Not checked in this inventory

When you document your own result, keep both the image tag and the guest version. Two images with similar names are not interchangeable proof.

How to test a feature on a new image

Pick the row that matches your experiment and reuse that lab's topology and configs. In Containerlab, IOL and IOL-L2 use Ethernet names, with eth1 mapped to Ethernet0/1; IOSv-L2 uses GigabitEthernet0/1 for eth1. Leave the management interface out of the test links, and check the real interface names before you paste configuration.

For a new comparison, keep the endpoints, addresses, traffic and success criteria the same. Record the image tag, show clock, guest version, baseline, fault, recovery and endpoint captures. A parser probe can show that syntax is missing; proving enforcement also needs traffic.

Cisco's CML FAQ lists nominal sizes of 1 vCPU and 1 GB for IOL and IOL-L2, 512 MB for IOSv, 768 MB for IOSv-L2, 2 GB for ASAv and 8 GB for FTDv. On my 63 GiB lab host, the IOL and IOSv-L2 labs in this matrix all ran beside a persistent FMCv.

Read next