Moved ProxyArp, SDN-IP and BgpRouter to use new config format.

The new config format is based on the new network configuration subsystem.

Includes a few config fixes to NetworkConfigLoader and InterfaceManager.

Change-Id: Id7f766736decb7afb6b63c2731d3baba9fc7c764
diff --git a/apps/bgprouter/pom.xml b/apps/bgprouter/pom.xml
index 86c0125..d3f6f52 100644
--- a/apps/bgprouter/pom.xml
+++ b/apps/bgprouter/pom.xml
@@ -49,6 +49,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
@@ -64,6 +69,6 @@
             <artifactId>onos-app-proxyarp</artifactId>
             <version>${project.version}</version>
         </dependency>
- 
+
     </dependencies>
 </project>
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
index 9a6680e..e5388d2 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/BgpRouter.java
@@ -20,7 +20,6 @@
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multiset;
-
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -29,9 +28,11 @@
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
-import org.onosproject.config.NetworkConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
@@ -56,15 +57,14 @@
 import org.onosproject.routing.FibListener;
 import org.onosproject.routing.FibUpdate;
 import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.BgpSpeaker;
-import org.onosproject.routing.config.Interface;
-import org.onosproject.routing.config.RoutingConfigurationService;
+import org.onosproject.routing.config.BgpConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 /* For test only - will be removed before Cardinal release
@@ -95,7 +95,10 @@
     protected RoutingService routingService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected RoutingConfigurationService configService;
+    protected InterfaceService interfaceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigService networkConfigService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PacketService packetService;
@@ -106,14 +109,6 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected DeviceService deviceService;
 
-    //
-    // NOTE: Unused reference - needed to guarantee that the
-    // NetworkConfigReader component is activated and the network configuration
-    // is read.
-    //
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected NetworkConfigService networkConfigService;
-
     private ApplicationId appId;
 
     // Reference count for how many times a next hop is used by a route
@@ -145,14 +140,25 @@
     @Activate
     protected void activate() {
         appId = coreService.registerApplication(BGP_ROUTER_APP);
-        getDeviceConfiguration(configService.getBgpSpeakers());
+
+        ApplicationId routerAppId = coreService.getAppId(RoutingService.ROUTER_APP_ID);
+        BgpConfig bgpConfig =
+                networkConfigService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
+
+        if (bgpConfig == null) {
+            log.error("No BgpConfig found");
+            return;
+        }
+
+        getDeviceConfiguration(bgpConfig);
 
         connectivityManager = new TunnellingConnectivityManager(appId,
-                                                                configService,
+                                                                bgpConfig,
+                                                                interfaceService,
                                                                 packetService,
                                                                 flowObjectiveService);
 
-        icmpHandler = new IcmpHandler(configService, packetService);
+        icmpHandler = new IcmpHandler(interfaceService, packetService);
         deviceListener = new InnerDeviceListener();
         routingService.addFibListener(new InternalFibListener());
         routingService.start();
@@ -162,7 +168,7 @@
 
         // Initialize devices now if they are already connected
         if (deviceService.isAvailable(deviceId)) {
-            processIntfFilters(true, configService.getInterfaces());
+            processIntfFilters(true, interfaceService.getInterfaces());
         }
 
         if (deviceService.isAvailable(ctrlDeviceId)) {
@@ -182,21 +188,36 @@
         log.info("BgpRouter stopped");
     }
 
-    private void getDeviceConfiguration(Map<String, BgpSpeaker> bgps) {
-        if (bgps == null || bgps.values().isEmpty()) {
-            log.error("BGP speakers configuration is missing");
+    private void getDeviceConfiguration(BgpConfig bgpConfig) {
+        Optional<BgpConfig.BgpSpeakerConfig> bgpSpeaker =
+                bgpConfig.bgpSpeakers().stream().findAny();
+
+        if (!bgpSpeaker.isPresent()) {
+            log.error("BGP speaker configuration not found");
             return;
         }
-        for (BgpSpeaker s : bgps.values()) {
-            ctrlDeviceId = s.connectPoint().deviceId();
-            if (s.interfaceAddresses() == null || s.interfaceAddresses().isEmpty()) {
-                log.error("BGP Router must have interfaces configured");
-                return;
-            }
-            deviceId = s.interfaceAddresses().get(0).connectPoint().deviceId();
-            break;
+
+        ctrlDeviceId = bgpSpeaker.get().connectPoint().deviceId();
+
+        Optional<IpAddress> peerAddress =
+                bgpSpeaker.get().peers().stream().findAny();
+
+        if (!peerAddress.isPresent()) {
+            log.error("BGP speaker must have peers configured");
+            return;
         }
 
+        Interface intf = interfaceService.getMatchingInterface(peerAddress.get());
+
+        if (intf == null) {
+            log.error("No interface found for peer");
+            return;
+        }
+
+        // Assume all peers are configured on the same device - this is required
+        // by the BGP router
+        deviceId = intf.connectPoint().deviceId();
+
         log.info("Router dpid: {}", deviceId);
         log.info("Control Plane OVS dpid: {}", ctrlDeviceId);
     }
@@ -283,7 +304,7 @@
         if (nextHopsCount.count(entry.nextHopIp()) == 0) {
             // There was no next hop in the multiset
 
-            Interface egressIntf = configService.getMatchingInterface(entry.nextHopIp());
+            Interface egressIntf = interfaceService.getMatchingInterface(entry.nextHopIp());
             if (egressIntf == null) {
                 log.warn("no egress interface found for {}", entry);
                 return;
@@ -405,7 +426,7 @@
                     if (deviceService.isAvailable(event.subject().id())) {
                         log.info("Device connected {}", event.subject().id());
                         if (event.subject().id().equals(deviceId)) {
-                            processIntfFilters(true, configService.getInterfaces());
+                            processIntfFilters(true, interfaceService.getInterfaces());
 
                             /* For test only - will be removed before Cardinal release
                             delay(1000);
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/IcmpHandler.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/IcmpHandler.java
index 5e52b15..8826535 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/IcmpHandler.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/IcmpHandler.java
@@ -19,6 +19,8 @@
 import org.onlab.packet.ICMP;
 import org.onlab.packet.IPv4;
 import org.onlab.packet.IpAddress;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
@@ -29,8 +31,6 @@
 import org.onosproject.net.packet.PacketContext;
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketService;
-import org.onosproject.routing.config.Interface;
-import org.onosproject.routing.config.RoutingConfigurationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,14 +41,14 @@
     private static final Logger log = LoggerFactory.getLogger(IcmpHandler.class);
 
     private final PacketService packetService;
-    private final RoutingConfigurationService configService;
+    private final InterfaceService interfaceService;
 
     private final IcmpProcessor processor = new IcmpProcessor();
 
 
-    public IcmpHandler(RoutingConfigurationService configService,
+    public IcmpHandler(InterfaceService interfaceService,
                        PacketService packetService) {
-        this.configService = configService;
+        this.interfaceService = interfaceService;
         this.packetService = packetService;
     }
 
@@ -67,7 +67,7 @@
         IPv4 ipv4 = (IPv4) ethernet.getPayload();
         ConnectPoint connectPoint = pkt.receivedFrom();
         IpAddress destIpAddress = IpAddress.valueOf(ipv4.getDestinationAddress());
-        Interface targetInterface = configService.getMatchingInterface(destIpAddress);
+        Interface targetInterface = interfaceService.getMatchingInterface(destIpAddress);
 
         if (targetInterface == null) {
             log.trace("No matching interface for {}", destIpAddress);
diff --git a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/TunnellingConnectivityManager.java b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/TunnellingConnectivityManager.java
index 06420c1..35af05e 100644
--- a/apps/bgprouter/src/main/java/org/onosproject/bgprouter/TunnellingConnectivityManager.java
+++ b/apps/bgprouter/src/main/java/org/onosproject/bgprouter/TunnellingConnectivityManager.java
@@ -15,14 +15,14 @@
  */
 package org.onosproject.bgprouter;
 
-import static org.slf4j.LoggerFactory.getLogger;
-
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IPv4;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.TCP;
 import org.onlab.packet.TpPort;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -36,12 +36,14 @@
 import org.onosproject.net.packet.PacketContext;
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketService;
-import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.BgpSpeaker;
-import org.onosproject.routing.config.InterfaceAddress;
-import org.onosproject.routing.config.RoutingConfigurationService;
+import org.onosproject.routing.config.BgpConfig;
 import org.slf4j.Logger;
 
+import java.util.Optional;
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
 
 /**
  * Manages connectivity between peers by tunnelling BGP traffic through
@@ -53,34 +55,32 @@
     private final Logger log = getLogger(getClass());
     private final ApplicationId appId;
 
-    private final BgpSpeaker bgpSpeaker;
+    private final BgpConfig.BgpSpeakerConfig bgpSpeaker;
 
     private final PacketService packetService;
-    private final RoutingConfigurationService configService;
+    private final InterfaceService interfaceService;
     private final FlowObjectiveService flowObjectiveService;
 
     private final BgpProcessor processor = new BgpProcessor();
 
     public TunnellingConnectivityManager(ApplicationId appId,
-                                         RoutingConfigurationService configService,
+                                         BgpConfig bgpConfig,
+                                         InterfaceService interfaceService,
                                          PacketService packetService,
                                          FlowObjectiveService flowObjectiveService) {
         this.appId = appId;
-        this.configService = configService;
+        this.interfaceService = interfaceService;
         this.packetService = packetService;
         this.flowObjectiveService = flowObjectiveService;
 
-        BgpSpeaker bgpSpeaker = null;
-        for (BgpSpeaker speaker : configService.getBgpSpeakers().values()) {
-            bgpSpeaker = speaker;
-            break;
-        }
+        Optional<BgpConfig.BgpSpeakerConfig> bgpSpeaker =
+                bgpConfig.bgpSpeakers().stream().findAny();
 
-        if (bgpSpeaker == null) {
+        if (!bgpSpeaker.isPresent()) {
             throw new IllegalArgumentException("Must have at least one BGP speaker configured");
         }
 
-        this.bgpSpeaker = bgpSpeaker;
+        this.bgpSpeaker = bgpSpeaker.get();
 
     }
 
@@ -149,14 +149,19 @@
         IpAddress dstAddress = IpAddress.valueOf(ipv4.getDestinationAddress());
 
         if (context.inPacket().receivedFrom().equals(bgpSpeaker.connectPoint())) {
-            BgpPeer peer = configService.getBgpPeers().get(dstAddress);
-            if (peer != null) {
-                outputPort = peer.connectPoint();
+            if (bgpSpeaker.peers().contains(dstAddress)) {
+                Interface intf = interfaceService.getMatchingInterface(dstAddress);
+                if (intf != null) {
+                    outputPort = intf.connectPoint();
+                }
             }
-        }
-        for (InterfaceAddress addr : bgpSpeaker.interfaceAddresses()) {
-            if (addr.ipAddress().equals(dstAddress) && !context.inPacket()
-                    .receivedFrom().equals(bgpSpeaker.connectPoint())) {
+        } else {
+            Set<Interface> interfaces =
+                    interfaceService.getInterfacesByPort(context.inPacket().receivedFrom());
+
+            if (interfaces.stream()
+                    .flatMap(intf -> intf.ipAddresses().stream())
+                    .anyMatch(ia -> ia.ipAddress().equals(dstAddress))) {
                 outputPort = bgpSpeaker.connectPoint();
             }
         }
diff --git a/apps/routing-api/pom.xml b/apps/routing-api/pom.xml
index 81c5079..1b9fc2f 100644
--- a/apps/routing-api/pom.xml
+++ b/apps/routing-api/pom.xml
@@ -37,6 +37,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-incubator-api</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
         </dependency>
diff --git a/apps/routing-api/src/main/java/org/onosproject/routing/RoutingService.java b/apps/routing-api/src/main/java/org/onosproject/routing/RoutingService.java
index 5706211..8b7040e 100644
--- a/apps/routing-api/src/main/java/org/onosproject/routing/RoutingService.java
+++ b/apps/routing-api/src/main/java/org/onosproject/routing/RoutingService.java
@@ -18,6 +18,7 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.routing.config.BgpConfig;
 
 import java.util.Collection;
 
@@ -28,6 +29,8 @@
 
     String ROUTER_APP_ID = "org.onosproject.router";
 
+    Class<BgpConfig> CONFIG_CLASS = BgpConfig.class;
+
     /**
      * Specifies the type of an IP address or an IP prefix location.
      */
