MANUALLY CONFIGURED ROUTES – STATIC, AGGREGATE, & GENERATED

When you are trying to set up a route manually for a particular purpose, you are faced with these 3 different options in Junos:

  • STATIC
  • GENERATED (summary route)
  • AGGREGATE (summary route)

And probably you have asked yourself: What are the differences?  Which one should I use? Does it really matter?

The goal of this article is to help you answer these questions, so next time you need to manually configure a route in your Juniper device(s), it will be easier for you to decide which type you need to use.

STATIC ROUTES

These are the easiest, maybe most common ones, or simply the ones that you have heard about since you started your career in Networking.

I am sure you can tell me what a static route is. You would probably say something like a manually configured route that is added to the routing table as soon as I configure it, and being “static”, it is a route that doesn’t change, doesn’t move, doesn’t go away, and it always preferred.

And for the most part: you would be right!  You create a static route manually, by defining the destination prefix, and the next hop. The route goes to the routing table, and it does not change, does not move, does not depend on a metric, or bandwidth, does not adapt to changes in the network, BUT it can actually go away or just become useless! It turns out that even static routes have some requirements to become active and be usable for forwarding traffic.  We will talk about that.

You probably know that a static route in Junos is configured under the [routing-options] hierarchy, using set static <prefix> next-hop <next-hop-address>. But, is that all you can do? Nope!    

There are several options and knobs that you can add to your static route. We are going to talk about a few of them too, using some examples.

1) NEXT HOP

The next hop is typically the IP address of a directly connected device.  Consider the following example:

Customer_Router_VR is configured with a static default route, that points to the address of ISP_Router_VR, while ISP_Router_VR is configured with a static route to the customer prefix, that points to the IP address of the physical interface of Customer_Router_VR . Both routers basically have static routes pointing to each other’s IP address

Here is how the configuration looks like:

 [edit routing-instances]
 jcluser@vMX-addr-0# show | display set relative | match routing-options 
 set Customer__VR routing-options static route 0.0.0.0/0 next-hop 172.16.1.2
 set ISP_Router_VR routing-options static route 10.1.1.0/24 next-hop 172.16.1.1 

We can validate connectivity between the Internal User and the Web Server.:

 jcluser@vMX-addr-0> ping 192.168.1.1 routing-instance Internal_User_VR rapid 
 PING 192.168.1.1 (192.168.1.1): 56 data bytes
 !!!!!
 --- 192.168.1.1 ping statistics ---
 5 packets transmitted, 5 packets received, 0% packet loss
 round-trip min/avg/max/stddev = 0.365/0.446/0.660/0.110 ms 

Let’s take a look at how one of this routes looks like in the routing table:

 jcluser@vMX-addr-0> show route 10.1.1.1 table ISP_Router_VR.inet.0        
 ISP_Router_VR.inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
 + = Active Route, - = Last Active, * = Both
 10.1.1.0/24        *[Static/5] 00:07:24
                     > to 172.16.1.1 via lt-0/0/0.2 

NOTE: I am typing show route 10.1.1.1, which is asking the router to find the longest match for 10.1.1.1. In other words, the route that the router would use to send traffic to 10.1.1.1.

In the show route output we can see a few things:

  • 10.1.1.0/24 is the destination prefix.
  • Between square brackets, the router shows the protocol or source of the route (in this case static), and the route’s preference value. The default preference value for a static route is 5, which makes it better than a router learned from a dynamic routing protocols such as OSPF, which has a default preference of 10. We will talk more about this later.
  • The * symbol indicates that the route is ACTIVE, which means it is the route that will be installed in the forwarding table, and that will be used to forward traffic.
  • The next-hop is 172.16.1.2

If you needed to describe this static route to someone you could say: “traffic going to 10.1.1.0/24 should be sent to 172.16.1.1”.  It is important to highlight that this next-hop is reachable out of interface lt-0/0/0.1 and is directly connected. Here is where we start talking about the requirements for a static route to become active:

  • the next-hop must be reachable, and
  • by default the next-hop must be directly connected.

Let’s say that we change the next hop of the static default route on the Customer_Router to be the loopback address on the ISP_Router.

 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# show 
 route 0.0.0.0/0 next-hop 172.16.1.2;
  
 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# replace pattern 172.16.1.2 with 2.2.2.2 
  
 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# show 
 route 0.0.0.0/0 next-hop 2.2.2.2; 
  
 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# commit 
 commit complete 

When we check the routing table again, we find that the 0/0 route is gone, and the internal user is no longer able to reach the Web Server:

 jcluser@vMX-addr-0> show route 0/0 exact table Customer__VR.inet.0           
  (no output)
 jcluser@vMX-addr-0>
  
 jcluser@vMX-addr-0> ping 192.168.1.1 routing-instance Internal_User_VR rapid                 
 PING 192.168.1.1 (192.168.1.1): 56 data bytes
 36 bytes from 10.1.1.254: Destination Net Unreachable
 Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
  4  5  00 0054 3a6b   0 0000  40  01 7393 10.1.1.1  192.168.1.1 
 .36 bytes from 10.1.1.254: Destination Net Unreachable
 Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
  4  5  00 0054 3a81   0 0000  40  01 737d 10.1.1.1  192.168.1.1 
 .36 bytes from 10.1.1.254: Destination Net Unreachable
 Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
  4  5  00 0054 3a90   0 0000  40  01 736e 10.1.1.1  192.168.1.1 
 .36 bytes from 10.1.1.254: Destination Net Unreachable
 Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
  4  5  00 0054 3aa3   0 0000  40  01 735b 10.1.1.1  192.168.1.1 
 .36 bytes from 10.1.1.254: Destination Net Unreachable
 Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst
  4  5  00 0054 3ab3   0 0000  40  01 734b 10.1.1.1  192.168.1.1 
 .
 --- 192.168.1.1 ping statistics ---
 5 packets transmitted, 0 packets received, 100% packet loss 

And you are probably going to say: “duh! That’s pretty obvious, Customer_Router does not know how to get to the loopback of ISP_Router. And you would be right, so let’s fix that.

We add a static route to reach the loopback of ISP_Router (2.2.2.2):

 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# set route 2.2.2.2 next-hop 172.16.1.2 
  
 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# commit 
 commit complete 

We validate that the route has been added:

jcluser@vMX-addr-0> show route 2.2.2.2 table Customer__VR.inet.0  
 Customer__VR.inet.0: 6 destinations, 6 routes (6 active, 0 holddown, 0 hidden)
 + = Active Route, - = Last Active, * = Both
 2.2.2.2/32         *[Static/5] 00:00:34
                     > to 172.16.1.2 via lt-0/0/0.1 

But our default route is still not there:

 jcluser@vMX-addr-0> show route 0/0 exact table Customer__VR.inet.0    
 (no output) 
jcluser@vMX-addr-0>

That is because the router by default expects the next-hop to be directly connected. This is where we introduce the second option that we will describe in this article.

2) RESOLVE:

You guess right, the resolve option can be used when the specified next hop is not directly connected. 

Let’s add that to our configuration:

 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# set route 0.0.0.0/0 resolve 
  
 [edit routing-instances Customer__VR routing-options static]
 jcluser@vMX-addr-0# commit 
 commit complete

 jcluser@vMX-addr-0> show route 0/0 exact table Customer__VR.inet.0                
 Customer__VR.inet.0: 7 destinations, 7 routes (7 active, 0 holddown, 0 hidden)
 + = Active Route, - = Last Active, * = Both
 0.0.0.0/0          *[Static/5] 00:00:25, metric2 0
                     > to 172.16.1.2 via lt-0/0/0.1 

BINGO! Out default route is back!

What we did here was tell our router that it was OK for him to go to the routing table to figure out how to get to the next-hop of the static route and use that information as the next-hop.

In other words, we told our router that in order to send traffic to any unknown destination (0/0), traffic had to be sent to 2.2.2.2, and that we were giving it permission to figure out how to get to 2.2.2.2. The router did a route lookup and ended up using 172.16.1.2 as the next-hop. 

