Basic LDP Configuration and Behavior on IOS and Junos

NetCraftsmen®

This post will be focusing on the configuration of LDP on IOS and Junos especially within the context of CCIE/JNCIE. The article will take a stepwise approach while comparing and contrasting the two at each step.

For this and future posts on MPLS/VPN topics, the following topology will be used. Each individual post may not deal with all components but no post will have additional components without a fair warning and a diagram.
 PE-CE Topology

Initial Configuration and Base Conditions

In this post, the following base conditions have been configured and verified in each device:
1. Link-layer connectivity
2. Routing configuration (every IP on every PE device should be reachable)
Other than the above, the routers only have a housekeeping (hostname, authentication etc.) configuration.
The following should also be noted:
1. There is no LDP enabled anywhere in the topology
2. The PE-CE interface have not been configured
The following minimal OSPF configuration has been applied on the provider core devices:
IOS
router ospf 1
 log-adjacency-changes
 network 0.0.0.0 255.255.255.255 area 0
Junos
protocols {
    ospf {
        area 0.0.0.0 {
            interface all;
        }
    }
}
This configuration essentially enables OSPF on each interface as well as includes the interface and its prefix in the router’s LSA1. One thing to be aware of here is the treatment of Loopback interfaces by the two software. If the industry best practice of using a /32 prefix-length on loopback interfaces is followed, the behavior of both OSs is exactly the same. For any other prefix-length, the behavior differs.
To illustrate the difference, notice the LSA 1 of device R1 for each OS:
R1#show ip ospf database router self-originate 
            OSPF Router with ID (1.1.1.1) (Process ID 1)
                Router Link States (Area 0)
  LS age: 5
  Options: (No TOS-capability, DC)
  LS Type: Router Links
  Link State ID: 1.1.1.1
  Advertising Router: 1.1.1.1
  LS Seq Number: 80000003
  Checksum: 0xB26B
  Length: 48
  Number of Links: 2
    Link connected to: a Stub Network
     (Link ID) Network/subnet number: 1.1.1.1
     (Link Data) Network Mask: 255.255.255.255
      Number of TOS metrics: 0
       TOS 0 Metrics: 1
    Link connected to: a Transit Network
     (Link ID) Designated Router address: 10.222.12.2
     (Link Data) Router Interface address: 10.222.12.1
      Number of TOS metrics: 0
       TOS 0 Metrics: 10

The loopback network is being advertised by IOS as a Stub Network with a mask of /32. This is in contrast with the applied mask of /24 but is in fact consistent the default loopback advertisement behavior described in RFC 2328. This inconsistency should be noted by the CCIE candidate as it will become important in the later part of the article.

nbhasin@R1# run show ospf database router advertising-router self extensive            
    OSPF database, Area 0.0.0.0
 Type       ID               Adv Rtr           Seq      Age  Opt  Cksum  Len 
Router  *1.1.1.1          1.1.1.1          0x80000004  2059  0x22 0x987b  60
  bits 0x0, link count 3
  id 10.222.12.2, data 10.222.12.1, Type Transit (2)
    Topology count: 0, Default metric: 1
  id 1.1.1.1, data 255.255.255.255, Type Stub (3)
    Topology count: 0, Default metric: 0
  id 1.1.1.0, data 255.255.255.0, Type Stub (3)
    Topology count: 0, Default metric: 0
  Topology default (ID 0)
    Type: Transit, Node ID: 10.222.12.2
      Metric: 1, Bidirectional
  Gen timer 00:15:41
  Aging timer 00:25:41
  Installed 00:34:19 ago, expires in 00:25:41, sent 00:34:17 ago
  Last changed 00:34:19 ago, Change count: 2, Ours

Junos displays a somewhat different behavior for loopback advertisements. While it stays compliant with RFC 2328, it eliminates the inherent inconsistency of the masks by advertising an additional prefix to describe the loopback network with the configured mask. This behavior lets the JNCIE candidate be a little more carefree with thier configuration.

