Carry location of next hop in ResolvedRoute

Change-Id: I64ca6ecc5cfcffc3ed19621053b0ee266c4093ea
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
index c036d8c..a295a14 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/SingleSwitchFibInstaller.java
@@ -215,7 +215,7 @@
 
         //clean up the routes.
         for (Map.Entry<IpPrefix, IpAddress> routes: prefixToNextHop.entrySet()) {
-            deleteRoute(new ResolvedRoute(routes.getKey(), null, null));
+            deleteRoute(new ResolvedRoute(routes.getKey(), null, null, null));
         }
 
         //clean up the filtering objective for interfaces.
diff --git a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
index 2621c9d..2b60f91 100644
--- a/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
+++ b/apps/routing/src/test/java/org/onosproject/routing/impl/SingleSwitchFibInstallerTest.java
@@ -279,7 +279,7 @@
      */
     @Test
     public void testRouteAdd() {
-        ResolvedRoute resolvedRoute = new ResolvedRoute(PREFIX1, NEXT_HOP1, MAC1);
+        ResolvedRoute resolvedRoute = new ResolvedRoute(PREFIX1, NEXT_HOP1, MAC1, SW1_ETH1);
 
         // Create the next objective
         NextObjective nextObjective = createNextObjective(MAC1, MAC1, SW1_ETH1.port(), VlanId.NONE, true);
@@ -305,7 +305,7 @@
      */
     @Test
     public void testRouteAddWithVlan() {
-        ResolvedRoute route = new ResolvedRoute(PREFIX1, NEXT_HOP2, MAC2);
+        ResolvedRoute route = new ResolvedRoute(PREFIX1, NEXT_HOP2, MAC2, SW1_ETH2);
 
         // Create the next objective
         NextObjective nextObjective = createNextObjective(MAC2, MAC2, SW1_ETH2.port(), VLAN1, true);
@@ -335,7 +335,7 @@
         testRouteAdd();
         reset(flowObjectiveService);
 
-        ResolvedRoute route = new ResolvedRoute(PREFIX1, NEXT_HOP2, MAC2);
+        ResolvedRoute route = new ResolvedRoute(PREFIX1, NEXT_HOP2, MAC2, SW1_ETH2);
 
         // Create the next objective
         NextObjective nextObjective = createNextObjective(MAC2, MAC2, SW1_ETH2.port(), VLAN1, true);
@@ -365,7 +365,7 @@
         testRouteAdd();
 
         // Construct the existing route
-        ResolvedRoute route = new ResolvedRoute(PREFIX1, null, null);
+        ResolvedRoute route = new ResolvedRoute(PREFIX1, null, null, null);
 
         // Create the flow objective
         reset(flowObjectiveService);
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
index 762ce52..a764c83 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/SdnIpFibTest.java
@@ -191,7 +191,7 @@
     @Test
     public void testRouteAddToNoVlan() {
         // Build the expected route
-        ResolvedRoute route = new ResolvedRoute(PREFIX1, IP3, MAC3);
+        ResolvedRoute route = new ResolvedRoute(PREFIX1, IP3, MAC3, SW3_ETH1);
 
         MultiPointToSinglePointIntent intent =
                 createIntentToThreeSrcOneTwo(PREFIX1);
@@ -215,7 +215,7 @@
     @Test
     public void testRouteAddToVlan() {
         // Build the expected route
-        ResolvedRoute route = new ResolvedRoute(PREFIX2, IP1, MAC1);
+        ResolvedRoute route = new ResolvedRoute(PREFIX2, IP1, MAC1, SW1_ETH1);
 
         MultiPointToSinglePointIntent intent = createIntentToOne(PREFIX2);
 
@@ -244,7 +244,7 @@
         testRouteAddToNoVlan();
 
         // Build the new route entries for prefix1 and prefix2
-        ResolvedRoute routePrefixOne = new ResolvedRoute(PREFIX1, IP1, MAC1);
+        ResolvedRoute routePrefixOne = new ResolvedRoute(PREFIX1, IP1, MAC1, SW1_ETH1);
 
         // Create the new expected intents
         MultiPointToSinglePointIntent newPrefixOneIntent = createIntentToOne(PREFIX1);
@@ -278,7 +278,7 @@
         testRouteAddToVlan();
 
         // Build the new route entries for prefix1 and prefix2
-        ResolvedRoute routePrefix = new ResolvedRoute(PREFIX2, IP3, MAC3);
+        ResolvedRoute routePrefix = new ResolvedRoute(PREFIX2, IP3, MAC3, SW3_ETH1);
 
         // Create the new expected intents
         MultiPointToSinglePointIntent newPrefixIntent =
@@ -310,7 +310,7 @@
         testRouteAddToNoVlan();
 
         // Construct the existing route entry
-        ResolvedRoute route = new ResolvedRoute(PREFIX1, null, null);
+        ResolvedRoute route = new ResolvedRoute(PREFIX1, null, null, null);
 
         // Create existing intent
         MultiPointToSinglePointIntent removedIntent =
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/NextHopData.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/NextHopData.java
new file mode 100644
index 0000000..2f05200
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/NextHopData.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016-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.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/incubator/api/src/main/java/org/onosproject/incubator/net/routing/ResolvedRoute.java b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/ResolvedRoute.java
index 68f2feb..d6cb4b4 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/routing/ResolvedRoute.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/routing/ResolvedRoute.java
@@ -19,6 +19,7 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
 
 import java.util.Objects;
 
@@ -32,17 +33,20 @@
     private final IpPrefix prefix;
     private final IpAddress nextHop;
     private final MacAddress nextHopMac;
+    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) {
+    public ResolvedRoute(Route route, MacAddress nextHopMac, ConnectPoint location) {
         this.prefix = route.prefix();
         this.nextHop = route.nextHop();
         this.nextHopMac = nextHopMac;
+        this.location = location;
     }
 
     /**
@@ -51,11 +55,14 @@
      * @param prefix route prefix
      * @param nextHop route next hop IP address
      * @param nextHopMac next hop MAC address
+     * @param location connect point where the next hop connects to
      */
-    public ResolvedRoute(IpPrefix prefix, IpAddress nextHop, MacAddress nextHopMac) {
+    public ResolvedRoute(IpPrefix prefix, IpAddress nextHop, MacAddress nextHopMac,
+                         ConnectPoint location) {
         this.prefix = prefix;
         this.nextHop = nextHop;
         this.nextHopMac = nextHopMac;
+        this.location = location;
     }
 
     /**
@@ -85,9 +92,18 @@
         return nextHopMac;
     }
 
+    /**
+     * 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(prefix, nextHop, nextHopMac);
+        return Objects.hash(prefix, nextHop, nextHopMac, location);
     }
 
     @Override
@@ -104,7 +120,8 @@
 
         return Objects.equals(this.prefix, that.prefix) &&
                 Objects.equals(this.nextHop, that.nextHop) &&
-                Objects.equals(this.nextHopMac, that.nextHopMac);
+                Objects.equals(this.nextHopMac, that.nextHopMac) &&
+                Objects.equals(this.location, that.location);
     }
 
     @Override
@@ -113,6 +130,7 @@
                 .add("prefix", prefix)
                 .add("nextHop", nextHop)
                 .add("nextHopMac", nextHopMac)
+                .add("location", location)
                 .toString();
     }
 }
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 9b75099..9eac65c 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
@@ -17,7 +17,6 @@
 package org.onosproject.incubator.net.routing;
 
 import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
 import org.onosproject.store.Store;
 
 import java.util.Collection;
@@ -78,30 +77,30 @@
      * Updates a next hop IP and MAC in the store.
      *
      * @param ip IP address
-     * @param mac MAC address
+     * @param nextHopData Information of the next hop
      */
-    void updateNextHop(IpAddress ip, MacAddress mac);
+    void updateNextHop(IpAddress ip, NextHopData nextHopData);
 
     /**
      * Removes a next hop IP and MAC from the store.
      *
      * @param ip IP address
-     * @param mac MAC address
+     * @param nextHopData Information of the next hop
      */
-    void removeNextHop(IpAddress ip, MacAddress mac);
+    void removeNextHop(IpAddress ip, NextHopData nextHopData);
 
     /**
      * Returns the MAC address of the given next hop.
      *
      * @param ip next hop IP
-     * @return MAC address
+     * @return Information of the next hop
      */
-    MacAddress getNextHop(IpAddress ip);
+    NextHopData getNextHop(IpAddress ip);
 
     /**
      * Returns all next hops in the route store.
      *
      * @return next hops
      */
-    Map<IpAddress, MacAddress> getNextHops();
+    Map<IpAddress, NextHopData> getNextHops();
 }
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/routing/impl/RouteManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/routing/impl/RouteManager.java
index a362316..4c0f59e 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/routing/impl/RouteManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/routing/impl/RouteManager.java
@@ -23,8 +23,8 @@
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
 import org.onosproject.event.ListenerService;
+import org.onosproject.incubator.net.routing.NextHopData;
 import org.onosproject.incubator.net.routing.NextHop;
 import org.onosproject.incubator.net.routing.ResolvedRoute;
 import org.onosproject.incubator.net.routing.Route;
@@ -118,9 +118,12 @@
             routeStore.getRouteTables().forEach(table -> {
                 Collection<Route> routes = routeStore.getRoutes(table);
                 if (routes != null) {
-                    routes.forEach(route ->
-                        l.post(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED,
-                                        new ResolvedRoute(route, routeStore.getNextHop(route.nextHop())))));
+                    routes.forEach(route -> {
+                        NextHopData nextHopData = routeStore.getNextHop(route.nextHop());
+                            l.post(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED,
+                                    new ResolvedRoute(route, nextHopData.mac(),
+                                            nextHopData.location())));
+                    });
                 }
             });
 
@@ -174,7 +177,7 @@
     @Override
     public Set<NextHop> getNextHops() {
         return routeStore.getNextHops().entrySet().stream()
-                .map(entry -> new NextHop(entry.getKey(), entry.getValue()))
+                .map(entry -> new NextHop(entry.getKey(), entry.getValue().mac()))
                 .collect(Collectors.toSet());
     }
 
@@ -203,24 +206,24 @@
         // Monitor the IP address for updates of the MAC address
         hostService.startMonitoringIp(route.nextHop());
 
-        MacAddress nextHopMac = routeStore.getNextHop(route.nextHop());
-        if (nextHopMac == null) {
+        NextHopData nextHopData = routeStore.getNextHop(route.nextHop());
+        if (nextHopData == null) {
             Set<Host> hosts = hostService.getHostsByIp(route.nextHop());
             Optional<Host> host = hosts.stream().findFirst();
             if (host.isPresent()) {
-                nextHopMac = host.get().mac();
+                nextHopData = NextHopData.fromHost(host.get());
             }
         }
 
-        if (nextHopMac != null) {
-            routeStore.updateNextHop(route.nextHop(), nextHopMac);
+        if (nextHopData != null) {
+            routeStore.updateNextHop(route.nextHop(), nextHopData);
         }
     }
 
     private void hostUpdated(Host host) {
         synchronized (this) {
             for (IpAddress ip : host.ipAddresses()) {
-                routeStore.updateNextHop(ip, host.mac());
+                routeStore.updateNextHop(ip, NextHopData.fromHost(host));
             }
         }
     }
@@ -228,7 +231,7 @@
     private void hostRemoved(Host host) {
         synchronized (this) {
             for (IpAddress ip : host.ipAddresses()) {
-                routeStore.removeNextHop(ip, host.mac());
+                routeStore.removeNextHop(ip, NextHopData.fromHost(host));
             }
         }
     }
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/routing/impl/RouteManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/routing/impl/RouteManagerTest.java
index 9393062..86ba6f6 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/routing/impl/RouteManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/routing/impl/RouteManagerTest.java
@@ -178,12 +178,12 @@
     @Test
     public void testRouteAdd() {
         Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);
-        ResolvedRoute resolvedRoute = new ResolvedRoute(route, MAC1);
+        ResolvedRoute resolvedRoute = new ResolvedRoute(route, MAC1, CP1);
 
         verifyRouteAdd(route, resolvedRoute);
 
         route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1);
-        resolvedRoute = new ResolvedRoute(route, MAC3);
+        resolvedRoute = new ResolvedRoute(route, MAC3, CP1);
 
         verifyRouteAdd(route, resolvedRoute);
     }
@@ -215,7 +215,7 @@
     public void testRouteUpdate() {
         Route route = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP1);
         Route updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX1, V4_NEXT_HOP2);