So, in order to send traffic to any destination, send traffic to 2.2.2.2, and to send traffic to 2.2.2.2 send traffic to 172.16.1.2.  This is called Route Resolution, and the next-hop in the static route is an indirect next-hop.

Here is another example:

I know! I know! Why would I want to do something like this? Why not just configure next-hop as 172.16.1.2 to start with?

Well, what if our topology is actually like this?

172.16.3/24 is not being advertised by OSPF. R1 is configured with a static route pointing to the loopback of R3, and to get to the loopback of R3 is has two possible routes learned from OSPF. And if load balancing is enabled, R1 can now send traffic going to 172.16.3/24 via both R2 and R4.

Wait! Does that mean I can have a static route with two next-hops? Yeap!

Let’s add as second interface between Customer_Router and ISP_Router and a second next-hop to our static route. 

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0] 
jcluser@vMX-addr-0# set next-hop 172.16.1.2                                              

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# set next-hop 172.16.2.2
  
[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# show next-hop [ 172.16.1.2 172.16.2.2 ];

We don’t need resolve because we are using directly connected neighbor in this example.

You can see that the routing table shows two next hops. However, only one of these next-hops is being used for forwarding traffic: the one with the > symbol.

If we check the forwarding table we can see that 172.16.1.2 is the only next hop installed. article.

jcluser@vMX-addr-0> show route forwarding-table destination 0/0 table Customer__VR.inet.0     
Routing table: Customer__VR.inet
Internet:
Enabled protocols: Bridging, 
Destination  Type RtRef Next hop             Type Index    NhRef Netif
default      user     0 0.2.80.3.0.<more>    ucst      616     4 lt-0/0/0.1
default            perm     0                rjct      690     1
0.0.0.0/32         perm     0                dscd      688     1 

In order to use both we would need to enable load balancing, but that can be the topic of another article. So, assuming we don’t want load balancing, what if we want 172.16.2.2 to be used instead of 172.16.1.1? 

That is where we start talking about preference value, and qualified next-hop.

3) PREFERENCE VALUE:

You might be familiar with the preference value assigned to each routing protocols or source of routing information, which allows the router to choose between routes for the same destination, from different routing protocols,.Yes, like administrative distance.

We already saw that the default preference value for a static route is 5.  That can of course be easily changed.

We can go under routing-options static and change the default preference for ALL static routes:

[edit routing-instances Customer__VR routing-options static]
jcluser@vMX-addr-0# set defaults preference 10 

Not what we want to do right now.

Or we can go under a specific static route and change the value only for that route:

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# set preference 10    
  
[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# commit 
commit complete
  
jcluser@vMX-addr-0> show route 0/0 exact table Customer__VR.inet.0
Customer__VR.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
 0.0.0.0/0          *[Static/10] 00:00:39
                     > to 172.16.1.2 via lt-0/0/0.1
                       to 172.16.2.2 via lt-0/0/0.7 

However, when we do that, the preference value is changed for all static routes, not for any specific next-hop.

Again, not what we want right now.

If what we want is one next-hop to be preferred over another next-hop for the same route, we need the ability to change the preference value for that specific next-hop within a specific static route. To achieve this we have something Qualified Next Hop.

4) QUALIFIED NEXT HOP

A qualified next hop is a next hop which can be “qualified” using attributes such as metric, preference, or tag.

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# set qualified-next-hop 172.16.2.2 ?  
Possible completions:
  <[Enter]>            Execute this command
+ apply-groups         Groups from which to inherit configuration data
+ apply-groups-except  Don't inherit configuration data from these groups
> bfd-liveness-detection  Bidirectional Forwarding Detection (BFD) options
  interface            Interface of qualified next hop
  mac-address          Next-hop Mac Address
  metric               Metric of qualified next hop
  preference           Preference of qualified next hop
  tag                  Tag string
  |                    Pipe through a command 

For a given static route you can configure next-hops and qualified next-hops at the same time:

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# help apropos next-hop | match set 
set next-hop 
set qualified-next-hop
---more---
  
[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# set next-hop 172.16.2.2 
  
[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# set qualified-next-hop 172.16.1.2 preference 10
  
[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# show 
next-hop 172.16.2.2;
qualified-next-hop 172.16.1.2 {
   preference 10;
} 

[edit routing-instances Customer__VR routing-options static route 0.0.0.0/0]
jcluser@vMX-addr-0# commit 
commit complete
  
jcluser@vMX-addr-0> show route 0/0 exact table Customer__VR.inet.0  
Customer__VR.inet.0: 9 destinations, 10 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
0.0.0.0/0          *[Static/5] 00:00:38
                    > to 172.16.2.2 via lt-0/0/0.7
                    [Static/10] 00:00:38
                    > to 172.16.1.2 via lt-0/0/0.1 

You can see now, that each next hop has its own preference value. Basically, we now have two static default routes with different next-hops and different preference values. The one with the LOWEST preference value is selected and becomes the active route.

Hopefully, you are still with me. Because now we are going to talk about an interesting option, the TRASH CAN!  

5) REJECT/DISCARD

Imagine that instead of pointing your static route to the address of one of your neighbors, you point it to the trash can or bit bucket.  That is, when traffic matches this route it is thrown away.  Sounds kind of absurd but believe it or now, there are situations when you want exactly that, and surely, we will talk about that in a few.  For now, just have faith, and keep reading. 

Before I get into the examples, let me explain one more thing. There are two types of trash cans: one that is silent, and one that tells about the packet being dropped.

And BTW. This is how I remember which one is which: Discard Don’t sent an ICMP message back.

Let’s take a look at an example, where using the trash can is useful.

Our customer router has learned routes to the subnets 172.16.100/28, 172.16.100.16/28, 172.16.100.32/28 and 172.16.100.48/28.

If you do a little binary math on the last octet, you will find that these 4 subnets have in common the first 26 bits.

Thus, the 4 subnets can be summarized as 172.16.100/26, which the ISP_Router has a static route in its routing table for. 

Life is good as long as all 4 subnets are up and reachable, as shown in the example below:

1) ISP_Router receives a packet with DA = 172.16.100.50

2) ISP_Router performs a L3 lookup, and the packet matches the static route pointing to 172.16.1.1

3) Packet is sent to Customer_Router

4) Customer_Router also performs a L3 lookup

5) Customer_Router sends the packet out of ge-0/0/0.0 to the proper next-hop (not shown in the diagram).

Now, what if network 172.16.100.48/28 becomes unavailable?

The ISP_Router is NOT aware of this subnet being unavailable, so when the packet going to 172.16.100.50 arrives, it forwards it the exact same way.

And here we go, because the specific route to 172.16.100.48/28 is no longer present in Customer_Router’s routing table, the only route that matches is the default route which points back to 172.16.1.2 (the ISP_Router). And guess what? When the ISP_Router receives the packet back, it does an L3 lookup and determines that the packet needs to sent back to Customer_Router.

You just got a beautiful routing loop!!! It will stop when the TTL expire, thanks goodness, but in the meantime you are wasting resources!

The solution is quite simple: Add a static route that summarizes all the subnets, and has a next-hop equal to (yes) the trash can!

So, when the packet arrives now to Customer_Router (while the specific subnet is still unreachable), the packet matches the 172.16.100/26 route because of longest match. As a result, the packet is thrown away, rather than sent back to the ISP_Router.  Some bandwidth and processing cycles were saved.

But what if all 4 subnets are down?  The ISP_Router has no clue, so any traffic that the ISP_Router receives going to any of these subnets is going to be sent to the Customer_Router, only to be dropped.

It would be nice if the route that the ISP_Router has for the networks inside the customer’s site, was dynamic and would go away when all the networks are down.

Let’s say that the customer has decided to run BGP and use routing policies to exchange routing information with the ISP and with the internal networks.  Here is our new topology:

The relevant configuration sections are shown below:

– Enable tunnel services so that tunnel interfaces get created:

