Unified MPLS

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.

#Access1
router bgp 100
 neighbor 2.2.2.2 remote-as 100
 neighbor 2.2.2.2 update-source Lo0
 
 

#Agg1
router bgp 100
 neighbor 1.1.1.1 remote-as 100
 neighbor 1.1.1.1 update-source Lo0
 neighbor 1.1.1.1 send-label
 neighbor 1.1.1.1 
 neighbor 1.1.1.1 route-reflector-client
 neighbor 5.5.5.5 remote-as 100
 neighbor 5.5.5.5 update-source Lo0
 neighbor 5.5.5.5 send-label
 neighbor 5.5.5.5 next-hop-self all
 neighbor 5.5.5.5 route-reflector-client
 
#Agg2
router bgp 100
 
 address-family ipv4 unicast
  
 !
 neighbor 2.2.2.2
  remote-as 100
  update-source Lo0
  
   route-reflector-client
   next-hop-self
 !
  neighbor 6.6.6.6
  remote-as 100
  update-source Lo0
  address-family ipv4 labeled-unicast
   route-reflector-client
   next-hop-self

#Access2
router bgp 100
 address-family ipv4 unicast
  network 6.6.6.6/32
  allocate-label all
 !
  neighbor 5.5.5.5
  remote-as 100
  update-source Lo0
  address-family ipv4 labeled-unicast

We now have an LSP between Access1 and Access2:

Access1#traceroute 6.6.6.6 source lo0 probe 1
Type escape sequence to abort.
Tracing the route to 6.6.6.6
VRF info: (vrf in name/id, vrf out name/id)
  1 10.1.2.2 [MPLS: Label 22 Exp 0] 13 msec
  2 10.2.3.3 [MPLS: Labels 19/24005 Exp 0] 13 msec
  3 10.3.4.4 [MPLS: Labels 24003/24005 Exp 0] 10 msec
  4 10.4.5.5 [MPLS: Label 24005 Exp 0] 12 msec
  5 10.5.6.6 11 msec

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!

Last updated