Tuesday, March 11, 2014

Juniper Route Leaking Part 1 - RIB Groups

One thing that Juniper excels at is the flexibility of leaking routes from one routing table to another. JUNOS has so many ways to leak routes from one routing table to the other that it’s sometimes confusing. What I’ll be doing here is try to clarify as much as possible the techniques commonly used to leak from one routing table to another.

Let’s begin by the first method which is using RIB groups.

You can consider RIB Groups as a bucket that contains routes from different routing tables then you take the routes from this bucket and put it in the desired routing table. We can split the RIB Group usage into two main sections:
1.       Directly connected Interfaces RIB groups
2.       Dynamic Routing Protocols RIB groups.

The only difference between the two is that the order of syntax. We’ll get to that later

Let’s check the following diagram



Router R3 is connected to R2 via interface Ge-0/0/2 which is under Virtual-Router R2. Meanwhile, R1 and R4 are connected to R3 in inet.0 RT.

R3 is also has R1 and R4 as OSPF neighbors in inet.0 RT whilst R2 is an OSPF neighbor in R2.inet.0 RT.

We can safely assume that all the received routes from R2 is completely segregated from routes received from R1 and R4.

Let’s check how the routing table looks like on R3


root@R3> show route

inet.0: 12 destinations, 12 routes (12 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:01:22, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
3.3.3.3/32         *[Direct/0] 00:01:37
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:01:22, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:01:22, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 00:01:37
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:01:37
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:01:22, metric 2
                      to 10.0.13.1 via ge-0/0/1.0
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.24.0/24       *[OSPF/10] 00:01:22, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 00:01:37
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:01:37
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:01:39, metric 1
                      MultiRecv

R2.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2.2.2.2/32         *[OSPF/10] 00:01:17, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
10.0.23.0/24       *[Direct/0] 00:01:37
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:01:37
                      Local via ge-0/0/2.0
224.0.0.5/32       *[OSPF/10] 00:01:39, metric 1
                      MultiRecv



Now let’s create a RIB group to share the interface routes between inet.0 and R2.inet.0 routing tables.

routing-options {
    rib-groups {
        DIRECT-ROUTES {                 
            import-rib [ inet.0 R2.inet.0 ];
        }
    }
}

Here, we created a RIB group called DIRECT-ROUTES which contains the routes of inet.0 and R2.inet.0 routing tables.

An important thing to remember here as we mentioned earlier, when importing routes of a directly connected interfaces, the sequence of routing tables between the brackets doesn’t matter; like if you typed R2.inet.0 before inet.0 that wouldn’t make a difference, unlike when importing routes from dynamic protocols which does make a difference.

Now here’s the tricky part when it comes to applying the RIB group to the routing-instance. I’ll put it in simple words

If you want to import routes from inet.0 to R2.inet.0, use the interface-routes under the routing options of inet.0

Here’s what the configuration looks like

routing-options {
    interface-routes {
        rib-group inet DIRECT-ROUTES;
    }
}

And here’s the result

root@R3> show route

inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:32:24, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
3.3.3.3/32         *[Direct/0] 00:32:39
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:32:24, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:32:24, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 00:32:39
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:32:39
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:32:24, metric 2
                      to 10.0.13.1 via ge-0/0/1.0
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.24.0/24       *[OSPF/10] 00:32:24, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 00:32:39
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:32:39 
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:32:41, metric 1
                      MultiRecv

R2.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2.2.2.2/32         *[OSPF/10] 00:32:19, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 00:02:35
                    > via lo0.10
10.0.13.0/24       *[Direct/0] 00:02:35
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:02:35
                      Local via ge-0/0/1.0
10.0.23.0/24       *[Direct/0] 00:32:39
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:32:39
                      Local via ge-0/0/2.0
10.0.34.0/24       *[Direct/0] 00:02:35
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:02:35
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:32:41, metric 1
                      MultiRecv

You can see now that all the routes that are directly connected in inet.0 in now present in R2.inet.0 routing table. What makes me wonder is why the reverse logic Juniper?, this configuration should be done under the routing instance I want to import the routes to not the other way around!

Now, let’s import the direct routes from R2.inet.0 to inet.0 routing table

routing-instances {
    R2 {
        instance-type virtual-router;  
        interface ge-0/0/2.0;
        routing-options {
            interface-routes {
                rib-group inet DIRECT-ROUTES;
            }
        }
    }
}

Now let’s check the inet.0 routing table again

root@R3> show route

inet.0: 13 destinations, 13 routes (13 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:41:46, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
3.3.3.3/32         *[Direct/0] 00:42:01
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:41:46, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:41:46, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 00:42:01
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:42:01
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:41:46, metric 2
                      to 10.0.13.1 via ge-0/0/1.0
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.23.0/24       *[Direct/0] 00:02:36
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:02:36
                      Local via ge-0/0/2.0
10.0.24.0/24       *[OSPF/10] 00:41:46, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 00:42:01
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:42:01
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:42:03, metric 1
                      MultiRecv

R2.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2.2.2.2/32         *[OSPF/10] 00:41:41, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 00:11:57
                    > via lo0.10
10.0.13.0/24       *[Direct/0] 00:11:57
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:11:57
                      Local via ge-0/0/1.0
10.0.23.0/24       *[Direct/0] 00:42:01
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:42:01
                      Local via ge-0/0/2.0
10.0.34.0/24       *[Direct/0] 00:11:57
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:11:57
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:42:03, metric 1
                      MultiRecv224.0.0.5/32       *[OSPF/10] 00:42:03, metric 1
                      MultiRecv

The direct routes of R2.inet.0 is now present in inet.0 routing table.

The second part of using RIB groups now is importing the routes in dynamic routing protocols, let’s see how to do that using the same reverse logic of Junos.

If you need to import the OSPF routes from inet.0 to R2.inet.0 routing table, here’s how to do it

routing-options {
    interface-routes {
        rib-group inet DIRECT-ROUTES;
    }
    rib-groups {
        DIRECT-ROUTES {
            import-rib [ inet.0 R2.inet.0 ];
        }
        R2-TO-GLOBAL {
            import-rib [ R2.inet.0 inet.0 ];
        }
    }
}

As previously mentioned, the first routing table in the bracket is the routing table we’ll take the routes from and the second routing table in the brackets will be the one we put the routes into.

If the first routing table doesn't match the table you’re configuring the RIB group under, you’ll get the following error while committing the changes:

root@R3# commit
[edit routing-instance R2 protocols]
  'ospf'
    rib-group R2-TO-GLOBAL: primary routing table does not match instance
error: configuration check-out failed

Let’s apply the defined RIB group under the R2.inet.0 routing instance OSPF protocol

routing-instances {
    R2 {
        instance-type virtual-router;
        interface ge-0/0/2.0;
        routing-options {
            interface-routes {
                rib-group inet DIRECT-ROUTES;
            }
        }
        protocols {
            ospf {
                rib-group R2-TO-GLOBAL;
                area 0.0.0.1 {
                    interface ge-0/0/2.0;
                }
            }
        }
    }
}

Here’s the imported routes in inet.0 routing-table


inet.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:55:29, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
2.2.2.2/32         *[OSPF/10] 00:02:04, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 00:55:44
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:55:29, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:55:29, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 00:55:44
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:55:44
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:55:29, metric 2
                      to 10.0.13.1 via ge-0/0/1.0
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.23.0/24       *[Direct/0] 00:16:19
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:16:19 
                      Local via ge-0/0/2.0
10.0.24.0/24       *[OSPF/10] 00:55:29, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 00:55:44
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:55:44
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:55:46, metric 1
                      MultiRecv

R2.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

2.2.2.2/32         *[OSPF/10] 00:02:04, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 00:25:40
                    > via lo0.10
10.0.13.0/24       *[Direct/0] 00:25:40
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:25:40
                      Local via ge-0/0/1.0
10.0.23.0/24       *[Direct/0] 00:55:44
                    > via ge-0/0/2.0   
10.0.23.3/32       *[Local/0] 00:55:44
                      Local via ge-0/0/2.0
10.0.34.0/24       *[Direct/0] 00:25:40
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:25:40
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 00:55:46, metric 1
                      MultiRecv


Looks pretty easy, now let’s import OSPF routes from inet.0 to R2.inet.0

routing-options {
    interface-routes {
        rib-group inet DIRECT-ROUTES;
    }
    rib-groups {
        DIRECT-ROUTES {
            import-rib [ inet.0 R2.inet.0 ];
        }
        R2-TO-GLOBAL {
            import-rib [ R2.inet.0 inet.0 ];
        }
        GLOBAL-TO-R2 {
            import-rib [ inet.0 R2.inet.0 ];
        }
    }
}


protocols {
    ospf {                             
        rib-group GLOBAL-TO-R2;
        area 0.0.0.0 {
            interface lo0.10;
            interface ge-0/0/1.0;
            interface ge-0/0/3.0;
        }
    }
}

Checking the R2.inet.0 routing table

root@R3> show route

inet.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:02:25, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
2.2.2.2/32         *[OSPF/10] 00:16:38, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 01:10:18
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:02:25, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 01:10:18
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 01:10:18
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
                      to 10.0.34.4 via ge-0/0/3.0
10.0.23.0/24       *[Direct/0] 00:30:53
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 00:30:53 
                      Local via ge-0/0/2.0
10.0.24.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 01:10:18
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 01:10:18
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 01:10:20, metric 1
                      MultiRecv

R2.inet.0: 14 destinations, 14 routes (14 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both

1.1.1.1/32         *[OSPF/10] 00:02:25, metric 1
                    > to 10.0.13.1 via ge-0/0/1.0
2.2.2.2/32         *[OSPF/10] 00:16:38, metric 1
                    > to 10.0.23.2 via ge-0/0/2.0
3.3.3.3/32         *[Direct/0] 00:40:14
                    > via lo0.10
4.4.4.4/32         *[OSPF/10] 00:02:25, metric 1
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.12.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
10.0.13.0/24       *[Direct/0] 00:40:14
                    > via ge-0/0/1.0
10.0.13.3/32       *[Local/0] 00:40:14
                      Local via ge-0/0/1.0
10.0.14.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.13.1 via ge-0/0/1.0
                      to 10.0.34.4 via ge-0/0/3.0
10.0.23.0/24       *[Direct/0] 01:10:18
                    > via ge-0/0/2.0
10.0.23.3/32       *[Local/0] 01:10:18
                      Local via ge-0/0/2.0
10.0.24.0/24       *[OSPF/10] 00:02:25, metric 2
                    > to 10.0.34.4 via ge-0/0/3.0
10.0.34.0/24       *[Direct/0] 00:40:14
                    > via ge-0/0/3.0
10.0.34.3/32       *[Local/0] 00:40:14
                      Local via ge-0/0/3.0
224.0.0.5/32       *[OSPF/10] 01:10:20, metric 1
                      MultiRecv


Hopefully that managed to make it easy to understand how to use RIB groups in JUNOS. In Part 2, we will be discussing route-leaking usingInstance Import command