Now an output of the routing tables of the core routers to ensure that each router (even the P) has loopback to loopback reachability in the network.

EDIT: 07/14/2013 – Updated the IOS output below to the correct version. Previous output collected showed the masks of R2 and R3 loopback IPs received via OSPF to be /24. The correct output, below, shows the correct mask – /32.

IOS
R1#show ip route ospf
     3.0.0.0/32 is subnetted, 1 subnets
O       3.3.3.3 [110/21] via 10.222.12.2, 00:21:55, FastEthernet0/0
     2.0.0.0/32 is subnetted, 1 subnets
O       2.2.2.2 [110/11] via 10.222.12.2, 00:21:55, FastEthernet0/0
     10.0.0.0/24 is subnetted, 2 subnets
O       10.222.23.0 [110/20] via 10.222.12.2, 00:21:55, FastEthernet0/0
R2#show ip route ospf
     1.0.0.0/32 is subnetted, 1 subnets
O       1.1.1.1 [110/11] via 10.222.12.1, 00:22:04, FastEthernet0/0
     3.0.0.0/32 is subnetted, 1 subnets
O       3.3.3.3 [110/11] via 10.222.23.3, 00:23:05, FastEthernet0/1
R3#show ip route ospf
     1.0.0.0/32 is subnetted, 1 subnets
O       1.1.1.1 [110/21] via 10.222.23.2, 00:21:45, FastEthernet0/1
     2.0.0.0/32 is subnetted, 1 subnets
O       2.2.2.2 [110/11] via 10.222.23.2, 00:22:54, FastEthernet0/1
     10.0.0.0/24 is subnetted, 2 subnets
O       10.222.12.0 [110/20] via 10.222.23.2, 00:22:54, FastEthernet0/1

 

Junos
nbhasin@R1# run show route protocol ospf 
inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
2.2.2.0/24         *[OSPF/10] 00:42:19, metric 1
                    > to 10.222.12.2 via em0.12
2.2.2.2/32         *[OSPF/10] 00:42:19, metric 1
                    > to 10.222.12.2 via em0.12
3.3.3.0/24         *[OSPF/10] 00:42:19, metric 2
                    > to 10.222.12.2 via em0.12
3.3.3.3/32         *[OSPF/10] 00:42:19, metric 2
                    > to 10.222.12.2 via em0.12
10.222.23.0/24     *[OSPF/10] 00:42:19, metric 2
                    > to 10.222.12.2 via em0.12
224.0.0.5/32       *[OSPF/10] 00:43:18, metric 1
                      MultiRecv
nbhasin@R2# run show route protocol ospf 
inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
1.1.1.0/24         *[OSPF/10] 00:42:25, metric 1
                    > to 10.222.12.1 via em0.12
1.1.1.1/32         *[OSPF/10] 00:42:25, metric 1
                    > to 10.222.12.1 via em0.12
3.3.3.0/24         *[OSPF/10] 00:42:25, metric 1
                    > to 10.222.23.3 via em0.23
3.3.3.3/32         *[OSPF/10] 00:42:25, metric 1
                    > to 10.222.23.3 via em0.23
224.0.0.5/32       *[OSPF/10] 00:43:16, metric 1
                      MultiRecv
nbhasin@R3# run show route protocol ospf 
inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
1.1.1.0/24         *[OSPF/10] 00:42:26, metric 2
                    > to 10.222.23.2 via em0.23
1.1.1.1/32         *[OSPF/10] 00:42:26, metric 2
                    > to 10.222.23.2 via em0.23
2.2.2.0/24         *[OSPF/10] 00:42:26, metric 1
                    > to 10.222.23.2 via em0.23
2.2.2.2/32         *[OSPF/10] 00:42:26, metric 1
                    > to 10.222.23.2 via em0.23
