Update to draft-ietf-idr-bgp-prefix-sid-05

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>

The initial implementation was against draft-keyupate-idr-bgp-prefix-sid-02
This updates our label-index implementation up to draft-ietf-idr-bgp-prefix-sid-05
- changed BGP_ATTR_LABEL_INDEX to BGP_ATTR_PREFIX_SID
- since there are multiple TLVs in BGP_ATTR_PREFIX_SID you can no longer
  rely on that flag to know if there is a label-index for the path. I
changed bgp_attr_extra_new() to init the label_index to
BGP_INVALID_LABEL_INDEX
- put some placeholder code in for the other two TLVs (IPv6 and
  Originator SRGB)
This commit is contained in:
Daniel Walton 2017-04-26 21:45:32 +00:00
parent a30c159769
commit c5a543b433
6 changed files with 160 additions and 85 deletions

View file

@ -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);
/* 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;
}
/* 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);
/* Store label index; subsequently, we'll check on address-family */
(bgp_attr_extra_get (attr))->label_index = label_index;
attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX);
/*
* 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)
/* Placeholder code for the IPv6 SID type */
else if (type == BGP_PREFIX_SID_IPV6)
{
attr->extra->label_index = BGP_INVALID_LABEL_INDEX;
attr->flag &= ~ATTR_FLAG_BIT(BGP_ATTR_LABEL_INDEX);
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);
}
/* Ignore reserved */
stream_getc (peer->ibuf);
stream_getw (peer->ibuf);
stream_get (&ipv6_sid, peer->ibuf, 16);
}
/* Placeholder code for the Originator SRGB type */
else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB)
{
/* 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. */

View file

@ -57,6 +57,14 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define BGP_ATTR_NHLEN_VPNV6_GLOBAL 8+IPV6_MAX_BYTELEN
#define BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ((8+IPV6_MAX_BYTELEN) * 2)
/* Prefix SID types */
#define BGP_PREFIX_SID_LABEL_INDEX 1
#define BGP_PREFIX_SID_IPV6 2
#define BGP_PREFIX_SID_ORIGINATOR_SRGB 3
#define BGP_PREFIX_SID_LABEL_INDEX_LENGTH 7
#define BGP_PREFIX_SID_IPV6_LENGTH 19
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
struct bgp_attr_encap_subtlv {
struct bgp_attr_encap_subtlv *next; /* for chaining */

View file

@ -450,9 +450,12 @@ bgp_dump_attr (struct peer *peer, struct attr *attr, char *buf, size_t size)
snprintf (buf + strlen (buf), size - strlen (buf), ", path %s",
aspath_print (attr->aspath));
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX)))
snprintf (buf + strlen (buf), size - strlen (buf), ", label-index %u",
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID)))
{
if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
snprintf (buf + strlen (buf), size - strlen (buf), ", label-index %u",
attr->extra->label_index);
}
if (strlen (buf) > 1)
return 1;

View file

@ -150,11 +150,15 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
if (reg)
{
assert (ri);
if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))
if (ri->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
{
assert (ri->attr->extra);
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl (s, ri->attr->extra->label_index);
if (ri->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{
flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
stream_putl (s, ri->attr->extra->label_index);
}
}
SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
}

View file

@ -301,16 +301,7 @@ bgp_pcount_adjust (struct bgp_node *rn, struct bgp_info *ri)
static int
bgp_label_index_differs (struct bgp_info *ri1, struct bgp_info *ri2)
{
u_int32_t ri1_label_index = BGP_INVALID_LABEL_INDEX;
u_int32_t ri2_label_index = BGP_INVALID_LABEL_INDEX;
if (ri1->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))
ri1_label_index = ri1->attr->extra->label_index;
if (ri2->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))
ri2_label_index = ri2->attr->extra->label_index;
return (!(ri1_label_index == ri2_label_index));
return (!(ri1->attr->extra->label_index == ri2->attr->extra->label_index));
}
/* Set/unset bgp_info flags, adjusting any other state as needed.
@ -1960,7 +1951,8 @@ bgp_process_main (struct work_queue *wq, void *data)
new_select->sub_type != old_select->sub_type)
{
if (new_select->sub_type == BGP_ROUTE_STATIC &&
new_select->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))
new_select->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID) &&
new_select->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{
if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
bgp_unregister_for_label (rn);
@ -3824,7 +3816,7 @@ bgp_static_update (struct bgp *bgp, struct prefix *p,
if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
{
(bgp_attr_extra_get (&attr))->label_index = bgp_static->label_index;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX);
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
}
/* Apply route-map. */
@ -7653,26 +7645,23 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (binfo->extra && binfo->extra->damp_info)
bgp_damp_info_vty (vty, binfo, json_path);
/* Label information */
if ((bgp_labeled_safi(safi) && binfo->extra) ||
(CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))))
/* Remove Label */
if (bgp_labeled_safi(safi) && binfo->extra)
{
if (bgp_labeled_safi(safi) && binfo->extra)
{
uint32_t label = label_pton(binfo->extra->tag);
if (json_paths)
json_object_int_add(json_path, "remoteLabel", label);
else
vty_out(vty, " Remote label: %d%s", label, VTY_NEWLINE);
}
uint32_t label = label_pton(binfo->extra->tag);
if (json_paths)
json_object_int_add(json_path, "remoteLabel", label);
else
vty_out(vty, " Remote label: %d%s", label, VTY_NEWLINE);
}
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX)))
{
if (json_paths)
json_object_int_add(json_path, "labelIndex", attr->extra->label_index);
else
vty_out(vty, " Label Index: %d%s", attr->extra->label_index, VTY_NEWLINE);
}
/* Label Index */
if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
{
if (json_paths)
json_object_int_add(json_path, "labelIndex", attr->extra->label_index);
else
vty_out(vty, " Label Index: %d%s", attr->extra->label_index, VTY_NEWLINE);
}
/* Line 8 display Addpath IDs */

View file

@ -973,7 +973,7 @@ struct bgp_nlri
#define BGP_ATTR_AS_PATHLIMIT 21
#define BGP_ATTR_ENCAP 23
#define BGP_ATTR_LARGE_COMMUNITIES 32
#define BGP_ATTR_LABEL_INDEX 40
#define BGP_ATTR_PREFIX_SID 40
#if ENABLE_BGP_VNC
#define BGP_ATTR_VNC 255
#endif