Wednesday, November 30, 2016

CCIE SPv4 - MPLS L2VPN - VPLS BGP Auto Discovery using BGP signaling with VLANs

Software versions:
IOS XE 15.5
IOS XR 5.3

The topology for this demo:

In this post we will be taking a look at a variation of the VPLS BGP AD with LDP where we simply replace LDP signaling with BGP. The configuration overall is pretty straightforward, there are a few differences obviously but most of it is the same. Now to be clear there are actually 2 different RFCs that are built around this capability, 4761 and 4762. Cisco went with 4762 and Juniper with with 4761. 4761 refers to BGP signalling and 4762 refers to LDP signalling.

RFC 4761
RFC 4762

In the first post, we took a look at VPLS BGP Auto Discovery with LDP signalling in an E-LAN design, meaning that all PEs had reachability to all other PEs, or a MP2MP design, literally like an Ethernet switch where 3 or more devices are plugged into switchports all in the same VLAN. BGP can also be configured this way, which is the point of this post. The other feature that hasn't been covered yet is the E-TREE design. The rooted P2MP design or a hub and spoke. E-LAN leverages the ability to keep the "auto-route-target" command on IOS/XE and the XRv boxes simply import/export all the different RT values available. Where in E-TREE you selectively import/export RT values on IOS and XRv. That will be in another post.

So you might ask yourself, why LDP vs BGP or vice versa? I asked the same question, both get the job done in my opinion, the major difference that I have seen is how they get it done. LDP is the born leader for label distribution, it's only goal in life is to propagate labels to all the participating routers. It is very easy to get up and running and then can be easily manipulated later with MPLS TE. BGP on the other hand, is a bit more involved. There is, in my opinion, more to learn in terms of how BGP signalling works than with LDP. If you have already learned how LDP works, UDP hello's to detect peers, TCP connection between LSRs to exchange label info, not much to it, for the most part anyways. BGP is significantly more involved.

With LDP, you configure it like you would a manual configuration, create the service instance, the l2vpn vfi and then bind them together with a bridge domain and it's pretty much working. With BGP on the other hand, you have to intelligently ID one device from the other, manually; give each device a label range to allocate labels for. There is some "genius" level math that goes on in the background to make sure PE1 and PE2 don't allocate the same labels for those PWs. I'll cover the math in a separate post. One thing that is a little easier with BGP signaling over LDP is the increase in support, meaning you don't have to increase the prefix length information to get the peering up.

One thing to note right away. you can't change the signaling protocol under the VFI while it is up and operational. The IOS parser will actually throw up an error if you try. I ended up just deleting the LDP VFI and rebuilding it with BGP. Almost the same configuration.

IOS
R3
l2vpn vfi context E_TREE
 vpn id 50693
 autodiscovery bgp signaling bgp
  ve id 3
  ve range 11
 address-family l2vpn vpls
  neighbor 192.168.1.15 activate
  neighbor 192.168.1.15 suppress-signaling-protocol ldp

R5
l2vpn vfi context E_TREE
 vpn id 50693
 autodiscovery bgp signaling bgp
  ve id 5
  ve range 11
 address-family l2vpn vpls
  neighbor 192.168.1.15 activate
  neighbor 192.168.1.15 suppress-signaling-protocol ldp

R6
l2vpn vfi context E_TREE
 vpn id 50693
 autodiscovery bgp signaling bgp
  ve id 6
  ve range 11
 address-family l2vpn vpls
  neighbor 192.168.1.15 activate
  neighbor 192.168.1.15 suppress-signaling-protocol ldp

IOS XR
XR1
l2vpn
 bridge group E-LAN
  bridge-domain E_LAN
   interface GigabitEthernet0/0/0/2.100
   !
   vfi E_LAN
    vpn-id 50693
    autodiscovery bgp
     rd 1:50693
     route-target import 1:50693
     route-target export 1:50693
     signaling-protocol bgp
      ve-id 11
      ve-range 11

Now we'll get the bridge domain on IOS setup.

R3
bridge-domain 100
 member GigabitEthernet3 service-instance 100
 member vfi E_TREE

R5
bridge-domain 100
 member GigabitEthernet2 service-instance 100
 member vfi E_TREE

R6
bridge-domain 100
 member GigabitEthernet2 service-instance 100
 member vfi E_TREE

There is no separate "bridge" configuration on XRv. It all is configured under the "l2vpn" configuration section.

Now we'll get the BGP part up and running. IOS for starters.

R3, R5 and R6
router bgp 1
 bgp log-neighbor-changes
 no bgp default ipv4-unicast
 neighbor 192.168.1.15 remote-as 1
 neighbor 192.168.1.15 transport connection-mode active
 neighbor 192.168.1.15 update-source Loopback0
 !
 address-family ipv4
 exit-address-family
 !
 address-family l2vpn vpls
  neighbor 192.168.1.15 activate
  neighbor 192.168.1.15 suppress-signaling-protocol ldp
 exit-address-family

XR1
router bgp 1
 address-family l2vpn vpls-vpws
 !
 neighbor 192.168.1.15
  remote-as 1
  update-source Loopback0
  session-open-mode active-only
  address-family l2vpn vpls-vpws
   Signalling ldp disable

OK, so now that we have that in place. Let's first verify the BGP configuration is working.

R3, R5 and R6, there will be slight differences in the output, unique to each router, but they are not worth highlighting.

