CORD-523 Introduce generic routing service in Segment Routing

Segment Routing now reacts to routes being added/removed through RouteService.

SR will disable SingleSwitchFibInstaller if vRouter is activated

SR will install a routing table entry on
    - The leaf where next hop attaches to
    - The other leaves that points packets to the leaf where next hop attaches to

Host handler no longer add any IP flow for hosts outside the configured subnet
    - We need to explicitly add a per host route via RouteService when needed (vSG)

Change suppressSubnet behavior
    - Before: do not push any flow
    - After: ignore subnet config but still push filtering obj with VLAN 4094
             ARP handler drops all packets from suppressed ports

Additional refactoring
    - Remove vRouterId. Gateway router now needs to be specify through route API
    - Limit the scope of some variables
    - Unify handler.init method name

Change-Id: Idd2fd19fa74e3fa6209eef5cf2ed79957715c5e9
diff --git a/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java b/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
index c24c3ca..34d6776 100644
--- a/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/AppConfigHandler.java
@@ -108,7 +108,7 @@
      *
      * @param deviceId device ID
      */
-    public void initVRouters(DeviceId deviceId) {
+    public void init(DeviceId deviceId) {
         SegmentRoutingAppConfig config =
                 srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
         populateVRouter(deviceId, getMacAddresses(config));
diff --git a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index 2cde3b9..4529389 100644
--- a/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -33,6 +33,7 @@
 import org.onosproject.net.packet.OutboundPacket;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
+import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -88,6 +89,13 @@
         ConnectPoint connectPoint = pkt.receivedFrom();
         DeviceId deviceId = connectPoint.deviceId();
 
+        SegmentRoutingAppConfig appConfig = srManager.cfgService
+                .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
+        if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
+            // Ignore ARP packets come from suppressed ports
+            return;
+        }
+
         if (!validateArpSpa(connectPoint, arp)) {
             log.debug("Ignore ARP packet discovered on {} with unexpected src protocol address {}.",
                     connectPoint, Ip4Address.valueOf(arp.getSenderProtocolAddress()));
diff --git a/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index 0770546..82a2829 100644
--- a/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -16,13 +16,10 @@
 
 package org.onosproject.segmentrouting;
 
-import com.google.common.collect.ImmutableSet;
-import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
-import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostLocation;
@@ -64,7 +61,7 @@
         flowObjectiveService = srManager.flowObjectiveService;
     }
 
-    protected void readInitialHosts(DeviceId devId) {
+    protected void init(DeviceId devId) {
         hostService.getHosts().forEach(host -> {
             DeviceId deviceId = host.location().deviceId();
             // The host does not attach to this device
@@ -106,8 +103,7 @@
 
             ips.forEach(ip -> {
                 // Populate IP table entry
-                if (ip.isIp4()) {
-                    addPerHostRoute(location, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(location, ip)) {
                     srManager.routingRulePopulator.populateRoute(
                             deviceId, ip.toIpPrefix(), mac, port);
                 }
@@ -144,8 +140,7 @@
 
             // Revoke IP table entry
             ips.forEach(ip -> {
-                if (ip.isIp4()) {
-                    removePerHostRoute(location, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(location, ip)) {
                     srManager.routingRulePopulator.revokeRoute(
                             deviceId, ip.toIpPrefix(), mac, port);
                 }
@@ -183,8 +178,7 @@
 
             // Revoke previous IP table entry
             prevIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    removePerHostRoute(prevLocation, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(prevLocation, ip)) {
                     srManager.routingRulePopulator.revokeRoute(
                             prevDeviceId, ip.toIpPrefix(), mac, prevPort);
                 }
@@ -207,8 +201,7 @@
 
             // Populate new IP table entry
             newIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    addPerHostRoute(newLocation, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(newLocation, ip)) {
                     srManager.routingRulePopulator.populateRoute(
                             newDeviceId, ip.toIpPrefix(), mac, newPort);
                 }
@@ -232,8 +225,7 @@
         if (accepted(event.prevSubject())) {
             // Revoke previous IP table entry
             prevIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    removePerHostRoute(prevLocation, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(prevLocation, ip)) {
                     srManager.routingRulePopulator.revokeRoute(
                             prevDeviceId, ip.toIpPrefix(), mac, prevPort);
                 }
@@ -243,8 +235,7 @@
         if (accepted(event.subject())) {
             // Populate new IP table entry
             newIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    addPerHostRoute(newLocation, ip.getIp4Address());
+                if (ip.isIp4() && srManager.deviceConfiguration.inSameSubnet(newLocation, ip)) {
                     srManager.routingRulePopulator.populateRoute(
                             newDeviceId, ip.toIpPrefix(), mac, newPort);
                 }
@@ -313,42 +304,7 @@
     }
 
     /**
-     * Add per host route to subnet list and populate the flow rule if the host
-     * does not belong to the configured subnet.
-     *
-     * @param location location of the host being added
-     * @param ip IP address of the host being added
-     */
-    private void addPerHostRoute(ConnectPoint location, Ip4Address ip) {
-        Ip4Prefix portSubnet = srManager.deviceConfiguration.getPortSubnet(
-                location.deviceId(), location.port());
-        if (portSubnet != null && !portSubnet.contains(ip)) {
-            Ip4Prefix ip4Prefix = ip.toIpPrefix().getIp4Prefix();
-            srManager.deviceConfiguration.addSubnet(location, ip4Prefix);
-            srManager.defaultRoutingHandler.populateSubnet(location,
-                    ImmutableSet.of(ip4Prefix));
-        }
-    }
-
-    /**
-     * Remove per host route from subnet list and revoke the flow rule if the
-     * host does not belong to the configured subnet.
-     *
-     * @param location location of the host being removed
-     * @param ip IP address of the host being removed
-     */
-    private void removePerHostRoute(ConnectPoint location, Ip4Address ip) {
-        Ip4Prefix portSubnet = srManager.deviceConfiguration.getPortSubnet(
-                location.deviceId(), location.port());
-        if (portSubnet != null && !portSubnet.contains(ip)) {
-            Ip4Prefix ip4Prefix = ip.toIpPrefix().getIp4Prefix();
-            srManager.deviceConfiguration.removeSubnet(location, ip4Prefix);
-            srManager.defaultRoutingHandler.revokeSubnet(ImmutableSet.of(ip4Prefix));
-        }
-    }
-
-    /**
-     * Check if a host is accepted or not.
+     * Determines whether a host should be accepted by SR or not.
      *
      * @param host host to be checked
      * @return true if segment routing accepts the host
diff --git a/src/main/java/org/onosproject/segmentrouting/RouteHandler.java b/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
new file mode 100644
index 0000000..694e1b0
--- /dev/null
+++ b/src/main/java/org/onosproject/segmentrouting/RouteHandler.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.segmentrouting;
+
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.incubator.net.routing.ResolvedRoute;
+import org.onosproject.incubator.net.routing.RouteEvent;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Handles RouteEvent and manages routing entries.
+ */
+public class RouteHandler {
+    private static final Logger log = LoggerFactory.getLogger(RouteHandler.class);
+    private final SegmentRoutingManager srManager;
+
+    public RouteHandler(SegmentRoutingManager srManager) {
+        this.srManager = srManager;
+    }
+
+    protected void init(DeviceId deviceId) {
+        srManager.routeService.getNextHops().forEach(nextHop -> {
+            if (nextHop.location().deviceId().equals(deviceId)) {
+                srManager.routeService.getRoutesForNextHop(nextHop.ip()).forEach(route -> {
+                    ResolvedRoute resolvedRoute =
+                            new ResolvedRoute(route, nextHop.mac(), nextHop.location());
+                    processRouteAddedInternal(resolvedRoute);
+                });
+            }
+        });
+    }
+
+    protected void processRouteAdded(RouteEvent event) {
+        log.info("processRouteAdded {}", event);
+        processRouteAddedInternal(event.subject());
+    }
+
+    private void processRouteAddedInternal(ResolvedRoute route) {
+        IpPrefix prefix = route.prefix();
+        MacAddress nextHopMac = route.nextHopMac();
+        ConnectPoint location = route.location();
+
+        srManager.deviceConfiguration.addSubnet(location, prefix.getIp4Prefix());
+        srManager.defaultRoutingHandler.populateSubnet(location, ImmutableSet.of(prefix.getIp4Prefix()));
+        srManager.routingRulePopulator.populateRoute(location.deviceId(), prefix,
+                nextHopMac, location.port());
+    }
+
+    protected void processRouteUpdated(RouteEvent event) {
+        log.info("processRouteUpdated {}", event);
+        processRouteRemovedInternal(event.prevSubject());
+        processRouteAddedInternal(event.subject());
+    }
+
+    protected void processRouteRemoved(RouteEvent event) {
+        log.info("processRouteRemoved {}", event);
+        processRouteRemovedInternal(event.subject());
+    }
+
+    private void processRouteRemovedInternal(ResolvedRoute route) {
+        IpPrefix prefix = route.prefix();
+        MacAddress nextHopMac = route.nextHopMac();
+        ConnectPoint location = route.location();
+
+        srManager.deviceConfiguration.removeSubnet(location, prefix.getIp4Prefix());
+        srManager.defaultRoutingHandler.revokeSubnet(ImmutableSet.of(prefix.getIp4Prefix()));
+        srManager.routingRulePopulator.revokeRoute(
+                location.deviceId(), prefix, nextHopMac, location.port());
+    }
+}
diff --git a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 28fd5ec..4e35571 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -562,18 +562,21 @@
         for (Port port : devPorts) {
             ConnectPoint connectPoint = new ConnectPoint(deviceId, port.number());
             // TODO: Handles dynamic port events when we are ready for dynamic config
-            SegmentRoutingAppConfig appConfig = srManager.cfgService
-                    .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
             if (!port.isEnabled()) {
                 disabledPorts++;
                 continue;
             }
+
+            boolean isSuppressed = false;
+            SegmentRoutingAppConfig appConfig = srManager.cfgService
+                    .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
             if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
+                isSuppressed = true;
                 suppressedPorts++;
-                continue;
             }
+
             Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
-            VlanId assignedVlan = (portSubnet == null)
+            VlanId assignedVlan = (portSubnet == null || isSuppressed)
                     ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
                     : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
 
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 84c5190..1a540ef 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -34,6 +34,9 @@
 import org.onosproject.event.Event;
 import org.onosproject.incubator.net.config.basics.McastConfig;
 import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.incubator.net.routing.RouteEvent;
+import org.onosproject.incubator.net.routing.RouteListener;
+import org.onosproject.incubator.net.routing.RouteService;
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
@@ -106,7 +109,6 @@
 import static com.google.common.base.Preconditions.checkState;
 import static org.onlab.util.Tools.groupedThreads;
 
-
 /**
  * Segment routing manager.
  */
@@ -117,70 +119,75 @@
     private static Logger log = LoggerFactory.getLogger(SegmentRoutingManager.class);
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CoreService coreService;
+    private ComponentConfigService compCfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected PacketService packetService;
+    CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostService hostService;
+    PacketService packetService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected DeviceService deviceService;
+    HostService hostService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected FlowObjectiveService flowObjectiveService;
+    DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected LinkService linkService;
+    FlowObjectiveService flowObjectiveService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected MastershipService mastershipService;
+    LinkService linkService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected StorageService storageService;
+    MastershipService mastershipService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    StorageService storageService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    MulticastRouteService multicastRouteService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    CordConfigService cordConfigService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    RouteService routeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     public NetworkConfigRegistry cfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected ComponentConfigService compCfgService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected MulticastRouteService multicastRouteService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected TopologyService topologyService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected CordConfigService cordConfigService;
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     public InterfaceService interfaceService;
 
-    protected ArpHandler arpHandler = null;
-    protected IcmpHandler icmpHandler = null;
-    protected IpHandler ipHandler = null;
-    protected RoutingRulePopulator routingRulePopulator = null;
+    ArpHandler arpHandler = null;
+    IcmpHandler icmpHandler = null;
+    IpHandler ipHandler = null;
+    RoutingRulePopulator routingRulePopulator = null;
     public ApplicationId appId;
     protected DeviceConfiguration deviceConfiguration = null;
 
-    protected DefaultRoutingHandler defaultRoutingHandler = null;
+    DefaultRoutingHandler defaultRoutingHandler = null;
     private TunnelHandler tunnelHandler = null;
     private PolicyHandler policyHandler = null;
     private InternalPacketProcessor processor = null;
     private InternalLinkListener linkListener = null;
     private InternalDeviceListener deviceListener = null;
     private AppConfigHandler appCfgHandler = null;
-    protected XConnectHandler xConnectHandler = null;
+    XConnectHandler xConnectHandler = null;
     private McastHandler mcastHandler = null;
-    protected HostHandler hostHandler = null;
+    HostHandler hostHandler = null;
     private CordConfigHandler cordConfigHandler = null;
+    RouteHandler routeHandler = null;
     private InternalEventHandler eventHandler = new InternalEventHandler();
     private final InternalHostListener hostListener = new InternalHostListener();
     private final InternalConfigListener cfgListener = new InternalConfigListener(this);
     private final InternalMcastListener mcastListener = new InternalMcastListener();
     private final InternalCordConfigListener cordConfigListener = new InternalCordConfigListener();
+    private final InternalRouteEventListener routeListener = new InternalRouteEventListener();
 
     private ScheduledExecutorService executorService = Executors
             .newScheduledThreadPool(1, groupedThreads("SegmentRoutingManager", "event-%d", log));
@@ -329,6 +336,8 @@
                 "purgeOnDisconnection", "true");
         compCfgService.preSetProperty("org.onosproject.net.flow.impl.FlowRuleManager",
                 "purgeOnDisconnection", "true");
+        compCfgService.preSetProperty("org.onosproject.vrouter.Vrouter",
+                "fibInstalledEnabled", "false");
 
         processor = new InternalPacketProcessor();
         linkListener = new InternalLinkListener();
@@ -338,6 +347,7 @@
         mcastHandler = new McastHandler(this);
         hostHandler = new HostHandler(this);
         cordConfigHandler = new CordConfigHandler(this);
+        routeHandler = new RouteHandler(this);
 
         cfgService.addListener(cfgListener);
         cfgService.registerConfigFactory(deviceConfigFactory);
@@ -361,6 +371,8 @@
 
         cfgListener.configureNetwork();
 
+        routeService.addListener(routeListener);
+
         log.info("Started");
     }
 
@@ -386,6 +398,7 @@
         cfgService.removeListener(cfgListener);
         cfgService.unregisterConfigFactory(deviceConfigFactory);
         cfgService.unregisterConfigFactory(appConfigFactory);
+        cfgService.unregisterConfigFactory(xConnectConfigFactory);
         cfgService.unregisterConfigFactory(mcastConfigFactory);
 
         // Withdraw ARP packet-in
@@ -398,6 +411,7 @@
         deviceService.removeListener(deviceListener);
         multicastRouteService.removeListener(mcastListener);
         cordConfigService.removeListener(cordConfigListener);
+        routeService.removeListener(routeListener);
 
         processor = null;
         linkListener = null;
@@ -868,7 +882,7 @@
         defaultRoutingHandler.populatePortAddressingRules(deviceId);
 
         if (mastershipService.isLocalMaster(deviceId)) {
-            hostHandler.readInitialHosts(deviceId);
+            hostHandler.init(deviceId);
             xConnectHandler.init(deviceId);
             cordConfigHandler.init(deviceId);
             DefaultGroupHandler groupHandler = groupHandlerMap.get(deviceId);
@@ -876,7 +890,8 @@
             routingRulePopulator.populateSubnetBroadcastRule(deviceId);
         }
 
-        appCfgHandler.initVRouters(deviceId);
+        appCfgHandler.init(deviceId);
+        routeHandler.init(deviceId);
     }
 
     private void processDeviceRemoved(Device device) {
@@ -1023,6 +1038,7 @@
                     default:
                         break;
                 }
+                configureNetwork();
             } else if (event.configClass().equals(XConnectConfig.class)) {
                 checkState(xConnectHandler != null, "XConnectHandler is not initialized");
                 switch (event.type()) {
@@ -1113,4 +1129,23 @@
             }
         }
     }
+
+    private class InternalRouteEventListener implements RouteListener {
+        @Override
+        public void event(RouteEvent event) {
+            switch (event.type()) {
+                case ROUTE_ADDED:
+                    routeHandler.processRouteAdded(event);
+                    break;
+                case ROUTE_UPDATED:
+                    routeHandler.processRouteUpdated(event);
+                    break;
+                case ROUTE_REMOVED:
+                    routeHandler.processRouteRemoved(event);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
 }
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index cb0a275..c2360cb 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -20,6 +20,7 @@
 import com.google.common.collect.SetMultimap;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
@@ -331,15 +332,7 @@
                       srinfo.subnets.values());
 
             ImmutableSet.Builder<Ip4Prefix> builder = ImmutableSet.builder();
-            builder.addAll(srinfo.subnets.values());
-            SegmentRoutingAppConfig appConfig =
-                    srManager.cfgService.getConfig(srManager.appId, SegmentRoutingAppConfig.class);
-            if (appConfig != null) {
-                if (deviceId.equals(appConfig.vRouterId().orElse(null))) {
-                    builder.add(Ip4Prefix.valueOf("0.0.0.0/0"));
-                }
-            }
-            return builder.build();
+            return builder.addAll(srinfo.subnets.values()).build();
         }
         return null;
     }
@@ -452,6 +445,20 @@
     }
 
     /**
+     * Checks if the IP is in the subnet defined on given connect point.
+     *
+     * @param connectPoint Connect point
+     * @param ip The IP address to check
+     * @return True if the IP belongs to the subnet.
+     *         False if the IP does not belong to the subnet, or
+     *         there is no subnet configuration on given connect point.
+     */
+    public boolean inSameSubnet(ConnectPoint connectPoint, IpAddress ip) {
+        Ip4Prefix portSubnet = getPortSubnet(connectPoint.deviceId(), connectPoint.port());
+        return portSubnet != null && portSubnet.contains(ip);
+    }
+
+    /**
      * Returns the ports corresponding to the adjacency Sid given.
      *
      * @param deviceId device identification of the router
@@ -516,7 +523,7 @@
         SegmentRoutingAppConfig appConfig = srManager.cfgService
                 .getConfig(srManager.appId, SegmentRoutingAppConfig.class);
         if (appConfig != null && appConfig.suppressSubnet().contains(connectPoint)) {
-            log.info("Ignore suppressed port {}", connectPoint);
+            log.info("Interface configuration on port {} is ignored", connectPoint);
             return true;
         }
         return false;
diff --git a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
index 3fe7e4b..7e85a74 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingAppConfig.java
@@ -22,10 +22,8 @@
 import org.onlab.packet.MacAddress;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.config.Config;
 
-import java.util.Optional;
 import java.util.Set;
 
 import static com.google.common.base.MoreObjects.toStringHelper;
@@ -35,7 +33,6 @@
  */
 public class SegmentRoutingAppConfig extends Config<ApplicationId> {
     private static final String VROUTER_MACS = "vRouterMacs";
-    private static final String VROUTER_ID = "vRouterId";
     private static final String SUPPRESS_SUBNET = "suppressSubnet";
     private static final String SUPPRESS_HOST_BY_PORT = "suppressHostByPort";
     // TODO We might want to move SUPPRESS_HOST_BY_PROVIDER to Component Config
@@ -44,9 +41,9 @@
 
     @Override
     public boolean isValid() {
-        return hasOnlyFields(VROUTER_MACS, VROUTER_ID, SUPPRESS_SUBNET,
+        return hasOnlyFields(VROUTER_MACS, SUPPRESS_SUBNET,
                 SUPPRESS_HOST_BY_PORT, SUPPRESS_HOST_BY_PROVIDER, MPLS_ECMP) &&
-                vRouterMacs() != null && vRouterId() != null &&
+                vRouterMacs() != null &&
                 suppressSubnet() != null && suppressHostByPort() != null &&
                 suppressHostByProvider() != null;
     }
@@ -125,39 +122,6 @@
     }
 
     /**
-     * Gets vRouter device ID.
-     *
-     * @return Optional vRouter device ID,
-     *         empty is not specified or null if not valid
-     */
-    public Optional<DeviceId> vRouterId() {
-        if (!object.has(VROUTER_ID)) {
-            return Optional.empty();
-        }
-
-        try {
-            return Optional.of(DeviceId.deviceId(object.path(VROUTER_ID).asText()));
-        } catch (IllegalArgumentException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Sets vRouter device ID.
-     *
-     * @param vRouterId vRouter device ID
-     * @return this {@link SegmentRoutingAppConfig}
-     */
-    public SegmentRoutingAppConfig setVRouterId(DeviceId vRouterId) {
-        if (vRouterId == null) {
-            object.remove(VROUTER_ID);
-        } else {
-            object.put(VROUTER_ID, vRouterId.toString());
-        }
-        return this;
-    }
-
-    /**
      * Gets names of ports to which SegmentRouting does not push subnet rules.
      *
      * @return Set of port names, empty if not specified, or null
@@ -294,7 +258,6 @@
     public String toString() {
         return toStringHelper(this)
                 .add("vRouterMacs", vRouterMacs())
-                .add("vRouterId", vRouterId())
                 .add("suppressSubnet", suppressSubnet())
                 .add("suppressHostByPort", suppressHostByPort())
                 .add("suppressHostByProvider", suppressHostByProvider())