10.222.12.0/24     *[OSPF/10] 00:42:26, metric 2
                    > to 10.222.23.2 via em0.23
224.0.0.5/32       *[OSPF/10] 00:43:16, metric 1
                      MultiRecv

Thus, there is loopback to loopback connectivity inside the core.

LDP Configuration

There is not only a difference of complexity between the minimal LDP configuration on IOS and Junos, but also a very marked behavioral difference. The behavioral difference will be illustrated after LDP has been successfully configured on both cores.

The IOS LDP configuration needs exactly one command on each LDP interface. The following minimal configuration is applied on all inter-provider device links. This is not needed on the PE-CE links.

R1(config)#int f0/0
R1(config-if)#mpls ip

Technically, the command “mpls ip” is also needed at the global configuration level but IOS has this command configured as a default so it does not need to be explicitly entered. After this command is configured everywhere, LDP neighbor relationships are formed between the three core devices.

Note: The LDP neighbor discovery process over UDP and neighbor relationship establishment over TCP are very important topics but are outside the scope of this article. The reader is strongly suggested to cover those articles using a good resource. The JNCIS Study Guide, available for free, is one such a source. RFC 5036 is also a good read especially for those interested in the CCIE/JNCIE Service Provider tracks.

R2#show mpls ldp neighbor
    Peer LDP Ident: 1.1.1.1:0; Local LDP Ident 2.2.2.2:0
        TCP connection: 1.1.1.1.646 - 2.2.2.2.38083
        State: Oper; Msgs sent/rcvd: 21/21; Downstream
        Up time: 00:06:31
        LDP discovery sources:
          FastEthernet0/0, Src IP addr: 10.222.12.1
        Addresses bound to peer LDP Ident:
          10.222.12.1     1.1.1.1         
    Peer LDP Ident: 3.3.3.3:0; Local LDP Ident 2.2.2.2:0
        TCP connection: 3.3.3.3.18993 - 2.2.2.2.646
        State: Oper; Msgs sent/rcvd: 21/21; Downstream
        Up time: 00:06:13
        LDP discovery sources:
          FastEthernet0/1, Src IP addr: 10.222.23.3
        Addresses bound to peer LDP Ident:
          10.222.23.3     3.3.3.3

The Junos minimal LDP configuration is a little bit more involved. Three (really two) main steps must be performed:

1. Enable family MPLS under all relevant interfaces. (Needs enablement under Loopback only in the case of directed LDP)
2. Configure the relevant interfaces under protocol mpls (Listed in nearly all reference documents but in reality, not needed for LDP)
3. Configure the relevant interfaces under protocol ldp (Again, loopback can be safely ignored)

The following minimal configuration is added on all provider routers for relevant interfaces (P router R2 is used in the output):

interfaces {
    em0 {
        unit 12 {
            family mpls;
        }
    }
        unit 23 {
            family mpls;
        }
    }
    lo0 {
        }
    }
}
protocols {
    mpls {
    }
    ldp {
        interface em0.12;
        interface em0.23;
    }
}

Notice that interfaces have not been enabled under protocols mpls even though it is stated as mandatory. LDP neighborships should now be functional for the provider core.

nbhasin@R2# run show ldp neighbor extensive 
Address            Interface          Label space ID         Hold time
10.222.12.1        em0.12             1.1.1.1:0                12
  Transport address: 1.1.1.1, Configuration sequence: 4
  Up for 00:39:17
  Reference count: 1
  Hold time: 15, Proposed local/peer: 15/15
  Hello flags: none
  Neighbor types: discovered
Address            Interface          Label space ID         Hold time
10.222.23.3        em0.23             3.3.3.3:0                11
  Transport address: 3.3.3.3, Configuration sequence: 2
  Up for 00:39:16
  Reference count: 1
  Hold time: 15, Proposed local/peer: 15/15
  Hello flags: none
  Neighbor types: discovered

FEC Advertisement