sh bgp l2vpn vpls all
BGP table version is 12, local router ID is 192.168.1.3
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale, m multipath, b backup-path, f RT-Filter,
              x best-external, a additional-path, c RIB-compressed,
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found

     Network          Next Hop            Metric LocPrf Weight Path
Route Distinguisher: 1:50693
 *>  1:50693:VEID-3:Blk-1/136
                       0.0.0.0                            32768 ?
 *>i 1:50693:VEID-5:Blk-1/136
                       192.168.1.5              0    100      0 ?
 *>i 1:50693:VEID-6:Blk-1/136
                       192.168.1.6              0    100      0 ?
 *>i 1:50693:VEID-11:Blk-1/136
                       192.168.1.11                  100      0 i
 *>i 1:50693:VEID-11:Blk-10/136
                       192.168.1.11                  100      0 i


RP/0/0/CPU0:XR1#sh bgp l2vpn vpls sum
Process       RcvTblVer   bRIB/RIB   LabelVer  ImportVer  SendTblVer  StandbyVer
Speaker              24         24         24         24          24           0

Neighbor        Spk    AS MsgRcvd MsgSent   TblVer  InQ OutQ  Up/Down  St/PfxRcd
192.168.1.15      0     1    8691    8643       24    0    0    5d23h          3


RP/0/0/CPU0:XR1#sh bgp l2vpn vpls
Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop        Rcvd Label      Local Label
Route Distinguisher: 1:50693 (default for vrf E-LAN:E_LAN)
*>i3:1/32             192.168.1.3     300             nolabel
*>i5:1/32             192.168.1.5     506             nolabel
*>i6:1/32             192.168.1.6     42              nolabel
*> 11:1/32            0.0.0.0         nolabel         24130
*> 11:10/32           0.0.0.0         nolabel         24115

One thing to highlight, the "nolabel" in the output, that is an indication that the data plane is not functioning. However the control plane is, which is why we received information.

Now let's go check the bridge domain information and break that down.

R3#sh bridge-domain
Bridge-domain 100 (4 ports in all)
State: UP                    Mac learning: Enabled
Aging-Timer: 300 second(s)
    GigabitEthernet3 service instance 100
    vfi E_TREE neighbor 192.168.1.5 50693
    vfi E_TREE neighbor 192.168.1.6 50693
    vfi E_TREE neighbor 192.168.1.11 50693
   AED MAC address    Policy  Tag       Age  Pseudoport
   0   000C.29BB.45EF forward dynamic   299  E_TREE.1004012
   1   FFFF.FFFF.FFFF flood   static    0    OLIST_PTR:0xe7ef8c00
   0   000C.29C9.1F5C forward dynamic   299  GigabitEthernet3.EFP100
   0   000C.2994.B818 forward dynamic   291  E_TREE.1004013

R5#sh bridge-domain
Bridge-domain 100 (4 ports in all)
State: UP                    Mac learning: Enabled
Aging-Timer: 300 second(s)
    GigabitEthernet2 service instance 100
    vfi E_TREE neighbor 192.168.1.3 50693
    vfi E_TREE neighbor 192.168.1.6 50693
    vfi E_TREE neighbor 192.168.1.11 50693
   AED MAC address    Policy  Tag       Age  Pseudoport
   0   000C.29BB.45EF forward dynamic   297  GigabitEthernet2.EFP100
   1   FFFF.FFFF.FFFF flood   static    0    OLIST_PTR:0xe7f06c20
   0   000C.29C9.1F5C forward dynamic   298  E_TREE.1004023
   0   000C.2994.B818 forward dynamic   290  E_TREE.1004021


R6#sh bridge-domain
Bridge-domain 100 (4 ports in all)
State: UP                    Mac learning: Enabled
Aging-Timer: 300 second(s)
    GigabitEthernet2 service instance 100
    vfi E_TREE neighbor 192.168.1.3 50693
    vfi E_TREE neighbor 192.168.1.5 50693
    vfi E_TREE neighbor 192.168.1.11 50693
   AED MAC address    Policy  Tag       Age  Pseudoport
   0   000C.29BB.45EF forward dynamic   293  E_TREE.1004017
   1   FFFF.FFFF.FFFF flood   static    0    OLIST_PTR:0xe7fce020
   0   000C.29C9.1F5C forward dynamic   294  E_TREE.1004019
   0   000C.2994.B818 forward dynamic   296  GigabitEthernet2.EFP100

You will notice that on each router, the MAC for the EFP100 interface will change, this is indicative of the CE MAC being learned and propagated to the other PE routers.

R6 Provisioning of the PWs. ***I know it says "E_TREE" in the output, that is the name of the VFI, not the design***

XR1
XC VFI VC[E_TREE/pw100011]: Processing provision of vfi-pw (0.0.0.11, 50693)
XC VFI VC[E_TREE/pw100011]: Setting up circuit
XC VFI VC[E_TREE/pw100011]: Provision vfi-pw switch
XC VFI VC[E_TREE/pw100011]: Sending update message to client
XC VFI VC[E_TREE/pw100011]: Circuit attributes to client:
XC VFI VC[E_TREE/pw100011]:  i/f: 4002
XC VFI VC[E_TREE/pw100011]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100011]:  Circuit directive: Go Active
XC VFI VC[E_TREE/pw100011]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100011]:  Circuit Encap: VFI
XC VFI VC[E_TREE/pw100011]:  Interworking type: none
XC VFI VC[E_TREE/pw100011]:  Segment type: VFI
XC VFI VC[E_TREE/pw100011]:  Switch handle: 16413
XC VFI VC[E_TREE/pw100011]:  MTU: 1500
XC VFI VC[E_TREE/pw100011]:  I/F Str: pw100003
XC VFI VC[E_TREE/pw100011]:  Circuit string: vfi

