TI-LFA FTW!

Having fast convergence times is one of most important aspects of running any Service Provider network. But perhaps more important is making sure that you actual have the necessary backup paths in the first place.

This quirk explores a network within which neither Classic Loop Free Alternate (LFA) nor Remote-LFA (R-LFA) provide complete backup coverage, and how Segment Routing can solve this using a technology called Topology Independent Loop Free Alternate (or TI-LFA).

This blog comes with a downloadable EVE-NG lab that can be found here. It is configured with the final TI-LFA and SR setup, but I’ll provide the configuration examples for both Classic-LFA and R-LFA as we go. We’ll just look at link protection in this post, but the principle for node and SRLG protection is similar.

I’ll assume anyone reading is well versed in the IGP + LDP Service Provider core model but will give a whistle stop introduction to Segment Routing for those who haven’t run into it yet…

Segment Routing – A Brief Introduction

Segment Routing (or SR) is one of the most exciting new technologies in the Service Provider world. On the face of it, it looks like “just another way to communicate labels” but once you dig into it, you’ll realise how powerful it can be.

This introduction will be just enough to get you to understand this post if you’ve never used SR before. I highly recommend checking out segment-routing.net for more information.

The best way to introduce SR is to compare it to LDP. So to that end, here’s a basic diagram as a reminder of how LDP works:

R3 is advertising its 1.1.1.3/32 loopback via ISIS and LDP communicates label information. This should hopefully be very familiar.

So how does SR differ?

Well, the difference is in how the label is communicated. Instead of using an extra protocol, like LDP, the label information is carried in the IGP itself. In the case of ISIS, it uses TLVs. In the case of OSPF it uses opaque LSAs (which are essentially a mechanism for carrying TLVs in and of themselves).

This means that instead of each router allocating is own label for every single prefix in its IGP routing table and then advertising these to their neighbors using multiple LDP sessions, the router that sources the prefix advertises its label information inside its IGP update packets. Only the source router actually does any allocating.

Before I show you a diagram, let’s get slightly technical about what SR is…

Segment Routing is defined as … “a source-based routing paradigm that uses stacks of instructions – referred to as Segments – to forward packets”. This might seem confusing, but basically Segments are MPLS Labels (they can also be IPv6 headers but we’ll just deal with MPLS labels here). Each label in a stack can be thought of as an instruction that tells the router what do with the packet.

There are two types of Segments (or instructions) we need to be concerned with in this post. Node-SIDs and Adj-SIDs.

  1. A Node-SID in a Service Provider network typically refers to a loopback address of a router that something like BGP would use as the next-hop (e.g. it puts the self in next-hop-self). This is analogous to the LDP label for a given IGP prefix that each route in an ISP core would assign. The “instruction” for a Node-SID is forward this packet on to the prefix along your best ECMP path for it.
  2. An Adj-SID represents a routers IGP neighborship. An Adj-SID has the “instruction” of forwarding this packet out of the interface toward this neighbor.

So how are these allocated and adverted?

Like I said before, they use the TLVs (or opaque LSAs) of the IGPs involved. But the advertisements of Adj-SIDs and Node-SIDs do differ slightly…

Adj-SIDs are (by default) automatically allocated from the default MPLS label pool (the same pool used to allocate LDP labels) and are simply advertised inside the TLV “as is”. There is more than one type of Adj-SIDs for each IGP nieghbor… they come in both protected/unprotected and IPv4/IPv6 flavours. This post will only deal with IPv4 unprotected, so don’t worry about the others for now.

The Node-SID is a little more complicated. It is statically assigned under the IGP config and comes from a reserved label range called the SRGB or Segment Routing Global Block. This is a different block from the default MPLS one and the best way to understand it is to put it in context…

Let’s say your SRGB is 17000-18999. This is range of 2000 labels. And let’s say that each router in the network get’s a Node-SID based on its router number (e.g. R5 gets Node-SID 17005 etc..). Well when a router advertises this information inside the TLV, it breaks it up into several key bits of information:

• The Prefix itself – a /32 when dealing with IPv4.
• A globally significant Index – this is just a number. In our case R5 gets index 5 and so on…
• The locally significant SRGB Base value – the first label in the Segment Routing label range. In our case the SRGB base is 17000.
• A locally significant Range value stating how big the SRGB is – for us it’s 2000

So for any given router its overall SRGB is the Base plus the Range. And because both the Base and the Range are locally significant, so is the SRGB.

What does this local significance mean?

Well it obviously means that it can differ one device to another… so when I said above “Let’s say your SRGB is 17000-18999″ I’ve assumed that all devices in the network have the same SRGB (and by extension the same Base and Range) configured. Again to best understand this, let’s continue within our current context…

