diff options
Diffstat (limited to 'bgpd/bgp_attr.c')
| -rw-r--r-- | bgpd/bgp_attr.c | 163 |
1 files changed, 117 insertions, 46 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index a25ebf4772..b2789cd47d 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -79,7 +79,7 @@ static const struct message attr_str [] = { BGP_ATTR_VNC, "VNC" }, #endif { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }, - { BGP_ATTR_LABEL_INDEX, "LABEL_INDEX" } + { BGP_ATTR_PREFIX_SID, "PREFIX_SID" } }; static const int attr_str_max = array_size(attr_str); @@ -533,7 +533,10 @@ static struct hash *attrhash; static struct attr_extra * bgp_attr_extra_new (void) { - return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra)); + struct attr_extra *extra; + extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra)); + extra->label_index = BGP_INVALID_LABEL_INDEX; + return extra; } void @@ -1290,7 +1293,7 @@ const u_int8_t attr_flags_values [] = { [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, [BGP_ATTR_LARGE_COMMUNITIES]= BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, - [BGP_ATTR_LABEL_INDEX] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, + [BGP_ATTR_PREFIX_SID] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, }; static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; @@ -2278,49 +2281,103 @@ bgp_attr_encap( return 0; } -/* Label index attribute */ +/* Prefix SID attribute + * draft-ietf-idr-bgp-prefix-sid-05 + */ static bgp_attr_parse_ret_t -bgp_attr_label_index (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update) +bgp_attr_prefix_sid (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update) { struct peer *const peer = args->peer; struct attr *const attr = args->attr; - const bgp_size_t length = args->length; + int type; + int length; u_int32_t label_index; + struct in6_addr ipv6_sid; + u_int32_t srgb_base; + u_int32_t srgb_range; + int srgb_count; - /* Length check. */ - if (length != 8) + attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID); + + type = stream_getc (peer->ibuf); + length = stream_getw (peer->ibuf); + + if (type == BGP_PREFIX_SID_LABEL_INDEX) { - zlog_err ("Bad label index length %d", length); + if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) + { + zlog_err ("Prefix SID label index length is %d instead of %d", length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + return bgp_attr_malformed (args, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, - args->total); - } + /* Ignore flags and reserved */ + stream_getc (peer->ibuf); + stream_getw (peer->ibuf); - /* First u32 is currently unused - reserved and flags (undefined) */ - stream_getl (peer->ibuf); + /* Fetch the label index and see if it is valid. */ + label_index = stream_getl (peer->ibuf); + if (label_index == BGP_INVALID_LABEL_INDEX) + return bgp_attr_malformed (args, + BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, + args->total); - /* Fetch the label index and see if it is valid. */ - label_index = stream_getl (peer->ibuf); - if (label_index == BGP_INVALID_LABEL_INDEX) - return bgp_attr_malformed (args, - BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, - args->total); + /* Store label index; subsequently, we'll check on address-family */ + (bgp_attr_extra_get (attr))->label_index = label_index; + + /* + * Ignore the Label index attribute unless received for labeled-unicast + * SAFI. + */ + if (!mp_update->length || mp_update->safi != SAFI_LABELED_UNICAST) + attr->extra->label_index = BGP_INVALID_LABEL_INDEX; + } - /* Store label index; subsequently, we'll check on address-family */ - (bgp_attr_extra_get (attr))->label_index = label_index; + /* Placeholder code for the IPv6 SID type */ + else if (type == BGP_PREFIX_SID_IPV6) + { + if (length != BGP_PREFIX_SID_IPV6_LENGTH) + { + zlog_err ("Prefix SID IPv6 length is %d instead of %d", length, BGP_PREFIX_SID_IPV6_LENGTH); + return bgp_attr_malformed (args, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } - attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX); + /* Ignore reserved */ + stream_getc (peer->ibuf); + stream_getw (peer->ibuf); - /* - * Ignore the Label index attribute unless received for labeled-unicast - * SAFI. We reset the flag, though it is probably unnecesary. - */ - if (!mp_update->length || mp_update->safi != SAFI_LABELED_UNICAST) + stream_get (&ipv6_sid, peer->ibuf, 16); + } + + /* Placeholder code for the Originator SRGB type */ + else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB) { - attr->extra->label_index = BGP_INVALID_LABEL_INDEX; - attr->flag &= ~ATTR_FLAG_BIT(BGP_ATTR_LABEL_INDEX); + /* Ignore flags */ + stream_getw (peer->ibuf); + + length -= 2; + + if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH) + { + zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ", + length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH); + return bgp_attr_malformed (args, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } + + srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH; + + for (int i = 0; i < srgb_count; i++) + { + stream_get (&srgb_base, peer->ibuf, 3); + stream_get (&srgb_range, peer->ibuf, 3); + } } + return BGP_ATTR_PARSE_PROCEED; } @@ -2622,8 +2679,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, case BGP_ATTR_ENCAP: ret = bgp_attr_encap (type, peer, length, attr, flag, startp); break; - case BGP_ATTR_LABEL_INDEX: - ret = bgp_attr_label_index (&attr_args, mp_update); + case BGP_ATTR_PREFIX_SID: + ret = bgp_attr_prefix_sid (&attr_args, mp_update); break; default: ret = bgp_attr_unknown (&attr_args); @@ -3412,17 +3469,24 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, /* Label index attribute. */ if (safi == SAFI_LABELED_UNICAST) { - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX)) + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) { u_int32_t label_index; assert (attr->extra); label_index = attr->extra->label_index; - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LABEL_INDEX); - stream_putc (s, 8); - stream_putl (s, 0); - stream_putl (s, label_index); + + if (label_index != BGP_INVALID_LABEL_INDEX) + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_PREFIX_SID); + stream_putc (s, 10); + stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX); + stream_putw (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + stream_putc (s, 0); // reserved + stream_putw (s, 0); // flags + stream_putl (s, label_index); + } } } @@ -3709,15 +3773,22 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr, stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1); } - /* Label index */ - if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX)) + /* Prefix SID */ + if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)) { assert (attr->extra); - stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_LABEL_INDEX); - stream_putc (s, 8); - stream_putl (s, 0); - stream_putl (s, attr->extra->label_index); + + if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX) + { + stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_PREFIX_SID); + stream_putc (s, 10); + stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX); + stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH); + stream_putc (s, 0); // reserved + stream_putw (s, 0); // flags + stream_putl (s, attr->extra->label_index); + } } /* Return total size of attribute. */ |