diff --git a/apps/routing-api/src/main/java/org/onosproject/routing/config/BgpConfig.java b/apps/routing-api/src/main/java/org/onosproject/routing/config/BgpConfig.java
new file mode 100644
index 0000000..54e2e0e
--- /dev/null
+++ b/apps/routing-api/src/main/java/org/onosproject/routing/config/BgpConfig.java
@@ -0,0 +1,84 @@
+/*
+ * 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.config;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.collect.Sets;
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Configuration object for BGP config.
+ */
+public class BgpConfig extends Config<ApplicationId> {
+
+    public static final String SPEAKERS = "bgpSpeakers";
+    public static final String CONNECT_POINT = "connectPoint";
+    public static final String PEERS = "peers";
+
+    // TODO add methods for updating config
+
+    /**
+     * Gets the set of configured BGP speakers.
+     *
+     * @return BGP speakers
+     */
+    public Set<BgpSpeakerConfig> bgpSpeakers() {
+        Set<BgpSpeakerConfig> speakers = Sets.newHashSet();
+
+        JsonNode speakersNode = node.get(SPEAKERS);
+        speakersNode.forEach(jsonNode -> {
+            Set<IpAddress> listenAddresses = Sets.newHashSet();
+            jsonNode.path(PEERS).forEach(addressNode ->
+                    listenAddresses.add(IpAddress.valueOf(addressNode.asText()))
+            );
+            speakers.add(new BgpSpeakerConfig(
+                    ConnectPoint.deviceConnectPoint(jsonNode.path(CONNECT_POINT).asText()),
+                    listenAddresses));
+        });
+
+        return speakers;
+    }
+
+    /**
+     * Configuration for a BGP speaker.
+     */
+    public static class BgpSpeakerConfig {
+
+        private ConnectPoint connectPoint;
+        private Set<IpAddress> peers;
+
+        public BgpSpeakerConfig(ConnectPoint connectPoint, Set<IpAddress> peers) {
+            this.connectPoint = checkNotNull(connectPoint);
+            this.peers = checkNotNull(peers);
+        }
+
+        public ConnectPoint connectPoint() {
+            return connectPoint;
+        }
+
+        public Set<IpAddress> peers() {
+            return peers;
+        }
+    }
+}
diff --git a/apps/routing-api/src/main/java/org/onosproject/routing/config/RoutingConfigurationService.java b/apps/routing-api/src/main/java/org/onosproject/routing/config/RoutingConfigurationService.java
index bbd9560..f8ee21b 100644
--- a/apps/routing-api/src/main/java/org/onosproject/routing/config/RoutingConfigurationService.java
+++ b/apps/routing-api/src/main/java/org/onosproject/routing/config/RoutingConfigurationService.java
@@ -77,7 +77,9 @@
      * Retrieves the entire set of interfaces in the network.
      *
      * @return the set of interfaces
+     * @deprecated in Drake release - use InterfaceService instead
      */
+    @Deprecated
     Set<Interface> getInterfaces();
 
     /**
@@ -86,7 +88,7 @@
      *
      * @return the set of connect points connected to BGP peers
      */
-    public Set<ConnectPoint> getBgpPeerConnectPoints();
+    Set<ConnectPoint> getBgpPeerConnectPoints();
 
     /**
      * Retrieves the interface associated with the given connect point.
@@ -94,7 +96,9 @@
      * @param connectPoint the connect point to retrieve interface information
      * for
      * @return the interface
+     * @deprecated in Drake release - use InterfaceService instead
      */
+    @Deprecated
     Interface getInterface(ConnectPoint connectPoint);
 
     /**
@@ -102,7 +106,9 @@
      *
      * @param ip IP address of the interface
      * @return the interface
+     * @deprecated in Drake release - use InterfaceService instead
      */
+    @Deprecated
     Interface getInterface(IpAddress ip);
 
     /**
@@ -111,7 +117,9 @@
      *
      * @param ipAddress IP address to match
      * @return the matching interface
+     * @deprecated in Drake release - use InterfaceService instead
      */
+    @Deprecated
     Interface getMatchingInterface(IpAddress ipAddress);
 
 }
diff --git a/apps/routing/src/main/java/org/onosproject/routing/cli/BgpPeersListCommand.java b/apps/routing/src/main/java/org/onosproject/routing/cli/BgpPeersListCommand.java
deleted file mode 100644
index ff6cf26..0000000
--- a/apps/routing/src/main/java/org/onosproject/routing/cli/BgpPeersListCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.cli;
-
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.impl.BgpConfig;
-
-/**
- * Lists the BGP peers configured in the system.
- */
-@Command(scope = "onos", name = "bgp-peers",
-        description = "Lists all BGP peers")
-public class BgpPeersListCommand extends AbstractShellCommand {
-
-    private static final String FORMAT = "%s : %s";
-
-    @Override
-    protected void execute() {
-        NetworkConfigService configService = get(NetworkConfigService.class);
-        CoreService coreService = get(CoreService.class);
-        ApplicationId appId = coreService.getAppId(RoutingService.ROUTER_APP_ID);
-
-        print(appId.toString());
-
-        BgpConfig config = configService.getConfig(appId, BgpConfig.class);
-
-        if (config == null || config.bgpPeers().isEmpty()) {
-            print("No peers configured");
-        } else {
-            config.bgpPeers().forEach(
-                    p -> print(FORMAT, p.ipAddress(), p.connectPoint()));
-        }
-    }
-}
diff --git a/apps/routing/src/main/java/org/onosproject/routing/cli/BgpSpeakersListCommand.java b/apps/routing/src/main/java/org/onosproject/routing/cli/BgpSpeakersListCommand.java
index 42b5076..d37c6d3 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/cli/BgpSpeakersListCommand.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/cli/BgpSpeakersListCommand.java
@@ -22,7 +22,7 @@
 import org.onosproject.core.CoreService;
 import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.impl.BgpConfig;
+import org.onosproject.routing.config.BgpConfig;
 
 /**
  * Lists the BGP speakers configured in the system.
@@ -47,7 +47,7 @@
             print("No speakers configured");
         } else {
             config.bgpSpeakers().forEach(
-                    s -> print(FORMAT, s.connectPoint(), s.listenAddresses()));
+                    s -> print(FORMAT, s.connectPoint(), s.peers()));
         }
     }
 }
diff --git a/apps/routing/src/main/java/org/onosproject/routing/config/impl/BgpConfig.java b/apps/routing/src/main/java/org/onosproject/routing/config/impl/BgpConfig.java
deleted file mode 100644
index 24400e8..0000000
--- a/apps/routing/src/main/java/org/onosproject/routing/config/impl/BgpConfig.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.config.impl;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.google.common.collect.Sets;
-import org.onlab.packet.IpAddress;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.config.Config;
-import org.onosproject.net.ConnectPoint;
-
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Configuration object for BGP config.
- */
-public class BgpConfig extends Config<ApplicationId> {
-
-    public static final String PEERS = "bgpPeers";
-    public static final String SPEAKERS = "bgpSpeakers";
-    public static final String CONNECT_POINT = "connectPoint";
-    public static final String IP_ADDRESS = "ipAddress";
-    public static final String LISTEN_ADDRESSES = "listenAddresses";
-
-    /**
-     * Gets the set of configured BGP peers.
-     *
-     * @return BGP peers
-     */
-    public Set<BgpPeerConfig> bgpPeers() {
-        Set<BgpPeerConfig> peers = Sets.newHashSet();
-
-        JsonNode peersNode = node.get(PEERS);
-        peersNode.forEach(jsonNode -> peers.add(
-                new BgpPeerConfig(ConnectPoint.deviceConnectPoint(jsonNode.path(CONNECT_POINT).asText()),
-                        IpAddress.valueOf(jsonNode.path(IP_ADDRESS).asText()))));
-
-        return peers;
-    }
-
-    /**
-     * Gets the set of configured BGP speakers.
-     *
-     * @return BGP speakers
-     */
-    public Set<BgpSpeakerConfig> bgpSpeakers() {
-        Set<BgpSpeakerConfig> speakers = Sets.newHashSet();
-
-        JsonNode speakersNode = node.get(SPEAKERS);
-        speakersNode.forEach(jsonNode -> {
-            Set<IpAddress> listenAddresses = Sets.newHashSet();
-            jsonNode.path(LISTEN_ADDRESSES).forEach(addressNode ->
-                    listenAddresses.add(IpAddress.valueOf(addressNode.asText()))
-            );
-            speakers.add(new BgpSpeakerConfig(
-                    ConnectPoint.deviceConnectPoint(jsonNode.path(CONNECT_POINT).asText()),
-                    listenAddresses));
-        });
-
-        return speakers;
-    }
-
-    /**
-     * Configuration for a BGP peer.
-     */
-    public class BgpPeerConfig {
-        private ConnectPoint connectPoint;
-        private IpAddress ipAddress;
-
-        public BgpPeerConfig(ConnectPoint connectPoint, IpAddress ipAddress) {
-            this.connectPoint = connectPoint;
-            this.ipAddress = ipAddress;
-        }
-
-        public ConnectPoint connectPoint() {
-            return connectPoint;
-        }
-
-        public IpAddress ipAddress() {
-            return ipAddress;
-        }
-
-    }
-
-    /**
-     * Configuration for a BGP speaker.
-     */
-    public class BgpSpeakerConfig {
-
-        private ConnectPoint connectPoint;
-        private Set<IpAddress> listenAddresses;
-
-        public BgpSpeakerConfig(ConnectPoint connectPoint, Set<IpAddress> listenAddresses) {
-            this.connectPoint = checkNotNull(connectPoint);
-            this.listenAddresses = checkNotNull(listenAddresses);
-        }
-
-        public ConnectPoint connectPoint() {
-            return connectPoint;
-        }
-
-        public Set<IpAddress> listenAddresses() {
-            return listenAddresses;
-        }
-    }
-}
diff --git a/apps/routing/src/main/java/org/onosproject/routing/config/impl/RoutingConfigurationImpl.java b/apps/routing/src/main/java/org/onosproject/routing/config/impl/RoutingConfigurationImpl.java
index ec0d901..1078319 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/config/impl/RoutingConfigurationImpl.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/config/impl/RoutingConfigurationImpl.java
@@ -30,16 +30,22 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.config.ConfigFactory;
 import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.NetworkConfigService;
 import org.onosproject.net.config.basics.SubjectFactories;
-import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.host.HostService;
+import org.onosproject.routing.config.BgpConfig;
 import org.onosproject.routing.config.BgpPeer;
 import org.onosproject.routing.config.BgpSpeaker;
 import org.onosproject.routing.config.Interface;
 import org.onosproject.routing.config.LocalIpPrefixEntry;
 import org.onosproject.routing.config.RoutingConfigurationService;
+import org.onosproject.routing.impl.Router;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -51,6 +57,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
 import static org.onosproject.routing.RouteEntry.createBinaryString;
 
@@ -74,6 +81,15 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetworkConfigRegistry registry;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigService configService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected InterfaceService interfaceService;
+
     private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>();
     private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>();
     private Set<IpAddress> gatewayIpAddresses = new HashSet<>();
@@ -178,7 +194,20 @@
 
     @Override
     public Set<ConnectPoint> getBgpPeerConnectPoints() {
-        return Collections.unmodifiableSet(bgpPeerConnectPoints);
+        // TODO perhaps cache this result in future
+        ApplicationId routerAppId = coreService.getAppId(Router.ROUTER_APP_ID);
+        if (routerAppId == null) {
+            return Collections.emptySet();
+        }
+
+        BgpConfig bgpConfig = configService.getConfig(routerAppId, BgpConfig.class);
+
+        return bgpConfig.bgpSpeakers().stream()
+                .flatMap(speaker -> speaker.peers().stream())
+                .map(peer -> interfaceService.getMatchingInterface(peer))
+                .filter(intf -> intf != null)
+                .map(intf -> intf.connectPoint())
+                .collect(Collectors.toSet());
     }
 
     @Override
