SR Linux MPLS/VPN Configuration Notes
After fixing the SR Linux LDP configuration template, I decided to add MPLS/VPN to the netlab SR Linux MPLS features. After all, the one-page recipe seemed simple enough, more so as we already have tested VRF and EVPN templates.
Alas, nothing is as simple as it looks. There were two details that tripped me pretty badly.
BGP Address Families
SR Linux configures BGP address families in two places: within the BGP protocol and within individual BGP neighbors. I should have just copied the documentation recipe, but of course, I didn’t. netlab SR Linux BGP configuration already has per-neighbor BGP address families, so I just activated l3vpn-ipv4-unicast AF within all IBGP neighbors, and the weirdest thing happened:
- The L3VPN address family was negotiated on the IBGP sessions.
- The BGP neighbor sent its routes over the L3VPN address family, and SR Linux silently1 ignored them.
- When I was inspecting the L3VPN IPv4 unicast routes, I could see none, but there was also no error message.
A:admin@dut# show protocols bgp routes l3vpn-ipv4-unicast summary------------------------------------------------------------------------------------------------------------------------------------Show report for the BGP route table of network-instance "default"------------------------------------------------------------------------------------------------------------------------------------Status codes: u=used, *=valid, >=best, x=stale, b=backup, w=unused-weight-onlyOrigin codes: i=IGP, e=EGP, ?=incomplete------------------------------------------------------------------------------------------------------------------------------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+| Status | Route | Network | Next Hop | MED | LocPref | Path Val || | Distinguisher | | | | | |+=================+=================+=================+=================+=================+=================+=================++-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+-----------------+------------------------------------------------------------------------------------------------------------------------------------0 received BGP routes: 0 used, 0 valid, 0 stale0 available destinations: 0 with ECMP multipaths------------------------------------------------------------------------------------------------------------------------------------
After adding the L3VPN IPv4 unicast address family and configuring keep-all-routes, I could see the routes advertised by the BGP peer, but they were still not used. Detailed printouts told me the routes were rejected:
A:admin@dut# show protocols bgp routes l3vpn-ipv4-unicast prefix 172.16.1.0/24 detail------------------------------------------------------------------------------------------------------------------------------------Show report for the BGP routes to network "172.16.1.0/24" network-instance "default"------------------------------------------------------------------------------------------------------------------------------------Route-distinguisher: 65000:1 Network: 172.16.1.0/24Received Paths: 1Path 1: <>Route source : neighbor 10.0.0.6Route Preference : MED is -, LocalPref is 100BGP next-hop : 10.0.0.6Path : iDomain Path : NoneCommunities : target:65000:1RR Attributes : No Originator-ID, Cluster-List is [ - ]Aggregation : Not an aggregate routeUnknown Attr : NoneInvalid Reason : Rejected_RouteTie Break Reason : noneRoute Flap Damping: None------------------------------------------------------------------------------------------------------------------------------------
It’s the Labels, STUPID!
I wasted hours before figuring out I had to read the small print in that IP-VPN SR Linux recipe:
As a prerequisite, a label block must be configured using the system mpls services network-instance dynamic-label-block name configuration.
The small print included a pointer to another document explaining how to configure the label block. I added the prerequisite label block, and all of a sudden, everything worked.
Here’s the label block configuration netlab uses. It sure would have been nice to have it included in the configuration recipe.
--{ + running }--[ system mpls ]--A:admin@dut# infolabel-ranges {dynamic ldp {start-label 10000end-label 15000}dynamic vpn {start-label 20000end-label 30000}}services {network-instance {dynamic-label-block vpn}}
It also turned out that the address-family configuration at the protocols bgp level was a red herring. All you have to configure to have a working MPLS/VPN network (assuming you have already configured VRF network instances and LDP) are the services label block and per-neighbor L3VPN address families.
Alternatively, you could just configure the L3VPN address family at the protocols bgp level, and it would be activated for all BGP neighbors.
A Note On Route Distinguishers and Route Targets
The SR Linux IP-VPN recipe I keep mentioning glosses over an important detail: if you don’t set the route distinguisher and route targets in the protocols bgp-vpn configuration of a VRF network instance, the system uses EVPN auto-derived RD/RT values, which might not be the best solution for an MPLS/VPN network.
Here’s how netlab sets them when configuring SR Linux for the “connect subnets” MPLS/VPN integration test:
--{ + running }--[ network-instance t1 ]--A:admin@dut# info protocols bgp-vpnbgp-instance 1 {route-distinguisher {rd 65000:1}route-target {export-rt target:65000:1import-rt target:65000:1}}
Want to Kick the Tires?
The MPLS/VPN on SR Linux functionality will be part of the 26.06 release. It is already merged into the netlab dev branch, so you can check it out from a local copy of the netlab repository.
To make MPLS/VPN work on SR Linux, you’ll have to set the clab.type node attribute to ixr-6e or similar (details), or change the defaults.devices.srlinux.clab.node.type default setting. You’ll also need a license file; its location can be specified in the clab.license node attribute or defaults.devices.srlinux.clab.node.license default setting.
-
Or not, maybe it was screaming into a log file I haven’t found yet. ↩︎