This is one are where both the OS have markedly different behavior which is really a result of a stark difference in implementation philosophies.

Both IOS and Junos implement

1. Unsolicited Distribution – A local label is distributed to all LDP neighbors without being prompted for it
2. Liberal Label Retention – A received label is retained whether it is being used for forwarding or not

The major difference is that IOS implements Independent Control mode of operation while Junos uses Ordered Control mode of operation for label distribution. Very succinctly, this enables IOS to generate and advertise a label for every single route in its routing table. On the other hand, Junos can only generate labels for routes it is an egress router for, i.e. directly connected routes. This is a basic difference in their LDP implementation philosophy and cannot be changed via configuration.

The other major difference is the actual labels that are generated and advertised by default. IOS will generate and advertise a label for every single route that is in its routing table. Junos, by default, will only generate and advertise a label for the lowest IP (as a /32 prefix regardless of the actual prefix-length under family inet) configured on the loopback interface. This Junos behavior is configurable via policy but is deemed outside the scope of this document.

Here is a comparison of the LDP databases on R1s from each OS:

IOS
R1#sho mpls ldp bindings 
  tib entry: 1.1.1.0/24, rev 33
        local binding:  tag: imp-null
  tib entry: 1.1.1.1/32, rev 44
        remote binding: tsr: 2.2.2.2:0, tag: 18
  tib entry: 2.2.2.0/24, rev 43(no route)
        local binding:  tag: 19
        remote binding: tsr: 2.2.2.2:0, tag: imp-null
  tib entry: 2.2.2.2/32, rev 50
        local binding:  tag: 16
  tib entry: 3.3.3.0/24, rev 46(no route)
        local binding:  tag: 20
        remote binding: tsr: 2.2.2.2:0, tag: 16
  tib entry: 3.3.3.3/32, rev 52
        local binding:  tag: 18
  tib entry: 10.222.12.0/24, rev 15
        local binding:  tag: imp-null
        remote binding: tsr: 2.2.2.2:0, tag: imp-null
  tib entry: 10.222.23.0/24, rev 37
        local binding:  tag: 17
        remote binding: tsr: 2.2.2.2:0, tag: imp-null

 

Junos
nbhasin@R1# run show ldp database 
Input label database, 1.1.1.1:0--2.2.2.2:0
  Label     Prefix
 301216     1.1.1.1/32
      3     2.2.2.2/32
 301232     3.3.3.3/32
Output label database, 1.1.1.1:0--2.2.2.2:0
  Label     Prefix
      3     1.1.1.1/32
 301824     2.2.2.2/32
 301840     3.3.3.3/32

The difference can be noticed in the treatment of loopbacks advertised by R2 and R3. Take R3’s loopback for example. In IOS, there are two entries for it (in bold). The entry 3.3.3.0/24 has both a local label of 20 and a remote label of 16. The problem is that there is no route learned via OSPF, as seen earlier, so the binding is not valid. On the other hand, the router has generated a label of 18 for 3.3.3.3/32 (the actual prefix learned via OSPF).

Junos, in contrast, only generates a local label for directly connected routes (3 or Pop Tag) or for FECs it already has learnt a label for. Even though this router knows about the 3.3.3.0/24 prefix, even with the most liberal label generation policy (proof is not shown here), it will never be able to generate a label for it unless it was advertised that label for that prefix from R2 via R3.

Finally, a look at the actual MPLS forwarding table for both IOS and Junos:

IOS
R1#sho mpls forwarding-table 
Local  Outgoing    Prefix            Bytes tag  Outgoing   Next Hop    
tag    tag or VC   or Tunnel Id      switched   interface              
16     Untagged    2.2.2.2/32        0          Fa0/0      10.222.12.2  
17     Pop tag     10.222.23.0/24    0          Fa0/0      10.222.12.2  
18     17          3.3.3.3/32        0          Fa0/0      10.222.12.2
R2#show mpls forwarding-table 
Local  Outgoing    Prefix            Bytes tag  Outgoing   Next Hop    
tag    tag or VC   or Tunnel Id      switched   interface              
17     Untagged    3.3.3.3/32        0          Fa0/1      10.222.23.3  
18     Untagged    1.1.1.1/32        0          Fa0/0      10.222.12.1  