Just like LDP each router installs an In and Out label in the LFIB for each prefix:
• The In label is the Index of that prefix plus its own local SRGB.
• The Out label is the Index plus the downstream neighbor’s SRGB.

Let’s put this in diagram form to illustrate. In the below diagram we are following how R4 advertises its loopback and label information:

Looking at the LSPDU in the diagram above R4 is advertising….

  • The 1.1.1.4/32 Prefix
  • An Index of 4
  • An SRGB Base of 17000
  • A Range of 2000
  • An unprotected IPv4 Adj-SID for each of its neighbors (R3 and R5) – other Adj-SIDs have been left out for simplicity

Now let’s consider how R2 installs entries into its LFIB for 1.1.1.4/32. R2’s best path to reach 1.1.1.4/32 is via R3 so it takes the information from both R4s LSPDU and R3s LDSPU…

In Label
R2’s In label for 1.1.1.4/32 is 17000 (its own SRGB Base) plus 4 (the Index from R4.00-00) = 17004.

Out Label
R2’s Out label for 1.1.1.4/32 is 17000 (R3’s SRGB Base which it would have got from R3.00-00) plus 4 (the Index from R4.00-00) = 17004.

You can very quickly see that if every device in the network has 17000-18999 as its SRGB, then the label will remain the same as traffic is forwarded through the network, because the In and Out labels will be the same!

From here we can illustrate how SR is a source routing paradigm. Let us assume that in our test network traffic comes into R1 and is destined for R5. However for some reason, we have a desire to send traffic over the R4-R5 link even though it is not the best IGP path. R1 can do this by stacking instructions (in the form of labels) onto the packet that other routers can interpret.

Here’s how it works:

R1 has added {17004} as the top label and {16345} as the bottom of stack label. Don’t worry about how the label stack derived. There are multiple policies and protocols that can facilitate this – but that is another blog in and of itself!

If you follow the packet through the network you can see that R2 is essentially doing a swap operation to the same label. R3 is then performing standard PHP before forwarding the packet to R4 (PHP works slightly differently in Segment Routing – I won’t detail it here but for our scenario it operates the same as in LDP). R4 sees the instruction of {16345} which tells it to pop the label and send it out of the interface for its adjacency to R5 (regardless of its best path).

This illustrates a number of advantages for SR:

• The source router is doing the steering.
• There is no need to keep state. In a traditional IGP+LDP network this kind of steering is typically achieved using MPLS TE and involves RSVP signalling to the head end router and back. With SR the source simply instantiates the label stack and forwards the packet.
• No need to run LDP. You’ve now one less protocol to run and no more LDP/IGP Sync issues.
• IPv6 label forwarding: IPv6 LDP never really took off. Cisco IOS-XR routers are able to advertise node-SIDs for both IPv4 and IPv6 prefixes. This can eliminate the need for technologies like 6PE.

Before moving on I’ll briefly show how, for example, SR on R4 would be configured for IOS-XR:

segment-routing
 global-block 17000 23999 <<< the SRGB Base and range are auto calculated based on this
!
interface Loopback0
 ipv4 address 1.1.1.4 255.255.255.255
!
router isis LAB
 is-type level-2-only
 net 49.0100.1111.1111.0004.00
 address-family ipv4 unicast
  metric-style wide
  segment-routing mpls sr-prefer <<< sr-prefer is needed if LDP is also running
 !
 address-family ipv6 unicast
  metric-style wide
  segment-routing mpls sr-prefer
 !
 interface Loopback0
  passive
  address-family ipv4 unicast
   prefix-sid absolute 17004 <<< configured as absolute values but broken up in the TLV
  !
 !
 interface GigabitEthernet0/0/0/0
  point-to-point
  address-family ipv4 unicast
  !
 interface GigabitEthernet0/0/0/1
  point-to-point
  address-family ipv4 unicast
  ! 
 !
!

There are more types of SIDs and many more applications for Segment Routing than I have shown here – but if you’re new to SR, this brief summary should be enough to help you understand TI-LFA. With that said, let’s look at how LFA and its different flavours work…

LFA Introduction

Loop Free Alternate is a Fast Reroute (FRR) technology that basically prepares a backup path ahead of a network failure. In the event of a failure, the traffic can be forwarded into the backup path immediately (the typical goal is sub 50ms) with minimal downtime. It can be thought of as roughly analogous to EIGRPs feasible successor.

The best way to learn is by example. So what I’ll do is walk through Classic-LFA, Remote-LFA and TI-LFA showing how each improves on the last. First, however, I’ll introduce some terminology before we get to the actual topologies:

PLR (Point of Local Repair) – The router doing the protection. This is the router that will watch for outages on its protected elements and initiate FRR behaviour if needed.
Release Point – The point in the network where, with respect to the destination prefix, the failure of the Protect Element makes no difference. It’s the job of the PLR to get traffic to the Release Point.
C, Protected Element – The part of the network being protected against failure. LFA can provide Link Protection, Node Protection or SRLG (Shared Risk Link Group) protection. This post only covers Link Protection, but the principle is the same.
D, Destination prefix – LFA is done with respect to a destination. So when presenting formulas and diagrams, D, will refer to the destination prefix.
N, Neighbor – A neighbor connected to the PLR that (in the case of Classic-LFA) is a possible Release Point for an FRR solution.
Post-convergence path – Refers to the best path to the destination, after the network has converged around the failure.

If a failure occurs at a given PLR router, it does the following:

  1. Assumes that the rest of the network is NOT aware of the failure yet – i.e. all the other routers think the link is still up and their CEF entries reflect that.
  2. Asks itself where it can send traffic such that it will not loop back or try cross the Protected Element that just went down – or to put it another way, where is the Release Point?
  3. If it has a directly connected Neighbor that satisfies the previous point, then send it to that Neighbor. Nice and easy, job done. This is Classic-LFA.
  4. If, however, the Release Point is not directly connected, traffic will need to be tunnelled to it somehow – this is R-LFA and TI-LFA.

Now that we’ve introduced the basic mechanism, let’s start with Classic-LFA.

Classic-LFA

Here is our starting topology:

The link we’re looking to protect is the link between R6 and R7. The prefix we will be protecting is the loopback of R3 (10.1.1.3/32). Traffic will be coming from R8. This makes R7 the PLR. We haven’t implemented SR yet so we’re just working with a standard IGP + LDP model.

Download the Classic-LFA configs here.

So, if you are protecting a single link Classic-LFA (also called local-LFA) can help. The rule for Classic-LFA is this (where Dist(x,y) is the IGP cost from x to y before the failure):

Dist(N, D) < Dist (PLR, N) + Dist (PLR, D)

If the cost for the Neighbor to reach the Destination is less than the cost of the PLR to reach the Neighbor plus the cost of the PLR to get to the Destination, the Neighbor is a valid Release Point. In short, this means that traffic won’t loop back or try to use the Protected Element.

Here’s the idea using our topology:

Prior to the failure traffic takes the R8-R7-R6-R2-R3 path.

When the R6-R7 link fails R7 must figure out where to send the traffic.

It can’t send it to R11. Remember R11 isn’t aware of the outage yet and it’s best path to R3 is back via R7 so it will simply loop it back. Or to put this in the formula:

Dist(N, D) < Dist (PLR, N) + Dist (PLR, D)
Dist(R11, R3) < Dist (R7, R11) + Dist (R7, R3)
40 < 10 + 30 FALSE!

But it can send it to R2! R2’s best path to R3’s loopback doesn’t cross the R6-R7 link:

Dist(N, D) < Dist (PLR, N) + Dist (PLR, D)
Dist(R2, R3) < Dist (R7, R2) + Dist (R7, R3)
10 < 100 + 30 TRUE!

So R2 is the valid Release Point and if R6-R7 fails R7 can forward traffic immediately over to R2.

Configuration and Verification of Classic-LFA

The below IOS-XR config shows the basic IS-IS config from R7’s point of view (I’ve left out the config for IPv6 for brevity, but all attached configs and the downloadable lab contain IPv6).

! Standard traceroute showing normal traffic flow
RP/0/RP0/CPU0:R8#traceroute 10.1.1.3 source loopback 0
Wed Jul 21 18:56:04.316 UTC

Type escape sequence to abort.
Tracing the route to 10.1.1.3

 1  10.7.8.7 [MPLS: Label 16723 Exp 0] 64 msec  48 msec  53 msec
 2  10.6.7.6 [MPLS: Label 16619 Exp 0] 50 msec  52 msec  52 msec
 3  10.2.6.2 [MPLS: Label 16212 Exp 0] 56 msec  52 msec  52 msec
 4  10.2.3.3 52 msec  *  51 msec

RP/0/RP0/CPU0:R8#

! Configuration
hostname R7
!
router isis LAB
 is-type level-2-only
 net 49.0100.1111.1111.0007.00
 log adjacency changes
 address-family ipv4 unicast
  metric-style wide
  advertise passive-only
  mpls ldp auto-config
 !
 interface Loopback0
  passive
  address-family ipv4 unicast
  !
 !
 ! This is the link to R6
 interface GigabitEthernet0/0/0/1
  point-to-point
  address-family ipv4 unicast
   fast-reroute per-prefix level 2 << enable Classic LFA
   mpls ldp sync
  !
 !
