diff options
Diffstat (limited to 'framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java')
-rw-r--r-- | framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java b/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java new file mode 100644 index 00000000..ec020230 --- /dev/null +++ b/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java @@ -0,0 +1,202 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.routing.bgp; + +import org.onlab.packet.IpPrefix; +import org.onosproject.routing.RouteUpdate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.LinkedList; + +/** + * Class to receive and process the BGP routes from each BGP Session/Peer. + */ +class BgpRouteSelector { + private static final Logger log = + LoggerFactory.getLogger(BgpRouteSelector.class); + + private BgpSessionManager bgpSessionManager; + + /** + * Constructor. + * + * @param bgpSessionManager the BGP Session Manager to use + */ + BgpRouteSelector(BgpSessionManager bgpSessionManager) { + this.bgpSessionManager = bgpSessionManager; + } + + /** + * Processes route entry updates: added/updated and deleted route + * entries. + * + * @param bgpSession the BGP session the route entry updates were + * received on + * @param addedBgpRouteEntries the added/updated route entries to process + * @param deletedBgpRouteEntries the deleted route entries to process + */ + synchronized void routeUpdates(BgpSession bgpSession, + Collection<BgpRouteEntry> addedBgpRouteEntries, + Collection<BgpRouteEntry> deletedBgpRouteEntries) { + Collection<RouteUpdate> routeUpdates = new LinkedList<>(); + RouteUpdate routeUpdate; + + if (bgpSessionManager.isShutdown()) { + return; // Ignore any leftover updates if shutdown + } + // Process the deleted route entries + for (BgpRouteEntry bgpRouteEntry : deletedBgpRouteEntries) { + routeUpdate = processDeletedRoute(bgpSession, bgpRouteEntry); + if (routeUpdate != null) { + routeUpdates.add(routeUpdate); + } + } + + // Process the added/updated route entries + for (BgpRouteEntry bgpRouteEntry : addedBgpRouteEntries) { + routeUpdate = processAddedRoute(bgpSession, bgpRouteEntry); + if (routeUpdate != null) { + routeUpdates.add(routeUpdate); + } + } + bgpSessionManager.getRouteListener().update(routeUpdates); + } + + /** + * Processes an added/updated route entry. + * + * @param bgpSession the BGP session the route entry update was received on + * @param bgpRouteEntry the added/updated route entry + * @return the result route update that should be forwarded to the + * Route Listener, or null if no route update should be forwarded + */ + private RouteUpdate processAddedRoute(BgpSession bgpSession, + BgpRouteEntry bgpRouteEntry) { + RouteUpdate routeUpdate; + BgpRouteEntry bestBgpRouteEntry = + bgpSessionManager.findBgpRoute(bgpRouteEntry.prefix()); + + // + // Install the new route entry if it is better than the + // current best route. + // + if ((bestBgpRouteEntry == null) || + bgpRouteEntry.isBetterThan(bestBgpRouteEntry)) { + bgpSessionManager.addBgpRoute(bgpRouteEntry); + routeUpdate = + new RouteUpdate(RouteUpdate.Type.UPDATE, bgpRouteEntry); + return routeUpdate; + } + + // + // If the route entry arrived on the same BGP Session as + // the current best route, then elect the next best route + // and install it. + // + if (bestBgpRouteEntry.getBgpSession() != + bgpRouteEntry.getBgpSession()) { + return null; // Nothing to do + } + + // Find the next best route + bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix()); + if (bestBgpRouteEntry == null) { + // + // TODO: Shouldn't happen. Install the new route as a + // pre-caution. + // + log.debug("BGP next best route for prefix {} is missing. " + + "Adding the route that is currently processed.", + bgpRouteEntry.prefix()); + bestBgpRouteEntry = bgpRouteEntry; + } + + // Install the next best route + bgpSessionManager.addBgpRoute(bestBgpRouteEntry); + routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE, + bestBgpRouteEntry); + return routeUpdate; + } + + /** + * Processes a deleted route entry. + * + * @param bgpSession the BGP session the route entry update was received on + * @param bgpRouteEntry the deleted route entry + * @return the result route update that should be forwarded to the + * Route Listener, or null if no route update should be forwarded + */ + private RouteUpdate processDeletedRoute(BgpSession bgpSession, + BgpRouteEntry bgpRouteEntry) { + RouteUpdate routeUpdate; + BgpRouteEntry bestBgpRouteEntry = + bgpSessionManager.findBgpRoute(bgpRouteEntry.prefix()); + + // + // Remove the route entry only if it was the best one. + // Install the the next best route if it exists. + // + // NOTE: We intentionally use "==" instead of method equals(), + // because we need to check whether this is same object. + // + if (bgpRouteEntry != bestBgpRouteEntry) { + return null; // Nothing to do + } + + // + // Find the next best route + // + bestBgpRouteEntry = findBestBgpRoute(bgpRouteEntry.prefix()); + if (bestBgpRouteEntry != null) { + // Install the next best route + bgpSessionManager.addBgpRoute(bestBgpRouteEntry); + routeUpdate = new RouteUpdate(RouteUpdate.Type.UPDATE, + bestBgpRouteEntry); + return routeUpdate; + } + + // + // No route found. Remove the route entry + // + bgpSessionManager.removeBgpRoute(bgpRouteEntry.prefix()); + routeUpdate = new RouteUpdate(RouteUpdate.Type.DELETE, bgpRouteEntry); + return routeUpdate; + } + + /** + * Finds the best route entry among all BGP Sessions. + * + * @param prefix the prefix of the route + * @return the best route if found, otherwise null + */ + private BgpRouteEntry findBestBgpRoute(IpPrefix prefix) { + BgpRouteEntry bestRoute = null; + + // Iterate across all BGP Sessions and select the best route + for (BgpSession bgpSession : bgpSessionManager.getBgpSessions()) { + BgpRouteEntry route = bgpSession.findBgpRoute(prefix); + if (route == null) { + continue; + } + if ((bestRoute == null) || route.isBetterThan(bestRoute)) { + bestRoute = route; + } + } + return bestRoute; + } +} |