Wednesday, November 14, 2012

The many maps of BGP

Every time I sit down with BGP for a prolonged period, I get quickly overwhelmed by the quantity of different types of "maps" that can be applied to various parts of the configuration.

I tried to count them this morning, and I came up with:
Suppress-Map
Unsuppress-Map
Inject-Map
Advertise-Map
Attribute-Map
Exist-Map
Non-exist-map
and of course traditional route-maps, which make for a total of 8.

When I sit down to fine-tune summarization, or do a conditional advertisement, I can never remember the term for the map I'm looking for.  So let's do a thorough run-down of what they all do.




 I have the usual IPs setup here.  Segment IPs are 192.168.XY.X, where X is the router number.  Each router has an Lo0 of X.X.X.X.
 
suppress-map
A suppress-map is a route map that's used for doing partial suppression of component routes of an aggregate.  The default, when aggregating with BGP, is to advertise both the aggregate and all the component routes.  If you want to advertise just the aggregate, you use the summary-only keyword at the end of the aggregate.  But if you want to suppress some, but not all, of the component routes, you use a suppress-map.
 
The syntax is:
aggregate-address <aggregate address> <subnet mask> suppress-map <route-map-name>
 
In our sample, we're going to add an Lo1 to R4:
 
int Lo1
  ip address 3.3.4.3 255.255.255.255
 
and advertise it into BGP.  All networks and all Lo0's are already advertised into BGP.
Combined with Lo0 from R3 (3.3.3.3), we now have some addresses we can aggregate.
 
Without any filtering, the command to summarize to a /16 is:
R3:
 router bgp 300
 aggregate-address 3.3.0.0 255.255.0.0
 
And on R2, we can see the outcome:
R2#sh ip bgp | i 3.3
*> 3.3.0.0/16       192.168.12.1                           0 100 300 i
*> 3.3.3.3/32       192.168.12.1                           0 100 300 i
*> 3.3.4.3/32       192.168.12.1                           0 100 300 I

We have the aggregate, plus the two component routes.
 
Now, let's modify R3 to restrict 3.3.3.3/32 from being advertised.
 
R3:
ip prefix-list one_loopback seq 5 permit 3.3.3.3/32
route-map suppress_one_loopback permit 10
 match ip address prefix-list one_loopback
router bgp 300
 aggregate-address 3.3.0.0 255.255.0.0 suppress-map suppress_one_loopback

and the results on R2:
 
R2#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.0.0/16       192.168.23.3             0             0 300 i
*                   192.168.12.1                           0 100 300 i
*> 3.3.4.3/32       192.168.23.3                           0 300 i
*                   192.168.12.1                           0 100 300 I

One aggregate, one component, but not the filtered component.
 
unsuppress-map
You probably already guessed that this accomplished the opposite of a suppress-map.  Let's say you have complete suppression via summary-only, or you globally suppressed a prefix with a suppress-map.  Let's say you have 20 eBGP neighbors, but want to leak that specific suppressed prefix to only one of them. 
 
Let's reintroduce one of those filtered routes from the suppress-map task above selectively back to R1.  Technically I could even re-use the same route-map I did for the suppression, but for clarity I made a new, identical one with a better name.
 
R3:
route-map unsuppress_one_loopback permit 10
 match ip address prefix-list one_loopback
router bgp 300
 neighbor 192.168.13.1 unsuppress-map unsuppress_one_loopback
and the outcome:
 
R2#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.0.0/16       192.168.23.3             0             0 300 i
*                   192.168.12.1                           0 100 300 i
*> 3.3.3.3/32       192.168.12.1                           0 100 300 i
*> 3.3.4.3/32       192.168.23.3                           0 300 i
*                   192.168.12.1                           0 100 300 i
Now we get 3.3.3.3/32 on R2, but only via R1.  Note the AS-PATH, 100 -> 300 is our only option.
 
inject-map
Inject maps "de-aggregate" routes based on the presence of a specific aggregate.  These are used by routers downstream from the aggregator to re-introduce prefixes.
 
We'll also see an introduction to the "exist-map" here.  The exist-map determines if the aggregate is present.
 