R3#sho mpls forwarding-table 
Local  Outgoing    Prefix            Bytes tag  Outgoing   Next Hop    
tag    tag or VC   or Tunnel Id      switched   interface              
16     Untagged    2.2.2.2/32        0          Fa0/1      10.222.23.2  
18     Pop tag     10.222.12.0/24    0          Fa0/1      10.222.23.2  
19     18          1.1.1.1/32        0          Fa0/1      10.222.23.2

At first look, everything may seem alright but there are major problems here. Pay attention specifically to the P router, R2. The outgoing labels for both R1 loopback and R3 loopback are both non-existent(untagged). This essentially means that these LSPs are now broken at R2. Similar behavior is seen on R1 for R2’s loopback and on R3 for R1’s loopback. Before uncovering the reason(s) for this, a look at the Junos MPLS forwarding table:

Junos
nbhasin@R1# run show route protocol ldp 
inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
inet.3: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
2.2.2.2/32         *[LDP/9] 00:24:50, metric 1
                    > to 10.222.12.2 via em0.12
3.3.3.3/32         *[LDP/9] 00:23:40, metric 1
                    > to 10.222.12.2 via em0.12, Push 301232
mpls.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
301824             *[LDP/9] 00:24:50, metric 1
                    > to 10.222.12.2 via em0.12, Pop      
301824(S=0)        *[LDP/9] 00:24:50, metric 1
                    > to 10.222.12.2 via em0.12, Pop      
301840             *[LDP/9] 00:23:40, metric 1
                    > to 10.222.12.2 via em0.12, Swap 301232
nbhasin@R2# run show route protocol ldp 
inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
inet.3: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
1.1.1.1/32         *[LDP/9] 00:25:05, metric 1
                    > to 10.222.12.1 via em0.12
3.3.3.3/32         *[LDP/9] 00:23:56, metric 1
                    > to 10.222.23.3 via em0.23
mpls.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
301216             *[LDP/9] 00:25:05, metric 1
                    > to 10.222.12.1 via em0.12, Pop      
301216(S=0)        *[LDP/9] 00:25:05, metric 1
                    > to 10.222.12.1 via em0.12, Pop      
301232             *[LDP/9] 00:23:56, metric 1
                    > to 10.222.23.3 via em0.23, Pop      
301232(S=0)        *[LDP/9] 00:23:56, metric 1
                    > to 10.222.23.3 via em0.23, Pop  