<other interfaces omitted for brevity>


! Verifying LFA path via link to R2 with overall metric of 110
P/0/RP0/CPU0:R7#show isis fast-reroute 10.1.1.3/32
Wed Jul 21 18:56:24.064 UTC

L2 10.1.1.3/32 [30/115]
     via 10.6.7.6, GigabitEthernet0/0/0/1, R6, Weight: 0
       Backup path: LFA, via 10.2.7.2, GigabitEthernet0/0/0/4, R2, Weight: 0, Metric: 110
RP/0/RP0/CPU0:R7#


RP/0/RP0/CPU0:R7#show cef 10.1.1.3/32
Wed Jul 21 18:56:40.664 UTC
10.1.1.3/32, version 314, internal 0x1000001 0x0 (ptr 0xe1bd080) [1], 0x0 (0xe380928), 0xa28 (0xeddf9f0)
 Updated Jul 21 18:55:44.495
 remote adjacency to GigabitEthernet0/0/0/1
 Prefix Len 32, traffic index 0, precedence n/a, priority 3
   via 10.2.7.2/32, GigabitEthernet0/0/0/4, 5 dependencies, weight 0, class 0, backup (Local-LFA) [flags 0x300]
    path-idx 0 NHID 0x0 [0xecbd890 0x0]
    next hop 10.2.7.2/32
    remote adjacency
     local label 16723      labels imposed {16212} << R2's label for R3
   via 10.6.7.6/32, GigabitEthernet0/0/0/1, 5 dependencies, weight 0, class 0, protected [flags 0x400]
    path-idx 1 bkup-idx 0 NHID 0x0 [0xed68270 0x0]
    next hop 10.6.7.6/32
     local label 16723      labels imposed {16619}
RP/0/RP0/CPU0:R7#


RP/0/RP0/CPU0:R7#sh ip route 10.1.1.3/32
Wed Jul 21 18:56:52.408 UTC

Routing entry for 10.1.1.3/32
  Known via "isis LAB", distance 115, metric 30, type level-2
  Installed Jul 21 18:55:44.473 for 00:01:08
  Routing Descriptor Blocks
    10.2.7.2, from 10.1.1.3, via GigabitEthernet0/0/0/4, Backup (Local-LFA) << Classic-LFA
      Route metric is 110
    10.6.7.6, from 10.1.1.3, via GigabitEthernet0/0/0/1, Protected
      Route metric is 30
  No advertising protos.
RP/0/RP0/CPU0:R7#

Shortcomings of Classic-LFA

There are two common shortcomings with Classic-LFA:

• The backup path is sub-optimal. The cost for R7 to reach R3 is now R7-R2-R3 = 110. It would be more efficient to go R7-R11-R10-R9-R6-R2-R3 = 70. This is indeed the Post Convergence Path shown in the diagram above.
• Coverage is not 100%. If the link to R2 was not present, there would be no Classic-LFA backup path, since nothing satisfies the formula. If there’s no directly connected neighbor that satisfied the formula, nothing can be done!

Remote-LFA can help with some of these problems. To demonstrate this let’s remove the R2-R7 link…

Remote-LFA

Our topology now looks like this:

You can see there is no Classic-LFA path here if link C goes down. But there obviously is a backup path (namely R11-R10-R9-R6-R2-R3), but if all we had was Classic-LFA we’d have to wait for the IGP to coverage, which in most networks is too long. R-LFA can step in and help but in order to explain how it does so, we first need to define a couple of terms to describe the network from the point of view of the PLR. P and Q space…

P and Q Space

The P-space and the Q-space are a collection of nodes within the network that have a specific relationship to the PLR or Destination, with respect to the Protected Element. This sounds complicated but I’ll walk through it. P and Q don’t stand for anything – they’re just arbitrary letters. Let’s start with the P-space

P-space: In our context, the definition of P-space is “The set of nodes such that, the shortest-path from the PLR to them does not cross the Protected Element.”

This basically represents the set of devices such that R7’s best path to them, doesn’t cross the R6-R7 link.

So to figure this out…

Start at R7 and for every other router in the network figure out R7’s best path to reach it.
Does its best path cross the R6-R7 link? (this includes all ECMP paths too!)
• yes? – then it is not the in the P-space
• no? – this it is in the P-space

In our network the P-space contains these routers:

Note that even though R10 could reach R7 via R11 with a total cost of 30, it also has an ECMP cost 30 path via R9-R6-R7, which disqualifies it.