First, let's remove the suppress & unsuppress maps on R3, and go back to just a summary-only aggregate:
 
R3:
router bgp 300
  no aggregate-address 3.3.0.0 255.255.0.0 suppress-map suppress_one_loopback
  no neighbor 192.168.13.1 unsuppress-map suppress_one_loopback
  aggregate-address 3.3.0.0 255.255.0.0 summary-only

Now we'll create an inject map on R1, to re-advertise 3.3.3.3/32 and 3.3.4.3/32 to R2.  Out of curiosity, let's make it originate something that doesn't actually exist (3.3.5.3/32).
 
R1:
ip prefix-list r3_aggregate seq 5 permit 3.3.0.0/16
ip prefix-list route-source seq 5 permit 192.168.12.2/32

ip prefix-list r3_component seq 5 permit 3.3.3.3/32
ip prefix-list r3_component seq 10 permit 3.3.4.3/32
ip prefix-list r3_component seq 15 permit 3.3.5.3/32

router bgp 100
 bgp inject-map r3_inject exist-map r3_aggregate_exist

There's a few different pieces here.  The exist-map must match both the route source (must be a /32) and the aggregate (must match the BGP table exactly).  So, in our case, if 3.3.0.0/16 comes from 192.168.12.2, introduce 3.3.3.3/32, 3.3.4.3/32. and 3.3.5.3/32.
 
Let's check these on R1 first.
 
R1#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.0.0/16       192.168.13.3             0             0 300 i
*                   192.168.12.2                           0 200 300 i
*> 3.3.3.3/32       192.168.12.2                           0 ?
*> 3.3.4.3/32       192.168.12.2                           0 ?
*> 3.3.5.3/32       192.168.12.2                           0 ?

Cool, they're present.
 
We can also check them with this command: show ip bgp injected-paths
 
R1#show ip bgp injected-paths
BGP table version is 16, local router ID is 1.1.1.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
              r RIB-failure, S Stale
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.3.3/32       192.168.12.2                           0 ?
*> 3.3.4.3/32       192.168.12.2                           0 ?
*> 3.3.5.3/32       192.168.12.2                           0 ?

Now let's take a peek at R2.
 
R2#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*  3.3.0.0/16       192.168.12.1                           0 100 300 i
*>                  192.168.23.3             0             0 300 i
*> 3.3.3.3/32       192.168.12.1                           0 100 ?
*> 3.3.4.3/32       192.168.12.1                           0 100 ?
*> 3.3.5.3/32       192.168.12.1                           0 100 ?

It learned them too, although the AS-PATH ends at R1.  That makes me wonder - is R3 also getting these?
 
R3#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.0.0/16       0.0.0.0                            32768 i
s  3.3.3.3/32       192.168.23.2                           0 200 100 ?
s                   192.168.13.1                           0 100 ?
s>                  0.0.0.0                  0         32768 i
s  3.3.4.3/32       192.168.23.2                           0 200 100 ?
s                   192.168.13.1                           0 100 ?
s>i                 192.168.34.4             0    100      0 i
s  3.3.5.3/32       192.168.23.2                           0 200 100 ?
s>                  192.168.13.1                           0 100 ?

Uh-oh.  While this doesn't actually cause a loop in our topology, we don't really want R3 to learn about its own routes.  What can we do to prevent this?
 
R1:
router bgp 100
  bgp inject-map r3_inject exist-map r3_aggregate_exist copy-attributes
 
You got it, we can copy the AS-PATH (etc) from the aggregate on to the component routes.  Problem solved:
 
R3#sh ip bgp 3.3.0.0 255.255.0.0 longer-prefix | b Network
   Network          Next Hop            Metric LocPrf Weight Path
*> 3.3.0.0/16       0.0.0.0                            32768 i
s> 3.3.3.3/32       0.0.0.0                  0         32768 i
s>i3.3.4.3/32       192.168.34.4             0    100      0 i
 
advertise-map (summarization)
Advertise-maps are used to determine which prefixes' attributes are inherited by the summary.  This can be useful, for example, if you're summarizing from two different ASes and only want one of the two to receive the summary.  That's exactly what we'll do in this example.
 
