BGP Conditional Advertisements

One of the seemingly complicated things to do in BGP is conditional advertisements. This can be used to apply policy to routes and only advertise specific routes when you (don’t) have another route. For example, you only advertise a default route when you have specific routes from a peer.

Another example is when you’re connected to two ISPs, but you prefer data to traverse just one of the two links. Maybe because one link is more expensive than the other or less reliable. Maybe you just like one more than the other. Whatever the reason, you want to perform traffic manipulation. Of course you could do something like as-path prepending, but you have no way to ensure this will be honored on the other side. They might have bgp bestpath as-path ignore enabled. The best way to force traffic to use a specific path is to have this path as the only path. However, just supressing the route isn’t smart in case of a failure somewhere. You could just advertise a summary to the other ISP (which would be an easier solution), but you need more granularity for some reason. In that case you can use Conditional Advertisements.

My example here is a simple topology of four routers in a diamond shape using very basic configuration.

BGP conditional advertisements topology

R1:

Interface              IP-Address    OK? Method Status                Protocol
GigabitEthernet0/0     unassigned    YES unset  administratively down down    
GigabitEthernet0/1     unassigned    YES unset  up                    up      
GigabitEthernet0/1.12  192.168.12.1  YES manual up                    up      
GigabitEthernet0/1.13  192.168.13.1  YES manual up                    up      
Loopback1              1.1.1.1       YES manual up                    up      
Loopback11             11.11.11.1    YES manual up                    up      
Loopback111            111.111.111.1 YES manual up                    up 

router bgp 100
 bgp log-neighbor-changes
 network 1.1.1.1 mask 255.255.255.255
 network 11.11.11.1 mask 255.255.255.255
 network 111.111.111.1 mask 255.255.255.255
 neighbor 192.168.12.2 remote-as 200
 neighbor 192.168.13.3 remote-as 300
R2:

Interface              IP-Address    OK? Method Status                Protocol
GigabitEthernet0/0     unassigned    YES unset  administratively down down    
GigabitEthernet0/1     unassigned    YES unset  up                    up      
GigabitEthernet0/1.12  192.168.12.2  YES manual up                    up         
GigabitEthernet0/1.24  192.168.24.2  YES manual up                    up      

router bgp 200
 bgp log-neighbor-changes
 neighbor 192.168.12.1 remote-as 100
 neighbor 192.168.24.4 remote-as 400
R3:

Interface              IP-Address    OK? Method Status                Protocol
GigabitEthernet0/0     unassigned    YES unset  administratively down down    
GigabitEthernet0/1     unassigned    YES unset  up                    up      
GigabitEthernet0/1.13  192.168.13.3  YES manual up                    up           
GigabitEthernet0/1.34  192.168.34.3  YES manual up                    up 

router bgp 300
 bgp log-neighbor-changes
 neighbor 192.168.13.1 remote-as 100
 neighbor 192.168.34.4 remote-as 400
R4:

Interface              IP-Address    OK? Method Status                Protocol
GigabitEthernet0/0     unassigned    YES unset  administratively down down    
GigabitEthernet0/1     unassigned    YES unset  up                    up      
GigabitEthernet0/1.24  192.168.24.4  YES manual up                    up      
GigabitEthernet0/1.34  192.168.34.4  YES manual up                    up      
Loopback1              4.4.4.4       YES manual up                    up    

router bgp 400
 bgp log-neighbor-changes
 network 4.4.4.4 mask 255.255.255.255
 neighbor 192.168.24.2 remote-as 200
 neighbor 192.168.34.3 remote-as 300

So as a verification we perform a trace from R4 to each loopback address of R1

R4#trace 1.1.1.1 so lo1
Type escape sequence to abort.
Tracing the route to 1.1.1.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.24.2 2 msec 2 msec 4 msec
  2 192.168.12.1 4 msec *  2 msec

R4#trace 11.11.11.1 so lo1
Type escape sequence to abort.
Tracing the route to 11.11.11.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.24.2 2 msec 2 msec 1 msec
  2 192.168.12.1 2 msec *  2 msec

