Move routing from incubator to a separate app
Change-Id: I961d10af99c572b1f8d9b3d37c6f52dd04422007
diff --git a/apps/route-service/api/BUCK b/apps/route-service/api/BUCK
new file mode 100644
index 0000000..68eeacf
--- /dev/null
+++ b/apps/route-service/api/BUCK
@@ -0,0 +1,13 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+]
+
+TEST_DEPS = [
+ '//lib:TEST',
+ '//core/api:onos-api-tests',
+]
+
+osgi_jar_with_tests (
+ deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
+)
diff --git a/apps/route-service/api/pom.xml b/apps/route-service/api/pom.xml
new file mode 100644
index 0000000..f136855
--- /dev/null
+++ b/apps/route-service/api/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2015-present Open Networking Foundation
+ ~
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-app-route-service</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.11.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>onos-app-route-service-api</artifactId>
+ <packaging>bundle</packaging>
+
+ <url>http://onosproject.org</url>
+
+ <description>Route Service Application API</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+
+</project>
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/InternalRouteEvent.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/InternalRouteEvent.java
new file mode 100644
index 0000000..899e54f
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/InternalRouteEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+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/apps/route-service/api/src/main/java/org/onosproject/routeservice/NextHopData.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/NextHopData.java
new file mode 100644
index 0000000..f3b7da7
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/NextHopData.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.Host;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Stores next hop information.
+ */
+public class NextHopData {
+
+ private final MacAddress mac;
+ private final ConnectPoint location;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param mac MAC address
+ * @param location Connect point
+ */
+ public NextHopData(MacAddress mac, ConnectPoint location) {
+ this.mac = mac;
+ this.location = location;
+ }
+
+ /**
+ * Returns the MAC address.
+ *
+ * @return MAC address
+ */
+ public MacAddress mac() {
+ return mac;
+ }
+
+ /**
+ * Returns the location.
+ *
+ * @return Connect point
+ */
+ public ConnectPoint location() {
+ return location;
+ }
+
+ /**
+ * Creates a new instance from a host.
+ *
+ * @param host Host information
+ * @return NextHopData instance
+ */
+ public static NextHopData fromHost(Host host) {
+ return new NextHopData(host.mac(), host.location());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mac, location);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof NextHopData)) {
+ return false;
+ }
+
+ NextHopData that = (NextHopData) other;
+
+ return Objects.equals(this.mac, that.mac) &&
+ Objects.equals(this.location, that.location);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("mac", mac)
+ .add("location", location)
+ .toString();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java
new file mode 100644
index 0000000..828827d
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/ResolvedRoute.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Represents a route with the next hop MAC address resolved.
+ */
+public class ResolvedRoute {
+
+ private final Route route;
+ private final MacAddress nextHopMac;
+ private final VlanId nextHopVlan;
+ private final ConnectPoint location;
+
+ /**
+ * Creates a new resolved route.
+ *
+ * @param route input route
+ * @param nextHopMac next hop MAC address
+ * @param location connect point where the next hop connects to
+ */
+ public ResolvedRoute(Route route, MacAddress nextHopMac, ConnectPoint location) {
+ this(route, nextHopMac, VlanId.NONE, location);
+ }
+
+ /**
+ * Creates a new resolved route.
+ *
+ * @param route input route
+ * @param nextHopMac next hop MAC address
+ * @param nextHopVlan next hop VLAN ID
+ * @param location connect point where the next hop connects to
+ */
+ public ResolvedRoute(Route route, MacAddress nextHopMac, VlanId nextHopVlan,
+ ConnectPoint location) {
+ this.route = route;
+ this.nextHopMac = nextHopMac;
+ this.nextHopVlan = nextHopVlan;
+ this.location = location;
+ }
+
+ /**
+ * Returns the original route.
+ *
+ * @return route
+ */
+ public Route route() {
+ return route;
+ }
+
+ /**
+ * Returns the IP prefix.
+ *
+ * @return IP prefix
+ */
+ public IpPrefix prefix() {
+ return route.prefix();
+ }
+
+ /**
+ * Returns the next hop IP address.
+ *
+ * @return IP address
+ */
+ public IpAddress nextHop() {
+ return route.nextHop();
+ }
+
+ /**
+ * Returns the next hop MAC address.
+ *
+ * @return MAC address
+ */
+ public MacAddress nextHopMac() {
+ return nextHopMac;
+ }
+
+ /**
+ * Returns the next hop VLAN ID.
+ *
+ * @return VLAN ID
+ */
+ public VlanId nextHopVlan() {
+ return nextHopVlan;
+ }
+
+ /**
+ * Returns the next hop location.
+ *
+ * @return connect point where the next hop attaches to
+ */
+ public ConnectPoint location() {
+ return location;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(route, nextHopMac, nextHopVlan, location);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof ResolvedRoute)) {
+ return false;
+ }
+
+ ResolvedRoute that = (ResolvedRoute) other;
+
+ return Objects.equals(this.route, that.route) &&
+ Objects.equals(this.nextHopMac, that.nextHopMac) &&
+ Objects.equals(this.nextHopVlan, that.nextHopVlan) &&
+ Objects.equals(this.location, that.location);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("route", route)
+ .add("nextHopMac", nextHopMac)
+ .add("nextHopVlan", nextHopVlan)
+ .add("location", location)
+ .toString();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/Route.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/Route.java
new file mode 100644
index 0000000..f542252
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/Route.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.cluster.NodeId;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Represents a route.
+ */
+public class Route {
+
+ private static final String VERSION_MISMATCH =
+ "Prefix and next hop must be in the same address family";
+
+ private static final NodeId UNDEFINED = new NodeId("-");
+
+ /**
+ * Source of the route.
+ */
+ public enum Source {
+ /**
+ * Route came from the iBGP route source.
+ */
+ BGP,
+
+ /**
+ * Route came from the FPM route source.
+ */
+ FPM,
+
+ /**
+ * Route can from the static route source.
+ */
+ STATIC,
+
+ /**
+ * Route source was not defined.
+ */
+ UNDEFINED
+ }
+
+ private final Source source;
+ private final IpPrefix prefix;
+ private final IpAddress nextHop;
+ private final NodeId sourceNode;
+
+ /**
+ * Creates a route.
+ *
+ * @param source route source
+ * @param prefix IP prefix
+ * @param nextHop next hop IP address
+ */
+ public Route(Source source, IpPrefix prefix, IpAddress nextHop) {
+ this(source, prefix, nextHop, UNDEFINED);
+ }
+
+ /**
+ * Creates a route.
+ *
+ * @param source route source
+ * @param prefix IP prefix
+ * @param nextHop next hop IP address
+ * @param sourceNode ONOS node the route was sourced from
+ */
+ public Route(Source source, IpPrefix prefix, IpAddress nextHop, NodeId sourceNode) {
+ checkNotNull(prefix);
+ checkNotNull(nextHop);
+ checkArgument(prefix.version().equals(nextHop.version()), VERSION_MISMATCH);
+
+ this.source = checkNotNull(source);
+ this.prefix = prefix;
+ this.nextHop = nextHop;
+ this.sourceNode = checkNotNull(sourceNode);
+ }
+
+ /**
+ * Returns the route source.
+ *
+ * @return route source
+ */
+ public Source source() {
+ return source;
+ }
+
+ /**
+ * Returns the IP prefix of the route.
+ *
+ * @return IP prefix
+ */
+ public IpPrefix prefix() {
+ return prefix;
+ }
+
+ /**
+ * Returns the next hop IP address.
+ *
+ * @return next hop
+ */
+ public IpAddress nextHop() {
+ return nextHop;
+ }
+
+ /**
+ * Returns the ONOS node the route was sourced from.
+ *
+ * @return ONOS node ID
+ */
+ public NodeId sourceNode() {
+ return sourceNode;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(prefix, nextHop);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof Route)) {
+ return false;
+ }
+
+ Route that = (Route) other;
+
+ return Objects.equals(this.prefix, that.prefix) &&
+ Objects.equals(this.nextHop, that.nextHop);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("prefix", prefix)
+ .add("nextHop", nextHop)
+ .toString();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteAdminService.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteAdminService.java
new file mode 100644
index 0000000..8886169
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteAdminService.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import java.util.Collection;
+
+/**
+ * Service allowing mutation of unicast routing state.
+ */
+public interface RouteAdminService extends RouteService {
+
+ /**
+ * Updates the given routes in the route service.
+ *
+ * @param routes collection of routes to update
+ */
+ void update(Collection<Route> routes);
+
+ /**
+ * Withdraws the given routes from the route service.
+ *
+ * @param routes collection of routes to withdraw
+ */
+ void withdraw(Collection<Route> routes);
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteConfig.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteConfig.java
new file mode 100644
index 0000000..cc77b59
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteConfig.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+
+import java.util.Set;
+
+/**
+ * Route configuration object for Route Service.
+ */
+public class RouteConfig extends Config<ApplicationId> {
+ private static final String PREFIX = "prefix";
+ private static final String NEXTHOP = "nextHop";
+
+ /**
+ * Returns all routes in this configuration.
+ *
+ * @return A set of route.
+ */
+ public Set<Route> getRoutes() {
+ ImmutableSet.Builder<Route> routes = ImmutableSet.builder();
+ array.forEach(route -> {
+ try {
+ IpPrefix prefix = IpPrefix.valueOf(route.path(PREFIX).asText());
+ IpAddress nextHop = IpAddress.valueOf(route.path(NEXTHOP).asText());
+ routes.add(new Route(Route.Source.STATIC, prefix, nextHop));
+ } catch (IllegalArgumentException e) {
+ // Ignores routes that cannot be parsed correctly
+ }
+ });
+ return routes.build();
+ }
+
+ @Override
+ public boolean isValid() {
+ array.forEach(routeNode -> {
+ if (!routeNode.isObject()) {
+ throw new IllegalArgumentException("Not object node");
+ }
+ ObjectNode route = (ObjectNode) routeNode;
+ isIpPrefix(route, PREFIX, FieldPresence.MANDATORY);
+ isIpAddress(route, NEXTHOP, FieldPresence.MANDATORY);
+ });
+ return true;
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteEvent.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteEvent.java
new file mode 100644
index 0000000..0428beb
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteEvent.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.joda.time.LocalDateTime;
+import org.onosproject.event.AbstractEvent;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Describes an event about a route.
+ */
+public class RouteEvent extends AbstractEvent<RouteEvent.Type, ResolvedRoute> {
+
+ private final ResolvedRoute prevSubject;
+ private final Collection<ResolvedRoute> alternativeRoutes;
+
+ /**
+ * Route event type.
+ */
+ public enum Type {
+
+ /**
+ * Route is new and the next hop is resolved.
+ * <p>
+ * The subject of this event should be the route being added.
+ * The prevSubject of this event should be null.
+ * </p>
+ */
+ ROUTE_ADDED,
+
+ /**
+ * Route has updated information.
+ * <p>
+ * The subject of this event should be the new route.
+ * The prevSubject of this event should be the old route.
+ * </p>
+ */
+ ROUTE_UPDATED,
+
+ /**
+ * Route was removed or the next hop becomes unresolved.
+ * <p>
+ * The subject of this event should be the route being removed.
+ * The prevSubject of this event should be null.
+ * </p>
+ */
+ ROUTE_REMOVED,
+
+ /**
+ * The set of alternative routes for the subject's prefix has changed,
+ * but the best route is still the same.
+ * <p>
+ * The subject is the best route for the prefix (which has already been
+ * notified in a previous event).
+ * The prevSubject of this event is null.
+ * The alternatives contains the new set of alternative routes.
+ * </p>
+ */
+ ALTERNATIVE_ROUTES_CHANGED
+ }
+
+ /**
+ * Creates a new route event without specifying previous subject.
+ *
+ * @param type event type
+ * @param subject event subject
+ */
+ public RouteEvent(Type type, ResolvedRoute subject) {
+ this(type, subject, null, Collections.emptySet());
+ }
+
+ /**
+ * Creates a new route event without specifying previous subject.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param alternatives alternative routes for subject's prefix
+ */
+ public RouteEvent(Type type, ResolvedRoute subject, Collection<ResolvedRoute> alternatives) {
+ this(type, subject, null, alternatives);
+ }
+
+ /**
+ * Creates a new route event.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param time event time
+ */
+ protected RouteEvent(Type type, ResolvedRoute subject, long time) {
+ super(type, subject, time);
+ this.prevSubject = null;
+
+ this.alternativeRoutes = Collections.emptySet();
+ }
+
+ /**
+ * Creates a new route event with previous subject.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param prevSubject previous subject
+ */
+ public RouteEvent(Type type, ResolvedRoute subject, ResolvedRoute prevSubject) {
+ this(type, subject, prevSubject, Collections.emptySet());
+ }
+
+ /**
+ * Creates a new route event with a previous subject and alternative routes.
+ *
+ * @param type event type
+ * @param subject event subject
+ * @param prevSubject previous subject
+ * @param alternatives alternative routes for subject's prefix
+ */
+ public RouteEvent(Type type, ResolvedRoute subject, ResolvedRoute prevSubject,
+ Collection<ResolvedRoute> alternatives) {
+ super(type, subject);
+ this.prevSubject = prevSubject;
+ this.alternativeRoutes = alternatives;
+ }
+
+ /**
+ * Returns the previous subject of the event.
+ *
+ * @return previous subject to which this event pertains
+ */
+ public ResolvedRoute prevSubject() {
+ return prevSubject;
+ }
+
+ /**
+ * Returns the set of alternative routes for the subject's prefix.
+ *
+ * @return alternative routes
+ */
+ public Collection<ResolvedRoute> alternatives() {
+ return alternativeRoutes;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(subject(), type(), prevSubject(), alternativeRoutes);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (!(other instanceof RouteEvent)) {
+ return false;
+ }
+
+ RouteEvent that = (RouteEvent) other;
+
+ return Objects.equals(this.subject(), that.subject()) &&
+ Objects.equals(this.type(), that.type()) &&
+ Objects.equals(this.prevSubject, that.prevSubject) &&
+ Objects.equals(this.alternativeRoutes, that.alternativeRoutes);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("time", new LocalDateTime(time()))
+ .add("type", type())
+ .add("subject", subject())
+ .add("prevSubject", prevSubject)
+ .add("alternatives", alternativeRoutes)
+ .toString();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteInfo.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteInfo.java
new file mode 100644
index 0000000..0969162
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteInfo.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+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/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteListener.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteListener.java
new file mode 100644
index 0000000..063f335
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for route events.
+ */
+public interface RouteListener extends EventListener<RouteEvent> {
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteService.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteService.java
new file mode 100644
index 0000000..c626e47
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteService.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.event.ListenerService;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Unicast IP route service.
+ */
+public interface RouteService extends ListenerService<RouteEvent, RouteListener> {
+
+ /**
+ * 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 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);
+
+ /**
+ * 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);
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteSet.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteSet.java
new file mode 100644
index 0000000..f464e5d
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteSet.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+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/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStore.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStore.java
new file mode 100644
index 0000000..6866762
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStore.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+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;
+import java.util.Set;
+
+/**
+ * Unicast route store.
+ */
+public interface RouteStore extends Store<InternalRouteEvent, RouteStoreDelegate> {
+
+ /**
+ * Adds or updates the given route in the store.
+ *
+ * @param route route to add or update
+ */
+ void updateRoute(Route route);
+
+ /**
+ * Removes the given route from the store.
+ *
+ * @param route route to remove
+ */
+ void removeRoute(Route route);
+
+ /**
+ * Returns the IDs for all route tables in the store.
+ *
+ * @return route table IDs
+ */
+ Set<RouteTableId> getRouteTables();
+
+ /**
+ * Returns the routes in the given route table, grouped by prefix.
+ *
+ * @param table route table ID
+ * @return routes
+ */
+ Collection<RouteSet> getRoutes(RouteTableId table);
+
+ /**
+ * Returns the routes that point to the given next hop IP address.
+ *
+ * @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);
+
+ /**
+ * Returns the name of this route store.
+ *
+ * @return the name of this route store
+ */
+ default String name() {
+ return getClass().getName();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStoreDelegate.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStoreDelegate.java
new file mode 100644
index 0000000..e9c5b00
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteStoreDelegate.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Route store delegate abstraction.
+ */
+public interface RouteStoreDelegate extends StoreDelegate<InternalRouteEvent> {
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTableId.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTableId.java
new file mode 100644
index 0000000..b522e6c
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTableId.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import java.util.Objects;
+
+/**
+ * Identifier for a routing table.
+ */
+public class RouteTableId {
+ private final String name;
+
+ /**
+ * Creates a new route table ID.
+ *
+ * @param name unique name for the route table
+ */
+ public RouteTableId(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the route table.
+ *
+ * @return table name
+ */
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof RouteTableId) {
+ RouteTableId that = (RouteTableId) obj;
+
+ return Objects.equals(this.name, that.name);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTools.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTools.java
new file mode 100644
index 0000000..5264719
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/RouteTools.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpPrefix;
+
+/**
+ * Routing tools.
+ */
+public final class RouteTools {
+
+ private RouteTools() {
+ }
+
+ /**
+ * Creates a binary string representation of an IP prefix.
+ *
+ * For each string, we put a extra "0" in the front. The purpose of
+ * doing this is to store the default route inside InvertedRadixTree.
+ *
+ * @param ipPrefix the IP prefix to use
+ * @return the binary string representation
+ */
+ public static String createBinaryString(IpPrefix ipPrefix) {
+ byte[] octets = ipPrefix.address().toOctets();
+ StringBuilder result = new StringBuilder(ipPrefix.prefixLength());
+ result.append("0");
+ for (int i = 0; i < ipPrefix.prefixLength(); i++) {
+ int byteOffset = i / Byte.SIZE;
+ int bitOffset = i % Byte.SIZE;
+ int mask = 1 << (Byte.SIZE - 1 - bitOffset);
+ byte value = octets[byteOffset];
+ boolean isSet = ((value & mask) != 0);
+ result.append(isSet ? "1" : "0");
+ }
+ return result.toString();
+ }
+}
diff --git a/apps/route-service/api/src/main/java/org/onosproject/routeservice/package-info.java b/apps/route-service/api/src/main/java/org/onosproject/routeservice/package-info.java
new file mode 100644
index 0000000..5bfe5ba
--- /dev/null
+++ b/apps/route-service/api/src/main/java/org/onosproject/routeservice/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.
+ */
+
+/**
+ * Unicast routing service.
+ */
+package org.onosproject.routeservice;
diff --git a/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteConfigTest.java b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteConfigTest.java
new file mode 100644
index 0000000..1e48420
--- /dev/null
+++ b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteConfigTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.ConfigApplyDelegate;
+
+import java.io.InputStream;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.*;
+
+/**
+ * Tests for class {@link RouteConfigTest}.
+ */
+public class RouteConfigTest {
+ private static final String KEY = "org.onosproject.routing";
+
+ private static final IpPrefix PREFIX1 = IpPrefix.valueOf("10.0.0.1/24");
+ private static final IpPrefix PREFIX2 = IpPrefix.valueOf("20.0.0.1/24");
+ private static final IpPrefix PREFIX3 = IpPrefix.valueOf("30.0.0.1/24");
+ private static final IpAddress NEXTHOP1 = IpAddress.valueOf("192.168.1.1");
+ private static final IpAddress NEXTHOP2 = IpAddress.valueOf("192.168.2.1");
+ private static final Route ROUTE1 = new Route(Route.Source.STATIC, PREFIX1, NEXTHOP1);
+ private static final Route ROUTE2 = new Route(Route.Source.STATIC, PREFIX2, NEXTHOP1);
+ private static final Route ROUTE3 = new Route(Route.Source.STATIC, PREFIX3, NEXTHOP2);
+ private static final Set<Route> EXPECTED_ROUTES = ImmutableSet.of(ROUTE1, ROUTE2, ROUTE3);
+ private static final Set<Route> UNEXPECTED_ROUTES = ImmutableSet.of(ROUTE1, ROUTE2);
+
+ private RouteConfig config;
+
+ @Before
+ public void setUp() throws Exception {
+ InputStream jsonStream = RouteConfigTest.class
+ .getResourceAsStream("/route-config.json");
+ ApplicationId subject = new TestApplicationId(KEY);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode = mapper.readTree(jsonStream);
+ ConfigApplyDelegate delegate = new MockDelegate();
+
+ config = new RouteConfig();
+ config.init(subject, KEY, jsonNode, mapper, delegate);
+ }
+
+ @Test
+ public void getRoutes() throws Exception {
+ assertThat(config.getRoutes(), is(EXPECTED_ROUTES));
+ assertThat(config.getRoutes(), not(UNEXPECTED_ROUTES));
+ }
+
+ private class MockDelegate implements ConfigApplyDelegate {
+ @Override
+ public void onApply(Config config) {
+ }
+ }
+}
diff --git a/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteServiceAdapter.java b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteServiceAdapter.java
new file mode 100644
index 0000000..1d6ec19
--- /dev/null
+++ b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteServiceAdapter.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpAddress;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Adapter class for the route service.
+ */
+public class RouteServiceAdapter implements RouteAdminService {
+ @Override
+ public void update(Collection<Route> routes) {
+
+ }
+
+ @Override
+ public void withdraw(Collection<Route> routes) {
+
+ }
+
+ @Override
+ public Collection<RouteInfo> getRoutes(RouteTableId id) {
+ return null;
+ }
+
+ @Override
+ public Collection<RouteTableId> getRouteTables() {
+ return null;
+ }
+
+ @Override
+ public Route longestPrefixMatch(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public Optional<ResolvedRoute> longestPrefixLookup(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public void addListener(RouteListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(RouteListener listener) {
+
+ }
+}
diff --git a/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteStoreAdapter.java b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteStoreAdapter.java
new file mode 100644
index 0000000..bf9e527
--- /dev/null
+++ b/apps/route-service/api/src/test/java/org/onosproject/routeservice/RouteStoreAdapter.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.routeservice;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Adapter class for the route store.
+ */
+public class RouteStoreAdapter implements RouteStore {
+ @Override
+ public void updateRoute(Route route) {
+
+ }
+
+ @Override
+ public void removeRoute(Route route) {
+
+ }
+
+ @Override
+ public Set<RouteTableId> getRouteTables() {
+ return null;
+ }
+
+ @Override
+ public Collection<RouteSet> getRoutes(RouteTableId table) {
+ return null;
+ }
+
+ @Override
+ public Collection<Route> getRoutesForNextHop(IpAddress ip) {
+ return null;
+ }
+
+ @Override
+ public RouteSet getRoutes(IpPrefix prefix) {
+ return null;
+ }
+
+ @Override
+ public void setDelegate(RouteStoreDelegate delegate) {
+
+ }
+
+ @Override
+ public void unsetDelegate(RouteStoreDelegate delegate) {
+
+ }
+
+ @Override
+ public boolean hasDelegate() {
+ return false;
+ }
+}
diff --git a/apps/route-service/api/src/test/resources/route-config.json b/apps/route-service/api/src/test/resources/route-config.json
new file mode 100644
index 0000000..9675f12
--- /dev/null
+++ b/apps/route-service/api/src/test/resources/route-config.json
@@ -0,0 +1,14 @@
+[
+ {
+ "prefix": "10.0.0.1/24",
+ "nextHop": "192.168.1.1"
+ },
+ {
+ "prefix": "20.0.0.1/24",
+ "nextHop": "192.168.1.1"
+ },
+ {
+ "prefix": "30.0.0.1/24",
+ "nextHop": "192.168.2.1"
+ }
+]
\ No newline at end of file