Route Separation

On a Junos router, we can configure routing-instances to create additional routing tables. This separates traffic at layer-3, in a similar fashion to VLANs separating traffic at layer-2.

There are several reasons this might be done, such as separating tenants, managing overlapping address space, or forcing traffic along a certain path.

However, on occasion, you might find that you need to ‘break’ this system. That is, you might need to allow some traffic from one routing instance to another. And that’s where things get tricky…

 

Routing Instances

Every routing instance has a separate routing table. For example, the default instance (called the master) uses the inet.0 routing table. If we created an instance called Tenant-1, it would use the Tenant-1.inet.0 routing table.

In the simple example shown here, we have an SRX router, with the master (or default) routing instance, and the Tenant-1 routing instance. Both routing-instances are the virtual router type (this is like the VRF-Lite system that Cisco use, if you’re more familiar with that terminology).

Each routing table contains three routes.

 

If we look at the routing tables, we can see that there are no routes that are in both routing table.

[email protected]# run show route terse

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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 192.168.1.0/24 S 5 >100.123.12.1
* ? 192.168.2.0/24 S 5 >100.123.12.1
* ? 192.168.3.0/24 S 5 >100.123.12.1


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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.0/24 D 0 >10.1.1.1
* ? 172.16.2.0/24 D 0 >10.1.1.1
* ? 172.16.3.0/24 D 0 >10.1.1.1

 

Usually this level of separation is a good thing. However, we might find that devices in the 172.16.1.0 /24 network need to access resources in 192.168.1.0 /24. With the current level of separation, this is not possible.

 

Route Leaking

The answer is with Route Leaking. This is a generic term that refers to leaking one or more routes between separate routing tables.

There’s a couple of different ways this can be done depending on our needs. A quick google will show you that the most common method on Junos is to use RIB Groups. However, this can be complicated, so in this article we’re going to look at a simplified method, called Instance Import.

Instance Import is suitable for routing instances configured as virtual routers, as in our example. If you have the vrf type, then you will need to look at RIB Groups.

 

Simple Instance Importing

We’ll start with a simple policy that shares all routes between these routing tables.

Routing policies are defined under the policy-options hierarchy:

policy-options {
policy-statement Tenant-to-Master {
   from instance Tenant-1;
   then accept;
}

 policy-statement Master-to-Tenant {
  from instance master;
then accept;
}
}

The config above creates two policies, named Tenant-to-Master and Master-to-Tenant.

Both of these policies are very simple. They identify all routes present in a particular routing instance. The accept action means they’re all viable candidates to be imported into another routing instance.

 

Next, we need to tell each routing instance to use these policies. First, importing routes into the master (of default) routing instance:

routing-options {
instance-import Tenant-to-Master;
}

Next, importing into Tenant-1:

routing-instances {
Tenant-1 {
routing-options {
instance-import Master-to-Tenant;
}
}
}

In both cases, we’re using the instance-import command to import routes into the routing instance. The policy controls what’s allowed to be imported.

 

When we look at the routing tables again, we see that they both contain all six routes:

[email protected]# run show route terse

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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.0/24 D 0 >10.1.1.1
* ? 172.16.2.0/24 D 0 >10.1.1.1
* ? 172.16.3.0/24 D 0 >10.1.1.1
* ? 192.168.1.0/24 S 5 >100.123.12.1
* ? 192.168.2.0/24 S 5 >100.123.12.1
* ? 192.168.3.0/24 S 5 >100.123.12.1


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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.0/24 D 0 >10.1.1.1
* ? 172.16.2.0/24 D 0 >10.1.1.1
* ? 172.16.3.0/24 D 0 >10.1.1.1
* ? 192.168.1.0/24 S 5 >100.123.12.1
* ? 192.168.2.0/24 S 5 >100.123.12.1
* ? 192.168.3.0/24 S 5 >100.123.12.1

 

 

Filtering via Policy

That’s good, but at this point, we’ve effectively broken the separation between these two routing instances completely. Looking back at our original plan, we only wanted to leak 192.168.1.0 /24 and 172.16.1.0 /24.

To do this, we can use a more specific routing policy:

policy-options {
policy-statement Master-to-Tenant {
term 1 {
from {
instance master;
route-filter 192.168.1.0/24 exact;
}
then accept;
}
term 2 {
then reject;
}
}
}

We’ve updated this policy to include two terms. The first term matches the routes we want to import. The second term matches everything else, so no other routes are imported.

Of course, we need to update the Tenant-to-Master policy too: 

policy-options {
policy-statement Master-to-Tenant {
term 1 {
from {
instance master;
route-filter 192.168.1.0/24 exact;
}
then accept;
}
term 2 {
then reject;
}
}
}

 

After this is committed, the routing tables look very simplified. Only the routes we’ve targeted are imported into the respective tables:

[email protected]# run show route terse

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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.0/24 D 0 >10.1.1.1
* ? 192.168.1.0/24 S 5 >100.123.12.1
* ? 192.168.2.0/24 S 5 >100.123.12.1
* ? 192.168.3.0/24 S 5 >100.123.12.1


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

A V Destination P Prf Metric 1 Metric 2 Next hop AS path
* ? 172.16.1.0/24 D 0 >10.1.1.1
* ? 172.16.2.0/24 D 0 >10.1.1.1
* ? 172.16.3.0/24 D 0 >10.1.1.1
* ? 192.168.1.0/24 S 5 >100.123.12.1

 

 

Filtering on Export

The example above filters routes as they are imported into a routing instance. Another option, which we won’t go into detail on, is to use the instance-export to control the routes that are allowed to be exported from a routing table.

You might do this if you have a lot of routing instances, and you need to be granular as to what you can share.

 

 

References

Juniper Networks (YouTube) – Route Sharing Instance Import

Keeran’s Blog – Leaking Routes into a Routing-Instance