R3
XC VFI VC[E_TREE/pw100010]: Processing provision of vfi-pw (0.0.0.3, 50693)
XC VFI VC[E_TREE/pw100010]: Setting up circuit
XC VFI VC[E_TREE/pw100010]: Provision vfi-pw switch
XC VFI VC[E_TREE/pw100010]: Sending update message to client
XC VFI VC[E_TREE/pw100010]: Circuit attributes to client:
XC VFI VC[E_TREE/pw100010]:  i/f: 4002
XC VFI VC[E_TREE/pw100010]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100010]:  Circuit directive: Go Active
XC VFI VC[E_TREE/pw100010]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100010]:  Circuit Encap: VFI
XC VFI VC[E_TREE/pw100010]:  Interworking type: none
XC VFI VC[E_TREE/pw100010]:  Segment type: VFI
XC VFI VC[E_TREE/pw100010]:  Switch handle: 20511
XC VFI VC[E_TREE/pw100010]:  MTU: 1500
XC VFI VC[E_TREE/pw100010]:  I/F Str: pw100003
XC VFI VC[E_TREE/pw100010]:  Circuit string: vfi

R3
XC VFI VC[E_TREE/pw100008]: Processing provision of vfi-pw (0.0.0.5, 50693)
XC VFI VC[E_TREE/pw100008]: Setting up circuit
XC VFI VC[E_TREE/pw100008]: Provision vfi-pw switch
XC VFI VC[E_TREE/pw100008]: Sending update message to client
XC VFI VC[E_TREE/pw100008]: Circuit attributes to client:
XC VFI VC[E_TREE/pw100008]:  i/f: 4002
XC VFI VC[E_TREE/pw100008]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100008]:  Circuit directive: Go Active
XC VFI VC[E_TREE/pw100008]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100008]:  Circuit Encap: VFI
XC VFI VC[E_TREE/pw100008]:  Interworking type: none
XC VFI VC[E_TREE/pw100008]:  Segment type: VFI
XC VFI VC[E_TREE/pw100008]:  Switch handle: 24609
XC VFI VC[E_TREE/pw100008]:  MTU: 1500
XC VFI VC[E_TREE/pw100008]:  I/F Str: pw100003
XC VFI VC[E_TREE/pw100008]:  Circuit string: vfi


Bringing up the PWs
XR1
XC VFI VC[E_TREE/pw100011]: Processing client Update message
XC VFI VC[E_TREE/pw100011]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100011]:  i/f: 4005
XC VFI VC[E_TREE/pw100011]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100011]:  Payload encap: Undefined
XC VFI VC[E_TREE/pw100011]:  Circuit Encap: Undefined
XC VFI VC[E_TREE/pw100011]:  Segment type: AToM
XC VFI VC[E_TREE/pw100011]:  Static VC: yes
XC VFI VC[E_TREE/pw100011]:  Control Word: no
XC VFI VC[E_TREE/pw100011]:  Fast Switchover: no
XC VFI VC[E_TREE/pw100011]:  I/F Str: pw100011
XC VFI VC[E_TREE/pw100011]:  Circuit string: 0.0.0.11:50693

R3
XC VFI VC[E_TREE/pw100011]: client update received for bd_id 64 all_up 0 pw up count 1
XC VFI VC[E_TREE/pw100011]: First pw up, starting the pw actv timer
XC VFI VC[E_TREE/pw100010]: Processing client Update message
XC VFI VC[E_TREE/pw100010]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100010]:  i/f: 4003
XC VFI VC[E_TREE/pw100010]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100010]:  Payload encap: Undefined
XC VFI VC[E_TREE/pw100010]:  Circuit Encap: Undefined
XC VFI VC[E_TREE/pw100010]:  Segment type: AToM
XC VFI VC[E_TREE/pw100010]:  Static VC: yes
XC VFI VC[E_TREE/pw100010]:  Control Word: no
XC VFI VC[E_TREE/pw100010]:  Fast Switchover: no
XC VFI VC[E_TREE/pw100010]:  I/F Str: pw100010
XC VFI VC[E_TREE/pw100010]:  Circuit string: 0.0.0.3:50693

R5
XC VFI VC[E_TREE/pw100008]: Processing client Update message
XC VFI VC[E_TREE/pw100008]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100008]:  i/f: 4004
XC VFI VC[E_TREE/pw100008]:  Status: UP (0x1)
XC VFI VC[E_TREE/pw100008]:  Payload encap: Undefined
XC VFI VC[E_TREE/pw100008]:  Circuit Encap: Undefined
XC VFI VC[E_TREE/pw100008]:  Segment type: AToM
XC VFI VC[E_TREE/pw100008]:  Static VC: yes
XC VFI VC[E_TREE/pw100008]:  Control Word: no
XC VFI VC[E_TREE/pw100008]:  Fast Switchover: no
XC VFI VC[E_TREE/pw100008]:  I/F Str: pw100008
XC VFI VC[E_TREE/pw100008]:  Circuit string: 0.0.0.5:50693

