Refactor route subsystem to support multiple routes for each prefix.

This resulted in a substantial refatoring of the route subsystem, including
some minor external API changes. The interface between the manager and the
store has been changed to deal with multiple routes per prefix. The distributed
route store has been updated to be able to distribute route table information.
The route subsystem no longer stores next hop information in the route store.
This information is already available from the host store so the routes system
simply fetches it from there.

Change-Id: I7657b3efb6dcb76afa6f17c931f154a970a16528
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/InternalRouteEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/InternalRouteEvent.java
new file mode 100644
index 0000000..0a70bb0
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/InternalRouteEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017-present 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.incubator.net.routing;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Route event for signalling between the store and the manager.
+ */
+public class InternalRouteEvent extends
+        AbstractEvent<InternalRouteEvent.Type, RouteSet> {
+
+    /**
+     * Internal route event type.
+     */
+    public enum Type {
+        /**
+         * Indicates a route was added to the store.
+         */
+        ROUTE_ADDED,
+
+        /**
+         * Indicates a route was removed from the store.
+         */
+        ROUTE_REMOVED
+    }
+
+    /**
+     * Creates a new internal route event.
+     *
+     * @param type route event type
+     * @param subject route set
+     */
+    public InternalRouteEvent(Type type, RouteSet subject) {
+        super(type, subject);
+    }
+
+    protected InternalRouteEvent(Type type, RouteSet subject, long time) {
+        super(type, subject, time);
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteInfo.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteInfo.java
new file mode 100644
index 0000000..c970681
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteInfo.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017-present 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.incubator.net.routing;
+
+import com.google.common.annotations.Beta;
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Routing information for a given prefix.
+ */
+@Beta
+public class RouteInfo {
+
+    private final IpPrefix prefix;
+    private final ResolvedRoute bestRoute;
+    private final Set<ResolvedRoute> allRoutes;
+
+    /**
+     * Creates a new route info object.
+     *
+     * @param prefix IP prefix
+     * @param bestRoute best route for this prefix if one exists
+     * @param allRoutes all known routes for this prefix
+     */
+    @Beta
+    public RouteInfo(IpPrefix prefix, ResolvedRoute bestRoute, Set<ResolvedRoute> allRoutes) {
+        this.prefix = checkNotNull(prefix);
+        this.bestRoute = bestRoute;
+        this.allRoutes = checkNotNull(allRoutes);
+    }
+
+    /**
+     * Returns the IP prefix.
+     *
+     * @return IP prefix
+     */
+    public IpPrefix prefix() {
+        return prefix;
+    }
+
+    /**
+     * Returns the best route for this prefix if one exists.
+     *
+     * @return optional best route
+     */
+    public Optional<ResolvedRoute> bestRoute() {
+        return Optional.ofNullable(bestRoute);
+    }
+
+    /**
+     * Returns all routes for this prefix.
+     *
+     * @return all routes
+     */
+    public Set<ResolvedRoute> allRoutes() {
+        return allRoutes;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(prefix, bestRoute, allRoutes);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof RouteInfo)) {
+            return false;
+        }
+
+        RouteInfo that = (RouteInfo) other;
+
+        return Objects.equals(this.prefix, that.prefix) &&
+                Objects.equals(this.bestRoute, that.bestRoute) &&
+                Objects.equals(this.allRoutes, that.allRoutes);
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteService.java
index 4fd99d4..4a298ba 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteService.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteService.java
@@ -21,6 +21,7 @@
 
 import java.util.Collection;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 /**
@@ -32,25 +33,55 @@
      * Returns all routes for all route tables in the system.
      *
      * @return map of route table name to routes in that table
+     * @deprecated in Kingfisher release. Use {@link #getRoutes(RouteTableId)}
+     * instead.
      */
+    @Deprecated
     Map<RouteTableId, Collection<Route>> getAllRoutes();
 
     /**
+     * Returns information about all routes in the given route table.
+     *
+     * @param id route table ID
+     * @return collection of route information
+     */
+    Collection<RouteInfo> getRoutes(RouteTableId id);
+
+    /**
+     * Returns the set of route tables in the system.
+     *
+     * @return collection of route table IDs.
+     */
+    Collection<RouteTableId> getRouteTables();
+
+    /**
      * Performs a longest prefix match on the given IP address. The call will
      * return the route with the most specific prefix that contains the given
      * IP address.
      *
      * @param ip IP address
      * @return longest prefix matched route
+     * @deprecated in Kingfisher release. Use {{@link #longestPrefixLookup(IpAddress)}}
+     * instead.
      */
+    @Deprecated
     Route longestPrefixMatch(IpAddress ip);
 
     /**
+     * Performs a longest prefix lookup on the given IP address.
+     *
+     * @param ip IP address to look up
+     * @return most specific matching route, if one exists
+     */
+    Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip);
+
+    /**
      * Returns the routes for the given next hop.
      *
      * @param nextHop next hop IP address
      * @return routes for this next hop
      */
+    @Deprecated
     Collection<Route> getRoutesForNextHop(IpAddress nextHop);
 
     /**
@@ -58,6 +89,7 @@
      *
      * @return set of next hops
      */
+    @Deprecated
     Set<NextHop> getNextHops();
 
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteSet.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteSet.java
new file mode 100644
index 0000000..89c3ce3
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteSet.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017-present 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.incubator.net.routing;
+
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A set of routes for a particular prefix in a route table.
+ */
+public class RouteSet {
+    private final RouteTableId tableId;
+
+    private final IpPrefix prefix;
+    private final Set<Route> routes;
+
+    /**
+     * Creates a new route set.
+     *
+     * @param tableId route table ID
+     * @param prefix IP prefix
+     * @param routes routes for the given prefix
+     */
+    public RouteSet(RouteTableId tableId, IpPrefix prefix, Set<Route> routes) {
+        this.tableId = checkNotNull(tableId);
+        this.prefix = checkNotNull(prefix);
+        this.routes = ImmutableSet.copyOf(checkNotNull(routes));
+    }
+
+    /**
+     * Returns the route table ID.
+     *
+     * @return route table ID
+     */
+    public RouteTableId tableId() {
+        return tableId;
+    }
+
+    /**
+     * Returns the IP prefix.
+     *
+     * @return IP prefix
+     */
+    public IpPrefix prefix() {
+        return prefix;
+    }
+
+    /**
+     * Returns the set of routes.
+     *
+     * @return routes
+     */
+    public Set<Route> routes() {
+        return routes;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(tableId, prefix, routes);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+
+        if (!(other instanceof RouteSet)) {
+            return false;
+        }
+
+        RouteSet that = (RouteSet) other;
+
+        return Objects.equals(this.tableId, that.tableId) &&
+                Objects.equals(this.prefix, that.prefix) &&
+                Objects.equals(this.routes, that.routes);
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStore.java
index 22a6285..27ec1c3 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStore.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStore.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present 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.
@@ -16,7 +16,9 @@
 
 package org.onosproject.incubator.net.routing;
 
+import com.google.common.annotations.Beta;
 import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
 import org.onosproject.store.Store;
 
 import java.util.Collection;
@@ -26,7 +28,7 @@
 /**
  * Unicast route store.
  */
-public interface RouteStore extends Store<RouteEvent, RouteStoreDelegate> {
+public interface RouteStore extends Store<InternalRouteEvent, RouteStoreDelegate> {
 
     /**
      * Adds or updates the given route in the store.
@@ -50,20 +52,12 @@
     Set<RouteTableId> getRouteTables();
 
     /**
-     * Returns the routes for a particular route table.
+     * Returns the routes in the given route table, grouped by prefix.
      *
-     * @param table route table
-     * @return collection of route in the table
+     * @param table route table ID
+     * @return routes
      */
-    Collection<Route> getRoutes(RouteTableId table);
-
-    /**
-     * Performs a longest prefix match with the given IP address.
-     *
-     * @param ip IP to look up
-     * @return longest prefix match route
-     */
-    Route longestPrefixMatch(IpAddress ip);
+    Collection<RouteSet> getRoutes(RouteTableId table);
 
     /**
      * Returns the routes that point to the given next hop IP address.
@@ -71,14 +65,26 @@
      * @param ip IP address of the next hop
      * @return routes for the given next hop
      */
+    // TODO think about including route table info
     Collection<Route> getRoutesForNextHop(IpAddress ip);
 
     /**
+     * Returns the set of routes in the default route table for the given prefix.
+     *
+     * @param prefix IP prefix
+     * @return route set
+     */
+    // TODO needs to be generalizable across route tables
+    @Beta
+    RouteSet getRoutes(IpPrefix prefix);
+
+    /**
      * Updates a next hop information in the store.
      *
      * @param ip IP address
      * @param nextHopData Information of the next hop
      */
+    @Deprecated
     void updateNextHop(IpAddress ip, NextHopData nextHopData);
 
     /**
@@ -87,6 +93,7 @@
      * @param ip IP address
      * @param nextHopData Information of the next hop
      */
+    @Deprecated
     void removeNextHop(IpAddress ip, NextHopData nextHopData);
 
     /**
@@ -95,6 +102,7 @@
      * @param ip next hop IP
      * @return Information of the next hop
      */
+    @Deprecated
     NextHopData getNextHop(IpAddress ip);
 
     /**
@@ -102,5 +110,17 @@
      *
      * @return next hops
      */
+    @Deprecated
     Map<IpAddress, NextHopData> getNextHops();
+
+    /**
+     * Performs a longest prefix match with the given IP address.
+     *
+     * @param ip IP to look up
+     * @return longest prefix match route
+     * @deprecated in Kingfisher release. Now handled by the manager instead of
+     * the store
+     */
+    @Deprecated
+    Route longestPrefixMatch(IpAddress ip);
 }
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStoreDelegate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStoreDelegate.java
index 8b94d82..29a6ee7 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStoreDelegate.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/RouteStoreDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-present 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.
@@ -21,5 +21,5 @@
 /**
  * Route store delegate abstraction.
  */
-public interface RouteStoreDelegate extends StoreDelegate<RouteEvent> {
+public interface RouteStoreDelegate extends StoreDelegate<InternalRouteEvent> {
 }