[edit chassis]
jcluser@vMX-addr-0# show | display set relative 
set fpc 0 pic 0 tunnel-services  

– Configure the interfaces:

[edit interfaces]
jcluser@vMX-addr-0# show | display set relative    
set lt-0/0/0 unit 1 encapsulation ethernet
set lt-0/0/0 unit 1 peer-unit 2
set lt-0/0/0 unit 1 family inet address 172.16.2.1/24
set lt-0/0/0 unit 2 encapsulation ethernet
set lt-0/0/0 unit 2 peer-unit 1
set lt-0/0/0 unit 2 family inet address 172.16.2.2/24
set lt-0/0/0 unit 3 encapsulation ethernet
set lt-0/0/0 unit 10 encapsulation ethernet
set lt-0/0/0 unit 10 peer-unit 11
set lt-0/0/0 unit 10 family inet address 172.16.1.2/24
set lt-0/0/0 unit 11 encapsulation ethernet
set lt-0/0/0 unit 11 peer-unit 10
set lt-0/0/0 unit 11 family inet address 172.16.1.1/24
set lo0 unit 11 family inet address 172.16.100.1/28
set lo0 unit 11 family inet address 172.16.100.17/28
set lo0 unit 11 family inet address 172.16.100.33/28
set lo0 unit 11 family inet address 172.16.100.49/28  

NOTE: The loopback addresses will simulate the internal subnets

– Add routing instance that will simulate the multiple routers:

[edit routing-instances]
jcluser@vMX-addr-0# show | display set relative    
set Customer_Router_VR instance-type virtual-router
set Customer_Router_VR interface lt-0/0/0.1
set Customer_Router_VR interface lt-0/0/0.10
set Customer_Router_VR routing-options autonomous-system 100
set Customer_Router_VR routing-options autonomous-system independent-domain
set Customer_Router_VR protocols bgp group IBGP peer-as 100
set Customer_Router_VR protocols bgp group IBGP neighbor 172.16.1.1
set Customer_Router_VR protocols bgp group EBGP export SUMMARY
set Customer_Router_VR protocols bgp group EBGP peer-as 200
set Customer_Router_VR protocols bgp group EBGP neighbor 172.16.2.2
set ISP_Router_VR instance-type virtual-router
set ISP_Router_VR interface lt-0/0/0.2
set ISP_Router_VR routing-options autonomous-system 200
set ISP_Router_VR routing-options autonomous-system independent-domain
set ISP_Router_VR protocols bgp group EBGP peer-as 100
set ISP_Router_VR protocols bgp group EBGP neighbor 172.16.2.1
set SITE1_GW_VR instance-type virtual-router
set SITE1_GW_VR interface lt-0/0/0.11
set SITE1_GW_VR interface lo0.11
set SITE1_GW_VR routing-options autonomous-system 100
set SITE1_GW_VR routing-options autonomous-system independent-domain
set SITE1_GW_VR protocols bgp group IBGP local-address 172.16.1.1
set SITE1_GW_VR protocols bgp group IBGP export lo0.11
set SITE1_GW_VR protocols bgp group IBGP peer-as 100
set SITE1_GW_VR protocols bgp group IBGP local-as 100
set SITE1_GW_VR protocols bgp group IBGP neighbor 172.16.1.2 

– Configure the routing-policies referenced under protocols BGP:

[edit policy-options policy-statement SUMMARY]
jcluser@vMX-addr-0# show | display set relative 
set term 1 from route-filter 172.16.100.0/26 exact
set term 1 then accept
set term 2 then reject
  
[edit policy-options policy-statement lo0.11]
jcluser@vMX-addr-0# show | display set relative                    
set term 1 from protocol direct
set term 1 from interface lo0.11
set term 1 then accept 

Notice that SITE1_GW_VR is using a routing-policy called lo0.11, which advertises the subnets under lo0.11.  Then Customer_Router_VR is using a policy called SUMMARY which matches 172.16.100.0/26 exact, and rejects everything else. Thus, the only route that Customer_Router_VR will advertise to the ISP is the 172.16.100.0/26. Remember that by default, active IBGP routes are advertised to EBGP neighbor, and we do not want to advertise the specific routes, only the summary.   

We check the routes that we are receiving from SITE1. We see all 4 subnets coming in.

jcluser@vMX-addr-0> show route receive-protocol bgp 172.16.1.1 table Customer_Router.inet.0
Customer_Router_VR.inet.0: 8 destinations, 8 routes (8 active, 0 holddown, 0 hidden)
  Prefix  Nexthop       MED     Lclpref    AS path
* 172.16.100.0/28          172.16.1.1                   100        I
* 172.16.100.16/28         172.16.1.1                   100        I
* 172.16.100.32/28         172.16.1.1                   100        I
* 172.16.100.48/28         172.16.1.1                   100        I 

Then we check what we are advertising the ISP. We see nothing!!

jcluser@vMX-addr-0> show route advertising-protocol bgp 172.16.2.2 table Customer_Router
(no output)
jcluser@vMX-addr-0>  

Remember that our export policy only matches on 172.16.100/26 exact. All the routes we are receiving are /28.  So, let’s add a static route for the summary route.

[edit routing-instances Customer_Router_VR routing-options]
jcluser@vMX-addr-0# set static route 172.16.100/26 reject 
 
[edit routing-instances Customer_Router_VR routing-options]
jcluser@vMX-addr-0# commit 
commit complete 

And then we check what we are sending to the ISP Router again. The route is being advertised now.

jcluser@vMX-addr-0> show route advertising-protocol bgp 172.16.2.2 table Customer_Router_VR.inet.0
Customer_Router_VR.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
Prefix                  Nexthop       MED     Lclpref    AS path
172.16.100.0/26         Self                               I 

Even though we were able to send the route dynamically to the ISP, we are really not achieving what we wanted.  The reason why we made all these changes was to make sure that if all the internal networks went away, the ISP would stop sending us traffic. I am sure you realize that this is not happening, and why, but let’s take a look.

We can simply shutdown the interface connecting to SITE1.

root@vMX-addr-0:/var/home/jcluser # ifconfig lt-0/0/0.10 down
root@vMX-addr-0:/var/home/jcluser # 

And all the routes we were receiving are obviously gone. However,the static routes is still there, and the ISP is still receiving the information.

jcluser@vMX-addr-0> show route 172.16.100/24                   
Customer_Router_VR.inet.0: 4 destinations, 4 routes (4 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Static/5] 00:04:44
                       Reject