R4#trace 111.111.111.1 so lo1
Type escape sequence to abort.
Tracing the route to 111.111.111.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.24.2 3 msec 3 msec 1 msec
  2 192.168.12.1 2 msec *  2 msec

So, for all routes the path via R2 is chosen. Now I need to influence incoming traffic. My business case states that traffic towards 1.1.1.1 and 111.111.111.1 should use R3, but 11.11.11.1 should enter through R2. This makes using summaries more difficult (not impossible, but I might not have control over 1.1.1.2 so it could be dangerous in real life). However, when the link to either router goes down all traffic should fail over to the other path.

This is where Conditional Advertisements come in. As long as both links exist I advertise 11.11.11.1 to R2 and 1.1.1.1 and 111.111.111.1 to R3.

The command we need to use for this is the neighbor x advertise-map command. The additional configuration on R1 looks like this:

ip prefix-list PL_R2_ADV_MAP permit 1.1.1.1/32
ip prefix-list PL_R2_ADV_MAP permit 111.111.111.1/32
!
ip prefix-list PL_R3_ADV_MAP permit 11.11.11.1/32
!
access-list 12 permit 192.168.12.0 0.0.0.255
access-list 13 permit 192.168.13.0 0.0.0.255
!
route-map R2_ADV_MAP permit 10
 match ip add prefix-list PL_R2_ADV_MAP
!
route-map R3_ADV_MAP permit 10
 match ip add prefix-list PL_R3_ADV_MAP
!
route-map R2_NON_EXIST permit 10
 match ip add 12
!
route-map R3_NON_EXIST permit 10
 match ip add 13
!
router bgp 100
net 192.168.12.0 m 255.255.255.0
net 192.168.13.0 m 255.255.255.0
neighbor 192.168.12.2 advertise-map R2_ADV_MAP non-exist-map R3_NON_EXIST
neighbor 192.168.13.3 advertise-map R3_ADV_MAP non-exist-map R2_NON_EXIST

This configuration is fairly simple. The basis is the neighbor 192.168.12.2 advertise-map R2_ADV_MAP non-exist-map R3_NON_EXIST line. This line defines which routes to advertise (R2_ADV_MAP) and when to do so. In this case when the routes defined in R3_NON_EXIST do not exist. So the effect of this configuration in regard to R2 is that 1.1.1.1 /32 and 111.111.111.1 /32 won’t be advertised to R2 as long as the route to R3 exists.

A key point here is that the non-exist-map and the exist-map look at the BGP table, not the RIB. That’s why the networks 192.168.12.0 and 192.168.13.0 are added to BGP.

Before we applied this configuration to R1 the BGP tables on R2 and R3 looked as follows:

R2:

     Network          Next Hop       Metric LocPrf Weight Path
 *>   1.1.1.1/32       192.168.12.1        0             0 100 i
 *    4.4.4.4/32       192.168.12.1                      0 100 300 400 i
 *>                    192.168.24.4        0             0 400 i
 *>   11.11.11.1/32    192.168.12.1        0             0 100 i
 *>   111.111.111.1/32 192.168.12.1        0             0 100 i

R3:

     Network          Next Hop       Metric LocPrf Weight Path
 *    1.1.1.1/32       192.168.34.4                      0 400 200 100 i
 *>                    192.168.13.1        0             0 100 i
 *>   4.4.4.4/32       192.168.34.4        0             0 400 i
 *    11.11.11.1/32    192.168.34.4                      0 400 200 100 i
 *>                    192.168.13.1        0             0 100 i
 *    111.111.111.1/32 192.168.34.4                      0 400 200 100 i
 *>                    192.168.13.1        0             0 100 i

After the change it looks as follows:

R2:

     Network          Next Hop       Metric LocPrf Weight Path
 *>   1.1.1.1/32       192.168.24.4                      0 400 300 100 i
 *    4.4.4.4/32       192.168.12.1                      0 100 300 400 i
 *>                    192.168.24.4        0             0 400 i
 *>   11.11.11.1/32    192.168.12.1        0             0 100 i
 *>   111.111.111.1/32 192.168.24.4                      0 400 300 100 i
 r>   192.168.12.0     192.168.12.1        0             0 100 i
 *>   192.168.13.0     192.168.12.1        0             0 100 i