Final verification that the configurations between PEs are correctly negotiated

XR1
XC VFI VC[E_TREE/pw100011]: Processing client Update message
XC VFI VC[E_TREE/pw100011]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100011]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100011]:  Circuit Encap: Ethernet
XC VFI VC[E_TREE/pw100011]:  Segment type: AToM
XC VFI VC[E_TREE/pw100011]:  VLAN ID: 0
XC VFI VC[E_TREE/pw100011]: Update VC type not needed

R3
XC VFI VC[E_TREE/pw100010]: Processing client Update message
XC VFI VC[E_TREE/pw100010]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100010]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100010]:  Circuit Encap: Ethernet
XC VFI VC[E_TREE/pw100010]:  Segment type: AToM
XC VFI VC[E_TREE/pw100010]:  VLAN ID: 0
XC VFI VC[E_TREE/pw100010]: Update VC type not needed

R5
XC VFI VC[E_TREE/pw100008]: Processing client Update message
XC VFI VC[E_TREE/pw100008]: Circuit attributes from client:
XC VFI VC[E_TREE/pw100008]:  Payload encap: Ethernet
XC VFI VC[E_TREE/pw100008]:  Circuit Encap: Ethernet
XC VFI VC[E_TREE/pw100008]:  Segment type: AToM
XC VFI VC[E_TREE/pw100008]:  VLAN ID: 0
XC VFI VC[E_TREE/pw100008]: Update VC type not needed

Now that the PWs are built between the PWs, we need to propagate the BGP NLRI between them.

%BGP-5-ADJCHANGE: neighbor 192.168.1.15 Up

Initial updates received from peers
XR1
BGP(9): 192.168.1.15 rcvd UPDATE w/ attr: nexthop 192.168.1.11, origin i, localpref 100, originator 192.168.1.11, clusterlist 192.168.1.15, extended community RT:1:50693 L2VPN L2:0x0:MTU-1500
BGP(9): 192.168.1.15 rcvd 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136
BGP(9): bump net 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136, non bpath  added
BGP(9): 192.168.1.15 rcvd 1:50693:VEID-11:Blk-10:VBS-11:LB-24115/136
BGP(9): bump net 1:50693:VEID-11:Blk-10:VBS-11:LB-24115/136, non bpath  added

R3
BGP(9): 192.168.1.15 rcvd UPDATE w/ attr: nexthop 192.168.1.3, origin ?, localpref 100, metric 0, originator 192.168.1.3, clusterlist 192.168.1.15, extended community RT:1:50693 L2VPN L2:0x0:MTU-1500
BGP(9): 192.168.1.15 rcvd 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136
BGP(9): bump net 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136, non bpath  added

R5
BGP(9): 192.168.1.15 rcvd UPDATE w/ attr: nexthop 192.168.1.5, origin ?, localpref 100, metric 0, originator 192.168.1.5, clusterlist 192.168.1.15, extended community RT:1:50693 L2VPN L2:0x0:MTU-1500
BGP(9): 192.168.1.15 rcvd 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136
BGP(9): bump net 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136, non bpath  added




Label allocation values are reported to the local router from the remote peers.
R3
BGP-L2VPN: set net vbs 11 label base 300
BGP(9): nettable_walker called for 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136
BGP(9): best path[0] 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136 source 192.168.1.6 nh 192.168.1.3 vpls-id: L2VPN L2:0x0:MTU-1500
BGP(9): add XC RIB route 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136 masklen 136 L2VPN L2:0x0:MTU-1500 pathcount: 1 [0] LDP source:192.168.1.6 nexthop:192.168.1.3 RT:1:50693
BGP(9): net was 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136

R5
BGP-L2VPN: set net vbs 11 label base 506
BGP(9): nettable_walker called for 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136
BGP(9): best path[0] 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136 source 192.168.1.6 nh 192.168.1.5 vpls-id: L2VPN L2:0x0:MTU-1500
BGP(9): add XC RIB route 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136 masklen 136 L2VPN L2:0x0:MTU-1500 pathcount: 1 [0] LDP source:192.168.1.6 nexthop:192.168.1.5 RT:1:50693
BGP(9): net was 1:50693:VEID-6:Blk-1:VBS-11:LB-42/136

R6
BGP-L2VPN: set net vbs 11 label base 42
BGP(9): nettable_walker called for 1:50693:VEID-6:Blk-1:VBS-11:LB-42/136
BGP(9): nettable_walker 1:50693:VEID-6:Blk-1:VBS-11:LB-42/136 route sourced locally
BGP(9): net was 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136

XR1
BGP-L2VPN: set net vbs 9 label base 24130
BGP(9): nettable_walker called for 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136
BGP(9): best path[0] 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136 source 192.168.1.6 nh 192.168.1.11 vpls-id: L2VPN L2:0x0:MTU-1500
BGP(9): add XC RIB route 1:50693:VEID-11:Blk-1:VBS-9:LB-24130/136 masklen 136 L2VPN L2:0x0:MTU-1500 pathcount: 1 [0] LDP source:192.168.1.6 nexthop:192.168.1.11 RT:1:50693
BGP(9): net was 1:50693:VEID-11:Blk-10:VBS-11:LB-24115/136



