aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteSelector.java
diff options
context:
space:
mode:
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.java202
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;
+ }
+}