nbhasin@R3# run show route protocol ldp 
inet.0: 10 destinations, 10 routes (10 active, 0 holddown, 0 hidden)
inet.3: 2 destinations, 2 routes (2 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
1.1.1.1/32         *[LDP/9] 00:24:03, metric 1
                    > to 10.222.23.2 via em0.23, Push 301216
2.2.2.2/32         *[LDP/9] 00:24:03, metric 1
                    > to 10.222.23.2 via em0.23
mpls.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
300864             *[LDP/9] 00:24:03, metric 1
                    > to 10.222.23.2 via em0.23, Pop      
300864(S=0)        *[LDP/9] 00:24:03, metric 1
                    > to 10.222.23.2 via em0.23, Pop      
300880             *[LDP/9] 00:24:03, metric 1
                    > to 10.222.23.2 via em0.23, Swap 301216

The readers are urged to take a detailed look at these three tables but they will find that each LSP is functional end to end. The lack of any labels for prefixes on R2 is because of the behavior of PHP(Penultimate Hop Popping) that is implement by default on both Junos and IOS. This is different than the “untagged” keyword seen on the IOS output. That essentially means that the local router was never advertised even an implicit-null (3) label by its neighbor and only knows an IP route to the destination. An IOS router will never forward an MPLS packet as an IP packet using an IP routing table lookup. PHP and packets with explicit-null (0,2) labels are still exceptions. Thus, it will drop any such packets and that results in the broken LSP.

The reason for this is the Independent Control mode of label generation used by IOS combined with the OSPF loopback advertisement behavior illustrated earlier. Take the case of R3. R3 is advertising a label for 3.3.3.0/24 via LDP. Via OSPF, R3 is advertising the prefix 3.3.3.3/32. As R1 and R2 receive the 3.3.3.3/24 route, they generate independent labels for 3.3.3.3/32. Thus, from R1, it seems there is functional LSP with an outgoing label of 17 towards R2. R2 though, only has a local label for it (17) but no label for the /32 has been advertised from the downstream router, R3. Thus, R2 notates this fact as Untagged and hence, the LSP is now broken.

A well-prepared CCIE candidate should know at least two different methods of fixing this. Although the actual configuration details of these methods are left to the reader, briefly these methods are:

1. Change the OSPF network type on the originating router’s loopback to Point-to-point (preferred)
2. Change the prefix-length of the loopback interface to /32 (usually a bad idea to change IP addressing at the CCIE lab)

Just like most other topics, one can easily learn a topic’s implementation on IOS and carry it over to Junos and vice-versa as long as they are careful to understand and note the subtle but significant differences in the approaches and options available.

The following resources are recommended, especially for the CCIE/JNCIE SP candidates:

1. RFC 5036
2. MPLS-Enabled Applications: Emerging Developments and New Technologies – ISBN 978-0470665459
3. Cisco IOS LDP Configuration Guide
4. Junos LDP Configuration Guide
5. JNCIS Study Guide by Joseph Soricelli

One response to “Basic LDP Configuration and Behavior on IOS and Junos

Leave a Reply

 

Nick Kelly

Cybersecurity Engineer, Cisco

Nick has over 20 years of experience in Security Operations and Security Sales. He is an avid student of cybersecurity and regularly engages with the Infosec community at events like BSides, RVASec, Derbycon and more. The son of an FBI forensics director, Nick holds a B.S. in Criminal Justice and is one of Cisco’s Fire Jumper Elite members. When he’s not working, he writes cyberpunk and punches aliens on his Playstation.

 

Virgilio “BONG” dela Cruz Jr.

CCDP, CCNA V, CCNP, Cisco IPS Express Security for AM/EE
Field Solutions Architect, Tech Data

Virgilio “Bong” has sixteen years of professional experience in IT industry from academe, technical and customer support, pre-sales, post sales, project management, training and enablement. He has worked in Cisco Technical Assistance Center (TAC) as a member of the WAN and LAN Switching team. Bong now works for Tech Data as the Field Solutions Architect with a focus on Cisco Security and holds a few Cisco certifications including Fire Jumper Elite.

 

John Cavanaugh

CCIE #1066, CCDE #20070002, CCAr
Chief Technology Officer, Practice Lead Security Services, NetCraftsmen

John is our CTO and the practice lead for a talented team of consultants focused on designing and delivering scalable and secure infrastructure solutions to customers across multiple industry verticals and technologies. Previously he has held several positions including Executive Director/Chief Architect for Global Network Services at JPMorgan Chase. In that capacity, he led a team managing network architecture and services.  Prior to his role at JPMorgan Chase, John was a Distinguished Engineer at Cisco working across a number of verticals including Higher Education, Finance, Retail, Government, and Health Care.

He is an expert in working with groups to identify business needs, and align technology strategies to enable business strategies, building in agility and scalability to allow for future changes. John is experienced in the architecture and design of highly available, secure, network infrastructure and data centers, and has worked on projects worldwide. He has worked in both the business and regulatory environments for the design and deployment of complex IT infrastructures.