-        ResolvedRoute updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2);
+        ResolvedRoute updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2, CP1);
 
         verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute);
 
@@ -223,13 +223,13 @@
         // In this case we expect to receive a ROUTE_UPDATED event.
         route = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP1);
         updatedRoute = new Route(Route.Source.STATIC, V4_PREFIX2, V4_NEXT_HOP2);
-        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2);
+        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC2, CP1);
 
         verifyRouteUpdated(route, updatedRoute, updatedResolvedRoute);
 
         route = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP1);
         updatedRoute = new Route(Route.Source.STATIC, V6_PREFIX1, V6_NEXT_HOP2);
-        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC4);
+        updatedResolvedRoute = new ResolvedRoute(updatedRoute, MAC4, CP1);
 
         verifyRouteRemoveThenAdd(route, updatedRoute, updatedResolvedRoute);
     }
@@ -248,7 +248,8 @@
         // First add the original route
         addRoute(original);
 
-        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED, new ResolvedRoute(original, null)));
+        routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
+                new ResolvedRoute(original, null, null)));
         expectLastCall().once();
         routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED, updatedResolvedRoute));
         expectLastCall().once();
@@ -308,7 +309,7 @@
         addRoute(route);
 
         RouteEvent withdrawRouteEvent = new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