Output from the remote peers informing R6 of the label ranges being allocated.

R3
BGP-L2VPN: modify prefix: LLB 0 LB 300
BGP(9): update modified for 1:50693:VEID-3:Blk-1:VBS-11:LB-300/136 VE ID 3 VBO 1 VBS 11 Label Base 300 /136

R5
BGP-L2VPN: modify prefix: LLB 0 LB 506
BGP(9): update modified for 1:50693:VEID-5:Blk-1:VBS-11:LB-506/136 VE ID 5 VBO 1 VBS 11 Label Base 506 /136

R6
BGP-L2VPN: modify prefix: LLB 0 LB 42
BGP(9): update modified for 1:50693:VEID-6:Blk-1:VBS-11:LB-42/136 VE ID 6 VBO 1 VBS 11 Label Base 42 /136

XR1
BGP-L2VPN: modify prefix: LLB 0 LB 24115
BGP(9): update modified for 1:50693:VEID-11:Blk-10:VBS-11:LB-24115/136 VE ID 11 VBO 10 VBS 11 Label Base 24115 /136



Now we can verify the CEs are able to reach each other.

R8#sh ospfv3 1 nei

          OSPFv3 1 address-family ipv6 (router-id 172.16.8.8)

Neighbor ID     Pri   State           Dead Time   Interface ID    Interface
172.16.9.9        1   FULL/DROTHER    00:00:39    12              GigabitEthernet1.100
172.16.10.10      1   FULL/DR         00:00:38    13              GigabitEthernet1.100

Excellent! This proves that the connectivity works as expected.

Thanks for stopping by!
Rob Riker, CCIE #50693

Sunday, November 27, 2016

CCIE SPv4 - MPLS - Static Labeling

Software versions:
IOS XE 15.5
IOS XR 5.3

The topology for this demo:
In this post we will take a look at how to configure static LSPs or Label Switch Paths. We won't be configuring static LSPs the entire path, but taking a look at the first 2 hops out and the last 2 hops in. This will let you see how to manually configure what LDP does automatically for us. The configuration is relatively straightforward for the most part. But as you will see, it is more an order of operations issue, meaning that when static labeling is configured and LDP has already been configured and converged, the dynamic labeling is preferred over the static labeling. 

The primary things that need to happen is the disabling of label advertisement, the filtering of label advertisement and binding of a prefix to a label so MPLS is able to recurse to the LFIB and find the next hop. In a previous post we configured the label ranges for both dynamic allocation and for static allocation, if that isn't done ahead of time, you won't have a static "table" to pull labels from. Think of it like a DHCP reservation, where we reserve the label based on IP prefix and not source MAC. 

During my testing of this feature, you won't be able to tell from the LFIB what labels were dynamically allocated vs statically assigned. You will have to reference the static label database to see what labels were affected. During our configuration I'll point out where we need to disable LDP so that the static labeling can take affect. We'll need to re-enable LDP to regain reachability between the peerings. 

To be clear, if you are motivated, you can create static mappings throughout the entire environment, I wouldn't advise that, but it is possible to be done. 

In case you haven't already configured the label range, we'll need to do that before we do anything else.

R3
mpls label range 300 399 static 3300 3399

mpls ldp neighbor 192.168.1.4 labels accept XR3_R6
mpls ldp label
 allocate global host-routes
no mpls ldp advertise-labels
ip access-list standard XR3_R6
 deny   192.168.1.13
 deny   192.168.1.6
 permit any
mpls static binding ipv4 192.168.1.6 255.255.255.255 3306
mpls static binding ipv4 192.168.1.6 255.255.255.255 output 10.3.4.4 411
mpls static binding ipv4 192.168.1.13 255.255.255.255 3313
mpls static binding ipv4 192.168.1.13 255.255.255.255 output 10.3.4.4 412

The top mapping is to R6 and the bottom mapping is to XR3, the first entry for both is the local mapping pulled from the static label range and the second entry is specifies an output towards the next hop, the next hop IP and the outgoing label. It is IMPERATIVE to make sure that if you're using LDP and then enabling static labeling that, you'll have to go to the next hop router, find out what that LSR has assigned as the "local" label and that will be how we populate labels 411 and 412. 

When we enabled the first mapping to R6, you will receive an error:
% Next hop 10.3.4.4 is an LDP peer (192.168.1.4:0) 
% Label learned from peer, if any, takes precedence
% Continuing with configuration of the label

To fix this issue, go to the interface, G1.34 and disable LDP autoconfig.
interface GigabitEthernet1.34
 no mpls ldp igp autoconfig

This will take down the LDP peering

%LDP-5-NBRCHG: LDP Neighbor 192.168.1.4:0 (1) is DOWN (LDP disabled on interface)

Now re-apply the static mapping for R6.

mpls static binding ipv4 192.168.1.6 255.255.255.255 3306

You'll need to jump to R4 and issue "show mpls ldp forwarding 192.168.1.6"

R4#sh mpls forwarding-table 192.168.1.6
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
411        518        192.168.1.6/32   19850461      Gi1.45     10.4.5.5

The "local label" of "411" is what needs to be populated next. 

mpls static binding ipv4 192.168.1.6 255.255.255.255 output 10.3.4.4 411

Now we can re-enable the LDP peering on R3 towards R4.

interface GigabitEthernet1.34
 mpls ldp igp autoconfig