diff --git a/apps/routing/src/main/java/org/onosproject/routing/impl/Router.java b/apps/routing/src/main/java/org/onosproject/routing/impl/Router.java
index c5c7741..c4f291ba 100644
--- a/apps/routing/src/main/java/org/onosproject/routing/impl/Router.java
+++ b/apps/routing/src/main/java/org/onosproject/routing/impl/Router.java
@@ -35,6 +35,8 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onosproject.core.CoreService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.host.HostEvent;
@@ -49,7 +51,6 @@
 import org.onosproject.routing.RouteListener;
 import org.onosproject.routing.RouteUpdate;
 import org.onosproject.routing.RoutingService;
-import org.onosproject.routing.config.Interface;
 import org.onosproject.routing.config.RoutingConfigurationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,6 +61,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
@@ -110,6 +112,9 @@
     protected BgpService bgpService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected InterfaceService interfaceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected RoutingConfigurationService routingConfigurationService;
 
     private ExecutorService bgpUpdatesExecutor;
@@ -603,8 +608,7 @@
             RouteEntry routeEntry = getLongestMatchableRouteEntry(dstIpAddress);
             if (routeEntry != null) {
                 nextHopIpAddress = routeEntry.nextHop();
-                Interface it = routingConfigurationService
-                        .getMatchingInterface(nextHopIpAddress);
+                Interface it = interfaceService.getMatchingInterface(nextHopIpAddress);
                 if (it != null) {
                     return it.connectPoint();
                 } else {
@@ -700,18 +704,18 @@
     private TrafficType trafficTypeClassifier(ConnectPoint srcConnectPoint,
                                               IpAddress dstIp) {
         LocationType dstIpLocationType = getLocationType(dstIp);
-        Interface srcInterface =
-                routingConfigurationService.getInterface(srcConnectPoint);
+        Optional<Interface> srcInterface =
+                interfaceService.getInterfacesByPort(srcConnectPoint).stream().findFirst();
 
         switch (dstIpLocationType) {
         case INTERNET:
-            if (srcInterface == null) {
+            if (!srcInterface.isPresent()) {
                 return TrafficType.HOST_TO_INTERNET;
             } else {
                 return TrafficType.INTERNET_TO_INTERNET;
             }
         case LOCAL:
-            if (srcInterface == null) {
+            if (!srcInterface.isPresent()) {
                 return TrafficType.HOST_TO_HOST;
             } else {
                 // TODO Currently we only consider local public prefixes.
diff --git a/apps/routing/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/routing/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 379eaac..866e1c4 100644
--- a/apps/routing/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/routing/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -32,9 +32,6 @@
       <action class="org.onosproject.routing.cli.RemoveRouteCommand"/>
     </command>
     <command>
-      <action class="org.onosproject.routing.cli.BgpPeersListCommand"/>
-    </command>
-    <command>
       <action class="org.onosproject.routing.cli.BgpSpeakersListCommand"/>
     </command>
   </command-bundle>
diff --git a/apps/sdnip/features.xml b/apps/sdnip/features.xml
index 8b286c3..21ae89d 100644
--- a/apps/sdnip/features.xml
+++ b/apps/sdnip/features.xml
@@ -22,8 +22,5 @@
         <bundle>mvn:${project.groupId}/onos-app-sdnip/${project.version}</bundle>
         <bundle>mvn:${project.groupId}/onos-app-routing-api/${project.version}</bundle>
         <bundle>mvn:${project.groupId}/onos-app-routing/${project.version}</bundle>
-	<!-- NOTE: Temporarily the sdnip app will bring the config bundle
-	     until we can specify dependencies between applictions -->
-	<bundle>mvn:${project.groupId}/onos-app-config/${project.version}</bundle>
     </feature>
 </features>
diff --git a/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java b/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
index cde59d1..e0e9faf 100644
--- a/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
+++ b/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
@@ -23,6 +23,8 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -43,8 +45,6 @@
 import org.onosproject.routing.FibListener;
 import org.onosproject.routing.FibUpdate;
 import org.onosproject.routing.IntentRequestListener;
-import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.Interface;
 import org.onosproject.routing.config.RoutingConfigurationService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -81,6 +81,7 @@
     private final ApplicationId appId;
     private final IntentService intentService;
     private final HostService hostService;
+    private final InterfaceService interfaceService;
     private final Map<IntentKey, PointToPointIntent> peerIntents;
     private final Map<IpPrefix, MultiPointToSinglePointIntent> routeIntents;
 
@@ -104,10 +105,12 @@
      */
     IntentSynchronizer(ApplicationId appId, IntentService intentService,
                        HostService hostService,
-                       RoutingConfigurationService configService) {
+                       RoutingConfigurationService configService,
+                       InterfaceService interfaceService) {
         this.appId = appId;
         this.intentService = intentService;
         this.hostService = hostService;
+        this.interfaceService = interfaceService;
         peerIntents = new ConcurrentHashMap<>();
         routeIntents = new ConcurrentHashMap<>();
 
@@ -122,12 +125,7 @@
      * Starts the synchronizer.
      */
     public void start() {
-        bgpIntentsSynchronizerExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                doIntentSynchronizationThread();
-            }
-        });
+        bgpIntentsSynchronizerExecutor.execute(this::doIntentSynchronizationThread);
     }
 
     /**
@@ -313,24 +311,11 @@
             MacAddress nextHopMacAddress) {
 
         // Find the attachment point (egress interface) of the next hop
-        Interface egressInterface;
-        if (configService.getBgpPeers().containsKey(nextHopIpAddress)) {
-            // Route to a peer
-            log.debug("Route to peer {}", nextHopIpAddress);
-            BgpPeer peer =
-                    configService.getBgpPeers().get(nextHopIpAddress);
-            egressInterface =
-                    configService.getInterface(peer.connectPoint());
-        } else {
-            // Route to non-peer
-            log.debug("Route to non-peer {}", nextHopIpAddress);
-            egressInterface =
-                    configService.getMatchingInterface(nextHopIpAddress);
-            if (egressInterface == null) {
-                log.warn("No outgoing interface found for {}",
-                         nextHopIpAddress);
-                return null;
-            }
+        Interface egressInterface = interfaceService.getMatchingInterface(nextHopIpAddress);
+        if (egressInterface == null) {
+            log.warn("No outgoing interface found for {}",
+                     nextHopIpAddress);
+            return null;
         }
 
         //
@@ -341,7 +326,8 @@
         log.debug("Generating intent for prefix {}, next hop mac {}",
                   prefix, nextHopMacAddress);
 
-        for (Interface intf : configService.getInterfaces()) {
+        for (Interface intf : interfaceService.getInterfaces()) {
+            // TODO this should be only peering interfaces
             if (!intf.connectPoint().equals(egressInterface.connectPoint())) {
                 ConnectPoint srcPort = intf.connectPoint();
                 ingressPorts.add(srcPort);
diff --git a/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java b/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
index ce85945..1e9db5b 100644
--- a/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
+++ b/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
@@ -22,6 +22,9 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.TpPort;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -29,11 +32,8 @@
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.InterfaceIpAddress;
 import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.BgpSpeaker;
-import org.onosproject.routing.config.Interface;
-import org.onosproject.routing.config.InterfaceAddress;
-import org.onosproject.routing.config.RoutingConfigurationService;
+import org.onosproject.routing.RoutingService;
+import org.onosproject.routing.config.BgpConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -41,6 +41,8 @@
 import java.util.Collection;
 import java.util.List;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Manages the connectivity requirements between peers.
  */
@@ -53,9 +55,11 @@
     private static final short BGP_PORT = 179;
 
     private final IntentSynchronizer intentSynchronizer;
-    private final RoutingConfigurationService configService;
+    private final NetworkConfigService configService;
+    private final InterfaceService interfaceService;
 
     private final ApplicationId appId;
+    private final ApplicationId routerAppId;
 
     /**
      * Creates a new PeerConnectivityManager.
@@ -66,28 +70,20 @@
      */
     public PeerConnectivityManager(ApplicationId appId,
                                    IntentSynchronizer intentSynchronizer,
-                                   RoutingConfigurationService configService) {
+                                   NetworkConfigService configService,
+                                   ApplicationId routerAppId,
+                                   InterfaceService interfaceService) {
         this.appId = appId;
         this.intentSynchronizer = intentSynchronizer;
         this.configService = configService;
+        this.routerAppId = routerAppId;
+        this.interfaceService = interfaceService;
     }
 
     /**
      * Starts the peer connectivity manager.
      */
     public void start() {
-        if (configService.getInterfaces().isEmpty()) {
-            log.warn("No interfaces found in configuration file");
-        }
-
-        if (configService.getBgpPeers().isEmpty()) {
-            log.warn("No BGP peers found in configuration file");
-        }
-
-        if (configService.getBgpSpeakers().isEmpty()) {
-            log.error("No BGP speakers found in configuration file");
-        }
-
         setUpConnectivity();
     }
 
@@ -99,78 +95,74 @@
 
     /**
      * Sets up paths to establish connectivity between all internal
-     * {@link BgpSpeaker}s and all external {@link BgpPeer}s.
+     * BGP speakers and external BGP peers.
      */
     private void setUpConnectivity() {
         List<PointToPointIntent> intents = new ArrayList<>();
 
-        for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
-                .values()) {
+        BgpConfig config = configService.getConfig(routerAppId, RoutingService.CONFIG_CLASS);
+
+        if (config == null) {
+            log.warn("No BgpConfig found");
+            return;
+        }
+
+        for (BgpConfig.BgpSpeakerConfig bgpSpeaker : config.bgpSpeakers()) {
             log.debug("Start to set up BGP paths for BGP speaker: {}",
-                      bgpSpeaker);
+                    bgpSpeaker);
 
-            for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
-
-                log.debug("Start to set up BGP paths between BGP speaker: {} "
-                                  + "to BGP peer: {}", bgpSpeaker, bgpPeer);
-
-                intents.addAll(buildPeerIntents(bgpSpeaker, bgpPeer));
-            }
+            intents.addAll(buildSpeakerIntents(bgpSpeaker));
         }
 
         // Submit all the intents.
         intentSynchronizer.submitPeerIntents(intents);
     }
 
-    /**
-     * Builds the required intents between a given internal BGP speaker and
-     * external BGP peer.
-     *
-     * @param bgpSpeaker the BGP speaker
-     * @param bgpPeer the BGP peer
-     * @return the intents to install
-     */
-    private Collection<PointToPointIntent> buildPeerIntents(
-            BgpSpeaker bgpSpeaker,
-            BgpPeer bgpPeer) {
+    private Collection<PointToPointIntent> buildSpeakerIntents(BgpConfig.BgpSpeakerConfig speaker) {
         List<PointToPointIntent> intents = new ArrayList<>();
 
-        ConnectPoint bgpdConnectPoint = bgpSpeaker.connectPoint();
+        for (IpAddress peerAddress : speaker.peers()) {
+            Interface peeringInterface = interfaceService.getMatchingInterface(peerAddress);
 
-        List<InterfaceAddress> interfaceAddresses =
-                bgpSpeaker.interfaceAddresses();
-
-        IpAddress bgpdAddress = null;
-        for (InterfaceAddress interfaceAddress : interfaceAddresses) {
-            Interface peerInterface = configService.getInterface(interfaceAddress.ipAddress());
-            if (peerInterface == null) {
+            if (peeringInterface == null) {
+                log.debug("No peering interface found for peer {} on speaker {}",
+                        peerAddress, speaker);
                 continue;
             }
 
-            for (InterfaceIpAddress interfaceIpAddress : peerInterface.ipAddresses()) {
-                // Only add intents where the peer and ONOS's addresses are
-                // in the same subnet
-                if (interfaceIpAddress.subnetAddress().contains(bgpPeer.ipAddress())) {
-                    bgpdAddress = interfaceAddress.ipAddress();
+            IpAddress peeringAddress = null;
+            for (InterfaceIpAddress address : peeringInterface.ipAddresses()) {
+                if (address.subnetAddress().contains(peerAddress)) {
+                    peeringAddress = address.ipAddress();
                     break;
                 }
             }
-            if (bgpdAddress != null) {
-                break;
-            }
-        }
-        if (bgpdAddress == null) {
-            log.debug("No IP address found for peer {} on interface {}",
-                    bgpPeer, bgpPeer.connectPoint());
-            return intents;
+
+            checkNotNull(peeringAddress);
+
+            intents.addAll(buildIntents(speaker.connectPoint(), peeringAddress,
+                    peeringInterface.connectPoint(), peerAddress));
         }
 
-        IpAddress bgpdPeerAddress = bgpPeer.ipAddress();
-        ConnectPoint bgpdPeerConnectPoint = bgpPeer.connectPoint();
+        return intents;
+    }
 
-        if (bgpdAddress.version() != bgpdPeerAddress.version()) {
-            return intents;
-        }
+    /**
+     * Builds the required intents between the two pairs of connect points and
+     * IP addresses.
+     *
+     * @param portOne the first connect point
+     * @param ipOne the first IP address
+     * @param portTwo the second connect point
+     * @param ipTwo the second IP address
+     * @return the intents to install
+     */
+    private Collection<PointToPointIntent> buildIntents(ConnectPoint portOne,
+                                                        IpAddress ipOne,
+                                                        ConnectPoint portTwo,
+                                                        IpAddress ipTwo) {
+
+        List<PointToPointIntent> intents = new ArrayList<>();
 
         TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
 
@@ -179,7 +171,7 @@
         byte tcpProtocol;
         byte icmpProtocol;
 
-        if (bgpdAddress.isIp4()) {
+        if (ipOne.isIp4()) {
             tcpProtocol = IPv4.PROTOCOL_TCP;
             icmpProtocol = IPv4.PROTOCOL_ICMP;
         } else {
@@ -189,26 +181,24 @@
 
         // Path from BGP speaker to BGP peer matching destination TCP port 179
         selector = buildSelector(tcpProtocol,
-                bgpdAddress,
-                bgpdPeerAddress,
+                ipOne,
+                ipTwo,
                 null,
                 BGP_PORT);
 
-        int priority = PRIORITY_OFFSET;
-
         intents.add(PointToPointIntent.builder()
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdConnectPoint)
-                .egressPoint(bgpdPeerConnectPoint)
-                .priority(priority)
+                .ingressPoint(portOne)
+                .egressPoint(portTwo)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         // Path from BGP speaker to BGP peer matching source TCP port 179
         selector = buildSelector(tcpProtocol,
-                bgpdAddress,
-                bgpdPeerAddress,
+                ipOne,
+                ipTwo,
                 BGP_PORT,
                 null);
 
@@ -216,15 +206,15 @@
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdConnectPoint)
-                .egressPoint(bgpdPeerConnectPoint)
-                .priority(priority)
+                .ingressPoint(portOne)
+                .egressPoint(portTwo)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         // Path from BGP peer to BGP speaker matching destination TCP port 179
         selector = buildSelector(tcpProtocol,
-                bgpdPeerAddress,
-                bgpdAddress,
+                ipTwo,
+                ipOne,
                 null,
                 BGP_PORT);
 
@@ -232,15 +222,15 @@
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdPeerConnectPoint)
-                .egressPoint(bgpdConnectPoint)
-                .priority(priority)
+                .ingressPoint(portTwo)
+                .egressPoint(portOne)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         // Path from BGP peer to BGP speaker matching source TCP port 179
         selector = buildSelector(tcpProtocol,
-                bgpdPeerAddress,
-                bgpdAddress,
+                ipTwo,
+                ipOne,
                 BGP_PORT,
                 null);
 
@@ -248,15 +238,15 @@
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdPeerConnectPoint)
-                .egressPoint(bgpdConnectPoint)
-                .priority(priority)
+                .ingressPoint(portTwo)
+                .egressPoint(portOne)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         // ICMP path from BGP speaker to BGP peer
         selector = buildSelector(icmpProtocol,
-                bgpdAddress,
-                bgpdPeerAddress,
+                ipOne,
+                ipTwo,
                 null,
                 null);
 
@@ -264,15 +254,15 @@
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdConnectPoint)
-                .egressPoint(bgpdPeerConnectPoint)
-                .priority(priority)
+                .ingressPoint(portOne)
+                .egressPoint(portTwo)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         // ICMP path from BGP peer to BGP speaker
         selector = buildSelector(icmpProtocol,
-                bgpdPeerAddress,
-                bgpdAddress,
+                ipTwo,
+                ipOne,
                 null,
                 null);
 
@@ -280,9 +270,9 @@
                 .appId(appId)
                 .selector(selector)
                 .treatment(treatment)
-                .ingressPoint(bgpdPeerConnectPoint)
-                .egressPoint(bgpdConnectPoint)
-                .priority(priority)
+                .ingressPoint(portTwo)
+                .egressPoint(portOne)
+                .priority(PRIORITY_OFFSET)
                 .build());
 
         return intents;
@@ -301,24 +291,16 @@
     private TrafficSelector buildSelector(byte ipProto, IpAddress srcIp,
                                           IpAddress dstIp, Short srcTcpPort,
                                           Short dstTcpPort) {
-        TrafficSelector.Builder builder = null;
+        TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPProtocol(ipProto);
 
         if (dstIp.isIp4()) {
-            builder = DefaultTrafficSelector.builder()
-                    .matchEthType(Ethernet.TYPE_IPV4)
-                    .matchIPProtocol(ipProto)
-                    .matchIPSrc(IpPrefix.valueOf(srcIp,
-                            IpPrefix.MAX_INET_MASK_LENGTH))
-                    .matchIPDst(IpPrefix.valueOf(dstIp,
-                            IpPrefix.MAX_INET_MASK_LENGTH));
+            builder.matchIPSrc(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET_MASK_LENGTH))
+                    .matchIPDst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET_MASK_LENGTH));
         } else {
-            builder = DefaultTrafficSelector.builder()
-                    .matchEthType(Ethernet.TYPE_IPV6)
-                    .matchIPProtocol(ipProto)
-                    .matchIPv6Src(IpPrefix.valueOf(srcIp,
-                            IpPrefix.MAX_INET6_MASK_LENGTH))
-                    .matchIPv6Dst(IpPrefix.valueOf(dstIp,
-                            IpPrefix.MAX_INET6_MASK_LENGTH));
+            builder.matchIPv6Src(IpPrefix.valueOf(srcIp, IpPrefix.MAX_INET6_MASK_LENGTH))
+                    .matchIPv6Dst(IpPrefix.valueOf(dstIp, IpPrefix.MAX_INET6_MASK_LENGTH));
         }
 
         if (srcTcpPort != null) {
diff --git a/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java b/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java
index d97e28a..3d1fe65 100644
--- a/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java
+++ b/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIp.java
@@ -26,9 +26,10 @@
 import org.onosproject.cluster.LeadershipEvent;
 import org.onosproject.cluster.LeadershipEventListener;
 import org.onosproject.cluster.LeadershipService;
-import org.onosproject.config.NetworkConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.routing.RoutingService;
@@ -70,14 +71,12 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected RoutingConfigurationService config;
 
-    //
-    // NOTE: Unused reference - needed to guarantee that the
-    // NetworkConfigReader component is activated and the network configuration
-    // is read.
-    //
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetworkConfigService networkConfigService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected InterfaceService interfaceService;
+
     private IntentSynchronizer intentSynchronizer;
     private PeerConnectivityManager peerConnectivity;
 
@@ -96,12 +95,15 @@
 
         intentSynchronizer = new IntentSynchronizer(appId, intentService,
                                                     hostService,
-                                                    config);
+                                                    config,
+                                                    interfaceService);
         intentSynchronizer.start();
 
         peerConnectivity = new PeerConnectivityManager(appId,
                                                        intentSynchronizer,
-                                                       config);
+                                                       networkConfigService,
+                coreService.getAppId(RoutingService.ROUTER_APP_ID),
+                                                       interfaceService);
         peerConnectivity.start();
 
         routingService.addFibListener(intentSynchronizer);
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
index 2a52539..fc5782e 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/IntentSyncTest.java
@@ -28,6 +28,9 @@
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -45,7 +48,6 @@
 import org.onosproject.routing.FibUpdate;
 import org.onosproject.routing.RouteEntry;
 import org.onosproject.routing.config.BgpPeer;
-import org.onosproject.routing.config.Interface;
 import org.onosproject.routing.config.RoutingConfigurationService;
 import org.onosproject.sdnip.IntentSynchronizer.IntentKey;
 
@@ -56,7 +58,11 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -71,7 +77,9 @@
 public class IntentSyncTest extends AbstractIntentTest {
 
     private RoutingConfigurationService routingConfig;
+    private InterfaceService interfaceService;
     private IntentService intentService;
+    private NetworkConfigService configService;
 
     private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
             DeviceId.deviceId("of:0000000000000001"),
@@ -90,6 +98,7 @@
             PortNumber.portNumber(1));
 
     private IntentSynchronizer intentSynchronizer;
+    private final Set<Interface> interfaces = Sets.newHashSet();
 
     private static final ApplicationId APPID = new ApplicationId() {
         @Override
@@ -108,17 +117,21 @@
         super.setUp();
 
         routingConfig = createMock(RoutingConfigurationService.class);
+        interfaceService = createMock(InterfaceService.class);
+        configService = createMock(NetworkConfigService.class);
 
         // These will set expectations on routingConfig
         setUpInterfaceService();
         setUpBgpPeers();
 
         replay(routingConfig);
+        replay(interfaceService);
 
         intentService = createMock(IntentService.class);
 
         intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    null, routingConfig);
+                                                    null, routingConfig,
+                                                    interfaceService);
     }
 
     /**
@@ -152,9 +165,6 @@
      * Sets up InterfaceService.
      */
     private void setUpInterfaceService() {
-
-        Set<Interface> interfaces = Sets.newHashSet();
-
         Set<InterfaceIpAddress> interfaceIpAddresses1 = Sets.newHashSet();
         interfaceIpAddresses1.add(new InterfaceIpAddress(
                 IpAddress.valueOf("192.168.10.101"),
@@ -190,16 +200,26 @@
                                           MacAddress.valueOf("00:00:00:00:00:04"),
                                           VlanId.vlanId((short) 1));
 
-        expect(routingConfig.getInterface(SW4_ETH1)).andReturn(
-                sw4Eth1).anyTimes();
+        expect(interfaceService.getInterfacesByPort(SW4_ETH1)).andReturn(
+                Collections.singleton(sw4Eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.40.1")))
+                .andReturn(sw4Eth1).anyTimes();
+
         interfaces.add(sw4Eth1);
 
-        expect(routingConfig.getInterface(SW1_ETH1)).andReturn(
-                sw1Eth1).anyTimes();
-        expect(routingConfig.getInterface(SW2_ETH1)).andReturn(
-                sw2Eth1).anyTimes();
-        expect(routingConfig.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
-        expect(routingConfig.getInterfaces()).andReturn(interfaces).anyTimes();
+        expect(interfaceService.getInterfacesByPort(SW1_ETH1)).andReturn(
+                Collections.singleton(sw1Eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.10.1")))
+                .andReturn(sw1Eth1).anyTimes();
+        expect(interfaceService.getInterfacesByPort(SW2_ETH1)).andReturn(
+                Collections.singleton(sw2Eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.20.1")))
+                .andReturn(sw2Eth1).anyTimes();
+        expect(interfaceService.getInterfacesByPort(SW3_ETH1)).andReturn(
+                Collections.singleton(sw3Eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(Ip4Address.valueOf("192.168.30.1")))
+                .andReturn(sw3Eth1).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
     }
 
     /**
@@ -599,8 +619,8 @@
         treatmentBuilder.setEthDst(MacAddress.valueOf(nextHopMacAddress));
 
         Set<ConnectPoint> ingressPoints = new HashSet<>();
-        for (Interface intf : routingConfig.getInterfaces()) {
-            if (!intf.equals(routingConfig.getInterface(egressPoint))) {
+        for (Interface intf : interfaces) {
+            if (!intf.connectPoint().equals(egressPoint)) {
                 ConnectPoint srcPort = intf.connectPoint();
                 ingressPoints.add(srcPort);
             }
@@ -621,7 +641,6 @@
      * A static MultiPointToSinglePointIntent builder, the returned intent is
      * equal to the input intent except that the id is different.
      *
-     *
      * @param intent the intent to be used for building a new intent
      * @param routeEntry the relative routeEntry of the intent
      * @return the newly constructed MultiPointToSinglePointIntent
diff --git a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
index 19c1d50..164b54d 100644
--- a/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
+++ b/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
@@ -29,6 +29,9 @@
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
@@ -41,9 +44,9 @@
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentService;
 import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.routing.config.BgpConfig;
 import org.onosproject.routing.config.BgpPeer;
 import org.onosproject.routing.config.BgpSpeaker;
-import org.onosproject.routing.config.Interface;
 import org.onosproject.routing.config.InterfaceAddress;
 import org.onosproject.routing.config.RoutingConfigurationService;
 
@@ -53,6 +56,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
@@ -78,16 +82,21 @@
         }
     };
 
+    private static final ApplicationId CONFIG_APP_ID = APPID;
+
     private PeerConnectivityManager peerConnectivityManager;
     private IntentSynchronizer intentSynchronizer;
     private RoutingConfigurationService routingConfig;
+    private InterfaceService interfaceService;
+    private NetworkConfigService networkConfigService;
     private IntentService intentService;
 
-    private Map<String, BgpSpeaker> bgpSpeakers;
+    private Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers;
     private Map<String, Interface> interfaces;
     private Map<IpAddress, BgpPeer> peers;
 
-    private Map<String, BgpSpeaker> configuredBgpSpeakers;
+    private BgpConfig bgpConfig;
+
     private Map<String, Interface> configuredInterfaces;
     private Map<IpAddress, BgpPeer> configuredPeers;
     private List<PointToPointIntent> intentList;
@@ -119,9 +128,12 @@
     public void setUp() throws Exception {
         super.setUp();
         routingConfig = createMock(RoutingConfigurationService.class);
+        interfaceService = createMock(InterfaceService.class);
+        networkConfigService = createMock(NetworkConfigService.class);
+        bgpConfig = createMock(BgpConfig.class);
 
-        // These will set expectations on routingConfig
-        bgpSpeakers = Collections.unmodifiableMap(setUpBgpSpeakers());
+        // These will set expectations on routingConfig and interfaceService
+        bgpSpeakers = setUpBgpSpeakers();
         interfaces = Collections.unmodifiableMap(setUpInterfaces());
         peers = Collections.unmodifiableMap(setUpPeers());
 
@@ -134,31 +146,20 @@
      *
      * @return configured BGP speakers as a map from speaker name to speaker
      */
-    private Map<String, BgpSpeaker> setUpBgpSpeakers() {
+    private Set<BgpConfig.BgpSpeakerConfig> setUpBgpSpeakers() {
 
-        configuredBgpSpeakers = new HashMap<>();
+        BgpConfig.BgpSpeakerConfig speaker1 = new BgpConfig.BgpSpeakerConfig(
+                s1Eth100, Collections.singleton(IpAddress.valueOf("192.168.10.1")));
 
-        BgpSpeaker bgpSpeaker1 = new BgpSpeaker(
-                "bgpSpeaker1",
-                "00:00:00:00:00:00:00:01", 100,
-                "00:00:00:00:00:01");
-        List<InterfaceAddress> interfaceAddresses1 = new LinkedList<>();
-        interfaceAddresses1.add(new InterfaceAddress(dpid1, 1, "192.168.10.101"));
-        bgpSpeaker1.setInterfaceAddresses(interfaceAddresses1);
-        configuredBgpSpeakers.put(bgpSpeaker1.name(), bgpSpeaker1);
+        BgpConfig.BgpSpeakerConfig speaker2 = new BgpConfig.BgpSpeakerConfig(
+                s1Eth100, Sets.newHashSet(IpAddress.valueOf("192.168.20.1"),
+                IpAddress.valueOf("192.168.30.1")));
 
-        // BGP speaker2 is attached to the same switch port with speaker1
-        BgpSpeaker bgpSpeaker2 = new BgpSpeaker(
-                "bgpSpeaker2",
-                "00:00:00:00:00:00:00:01", 100,
-                "00:00:00:00:00:02");
-        List<InterfaceAddress> interfaceAddresses2 = new LinkedList<>();
-        interfaceAddresses2.add(new InterfaceAddress(dpid2, 1, "192.168.20.101"));
-        interfaceAddresses2.add(new InterfaceAddress(dpid2, 1, "192.168.30.101"));
-        bgpSpeaker2.setInterfaceAddresses(interfaceAddresses2);
-        configuredBgpSpeakers.put(bgpSpeaker2.name(), bgpSpeaker2);
+        Set<BgpConfig.BgpSpeakerConfig> bgpSpeakers = Sets.newHashSet();
+        bgpSpeakers.add(speaker1);
+        bgpSpeakers.add(speaker2);
 
-        return configuredBgpSpeakers;
+        return bgpSpeakers;
     }
 
     /**
@@ -201,26 +202,31 @@
                 VlanId.NONE);
         configuredInterfaces.put(interfaceSw2Eth1intf2, intfsw2eth1intf2);
 
-        expect(routingConfig.getInterface(s1Eth1))
+        expect(interfaceService.getInterfacesByPort(s1Eth1))
+                .andReturn(Collections.singleton(intfsw1eth1)).anyTimes();
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
+                .andReturn(Collections.singleton(intfsw1eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
                 .andReturn(intfsw1eth1).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.10.101")))
-                .andReturn(intfsw1eth1).anyTimes();
-        expect(routingConfig.getInterface(s2Eth1))
+        expect(interfaceService.getInterfacesByPort(s2Eth1))
+                .andReturn(Collections.singleton(intfsw2eth1)).anyTimes();
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
+                .andReturn(Collections.singleton(intfsw2eth1)).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
                 .andReturn(intfsw2eth1).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.20.101")))
-                .andReturn(intfsw2eth1).anyTimes();
-        //expect(routingConfig.getInterface(s2Eth1))
-        //        .andReturn(intfsw2eth1intf2).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.30.101")))
+
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
+                .andReturn(Collections.singleton(intfsw2eth1intf2)).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
                 .andReturn(intfsw2eth1intf2).anyTimes();
 
         // Non-existent interface used during one of the tests
-        expect(routingConfig.getInterface(new ConnectPoint(
-                    DeviceId.deviceId(SdnIp.dpidToUri("00:00:00:00:00:00:01:00")),
-                    PortNumber.portNumber(1))))
+        expect(interfaceService.getInterfacesByPort(new ConnectPoint(
+                DeviceId.deviceId(SdnIp.dpidToUri("00:00:00:00:00:00:01:00")),
+                PortNumber.portNumber(1))))
                     .andReturn(null).anyTimes();
 
-        expect(routingConfig.getInterfaces()).andReturn(
+        expect(interfaceService.getInterfaces()).andReturn(
                 Sets.newHashSet(configuredInterfaces.values())).anyTimes();
 
         return configuredInterfaces;
@@ -398,7 +404,6 @@
      * Sets up intents for ICMP paths.
      */
     private void setUpIcmpIntents() {
-
         // Start to build intents between BGP speaker1 and BGP peer1
         icmpPathintentConstructor(
                 "192.168.10.101/32", "192.168.10.1/32", s1Eth100, s1Eth1);
@@ -415,7 +420,6 @@
                 "192.168.30.101/32", "192.168.30.1/32", s1Eth100, s2Eth1);
         icmpPathintentConstructor(
                 "192.168.30.1/32", "192.168.30.101/32", s2Eth1, s1Eth100);
-
     }
 
     /**
@@ -424,22 +428,28 @@
      * @throws TestUtilsException if exceptions when using TestUtils
      */
     private void initPeerConnectivity() throws TestUtilsException {
-
         expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
-        expect(routingConfig.getBgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
+        expect(bgpConfig.bgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
+        replay(bgpConfig);
+        expect(networkConfigService.getConfig(APPID, BgpConfig.class)).andReturn(bgpConfig).anyTimes();
+        replay(networkConfigService);
         replay(routingConfig);
+        replay(interfaceService);
 
         intentService = createMock(IntentService.class);
         replay(intentService);
 
         intentSynchronizer = new IntentSynchronizer(APPID, intentService,
-                                                    null, routingConfig);
+                                                    null, routingConfig,
+                                                    interfaceService);
         intentSynchronizer.leaderChanged(true);
         TestUtils.setField(intentSynchronizer, "isActivatedLeader", true);
 
         peerConnectivityManager =
             new PeerConnectivityManager(APPID, intentSynchronizer,
-                                        routingConfig);
+                                        networkConfigService,
+                                        CONFIG_APP_ID,
+                                        interfaceService);
     }
 
     /**
@@ -472,42 +482,28 @@
      */
     @Test
     public void testNullInterfaces() {
-        reset(routingConfig);
-        expect(routingConfig.getInterfaces()).andReturn(
+        reset(interfaceService);
+
+        expect(interfaceService.getInterfaces()).andReturn(
                 Sets.<Interface>newHashSet()).anyTimes();
-        expect(routingConfig.getInterface(s2Eth1))
+        expect(interfaceService.getInterfacesByPort(s2Eth1))
+                .andReturn(Collections.emptySet()).anyTimes();
+        expect(interfaceService.getInterfacesByPort(s1Eth1))
+        .andReturn(Collections.emptySet()).anyTimes();
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.10.101")))
+                .andReturn(Collections.emptySet()).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.10.1")))
                 .andReturn(null).anyTimes();
-        expect(routingConfig.getInterface(s1Eth1))
-        .andReturn(null).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.10.101")))
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.20.101")))
+                .andReturn(Collections.emptySet()).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.20.1")))
                 .andReturn(null).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.20.101")))
-                .andReturn(null).anyTimes();
-        expect(routingConfig.getInterface(IpAddress.valueOf("192.168.30.101")))
+        expect(interfaceService.getInterfacesByIp(IpAddress.valueOf("192.168.30.101")))
+                .andReturn(Collections.emptySet()).anyTimes();
+        expect(interfaceService.getMatchingInterface(IpAddress.valueOf("192.168.30.1")))
                 .andReturn(null).anyTimes();
 
-        expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
-        expect(routingConfig.getBgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
-        replay(routingConfig);
-
-        reset(intentService);
-        replay(intentService);
-        peerConnectivityManager.start();
-        verify(intentService);
-    }
-
-    /**
-     *  Tests a corner case, when there are no BGP peers in the configuration.
-     */
-    @Test
-    public void testNullBgpPeers() {
-        reset(routingConfig);
-        expect(routingConfig.getInterfaces()).andReturn(
-                Sets.newHashSet(interfaces.values())).anyTimes();
-
-        expect(routingConfig.getBgpPeers()).andReturn(new HashMap<>()).anyTimes();
-        expect(routingConfig.getBgpSpeakers()).andReturn(bgpSpeakers).anyTimes();
-        replay(routingConfig);
+        replay(interfaceService);
 
         reset(intentService);
         replay(intentService);
@@ -521,12 +517,11 @@
     @Test
     public void testNullBgpSpeakers() {
         reset(routingConfig);
-        expect(routingConfig.getInterfaces()).andReturn(
-                Sets.newHashSet(interfaces.values())).anyTimes();
+        reset(bgpConfig);
 
+        expect(bgpConfig.bgpSpeakers()).andReturn(Collections.emptySet()).anyTimes();
+        replay(bgpConfig);
         expect(routingConfig.getBgpPeers()).andReturn(peers).anyTimes();
-        expect(routingConfig.getBgpSpeakers()).andReturn(
-                Collections.emptyMap()).anyTimes();
         replay(routingConfig);
 
         reset(intentService);
@@ -562,7 +557,6 @@
         interfaceAddresses100.add(new InterfaceAddress(dpid1, 1, "192.168.10.201"));
         interfaceAddresses100.add(new InterfaceAddress(dpid2, 1, "192.168.20.201"));
         bgpSpeaker100.setInterfaceAddresses(interfaceAddresses100);
-        configuredBgpSpeakers.put(bgpSpeaker100.name(), bgpSpeaker100);
         testConnectionSetup();
     }
 }
diff --git a/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java b/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
index e66c81b..810ca6c 100644
--- a/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
+++ b/core/net/src/main/java/org/onosproject/net/config/impl/NetworkConfigLoader.java
@@ -23,6 +23,7 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.config.Config;
 import org.onosproject.net.config.NetworkConfigEvent;
 import org.onosproject.net.config.NetworkConfigListener;
 import org.onosproject.net.config.NetworkConfigService;
@@ -49,11 +50,11 @@
 
     // FIXME: Add mutual exclusion to make sure this happens only once per startup.
 
-    private Map<InnerConfigPosition, ObjectNode> jsons = Maps.newHashMap();
+    private final Map<InnerConfigPosition, ObjectNode> jsons = Maps.newConcurrentMap();
 
     private final NetworkConfigListener configListener = new InnerConfigListener();
 
-    ObjectNode root;
+    private ObjectNode root;
 
     @Activate
     public void activate() {
@@ -101,24 +102,24 @@
      * Inner class that allows for tracking of JSON class configurations.
      */
     private final class InnerConfigPosition {
-        private String subjectKey, subject, classKey;
+        private final String subjectKey, subject, configKey;
 
-        private String getSubjectKey() {
+        private String subjectKey() {
             return subjectKey;
         }
 
-        private String getSubject() {
+        private String subject() {
             return subject;
         }
 
-        private String getClassKey() {
-            return classKey;
+        private String configKey() {
+            return configKey;
         }
 
-        private InnerConfigPosition(String subjectKey, String subject, String classKey) {
+        private InnerConfigPosition(String subjectKey, String subject, String configKey) {
             this.subjectKey = subjectKey;
             this.subject = subject;
-            this.classKey = classKey;
+            this.configKey = configKey;
         }
 
         @Override
@@ -128,15 +129,16 @@
             }
             if (obj instanceof InnerConfigPosition) {
                 final InnerConfigPosition that = (InnerConfigPosition) obj;
-                return Objects.equals(this.subjectKey, that.subjectKey) && Objects.equals(this.subject, that.subject)
-                        && Objects.equals(this.classKey, that.classKey);
+                return Objects.equals(this.subjectKey, that.subjectKey)
+                        && Objects.equals(this.subject, that.subject)
+                        && Objects.equals(this.configKey, that.configKey);
             }
             return false;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(subjectKey, subject, classKey);
+            return Objects.hash(subjectKey, subject, configKey);
         }
     }
 
@@ -174,38 +176,41 @@
     }
 
     /**
-     * Apply the configurations associated with all of the config classes that are imported and have not yet been
-     * applied.
+     * Apply the configurations associated with all of the config classes that
+     * are imported and have not yet been applied.
      */
-    protected void applyConfigurations() {
+    private void applyConfigurations() {
         Iterator<Map.Entry<InnerConfigPosition, ObjectNode>> iter = jsons.entrySet().iterator();
 
         Map.Entry<InnerConfigPosition, ObjectNode> entry;
         InnerConfigPosition key;
         ObjectNode node;
         String subjectKey;
-        String subject;
-        String classKey;
+        String subjectString;
+        String configKey;
 
         while (iter.hasNext()) {
             entry = iter.next();
             node = entry.getValue();
             key = entry.getKey();
-            subjectKey = key.getSubjectKey();
-            subject = key.getSubject();
-            classKey = key.getClassKey();
+            subjectKey = key.subjectKey();
+            subjectString = key.subject();
+            configKey = key.configKey();
+
+            Class<? extends Config> configClass =
+                    networkConfigService.getConfigClass(subjectKey, configKey);
             //Check that the config class has been imported
-            if (networkConfigService.getConfigClass(subjectKey, subject) != null) {
+            if (configClass != null) {
+
+                Object subject = networkConfigService.getSubjectFactory(subjectKey).
+                        createSubject(subjectString);
 
                 //Apply the configuration
-                networkConfigService.applyConfig(networkConfigService.getSubjectFactory(subjectKey).
-                                createSubject(subject),
-                        networkConfigService.getConfigClass(subjectKey, classKey), node);
+                networkConfigService.applyConfig(subject, configClass, node);
 
                 //Now that it has been applied the corresponding JSON entry is no longer needed
-                jsons.remove(key);
+                iter.remove();
             }
-
         }
     }
 
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
index fe369ae..99d401a 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostManager.java
@@ -24,6 +24,7 @@
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.provider.AbstractListenerProviderRegistry;
 import org.onosproject.core.Permission;
 import org.onosproject.net.config.NetworkConfigEvent;
@@ -86,6 +87,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected NetworkConfigService networkConfigService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected InterfaceService interfaceService;
+
     private HostMonitor monitor;
 
     @Activate
@@ -93,7 +97,7 @@
         store.setDelegate(delegate);
         eventDispatcher.addSink(HostEvent.class, listenerRegistry);
         networkConfigService.addListener(networkConfigListener);
-        monitor = new HostMonitor(deviceService, packetService, this);
+        monitor = new HostMonitor(packetService, this, interfaceService);
         monitor.start();
         log.info("Started");
     }
diff --git a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
index 6dc71fc..fe25236 100644
--- a/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onosproject/net/host/impl/HostMonitor.java
@@ -20,26 +20,23 @@
 import org.onlab.packet.ARP;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.ICMP6;
-import org.onlab.packet.IpAddress;
 import org.onlab.packet.IPv6;
+import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onlab.packet.ndp.NeighborDiscoveryOptions;
 import org.onlab.packet.ndp.NeighborSolicitation;
 import org.onlab.util.Timer;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.instructions.Instruction;
 import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.host.HostProvider;
 import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.host.PortAddresses;
 import org.onosproject.net.packet.DefaultOutboundPacket;
 import org.onosproject.net.packet.OutboundPacket;
 import org.onosproject.net.packet.PacketService;
@@ -63,9 +60,9 @@
  * </p>
  */
 public class HostMonitor implements TimerTask {
-    private DeviceService deviceService;
     private PacketService packetService;
     private HostManager hostManager;
+    private InterfaceService interfaceService;
 
     private final Set<IpAddress> monitoredAddresses;
 
@@ -80,20 +77,19 @@
     /**
      * Creates a new host monitor.
      *
-     * @param deviceService device service used to find edge ports
      * @param packetService packet service used to send packets on the data plane
      * @param hostManager host manager used to look up host information and
      * probe existing hosts
+     * @param interfaceService interface service for interface information
      */
-    public HostMonitor(DeviceService deviceService, PacketService packetService,
-            HostManager hostManager) {
+    public HostMonitor(PacketService packetService, HostManager hostManager,
+                       InterfaceService interfaceService) {
 
-        this.deviceService = deviceService;
         this.packetService = packetService;
         this.hostManager = hostManager;
+        this.interfaceService = interfaceService;
 
-        monitoredAddresses = Collections.newSetFromMap(
-                new ConcurrentHashMap<IpAddress, Boolean>());
+        monitoredAddresses = Collections.newSetFromMap(new ConcurrentHashMap<>());
         hostProviders = new ConcurrentHashMap<>();
     }
 
@@ -176,29 +172,21 @@
      * @param targetIp IP address to send the request for
      */
     private void sendArpNdpRequest(IpAddress targetIp) {
-        // Find ports with an IP address in the target's subnet and sent ARP/ND
-        // probes out those ports.
-        for (Device device : deviceService.getDevices()) {
-            for (Port port : deviceService.getPorts(device.id())) {
-                ConnectPoint cp = new ConnectPoint(device.id(), port.number());
-                Set<PortAddresses> portAddressSet =
-                    hostManager.getAddressBindingsForPort(cp);
+        Interface intf = interfaceService.getMatchingInterface(targetIp);
 
-                for (PortAddresses portAddresses : portAddressSet) {
-                    for (InterfaceIpAddress ia : portAddresses.ipAddresses()) {
-                        if (ia.subnetAddress().contains(targetIp)) {
-                            sendArpNdpProbe(device.id(), port, targetIp,
-                                            ia.ipAddress(),
-                                            portAddresses.mac(),
-                                            portAddresses.vlan());
-                        }
-                    }
-                }
+        if (intf == null) {
+            return;
+        }
+
+        for (InterfaceIpAddress ia : intf.ipAddresses()) {
+            if (ia.subnetAddress().contains(targetIp)) {
+                sendArpNdpProbe(intf.connectPoint(), targetIp, ia.ipAddress(),
+                        intf.mac(), intf.vlan());
             }
         }
     }
 
-    private void sendArpNdpProbe(DeviceId deviceId, Port port,
+    private void sendArpNdpProbe(ConnectPoint connectPoint,
                                  IpAddress targetIp,
                                  IpAddress sourceIp, MacAddress sourceMac,
                                  VlanId vlan) {
@@ -215,14 +203,14 @@
         }
 
         List<Instruction> instructions = new ArrayList<>();
-        instructions.add(Instructions.createOutput(port.number()));
+        instructions.add(Instructions.createOutput(connectPoint.port()));
 
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-            .setOutput(port.number())
+            .setOutput(connectPoint.port())
             .build();
 
         OutboundPacket outboundPacket =
-            new DefaultOutboundPacket(deviceId, treatment,
+            new DefaultOutboundPacket(connectPoint.deviceId(), treatment,
                                       ByteBuffer.wrap(probePacket.serialize()));
 
         packetService.emit(outboundPacket);
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index 8fad769..06d0e9a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -98,7 +98,7 @@
                 partialTree = true;
 
                 for (Link link : path.links()) {
-                    if (links.containsKey(link.src().deviceId())) {
+                    if (links.containsKey(link.dst().deviceId())) {
                         // We've already reached the existing tree with the first
                         // part of this path. Add the merging point with different
                         // incoming port, but don't add the remainder of the path
diff --git a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
index b5acde6..1a56d0e 100644
--- a/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
+++ b/core/net/src/main/java/org/onosproject/net/proxyarp/impl/ProxyArpManager.java
@@ -34,6 +34,8 @@
 import org.onlab.packet.ndp.NeighborDiscoveryOptions;
 import org.onlab.packet.ndp.NeighborSolicitation;
 import org.onosproject.core.Permission;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.device.DeviceService;
@@ -41,8 +43,6 @@
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.host.HostService;
-import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.host.PortAddresses;
 import org.onosproject.net.link.LinkService;
 import org.onosproject.net.packet.DefaultOutboundPacket;
 import org.onosproject.net.packet.InboundPacket;
@@ -53,9 +53,7 @@
 import org.slf4j.Logger;
 
 import java.nio.ByteBuffer;
-import java.util.HashSet;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -95,17 +93,15 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ProxyArpStore store;
 
-    /**
-     * Listens to both device service and link service to determine
-     * whether a port is internal or external.
-     */
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected InterfaceService interfaceService;
+
     @Activate
     public void activate() {
         store.setDelegate(this::sendTo);
         log.info("Started");
     }
 
-
     @Deactivate
     public void deactivate() {
         store.setDelegate(null);
@@ -140,21 +136,18 @@
 
         VlanId vlan = vlanId(eth.getVlanID());
 
-        if (isOutsidePort(inPort)) {
+        if (hasIpAddress(inPort)) {
             // If the request came from outside the network, only reply if it was
             // for one of our external addresses.
-            Set<PortAddresses> addressSet =
-                    hostService.getAddressBindingsForPort(inPort);
 
-            for (PortAddresses addresses : addressSet) {
-                for (InterfaceIpAddress ia : addresses.ipAddresses()) {
-                    if (ia.ipAddress().equals(targetAddress)) {
-                        Ethernet arpReply =
-                                ARP.buildArpReply(targetAddress, addresses.mac(), eth);
-                        sendTo(arpReply, inPort);
-                    }
-                }
-            }
+            interfaceService.getInterfacesByPort(inPort)
+                    .stream()
+                    .filter(intf -> intf.ipAddresses()
+                            .stream()
+                            .anyMatch(ia -> ia.ipAddress().equals(targetAddress)))
+                    .forEach(intf -> buildAndSendArp(targetAddress, intf.mac(), eth, inPort));
+
+            // Stop here and don't proxy ARPs if the port has an IP address
             return;
         }
 
@@ -164,7 +157,7 @@
 
         Host dst = null;
         Host src = hostService.getHost(hostId(eth.getSourceMAC(),
-                                              vlanId(eth.getVlanID())));
+                vlanId(eth.getVlanID())));
 
         for (Host host : hosts) {
             if (host.vlan().equals(vlan)) {
@@ -175,8 +168,7 @@
 
         if (src != null && dst != null) {
             // We know the target host so we can respond
-            Ethernet arpReply = ARP.buildArpReply(targetAddress, dst.mac(), eth);
-            sendTo(arpReply, inPort);
+            buildAndSendArp(targetAddress, dst.mac(), eth, inPort);
             return;
         }
 
@@ -185,16 +177,14 @@
         // address. Forward it over to the correct port.
         Ip4Address source =
                 Ip4Address.valueOf(arp.getSenderProtocolAddress());
-        Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
+
         boolean matched = false;
-        for (PortAddresses pa : sourceAddresses) {
-            for (InterfaceIpAddress ia : pa.ipAddresses()) {
-                if (ia.ipAddress().equals(source) &&
-                        pa.vlan().equals(vlan)) {
-                    matched = true;
-                    sendTo(eth, pa.connectPoint());
-                    break;
-                }
+        Set<Interface> interfaces = interfaceService.getInterfacesByIp(source);
+        for (Interface intf : interfaces) {
+            if (intf.vlan().equals(vlan)) {
+                matched = true;
+                sendTo(eth, intf.connectPoint());
+                break;
             }
         }
 
@@ -202,10 +192,8 @@
             return;
         }
 
-        //
         // The request couldn't be resolved.
         // Flood the request on all ports except the incoming port.
-        //
         flood(eth, inPort);
     }
 
@@ -219,42 +207,14 @@
 
         // If the request came from outside the network, only reply if it was
         // for one of our external addresses.
-        if (isOutsidePort(inPort)) {
-            Set<PortAddresses> addressSet =
-                    hostService.getAddressBindingsForPort(inPort);
-
-            for (PortAddresses addresses : addressSet) {
-                for (InterfaceIpAddress ia : addresses.ipAddresses()) {
-                    if (ia.ipAddress().equals(targetAddress)) {
-                        Ethernet ndpReply =
-                                buildNdpReply(targetAddress, addresses.mac(), eth);
-                        sendTo(ndpReply, inPort);
-                    }
-                }
-            }
+        if (hasIpAddress(inPort)) {
+            interfaceService.getInterfacesByPort(inPort)
+                    .stream()
+                    .filter(intf -> intf.ipAddresses()
+                            .stream()
+                            .anyMatch(ia -> ia.ipAddress().equals(targetAddress)))
+                    .forEach(intf -> buildAndSendNdp(targetAddress, intf.mac(), eth, inPort));
             return;
-        } else {
-            // If the source address matches one of our external addresses
-            // it could be a request from an internal host to an external
-            // address. Forward it over to the correct ports.
-            Ip6Address source =
-                    Ip6Address.valueOf(ipv6.getSourceAddress());
-            Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
-            boolean matched = false;
-            for (PortAddresses pa : sourceAddresses) {
-                for (InterfaceIpAddress ia : pa.ipAddresses()) {
-                    if (ia.ipAddress().equals(source) &&
-                            pa.vlan().equals(vlan)) {
-                        matched = true;
-                        sendTo(eth, pa.connectPoint());
-                        break;
-                    }
-                }
-            }
-
-            if (matched) {
-                return;
-            }
         }
 
         // Continue with normal proxy ARP case
@@ -272,23 +232,49 @@
             }
         }
 
-        if (src == null || dst == null) {
-            //
-            // The request couldn't be resolved.
-            // Flood the request on all ports except the incoming ports.
-            //
-            flood(eth, inPort);
+        if (src != null || dst != null) {
+            // We know the target host so we can respond
+            buildAndSendNdp(targetAddress, dst.mac(), eth, inPort);
             return;
         }
 
-        //
-        // Reply on the port the request was received on
-        //
-        Ethernet ndpReply = buildNdpReply(targetAddress, dst.mac(), eth);
-        sendTo(ndpReply, inPort);
+        // If the source address matches one of our external addresses
+        // it could be a request from an internal host to an external
+        // address. Forward it over to the correct port.
+        Ip6Address source =
+                Ip6Address.valueOf(ipv6.getSourceAddress());
+
+        boolean matched = false;
+
+        Set<Interface> interfaces = interfaceService.getInterfacesByIp(source);
+        for (Interface intf : interfaces) {
+            if (intf.vlan().equals(vlan)) {
+                matched = true;
+                sendTo(eth, intf.connectPoint());
+                break;
+            }
+        }
+
+        if (matched) {
+            return;
+        }
+
+        // The request couldn't be resolved.
+        // Flood the request on all ports except the incoming ports.
+        flood(eth, inPort);
     }
     //TODO checkpoint
 
+    private void buildAndSendArp(Ip4Address srcIp, MacAddress srcMac,
+                                 Ethernet request, ConnectPoint port) {
+        sendTo(ARP.buildArpReply(srcIp, srcMac, request), port);
+    }
+
+    private void buildAndSendNdp(Ip6Address srcIp, MacAddress srcMac,
+                                 Ethernet request, ConnectPoint port) {
+        sendTo(buildNdpReply(srcIp, srcMac, request), port);
+    }
+
     /**
      * Outputs the given packet out the given port.
      *
@@ -314,30 +300,18 @@
     }
 
     /**
-     * Finds ports with an address in the subnet of the target address.
-     *
-     * @param target the target address to find a matching port for
-     * @return a set of PortAddresses describing ports in the subnet
-     */
-    private Set<PortAddresses> findPortsInSubnet(IpAddress target) {
-        Set<PortAddresses> result = new HashSet<>();
-        for (PortAddresses addresses : hostService.getAddressBindings()) {
-            result.addAll(addresses.ipAddresses().stream().filter(ia -> ia.subnetAddress().contains(target)).
-                    map(ia -> addresses).collect(Collectors.toList()));
-        }
-        return result;
-    }
-
-    /**
-     * Returns whether the given port is an outside-facing port with an IP
-     * address configured.
+     * Returns whether the given port has any IP addresses configured or not.
      *
      * @param port the port to check
-     * @return true if the port is an outside-facing port, otherwise false
+     * @return true if the port has at least one IP address configured,
+     * otherwise false
      */
-    private boolean isOutsidePort(ConnectPoint port) {
-        // TODO: Is this sufficient to identify outside-facing ports: just having IP addresses on a port?
-        return !hostService.getAddressBindingsForPort(port).isEmpty();
+    private boolean hasIpAddress(ConnectPoint port) {
+        return interfaceService.getInterfacesByPort(port)
+                .stream()
+                .map(intf -> intf.ipAddresses())
+                .findAny()
+                .isPresent();
     }
 
     @Override
@@ -418,7 +392,7 @@
         ByteBuffer buf = ByteBuffer.wrap(request.serialize());
 
         for (ConnectPoint connectPoint : edgeService.getEdgePoints()) {
-            if (isOutsidePort(connectPoint) || connectPoint.equals(inPort)) {
+            if (hasIpAddress(connectPoint) || connectPoint.equals(inPort)) {
                 continue;
             }
 
@@ -427,7 +401,6 @@
             packetService.emit(new DefaultOutboundPacket(connectPoint.deviceId(),
                                                          builder.build(), buf));
         }
-
     }
 
     /**
diff --git a/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java b/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
index 90cf6b4..d6ff473 100644
--- a/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
+++ b/core/net/src/test/java/org/onosproject/net/host/impl/HostMonitorTest.java
@@ -26,6 +26,8 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -94,7 +96,7 @@
         expectLastCall().once();
         replay(hostProvider);
 
-        hostMonitor = new HostMonitor(null, null, hostManager);
+        hostMonitor = new HostMonitor(null, hostManager, null);
 
         hostMonitor.registerHostProvider(hostProvider);
         hostMonitor.addMonitoringFor(TARGET_IP_ADDR);
@@ -129,16 +131,20 @@
                 new PortAddresses(cp, Collections.singleton(IA1), sourceMac, VlanId.NONE);
 
         expect(hostManager.getHostsByIp(TARGET_IP_ADDR))
-                .andReturn(Collections.<Host>emptySet()).anyTimes();
-        expect(hostManager.getAddressBindingsForPort(cp))
-                .andReturn(Collections.singleton(pa)).anyTimes();
+                .andReturn(Collections.emptySet()).anyTimes();
         replay(hostManager);
 
+        InterfaceService interfaceService = createMock(InterfaceService.class);
+        expect(interfaceService.getMatchingInterface(TARGET_IP_ADDR))
+                .andReturn(new Interface(cp, Collections.singleton(IA1), sourceMac, VlanId.NONE))
+                .anyTimes();
+        replay(interfaceService);
+
         TestPacketService packetService = new TestPacketService();
 
 
         // Run the test
-        hostMonitor = new HostMonitor(deviceService, packetService, hostManager);
+        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService);
 
         hostMonitor.addMonitoringFor(TARGET_IP_ADDR);
         hostMonitor.run(null);
@@ -197,16 +203,20 @@
                                   VlanId.vlanId(vlan));
 
         expect(hostManager.getHostsByIp(TARGET_IP_ADDR))
-                .andReturn(Collections.<Host>emptySet()).anyTimes();
-        expect(hostManager.getAddressBindingsForPort(cp))
-                .andReturn(Collections.singleton(pa)).anyTimes();
+                .andReturn(Collections.emptySet()).anyTimes();
         replay(hostManager);
 
+        InterfaceService interfaceService = createMock(InterfaceService.class);
+        expect(interfaceService.getMatchingInterface(TARGET_IP_ADDR))
+                .andReturn(new Interface(cp, Collections.singleton(IA1), sourceMac, VlanId.vlanId(vlan)))
+                .anyTimes();
+        replay(interfaceService);
+
         TestPacketService packetService = new TestPacketService();
 
 
         // Run the test
-        hostMonitor = new HostMonitor(deviceService, packetService, hostManager);
+        hostMonitor = new HostMonitor(packetService, hostManager, interfaceService);
 
         hostMonitor.addMonitoringFor(TARGET_IP_ADDR);
         hostMonitor.run(null);
diff --git a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
index e96602b..3978c48 100644
--- a/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -23,8 +23,11 @@
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultHost;
 import org.onosproject.net.Device;
@@ -44,7 +47,6 @@
 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.host.InterfaceIpAddress;
-import org.onosproject.net.host.PortAddresses;
 import org.onosproject.net.link.LinkListener;
 import org.onosproject.net.link.LinkService;
 import org.onosproject.net.packet.DefaultOutboundPacket;
@@ -57,12 +59,17 @@
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * Tests for the {@link ProxyArpManager} class.
@@ -104,6 +111,7 @@
     private DeviceService deviceService;
     private LinkService linkService;
     private HostService hostService;
+    private InterfaceService interfaceService;
 
     @Before
     public void setUp() throws Exception {
@@ -119,6 +127,9 @@
         hostService = createMock(HostService.class);
         proxyArp.hostService = hostService;
 
+        interfaceService = createMock(InterfaceService.class);
+        proxyArp.interfaceService = interfaceService;
+
         createTopology();
         proxyArp.deviceService = deviceService;
         proxyArp.linkService = linkService;
@@ -207,7 +218,7 @@
     }
 
     private void addAddressBindings() {
-        Set<PortAddresses> addresses = Sets.newHashSet();
+        Set<Interface> interfaces = Sets.newHashSet();
 
         for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) {
             ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
@@ -219,29 +230,28 @@
             Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
             InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
             InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
-            PortAddresses pa1 =
-                    new PortAddresses(cp, Sets.newHashSet(ia1),
-                            MacAddress.valueOf(2 * i - 1),
-                            VlanId.vlanId((short) 1));
-            PortAddresses pa2 =
-                    new PortAddresses(cp, Sets.newHashSet(ia2),
-                            MacAddress.valueOf(2 * i),
-                            VlanId.NONE);
+            Interface intf1 = new Interface(cp, Sets.newHashSet(ia1),
+                    MacAddress.valueOf(2 * i - 1),
+                    VlanId.vlanId((short) 1));
+            Interface intf2 = new Interface(cp, Sets.newHashSet(ia2),
+                    MacAddress.valueOf(2 * i),
+                    VlanId.NONE);
 
-            addresses.add(pa1);
-            addresses.add(pa2);
+            interfaces.add(intf1);
+            interfaces.add(intf2);
 
-            expect(hostService.getAddressBindingsForPort(cp))
-                    .andReturn(Sets.newHashSet(pa1, pa2)).anyTimes();
+            expect(interfaceService.getInterfacesByPort(cp))
+                    .andReturn(Sets.newHashSet(intf1, intf2)).anyTimes();
         }
 
-        expect(hostService.getAddressBindings()).andReturn(addresses).anyTimes();
+        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
 
         for (int i = 1; i <= NUM_FLOOD_PORTS; i++) {
             ConnectPoint cp = new ConnectPoint(getDeviceId(i + NUM_ADDRESS_PORTS),
                     P1);
-            expect(hostService.getAddressBindingsForPort(cp))
-                    .andReturn(Collections.<PortAddresses>emptySet()).anyTimes();
+
+            expect(interfaceService.getInterfacesByPort(cp))
+                    .andReturn(Collections.emptySet()).anyTimes();
         }
     }
 
@@ -254,6 +264,7 @@
     public void testNotKnown() {
         expect(hostService.getHostsByIp(IP1)).andReturn(Collections.<Host>emptySet());
         replay(hostService);
+        replay(interfaceService);
 
         assertFalse(proxyArp.isKnown(IP1));
     }
@@ -271,6 +282,7 @@
         expect(hostService.getHostsByIp(IP1))
                 .andReturn(Sets.newHashSet(host1, host2));
         replay(hostService);
+        replay(interfaceService);
 
         assertTrue(proxyArp.isKnown(IP1));
     }
@@ -296,6 +308,7 @@
         expect(hostService.getHost(HID2)).andReturn(requestor);
 
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
 
@@ -319,11 +332,14 @@
                 Collections.singleton(IP2));
 
         expect(hostService.getHostsByIp(IP1))
-                .andReturn(Collections.<Host>emptySet());
+                .andReturn(Collections.emptySet());
+        expect(interfaceService.getInterfacesByIp(IP2))
+                .andReturn(Collections.emptySet());
         expect(hostService.getHost(HID2)).andReturn(requestor);
 
 
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
 
@@ -354,9 +370,12 @@
 
         expect(hostService.getHostsByIp(IP1))
                 .andReturn(Collections.singleton(replyer));
+        expect(interfaceService.getInterfacesByIp(IP2))
+                .andReturn(Collections.emptySet());
         expect(hostService.getHost(HID2)).andReturn(requestor);
 
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, IP2, IP1);
 
@@ -382,6 +401,7 @@
 
         expect(hostService.getHost(HID2)).andReturn(requestor);
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REQUEST, MAC2, null, theirIp, ourFirstIp);
         isEdgePointReturn = true;
@@ -405,6 +425,7 @@
     @Test
     public void testReplyExternalPortBadRequest() {
         replay(hostService); // no further host service expectations
+        replay(interfaceService);
 
         Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
 
@@ -428,8 +449,13 @@
         Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
 
         expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
+        expect(interfaceService.getInterfacesByIp(ourIp))
+                .andReturn(Collections.singleton(new Interface(getLocation(1),
+                        Collections.singleton(new InterfaceIpAddress(ourIp, IpPrefix.valueOf("10.0.1.1/24"))),
+                        ourMac, VLAN1)));
         expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
         replay(hostService);
+        replay(interfaceService);
 
         // This is a request from something inside our network (like a BGP
         // daemon) to an external host.
@@ -462,6 +488,7 @@
         expect(hostService.getHost(HID1)).andReturn(host1);
         expect(hostService.getHost(HID2)).andReturn(host2);
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1);
 
@@ -482,6 +509,7 @@
     public void testForwardFlood() {
         expect(hostService.getHost(HID1)).andReturn(null);
         replay(hostService);
+        replay(interfaceService);
 
         Ethernet arpRequest = buildArp(ARP.OP_REPLY, MAC2, MAC1, IP2, IP1);
 
@@ -508,12 +536,7 @@
         assertEquals(NUM_FLOOD_PORTS - 1, packetService.packets.size());
 
         Collections.sort(packetService.packets,
-                new Comparator<OutboundPacket>() {
-                    @Override
-                    public int compare(OutboundPacket o1, OutboundPacket o2) {
-                        return o1.sendThrough().uri().compareTo(o2.sendThrough().uri());
-                    }
-                });
+                (o1, o2) -> o1.sendThrough().uri().compareTo(o2.sendThrough().uri()));
 
 
         for (int i = 0; i < NUM_FLOOD_PORTS - 1; i++) {
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/ConfigException.java b/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/ConfigException.java
new file mode 100644
index 0000000..071be6a
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/ConfigException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.incubator.net.config.basics;
+
+/**
+ * Signals that an error was encountered while reading/writing configuration.
+ */
+public class ConfigException extends Exception {
+
+    /**
+     * Constructs a new ConfigException with the given message.
+     *
+     * @param message message
+     */
+    public ConfigException(String message) {
+        super(message);
+    }
+
+    /**
+     * Constructs a new ConfigException with the given message and cause.
+     *
+     * @param message message
+     * @param cause cause
+     */
+    public ConfigException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java b/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
index 6244676..600fe3d 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/config/basics/InterfaceConfig.java
@@ -36,19 +36,41 @@
     public static final String MAC = "mac";
     public static final String VLAN = "vlan";
 
+    public static final String IP_MISSING_ERROR = "Must have at least one IP address";
+    public static final String MAC_MISSING_ERROR = "Must have a MAC address for each interface";
+    public static final String CONFIG_VALUE_ERROR = "Error parsing config value";
+
     /**
      * Retrieves all interfaces configured on this port.
      *
      * @return set of interfaces
+     * @throws ConfigException if there is any error in the JSON config
      */
-    public Set<Interface> getInterfaces() {
+    public Set<Interface> getInterfaces() throws ConfigException {
         Set<Interface> interfaces = Sets.newHashSet();
 
-        for (JsonNode intfNode : node.path(INTERFACES)) {
-            interfaces.add(new Interface(subject,
-                    getIps(intfNode),
-                    MacAddress.valueOf(intfNode.path(MAC).asText()),
-                    VlanId.vlanId(Short.parseShort(intfNode.path(VLAN).asText()))));
+        try {
+            for (JsonNode intfNode : node.path(INTERFACES)) {
+                Set<InterfaceIpAddress> ips = getIps(intfNode);
+                if (ips.isEmpty()) {
+                    throw new ConfigException(IP_MISSING_ERROR);
+                }
+
+                if (intfNode.path(MAC).isMissingNode()) {
+                    throw new ConfigException(MAC_MISSING_ERROR);
+                }
+
+                MacAddress mac = MacAddress.valueOf(intfNode.path(MAC).asText());
+
+                VlanId vlan = VlanId.NONE;
+                if (!intfNode.path(VLAN).isMissingNode()) {
+                    vlan = VlanId.vlanId(Short.valueOf(intfNode.path(VLAN).asText()));
+                }
+
+                interfaces.add(new Interface(subject, ips, mac, vlan));
+            }
+        } catch (IllegalArgumentException e) {
+            throw new ConfigException(CONFIG_VALUE_ERROR, e);
         }
 
         return interfaces;
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java b/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
index 09b8cf2..15ecf34 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/intf/Interface.java
@@ -25,6 +25,8 @@
 import java.util.Objects;
 import java.util.Set;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * An Interface maps network configuration information (such as addresses and
  * vlans) to a port in the network.
@@ -46,10 +48,10 @@
     public Interface(ConnectPoint connectPoint,
                      Set<InterfaceIpAddress> ipAddresses,
                      MacAddress macAddress, VlanId vlan) {
-        this.connectPoint = connectPoint;
-        this.ipAddresses = Sets.newHashSet(ipAddresses);
-        this.macAddress = macAddress;
-        this.vlan = vlan;
+        this.connectPoint = checkNotNull(connectPoint);
+        this.ipAddresses = Sets.newHashSet(checkNotNull(ipAddresses));
+        this.macAddress = checkNotNull(macAddress);
+        this.vlan = checkNotNull(vlan);
     }
 
     /**
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java
index 9415e8f..f82cdbf 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/intf/impl/InterfaceManager.java
@@ -26,19 +26,18 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.VlanId;
-import org.onosproject.net.config.NetworkConfigEvent;
-import org.onosproject.net.config.NetworkConfigListener;
-import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.incubator.net.config.basics.ConfigException;
 import org.onosproject.incubator.net.config.basics.InterfaceConfig;
 import org.onosproject.incubator.net.intf.Interface;
 import org.onosproject.incubator.net.intf.InterfaceService;
 import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Device;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -55,11 +54,11 @@
 
     private final Logger log = LoggerFactory.getLogger(getClass());
 
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected NetworkConfigService configService;
+    private static final Class<ConnectPoint> SUBJECT_CLASS = ConnectPoint.class;
+    private static final Class<InterfaceConfig> CONFIG_CLASS = InterfaceConfig.class;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
+    protected NetworkConfigService configService;
 
     private final InternalConfigListener listener = new InternalConfigListener();
 
@@ -69,14 +68,12 @@
     public void activate() {
         configService.addListener(listener);
 
-        for (Device d : deviceService.getDevices()) {
-            for (Port p : deviceService.getPorts(d.id())) {
-                InterfaceConfig config =
-                    configService.getConfig(new ConnectPoint(d.id(), p.number()), InterfaceConfig.class);
+        // TODO address concurrency issues here
+        for (ConnectPoint subject : configService.getSubjects(SUBJECT_CLASS, CONFIG_CLASS)) {
+            InterfaceConfig config = configService.getConfig(subject, CONFIG_CLASS);
 
-                if (config != null) {
-                    updateInterfaces(config);
-                }
+            if (config != null) {
+                updateInterfaces(config);
             }
         }
 
@@ -100,7 +97,11 @@
 
     @Override
     public Set<Interface> getInterfacesByPort(ConnectPoint port) {
-        return ImmutableSet.copyOf(interfaces.get(port));
+        Set<Interface> intfs = interfaces.get(port);
+        if (intfs == null) {
+            return Collections.emptySet();
+        }
+        return ImmutableSet.copyOf(intfs);
     }
 
     @Override
@@ -108,7 +109,9 @@
         return interfaces.values()
                 .stream()
                 .flatMap(set -> set.stream())
-                .filter(intf -> intf.ipAddresses().contains(ip))
+                .filter(intf -> intf.ipAddresses()
+                        .stream()
+                        .anyMatch(ia -> ia.ipAddress().equals(ip)))
                 .collect(collectingAndThen(toSet(), ImmutableSet::copyOf));
     }
 
@@ -139,7 +142,11 @@
     }
 
     private void updateInterfaces(InterfaceConfig intfConfig) {
-        interfaces.put(intfConfig.subject(), intfConfig.getInterfaces());
+        try {
+            interfaces.put(intfConfig.subject(), intfConfig.getInterfaces());
+        } catch (ConfigException e) {
+            log.error("Error in interface config", e);
+        }
     }
 
     private void removeInterfaces(ConnectPoint port) {