First, we'll remove some of the config from the last task:
R1:
router bgp 100
 no bgp inject-map r3_inject exist-map r3_aggregate_exist copy-attributes
 
R3:
router bgp 300
 no aggregate-address 3.3.0.0 255.255.0.0 summary-only

We'll add an Lo1 on R2, put 3.3.2.2/32 on it, and advertise it into BGP:

R2:
interface Loopback1
 ip address 3.3.2.2 255.255.255.255

router bgp 200
 network 3.3.2.2 mask 255.255.255.255
 
Now let's summarize 3.3.0.0/16 on R1, with the as-set parameter:
 
R1:
router bgp 100
 aggregate-address 3.3.0.0 255.255.0.0 as-set

We can see the outcome on R1:
 
R1(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
BGP routing table entry for 3.3.0.0/16, version 19
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1
  {200,300}, (aggregated by 100 1.1.1.1)
    0.0.0.0 from 0.0.0.0 (1.1.1.1)
      Origin IGP, localpref 100, weight 32768, valid, aggregated, local, best
 
And as you might expect, we don't see it on R2 or R3, because their ASes are in the AS-SET:
 
R2(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
% Network not in table
R3(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
% Network not in table

Let's work it out so that R2 can learn this summary.
 
R1:
ip prefix-list only_r3 seq 5 permit 3.3.3.3/32
route-map only_r3_advertise_map permit 10
 match ip address prefix-list only_r3
router bgp 100
 aggregate-address 3.3.0.0 255.255.0.0 as-set advertise-map only_r3_advertise_map

Now that the as-set should only be built from the attributes of 3.3.3.3/32, we should only see AS 300 in the AS-SET:
 
R1(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
BGP routing table entry for 3.3.0.0/16, version 20
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1
  300, (aggregated by 100 1.1.1.1)
    0.0.0.0 from 0.0.0.0 (1.1.1.1)
      Origin IGP, localpref 100, weight 32768, valid, aggregated, local, atomic-aggregate, best
 
Looking good...
 
R2(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
BGP routing table entry for 3.3.0.0/16, version 54
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1
  100 300, (aggregated by 100 1.1.1.1)
    192.168.12.1 from 192.168.12.1 (1.1.1.1)
      Origin IGP, metric 0, localpref 100, valid, external, atomic-aggregate, best
 
And R2 has the summary!
 
Just to verify on R3:
 
R3(config-router)#do sh ip bgp 3.3.0.0 255.255.0.0
% Network not in table
 
attribute-map
Attribute maps can be used to set arbitrary attributes to a summary.  As mentioned above, attributes are inherited from the prefixes they encompass.  However, if you want to set your own attributes, or even remove some inherited attributes, you can turn to the attribute-map.
 
Let's add a bunch of random attributes to the aggregate we created on R1.
 
R1:
route-map some_attributes permit 10
 set metric 500
 set local-preference 200
 set origin igp
 set community 100:1

router bgp 100
 aggregate-address 3.3.0.0 255.255.0.0 attribute-map some_attributes
 
Verification:
 
R1#sh ip bgp 3.3.0.0/16
BGP routing table entry for 3.3.0.0/16, version 27
Paths: (1 available, best #1, table Default-IP-Routing-Table)
  Advertised to update-groups:
        1
  Local, (aggregated by 100 1.1.1.1)
    0.0.0.0 from 0.0.0.0 (1.1.1.1)
      Origin IGP, metric 500, localpref 200, weight 32768, valid, aggregated, local, atomic-aggregate, best
      Community: 100:1
 
There's everything we set.  Not much more to be said there.
 
Advertise-map w/ exist-map & non-exist-map
This version of the advertise-map isn't related to summarization, but instead to conditional advertisement.  The exist or non-exist map is used in conjuction with the advertise-map, to match the existence, or lack thereof, of other prefixes, as the decision making process of the conditional advertisement.  Common uses might be "If I can reach a prefix specific to my upstream ISP, only then should I advertise a default", or "If I can't find a prefix from ISP1, I should originate one of my prefixes to my backup IGP."  We'll look at both here.
 
Let's say R3 & R4 represent an ISP, and R1 is an edge router for a large multi-AS enterprise.  R2 is part of the same enterprise.  I will be shutting down the link between R2 and R3 for this exercise.  If R1 can reach R3, I want it to advertise a default route to R2.
 
R2:
interface FastEthernet0/1
 shutdown
 
R3:
interface Loopback0
 shutdown
 
R1:
ip prefix-list default seq 5 permit 0.0.0.0/0
ip prefix-list r3loopback seq 5 permit 3.3.3.3/32
 
route-map advertise_default permit 10
 match ip address prefix-list default
route-map r3-exist-map permit 10
 match ip address prefix-list r3loopback
 
ip route 0.0.0.0 0.0.0.0 192.168.13.3

router bgp 100
 redistribute static
 neighbor 192.168.12.2 advertise-map advertise_default exist-map r3-exist-map
 default-information originate
 
So, if we see 3.3.3.3/32 in the BGP table, send 0.0.0.0/0 to R2.  We of course don't see 3.3.3.3/32 in the table, because I shut the interface down above.  Let's have a look at what our BGP tables look like first.
 
R1#sh ip bgp | i 0.0.0.0
*> 0.0.0.0          192.168.13.3             0         32768 ?
<output omitted>
 
We've got the default on R1, from redistribution.  What about R2?
 
R2(config-if)#do sh ip bgp | i 0.0.0.0
*> 2.2.2.2/32       0.0.0.0                  0         32768 i
*> 3.3.2.2/32       0.0.0.0                  0         32768 i
*> 192.168.12.0     0.0.0.0                  0         32768 I
 
No default on R2 yet.
 
Let's take R3's loopback0 out of shutdown:
 
R3:
interface Lo0
 no shutdown
 
After a little bit of prodding via clear ip bgp * soft, I end up with:
 
R2(config-if)#do sh ip bgp | i 0.0.0.0
*> 0.0.0.0          192.168.12.1             0             0 100 ?
*> 2.2.2.2/32       0.0.0.0                  0         32768 i
*> 3.3.2.2/32       0.0.0.0                  0         32768 i
*> 192.168.12.0     0.0.0.0                  0         32768 I
 
There's our default!
 
Now let's say that R1 is an enterprise router, and R2 and R3 are both ISPs.  R1 prefers R2's billing policy, and only wants to get ingress traffic from him towards R1's loopback0 if R3 is down.
 
R1:
ip prefix-list myloopback seq 5 permit 1.1.1.1/32
ip prefix-list r2loopback seq 5 permit 2.2.2.2/32
 
route-map r1loopback permit 10
 match ip address prefix-list myloopback
route-map r2-exist-map permit 10
 match ip address prefix-list r2loopback
 
router bgp 100
 no default-information originate ! Cleanup from last task
 no neighbor 192.168.12.2 advertise-map advertise_default exist-map r3-exist-map ! ditto
 neighbor 192.168.13.3 advertise-map r1loopback non-exist-map r2-exist-map
 
So, if R2's loopback does not exist in the BGP table, then advertise 1.1.1.1 to R3.
 
Since R2's loopback is very much in the BGP table, we see that 1.1.1.1/32 is not advertised to R3:
 
R3#sh ip bgp 1.1.1.1/32
% Network not in table

Let's shut down lo0 on R2:
interface Loopback0
 shutdown
 
And see what happens on R3:
 
R3#sh ip bgp 1.1.1.1/32
BGP routing table entry for 1.1.1.1/32, version 74
Paths: (1 available, best #1, table Default-IP-Routing-Table)
Flag: 0x820
  Advertised to update-groups:
        1    2
  100
    192.168.13.1 from 192.168.13.1 (1.1.1.1)
      Origin IGP, metric 0, localpref 100, valid, external, best
 
Enjoy!
 
Jeff Kronlage
 

2 comments:

  1. Good notes.
    The route-map config of the inject-map session is missing,it could be added to make it clearer to the reader.
    Thank you for your excellent effort.

    ReplyDelete