OSPF Virtual Link and Sham-Link Lab: Repairing a Backbone, Overriding a Preference
Two OSPF features get grouped together in every CCIE study guide and confused in almost every lab attempt. Virtual links and sham-links both create a logical adjacency between routers that are not directly connected, both appear as unnumbered point-to-point links, and both set the DoNotAge bit on the LSAs they carry. That is where the similarity ends. A virtual link repairs a broken area topology inside a single OSPF domain. A sham-link repairs a broken metric preference across an MPLS L3VPN where the OSPF domain has been split in two and stitched back together by BGP. Solving a sham-link problem with a virtual link is impossible; attempting it is one of the classic ways to lose an hour in the lab.
The distinction reduces to what each one lies about. A virtual link tells the OSPF SPF calculation that two ABRs are directly attached to area 0, even though the path between them traverses a non-backbone transit area — it restores backbone contiguity so that inter-area routing works at all. A sham-link tells the SPF calculation that two PE routers have an intra-area link inside a customer VRF, even though the path between them is an MPLS VPN. That matters because OSPF always prefers an intra-area route over an inter-area route regardless of cost, so a slow customer backdoor link between two sites will beat a fast MPLS core every single time. The sham-link makes the MPLS path intra-area so that cost, not route type, decides. Neither feature adds capability; both remove an artificial preference the protocol would otherwise enforce.
This article builds both in one lab. Section one separates the two problems precisely and gives the decision rule for which feature applies. Section two dissects virtual-link mechanics — the transit area restrictions, why the cost is not configurable, and how the V bit appears in the Router LSA. Section three covers the MPLS L3VPN superbackbone, the DN bit, domain IDs, and exactly why a backdoor link wins without a sham-link. Section four is the full build with verification output for both. Section five catalogues the failure modes: stub transit areas, unreachable sham-link endpoints, domain-ID mismatches producing type 5 instead of type 3, and the recursive-advertisement trap that silently breaks a sham-link the moment it comes up.