ISP_Router_VR.inet.0: 3 destinations, 3 routes (3 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[BGP/170] 00:04:44, localpref 100
                     AS path: 100 I, validation-state: unverified
                   > to 172.16.2.1 via lt-0/0/0.2 

If you still remember some of what you read about static routes 😉 , you will know that the requirement for a static route to be active is next-hop reachability. Turns out we are just using our trash can as next hop, so our static route in this case will always be active.

OK, we know now that this is NOT going to work the way we want!! What do we do then?

This is where we finally introduce the idea of aggregate and generated routes. Get comfortable and keep reading.

AGGREGATE ROUTES

Aggregate routes are also manually defined routes, but have some interesting characteristics. They represent a collection of more specific routes, and the key here is “more specific routes”.

Aggregate routes are also defined under the [edit routing-options] hierarchy level by defining a destination prefix, but they do NOT give you the option of configuring a next hop.

Let me repeat that: aggregate routes do NOT let you configure a next hop address.

[edit routing-options aggregate]
jcluser@vMX-addr-0# set route 172.16.100/26 next-h?      
No valid completions 

So guess what, you can only point traffic matching an aggregate route to: the trash can!

You can do reject, which is the default, when you don’t specify anything (not an actual keyword), OR discard if you explicitly define it.

[edit routing-options aggregate]
jcluser@vMX-addr-0# set route 172.16.100/26 r?  
No valid completions
  
[edit routing-options aggregate]
jcluser@vMX-addr-0# set route 172.16.100/26 d?  
Possible completions:
discard              Drop packets to destination; send no ICMP unreachables 

There is the first difference between statics and aggregate routes: the NEXT HOP!

Now, the big great awesome difference between aggregates and statics is something called: CONTRIBUTING ROUTES. 

Aggregate routes must have at least one contributing route! That is the requirement for aggregate routes to become active.

Let’s go back to the lab and replace the static route with an aggregate route.

We first create the aggregate route:

[edit routing-instances Customer_Router_VR routing-options aggregate]
jcluser@vMX-addr-0# set route 172.16.100/26 discard         
  
[edit routing-instances Customer_Router_VR routing-options aggregate]
jcluser@vMX-addr-0# commit 
commit complete 

And modify the policy:

[edit policy-options policy-statement SUMMARY]
jcluser@vMX-addr-0# set term 1 from protocol aggregate 
  
[edit policy-options policy-statement SUMMARY]
jcluser@vMX-addr-0# show | display set relative 
set term 1 from protocol aggregate
set term 1 from route-filter 172.16.100.0/26 exact
set term 1 then accept
set term 2 then reject 

We then check the status of the new route and we notice that it is HIDDEN!. 

jcluser@vMX-addr-0> show route protocol aggregate hidden table Customer_Router_VR.inet.0 
Customer_Router_VR.inet.0: 9 destinations, 10 routes (9 active, 0 holddown, 1 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26     [Aggregate] 00:02:30
                     Discard  

When we look at the details.

jcluser@vMX-addr-0> show route protocol aggregate hidden table Customer_Router_VR.inet.0 extensive  
Customer_Router_VR.inet.0: 9 destinations, 10 routes (9 active, 0 holddown, 1 hidden)
172.16.100.0/26 (2 entries, 1 announced)
TSI:
KRT in-kernel 172.16.100.0/26 -> {}
          Aggregate
                 Next hop type: Discard, Next hop index: 0
                 Address: 0xce30670
                 Next-hop reference count: 1
                 State: <Hidden Int Ext>
                 Inactive reason: Unusable path
                 Local AS:   100 
                 Age: 1:40 
                 Validation State: unverified 
                 Task: Aggregate
                 AS path: I 
                                 Flags: Discard Depth: 0 Inactive 

We find “inactive reason: unusable path”.  Then we remember that we shut down the interface lt-0/0/0.10 before! 😊

root@vMX-addr-0:/var/home/jcluser # ifconfig lt-0/0/0.10 up
root@vMX-addr-0:/var/home/jcluser #

We fix that, and now the route is a valid route. Thought we notice that it is not active.

jcluser@vMX-addr-0> show route 172.16/16 table Customer_Router_VR.inet protocol aggregate  
Customer_Router_VR.inet.0: 9 destinations, 10 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26     [Aggregate/130] 00:00:21
                     Discard 

Can you figure out why?

Check the routing table again, this time without specifying protocol aggregate.

jcluser@vMX-addr-0> show route 172.16.100/26 exact table Customer_Router_VR.inet.0     
Customer_Router_VR.inet.0: 9 destinations, 10 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Static/5] 00:32:43
                    Reject
                    [Aggregate/130] 00:02:18
                    Discard  

Aha! We never removed the static route that we had previously configured, and if you pay attention to the values between square brackets you will see that the default preference value for aggregate routes is 130, and the default for static routes is 5. Lower is better, thus the static route is selected as the active route.

We need to fix this if we want BGP to advertise the route, as it only considers active routes for advertisement by default.

We can just deactivate the static route:

[edit]
jcluser@vMX-addr-0# top deactivate routing-instances Customer_Router_VR routing-options static    
  
[edit]
jcluser@vMX-addr-0# commit 
commit complete 

And here we go:

jcluser@vMX-addr-0> show route 172.16/16 table Customer_Router_VR.inet protocol aggregate     
Customer_Router_VR.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Aggregate/130] 00:04:15
                      Discard 

Our aggregate is active, because the static is no longer there, though don’t forget the magic sauce: Contributing routes!

If we look at the extensive show route output, we can see the list of routes contributing to this aggregate.

jcluser@vMX-addr-0> show route 172.16/16 table Customer_Router_VR.inet protocol aggregate extensive    
Customer_Router_VR.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
172.16.100.0/26 (1 entry, 1 announced)
TSI:
KRT in-kernel 172.16.100.0/26 -> {}
Page 0 idx 1, (group EBGP type External) Type 1 val 0xba0bfc0 (adv_entry)
    Advertised metrics:
      Nexthop: Self
      AS path: [100] I (LocalAgg)
      Communities:
      Path 172.16.100.0 Vector len 4.  Val: 1
         *Aggregate Preference: 130
                 Next hop type: Discard, Next hop index: 0
                 Address: 0xce30670
                 Next-hop reference count: 2
                 State: <Active Int Ext>
                 Local AS:   100 
                 Age: 5:05 
                 Validation State: unverified 
                 Task: Aggregate
                 Announcement bits (3): 0-KRT 1-BGP_RT_Background 2-Resolve tree 1 
                 AS path: I  (LocalAgg)
                                 Flags: DiscardDepth: 0Active
                 AS path list:
                 AS path: I Refcount: 4
                 Contributing Routes (4):
                 172.16.100.0/28 proto BGP
                 172.16.100.16/28 proto BGP
                 172.16.100.32/28 proto BGP
                 172.16.100.48/28 proto BGP 

Remember again: Contributing routes are more specific routes within the range defined by your aggregate. And, as long as one of this routes exists in the routing table, your aggregate with be active in the routing table.

If your aggregate is 172.16.1/24, any route that begins with 172.16.1.0 in the first 24 bits and is more specific (subnet mask is longer than 24), will be a contributing route.  172.16.1.0/26, 172.16.1.128/26, 172.16.1.192/28, 172.16.1.208/28 and 172.16.1.240/28 are examples of contributing routes for 172.16.1/24. 

Notice that I highlighted ANY ROUTE. That means any route that is more specific.  You could configure an aggregate as 0/0, and every single route in the routing table will be more specific than 0/0, and will be a contributing route. 

What if I only want certain routes to be contributing routes, and I want the aggregate to go away when those particular routes go away, regardless of the presence of other specific routes?

The answer is: Routing Policies!!!

Let’s go back to the lab to see how.