%LDP-5-NBRCHG: LDP Neighbor 192.168.1.4:0 (1) is UP

Let's go ahead and do some verification.

R3#show mpls forwarding-table 192.168.1.6
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
3306       411        192.168.1.6/32   0             Gi1.34     10.3.4.4

R3#show mpls static binding
192.168.1.6/32: Incoming label: 3306
  Outgoing labels:
     10.3.4.4                 411

Since we want to apply static labels for XR3 as well, we'll have to repeat the same process we used for R6, I won't re-copy the configuration in here again, just follow the above steps. 

One thing to note on R3, to get to R6, we use the SPF towards R4, but for XR3 we have multiple paths that could be taken to get there. When you specify a local label and there are 2 or more ways to get there, if one way is statically configured and the other is dynamically built, you won't be able to tell the difference from the LFIB. You can statically configure both paths if you choose to do so. 

Let's configure the path to XR3 now, repeat the above steps as necessary to get the static configuration to take effect.

mpls static binding ipv4 192.168.1.13 255.255.255.255 3313
mpls static binding ipv4 192.168.1.13 255.255.255.255 output 10.3.4.4 412

You'll notice that for R6 I used label value 3306 and for XR3 I used 3313, it makes it easy to determine who I am sending traffic towards. I mentioned a couple times that you can't tell a static label from a dynamic label, mostly true, but I explicitly configured 3300-3399 as static labels, dynamically assigned labels fall under the 300-399 range. So I can tell when an LSP is static or dynamic. 

Let's see the output of the LFIB on R3 so we can see our handywork.

R3#show mpls forwarding-table 192.168.1.6
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
3306       411        192.168.1.6/32   0             Gi1.34     10.3.4.4

R3#show mpls forwarding-table 192.168.1.13
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
3313       412        192.168.1.13/32  0             Gi1.34     10.3.4.4
           24417      192.168.1.13/32  0             Gi1.143    10.14.3.14




Let's go over to R4 and get him setup to forward labeled traffic towards R3.


R4
mpls label range 400 499 static 4400 4499
mpls ldp label
 allocate global host-routes
no mpls ldp advertise-labels
mpls ldp advertise-labels for ALL
 mpls ldp autoconfig
mpls static binding ipv4 192.168.1.3 255.255.255.255 4403
mpls static binding ipv4 192.168.1.3 255.255.255.255 output 10.3.4.3 implicit-null
ip access-list standard ALL
 permit any

As you can see pretty much the same configuration, the only difference is that we're removing the Transport label on the PHP LSR. This is done with the "implicit null" command at the end of the second mapping statement. It does the exact same thing LDP does, but here it has to be manually configured to remove the label. There is an "explicit null" command as well for instances where the Transport label needs to be maintained to the PE. 

Let's go ahead and go back to R3 and do some ping/trace testing.

R3#ping 192.168.1.6 source lo0
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 192.168.1.6, timeout is 2 seconds:
Packet sent with a source address of 192.168.1.3
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/5/18 ms

R3#trace 192.168.1.6 source lo0 num
Type escape sequence to abort.
Tracing the route to 192.168.1.6
VRF info: (vrf in name/id, vrf out name/id)
  1 10.3.4.4 [MPLS: Label 411 Exp 0] 2 msec 1 msec 8 msec
  2 10.4.5.5 [MPLS: Label 518 Exp 0] 20 msec 20 msec 20 msec
  3 10.5.6.6 20 msec *  2 msec

To verify this we will consult the IP RIB, LFIB and CEF table.

R3#sh ip route 192.168.1.6
Routing entry for 192.168.1.6/32
  Known via "ospf 1", distance 110, metric 4, type intra area
  Last update from 10.3.4.4 on GigabitEthernet1.34, 04:08:31 ago
  Routing Descriptor Blocks:
  * 10.3.4.4, from 192.168.1.6, 04:08:31 ago, via GigabitEthernet1.34
      Route metric is 4, traffic share count is 1

R3#sh mpls forwarding-table 192.168.1.6
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
3306       411        192.168.1.6/32   0             Gi1.34     10.3.4.4

R3#sh ip cef 192.168.1.6
192.168.1.6/32
  nexthop 10.3.4.4 GigabitEthernet1.34 label 411

So as far as I can tell, and I think it's working! I have demonstrated a unidirectional static LSP, similar to how an MPLS TE tunnel would work, the difference being, we have no mechanism checking for constraints. We'll take a deep look at MPLS TE later on.



Now that we have done this on IOS, let's take a look at IOS XR. I ran into several issues, most of which I will point out here for your benefit. Most of it was minor operator error, yeah, I make mistakes too ;) I have resolved all of the issues seen, most of them very easy to rectify. I call them out as they weren't obvious at first, so I highlight them so you don't have to struggle like I did.

This will be a bidirectional static mapping, R3 to XR3 and the vice-versa. R3 points to R4, R4 points to R3; XR3 points to XR2, XR2 points to XR3. I'll breakdown the logic for completeness so you can see the IOS and XR variations.

As you can see the MPLS static configuration like most things in XR has its own configuration section. We specify the AFI and then setup the local label allocation for the prefix, then we have to tell the configuration how we want to forward data towards that destination prefix, there can be multiple path options, This will come into play during our HA deepdive when we begin MPLS TE where you may have multiple paths setup. When you specify a path, the outgoing interface, the next hop and the outgoing label, this is exactly what LDP does dynamically for us. 