What Problems Do Virtual Links and Sham-Links Each Actually Solve?
How do I decide which one a scenario needs?
Ask one question: is the problem reachability or preference? If an area has no physical or logical attachment to area 0, inter-area routing through it is broken — its ABR's Type 3 LSAs are ignored by other routers and traffic never arrives. That is a reachability failure, and a virtual link is the repair. If all destinations are reachable but traffic takes a customer backdoor link instead of the MPLS core, nothing is broken in the graph — OSPF is correctly applying its rule that intra-area beats inter-area. That is a preference failure, and only a sham-link changes it. Virtual links live inside one OSPF domain; sham-links exist only in a PE VRF across an L3VPN.
A Deeper Dive into the Two Problem Statements
Why OSPF insists the backbone be contiguous
OSPF's inter-area routing model is a two-level hierarchy with a strict rule: all inter-area traffic transits area 0. An ABR summarises its attached non-backbone areas into area 0 and injects area 0's information back down. The rule that makes this loop-free is that a router only accepts Type 3 Summary LSAs from an ABR that is itself attached to area 0. If R2 in the reference topology connects area 1 to area 2 but never touches area 0, it is not a legitimate ABR from the backbone's perspective, and the summaries it generates are ignored by routers computing paths from area 0.
The consequence is asymmetric and confusing. R2 knows about area 0 destinations because it hears them from R1. Routers in area 0 do not know about area 2 destinations, because R2's summaries never reach them through a valid backbone attachment. Ping from area 2 to area 0 leaves and never comes back, and the temptation is to blame an ACL.
Why an intra-area route always wins
OSPF route preference is ordered by type before it is ordered by cost: intra-area (O), then inter-area (O IA), then external type 1 (E1), then external type 2 (E2). This ordering is absolute. A 64 kbps intra-area path defeats a 10 Gbps inter-area path, and no amount of cost manipulation changes it, because cost is only compared within a type.
In an MPLS L3VPN, the customer's OSPF domain is cut at every PE. Routes learned by PE-1 from CE-1 are carried across the core in BGP VPNv4 and re-originated by PE-2 into the customer's OSPF process as Type 3 Summary LSAs — inter-area, by construction. If the customer also owns a direct link between the two sites within the same OSPF area, that link produces intra-area routes. Intra-area wins, so the backdoor carries production traffic and the MPLS service the customer is paying for sits idle until the backdoor fails.
| Dimension | Virtual link | Sham-link | Practical consequence |
|---|---|---|---|
| Problem class | Discontiguous backbone — reachability failure | Backdoor preferred over MPLS core — preference failure | Symptoms differ completely: one loses routes, the other keeps them but uses the wrong path |
| Where configured | Between two ABRs, under the global OSPF process | Between two PEs, under router ospf <pid> vrf <name> |
A sham-link command is rejected outright in a non-VRF OSPF process |
| Endpoint identifier | Neighbour Router ID | Source and destination IPv4 addresses (VRF loopbacks) | Virtual links fail on router-ID typos; sham-links fail on unreachable loopbacks |
| Belongs to which area | Area 0, always | The area you name in the command — any area, commonly a non-zero one | Virtual link authentication follows area 0 settings, not the transit area's |
| Cost | Derived from the intra-area path through the transit area; not configurable | Configurable, default 1 | Sham-link cost is your tuning knob against the backdoor; virtual link cost is not a knob at all |
| Underlying transport | The transit OSPF area itself | The MPLS VPN core, reached via BGP VPNv4 | A sham-link depends on BGP being up; a virtual link depends only on OSPF |
What both features share
Both are modelled as unnumbered point-to-point links in the Router LSA of their respective areas. Both are treated as demand circuits, which means LSAs traversing them carry the DoNotAge bit so that periodic refresh does not have to cross them. Both require the underlying path to be up and stable before the logical adjacency will form. And both are invisible in show ip interface brief, which is why operators inherit them without knowing they exist.
The decision rule, stated as a flowchart in words
- Are you inside a single OSPF domain with no MPLS VPN involved? Then a sham-link is not an option; the answer is a virtual link or a redesign.
- Is an area failing to exchange inter-area routes because its ABR has no area 0 attachment? Virtual link through the transit area that does touch area 0.
- Is the transit area a stub, totally stubby, or NSSA? A virtual link cannot be built through it — convert the area or pick a different transit path.
- Are you a service provider or enterprise running OSPF as the PE-CE protocol, with a customer backdoor link in the same area as the MPLS-connected sites? Sham-link between the PEs, with a cost lower than the backdoor path.
- Is the backdoor in a different area from the MPLS-attached interfaces? Then both paths are inter-area and normal cost comparison already applies — you do not need a sham-link.
How Does a Virtual Link Repair a Discontiguous Backbone?
What exactly does a virtual link create?
A virtual link creates a logical unnumbered point-to-point adjacency in area 0 between two ABRs that both border a common non-backbone transit area. Each endpoint is identified by the remote router's OSPF Router ID, not by an interface address. Once the adjacency forms, both routers are legitimately attached to area 0, so their Type 3 Summary LSAs are accepted by the rest of the backbone. The link's cost is not configurable: it is the cost of the shortest intra-area path between the two endpoints through the transit area, computed by SPF and updated automatically when that path changes.
A Deeper Dive into Virtual Link Mechanics and Configuration
The transit area restrictions, and why they exist
The transit area must carry full routing information for the virtual link to work, because the endpoints must be able to compute an intra-area path to each other. That rules out stub areas, totally stubby areas, and NSSAs — all of which suppress some category of LSA. It also rules out an area where one of the endpoints is not actually an ABR. And the transit area cannot be area 0 itself, which would be circular.
Cisco IOS enforces the stub restriction: configuring area 1 virtual-link where area 1 is defined as stub is rejected or silently non-functional depending on order of configuration. This is a favourite lab trap, because the stub definition is often several screens away from the virtual-link line.
! ===== R1: ABR between area 0 and transit area 1 =====
router ospf 1
router-id 1.1.1.1
! Peer is identified by ROUTER ID, never by interface address
area 1 virtual-link 2.2.2.2
!
! ===== R2: ABR between transit area 1 and area 2 =====
router ospf 1
router-id 2.2.2.2
area 1 virtual-link 1.1.1.1
The V bit and how the database records a virtual link
A router that terminates a virtual link sets the V bit in its Router LSA for the transit area, alongside the B bit that marks it as an ABR. The virtual link itself appears in the area 0 Router LSA as a link of type 4, "virtual link", with the neighbour's Router ID as the link ID. Reading the Router LSA is the definitive way to confirm the link is genuinely established rather than merely configured.
R1# show ip ospf database router adv-router 1.1.1.1
OSPF Router with ID (1.1.1.1) (Process ID 1)
Router Link States (Area 0)
LS Type: Router Links
Link State ID: 1.1.1.1
Advertising Router: 1.1.1.1
Flags: B VL-endpoint
Number of Links: 2
Link connected to: a Virtual Link
(Link ID) Neighboring Router ID: 2.2.2.2
(Link Data) Router Interface address: 10.1.12.1
Number of MTID metrics: 0
TOS 0 Metrics: 64
Why you cannot set a virtual link cost — and what to do instead
The cost shown above, 64, is not something you typed. It is the total cost of the intra-area path R1 takes through area 1 to reach R2. To make the virtual link cheaper you must make that underlying path cheaper, by adjusting interface costs inside the transit area. This is the single most common misunderstanding about virtual links: people search for a cost keyword that does not exist on the command.
! Wrong: there is no cost keyword on a virtual link
R1(config-router)# area 1 virtual-link 2.2.2.2 cost 10
^
% Invalid input detected at '^' marker.
!
! Right: influence the underlying transit-area path instead
R1(config)# interface GigabitEthernet0/1
R1(config-if)# ip ospf cost 10
Timers and authentication on a virtual link
A virtual link uses point-to-point default timers: hello 10 seconds, dead 40 seconds. Both are adjustable on the command itself, and both must match on the two endpoints or the adjacency never leaves INIT. Authentication is the subtler issue: because the virtual link belongs to area 0, it inherits area 0's authentication configuration, not the transit area's. A network with area 0 authentication message-digest requires a key on the virtual link even though no area 0 interface exists on the transit path.
! ===== Virtual link with MD5 authentication and tuned timers =====
router ospf 1
router-id 1.1.1.1
area 0 authentication message-digest
area 1 virtual-link 2.2.2.2 hello-interval 5 dead-interval 20
area 1 virtual-link 2.2.2.2 authentication message-digest
area 1 virtual-link 2.2.2.2 message-digest-key 1 md5 L4bK3y2026
show ip ospf virtual-links reports the link DOWN with no neighbour. Cause: area 0 authentication message-digest is configured, and the virtual link — which belongs to area 0 — has no key. Confirm: debug ip ospf adj shows Mismatched Authentication type or Mismatch Authentication Key on the OSPF_VL0 interface. Fix: add matching authentication message-digest and message-digest-key clauses to the virtual-link statement on both ABRs.What the healthy virtual link looks like
R1# show ip ospf virtual-links
Virtual Link OSPF_VL0 to router 2.2.2.2 is up
Run as demand circuit
DoNotAge LSA allowed.
Transit area 1, via interface GigabitEthernet0/1
Topology-MTID Cost Disabled Shutdown Topology Name
0 64 no no Base
Transmit Delay is 1 sec, State POINT_TO_POINT,
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
Adjacency State FULL (Hello suppressed)
Index 1/2/2, retransmission queue length 0, number of retransmission 0
!
R1# show ip ospf neighbor
Neighbor ID Pri State Dead Time Address Interface
2.2.2.2 0 FULL/ - - 10.1.12.2 OSPF_VL0
2.2.2.2 1 FULL/DR 00:00:34 10.1.12.2 GigabitEthernet0/1
Three signals confirm health. The state is up rather than DOWN. The neighbour appears twice — once over the real interface in the transit area and once over the pseudo-interface OSPF_VL0 in area 0. And the dead time on the virtual link neighbour shows a dash, because hellos are suppressed on a demand circuit; a numeric countdown there means the demand-circuit behaviour did not engage.
show ip ospf | include Router ID and compare with the value in your area 1 virtual-link line. Fix: use the Router ID. If Router IDs are dynamically chosen, pin them with router-id on both ABRs before building the link, or a reload will silently break it.Why Does an MPLS L3VPN Backdoor Link Beat the Core Without a Sham-Link?
What does the MPLS VPN superbackbone do to a customer's OSPF domain?
When OSPF runs as the PE-CE protocol, each PE terminates the customer's OSPF process inside a VRF and redistributes those routes into BGP VPNv4 for transport across the core. The remote PE redistributes them back into its own VRF OSPF process. Because that re-origination happens at an area boundary, the resulting LSAs are Type 3 Summary LSAs — inter-area by definition. The MPLS core therefore behaves like an OSPF backbone superset, often called the superbackbone. Any customer link that directly joins two sites within the same area produces genuine intra-area routes, and OSPF's type ordering makes those win no matter how slow the link is.
A Deeper Dive into the Superbackbone, Domain IDs, and the DN Bit
How a route crosses the superbackbone
Follow a prefix from CE-1 to CE-2. CE-1 advertises 192.168.10.0/24 in OSPF area 1 to PE-1. PE-1's VRF OSPF process installs it and redistributes it into BGP under address-family ipv4 vrf CUST-A. BGP attaches three OSPF-specific extended communities: the OSPF Domain ID, the OSPF Route Type, and the OSPF Router ID of the originating PE. The VPNv4 route crosses the core to PE-2, which redistributes it back into the customer VRF's OSPF process, using the extended communities to decide what LSA type to generate.
Those extended communities are the whole mechanism. The Domain ID determines whether the remote PE re-originates the prefix as a Type 3 inter-area summary or as a Type 5 external. The Route Type community preserves the original area number and LSA type so the reconstruction is faithful. If Domain IDs match between the two PE VRF configurations, the customer sees inter-area routes and the domain looks continuous. If they differ, the customer sees external routes and every metric comparison changes.
| Condition on PE-2 | LSA generated toward CE-2 | Route code seen by CE-2 | Design implication |
|---|---|---|---|
| Domain IDs match, original was intra- or inter-area | Type 3 Summary | O IA |
Normal L3VPN behaviour; loses to any intra-area backdoor |
| Domain IDs differ (or one is unset and non-default) | Type 5 External | O E2 |
Loses to both intra-area and inter-area routes; usually unintended |
| Original prefix was an OSPF external in the source site | Type 5 External | O E2 |
Correct and expected; external-ness is preserved end to end |
| Sham-link established in the same area | Type 1 Router LSA across the sham-link | O (intra-area) |
Now competes with the backdoor on cost, which is the goal |
The DN bit and why it exists
A PE that re-originates a customer prefix into OSPF sets the DN (down) bit in the LSA options field. A PE receiving an LSA with DN set will not redistribute it back into BGP. Without this, a prefix could loop: PE-2 injects it into the customer OSPF domain, a CE with two PE attachments carries it to PE-3, PE-3 redistributes it into BGP again, and the route circulates with mutating attributes. The DN bit is a simple, effective loop stop, and it is set on Type 3, Type 5, and Type 7 LSAs originated by a PE.
The DN bit becomes an obstacle in VRF-lite designs, where a router uses VRFs without MPLS and legitimately needs to pass routes between them. The capability vrf-lite command under the VRF OSPF process disables the DN-bit and domain-ID checks so that those routes are processed normally.
! VRF-lite: no MPLS, so the PE loop-prevention checks are unwanted
router ospf 100 vrf CUST-A
capability vrf-lite
network 192.168.10.0 0.0.0.255 area 1
show ip ospf database for the VRF but the prefix never appears in show ip route vrf. Cause: the LSA carries the DN bit, and the receiving router is running an OSPF process in a VRF, so it deliberately ignores it. Confirm: show ip ospf database summary <prefix> and look for Options: (No TOS-capability, DC, Downward). Fix: add capability vrf-lite in the receiving VRF's OSPF process — but only where there is genuinely no MPLS VPN, because the check exists to prevent real loops.Domain ID configuration and the default that surprises people
If you configure no domain ID, IOS uses a default derived from the OSPF process, and two PEs with different process IDs in the same VRF can end up disagreeing. The symptom is customer routes appearing as O E2 instead of O IA, which usually surfaces as a routing preference complaint rather than an outage. Set the domain ID explicitly on every PE serving a given customer.
! ===== Explicit domain ID on both PEs for this customer =====
router ospf 100 vrf CUST-A
router-id 10.0.0.1
domain-id 0.0.0.100
network 172.16.1.0 0.0.0.255 area 1
Quantifying the problem before you fix it
Prove the preference inversion before configuring a sham-link, so that you can prove the fix afterwards. On CE-1, the remote site prefix should appear as O via the backdoor rather than O IA via the PE.
CE-1# show ip route 192.168.20.0
Routing entry for 192.168.20.0/24
Known via "ospf 1", distance 110, metric 1563, type intra area
Last update from 10.99.99.2 on GigabitEthernet0/2, 00:04:11 ago
Routing Descriptor Blocks:
* 10.99.99.2, from 2.2.2.2, 00:04:11 ago, via GigabitEthernet0/2
Route metric is 1563, traffic share count is 1
! ^ 'intra area' over the 2 Mbps backdoor, with a metric far worse
! than the MPLS path - and it still wins, because type beats cost.
How Do I Build and Verify Both Features in One Lab?
What is the minimum working configuration for each?
A virtual link needs one line per ABR naming the transit area and the peer's Router ID, plus matching authentication if area 0 is authenticated. A sham-link needs more scaffolding: a /32 loopback in the VRF on each PE, those loopbacks advertised into BGP VPNv4 but deliberately not into the VRF's OSPF process, and one area X sham-link statement per PE naming local and remote loopback addresses. The sham-link cost should be set below the backdoor's end-to-end cost so the MPLS path wins after the link comes up.
A Deeper Dive into the Full Build and Verification
Virtual link build, both ends
! ===== R1 - ABR touching area 0 and transit area 1 =====
interface Loopback0
ip address 1.1.1.1 255.255.255.255
!
router ospf 1
router-id 1.1.1.1
network 10.0.1.0 0.0.0.255 area 0
network 10.1.12.0 0.0.0.255 area 1
area 1 virtual-link 2.2.2.2
!
! ===== R2 - ABR touching transit area 1 and area 2 =====
interface Loopback0
ip address 2.2.2.2 255.255.255.255
!
router ospf 1
router-id 2.2.2.2
network 10.1.12.0 0.0.0.255 area 1
network 10.2.23.0 0.0.0.255 area 2
area 1 virtual-link 1.1.1.1
Sham-link scaffolding: the VRF loopbacks
The endpoint loopbacks must be inside the VRF, must be /32, and must reach each other through BGP VPNv4 rather than through the customer's OSPF process. Advertising them in OSPF creates a recursion: the sham-link's own reachability would depend on the sham-link being up.
! ===== PE-1: sham-link endpoint loopback in the customer VRF =====
interface Loopback100
vrf forwarding CUST-A
ip address 10.0.0.1 255.255.255.255
!
! Advertise it in BGP so PE-2 learns it over VPNv4 - NOT in OSPF
router bgp 65000
address-family ipv4 vrf CUST-A
network 10.0.0.1 mask 255.255.255.255
redistribute ospf 100 vrf CUST-A match internal external
exit-address-family
! ===== PE-2: mirror image =====
interface Loopback100
vrf forwarding CUST-A
ip address 10.0.0.2 255.255.255.255
!
router bgp 65000
address-family ipv4 vrf CUST-A
network 10.0.0.2 mask 255.255.255.255
redistribute ospf 100 vrf CUST-A match internal external
exit-address-family
The sham-link statements
Source first, destination second, then the area and cost. Note the area must be the same area the backdoor link lives in — that is the entire point.
! ===== PE-1 =====
router ospf 100 vrf CUST-A
router-id 10.0.0.1
domain-id 0.0.0.100
network 172.16.1.0 0.0.0.255 area 1
area 1 sham-link 10.0.0.1 10.0.0.2 cost 20
!
! ===== PE-2 =====
router ospf 100 vrf CUST-A
router-id 10.0.0.2
domain-id 0.0.0.100
network 172.16.2.0 0.0.0.255 area 1
area 1 sham-link 10.0.0.2 10.0.0.1 cost 20
Verifying the sham-link
PE-1# show ip ospf sham-links
Sham Link OSPF_SL0 to address 10.0.0.2 is up
Area 1 source address 10.0.0.1
Run as demand circuit
DoNotAge LSA allowed.
Cost of using 20 State POINT_TO_POINT,
Timer intervals configured, Hello 10, Dead 40, Wait 40, Retransmit 5
Hello due in 00:00:03
Adjacency State FULL (Hello suppressed)
Index 2/2, retransmission queue length 0, number of retransmission 1
First 0x0(0)/0x0(0) Next 0x0(0)/0x0(0)
Last retransmission scan length is 1, maximum is 1
!
PE-1# show ip ospf 100 neighbor
Neighbor ID Pri State Dead Time Address Interface
10.0.0.2 0 FULL/ - - 10.0.0.2 OSPF_SL0
172.16.1.2 1 FULL/BDR 00:00:33 172.16.1.2 GigabitEthernet0/1
Proving the preference actually inverted
The test that matters is on the CE, not the PE. After the sham-link comes up, the remote prefix should still be intra-area — but now via the PE, with a lower metric than the backdoor path.
CE-1# show ip route 192.168.20.0
Routing entry for 192.168.20.0/24
Known via "ospf 1", distance 110, metric 31, type intra area
Last update from 172.16.1.1 on GigabitEthernet0/1, 00:00:47 ago
Routing Descriptor Blocks:
* 172.16.1.1, from 10.0.0.2, 00:00:47 ago, via GigabitEthernet0/1
Route metric is 31, traffic share count is 1
! ^ Still intra area, but now via the PE at metric 31 instead of the
! backdoor at 1563. Cost, not route type, is now deciding.
| Verification goal | Command | Healthy indicator | What a failure looks like |
|---|---|---|---|
| Virtual link adjacency | show ip ospf virtual-links |
State up, Adjacency State FULL (Hello suppressed) |
DOWN with no neighbour, or FULL with a numeric dead timer |
| Backbone contiguity restored | show ip ospf database router adv-router <ABR> |
Flags: B VL-endpoint and a link of type "a Virtual Link" |
Flags show only B; no virtual-link entry in the area 0 LSA |
| Sham-link adjacency | show ip ospf sham-links |
State up, correct cost, hellos suppressed |
No output at all, or the link listed with no adjacency |
| Endpoint reachability | show ip route vrf CUST-A 10.0.0.2 |
Learned via BGP, next hop the remote PE loopback | Learned via OSPF — the recursion trap |
| Preference inversion | show ip route on the CE |
type intra area, next hop toward the PE |
type intra area with the backdoor next hop, metric unchanged |
Which Virtual-Link and Sham-Link Mistakes Break Real Networks?
What fails most often, and what does each failure look like?
Five failures dominate. A stub transit area makes a virtual link impossible and produces no useful error. A dynamically chosen Router ID changes after a reload and breaks a working virtual link months later. A sham-link endpoint loopback advertised into the customer's OSPF process creates a recursion that makes the link flap or never come up. A domain-ID mismatch turns inter-area routes into externals, quietly changing every preference decision in the customer's network. And a virtual link left in place after a redesign becomes permanent technical debt, because it works and nobody knows why it exists.
A Deeper Dive into Failure Modes and Their Remedies
The stub transit area
A virtual link requires the transit area to carry full LSA information. If the area is stub, totally stubby, or NSSA, the endpoints cannot compute the intra-area path the virtual link depends on. IOS rejects the combination, but the rejection depends on configuration order — if the virtual link exists first and you then make the area stub, the link goes down rather than the command failing.
R1(config-router)# area 1 stub
! With a virtual link already configured through area 1, IOS responds:
% OSPF: Area 1 cannot be a stub, it has virtual links through it
! Reverse order fails differently - the virtual link simply never comes up
show ip ospf virtual-links reports DOWN. Cause: someone made the transit area stub or totally stubby to reduce the database size, not knowing a virtual link crossed it. Confirm: show ip ospf | section Area 1 and look for "It is a stub area". Fix: revert the area type, or eliminate the virtual link by giving the orphaned area a real backbone attachment. Document every virtual link in the area design so this change is caught at review.Router IDs that move
OSPF picks its Router ID from the highest loopback address, or the highest active interface address if no loopback exists. A virtual link references the peer's Router ID literally. Add a loopback with a higher address, or reload a router whose highest interface changed, and the virtual link points at an identifier nobody owns. The link goes down and the configuration still looks perfect.
! Always pin router IDs on virtual link endpoints - both ends
router ospf 1
router-id 1.1.1.1
! Changing an existing router-id requires a process restart to take effect:
! clear ip ospf process
! This is disruptive. Pin the ID at build time, not during an incident.
The sham-link recursion trap
This is the highest-value failure to understand, because the configuration that causes it looks entirely reasonable. If the sham-link endpoint loopback is advertised into the customer VRF's OSPF process — with a network statement, or by being covered by an existing one — then once the sham-link forms, PE-1 may learn 10.0.0.2 through the sham-link itself. The sham-link's transport now depends on the sham-link, and the adjacency collapses. It then re-forms through BGP, collapses again, and the link oscillates.
! WRONG - this network statement covers the sham-link loopback
router ospf 100 vrf CUST-A
network 10.0.0.0 0.255.255.255 area 1
! ^ 10.0.0.1/32 now advertised in OSPF. Recursion. Link flaps.
!
! RIGHT - keep the endpoint out of OSPF entirely, BGP carries it
router ospf 100 vrf CUST-A
network 172.16.1.0 0.0.0.255 area 1
!
router bgp 65000
address-family ipv4 vrf CUST-A
network 10.0.0.1 mask 255.255.255.255
! Diagnostic: the endpoint MUST be learned via BGP, not OSPF
PE-1# show ip route vrf CUST-A 10.0.0.2
Routing entry for 10.0.0.2/32
Known via "bgp 65000", distance 200, metric 0, type internal
Last update from 203.0.113.2 00:12:41 ago
! ^ 'bgp' here is correct. If it says 'ospf', you have the recursion bug.
Domain-ID mismatch masquerading as a design problem
Two PEs serving the same customer with different domain IDs re-originate each other's routes as Type 5 externals. Everything still reaches everything, so no alarm fires, but the customer's route selection changes: externals lose to both intra-area and inter-area routes, so any alternative path now wins more easily. The complaint arrives as "traffic is taking a strange path" weeks later.
! Compare domain IDs across PEs serving the same VRF
PE-1# show ip ospf 100 | include Domain ID
Domain ID type 0x0005, value 0.0.0.100
!
PE-2# show ip ospf 100 | include Domain ID
Domain ID type 0x0005, value 0.0.0.200
! ^ Mismatch. Customer sees O E2 where O IA was intended.
!
! Inspect the extended communities carried with the VPNv4 route
PE-2# show bgp vpnv4 unicast vrf CUST-A 192.168.10.0
Extended Community: RT:65000:100 OSPF DOMAIN ID:0x0005:0100000000
OSPF RT:1:2:0 OSPF ROUTER ID:10.0.0.1:0
show ip route <prefix> and compare the metric against the sum of costs along each path. Fix: lower the sham-link cost, or raise the backdoor interface cost with ip ospf cost on the CE. Deciding which is cleaner is a design question: the backdoor is usually meant to be a backup, so raising its cost states that intent explicitly.Virtual links as permanent architecture
RFC 2328 describes virtual links as a repair mechanism, and every design guide repeats that they are transitional. In practice they persist for years, because they work. The costs of leaving one in place are real: it makes the transit area load-bearing for backbone traffic, it creates a dependency on two specific Router IDs, and it constrains the transit area's type forever. Track them, review them, and treat a virtual link older than one design cycle as a defect in the area plan.
| Failure | Feature affected | Confirming command | Fix | Prevention |
|---|---|---|---|---|
| Stub transit area | Virtual link | show ip ospf | section Area |
Revert area type or re-attach the orphan area | Document virtual links in the area design |
| Router ID drift | Virtual link | show ip ospf | include Router ID |
Correct the peer ID; restart the process if the local ID changed | Pin router-id on every OSPF router |
| Area 0 authentication mismatch | Virtual link | debug ip ospf adj |
Add matching keys to the virtual-link statement | Configure authentication and the virtual link in one change |
| Endpoint advertised in OSPF | Sham-link | show ip route vrf X <endpoint> |
Remove the covering network statement; advertise in BGP only |
Use a dedicated loopback outside any OSPF network range |
| Domain ID mismatch | Sham-link / L3VPN | show ip ospf <pid> | include Domain ID |
Set the same explicit domain ID on all PEs for the VRF | Template the PE VRF configuration per customer |
| Sham-link cost too high | Sham-link | show ip route on the CE |
Lower sham-link cost or raise backdoor interface cost | Compute both end-to-end costs during design |
Conclusion
Strip away the configuration syntax and both features are doing the same structural thing: asserting an adjacency that the physical topology does not provide, so that a rule the protocol enforces unconditionally can be satisfied. OSPF requires a contiguous backbone and it requires that intra-area beats inter-area. Neither rule is negotiable, and neither has a knob. A virtual link satisfies the first rule by manufacturing a backbone attachment; a sham-link satisfies the second by manufacturing an intra-area path. Once you see them as assertions about topology rather than as tunnels or links, the restrictions stop feeling arbitrary — a virtual link needs full LSA information in the transit area because it must compute a real path underneath the assertion, and a sham-link needs its endpoints in BGP because the assertion cannot be its own foundation.
The methodology that follows is short. Classify the symptom as reachability or preference before touching a command, because that single distinction eliminates half the possible answers. Identify what each end of the logical link is keyed on — Router ID for a virtual link, IPv4 address for a sham-link — and pin that identifier so it cannot drift. Establish the underlying transport first and prove it independently: the transit-area path for a virtual link, the BGP VPNv4 route for a sham-link. Then verify in three steps rather than one: the adjacency, the database, and the downstream routing decision. The third step is where an apparently successful configuration is most often revealed to have changed nothing.
In production, the payoff is a network where the MPLS service the customer buys actually carries their traffic, and where an area that lost its backbone attachment during a merger keeps routing while the design is corrected. In the lab, the payoff is recognising in ten seconds which of the two a task is asking for, and knowing that the sham-link answer has four moving parts — loopback, BGP advertisement, domain ID, cost — rather than one. Build the reference topology, break each of the six failures in the table above, and read what each command reports while it is broken. That output is what you will actually be looking at when it matters.
External Links Recommendations
- RFC 2328 — OSPF Version 2: Section 15 defines virtual links, their configuration parameters, and the rule that their cost derives from the intra-area path.
- RFC 1793 — Extending OSPF to Support Demand Circuits: the DoNotAge bit and demand-circuit behaviour that both virtual links and sham-links inherit.
- RFC 4577 — OSPF as the PE/CE Protocol in BGP/MPLS IP VPNs: sham-links, the DN bit, domain IDs, and the OSPF extended communities.
- RFC 4364 — BGP/MPLS IP Virtual Private Networks: the VPNv4 address family and route distribution model the superbackbone is built on.
- Cisco — OSPF Virtual Link Configuration and Verification: worked examples with database output.
- Cisco IOS-XE OSPF Configuration Guide: current syntax for
area virtual-link,area sham-link,domain-id, andcapability vrf-lite. - Cisco Learning Network — CCIE Enterprise Infrastructure: blueprint and equipment details for the current lab exam.
Reference Notes
- RFC 2328, Section 15 — Virtual Links: definition, the requirement that both endpoints be area border routers of a common non-backbone transit area, and identification by Router ID.
- RFC 2328, Section 15 — the virtual link's InterfaceUp cost is the cost of the intra-area path between the two endpoints, and is therefore not independently configurable.
- RFC 2328, Section 3.6 — the rule that a virtual link's transit area must not be a stub area.
- RFC 2328, Section 16.2 — route preference ordering: intra-area, inter-area, then external, applied before metric comparison.
- RFC 2328, Appendix A.4.2 — Router LSA flag bits, including the V bit set by a virtual link endpoint.
- RFC 1793 — the DoNotAge bit and the treatment of demand circuits, including hello suppression on an established adjacency.
- RFC 4577, Section 4.2.7 — OSPF sham-links: purpose, endpoint addressing, and the requirement that endpoints be reachable other than via the sham-link itself.
- RFC 4577, Section 4.2.5 — the DN bit and its role in preventing routing loops between a PE and a multi-homed customer site.
- RFC 4577, Section 4.2.1 — the OSPF Domain Identifier extended community and its effect on whether a route is re-originated as a Type 3 summary or a Type 5 external.
- RFC 4577, Section 4.2.2 — the OSPF Route Type extended community carrying the original area and LSA type across the VPN backbone.
- RFC 4364 — BGP/MPLS IP VPN architecture: VPNv4 route distribution, route targets, and the PE-CE routing model.
- Cisco IOS-XE IP Routing OSPF Configuration Guide — syntax and behaviour of
area sham-link,domain-id, andcapability vrf-lite.