Here is our new topology and config:

 [edit interfaces]
 jcluser@vMX-addr-0# show | display set relative 
 set lt-0/0/0 unit 1 encapsulation ethernet
 set lt-0/0/0 unit 1 peer-unit 2
 set lt-0/0/0 unit 1 family inet address 172.16.2.1/24
 set lt-0/0/0 unit 2 encapsulation ethernet
 set lt-0/0/0 unit 2 peer-unit 1
 set lt-0/0/0 unit 2 family inet address 172.16.2.2/24
 set lt-0/0/0 unit 10 encapsulation ethernet
 set lt-0/0/0 unit 10 peer-unit 11
 set lt-0/0/0 unit 10 family inet address 172.16.1.2/30
 set lt-0/0/0 unit 11 encapsulation ethernet
 set lt-0/0/0 unit 11 peer-unit 10
 set lt-0/0/0 unit 11 family inet address 172.16.1.1/30
 set lt-0/0/0 unit 20 encapsulation ethernet
 set lt-0/0/0 unit 20 peer-unit 21
 set lt-0/0/0 unit 20 family inet address 172.16.1.130/30
 set lt-0/0/0 unit 21 encapsulation ethernet
 set lt-0/0/0 unit 21 peer-unit 20
 set lt-0/0/0 unit 21 family inet address 172.16.1.129/30
 set lo0 unit 1 family inet address 172.16.100.1/28
 set lo0 unit 1 family inet address 172.16.100.17/28
 set lo0 unit 1 family inet address 172.16.100.33/28
 set lo0 unit 1 family inet address 172.16.100.49/28
 set lo0 unit 2 family inet address 172.16.100.65/28
 set lo0 unit 2 family inet address 172.16.100.81/28
 set lo0 unit 2 family inet address 172.16.100.97/28
 set lo0 unit 2 family inet address 172.16.100.113/28
  
 [edit routing-instances]
 jcluser@vMX-addr-0# show | display set relative 
 set Customer_Router_VR instance-type virtual-router
 set Customer_Router_VR interface lt-0/0/0.1
 set Customer_Router_VR interface lt-0/0/0.10
 set Customer_Router_VR interface lt-0/0/0.20
 set Customer_Router_VR routing-options autonomous-system 100
 set Customer_Router_VR routing-options autonomous-system independent-domain
 set Customer_Router_VR protocols bgp group IBGP type internal
 set Customer_Router_VR protocols bgp group IBGP neighbor 172.16.1.1
 set Customer_Router_VR protocols bgp group IBGP neighbor 172.16.1.129
 set Customer_Router_VR protocols bgp group EBGP neighbor 172.16.2.2 peer-as 200
 set ISP_Router_VR instance-type virtual-router
 set ISP_Router_VR interface lt-0/0/0.2
 set ISP_Router_VR routing-options autonomous-system 200
 set ISP_Router_VR protocols bgp group EBGP neighbor 172.16.2.1 peer-as 100
 set SITE1_GW instance-type virtual-router
 set SITE1_GW interface lt-0/0/0.11
 set SITE1_GW interface lo0.1
 set SITE1_GW routing-options autonomous-system 100
 set SITE1_GW routing-options autonomous-system independent-domain
 set SITE1_GW protocols bgp group IBGP type internal
 set SITE1_GW protocols bgp group IBGP export LOOPBACK
 set SITE1_GW protocols bgp group IBGP neighbor 172.16.1.2
 set SITE2_GW instance-type virtual-router
 set SITE2_GW interface lt-0/0/0.21
 set SITE2_GW interface lo0.2
 set SITE2_GW routing-options autonomous-system 100
 set SITE2_GW routing-options autonomous-system independent-domain
 set SITE2_GW protocols bgp group IBGP type internal
 set SITE2_GW protocols bgp group IBGP export LOOPBACK
 set SITE2_GW protocols bgp group IBGP neighbor 172.16.1.130
  
 [edit policy-options policy-statement LOOPBACK]
 jcluser@vMX-addr-0# show | display set relative 
 set term 1 from protocol direct
 set term 1 from interface lo0.1
 set term 1 from interface lo0.2
 set term 1 then accept 

There are now two different sites connected to the Customer Router. Each site is advertising 4 different subnets as shown:

The Customer Router should summarize the routes from each site and send that summary to the other site, and should summarize the entire range from both sites, and advertise that summary and only that summary to the ISP Router (no specific routes).  The advertisements should stop if all the subnets go away.

Based on our current configuration the Customer_Router is receiving the subnets from the SITES, is advertising everything to the ISP router, but nothing to the SITE GWs.  

jcluser@vMX-addr-0> show route 172.16.100/24 table SITE1_GW.inet.0 terse | match /2     
* ? 172.16.100.0/28    D   0                       >lo0.1       
* ? 172.16.100.16/28   D   0                       >lo0.1       
* ? 172.16.100.32/28   D   0                       >lo0.1       
* ? 172.16.100.48/28   D   0                       >lo0.1       
  
jcluser@vMX-addr-0> show route 172.16.100/24 table SITE2_GW.inet.0 terse | match /2      
* ? 172.16.100.64/28   D   0                       >lo0.2       
* ? 172.16.100.80/28   D   0                       >lo0.2       
* ? 172.16.100.96/28   D   0                       >lo0.2       
* ? 172.16.100.112/28  D   0                       >lo0.2       
  
jcluser@vMX-addr-0> route 172.16.100/24 table Customer_Router_VR.inet.0 | match "172.16"      
172.16.100.0/28    *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.1 via lt-0/0/0.10
172.16.100.16/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.1 via lt-0/0/0.10
172.16.100.32/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.1 via lt-0/0/0.10
172.16.100.48/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.1 via lt-0/0/0.10
172.16.100.64/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.129 via lt-0/0/0.20
172.16.100.80/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.129 via lt-0/0/0.20
172.16.100.96/28   *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.129 via lt-0/0/0.20
172.16.100.112/28  *[BGP/170] 01:56:38, localpref 100
                    > to 172.16.1.129 via lt-0/0/0.20

jcluser@vMX-addr-0> show route 172.16.100/24 table ISP_Router_VR.inet.0 | match "172.16"         172.16.100.0/28    *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.16/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.32/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.48/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.64/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.80/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.96/28   *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2
172.16.100.112/28  *[BGP/170] 01:54:48, localpref 100
                    > to 172.16.2.1 via lt-0/0/0.2 

We can solve the lack of advertisements to the SITE GWs quite easily.

We first create a couple of aggregate routes:

[edit routing-instances Customer_Router_VR routing-options]
jcluser@vMX-addr-0# set aggregate route 172.16.100/26 discard 
  
[edit routing-instances Customer_Router_VR routing-options]
jcluser@vMX-addr-0# set aggregate route 172.16.100.64/26 discard 
  
[edit routing-instances Customer_Router_VR routing-options]
jcluser@vMX-addr-0# commit 
commit complete
  
jcluser@vMX-addr-0> show route protocol aggregate table Customer_Router_VR.inet.0 
Customer_Router_VR.inet.0: 16 destinations, 16 routes (16 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Aggregate/130] 00:00:31
                     Discard
172.16.100.64/26   *[Aggregate/130] 00:00:31
                     Discard
  
jcluser@vMX-addr-0> show route protocol aggregate table Customer_Router_VR.inet.0 
Customer_Router_VR.inet.0: 16 destinations, 16 routes (16 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Aggregate/130] 00:00:31
                     Discard
172.16.100.64/26   *[Aggregate/130] 00:00:31
                     Discard 

Then we create an export policy to advertise the aggregates to the SITES.

[edit policy-options]
jcluser@vMX-addr-0# show | display set relative | match AGG   
set policy-statement AGGREGATE1 term 1 from route-filter 172.16.100.64/26 exact
set policy-statement AGGREGATE1 term 1 then accept
set policy-statement AGGREGATE2 term 1 from route-filter 172.16.100.0/26 exact
set policy-statement AGGREGATE2 term 1 then accept
  
[edit routing-instances Customer_Router_VR protocols bgp group IBGP]
jcluser@vMX-addr-0# set neighbor 172.16.1.1 export AGGREGATE1      
  
[edit routing-instances Customer_Router_VR protocols bgp group IBGP]
jcluser@vMX-addr-0# set neighbor 172.16.1.129 export AGGREGATE2    
  
[edit routing-instances Customer_Router_VR protocols bgp group IBGP]
jcluser@vMX-addr-0# commit 
commit complete 

We check the routing tables of the SITE GW routers and yeap! Routes are there now.  

jcluser@vMX-addr-0> show route table SITE1_GW.inet.0 protocol bgp
SITE1_GW.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.64/26   *[BGP/170] 00:00:27, localpref 100
                     AS path: I, validation-state: unverified
                   > to 172.16.1.2 via lt-0/0/0.11
 
jcluser@vMX-addr-0> show route table SITE2_GW.inet.0 protocol bgp    
SITE2_GW.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[BGP/170] 00:00:33, localpref 100
                     AS path: I, validation-state: unverified
                   > to 172.16.1.130 via lt-0/0/0.21 

We should in fact be able to ping from one site to the other.

jcluser@vMX-addr-0# run ping 172.16.100.65 source 172.16.100.1 routing-instance SITE1_GW rapid           
PING 172.16.100.65 (172.16.100.65): 56 data bytes
!!!!!
--- 172.16.100.65 ping statistics ---
5 packets transmitted, 5 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.310/0.424/0.697/0.141 ms 

First problem solved! Let’s now tackle the second one.  We should not be advertising everything to the ISP router as we are, only a summary for the entire range of addresses from the two Sites.

