Unified MPLS, also called Seamless MPLS, was defined in draft-ietf-mpls-seamless-mpls-07. This is not really a new technology, but a combination of tools to allow for multiple IGP islands within a single AS. This allows you to form end-to-end LSPs even though you don’t have a single IGP. (An end-to-end LSP is an LSP in which the bottom service label never changes).
This is sort of like Inter-AS VPNs, but you could call it “Inter-Domain IGP / Intra-Domain AS”. The service provider has multiple, separate IGP processes for scalability, but a single BGP AS.
Imagine the following topology, which we will use for our lab:
For scalability, the service provider has created a single OSPF process for each agg router and all access routers that connect to that agg router. For brevity only a single access router connects to each agg in our lab. The core, comprising of all agg and core routers, runs ISIS.
What happens if we want to have an LSP from Access1 to Access2? By default, this will not work, as Access1 does not know Access2’s loopback and vice versa. You could redistribute all loopbacks into every IGP process, but this kind of defeats the purpose of having multiple IGPs. If you have thousands of routers in each IGP process, you don’t want to flood the IGP with thousands of external /32s.
The Unified MPLS solution uses BGP-LU (Labeled Unicast) to exchange the /32 loopbacks of access routers in the topology. BGP is much better equiped to handle a large number of routes than IGP is.
The agg routers are ASBRs, because they participate in both the ISIS core and the OSPF processes. The access routers will run BGP-LU with the Agg router in their area. The agg routers will also run BGP-LU between each other. The core can stay “BGP-Free” as no CEs or services connect directly to the core.
The potential problem with this is that, by default, when an iBGP route is reflected to another iBGP router, you cannot alter the next-hop. Access1 will get a /32 route for Access2 but pointing to Access2. Obviously this cannot work. Agg1 needs to insert itself into the path by setting the next-hop of the /32 for Access2 to itself when it advertises the route to Access1. In order to change the next-hop on iBGP learned routes that are advertised to iBGP peers you have to use a special command:
IOS-XE: next-hop-self all on the neighbor statement
IOS-XR: ibgp policy out enforce-modifications globally + next-hop-self on the neighbor’s AFI/SAFI
Let’s set this up in our lab so you can get a better understanding of how this works.
Lab
First we’ll configure standard IGP/LDP on all routers. Remember there is no redistribution between the IGP processes. On the agg routers we’ll advertise the loopback into both IGPs.
#Access1
hostname Access1
!
line con 0
logging sync
!
int Gi1
ip address 10.1.2.1 255.255.255.0
no shut
mpls ip
ip ospf network point-to-point
!
int Lo0
ip address 1.1.1.1 255.255.255.255
!
router ospf 1
network 0.0.0.0 255.255.255.255 area 0
#Agg1
hostname Agg1
!
line con 0
logging sync
!
int Gi1
ip address 10.1.2.2 255.255.255.0
no shut
mpls ip
ip ospf network point-to-point
!
int Gi2
ip address 10.2.3.2 255.255.255.0
no shut
mpls ip
ip router isis
isis network point-to-point
!
int Lo0
ip address 2.2.2.2 255.255.255.255
ip router isis
!
router ospf 1
network 10.1.2.0 0.0.0.255 area 0
network 2.2.2.2 255.255.255.255 area 0
!
router isis
net 49.0001.0000.0000.0002.00
is-type level-2-only
metric-style wide
#Core1
hostname Core1
!
line con 0
logging sync
!
int Gi1
ip address 10.3.4.3 255.255.255.0
no shut
mpls ip
ip router isis
isis network point-to-point
!
int Gi2
ip address 10.2.3.3 255.255.255.0
no shut
mpls ip
ip router isis
isis network point-to-point
!
int Lo0
ip address 3.3.3.3 255.255.255.255
ip router isis
!
router isis
net 49.0001.0000.0000.0003.00
is-type level-2-only
metric-style wide
#Core2
hostname Core2
!
int Gi0/0/0/0
ip address 10.3.4.4/24
no shut
!
int Gi0/0/0/1
ip address 10.4.5.4/24
no shut
!
int lo0
ip address 4.4.4.4/32
!
router isis 1
net 49.0001.0000.0000.0004.00
is-type level-2-only
address-family ipv4 unicast
metric-style wide
int Gi0/0/0/0
point-to-point
address-family ipv4 unicast
int Gi0/0/0/1
point-to-point
address-family ipv4 unicast
int Lo0
address-family ipv4 unicast
!
mpls ldp
int Gi0/0/0/0
int Gi0/0/0/1
#Agg2
hostname Agg2
!
int Gi0/0/0/0
ip address 10.5.6.5/24
no shut
!
int Gi0/0/0/1
ip address 10.4.5.5/24
no shut
!
int lo0
ip address 5.5.5.5/32
!
router isis 1
net 49.0001.0000.0000.0005.00
is-type level-2-only
address-family ipv4 unicast
metric-style wide
int Gi0/0/0/1
point-to-point
address-family ipv4 unicast
int Lo0
address-family ipv4 unicast
!
router ospf 2
area 0
int Gi0/0/0/0
int Lo0
!
mpls ldp
int Gi0/0/0/0
int Gi0/0/0/1
#Access2
hostname Access2
!
int Gi0/0/0/0
ip address 10.5.6.6/24
no shut
!
int lo0
ip address 6.6.6.6/32
!
router ospf 2
area 0
int Gi0/0/0/0
int Lo0
!
mpls ldp
int Gi0/0/0/0
Now we’ll configure BGP-LU on the access and agg routers. Each access router advertises its own loopback. The agg routers treat access routers as RR clients and each other as RR clients.
Let’s go hop-by-hop and understand where each label came from.
Hop1
Label 22 is imposed because this is the label that Agg1 advertised to Access1 for 6.6.6.6/32 via BGP-LU.
Access1#show bgp ipv4 unicast labels
Network Next Hop In label/Out label
1.1.1.1/32 0.0.0.0 imp-null/nolabel
6.6.6.6/32 2.2.2.2 nolabel/22
Access1#show bgp ipv4 unicast 6.6.6.6/32
BGP routing table entry for 6.6.6.6/32, version 5
Paths: (1 available, best #1, table default)
Not advertised to any peer
Refresh Epoch 1
Local
2.2.2.2 (metric 2) from 2.2.2.2 (2.2.2.2)
Origin IGP, metric 0, localpref 100, valid, internal, best
Originator: 6.6.6.6, Cluster list: 2.2.2.2, 5.5.5.5
mpls labels in/out nolabel/22
rx pathid: 0, tx pathid: 0x0
Updated on Aug 18 2022 23:44:34 UTC
Hop2
Agg1 swaps label 22 for label 24005, because this is the label that Agg2 advertised to Agg1 via BGP-LU.
Agg1#show bgp ipv4 unicast labels
Network Next Hop In label/Out label
1.1.1.1/32 1.1.1.1 16/imp-null
6.6.6.6/32 5.5.5.5 22/24005
Agg1 also needs to push the transport label representing Agg2’s loopback, as Core1 and Core2 are BGP-free. This is very similar to vpnv4, where the top label seen in the core is the label representing the remote PE’s loopback.
Agg1#show mpls forwarding-table 5.5.5.5
Local Outgoing Prefix Bytes Label Outgoing Next Hop
Label Label or Tunnel Id Switched interface
21 19 5.5.5.5/32 0 Gi2 10.2.3.3
Hop3
Core1 swaps 19 for 24003. This is a normal LDP operation.
Core1#show mpls forwarding-table 5.5.5.5
Local Outgoing Prefix Bytes Label Outgoing Next Hop
Label Label or Tunnel Id Switched interface
19 24003 5.5.5.5/32 7971 Gi1 10.3.4.4
Hop4
Core2 pops label 24003 and delivers to Agg2. This is another normal LDP operation.
RP/0/0/CPU0:Core2#show mpls forwarding prefix 5.5.5.5/32
Thu Aug 18 23:53:58.524 UTC
Local Outgoing Prefix Outgoing Next Hop Bytes
Label Label or ID Interface Switched
------ ----------- ------------------ ------------ --------------- ------------
24003 Pop 5.5.5.5/32 Gi0/0/0/1 10.4.5.5 9684
Hop5
Agg2 pops the BGP-LU label that it advertised to Agg1 and delivers to Access2
RP/0/0/CPU0:Agg2#show mpls forwarding labels 24005
Thu Aug 18 23:55:01.240 UTC
Local Outgoing Prefix Outgoing Next Hop Bytes
Label Label or ID Interface Switched
------ ----------- ------------------ ------------ --------------- ------------
24005 Pop 6.6.6.6/32 Gi0/0/0/0 10.5.6.6 8981
RP/0/0/CPU0:Agg2#show bgp ipv4 unicast labels
<snip>
Network Next Hop Rcvd Label Local Label
*>i1.1.1.1/32 2.2.2.2 16 24006
*>i6.6.6.6/32 6.6.6.6 3 24005
The labels that Agg1 and Agg2 advertised to each other over BGP-LU are actually just the LDP labels allocated for the prefixes 1.1.1.1/32 and 6.6.6.6/32 that were already allocated.
Adding an L2VPN Service
Let’s test the end-to-end LSP by adding an L2VPN service between Access1 and Access2. If you would like to follow along, you will need to swap Access2 XRv for a XRv9000.
CE1 connects to Access1 on Gi2:
CE2 connects to Access2 on Gi0/0/0/1:
#CE1
hostname CE1
!
line con 0
logging sync
!
int Gi1
ip address 10.1.1.1 255.255.255.252
no shut
#CE2
hostname CE2
!
line con 0
logging sync
!
int Gi1
ip address 10.1.1.2 255.255.255.252
no shut
#Access1
int Gi2
no shut
service instance 1 ethernet
encapsulation default
xconnect 6.6.6.6 1 encapsulation mpls
#Access2
int Gi0/0/0/1 l2transport
no shut
!
l2vpn xconnect group XC p2p CUSTOMER1
int Gi0/0/0/1
neighbor 1.1.1.1 pw-id 1
Test your understanding
Question: How many labels are seen on the link between Agg1 and Core1 when CE1 pings CE2?
Answer: Three. The top label is the transport label which represents Agg2. The middle label is the BGP label that Agg2 advertised for 6.6.6.6/32. The bottom label is the service label which Access2 advertised to Access1 for this L2VPN.
19 is the transport label, 24005 is the BGP label, and 24000 is the service label.
Question: Why didn’t we need to run BGP between Access1 and Access2 for this L2VPN to work?
Answer: The xconnect is a Martini circuit. This uses targeted LDP to exchange the service label. See the section “IOS-XE Ethernet Services/E-Line” for more information or practice.
What is interesting is that because Access1 and Access2 only know each other via a labeled path, the targeted LDP Hellos are actually MPLS-encapsulated!