Skip to content

Commit 57d187b

Browse files
jobdonaldsharp
authored andcommitted
Support for BGP Large Communities
BGP Large Communities are a novel way to signal information between networks. An example of a Large Community is: "2914:65400:38016". Large BGP Communities are composed of three 4-byte integers, separated by a colon. This is easy to remember and accommodates advanced routing policies in relation to 4-Byte ASNs. This feature was developed by: Keyur Patel <keyur@arrcus.com> (Arrcus, Inc.), Job Snijders <job@ntt.net> (NTT Communications), David Lamparter <equinox@opensourcerouting.org> and Donald Sharp <sharpd@cumulusnetworks.com> Signed-off-by: Job Snijders <job@ntt.net> Signed-off-by: David Lamparter <equinox@opensourcerouting.org> Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
1 parent 45680e7 commit 57d187b

20 files changed

+2093
-23
lines changed

bgpd/Makefile.am

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ libbgp_a_SOURCES = \
7575
bgpd.c bgp_fsm.c bgp_aspath.c bgp_community.c bgp_attr.c \
7676
bgp_debug.c bgp_route.c bgp_zebra.c bgp_open.c bgp_routemap.c \
7777
bgp_packet.c bgp_network.c bgp_filter.c bgp_regex.c bgp_clist.c \
78-
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_mplsvpn.c bgp_nexthop.c \
78+
bgp_dump.c bgp_snmp.c bgp_ecommunity.c bgp_lcommunity.c \
79+
bgp_mplsvpn.c bgp_nexthop.c \
7980
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
8081
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
8182
bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC)
@@ -85,7 +86,8 @@ noinst_HEADERS = \
8586
bgp_aspath.h bgp_attr.h bgp_community.h bgp_debug.h bgp_fsm.h \
8687
bgp_network.h bgp_open.h bgp_packet.h bgp_regex.h bgp_route.h \
8788
bgpd.h bgp_filter.h bgp_clist.h bgp_dump.h bgp_zebra.h \
88-
bgp_ecommunity.h bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
89+
bgp_ecommunity.h bgp_lcommunity.h \
90+
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
8991
bgp_advertise.h bgp_snmp.h bgp_vty.h bgp_mpath.h bgp_nht.h \
9092
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
9193
$(BGP_VNC_RFAPI_HD)

bgpd/bgp_attr.c

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
4242
#include "bgpd/bgp_debug.h"
4343
#include "bgpd/bgp_packet.h"
4444
#include "bgpd/bgp_ecommunity.h"
45+
#include "bgpd/bgp_lcommunity.h"
4546
#include "bgpd/bgp_updgrp.h"
4647
#include "bgpd/bgp_encap_types.h"
4748
#if ENABLE_BGP_VNC
@@ -76,6 +77,7 @@ static const struct message attr_str [] =
7677
#if ENABLE_BGP_VNC
7778
{ BGP_ATTR_VNC, "VNC" },
7879
#endif
80+
{ BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }
7981
};
8082
static const int attr_str_max = array_size(attr_str);
8183

@@ -670,6 +672,8 @@ attrhash_key_make (void *p)
670672

671673
if (extra)
672674
{
675+
if (extra->lcommunity)
676+
MIX(lcommunity_hash_make (extra->lcommunity));
673677
if (extra->ecommunity)
674678
MIX(ecommunity_hash_make (extra->ecommunity));
675679
if (extra->cluster)
@@ -718,6 +722,7 @@ attrhash_cmp (const void *p1, const void *p2)
718722
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
719723
&& IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in)
720724
&& ae1->ecommunity == ae2->ecommunity
725+
&& ae1->lcommunity == ae2->lcommunity
721726
&& ae1->cluster == ae2->cluster
722727
&& ae1->transit == ae2->transit
723728
&& (ae1->encap_tunneltype == ae2->encap_tunneltype)
@@ -836,6 +841,13 @@ bgp_attr_intern (struct attr *attr)
836841
attre->ecommunity->refcnt++;
837842

838843
}
844+
if (attre->lcommunity)
845+
{
846+
if (! attre->lcommunity->refcnt)
847+
attre->lcommunity = lcommunity_intern (attre->lcommunity);
848+
else
849+
attre->lcommunity->refcnt++;
850+
}
839851
if (attre->cluster)
840852
{
841853
if (! attre->cluster->refcnt)
@@ -1026,6 +1038,10 @@ bgp_attr_unintern_sub (struct attr *attr)
10261038
if (attr->extra->ecommunity)
10271039
ecommunity_unintern (&attr->extra->ecommunity);
10281040
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES));
1041+
1042+
if (attr->extra->lcommunity)
1043+
lcommunity_unintern (&attr->extra->lcommunity);
1044+
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES));
10291045

10301046
if (attr->extra->cluster)
10311047
cluster_unintern (attr->extra->cluster);
@@ -1096,6 +1112,8 @@ bgp_attr_flush (struct attr *attr)
10961112