XR3
mpls ldp
 address-family ipv4
  label
   local
    allocate for host-routes
    advertise
     for ALL
ipv4 access-list ALL
 10 permit ipv4 any any
!
mpls label range table 0 24300 24399
mpls static
 address-family ipv4 unicast
  local-label 24303 allocate per-prefix 192.168.1.3/32
   forward
    path 1 nexthop GigabitEthernet0/0/0/0.1213 10.12.13.12 out-label 24205


When you specify the label range in XR you specify it for table 0 or the global table, XRv doesn't allow you to add another table from a VRF in my testing.  You will notice that the range for dynamic labels is the same as static labels. However you can specify whatever label value you would like, I kept the value inside the range I defined previously.

I allocate the value 24303 for R3's loopback address, which is the end of the LSP.

Forward indicates rewriting capabilities to swap labels from the local label to the outgoing label.

With the nexthop info, be careful to specify a next hop IP and then the out-label. The out label, like IOS needs to be same that the next hop, XR2 uses to reach R3's loopback.

You can verify this is working with the following commands.

show mpls forwarding table prefix prefix/length

RP/0/0/CPU0:XR3#show mpls forwarding prefix 192.168.1.3/32
Sun Nov 27 19:49:14.328 UTC
Local  Outgoing    Prefix             Outgoing     Next Hop        Bytes
Label  Label       or ID              Interface                    Switched
------ ----------- ------------------ ------------ --------------- ------------
24303  24205       192.168.1.3/32     Gi0/0/0/0.1213 10.12.13.12     7236


show mpls lsd forwarding ipv4 detail | b 192.168.1.3/32
RP/0/0/CPU0:XR3#show mpls lsd forwarding ipv4 detail | b 192.168.1.3/32
Sun Nov 27 19:50:33.713 UTC
'default':4U, 192.168.1.3/32, (24303), 1 Paths
   1/1: IPv4, 'default':4U, Gi0/0/0/0.1213, nh=10.12.13.12, lbl=24205, flags=0x0
            nh-id=0x0, path-id=0, backup-path-id=0, load-metric=0
      BCDL priority:4, LSD queue:21, version:167, flag:0x28
      Installed Nov 26 23:10:45.909 (20:39:47 ago)

The important thing to note is that the "nh" is set to XR2s LAN address. This is very important, if not set in the mpls static configuration, recursion won't be successful. 


XR2
mpls ldp
 address-family ipv4
  label
   local
    allocate for host-routes
    advertise
     for ALL
    !
   !
  !
 !
!
ipv4 access-list ALL
 10 permit ipv4 any any
!
mpls label range table 0 24200 24299
mpls static
 address-family ipv4 unicast
  local-label 24233 allocate per-prefix 192.168.1.13/32
   forward
    path 1 nexthop GigabitEthernet0/0/0/0.1213 10.12.13.13 out-label pop

As you can see above, very similar configuration. The difference, and my first major issue was leaving the next hop IP out of the mpls static configuration, you'll notice below that the "nh" info has the next hop set to 10.12.13.13, it will be populated with "0.0.0.0" and the LSP will be broken, Traffic will not forward since the next hop is incorrectly set. Adding that info will fix that problem.

The other thing that is different is the " out-label" is set to "pop" or implicit null. This can also be set to "explicit-null" in the case you have to extend the Transport label to the PE. 

RP/0/0/CPU0:XR2#show mpls lsd forwarding ipv4 detail | b 192.168.1.13/32
Sun Nov 27 19:53:10.246 UTC
'default':4U, 192.168.1.13/32, (24233), 1 Paths
   1/1: IPv4, 'default':4U, Gi0/0/0/0.1213, nh=10.12.13.13, lbl=Pop, flags=0x0
            nh-id=0x0, path-id=0, backup-path-id=0, load-metric=0
      BCDL priority:4, LSD queue:21, version:90, flag:0x28
      Installed Nov 26 23:10:46.252 (20:42:24 ago)


RP/0/0/CPU0:XR3#show mpls lsd forwarding
24303, (IPv4, 'default':4U, 192.168.1.3/32), 1 Paths
   1/1: IPv4, 'default':4U, Gi0/0/0/0.1213, nh=10.12.13.12, lbl=24205, flags=0x0
24307, (IPv4, 'default':4U, 192.168.1.12/32), 1 Paths
   1/1: IPv4, 'default':4U, Gi0/0/0/0.1213, nh=10.12.13.12, lbl=3, flags=0x0

It's great that we have outputs that indicate that we should have reachability, but I'm in the game of actually seeing traces show up. So let's Trace R3 to XR3 and XR3 to R3 and make sure that our configuration works as it is intended to.

RP/0/0/CPU0:XR3#traceroute 192.168.1.3 source 192.168.1.13 num
Sun Nov 27 20:04:54.134 UTC

Type escape sequence to abort.
Tracing the route to 192.168.1.3

 1  10.12.13.12 [MPLS: Label 24205 Exp 0] 9 msec  0 msec  0 msec
 2  10.1.12.1 [MPLS: Label 115 Exp 0] 0 msec  0 msec  0 msec
 3  10.1.15.15 [MPLS: Label 24515 Exp 0] 0 msec  0 msec  0 msec
 4  10.15.4.4 [MPLS: Label 4403 Exp 0] 0 msec  0 msec  0 msec
 5  10.3.4.3 0 msec  *  0 msec