-                new ResolvedRoute(route, null));
+                new ResolvedRoute(route, null, null));
 
         reset(routeListener);
         routeListener.event(withdrawRouteEvent);
@@ -346,7 +347,7 @@
         // Now when we send the event, we expect the FIB update to be sent
         reset(routeListener);
         routeListener.event(new RouteEvent(RouteEvent.Type.ROUTE_ADDED,
-                new ResolvedRoute(route, MAC1)));
+                new ResolvedRoute(route, MAC1, CP1)));
         replay(routeListener);
 
         // Send in the host event
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/routing/impl/LocalRouteStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/routing/impl/LocalRouteStore.java
index d687327..a1e3120 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/routing/impl/LocalRouteStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/routing/impl/LocalRouteStore.java
@@ -29,7 +29,7 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MacAddress;
+import org.onosproject.incubator.net.routing.NextHopData;
 import org.onosproject.incubator.net.routing.ResolvedRoute;
 import org.onosproject.incubator.net.routing.Route;
 import org.onosproject.incubator.net.routing.RouteEvent;
@@ -63,7 +63,7 @@
     private static final RouteTableId IPV4 = new RouteTableId("ipv4");
     private static final RouteTableId IPV6 = new RouteTableId("ipv6");
 
-    private Map<IpAddress, MacAddress> nextHops = new ConcurrentHashMap<>();
+    private Map<IpAddress, NextHopData> nextHops = new ConcurrentHashMap<>();
 
     @Activate
     public void activate() {
@@ -114,42 +114,42 @@
     }
 
     @Override