You probably thought about it already: a summary => a third aggregate route, and a new policy.

 [edit routing-instances Customer_Router_VR routing-options aggregate]
 jcluser@vMX-addr-0# show 
 route 172.16.100.0/26 discard;
 route 172.16.100.64/26 discard;
  
 [edit routing-instances Customer_Router_VR routing-options aggregate]
 jcluser@vMX-addr-0# set route 172.16.100.0/25 discard
 
 [edit policy-options]
 jcluser@vMX-addr-0# copy policy-statement AGGREGATE2 to policy-statement AGGREGATE3  
  
 [edit policy-options]
 jcluser@vMX-addr-0# edit policy-statement AGGREGATE3  
 
 [edit policy-options policy-statement AGGREGATE3]
 jcluser@vMX-addr-0# replace pattern /26 with /25
  
 [edit policy-options policy-statement AGGREGATE3]
 jcluser@vMX-addr-0# show | display set relative 
 set term 1 from route-filter 172.16.100.0/25 exact
 set term 1 then accept
  
 [edit routing-instances Customer_Router_VR protocols bgp group EBGP]
 jcluser@vMX-addr-0# set export AGGREGATE3 
 
 [edit routing-instances Customer_Router_VR protocols bgp group EBGP]
 jcluser@vMX-addr-0# commit 
 commit complete 