So that’s the P-space, but what about the Q-space…?

Q-space: The formal definition of Q-space is “the set of nodes such that their shortest-path to the Destination does not cross the Protected Element.”

This basically represents the set of devices that can get to R3 (the Destination) without worrying about whether or not the R6-R7 link has failed. They are basically on the other side of the failure with respect to the Destination – or in other words, they are candidate Release Points.

So to figure this out…

Go to each router in the network and figure out its best path to reach R3.
Does its best path cross the R6—R7 link? (again, this includes all ECMP paths too!)
• yes? – then it is not in the Q-space
• no? – this it is in the Q-space
So in our network the Q-space contains these routers:

What we want is a place where P and Q overlap. If we can get it to that router we can avoid the downed Protected Element and get the traffic to the Destination.

But in our setup they don’t overlap!

However, we can use something called the extended P-space to increase our reach. So what is the extended P-space?

Think about the network from R7s point of view. R7 can’t control what other routers do once it sends a packet on its way. But it can decide which of its interfaces it sends the packet out of. This allows us to consider not just our own P-space, but also the P-space of any directly connected Neighbors that exist in our own P-space. Adding all these together forms what we call the extended P-space.

In short, the extended-P space from the point of view of any node (in our case R7), is its own P-space + the P-space of all of its directly connected P-space Neighbors.

So for R7, we calculate the P-space for R4, R11 and R8 (we don’t calculate the P-space of R6, since R6 is not in R7’s P-space).

The P-space for R4 and R8 are identical:

The P-space of R11 is a little bigger:

Again, to reiterate how we calculate R11’s P-space, look at each device in the blue area and note that its best path to reach R11 doesn’t cross C.

If we combine these, we get our extended P-space:

Now if we combine the extended P-space and the Q-space we have an overlap at R10!

Any nodes in the overlap are called PQ nodes – these will be valid Release Points. If there is more than one, R7 will select the nearest. But how do we get the traffic there? If the R6-R7 link failed and the PLR simply sent traffic to R11 it would send it straight back (remember R11 isn’t aware of the failure yet). Here’s where R-LFA and its tunnelling kick in…

Remote-LFA Tunnelling

Download the R-LFA configs here.

Once the PQ node is found, the PLR will prepare a backup path whereby it puts the protected traffic in an LSP that ends on the PQ node. This is done by pushing a label on top of the stack.

But before it does that it must do the regular LDP swap operation for the original LSP to the Destination (R3). Under normal LDP conditions, it would swap the incoming label with the local label of its downstream neighbor (learned via LDP). But in this case the R7 doesn’t have an LDP session to the PQ node (R10)… so it builds a targeted one!

Over this targeted LDP session the PQ node will tell the PLR what its local label is for the destination prefix. It is this label that the PLR will swap the transport label for before it pushes on the label that will forward traffic to the PQ node.

To put this in diagram form for our example:

In our example, R10 tells R7 what its local LDP label is for R3 loopbacks. R7 swaps the transport label for this tLDP-learned label and then pushes R11’s label for R10 on top and forwards it to R11.

All of these tLDP sessions and calculations are done ahead of time. So that switching to the backup tunnel is as fast as possible.

Configuration and Verification for R-LFA

Here’s the IOS-XR configuration and verification output for R-LFA:

! Configuration
hostname R7
!
router isis LAB
 is-type level-2-only
 net 49.0100.1111.1111.0007.00
 log adjacency changes
 address-family ipv4 unicast
  metric-style wide
  advertise passive-only
  mpls ldp auto-config
 !
 interface Loopback0
  passive
  address-family ipv4 unicast
  !
 !
 interface GigabitEthernet0/0/0/0
  point-to-point
  address-family ipv4 unicast
   fast-reroute per-prefix level 2
   fast-reroute per-prefix remote-lfa tunnel mpls-ldp << Enable R-LFA
   mpls ldp sync
  !
 <other interfaces left out for brevity>