OK, so we have a solid trace, now, lets make sure the path taken is the correct path, we start with the IP RIB, then the LFIB, then the CEF table.

RP/0/0/CPU0:XR3#sh ip route 192.168.1.3
Sun Nov 27 20:05:40.781 UTC

Routing entry for 192.168.1.3/32
  Known via "ospf 1", distance 110, metric 6, type intra area
  Installed Nov 21 16:23:19.938 for 6d03h
  Routing Descriptor Blocks
    10.13.2.2, from 192.168.1.3, via GigabitEthernet0/0/0/0.132
      Route metric is 6
    10.12.13.12, from 192.168.1.3, via GigabitEthernet0/0/0/0.1213
      Route metric is 6

RP/0/0/CPU0:XR3#show mpls forwarding prefix 192.168.1.3/32
Sun Nov 27 20:06:46.326 UTC
Local  Outgoing    Prefix             Outgoing     Next Hop        Bytes
Label  Label       or ID              Interface                    Switched
------ ----------- ------------------ ------------ --------------- ------------
24303  24205       192.168.1.3/32     Gi0/0/0/0.1213 10.12.13.12     9980

RP/0/0/CPU0:XR3#show cef 192.168.1.3
Sun Nov 27 20:08:07.001 UTC
192.168.1.3/32, version 99, internal 0x1000001 0x20 (ptr 0xa13b8bf4) [1], 0x0 (0xa139ec20), 0xa28 (0xa152c208)
 Updated Nov 26 22:50:44.772
 local adjacency 10.12.13.12
 Prefix Len 32, traffic index 0, precedence n/a, priority 4
   via 10.12.13.12, GigabitEthernet0/0/0/0.1213, 7 dependencies, weight 0, class 0 [flags 0x0]
    path-idx 0 NHID 0x0 [0xa10441fc 0x0]
    next hop 10.12.13.12
    local adjacency
     local label 24303      labels imposed {24205}

So, the RIB, we see that we have a route for 192.168.1.3/32 out towards XR2 and R2. The next step is to determine if there is a label allocated both locally and one to reach the next hop. We see there is with 24303 is the local label and 24205 as the outgoing label. Then we go to the CEF table to see what path will be chosen by the router to get to R3s loopback. The CEF table has chosen the path towards XR2, it's the same amount of hops wither direction to R3, but XRv in my testing does not leverage ECMP, it will always chose one path.

R3#traceroute 192.168.1.13 source lo0 num
Type escape sequence to abort.
Tracing the route to 192.168.1.13
VRF info: (vrf in name/id, vrf out name/id)
  1 10.14.3.14 [MPLS: Label 24417 Exp 0] 6 msec
    10.3.4.4 [MPLS: Label 412 Exp 0] 4 msec
    10.14.3.14 [MPLS: Label 24417 Exp 0] 5 msec
  2 10.15.4.15 [MPLS: Label 24511 Exp 0] 4 msec
    10.14.15.15 [MPLS: Label 24511 Exp 0] 9 msec
    10.15.4.15 [MPLS: Label 24511 Exp 0] 6 msec
  3 10.1.15.1 [MPLS: Label 121 Exp 0] 13 msec 15 msec 15 msec
  4 10.1.12.12 [MPLS: Label 24233 Exp 0] 25 msec 20 msec 20 msec
  5 10.12.13.13 18 msec *  7 msec

R3 does the exact same thing as XR3. Let's break that path down as well from R3's recursion process.

R3#sh ip route 192.168.1.13
Routing entry for 192.168.1.13/32
  Known via "ospf 1", distance 110, metric 6, type intra area
  Last update from 10.3.4.4 on GigabitEthernet1.34, 2d20h ago
  Routing Descriptor Blocks:
  * 10.14.3.14, from 192.168.1.13, 2d20h ago, via GigabitEthernet1.143
      Route metric is 6, traffic share count is 1
    10.3.4.4, from 192.168.1.13, 2d20h ago, via GigabitEthernet1.34
      Route metric is 6, traffic share count is 1

R3#show mpls forwarding-table 192.168.1.13
Local      Outgoing   Prefix           Bytes Label   Outgoing   Next Hop
Label      Label      or Tunnel Id     Switched      interface
3313       412        192.168.1.13/32  0             Gi1.34     10.3.4.4
           24417      192.168.1.13/32  0             Gi1.143    10.14.3.14

R3#sh ip cef 192.168.1.13
192.168.1.13/32
  nexthop 10.3.4.4 GigabitEthernet1.34 label 412
  nexthop 10.14.3.14 GigabitEthernet1.143 label 24417

As you can see from the above trace, ECMP is available towards XR3 and is used. R3 looks in the RIB and finds a route to 192.168.1.13 via 2 different paths, one towards R4 and the other towards XR4. Next the LFIB is referenced and 2 LSPs are available, the local label for both is 3313 which is manually configured, outgoing label 412 is manually configured as well and was referenced from R4, outgoing label 24417 was learned via LDP. Now we have to reference the CEF table to determine how to forward the traffic. R3 will use both the path towards R4 and XR4 to get to XR3. The proof is in the trace output as well but knowing how to recurse is very important, it will aid us later on when using more advanced labeling techniques.

Thanks for stopping by!
Rob Riker, CCIE #50693