bgpd: This patch implements the exchange of the BGP-Prefix-SID label index attr

Implement BGP Prefix-SID IETF draft to be able to signal a labeled-unicast
prefix with a label index (segment ID). This makes it easier to deploy
global MPLS labels with BGP, even without other aspects of Segment Routing
implemented.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
This commit is contained in:
Vivek Venkatraman 2017-03-09 12:22:04 -05:00 committed by Donald Sharp
parent 1b6d5c7e08
commit 6cf48acc1c
7 changed files with 127 additions and 3 deletions

View File

@ -676,6 +676,7 @@ attrhash_key_make (void *p)
MIX(extra->mp_nexthop_global_in.s_addr);
MIX(extra->originator_id.s_addr);
MIX(extra->tag);
MIX(extra->label_index);
}
if (attr->aspath)
@ -730,6 +731,7 @@ attrhash_cmp (const void *p1, const void *p2)
&& ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
&& ae1->weight == ae2->weight
&& ae1->tag == ae2->tag
&& ae1->label_index == ae2->label_index
&& ae1->mp_nexthop_len == ae2->mp_nexthop_len
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
&& IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
@ -1287,6 +1289,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,
};
static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
@ -2274,6 +2277,52 @@ bgp_attr_encap(
return 0;
}
/* Label index attribute */
static bgp_attr_parse_ret_t
bgp_attr_label_index (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;
u_int32_t label_index;
/* Length check. */
if (length != 8)
{
zlog_err ("Bad label index length %d", length);
return bgp_attr_malformed (args,
BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
args->total);
}
/* 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->afi != SAFI_LABELED_UNICAST)
{
attr->extra->label_index = BGP_INVALID_LABEL_INDEX;
attr->flag &= ~ATTR_FLAG_BIT(BGP_ATTR_LABEL_INDEX);
}
return BGP_ATTR_PARSE_PROCEED;
}
/* BGP unknown attribute treatment. */
static bgp_attr_parse_ret_t
bgp_attr_unknown (struct bgp_attr_parser_args *args)
@ -2572,6 +2621,9 @@ 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);
break;
default:
ret = bgp_attr_unknown (&attr_args);
break;
@ -3355,6 +3407,23 @@ 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))
{
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 ( send_as4_path )
{
/* If the peer is NOT As4 capable, AND */
@ -3638,6 +3707,17 @@ 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))
{
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);
}
/* Return total size of attribute. */
len = stream_get_endp (s) - cp - 2;
stream_putw_at (s, cp, len);

View File

@ -134,6 +134,9 @@ struct attr_extra
/* route tag */
route_tag_t tag;
/* Label index */
u_int32_t label_index;
uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */

View File

@ -450,6 +450,10 @@ 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",
attr->extra->label_index);
if (strlen (buf) > 1)
return 1;
else

View File

@ -143,6 +143,11 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, int reg)
stream_putw(s, PREFIX_FAMILY(p));
stream_put_prefix(s, p);
stream_putw_at (s, 0, stream_get_endp (s));
if (reg)
SET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
else
UNSET_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL);
zclient_send_message(zclient);
return;

View File

@ -1942,9 +1942,21 @@ bgp_process_main (struct work_queue *wq, void *data)
{
label_valid = bgp_is_valid_label (rn->local_label);
if (!old_select && new_select && !label_valid)
bgp_register_for_label (rn);
{
if (new_select->sub_type == BGP_ROUTE_STATIC &&
new_select->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX))
{
label_ntop (MPLS_IMP_NULL_LABEL, 1, rn->local_label);
bgp_set_valid_label(rn->local_label);
}
else
bgp_register_for_label (rn);
}
else if (old_select && !new_select)
bgp_unregister_for_label (rn);
{
if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
bgp_unregister_for_label (rn);
}
}
/* If best route remains the same and this is not due to user-initiated
@ -3792,6 +3804,13 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
if (bgp_static->atomic)
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
/* Store label index, if required. */
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);
}
/* Apply route-map. */
if (bgp_static->rmap.name)
{
@ -7631,9 +7650,20 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (json_paths)
json_object_int_add(json_path, "remote-label", label);
else
vty_out(vty, " Remote label: %d%s", label, VTY_NEWLINE);
vty_out(vty, " Remote label: %d", label);
}
if (CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LABEL_INDEX)))
{
if (json_paths)
json_object_int_add(json_path, "label-index", attr->extra->label_index);
else
vty_out(vty, ", Label Index: %d", attr->extra->label_index);
}
if (!json_paths)
vty_out (vty, "%s", VTY_NEWLINE);
/* Line 8 display Addpath IDs */
if (binfo->addpath_rx_id || binfo->addpath_tx_id)
{

View File

@ -63,6 +63,7 @@ struct bgp_node
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
#define BGP_NODE_USER_CLEAR (1 << 1)
#define BGP_NODE_LABEL_CHANGED (1 << 2)
#define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3)
};
/*

View File

@ -972,6 +972,7 @@ struct bgp_nlri
#define BGP_ATTR_AS4_AGGREGATOR 18
#define BGP_ATTR_AS_PATHLIMIT 21
#define BGP_ATTR_ENCAP 23
#define BGP_ATTR_LABEL_INDEX 30
#define BGP_ATTR_LARGE_COMMUNITIES 32
#if ENABLE_BGP_VNC
#define BGP_ATTR_VNC 255