! Verification of backup path
RP/0/RP0/CPU0:R7#show cef 10.1.1.3/32 detail
Wed Jul 21 19:07:22.598 UTC
10.1.1.3/32, version 387, internal 0x1000001 0x0 (ptr 0xe1bd080) [1], 0x0 (0xe380928), 0xa28 (0xeddfac8)
 Updated Jul 21 19:05:46.659
 remote adjacency to GigabitEthernet0/0/0/1
 Prefix Len 32, traffic index 0, precedence n/a, priority 3
  gateway array (0xe1e7da8) reference count 15, flags 0x500068, source lsd (5), 1 backups
                [6 type 5 flags 0x8401 (0xe525560) ext 0x0 (0x0)]
  LW-LDI[type=5, refc=3, ptr=0xe380928, sh-ldi=0xe525560]
  gateway array update type-time 1 Jul 21 19:04:24.215
 LDI Update time Jul 21 19:04:24.215
 LW-LDI-TS Jul 21 19:04:38.931
   via 10.7.11.11/32, GigabitEthernet0/0/0/3, 5 dependencies, weight 0, class 0, backup [flags 0x300]
    path-idx 0 NHID 0x0 [0xecbd410 0x0]
    next hop 10.7.11.11/32
    remote adjacency
     local label 16723      labels imposed {24112 24017} << 24112 is R11's label for R10 and 24017 is R10's label for R3 
   via 10.6.7.6/32, GigabitEthernet0/0/0/1, 5 dependencies, weight 0, class 0, protected [flags 0x400] 
    path-idx 1 bkup-idx 0 NHID 0x0 [0xed686d0 0x0]
    next hop 10.6.7.6/32
     local label 16723      labels imposed {16619}


    Load distribution: 0 (refcount 6)

    Hash  OK  Interface                 Address
    0     Y   GigabitEthernet0/0/0/1    remote
RP/0/RP0/CPU0:R7#

! Verification of R10s tLDP session and config
RP/0/RP0/CPU0:R10#sh mpls ldp neighbor 10.1.1.7:0

Peer LDP Identifier: 10.1.1.7:0
  TCP connection: 10.1.1.7:646 - 10.1.1.10:44079
  Graceful Restart: No
  Session Holdtime: 180 sec
  State: Oper; Msgs sent/rcvd: 18/18; Downstream-Unsolicited
  Up time: 00:03:58
  LDP Discovery Sources:
    IPv4: (1)
      Targeted Hello (10.1.1.10 -> 10.1.1.7, passive)
    IPv6: (0)
  Addresses bound to this peer:
    IPv4: (5)
      10.1.1.7       10.4.7.7       10.6.7.7       10.7.8.7
      10.7.11.7
    IPv6: (0)

RP/0/RP0/CPU0:R10#sh run mpls ldp
mpls ldp
 address-family ipv4
  discovery targeted-hello accept << this is needed to accept targeted LDP sessions
 !
!
RP/0/RP0/CPU0:R10#

So that’s R-LFA. It can help to reach a Release Point if it isn’t a directly connected neighbor. It’s also worth noting that R-LFA can use SR labels if they are available, rather than using tLDP.

Shortcomings of R-LFA

But there are shortcomings with R-LFA too:

• There is increased complexity with all of the tLDP sessions running everywhere.
• The backup path still might not be post-convergence path – meaning that traffic will be forwarding in a suboptimal manner while the network converges and then will need to switch to the new best path once convergence is complete.
• Coverage is still not 100% – there might not be a PQ overlap!

We’ll look at just such a case with no PQ overlap next…

TI-LFA and SR

First off, lets assume that we have removed LDP from the our network and configured SR instead. I won’t go through the process of turning LDP off and turning SR on beyond briefly showing this configuration:

segment-routing
 global-block 17000 23999 << define the SRGB
!
router isis LAB
 address-family ipv4 unicast
  no mpls ldp auto-config << turn off LDP
  metric-style wide
  segment-routing mpls sr-prefer << enable SR
 !
 interface Loopback0
  address-family ipv4 unicast
   prefix-sid absolute 17001 << statically create the node SID
  !
 !
 interface GigabitEthernet0/0/0/0
  point-to-point
  address-family ipv4 unicast
   no mpls ldp sync << turn off LDP-IGP sync
 !
!

The downloadable lab for this blog has both SR and LDP configured but SR is preferred.

Now we’ll make another change to our topology by increasing the R9-R10 metric as follows:

This is a subtle change. But if we go through the process of calculating the P and Q spaces we get the following:

You can see there is no PQ overlap (this includes R7’s extended P-space). Let’s try to fix this using R-LFA…

We can’t do what we did last time and use R10 as the node to build our tLDP session to. If we tunnel traffic to R10, what label to we put at the bottom of the stack?

If we use R10’s local label for R3 it will forward the traffic straight back to R11. This is precisely what it means to be in the P-space! It’s worth noting here that since we’re now using SR, R10’s local label for R3 with be the globally recognised 17003 label – but the problem will be the same nonetheless since R10s best path to R3 crosses the R7-R6 link.

Ok but what about R9…? If we try to tunnel traffic to R9, R7 will have to send traffic traffic to R11 with a top label of R11’s local label for R9 (again an SR label, namely 17009). But what will R11 do when it get’s this packet? It will send the traffic straight back to R7! – if this wasn’t the case, R9 wouldn’t be in the Q-space!