We check the routing table of ISP Router and…

 jcluser@vMX-addr-0> show route 172.16.100/24 table ISP_Router_VR.inet.0 terse 
 ISP_Router_VR.inet.0: 11 destinations, 11 routes (11 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.100.0/25    B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.0/28    B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.16/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.32/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.48/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.64/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.80/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.96/28   B 170        100                             100 I
   unverified                                       >172.16.2.1
 * ? 172.16.100.112/28  B 170        100                             100 I
   unverified                                       >172.16.2.1 

Wait! We see the aggregate route, but we still see all 8 specific routes. WHY?

Well, BGP advertisement rules, and default policy: “An active IBGP route is advertised to EBGP neighbors by default.”

We need to make sure that our policy overrides this behavior, so we go back and slightly change it:

[edit policy-options policy-statement AGGREGATE3]
jcluser@vMX-addr-0# set term 2 then reject
  
[edit policy-options policy-statement AGGREGATE3]
jcluser@vMX-addr-0# commit                                                 
commit complete 

We check the routing table of ISP Router again:  

jcluser@vMX-addr-0> show route 172.16.100/24 table ISP_Router_VR.inet.0 terse    
ISP_Router_VR.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.100.0/25    B 170        100                             100 I
  unverified                                       >172.16.2.1 

And that looks much better. Second problem solved!

We also said that these advertisements should stop when the subnets go away.  We really don’t need to do anything at this point, but let’s check the contributing routes to see how this will work:

For the 172.16.100/26 aggregate, only the 4 subnets received from SITE1_GW are contributing routes. When these 4 routes go away, the aggregate will go away.

jcluser@vMX-addr-0> show route 172.16.100.0/26 exact table Customer_Router_VR.inet.0 extensive | find contributing     
                 Contributing Routes (4):
                 172.16.100.0/28 proto BGP
                 172.16.100.16/28 proto BGP
                 172.16.100.32/28 proto BGP
                 172.16.100.48/28 proto BGP 

For the 172.16.100.64/26 aggregate, only the 4 subnets received from SITE2_GW are contributing routes. When these 4 routes go away, the aggregate will go away:

jcluser@vMX-addr-0> show route 172.16.100.64/26 exact table Customer_Router_VR.inet.0 extensive | find contributing               
                 Contributing Routes (4):
                 172.16.100.64/28 proto BGP
                 172.16.100.80/28 proto BGP
                 172.16.100.96/28 proto BGP
                 172.16.100.112/28 proto BGP 

And for the 172.16.100.0/25 aggregate we have:

jcluser@vMX-addr-0> show route 172.16.100.0/25 exact table Customer_Router_VR.inet.0 extensive | find contributing    
                 Contributing Routes (2):
                 172.16.100.0/26 proto Aggregate
                 172.16.100.64/26 proto Aggregate 

Interesting!!! I bet you were expecting 172.16.100.0/28, 172.16.100.16/28, 172.16.100.32/28 and so on to all be listed here. But a route can only be a contributing route of ONE aggregate.  The 8 subnets are contributing routes of the /26 aggregates already. 

SO:  

  • if the 4 subnets from SITE1 go away, 172.16.100.0/26 goes away,
  • if the 4 subnets from SITE2 go away, 172.16.100.65/26 goes away, and
  • if all 8 subnets go away, the two /26 aggregates which are the contributing routes of the /25 go away, Thus the /25 goes away too!

Now, one more thing before we move on to GENERATED routes: what if I do not want all the more specific routes within a range to be considered contributing routes?

Here is our new sample topology to look at this next question:

The situation is here is the following. SITE_GW1 and SITE-GW2 are both learning about subnets 172.16.100/28, 172.16.100.16/28, 172.16.100.32/28 and 172.16.100.64/28 from some IGP. Customer Router_1 and Customer_Router_2 will aggregate these subnets and advertise the aggregate to ISP_Router1 and ISP_Router2. 

However, we need to make sure that the aggregate is only advertised if the router has specific routes to 172.16.100/28 and 172.16.100.48/28 (we only care about these two subnets). In other words, we want the Customer routers to stop advertising the aggregate if these two prefixes are no longer known.  Let’s say that these two destinations are critical and we want Customer_Router_1 to stop advertising the aggregate when these two routes go away, so that the ISP starts sending traffic towards Customer_Router_2, for example.

What we need to do is make sure that ONLY these subnets are contributing routes.  Let’s take a look at how to achieve this.

I am going to build only the top half of the topology, to demonstrate.

[edit interfaces]
jcluser@vMX-addr-0# show | display set relative 
set lt-0/0/0 unit 1 encapsulation ethernet
set lt-0/0/0 unit 1 peer-unit 2
set lt-0/0/0 unit 1 family inet address 172.16.1.1/24
set lt-0/0/0 unit 2 encapsulation ethernet
set lt-0/0/0 unit 2 peer-unit 1
set lt-0/0/0 unit 2 family inet address 172.16.1.2/24
set lt-0/0/0 unit 3 encapsulation ethernet
set lt-0/0/0 unit 3 peer-unit 4
set lt-0/0/0 unit 3 family inet address 172.16.2.1/24
set lt-0/0/0 unit 4 encapsulation ethernet
set lt-0/0/0 unit 4 peer-unit 3
set lt-0/0/0 unit 4 family inet address 172.16.2.2/24
set lo0 unit 0 family inet address 172.16.100.1/28
set lo0 unit 0 family inet address 172.16.100.17/28
set lo0 unit 0 family inet address 172.16.100.33/28
set lo0 unit 0 family inet address 172.16.100.49/28
 
[edit routing-instances]
jcluser@vMX-addr-0# show | display set relative 
set Customer_Router_1 instance-type virtual-router
set Customer_Router_1 interface lt-0/0/0.2
set Customer_Router_1 interface lt-0/0/0.3
set Customer_Router_1 routing-options aggregate route 172.16.100.0/26 discard
set Customer_Router_1 routing-options autonomous-system 100
set Customer_Router_1 routing-options autonomous-system independent-domain
set Customer_Router_1 protocols bgp group IBGP neighbor 172.16.1.1 peer-as 100
set Customer_Router_1 protocols bgp group EBGP export aggregate
set Customer_Router_1 protocols bgp group EBGP neighbor 172.16.2.2 peer-as 200
set ISP_Router_1 instance-type virtual-router
set ISP_Router_1 interface lt-0/0/0.4
set ISP_Router_1 routing-options autonomous-system 200
set ISP_Router_1 routing-options autonomous-system independent-domain
set ISP_Router_1 protocols bgp group EBGP neighbor 172.16.2.1 peer-as 100
set SITE_GW1 instance-type virtual-router
set SITE_GW1 interface lt-0/0/0.1
set SITE_GW1 interface lo0.0
set SITE_GW1 routing-options autonomous-system 100
set SITE_GW1 routing-options autonomous-system independent-domain
set SITE_GW1 protocols bgp group IBGP export loopback
set SITE_GW1 protocols bgp group IBGP neighbor 172.16.1.2 peer-as 100
 
[edit policy-options policy-statement loopback]
jcluser@vMX-addr-0# show| display set relative 
set term 1 from protocol direct
set term 1 from interface lo0.0
set term 1 then accept
 
[edit policy-options policy-statement aggregate]
jcluser@vMX-addr-0# show | display set relative 
set term 1 from protocol aggregate
set term 1 then accept
set term 2 then reject 

As in previous examples, with our current configuration Customer_Router_1 will be advertising the aggregate route only to ISP_Router_1, as required:

jcluser@vMX-addr-0> show route advertising-protocol bgp 172.16.2.2 
Customer_Router_1.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
 Prefix  Nexthop       MED     Lclpref    AS path
* 172.16.100.0/26         Self                                    I 

However, the contributing routes of the aggregate are all 4 subnets:

jcluser@vMX-addr-0> show route 172.16.100/26 exact table Customer_Router_1.inet.0 extensive | find contributing
                 Contributing Routes (4):
                 172.16.100.0/28 proto BGP
                 172.16.100.16/28 proto BGP
                 172.16.100.32/28 proto BGP
                 172.16.100.48/28 proto BGP 

We need only 172.16.100/28 and 172.16.100.48/28 to be contributing routes. To achieve this we are going to create another routing-policy:

[edit policy-options policy-statement contributing]
jcluser@vMX-addr-0# show| display set relative 
set term 1 from route-filter 172.16.100.0/28 exact
set term 1 from route-filter 172.16.100.48/28 exact
set term 1 then accept
set term 2 then reject 

And apply it to the aggregate route itself:

[edit routing-instances Customer_Router_1 routing-options]
jcluser@vMX-addr-0# set aggregate route 172.16.100.0/26 policy contributing 

And now, only the two routes that we are interested on are considered contributing routes as we wanted:

jcluser@vMX-addr-0> route 172.16.100/26 exact table Customer_Router_1.inet.0 extensive | find contributing   
                 Contributing Routes (2):
                 172.16.100.0/28 proto BGP
                 172.16.100.48/28 proto BGP 

At this point we have probably covered more stuff about static and aggregate routes that you could ever imagine, but there is yet another route type that we need to talk about.  

GENERATED ROUTES

This types of routes are similar to aggregate routes: they need contributing routes to exist! However, as you probably imagine there is one big difference, else why have them?

The big difference is that while aggregate routes do NOT allow you to configure a next-hop but only the trash can, generated routes do NOT allow you to configure either, though they DO HAVE a next-hop = a neighbor address.

[edit]
jcluser@vMX-addr-0# set routing-options generate route 172.16.100/26 discard?
No valid completions
 
[edit]
jcluser@vMX-addr-0# set routing-options generate route 172.16.100/26 next-hop?    
No valid completions 

But, if the router does not allow you to configure a next-hop, where does it get it from?

The answer is: the router figures it out! The generated route inherits the next-hop of the primary contributing route, which is selected based on metric, preference value, and other attributes.  Let’s take a look at an example:

The idea here is that Customer Router has a summary route, that requires contributing routes, and goes away when those contributing routes go away. The summary can be advertised to the ISP router, just like we did before with aggregate routes.

However, in this case rather than throwing away a packet when a specific subnet is not know, the packet is sent to the next hop of the aggregate. You will find that this is described as gateway of last resource in some documents.

The address of the next-hop for the generated route, will be inherited from one of the contributing routes.

Let’s take a look using the same configuration in the previous example, though for now, we are going to remove the export policy from EBGP:

[edit routing-instances Customer_Router_1 protocols bgp group EBGP]
jcluser@vMX-addr-0# delete export 
 
[edit routing-instances Customer_Router_1 protocols bgp group EBGP]
jcluser@vMX-addr-0# commit 
commit complete 

Let’s check that we are receiving all the routes:

jcluser@vMX-addr-0> show route receive-protocol bgp 172.16.1.1 table Customer_Router_1.inet.0 
Customer_Router_1.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
   Prefix  Nexthop       MED     Lclpref    AS path
* 172.16.100.0/28         172.16.1.1                   100        I
* 172.16.100.16/28        172.16.1.1                   100        I
* 172.16.100.32/28        172.16.1.1                   100        I
* 172.16.100.48/28        172.16.1.1                   100        I 

We know that because of the BGP default policy these will all be advertised to the ISP router:

jcluser@vMX-addr-0> show route advertising-protocol bgp 172.16.2.2 
Customer_Router_1.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
   Prefix  Nexthop       MED     Lclpref    AS path
* 172.16.100.0/28         Self                                    I
* 172.16.100.16/28        Self                                    I
* 172.16.100.32/28        Self                                    I
* 172.16.100.48/28        Self                                    I 

To stop these routes from being advertised, and replace them with a summary we are going to create a generated route, and export it with a new policy.

[edit routing-instances Customer_Router_1 routing-options]
jcluser@vMX-addr-0# set generate route 172.16.100.0/26  

Now, you might find this interesting, when we try to configure our new policy.

[edit policy-options policy-statement generated]
jcluser@vMX-addr-0# set term 1 from protocol g? 
No valid completions 

We find that there is no option for protocol generated. We need to still to do:

from protocol aggregate.

In fact, we can just reapply the exact same policy we were using before:

[edit policy-options policy-statement aggregate]
jcluser@vMX-addr-0# show| display set relative 
set term 1 from protocol aggregate
set term 1 then accept
set term 2 then reject
 
[edit routing-instances Customer_Router_1 protocols bgp group EBGP]
jcluser@vMX-addr-0# set export aggregate 
 
[edit routing-instances Customer_Router_1 protocols bgp group EBGP]
jcluser@vMX-addr-0# commit 
commit complete 

We check what we are now advertising to the ISP router, and find that only the summary is being advertised as we wanted:

jcluser@vMX-addr-0> show route advertising-protocol bgp 172.16.2.2                             
Customer_Router_1.inet.0: 9 destinations, 9 routes (9 active, 0 holddown, 0 hidden)
  Prefix  Nexthop       MED     Lclpref    AS path
* 172.16.100.0/26         Self                                    I 

So, the policy is exactly the same but instead of doing set routing-options aggregate we did set routing-options generated.  What is the difference?

Let’s take a look at the route. But first, just for comparison, let me create an aggregate route also.

[edit routing-instances Customer_Router_1 routing-options]
jcluser@vMX-addr-0# set aggregate route 172.16.100.64/26 discard 
  
[edit interfaces lo0 unit 0]
jcluser@vMX-addr-0# set family inet address 172.16.100.65/28
 
[edit routing-instances Customer_Router_1 routing-options]
jcluser@vMX-addr-0# commit 
commit complete 

Here are our two routes so that we can compare them:

GENERATED:
jcluser@vMX-addr-0> show route 172.16.100/26 exact table Customer_Router_1      
Customer_Router_1.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Aggregate/130] 00:00:25, metric2 0
                     > to 172.16.1.1 via lt-0/0/0.2
AGGREGATE:
jcluser@vMX-addr-0> show route 172.16.100.64/26 exact table Customer_Router_1
Customer_Router_1.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.64/26   *[Aggregate/130] 00:00:27
                       Discard 

I  hope the difference is now easy to spot: the generated route has an actual next-hop (172.16.1.1) and a metric, while the aggregate is pointing to the trash can (discard).

Besides that, there is really not much difference. They both have the same preference value (130) and they both are referred to as “Aggregate” routes.

In fact, you can enter: show route protocols aggregate, and obtain information about the two routes:

jcluser@vMX-addr-0> show route protocol aggregate table Customer_Router_1.inet.0   
Customer_Router_1.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
+ = Active Route, - = Last Active, * = Both
172.16.100.0/26    *[Aggregate/130] 00:05:50, metric2 0
                    > to 172.16.1.1 via lt-0/0/0.2
