bgp_set_valid_label(&dest->local_label);
}
SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
- bgp_dest_unlock_node(dest);
bgp_process(bgp, dest, afi, safi);
+ bgp_dest_unlock_node(dest);
return 1;
}
return dest->local_label;
}
+static void bgp_send_fec_register_label_msg(struct bgp_dest *dest, bool reg,
+ uint32_t label_index)
+{
+ struct stream *s;
+ int command;
+ const struct prefix *p;
+ uint16_t flags = 0;
+ size_t flags_pos = 0;
+ mpls_label_t *local_label = &(dest->local_label);
+ bool have_label_to_reg =
+ bgp_is_valid_label(local_label)
+ && label_pton(local_label) != MPLS_LABEL_IMPLICIT_NULL;
+
+ p = bgp_dest_get_prefix(dest);
+
+ /* Check socket. */
+ if (!zclient || zclient->sock < 0)
+ return;
+
+ if (BGP_DEBUG(labelpool, LABELPOOL))
+ zlog_debug("%s: FEC %sregister %pRN label_index=%u label=%u",
+ __func__, reg ? "" : "un", bgp_dest_to_rnode(dest),
+ label_index, label_pton(local_label));
+ /* If the route node has a local_label assigned or the
+ * path node has an MPLS SR label index allowing zebra to
+ * derive the label, proceed with registration. */
+ s = zclient->obuf;
+ stream_reset(s);
+ command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
+ zclient_create_header(s, command, VRF_DEFAULT);
+ flags_pos = stream_get_endp(s); /* save position of 'flags' */
+ stream_putw(s, flags); /* initial flags */
+ stream_putw(s, PREFIX_FAMILY(p));
+ stream_put_prefix(s, p);
+ if (reg) {
+ /* label index takes precedence over auto-assigned label. */
+ if (label_index != 0) {
+ flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
+ stream_putl(s, label_index);
+ } else if (have_label_to_reg) {
+ flags |= ZEBRA_FEC_REGISTER_LABEL;
+ stream_putl(s, label_pton(local_label));
+ }
+ SET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
+ } else
+ UNSET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
+
+ /* Set length and flags */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ /*
+ * We only need to write new flags if this is a register
+ */
+ if (reg)
+ stream_putw_at(s, flags_pos, flags);
+
+ zclient_send_message(zclient);
+}
+
/**
* This is passed as the callback function to bgp_labelpool.c:bgp_lp_get()
* by bgp_reg_dereg_for_label() when a label needs to be obtained from
int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid,
bool allocated)
{
- struct bgp_path_info *pi;
struct bgp_dest *dest;
- pi = labelid;
- /* Is this path still valid? */
- if (!bgp_path_info_unlock(pi)) {
- if (BGP_DEBUG(labelpool, LABELPOOL))
- zlog_debug(
- "%s: bgp_path_info is no longer valid, ignoring",
- __func__);
+ dest = labelid;
+
+ /*
+ * if the route had been removed or the request has gone then reject
+ * the allocated label. The requesting code will have done what is
+ * required to allocate the correct label
+ */
+ if (!CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
+ bgp_dest_unlock_node(dest);
return -1;
}
- dest = pi->net;
+ bgp_dest_unlock_node(dest);
if (BGP_DEBUG(labelpool, LABELPOOL))
zlog_debug("%s: FEC %pRN label=%u, allocated=%d", __func__,
if (!allocated) {
/*
- * previously-allocated label is now invalid
+ * previously-allocated label is now invalid, set to implicit
+ * null until new label arrives
*/
- if (pi->attr->label_index == MPLS_INVALID_LABEL_INDEX
- && pi->attr->label != MPLS_LABEL_NONE
- && CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
- bgp_unregister_for_label(dest);
+ if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
+ UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
&dest->local_label);
bgp_set_valid_label(&dest->local_label);
}
- return 0;
- }
-
- /*
- * label index is assigned, this should be handled by SR-related code,
- * so retry FEC registration and then reject label allocation for
- * it to be released to label pool
- */
- if (pi->attr->label_index != MPLS_INVALID_LABEL_INDEX) {
- flog_err(
- EC_BGP_LABEL,
- "%s: FEC %pRN Rejecting allocated label %u as Label Index is %u",
- __func__, bgp_dest_to_rnode(dest), new_label,
- pi->attr->label_index);
-
- bgp_register_for_label(pi->net, pi);
-
- return -1;
- }
-
- if (pi->attr->label != MPLS_INVALID_LABEL) {
- if (new_label == pi->attr->label) {
- /* already have same label, accept but do nothing */
- return 0;
- }
- /* Shouldn't happen: different label allocation */
- flog_err(EC_BGP_LABEL,
- "%s: %pRN had label %u but got new assignment %u",
- __func__, bgp_dest_to_rnode(dest), pi->attr->label,
- new_label);
- /* continue means use new one */
}
label_ntop(new_label, 1, &dest->local_label);
/*
* Get back to registering the FEC
*/
- bgp_register_for_label(pi->net, pi);
+ bgp_send_fec_register_label_msg(dest, true, 0);
return 0;
}
bool reg)
{
bool with_label_index = false;
- struct stream *s;
const struct prefix *p;
- mpls_label_t *local_label;
- int command;
- uint16_t flags = 0;
- size_t flags_pos = 0;
+ bool have_label_to_reg =
+ bgp_is_valid_label(&dest->local_label)
+ && label_pton(&dest->local_label) != MPLS_LABEL_IMPLICIT_NULL;
p = bgp_dest_get_prefix(dest);
- local_label = &(dest->local_label);
- /* this prevents the loop when we're called by
- * bgp_reg_for_label_callback()
- */
- bool have_label_to_reg = bgp_is_valid_label(local_label)
- && label_pton(local_label) != MPLS_LABEL_IMPLICIT_NULL;
if (reg) {
assert(pi);
ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))
&& pi->attr->label_index != BGP_INVALID_LABEL_INDEX) {
with_label_index = true;
+ UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
} else {
/*
- * If no label index was provided -- assume any label
+ * If no label has been registered -- assume any label
* from label pool will do. This means that label index
* always takes precedence over auto-assigned labels.
*/
if (!have_label_to_reg) {
+ SET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
if (BGP_DEBUG(labelpool, LABELPOOL))
zlog_debug(
"%s: Requesting label from LP for %pFX",
__func__, p);
-
- /* bgp_reg_for_label_callback() will call back
- * __func__ when it gets a label from the pool.
- * This means we'll never register FECs without
- * valid labels.
+ /* bgp_reg_for_label_callback() will deal with
+ * fec registration when it gets a label from
+ * the pool. This means we'll never register
+ * FECs withoutvalid labels.
*/
- bgp_lp_get(LP_TYPE_BGP_LU, pi,
- bgp_reg_for_label_callback);
+ bgp_lp_get(LP_TYPE_BGP_LU, dest,
+ bgp_reg_for_label_callback);
return;
}
}
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
+ bgp_lp_release(LP_TYPE_BGP_LU, dest,
+ label_pton(&dest->local_label));
}
- /* Check socket. */
- if (!zclient || zclient->sock < 0)
- return;
-
- /* If the route node has a local_label assigned or the
- * path node has an MPLS SR label index allowing zebra to
- * derive the label, proceed with registration. */
- s = zclient->obuf;
- stream_reset(s);
- command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
- zclient_create_header(s, command, VRF_DEFAULT);
- flags_pos = stream_get_endp(s); /* save position of 'flags' */
- stream_putw(s, flags); /* initial flags */
- stream_putw(s, PREFIX_FAMILY(p));
- stream_put_prefix(s, p);
- if (reg) {
- if (have_label_to_reg) {
- flags |= ZEBRA_FEC_REGISTER_LABEL;
- stream_putl(s, label_pton(local_label));
- } else if (with_label_index) {
- flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX;
- stream_putl(s, pi->attr->label_index);
- }
- SET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
- } else
- UNSET_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL);
-
- /* Set length and flags */
- stream_putw_at(s, 0, stream_get_endp(s));
-
- /*
- * We only need to write new flags if this is a register
- */
- if (reg)
- stream_putw_at(s, flags_pos, flags);
-
- zclient_send_message(zclient);
+ bgp_send_fec_register_label_msg(
+ dest, reg, with_label_index ? pi->attr->label_index : 0);
}
static int bgp_nlri_get_labels(struct peer *peer, uint8_t *pnt, uint8_t plen,
return BGP_NLRI_PARSE_ERROR_LABEL_LENGTH;
}
- if ((afi == AFI_IP && p.prefixlen > 32)
- || (afi == AFI_IP6 && p.prefixlen > 128))
+ if ((afi == AFI_IP && p.prefixlen > IPV4_MAX_BITLEN)
+ || (afi == AFI_IP6 && p.prefixlen > IPV6_MAX_BITLEN))
return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
/* Fetch prefix from NLRI packet */
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 labeled-unicast NLRI is link-local address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}