10971113
if (attre->ecommunity && ! attre->ecommunity->refcnt)
10981114
ecommunity_free (&attre->ecommunity);
1115+
if (attre->lcommunity && ! attre->lcommunity->refcnt)
1116+
lcommunity_free (&attre->lcommunity);
10991117
if (attre->cluster && ! attre->cluster->refcnt)
11001118
{
11011119
cluster_free (attre->cluster);
@@ -1254,6 +1272,7 @@ const u_int8_t attr_flags_values [] = {
12541272
[BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
12551273
[BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
12561274
[BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
1275+
[BGP_ATTR_LARGE_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
12571276
};
12581277
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
12591278

@@ -2042,6 +2061,40 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
20422061
return BGP_ATTR_PARSE_PROCEED;
20432062
}
20442063

2064+
/* Large Community attribute. */
2065+
static bgp_attr_parse_ret_t
2066+
bgp_attr_large_community (struct bgp_attr_parser_args *args)
2067+
{
2068+
struct peer *const peer = args->peer;
2069+
struct attr *const attr = args->attr;
2070+
const bgp_size_t length = args->length;
2071+
2072+
/*
2073+
* Large community follows new attribute format.
2074+
*/
2075+
if (length == 0)
2076+
{
2077+
if (attr->extra)
2078+
attr->extra->lcommunity = NULL;
2079+
/* Empty extcomm doesn't seem to be invalid per se */
2080+
return BGP_ATTR_PARSE_PROCEED;
2081+
}
2082+
2083+
(bgp_attr_extra_get (attr))->lcommunity =
2084+
lcommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length);
2085+
/* XXX: fix ecommunity_parse to use stream API */
2086+
stream_forward_getp (peer->ibuf, length);
2087+
2088+
if (attr->extra && !attr->extra->lcommunity)
2089+
return bgp_attr_malformed (args,
2090+
BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
2091+
args->total);
2092+
2093+
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES);
2094+
2095+
return BGP_ATTR_PARSE_PROCEED;
2096+
}
2097+
20452098
/* Extended Community attribute. */
20462099
static bgp_attr_parse_ret_t
20472100
bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
@@ -2063,7 +2116,7 @@ bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
20632116
/* XXX: fix ecommunity_parse to use stream API */
20642117
stream_forward_getp (peer->ibuf, length);
20652118

2066-
if (!attr->extra->ecommunity)
2119+
if (attr->extra && !attr->extra->ecommunity)
20672120
return bgp_attr_malformed (args,
20682121
BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
20692122
args->total);
@@ -2477,6 +2530,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
24772530
case BGP_ATTR_COMMUNITIES:
24782531
ret = bgp_attr_community (&attr_args);
24792532
break;
2533+
case BGP_ATTR_LARGE_COMMUNITIES:
2534+
ret = bgp_attr_large_community (&attr_args);
2535+
break;
24802536
case BGP_ATTR_ORIGINATOR_ID:
24812537
ret = bgp_attr_originator_id (&attr_args);
24822538
break;
@@ -3101,6 +3157,28 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
31013157
stream_put (s, attr->community->val, attr->community->size * 4);
31023158
}
31033159

3160+
/*
3161+
* Large Community attribute.
3162+
*/
3163+
if (attr->extra &&
3164+
CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY)
3165+
&& (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES)))
3166+
{
3167+
if (attr->extra->lcommunity->size * 12 > 255)
3168+
{
3169+
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3170+
stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3171+
stream_putw (s, attr->extra->lcommunity->size * 12);
3172+
}
3173+
else
3174+
{
3175+
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3176+
stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3177+
stream_putc (s, attr->extra->lcommunity->size * 12);
3178+
}
3179+
stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3180+
}
3181+
31043182
/* Route Reflector. */
31053183
if (peer->sort == BGP_PEER_IBGP
31063184
&& from
@@ -3333,6 +3411,7 @@ bgp_attr_init (void)
33333411
attrhash_init ();
33343412
community_init ();
33353413
ecommunity_init ();
3414+
lcommunity_init ();
33363415
cluster_init ();
33373416
transit_init ();
33383417
encap_init ();
@@ -3345,6 +3424,7 @@ bgp_attr_finish (void)
33453424
attrhash_finish ();
33463425
community_finish ();
33473426
ecommunity_finish ();
3427+
lcommunity_finish ();
33483428
cluster_finish ();
33493429
transit_finish ();
33503430
encap_finish ();
@@ -3448,6 +3528,25 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
34483528
stream_put (s, attr->community->val, attr->community->size * 4);
34493529
}
34503530

3531+
/* Large Community attribute. */
3532+
if (attr->extra && attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LARGE_COMMUNITIES))
3533+
{
3534+
if (attr->extra->lcommunity->size * 12 > 255)
3535+
{
3536+
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN);
3537+
stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3538+
stream_putw (s, attr->extra->lcommunity->size * 12);
3539+
}
3540+
else
3541+
{
3542+
stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
3543+
stream_putc (s, BGP_ATTR_LARGE_COMMUNITIES);
3544+
stream_putc (s, attr->extra->lcommunity->size * 12);
3545+
}
3546+
3547+
stream_put (s, attr->extra->lcommunity->val, attr->extra->lcommunity->size * 12);
3548+
}
3549+
34513550
/* Add a MP_NLRI attribute to dump the IPv6 next hop */
34523551
if (prefix != NULL && prefix->family == AF_INET6 && attr->extra &&
34533552
(attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||

bgpd/bgp_attr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ struct attr_extra
9292

9393
/* Extended Communities attribute. */
9494
struct ecommunity *ecommunity;
95+
96+
/* Large Communities attribute. */
97+
struct lcommunity *lcommunity;
9598

9699
/* Route-Reflector Cluster attribute */
97100
struct cluster_list *cluster;

0 commit comments

Comments
 (0)