-    public void updateNextHop(IpAddress ip, MacAddress mac) {
+    public void updateNextHop(IpAddress ip, NextHopData nextHopData) {
         Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip);
 
-        if (!routes.isEmpty() && !mac.equals(nextHops.get(ip))) {
-            MacAddress oldMac = nextHops.put(ip, mac);
+        if (!routes.isEmpty() && !nextHopData.equals(nextHops.get(ip))) {
+            NextHopData oldNextHop = nextHops.put(ip, nextHopData);
 
             for (Route route : routes) {
-                if (oldMac == null) {
+                if (oldNextHop == null) {
                     notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_ADDED,
-                            new ResolvedRoute(route, mac)));
+                            new ResolvedRoute(route, nextHopData.mac(), nextHopData.location())));
                 } else {
                     notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED,
-                            new ResolvedRoute(route, mac)));
+                            new ResolvedRoute(route, nextHopData.mac(), nextHopData.location())));
                 }
             }
         }
     }
 
     @Override
-    public void removeNextHop(IpAddress ip, MacAddress mac) {
-        if (nextHops.remove(ip, mac)) {
+    public void removeNextHop(IpAddress ip, NextHopData nextHopData) {
+        if (nextHops.remove(ip, nextHopData)) {
             Collection<Route> routes = getDefaultRouteTable(ip).getRoutesForNextHop(ip);
             for (Route route : routes) {
                 notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
-                        new ResolvedRoute(route, null)));
+                        new ResolvedRoute(route, null, null)));
             }
         }
     }
 
     @Override
-    public MacAddress getNextHop(IpAddress ip) {
+    public NextHopData getNextHop(IpAddress ip) {
         return nextHops.get(ip);
     }
 
     @Override
-    public Map<IpAddress, MacAddress> getNextHops() {
+    public Map<IpAddress, NextHopData> getNextHops() {
         return ImmutableMap.copyOf(nextHops);
     }
 
@@ -223,25 +223,25 @@
                     return;
                 }
 
-                MacAddress nextHopMac = nextHops.get(route.nextHop());
+                NextHopData nextHopData = nextHops.get(route.nextHop());
 
                 if (oldRoute != null && !oldRoute.nextHop().equals(route.nextHop())) {
-                    if (nextHopMac == null) {
+                    if (nextHopData == null) {
                         // We don't know the new MAC address yet so delete the route
                         notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
-                                new ResolvedRoute(oldRoute, null)));
+                                new ResolvedRoute(oldRoute, null, null)));
                     } else {
                         // We know the new MAC address so update the route
                         notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_UPDATED,
-                                new ResolvedRoute(route, nextHopMac)));
+                                new ResolvedRoute(route, nextHopData.mac(), nextHopData.location())));
                     }
                     return;
                 }
 
 
-                if (nextHopMac != null) {
+                if (nextHopData != null) {
                     notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_ADDED,
-                            new ResolvedRoute(route, nextHopMac)));
+                            new ResolvedRoute(route, nextHopData.mac(), nextHopData.location())));
                 }
             }
         }
@@ -259,7 +259,7 @@
                 if (removed != null) {
                     reverseIndex.remove(removed.nextHop(), removed);
                     notifyDelegate(new RouteEvent(RouteEvent.Type.ROUTE_REMOVED,
-                            new ResolvedRoute(route, null)));
+                            new ResolvedRoute(route, null, null)));
                 }
             }
         }