mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 17:40:04 +00:00
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:
parent
1b6d5c7e08
commit
6cf48acc1c
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user