So what do we do? Well here’s where the power of Segment Routing steps in. Topology Independent Loop Free Alternate (or TI-LFA) utilizes Adj-SIDs to bridge the PQ space gap . Remember Adj-SIDs are locally generated labels communicated via the IGP TLVs that act as instructions to forward traffic to their local neighbors.

R7 does the following:
• Calculates what the best path to R3 would be if the link from R6-R7 were to go down (or in other words, it calculates the post-convergence path) – in this case it sees the best path is R7-R11-R10-R9-R6-R2-R3.
• Calculates the Segment List needed to forward traffic along this path – assuming other nodes in the network will not yet be aware of the R6-R7 failure.
• Installs this Segment List as the backup path.

The details of the algorithm used to calculate the Segment List is not publicised by Cisco, but in our case, the general principle is straight forward to grasp.

The top most label (or segment) gets the traffic to the border P node – R10.

The next label is the Adj-SID that R10 has for R9. It basically instructs R10 to pop the Adj-SID label and forward it out of its Adjacency to R9 – this is the PQ bridging in action.

The bottom of stack label is simply the Node-SID for R3. When R9 gets it, we know it will forward it on to R3 without crossing the protected link, because it is in the Q-space.

To put this in diagram form, we get the following:

Once TI-LFA is enabled all of this is calculated and installed automatically. A key thing to highlight here is that the backup path is the same as the post-convergence path. This means that traffic will not have to change its path through the network again when the IGP converges. The only thing that will change is the label stack.

Configuration and Verification of TI-LFA

TI-LFA is pretty easy to configure and verification is straight forward when you know what to look for…

! Configuration
hostname R7
!
router isis LAB
 is-type level-2-only
 net 49.0100.1111.1111.0007.00
 log adjacency changes
 address-family ipv4 unicast
  metric-style wide
  advertise passive-only
  mpls ldp auto-config
 !
 interface Loopback0
  passive
  address-family ipv4 unicast
  !
 !
 interface GigabitEthernet0/0/0/0
  point-to-point
  address-family ipv4 unicast
   fast-reroute per-prefix level 2
   fast-reroute per-prefix ti-lfa level 2 << Enable TI-LFA
  !
 <other interfaces left out for brevity>

! Verification
RP/0/RP0/CPU0:R7#show isis fast-reroute 10.1.1.3/32 detail
Thu Jul 22 21:30:52.232 UTC

L2 10.1.1.3/32 [30/115] Label: 17003, medium priority
     via 10.6.7.6, GigabitEthernet0/0/0/1, Label: 17003, R6, SRGB Base: 17000, Weight: 0
       Backup path: TI-LFA (link), via 10.7.11.11, GigabitEthernet0/0/0/3 R11, SRGB Base: 17000, Weight: 0, Metric: 160
         P node: R10.00 [10.1.1.10], Label: 17010 <<< P and Q nodes are specified
         Q node: R9.00 [10.1.1.9], Label: 24001 <<< 24001 is R10s Adj-SID for R9
         Prefix label: 17003
         Backup-src: R3.00
       P: No, TM: 160, LC: No, NP: No, D: No, SRLG: Yes
     src R3.00-00, 10.1.1.3, prefix-SID index ImpNull, R:0 N:1 P:0 E:0 V:0 L:0,
         Alg:0
RP/0/RP0/CPU0:R7#

RP/0/RP0/CPU0:R7#show cef 10.1.1.3/32 detail
Thu Jul 22 21:31:05.178 UTC
10.1.1.3/32, version 837, labeled SR, internal 0x1000001 0x83 (ptr 0xe1ba878) [1], 0x0 (0xe3800e8), 0xa28 (0xee59a38)
 Updated May 23 15:22:46.988
 remote adjacency to GigabitEthernet0/0/0/1
 Prefix Len 32, traffic index 0, precedence n/a, priority 1
  gateway array (0xe1e7838) reference count 15, flags 0x500068, source rib (7), 1 backups
                [6 type 5 flags 0x8401 (0xe524e10) ext 0x0 (0x0)]
  LW-LDI[type=5, refc=3, ptr=0xe3800e8, sh-ldi=0xe524e10]
  gateway array update type-time 1 May 23 15:22:46.989
 LDI Update time Jul 22 20:51:34.950
 LW-LDI-TS Jul 22 20:51:34.951
   via 10.7.11.11/32, GigabitEthernet0/0/0/3, 12 dependencies, weight 0, class 0, backup (TI-LFA) [flags 0xb00]
    path-idx 0 NHID 0x0 [0xecbd770 0x0]
    next hop 10.7.11.11/32, Repair Node(s): 10.1.1.10, 10.1.1.9 << PQ nodes called repair nodes
    remote adjacency
     local label 17003      labels imposed {17010 24001 17003}
   via 10.6.7.6/32, GigabitEthernet0/0/0/1, 12 dependencies, weight 0, class 0, protected [flags 0x400]
    path-idx 1 bkup-idx 0 NHID 0x0 [0xf082510 0x0]
    next hop 10.6.7.6/32
     local label 17003      labels imposed {17003}


    Load distribution: 0 (refcount 6)

    Hash  OK  Interface                 Address
    0     Y   GigabitEthernet0/0/0/1    remote
