return true;
}
+mpls_label_t bgp_mplsvpn_nh_label_bind_get_label(struct bgp_path_info *pi)
+{
+ mpls_label_t label;
+ struct bgp_mplsvpn_nh_label_bind_cache *bmnc;
+
+ bmnc = pi->mplsvpn.bmnc.nh_label_bind_cache;
+ if (!bmnc || bmnc->new_label == MPLS_INVALID_LABEL)
+ /* allocation in progress
+ * or path not eligible for local label
+ */
+ return MPLS_INVALID_LABEL;
+
+ label = mpls_lse_encode(bmnc->new_label, 0, 0, 1);
+ bgp_set_valid_label(&label);
+
+ return label;
+}
+
/* Called upon reception of a ZAPI Message from zebra, about
* a new available label.
*/
bool allocated)
{
struct bgp_mplsvpn_nh_label_bind_cache *bmnc = context;
+ struct bgp_table *table;
+ struct bgp_path_info *pi;
if (BGP_DEBUG(labelpool, LABELPOOL))
zlog_debug("%s: label=%u, allocated=%d, nexthop=%pFX, label %u",
bmnc->allocation_in_progress = false;
/* Create MPLS entry with new_label */
- /* Trigger BGP process to re-advertise updates */
+ LIST_FOREACH (pi, &(bmnc->paths), mplsvpn.bmnc.nh_label_bind_thread) {
+ /* we can advertise it */
+ if (!pi->net)
+ continue;
+ table = bgp_dest_table(pi->net);
+ if (!table)
+ continue;
+ SET_FLAG(pi->net->flags, BGP_NODE_LABEL_CHANGED);
+ bgp_process(table->bgp, pi->net, table->afi, table->safi);
+ }
+
return 0;
}
extern void bgp_mplsvpn_path_nh_label_bind_unlink(struct bgp_path_info *pi);
extern void bgp_mplsvpn_nh_label_bind_register_local_label(
struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info *pi);
+mpls_label_t bgp_mplsvpn_nh_label_bind_get_label(struct bgp_path_info *pi);
/* used to bind a local label to the (label, nexthop) values
* from an incoming BGP mplsvpn update
return path;
}
+bool bgp_path_info_nexthop_changed(struct bgp_path_info *pi, struct peer *to,
+ afi_t afi)
+{
+ if (pi->peer->sort == BGP_PEER_IBGP && to->sort == BGP_PEER_IBGP &&
+ !CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_FORCE_NEXTHOP_SELF))
+ /* IBGP RR with no nexthop self force configured */
+ return false;
+
+ if (to->sort == BGP_PEER_IBGP &&
+ !CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_NEXTHOP_SELF))
+ /* IBGP RR with no nexthop self configured */
+ return false;
+
+ if (CHECK_FLAG(to->af_flags[afi][SAFI_MPLS_VPN],
+ PEER_FLAG_NEXTHOP_UNCHANGED))
+ /* IBGP or EBGP with nexthop attribute unchanged */
+ return false;
+
+ return true;
+}
+
/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
{
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
bool nh_reset = false;
uint64_t cum_bw;
+ mpls_label_t label;
if (DISABLE_BGP_ANNOUNCE)
return false;
/* If it's labeled safi, make sure the route has a valid label. */
if (safi == SAFI_LABELED_UNICAST) {
- mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
+ label = bgp_adv_label(dest, pi, peer, afi, safi);
if (!bgp_is_valid_label(&label)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug("u%" PRIu64 ":s%" PRIu64
p, &label);
return false;
}
+ } else if (safi == SAFI_MPLS_VPN &&
+ CHECK_FLAG(pi->flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND) &&
+ pi->mplsvpn.bmnc.nh_label_bind_cache && from && peer &&
+ pi->peer != peer && pi->sub_type != BGP_ROUTE_IMPORTED &&
+ pi->sub_type != BGP_ROUTE_STATIC &&
+ bgp_mplsvpn_path_uses_valid_mpls_label(pi) &&
+ bgp_path_info_nexthop_changed(pi, peer, afi)) {
+ /* Redistributed mpls vpn route between distinct
+ * peers from 'pi->peer' to 'to',
+ * and an mpls label is used in this path,
+ * and there is a nh label bind entry,
+ * then get appropriate mpls local label
+ * and check its validity
+ */
+ label = bgp_mplsvpn_nh_label_bind_get_label(pi);
+ if (!bgp_is_valid_label(&label)) {
+ if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
+ zlog_debug("u%" PRIu64 ":s%" PRIu64
+ " %pFX is filtered - no valid label",
+ subgrp->update_group->id, subgrp->id,
+ p);
+ return false;
+ }
}
/* Do not send back route to sender. */
struct prefix_rd *prd);
extern struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path);
extern struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path);
+extern bool bgp_path_info_nexthop_changed(struct bgp_path_info *pi,
+ struct peer *to, afi_t afi);
extern struct bgp_path_info *
bgp_get_imported_bpi_ultimate(struct bgp_path_info *info);
extern void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi);
safi);
label_pnt = &label;
num_labels = 1;
+ } else if (safi == SAFI_MPLS_VPN && path &&
+ CHECK_FLAG(path->flags,
+ BGP_PATH_MPLSVPN_NH_LABEL_BIND) &&
+ path->mplsvpn.bmnc.nh_label_bind_cache &&
+ path->peer && path->peer != peer &&
+ path->sub_type != BGP_ROUTE_IMPORTED &&
+ path->sub_type != BGP_ROUTE_STATIC &&
+ bgp_mplsvpn_path_uses_valid_mpls_label(
+ path) &&
+ bgp_path_info_nexthop_changed(path, peer,
+ afi)) {
+ /* Redistributed mpls vpn route between distinct
+ * peers from 'pi->peer' to 'to',
+ * and an mpls label is used in this path,
+ * and there is a nh label bind entry,
+ * then get appropriate mpls local label. When
+ * called here, 'get_label()' returns a valid
+ * label.
+ */
+ label = bgp_mplsvpn_nh_label_bind_get_label(
+ path);
+ label_pnt = &label;
+ num_labels = 1;
} else if (path && path->extra) {
label_pnt = &path->extra->label[0];
num_labels = path->extra->num_labels;