MIX(extra->mp_nexthop_global_in.s_addr);
MIX(extra->originator_id.s_addr);
MIX(extra->tag);
+ MIX(extra->label_index);
}
if (attr->aspath)
&& 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)
[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;
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)
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;
}
}
+ /* 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 */
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);
{
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
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)
{
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)
{