[j-nsp] BGP Communities

Richard A Steenbergen ras at e-gerbil.net
Wed May 5 11:14:25 EDT 2010


On Wed, May 05, 2010 at 10:05:42AM -0400, Paul Stewart wrote:
>     community inbound-xxxx members [ 11666:2000 11666:2002 ];
>     community outbound-xxxx members [ 11666:4000 11666:5000 ];

Defining multiple members like this is how you implement a logical AND,
so both members will be required if you use this to match. You can test
your community definitions by doing "show route community-name
outbound-xxxx". If you wanted to do a logical OR, you would do:

community customer members 11666:4000;
community internal members 11666:5000;

policy-statement whatever {
    term whatever {
        from community [ customer internal ];
        then whatever;
    }
}

For some ideas on how to implement a complex commnuity system, along 
with some JUNOS examples (though the really fun ones involve commit 
scripts :P), take a look at:

http://www.nanog.org/meetings/nanog40/presentations/BGPcommunities.pdf

> In the Cisco world, we had to define network statements of our own subnets
> and route those blocks to Null0 in order to advertise. I'm thinking
> something similar here in JunOS?

This is one of the biggest gotchas for people who are new to JUNOS, 
there is no concept of a redistribute or network statement. In a Cisco 
model, you "add routes to bgp" with a network or redistribute statement, 
and then the routes are advertised to neighbors just like any other 
route already in BGP. In JUNOS, you have to make your export policy do 
the announcement from whatever other protocol you are coming from 
(static hold-down route, or whatever), to every neighbor. This method is 
far more powerful, and doesn't present a big issue when you combine it 
with the functionality of policy chains or subroutines, but it does 
force even simple BGP users to start writing relatively complex policy 
statements just to get the most basic of functionality. It definitely 
isn't my favorite Juniperism, just because of the needless grief it 
creates for newbies.

My personal favorite way to do this kind of thing is with a prefix-list, 
and a policy-statement referencing that prefix-list, to apply all the 
types of behaviors you need. For example, my policies look something 
like this:

    policy-statement TRANSIT-OUT {
        term EXPORT {
            from policy ( ! INTERNAL-BGP-EXPORT-CUSTS );
            then reject;
        }
        term FILTER-BORDER {
            from policy ( ! INTERNAL-BORDER-OUT );
            then reject;
        }
        term PARSE-COMMUNITIES {
            from policy ( ! AUTO-COMMUNITY-TRANSIT-OUT );
            then reject;
        }
        term REGIONAL {
            from community TAG_MORE_SPECIFIC;
            then {
                community add NO_EXPORT;
            }
        }
        then {
            next-hop self;
        }
    }

And then my EXPORT-CUSTS policy (which is the same subroutine used for 
peer policies, basically "advertise all my internal and customer 
routes") is:

    policy-statement INTERNAL-BGP-EXPORT-CUSTS {
        /* Export Customers and Internal routes only */
        term ORIGINATE {
            from policy INTERNAL-BGP-ORIGINATE;
            then accept;
        }
        term EXPORT {
            from {
                protocol bgp;
                community [ MATCH_CUSTOMER MATCH_INTERNAL ];
            }
            then accept;
        }
        then reject;
    }

Which then further uses a common subroutine to handle BGP origination, 
which is what you're after:

    policy-statement INTERNAL-BGP-ORIGINATE {
        term ORIGINATE-IPV6 {
            from {
                protocol [ direct static ospf isis ];
                rib inet6.0;
                family inet6;
                prefix-list BGP-ORIGINATE-IPV6;
            }
            then {
                metric 0;
                local-preference 400;
                community add TAG_INTERNAL;
                default-action accept;
                accept;
            }
        }
        term ORIGINATE-AGGREGATE {
            from {
                protocol [ direct static ospf isis ];
                prefix-list BGP-ORIGINATE-AGGREGATE;
            }
            then {
                metric 0;
                local-preference 400;
                community add TAG_INTERNAL;
                default-action accept;
                accept;
            }
        }
        term ORIGINATE-REGIONAL {
            from {
                protocol [ direct static ospf isis ];
                prefix-list BGP-ORIGINATE-REGIONAL;
            }
            then {
                metric 0;
                local-preference 400;
                community add TAG_INTERNAL;
                community add TAG_MORE_SPECIFIC;
                default-action accept;
                accept;
            }
        }
        term ORIGINATE-CUSTOMER {
            from {
                protocol [ direct static ospf isis ];
                prefix-list BGP-ORIGINATE-CUSTOMER;
            }
            then {
                metric 0;
                local-preference 300;
                community add TAG_CUSTOMER;
                default-action accept;
                accept;
            }
        }
        then reject;
    }

As you can see, it's easy to put together some common subroutines which 
get reuse in multiple policies, letting you make very specific 
modifications as needed without ending up in a giant IOS route-map mess. 
In the example above, if you wanted to originate a route for a customer 
locally you would define the static hold-down (or whatever you would 
normally do :P), and then add that prefix to the prefix-list 
BGP-ORIGINATE-CUSTOMER. Then that route would be properly tagged and 
exported on every neighbor, using the common origination subroutines. :)

Another option is to define the communities you want under the static 
route definition, for example:

static {
    route 1.2.3.4 {
        discard;
        community 11666:4000;
    }
}

But this carries several liabilities. For starters, you would have no 
way to "redistribute" from other routing protocols, or even from a 
directly connected interface (consider what happens if you have a 
customer /24 applied to an interface and then want to announce it). It 
also limits your potential automation, since you can't use a named 
community when setting a static route.

-- 
Richard A Steenbergen <ras at e-gerbil.net>       http://www.e-gerbil.net/ras
GPG Key ID: 0xF8B12CBC (7535 7F59 8204 ED1F CC1C 53AF 4C41 5ECA F8B1 2CBC)


More information about the juniper-nsp mailing list