R3:


     Network          Next Hop       Metric LocPrf Weight Path
 *>   1.1.1.1/32       192.168.13.1        0             0 100 i
 *>   4.4.4.4/32       192.168.34.4        0             0 400 i
 *>   11.11.11.1/32    192.168.34.4                      0 400 200 100 i
 *>   111.111.111.1/32 192.168.13.1        0             0 100 i
 *    192.168.12.0     192.168.34.4                      0 400 200 100 i
 *>                    192.168.13.1        0             0 100 i
 r    192.168.13.0     192.168.34.4                      0 400 200 100 i
 r>                    192.168.13.1        0             0 100 i

The traceroutes reflect this behavior:

R4#trace 1.1.1.1 so lo1      
Type escape sequence to abort.
Tracing the route to 1.1.1.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.34.3 2 msec 4 msec 1 msec
  2 192.168.13.1 [AS 100] 1 msec *  5 msec

R4#trace 11.11.11.1 so lo1   
Type escape sequence to abort.
Tracing the route to 11.11.11.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.24.2 2 msec 3 msec 6 msec
  2 192.168.12.1 [AS 100] 3 msec *  3 msec

R4#trace 111.111.111.1 so lo1
Type escape sequence to abort.
Tracing the route to 111.111.111.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.34.3 3 msec 2 msec 2 msec
  2 192.168.13.1 [AS 100] 2 msec *  2 msec

So that’s great right? If the link to R3 goes down everything will be routed via R2. So let’s test that case:

R1(config)#int g 0/1.13
R1(config-subif)#sh
R1(config-subif)#
R1(config-subif)#do sh ip bgp

     Network          Next Hop       Metric LocPrf Weight Path
 *>   1.1.1.1/32       0.0.0.0             0         32768 i
 *>   4.4.4.4/32       192.168.12.2                      0 200 400 i
 *>   11.11.11.1/32    0.0.0.0             0         32768 i
 *>   111.111.111.1/32 0.0.0.0             0         32768 i
 *>   192.168.12.0     0.0.0.0             0         32768 i

We can see that 192.168.13.0 has been removed from the BGP table. This should mean that R2 now has the BGP routes to 1.1.1.1 /32 and 111.111.111.1 /32 pointing directly to R1.

R2:

     Network          Next Hop       Metric LocPrf Weight Path
 *>   1.1.1.1/32       192.168.12.1        0             0 100 i
 *                     192.168.24.4                      0 400 300 100 i
 *>   4.4.4.4/32       192.168.24.4        0             0 400 i
 *>   11.11.11.1/32    192.168.12.1        0             0 100 i
 *>   111.111.111.1/32 192.168.12.1        0             0 100 i
 *                     192.168.24.4                      0 400 300 100 i
 r>   192.168.12.0     192.168.12.1        0             0 100 i
 *>   192.168.13.0     192.168.24.4                      0 400 300 100 i

Which is the case. The old BGP route however is still there. That’s because BGP is a slow protocol and R3 hasn’t removed the routes yet because it doesn’t know the neighbor is down for a long time. But after a few minutes R4 will use R2 as route to the destinations for which it used to use R3:

R4#trace 111.111.111.1 so lo1
Type escape sequence to abort.
Tracing the route to 111.111.111.1
VRF info: (vrf in name/id, vrf out name/id)
  1 192.168.24.2 3 msec 3 msec 5 msec
  2 192.168.12.1 [AS 100] 3 msec *  2 msec
R4#

Keep in mind that BGP is a slow protocol and failover using this mechanism isn’t subsecond or even subminute. Especially when this information has to propagate the internet it can take a while. The other thing to keep in mind is that this solution only works when the link actually goes down and the route that is tracked is removed from the BGP table. In a soft failure scenario in which you can’t reach the neighbor, but the link stays up this doesn’t work. To work around that you can use an IP SLA using a tracked object on a dummy static route and redistribute that dummy route into BGP. Once the IP SLA goes down the tracked static will disappear from the routing table and therefor from the BGP table. This is a more reliable way of doing this.