RP/0/RP0/CPU0:R7#

Demonstration

To close off this blog I’ll give a packet capture demonstration of TI-LFA in action. In my EVE-NG lab environment, if I set a constant ping from R8 to R3 before shutting down the R6-R7 link, the IGP actually converges too fast for me capture any TI-LFA encapsulated packets. The fix this problem I updated the PLR as follows:

RP/0/RP0/CPU0:R7#conf t
Fri Aug 27 17:00:09.741 UTC
RP/0/RP0/CPU0:R7(config)#ipv4 unnumbered mpls traffic-eng Loopback0
RP/0/RP0/CPU0:R7(config)#!
RP/0/RP0/CPU0:R7(config)#mpls traffic-eng
RP/0/RP0/CPU0:R7(config-mpls-te)#!
RP/0/RP0/CPU0:R7(config-mpls-te)#router isis LAB
RP/0/RP0/CPU0:R7(config-isis)# address-family ipv4 unicast
RP/0/RP0/CPU0:R7(config-isis-af)#  microloop avoidance segment-routing
RP/0/RP0/CPU0:R7(config-isis-af)#  microloop avoidance rib-update-delay 10000
RP/0/RP0/CPU0:R7(config-isis-af)#commit

I’m not going to go into detail on what microloop avoidance is here. But put briefly a microloop is, as the name suggests, is very short term routing loop caused by the fact that different routers will update their forwarding tables at different rates after a network change. Microloop avoidance is a mechanism that uses Segment Routing to detect and avoid such conditions. The main take away here though, is the rib-update-delay command. This instructs the router to hold the LFA path in the RIB for a certain period regardless of whether or not it could converge quicker. In our case we’re instructing R7 to keep forwarding traffic along the TI-LFA backup path after the R6-R7 failure for 10 seconds (or 10,000 milliseconds).

Once this was sorted, I started a packet capture on R11’s interface facing R7 and repeated the test…

RP/0/RP0/CPU0:R8#ping 10.1.1.3 source lo0 repeat 10000
Fri Aug 27 17:01:29.996 UTC
Type escape sequence to abort.
Sending 10000, 100-byte ICMP Echos to 10.1.1.3, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!...!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!
<output omitted>
RP/0/RP0/CPU0:R7#conf t
Fri Aug 27 17:01:50.259 UTC
RP/0/RP0/CPU0:R7(config)#interface gigabitEthernet 0/0/0/1
RP/0/RP0/CPU0:R7(config-if)#shut
RP/0/RP0/CPU0:R7(config-if)#commit
Fri Aug 27 17:01:58.731 UTC
RP/0/RP0/CPU0:R7(config-if)#

If we look at the PCAP on R11 we can see the correct labels are being used on the ICMP packets.

Checking R7 before the 10 seconds are up shows a backup TI-LFA tunnel in use:

RP/0/RP0/CPU0:R7#sh isis fast-reroute tunnel
Fri Aug 27 17:02:04.210 UTC

IS-IS LAB SRTE backup tunnels

tunnel-te32770, state up, type primary-uloop
  Outgoing interface: GigabitEthernet0/0/0/3
  Next hop: 10.7.11.11
  Label stack: 17010, 24001
  Prefix: 10.1.1.1/32 10.1.1.2/32 10.1.1.3/32 10.1.1.5/32 10.1.1.6/32 10.1.1.9/32

RP/0/RP0/CPU0:R7#

The Prefix field shows all of the IGP destinations for which R7 will use this tunnel. Note that 10.1.1.3/32 is in that list. You can try this yourself in the downloadable lab.

Conclusions

So that’s TI-LFA using SR! I’ve tried to present this blog as a basic introduction to LFA types as well as a demonstration of how powerful SR can be. There are more nuanced scenarios involving a mix of SR-capable and LDP-only nodes, but LDP/SR interoperation is another topic entirely. We’ve seen how traditional technologies like Classic LFA and R-LFA are adequate in most circumstance but TI-LFA with the power of SR can provide complete coverage. Thank you for reading.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: