hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
}
+static void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
+ safi_t safi)
+{
+ struct bgp_node *rn, *nrn;
+
+ for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
+ rn = bgp_route_next(rn)) {
+ if (rn->info != NULL) {
+ /* Special handling for 2-level routing
+ * tables. */
+ if (safi == SAFI_MPLS_VPN
+ || safi == SAFI_ENCAP
+ || safi == SAFI_EVPN) {
+ for (nrn = bgp_table_top((
+ struct bgp_table
+ *)(rn->info));
+ nrn;
+ nrn = bgp_route_next(nrn))
+ bgp_process(bgp, nrn,
+ afi, safi);
+ } else
+ bgp_process(bgp, rn, afi, safi);
+ }
+ }
+}
+
/* Force a bestpath recalculation for all prefixes. This is used
* when 'bgp bestpath' commands are entered.
*/
{
afi_t afi;
safi_t safi;
- struct bgp_node *rn, *nrn;
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
- rn = bgp_route_next(rn)) {
- if (rn->info != NULL) {
- /* Special handling for 2-level routing
- * tables. */
- if (safi == SAFI_MPLS_VPN
- || safi == SAFI_ENCAP
- || safi == SAFI_EVPN) {
- for (nrn = bgp_table_top((
- struct bgp_table
- *)(rn->info));
- nrn;
- nrn = bgp_route_next(nrn))
- bgp_process(bgp, nrn,
- afi, safi);
- } else
- bgp_process(bgp, rn, afi, safi);
- }
- }
+ bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
}
}
}
return peer;
}
+/*
+ * Return true if we have a peer configured to use this afi/safi
+ */
+int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+ struct listnode *node;
+ struct peer *peer;
+
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+ continue;
+
+ if (peer->afc[afi][safi])
+ return 1;
+ }
+
+ return 0;
+}
+
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
struct peer_group *group;
struct listnode *node, *nnode;
struct peer *tmp_peer;
+ struct bgp *bgp;
/* Nothing to do if we've already activated this peer */
if (peer->afc[afi][safi])
return ret;
+ bgp = peer->bgp;
+
/* This is a peer-group so activate all of the members of the
* peer-group as well */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
ret |= non_peergroup_activate_af(peer, afi, safi);
}
+ /* If this is the first peer to be activated for this afi/labeled-unicast
+ * recalc bestpaths to trigger label allocation */
+ if (safi == SAFI_LABELED_UNICAST && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_info("peer(s) are now active for labeled-unicast, allocate MPLS labels");
+
+ bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
+ bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
+ }
+
return ret;
}
struct peer_group *group;
struct peer *tmp_peer;
struct listnode *node, *nnode;
+ struct bgp *bgp;
/* Nothing to do if we've already de-activated this peer */
if (!peer->afc[afi][safi])
ret |= non_peergroup_deactivate_af(peer, afi, safi);
}
+ bgp = peer->bgp;
+
+ /* If this is the last peer to be deactivated for this afi/labeled-unicast
+ * recalc bestpaths to trigger label deallocation */
+ if (safi == SAFI_LABELED_UNICAST &&
+ bgp->allocate_mpls_labels[afi][SAFI_UNICAST] &&
+ !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_info("peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
+
+ bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
+ bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
+ }
return ret;
}
* routes to be processed still referencing the struct bgp.
*/
listnode_delete(bm->bgp, bgp);
+ if (list_isempty(bm->bgp))
+ bgp_close();
/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))