172.16.100.64/26   *[Aggregate/130] 00:05:50
                      Discard 

Let’s check more details:

 jcluser@vMX-addr-0> show route protocol aggregate table Customer_Router_1.inet.0 
 Customer_Router_1.inet.0: 11 destinations, 11 routes (11 active, 0 holddown, 0 hidden)
 172.16.100.0/26 (1 entry, 1 announced)
 TSI:
 KRT in-kernel 172.16.100.0/26 -> {indirect(1048574)}
 Page 0 idx 0, (group EBGP type External) Type 1 val 0xba0c7bc (adv_entry)
    Advertised metrics:
      Nexthop: Self
      AS path: [100] I
      Communities:
 Path 172.16.100.0 Vector len 4.  Val: 0
         *Aggregate Preference: 130
                 Next hop type: Indirect, Next hop index: 0
                 Address: 0xce31f90
                 Next-hop reference count: 12
                 Next hop type: Router, Next hop index: 665
                 Next hop: 172.16.1.1 via lt-0/0/0.2, selected   <= REAL NEXT HOP
                 Session Id: 0x140
               Protocol next hop: 172.16.1.1
                 Indirect next hop: 0xba3d900 1048574 INH Session ID: 0x141
                 State: <Active Int Ext>
                 Local AS:   100 
                 Age: 6:56 Metric2: 0 
                 Validation State: unverified 
                 Task: Aggregate
                 Announcement bits (3): 0-KRT 2-BGP_RT_Background 3-Resolve tree 1 
                 AS path: I 
                        Flags: Generate ResolveDepth: 0Active
               Contributing Routes (4):
               172.16.100.0/28 proto BGP
               172.16.100.16/28 proto BGP
               172.16.100.32/28 proto BGP
               172.16.100.48/28 proto BGP
                 Indirect next hops: 1
                         Protocol next hop: 172.16.1.1
                         Indirect next hop: 0xba3d900 1048574 INH Session ID: 0x141
                         Indirect path forwarding next hops: 1
                             Next hop type: Router
                             Next hop: 172.16.1.1 via lt-0/0/0.2
                            Session Id: 0x140
                                 172.16.1.0/24 Originating RIB: Customer_Router_1.inet.0
                                 Node path count: 1
                                 Forwarding nexthops: 1
   Next hop type: Interface
   Nexthop: via lt-0/0/0.2
  
 172.16.100.64/26 (1 entry, 1 announced)
 TSI:
 KRT in-kernel 172.16.100.64/26 -> {}
 Page 0 idx 0, (group EBGP type External) Type 1 val 0xba0c650 (adv_entry)
    Advertised metrics:
      Nexthop: Self
      AS path: [100] I (LocalAgg)
      Communities:
 Path 172.16.100.64 Vector len 4.  Val: 0
         *Aggregate Preference: 130
                 Next hop type: Discard, Next hop index: 0    <= TRASH CAN AS NEXT HOP
                 Address: 0xce30670
                 Next-hop reference count: 2
                 State: <Active Int Ext>
                 Local AS:   100 
                 Age: 6:56 
                 Validation State: unverified 
                 Task: Aggregate
                 Announcement bits (3): 0-KRT 2-BGP_RT_Background 3-Resolve tree 1 
                 AS path: I  (LocalAgg)
                                 Flags: DiscardDepth: 0Active
                 AS path list:
                 AS path: I Refcount: 1
               Contributing Routes (1):
               172.16.100.64/28 proto BGP 

In this example is it not easy to tell which route was used to select the next-hop, so let me use some little tricks to show you the behavior:

 [edit policy-options policy-statement loopback]
 jcluser@vMX-addr-0# show| display set relative 
 set term 1 from route-filter 172.16.100.0/28 exact
 set term 1 then next-hop 172.16.1.11
 set term 1 then accept
 set term 2 from route-filter 172.16.100.16/28 exact
 set term 2 then next-hop 172.16.1.12
 set term 2 then accept
 set term 4 from route-filter 172.16.100.32/28 exact
 set term 4 then next-hop 172.16.1.14
 set term 4 then accept
 set term 3 from route-filter 172.16.100.48/28 exact
 set term 3 then next-hop 172.16.1.13
 set term 3 then accept
  
 [edit routing-instances Customer_Router_1 protocols bgp group IBGP]
 jcluser@vMX-addr-0# set accept-remote-nexthop
  
 [edit policy-options policy-statement loopback]
 jcluser@vMX-addr-0# commit 
 commit complete
  
 jcluser@vMX-addr-0> show route receive-protocol bgp 172.16.1.1 table Customer_Router_1.inet.0 
 Customer_Router_1.inet.0: 10 destinations, 10 routes (9 active, 0 holddown, 1 hidden)
   Prefix  Nexthop       MED     Lclpref    AS path
 * 172.16.100.0/28         172.16.1.11                  100        I
 * 172.16.100.16/28        172.16.1.12                  100        I
 * 172.16.100.32/28        172.16.1.14                  100        I
 * 172.16.100.48/28        172.16.1.13                  100        I 

The routes now have different next-hops, and when we can check the aggregate route again, and compare the contributing routes to figure out which one was selected as the primary route and why:

jcluser@vMX-addr-0> show route 172.16.100.0/26 exact extensive table Customer_Router_1.inet.0 | match "next hop"   
                 Next hop type: Indirect, Next hop index: 0
                 Next hop type: Router, Next hop index: 672
                 Next hop: 172.16.1.11 via lt-0/0/0.2, selected
                 Protocol next hop: 172.16.1.11
                 Indirect next hop: 0xba3f700 1048577 INH Session ID: 0x14e
                 Indirect next hops: 1
                         Protocol next hop: 172.16.1.11
                         Indirect next hop: 0xba3f700 1048577 INH Session ID: 0x14e
                         Indirect path forwarding next hops: 1
                                 Next hop type: Router
                                 Next hop: 172.16.1.11 via lt-0/0/0.2
                                 Next hop type: Interface 

I can change the next-hop of the first route, and the next-hop of the aggregate also changes:

 [edit policy-options policy-statement loopback term 1]
 jcluser@vMX-addr-0# set then next-hop 172.16.1.111 
  
 [edit policy-options policy-statement loopback term 1]
 jcluser@vMX-addr-0# commit 
 commit complete

 jcluser@vMX-addr-0> show route 172.16.100.0/26 exact extensive table Customer_Router_1.inet.0 |  
 match "next hop"  
                 Next hop type: Indirect, Next hop index: 0
                 Next hop type: Router, Next hop index: 673
                 Next hop: 172.16.1.111 via lt-0/0/0.2, selected
                 Protocol next hop: 172.16.1.111
                 Indirect next hop: 0xba3f400 1048578 INH Session ID: 0x14c
                 Indirect next hops: 1
                         Protocol next hop: 172.16.1.111
                         Indirect next hop: 0xba3f400 1048578 INH Session ID: 0x14c
                         Indirect path forwarding next hops: 1
                                 Next hop type: Router
                                 Next hop: 172.16.1.111 via lt-0/0/0.2
                                 Next hop type: Interface 

So, the primary contributing route in this case, is the route with the lowest value.

You can change this using a policy that changes which routes are contributing routes as we did before, or you can play with the metric, or preference value, to make one route preferred over another. The router takes into account the metric, preference value, and subnet mask length of the routes to choose which contributing route is the primary.  

I am attaching a document that shows you some examples changing metric, preference and subnet mask length.

IN SUMMARY

That was a long article, which you were probably not expecting, so here is a quick summary of the things that we covered, that I hope you find helpful:

P.S. Though I try to make the examples similar to real cases, keep in mind that the intention of the examples is to demonstrate how the different types of manual routes, and their options work, not to show you how to necessarily do things in the real world, though I have found some of the tricks I showed you useful to solve or troubleshot some of my customers issues. 😉

Related posts