if (attr->aspath)
MIX(aspath_key_make(attr->aspath));
- if (attr->community)
- MIX(community_hash_make(attr->community));
-
+ if (bgp_attr_get_community(attr))
+ MIX(community_hash_make(bgp_attr_get_community(attr)));
if (bgp_attr_get_lcommunity(attr))
MIX(lcommunity_hash_make(bgp_attr_get_lcommunity(attr)));
if (bgp_attr_get_ecommunity(attr))
if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
&& attr1->nexthop.s_addr == attr2->nexthop.s_addr
&& attr1->aspath == attr2->aspath
- && attr1->community == attr2->community && attr1->med == attr2->med
+ && bgp_attr_get_community(attr1)
+ == bgp_attr_get_community(attr2)
+ && attr1->med == attr2->med
&& attr1->local_pref == attr2->local_pref
&& attr1->rmap_change_flags == attr2->rmap_change_flags) {
if (attr1->aggregator_as == attr2->aggregator_as
struct ecommunity *ecomm = NULL;
struct ecommunity *ipv6_ecomm = NULL;
struct lcommunity *lcomm = NULL;
+ struct community *comm = NULL;
- /* Intern referenced strucutre. */
+ /* Intern referenced structure. */
if (attr->aspath) {
if (!attr->aspath->refcnt)
attr->aspath = aspath_intern(attr->aspath);
else
attr->aspath->refcnt++;
}
- if (attr->community) {
- if (!attr->community->refcnt)
- attr->community = community_intern(attr->community);
+
+ comm = bgp_attr_get_community(attr);
+ if (comm) {
+ if (!comm->refcnt)
+ bgp_attr_set_community(attr, community_intern(comm));
else
- attr->community->refcnt++;
+ comm->refcnt++;
}
ecomm = bgp_attr_get_ecommunity(attr);
struct attr *new;
int ret;
- memset(&attr, 0, sizeof(struct attr));
+ memset(&attr, 0, sizeof(attr));
/* Origin attribute. */
attr.origin = origin;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ /* MED */
+ attr.med = 0;
+ attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
/* AS path attribute. */
if (aspath)
attr.aspath = aspath_intern(aspath);
community_del_val(community, &gshut);
}
- attr.community = community;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
+ bgp_attr_set_community(&attr, community);
}
- if (ecommunity) {
+ if (ecommunity)
bgp_attr_set_ecommunity(&attr, ecommunity);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- }
- if (lcommunity) {
+ if (lcommunity)
bgp_attr_set_lcommunity(&attr, lcommunity);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
- }
if (bgp_in_graceful_shutdown(bgp))
bgp_attr_add_gshut_community(&attr);
struct attr attr_tmp = attr;
struct bgp_path_info rmap_path;
- memset(&rmap_path, 0, sizeof(struct bgp_path_info));
+ memset(&rmap_path, 0, sizeof(rmap_path));
rmap_path.peer = bgp->peer_self;
rmap_path.attr = &attr_tmp;
struct ecommunity *ipv6_ecomm = NULL;
struct cluster_list *cluster;
struct lcommunity *lcomm = NULL;
+ struct community *comm = NULL;
/* aspath refcount shoud be decrement. */
aspath_unintern(&attr->aspath);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
- if (attr->community)
- community_unintern(&attr->community);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
+ comm = bgp_attr_get_community(attr);
+ community_unintern(&comm);
+ bgp_attr_set_community(attr, NULL);
ecomm = bgp_attr_get_ecommunity(attr);
ecommunity_unintern(&ecomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
bgp_attr_set_ecommunity(attr, NULL);
ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
ecommunity_unintern(&ipv6_ecomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
bgp_attr_set_ipv6_ecommunity(attr, NULL);
lcomm = bgp_attr_get_lcommunity(attr);
lcommunity_unintern(&lcomm);
- UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
bgp_attr_set_lcommunity(attr, NULL);
cluster = bgp_attr_get_cluster(attr);
struct ecommunity *ipv6_ecomm;
struct cluster_list *cluster;
struct lcommunity *lcomm;
+ struct community *comm;
if (attr->aspath && !attr->aspath->refcnt) {
aspath_free(attr->aspath);
attr->aspath = NULL;
}
- if (attr->community && !attr->community->refcnt)
- community_free(&attr->community);
+ comm = bgp_attr_get_community(attr);
+ if (comm && !comm->refcnt)
+ community_free(&comm);
+ bgp_attr_set_community(attr, NULL);
+
ecomm = bgp_attr_get_ecommunity(attr);
if (ecomm && !ecomm->refcnt)
ecommunity_free(&ecomm);
bgp_attr_set_ecommunity(attr, NULL);
+
ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(attr);
if (ipv6_ecomm && !ipv6_ecomm->refcnt)
ecommunity_free(&ipv6_ecomm);
bgp_attr_set_ipv6_ecommunity(attr, NULL);
+
lcomm = bgp_attr_get_lcommunity(attr);
if (lcomm && !lcomm->refcnt)
lcommunity_free(&lcomm);
* are partial/optional and hence where the error likely was not
* introduced by the sending neighbour.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
bgp_size_t length)
{
}
/* Get origin attribute of the update message. */
-static bgp_attr_parse_ret_t bgp_attr_origin(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_origin(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
return BGP_ATTR_PARSE_PROCEED;
}
-static bgp_attr_parse_ret_t bgp_attr_aspath_check(struct peer *const peer,
- struct attr *const attr)
+static enum bgp_attr_parse_ret bgp_attr_aspath_check(struct peer *const peer,
+ struct attr *const attr)
{
/* These checks were part of bgp_attr_aspath, but with
* as4 we should to check aspath things when
/*
* Check that the nexthop attribute is valid.
*/
-bgp_attr_parse_ret_t
-bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
+enum bgp_attr_parse_ret bgp_attr_nexthop_valid(struct peer *peer,
+ struct attr *attr)
{
in_addr_t nexthop_h;
}
/* Nexthop attribute. */
-static bgp_attr_parse_ret_t bgp_attr_nexthop(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_nexthop(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
}
/* MED atrribute. */
-static bgp_attr_parse_ret_t bgp_attr_med(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
}
/* Local preference attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_local_pref(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
}
/* New Aggregator attribute */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
as_t *as4_aggregator_as,
struct in_addr *as4_aggregator_addr)
/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
struct aspath *as4_path, as_t as4_aggregator,
struct in_addr *as4_aggregator_addr)
}
/* Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_community(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
const bgp_size_t length = args->length;
if (length == 0) {
- attr->community = NULL;
+ bgp_attr_set_community(attr, NULL);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
}
- attr->community =
- community_parse((uint32_t *)stream_pnt(peer->curr), length);
+ bgp_attr_set_community(
+ attr,
+ community_parse((uint32_t *)stream_pnt(peer->curr), length));
/* XXX: fix community_parse to use stream API and remove this */
stream_forward_getp(peer->curr, length);
/* The Community attribute SHALL be considered malformed if its
* length is not a non-zero multiple of 4.
*/
- if (!attr->community)
+ if (!bgp_attr_get_community(attr))
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
/* Originator ID attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_originator_id(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
}
/* Cluster list attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
}
/* Large Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_large_community(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
/* Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
-
/* Extract DF election preference and mobility sequence number */
attr->df_pref = bgp_attr_df_pref_from_ec(attr, &attr->df_alg);
}
/* IPv6 Extended Community attribute. */
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES);
-
return BGP_ATTR_PARSE_PROCEED;
}
/* SRv6 Service Data Sub-Sub-TLV attribute
* draft-ietf-bess-srv6-services-07
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_srv6_service_data(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
args->total);
}
+ if (length < BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH) {
+ flog_err(
+ EC_BGP_ATTR_LEN,
+ "Malformed SRv6 Service Data Sub-Sub-TLV attribute - insufficient data (need %u, have %hu remaining in UPDATE)",
+ BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE_LENGTH,
+ length);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+ args->total);
+ }
+
if (type == BGP_PREFIX_SID_SRV6_L3_SERVICE_SID_STRUCTURE) {
loc_block_len = stream_getc(peer->curr);
loc_node_len = stream_getc(peer->curr);
/* SRv6 Service Sub-TLV attribute
* draft-ietf-bess-srv6-services-07
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_srv6_service(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
uint8_t type, sid_flags;
uint16_t length, endpoint_behavior;
size_t headersz = sizeof(type) + sizeof(length);
- bgp_attr_parse_ret_t err;
+ enum bgp_attr_parse_ret err;
char buf[BUFSIZ];
if (STREAM_READABLE(peer->curr) < headersz) {
* Read an individual SID value returning how much data we have read
* Returns 0 if there was an error that needs to be passed up the stack
*/
-static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length,
- struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_psid_sub(uint8_t type, uint16_t length,
+ struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
/* Prefix SID attribute
* draft-ietf-idr-bgp-prefix-sid-05
*/
-bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
+enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
- bgp_attr_parse_ret_t ret;
+ enum bgp_attr_parse_ret ret;
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
/* PMSI tunnel attribute (RFC 6514)
* Basic validation checks done here.
*/
-static bgp_attr_parse_ret_t
+static enum bgp_attr_parse_ret
bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
{
struct peer *const peer = args->peer;
}
/* BGP unknown attribute treatment. */
-static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
+static enum bgp_attr_parse_ret
+bgp_attr_unknown(struct bgp_attr_parser_args *args)
{
bgp_size_t total = args->total;
struct transit *transit;
/* Read attribute of update packet. This function is called from
bgp_update_receive() in bgp_packet.c. */
-bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
- bgp_size_t size, struct bgp_nlri *mp_update,
- struct bgp_nlri *mp_withdraw)
+enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
+ bgp_size_t size,
+ struct bgp_nlri *mp_update,
+ struct bgp_nlri *mp_withdraw)
{
- bgp_attr_parse_ret_t ret;
+ enum bgp_attr_parse_ret ret;
uint8_t flag = 0;
uint8_t type = 0;
bgp_size_t length;
struct attr *attr)
{
size_t sizep;
- iana_afi_t pkt_afi;
- iana_safi_t pkt_safi;
+ iana_afi_t pkt_afi = IANA_AFI_IPV4;
+ iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
afi_t nh_afi;
/* Set extended bit always to encode the attribute length as 2 bytes */
/* Community attribute. */
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
- if (attr->community->size * 4 > 255) {
+ struct community *comm = NULL;
+
+ comm = bgp_attr_get_community(attr);
+ if (comm->size * 4 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_COMMUNITIES);
- stream_putw(s, attr->community->size * 4);
+ stream_putw(s, comm->size * 4);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
- stream_putc(s, attr->community->size * 4);
+ stream_putc(s, comm->size * 4);
}
- stream_put(s, attr->community->val, attr->community->size * 4);
+ stream_put(s, comm->val, comm->size * 4);
}
/*
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
&& (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
-
- if (peer->sort == BGP_PEER_IBGP
- || peer->sort == BGP_PEER_CONFED) {
+ bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT) &&
+ from &&
+ CHECK_FLAG(from->af_flags[afi][safi],
+ PEER_FLAG_RSERVER_CLIENT);
+
+ if (peer->sort == BGP_PEER_IBGP ||
+ peer->sort == BGP_PEER_CONFED || transparent) {
if (ecomm->size * 8 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
{
unsigned long attrlen_pnt;
- iana_afi_t pkt_afi;
- iana_safi_t pkt_safi;
+ iana_afi_t pkt_afi = IANA_AFI_IPV4;
+ iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
/* Set extended bit always to encode the attribute length as 2 bytes */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_EXTLEN);
/* Community attribute. */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
- if (attr->community->size * 4 > 255) {
+ struct community *comm = NULL;
+
+ comm = bgp_attr_get_community(attr);
+ if (comm->size * 4 > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, BGP_ATTR_COMMUNITIES);
- stream_putw(s, attr->community->size * 4);
+ stream_putw(s, comm->size * 4);
} else {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
- stream_putc(s, attr->community->size * 4);
+ stream_putc(s, comm->size * 4);
}
- stream_put(s, attr->community->val, attr->community->size * 4);
+ stream_put(s, comm->val, comm->size * 4);
}
/* Large Community attribute. */