L3VPN Service
This page documents the L3VPN service end-to-end: how an operator creates one through the Streamlit catalog, what Infrahub does automatically, and how each vendor's configuration differs.
For field-level schema details see schema-reference.
User flow
Step-by-step
-
Catalog form — The operator fills in the VPN name, selects a tenant, picks a PE and a customer subnet for each site, and chooses a routing protocol (eBGP / static / connected).
-
Branch + objects — The catalog allocates a
vpn_idfromvpn_id_pool, opens a feature branch, and writesServiceL3Vpn+ServiceL3VpnSiteobjects to Infrahub. All objects start withstatus = draft / provisioning. -
Proposed Change — The catalog opens a
CoreProposedChangefrom the feature branch intomain. This triggers the generator and checks automatically. -
Generator run —
L3VpnGeneratordoes all heavy lifting:- Creates an
IpamVRFwithvrf_rd = <provider-asn>:<vpn_id>. - Creates matching import and export route targets.
- Selects the lowest-numbered free interface on the PE.
- Allocates a /30 from
pe_ce_pooland creates the PE and CE IP addresses. - Places the customer subnet prefix into the VRF.
- Creates a
RoutingBGPSession(eBGP,session_type = EXTERNAL) whenrouting_protocol = ebgp. - Promotes
ServiceL3Vpn.statustoactiveandServiceL3VpnSite.statustoactive.
- Creates an
-
Checks — Four checks must pass before merge is allowed (see Checks below).
-
Transforms — Configuration artifacts are rendered for each PE that has at least one L3VPN site.
-
Merge — The operator reviews the diff in the Infrahub UI and merges. On the target platform the artifact is pushed via the relevant
invoketask (e.g.invoke lab.push-arista).
Checks
| Check | File | What it enforces |
|---|---|---|
l3vpn_overlap | checks/l3vpn_overlap.py | No two active ServiceL3Vpn objects share the same vpn_id |
l3vpn_site_subnet | checks/l3vpn_site_subnet.py | The customer subnet is not already claimed by another site in the same VRF |
pe_interface_alloc | checks/pe_interface_alloc.py | The nominated PE interface exists and has status = free |
backbone_session_count | checks/backbone_session_count.py | Every PE in the backbone has at least 3 iBGP sessions (full-mesh invariant) |
A failing check blocks merge of the proposed change. The operator can see the check result in the Infrahub UI under the proposed change's Checks tab.
Generator: what it creates
| Object | Created by | Notes |
|---|---|---|
IpamVRF | _ensure_vrf | Name = VPN name; vrf_rd = <asn>:<vpn_id> |
IpamRouteTarget | find_or_create_route_target | Same value used for import and export RT |
InterfacePhysical (updated) | next_free_physical_interface | Lowest free-status interface on the PE; role set to cust |
IpamPrefix (/30) | allocate_prefix_from_pool | Allocated from pe_ce_pool; placed in VRF |
IpamIPAddress × 2 | direct create | .1 = PE, .2 = CE within the /30 |
RoutingBGPSession | _ensure_ebgp_session | Only when routing_protocol = ebgp; session_type = EXTERNAL |
The generator is idempotent: re-running it on an L3VPN that already has a VRF and allocated addresses will skip re-creation and only update missing fields.
Per-vendor configuration
The transform layer renders a full configuration fragment for each PE when that PE has at least one active L3VPN site. Configuration sections differ by vendor:
Arista EOS
vrf instance <name>
rd <asn>:<vpn_id>
!
router bgp <asn>
vrf <name>
rd <asn>:<vpn_id>
route-target import <rt>
route-target export <rt>
neighbor <ce-ip> remote-as <ce-asn>
network <customer-subnet>
Cisco IOS-XR
vrf <name>
address-family ipv4 unicast
import route-target
<rt>
export route-target
<rt>
!
router bgp <asn>
vrf <name>
rd <asn>:<vpn_id>
address-family ipv4 unicast
neighbor <ce-ip>
remote-as <ce-asn>
Juniper Junos
routing-instances {
<name> {
instance-type vrf;
interface <pe-iface>;
vrf-target target:<rt>;
protocols {
bgp {
group PE-CE {
neighbor <ce-ip> {
peer-as <ce-asn>;
}
}
}
}
}
}
Nokia SR OS
service {
vprn "<name>" customer "1" create
route-distinguisher <rd>
vrf-target target:<rt>
interface "<pe-iface>" create
address <pe-ip>/<mask>
sap <port>:0 create
exit
exit
bgp-vpn-backup
no shutdown
exit
}