@@ -42,6 +42,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
42
42
#include "bgpd/bgp_debug.h"
43
43
#include "bgpd/bgp_packet.h"
44
44
#include "bgpd/bgp_ecommunity.h"
45
+ #include "bgpd/bgp_lcommunity.h"
45
46
#include "bgpd/bgp_updgrp.h"
46
47
#include "bgpd/bgp_encap_types.h"
47
48
#if ENABLE_BGP_VNC
@@ -76,6 +77,7 @@ static const struct message attr_str [] =
76
77
#if ENABLE_BGP_VNC
77
78
{ BGP_ATTR_VNC , "VNC" },
78
79
#endif
80
+ { BGP_ATTR_LARGE_COMMUNITIES , "LARGE_COMMUNITY" }
79
81
};
80
82
static const int attr_str_max = array_size (attr_str );
81
83
@@ -670,6 +672,8 @@ attrhash_key_make (void *p)
670
672
671
673
if (extra )
672
674
{
675
+ if (extra -> lcommunity )
676
+ MIX (lcommunity_hash_make (extra -> lcommunity ));
673
677
if (extra -> ecommunity )
674
678
MIX (ecommunity_hash_make (extra -> ecommunity ));
675
679
if (extra -> cluster )
@@ -718,6 +722,7 @@ attrhash_cmp (const void *p1, const void *p2)
718
722
&& IPV6_ADDR_SAME (& ae1 -> mp_nexthop_local , & ae2 -> mp_nexthop_local )
719
723
&& IPV4_ADDR_SAME (& ae1 -> mp_nexthop_global_in , & ae2 -> mp_nexthop_global_in )
720
724
&& ae1 -> ecommunity == ae2 -> ecommunity
725
+ && ae1 -> lcommunity == ae2 -> lcommunity
721
726
&& ae1 -> cluster == ae2 -> cluster
722
727
&& ae1 -> transit == ae2 -> transit
723
728
&& (ae1 -> encap_tunneltype == ae2 -> encap_tunneltype )
@@ -836,6 +841,13 @@ bgp_attr_intern (struct attr *attr)
836
841
attre -> ecommunity -> refcnt ++ ;
837
842
838
843
}
844
+ if (attre -> lcommunity )
845
+ {
846
+ if (! attre -> lcommunity -> refcnt )
847
+ attre -> lcommunity = lcommunity_intern (attre -> lcommunity );
848
+ else
849
+ attre -> lcommunity -> refcnt ++ ;
850
+ }
839
851
if (attre -> cluster )
840
852
{
841
853
if (! attre -> cluster -> refcnt )
@@ -1026,6 +1038,10 @@ bgp_attr_unintern_sub (struct attr *attr)
1026
1038
if (attr -> extra -> ecommunity )
1027
1039
ecommunity_unintern (& attr -> extra -> ecommunity );
1028
1040
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 ));
1029
1045
1030
1046
if (attr -> extra -> cluster )
1031
1047
cluster_unintern (attr -> extra -> cluster );
@@ -1096,6 +1112,8 @@ bgp_attr_flush (struct attr *attr)
1096
1112
1097
1113
if (attre -> ecommunity && ! attre -> ecommunity -> refcnt )
1098
1114
ecommunity_free (& attre -> ecommunity );
1115
+ if (attre -> lcommunity && ! attre -> lcommunity -> refcnt )
1116
+ lcommunity_free (& attre -> lcommunity );
1099
1117
if (attre -> cluster && ! attre -> cluster -> refcnt )
1100
1118
{
1101
1119
cluster_free (attre -> cluster );
@@ -1254,6 +1272,7 @@ const u_int8_t attr_flags_values [] = {
1254
1272
[BGP_ATTR_EXT_COMMUNITIES ] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS ,
1255
1273
[BGP_ATTR_AS4_PATH ] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS ,
1256
1274
[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
1257
1276
};
1258
1277
static const size_t attr_flags_values_max = array_size (attr_flags_values ) - 1 ;
1259
1278
@@ -2042,6 +2061,40 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args,
2042
2061
return BGP_ATTR_PARSE_PROCEED ;
2043
2062
}
2044
2063
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
+
2045
2098
/* Extended Community attribute. */
2046
2099
static bgp_attr_parse_ret_t
2047
2100
bgp_attr_ext_communities (struct bgp_attr_parser_args * args )
@@ -2063,7 +2116,7 @@ bgp_attr_ext_communities (struct bgp_attr_parser_args *args)
2063
2116
/* XXX: fix ecommunity_parse to use stream API */
2064
2117
stream_forward_getp (peer -> ibuf , length );
2065
2118
2066
- if (!attr -> extra -> ecommunity )
2119
+ if (attr -> extra && !attr -> extra -> ecommunity )
2067
2120
return bgp_attr_malformed (args ,
2068
2121
BGP_NOTIFY_UPDATE_OPT_ATTR_ERR ,
2069
2122
args -> total );
@@ -2477,6 +2530,9 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size,
2477
2530
case BGP_ATTR_COMMUNITIES :
2478
2531
ret = bgp_attr_community (& attr_args );
2479
2532
break ;
2533
+ case BGP_ATTR_LARGE_COMMUNITIES :
2534
+ ret = bgp_attr_large_community (& attr_args );
2535
+ break ;
2480
2536
case BGP_ATTR_ORIGINATOR_ID :
2481
2537
ret = bgp_attr_originator_id (& attr_args );
2482
2538
break ;
@@ -3101,6 +3157,28 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
3101
3157
stream_put (s , attr -> community -> val , attr -> community -> size * 4 );
3102
3158
}
3103
3159
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
+
3104
3182
/* Route Reflector. */
3105
3183
if (peer -> sort == BGP_PEER_IBGP
3106
3184
&& from
@@ -3333,6 +3411,7 @@ bgp_attr_init (void)
3333
3411
attrhash_init ();
3334
3412
community_init ();
3335
3413
ecommunity_init ();
3414
+ lcommunity_init ();
3336
3415
cluster_init ();
3337
3416
transit_init ();
3338
3417
encap_init ();
@@ -3345,6 +3424,7 @@ bgp_attr_finish (void)
3345
3424
attrhash_finish ();
3346
3425
community_finish ();
3347
3426
ecommunity_finish ();
3427
+ lcommunity_finish ();
3348
3428
cluster_finish ();
3349
3429
transit_finish ();
3350
3430
encap_finish ();
@@ -3448,6 +3528,25 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr,
3448
3528
stream_put (s , attr -> community -> val , attr -> community -> size * 4 );
3449
3529
}
3450
3530
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
+
3451
3550
/* Add a MP_NLRI attribute to dump the IPv6 next hop */
3452
3551
if (prefix != NULL && prefix -> family == AF_INET6 && attr -> extra &&
3453
3552
(attr -> extra -> mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL ||
0 commit comments