CORD-60 Support dynamic vSG creation/deletion

We no longer need to configure /32 IP in interfaces.
SR will push a per-host route when discovering a host
with IP address(es) that does not belong to configured subnet.

Also includes:
- HostHandler refactoring

Change-Id: Ic1ad42d1ccdfee32be85f49e6fc94d9026000ffc
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 9f2e84e..1324795 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -15,11 +15,13 @@
  */
 package org.onosproject.segmentrouting;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
 import org.onlab.packet.IpPrefix;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
@@ -45,9 +47,9 @@
  * routing rule population.
  */
 public class DefaultRoutingHandler {
-
-    private static Logger log = LoggerFactory
-            .getLogger(DefaultRoutingHandler.class);
+    private static final int MAX_RETRY_ATTEMPTS = 5;
+    private static final String ECMPSPG_MISSING = "ECMP shortest path graph not found";
+    private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class);
 
     private SegmentRoutingManager srManager;
     private RoutingRulePopulator rulePopulator;
@@ -56,7 +58,6 @@
     private DeviceConfiguration config;
     private final Lock statusLock = new ReentrantLock();
     private volatile Status populationStatus;
-    private static final int MAX_RETRY_ATTEMPTS = 5;
     private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
 
     /**
@@ -113,7 +114,7 @@
                 }
 
                 EcmpShortestPathGraph ecmpSpg = new EcmpShortestPathGraph(sw.id(), srManager);
-                if (!populateEcmpRoutingRules(sw.id(), ecmpSpg)) {
+                if (!populateEcmpRoutingRules(sw.id(), ecmpSpg, ImmutableSet.of())) {
                     log.debug("populateAllRoutingRules: populationStatus is ABORTED");
                     populationStatus = Status.ABORTED;
                     log.debug("Abort routing rule population");
@@ -210,7 +211,7 @@
             if (link.size() == 1) {
                 log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", link.get(0));
                 EcmpShortestPathGraph ecmpSpg = new EcmpShortestPathGraph(link.get(0), srManager);
-                if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
+                if (populateEcmpRoutingRules(link.get(0), ecmpSpg, ImmutableSet.of())) {
                     log.debug("Populating flow rules from {} to all is successful",
                               link.get(0));
                     currentEcmpSpgMap.put(link.get(0), ecmpSpg);
@@ -255,7 +256,8 @@
                                 nextHops.add(via.get(0));
                             }
                         }
-                        if (!populateEcmpRoutingRulePartial(targetSw, dst, nextHops)) {
+                        if (!populateEcmpRoutingRulePartial(targetSw, dst,
+                                nextHops, ImmutableSet.of())) {
                             return false;
                         }
                         log.debug("Populating flow rules from {} to {} is successful",
@@ -422,8 +424,17 @@
         return subLinks;
     }
 
+    /**
+     * Populate ECMP rules for subnets from all switches to destination.
+     *
+     * @param destSw Device ID of destination switch
+     * @param ecmpSPG ECMP shortest path graph
+     * @param subnets Subnets to be populated. If empty, populate all configured subnets.
+     * @return true if succeed
+     */
     private boolean populateEcmpRoutingRules(DeviceId destSw,
-                                             EcmpShortestPathGraph ecmpSPG) {
+                                             EcmpShortestPathGraph ecmpSPG,
+                                             Set<Ip4Prefix> subnets) {
 
         HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = ecmpSPG
                 .getAllLearnedSwitchesAndVia();
@@ -440,7 +451,7 @@
                         nextHops.add(via.get(0));
                     }
                 }
-                if (!populateEcmpRoutingRulePartial(targetSw, destSw, nextHops)) {
+                if (!populateEcmpRoutingRulePartial(targetSw, destSw, nextHops, subnets)) {
                     return false;
                 }
             }
@@ -449,9 +460,19 @@
         return true;
     }
 
+    /**
+     * Populate ECMP rules for subnets from target to destination via nexthops.
+     *
+     * @param targetSw Device ID of target switch
+     * @param destSw Device ID of destination switch
+     * @param nextHops List of next hops
+     * @param subnets Subnets to be populated. If empty, populate all configured subnets.
+     * @return true if succeed
+     */
     private boolean populateEcmpRoutingRulePartial(DeviceId targetSw,
                                                    DeviceId destSw,
-                                                   Set<DeviceId> nextHops) {
+                                                   Set<DeviceId> nextHops,
+                                                   Set<Ip4Prefix> subnets) {
         boolean result;
 
         if (nextHops.isEmpty()) {
@@ -473,13 +494,11 @@
         }
 
         if (targetIsEdge && destIsEdge) {
-            Set<Ip4Prefix> subnets = config.getSubnets(destSw);
+            subnets = (subnets != null && !subnets.isEmpty()) ? subnets : config.getSubnets(destSw);
             log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
                       targetSw, destSw, subnets);
-            result = rulePopulator.populateIpRuleForSubnet(targetSw,
-                                                           subnets,
-                                                           destSw,
-                                                           nextHops);
+            result = rulePopulator.populateIpRuleForSubnet(targetSw, subnets,
+                                                           destSw, nextHops);
             if (!result) {
                 return false;
             }
@@ -575,18 +594,54 @@
         }
     }
 
-    public void purgeEcmpGraph(DeviceId deviceId) {
+    /**
+     * Populate rules of given subnet at given location.
+     *
+     * @param cp connect point of the subnet being added
+     * @param subnets subnet being added
+     * @return true if succeed
+     */
+    protected boolean populateSubnet(ConnectPoint cp, Set<Ip4Prefix> subnets) {
+        statusLock.lock();
+        try {
+            EcmpShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(cp.deviceId());
+            if (ecmpSpg == null) {
+                log.warn("Fail to populating subnet {}: {}", subnets, ECMPSPG_MISSING);
+                return false;
+            }
+            return populateEcmpRoutingRules(cp.deviceId(), ecmpSpg, subnets);
+        } finally {
+            statusLock.unlock();
+        }
+    }
+
+    /**
+     * Revoke rules of given subnet at given location.
+     *
+     * @param subnets subnet being removed
+     * @return true if succeed
+     */
+    protected boolean revokeSubnet(Set<Ip4Prefix> subnets) {
+        statusLock.lock();
+        try {
+            return srManager.routingRulePopulator.revokeIpRuleForSubnet(subnets);
+        } finally {
+            statusLock.unlock();
+        }
+    }
+
+    protected void purgeEcmpGraph(DeviceId deviceId) {
         currentEcmpSpgMap.remove(deviceId);
         if (updatedEcmpSpgMap != null) {
             updatedEcmpSpgMap.remove(deviceId);
         }
     }
 
-    private class RetryFilters implements Runnable {
+    private final class RetryFilters implements Runnable {
         int attempts = MAX_RETRY_ATTEMPTS;
         DeviceId devId;
 
-        public RetryFilters(DeviceId deviceId) {
+        private RetryFilters(DeviceId deviceId) {
             devId = deviceId;
         }
 
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index e9a4706..05bba2d 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -16,13 +16,15 @@
 
 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.core.CoreService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostLocation;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -46,7 +48,6 @@
 public class HostHandler {
     private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
     private final SegmentRoutingManager srManager;
-    private CoreService coreService;
     private HostService hostService;
     private FlowObjectiveService flowObjectiveService;
 
@@ -57,7 +58,6 @@
      */
     public HostHandler(SegmentRoutingManager srManager) {
         this.srManager = srManager;
-        coreService = srManager.coreService;
         hostService = srManager.hostService;
         flowObjectiveService = srManager.flowObjectiveService;
     }
@@ -65,45 +65,204 @@
     protected void readInitialHosts(DeviceId devId) {
         hostService.getHosts().forEach(host -> {
             DeviceId deviceId = host.location().deviceId();
+            // The host does not attach to this device
             if (!deviceId.equals(devId)) {
-                // not an attached host to this device
                 return;
             }
-            MacAddress mac = host.mac();
-            VlanId vlanId = host.vlan();
-            PortNumber port = host.location().port();
-            Set<IpAddress> ips = host.ipAddresses();
-            log.debug("Attached Host {}/{} is added at {}:{}", mac, vlanId,
-                      deviceId, port);
+            processHostAddedEventInternal(host.mac(), host.vlan(),
+                    host.location(), host.ipAddresses());
+        });
+    }
 
+    protected void processHostAddedEvent(HostEvent event) {
+        processHostAddedEventInternal(event.subject().mac(), event.subject().vlan(),
+                event.subject().location(), event.subject().ipAddresses());
+    }
+
+    private void processHostAddedEventInternal(MacAddress mac, VlanId vlanId,
+            HostLocation location, Set<IpAddress> ips) {
+        DeviceId deviceId = location.deviceId();
+        PortNumber port = location.port();
+        log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
+
+        if (!srManager.deviceConfiguration.suppressHost().contains(location)) {
             // Populate bridging table entry
+            log.debug("Populate L2 table entry for host {} at {}:{}",
+                    mac, deviceId, port);
             ForwardingObjective.Builder fob =
-                    getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
+                    hostFwdObjBuilder(deviceId, mac, vlanId, port);
             if (fob == null) {
-                log.warn("Aborting host bridging & routing table entries due "
-                         + "to error for dev:{} host:{}", deviceId, host);
+                log.warn("Fail to create fwd obj for host {}/{}. Abort.", mac, vlanId);
                 return;
             }
             ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Host rule for {} populated", host),
+                    (objective) -> log.debug("Host rule for {}/{} populated", mac, vlanId),
                     (objective, error) ->
-                            log.warn("Failed to populate host rule for {}: {}", host, error));
+                            log.warn("Failed to populate host rule for {}/{}: {}", mac, vlanId, error));
             flowObjectiveService.forward(deviceId, fob.add(context));
 
-            // Populate IP table entry
             ips.forEach(ip -> {
+                // Populate IP table entry
                 if (ip.isIp4()) {
+                    addPerHostRoute(location, ip.getIp4Address());
                     srManager.routingRulePopulator.populateIpRuleForHost(
                             deviceId, ip.getIp4Address(), mac, port);
                 }
             });
-        });
+        }
     }
 
-    private ForwardingObjective.Builder getForwardingObjectiveBuilder(
+    protected void processHostRemoveEvent(HostEvent event) {
+        MacAddress mac = event.subject().mac();
+        VlanId vlanId = event.subject().vlan();
+        HostLocation location = event.subject().location();
+        DeviceId deviceId = location.deviceId();
+        PortNumber port = location.port();
+        Set<IpAddress> ips = event.subject().ipAddresses();
+        log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
+
+        if (!srManager.deviceConfiguration.suppressHost()
+                .contains(new ConnectPoint(deviceId, port))) {
+            // Revoke bridging table entry
+            ForwardingObjective.Builder fob =
+                    hostFwdObjBuilder(deviceId, mac, vlanId, port);
+            if (fob == null) {
+                log.warn("Fail to create fwd obj for host {}/{}. Abort.", mac, vlanId);
+                return;
+            }
+            ObjectiveContext context = new DefaultObjectiveContext(
+                    (objective) -> log.debug("Host rule for {} revoked", event.subject()),
+                    (objective, error) ->
+                            log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
+            flowObjectiveService.forward(deviceId, fob.remove(context));
+
+            // Revoke IP table entry
+            ips.forEach(ip -> {
+                if (ip.isIp4()) {
+                    removePerHostRoute(location, ip.getIp4Address());
+                    srManager.routingRulePopulator.revokeIpRuleForHost(
+                            deviceId, ip.getIp4Address(), mac, port);
+                }
+            });
+        }
+    }
+
+    protected void processHostMovedEvent(HostEvent event) {
+        MacAddress mac = event.subject().mac();
+        VlanId vlanId = event.subject().vlan();
+        HostLocation prevLocation = event.prevSubject().location();
+        DeviceId prevDeviceId = prevLocation.deviceId();
+        PortNumber prevPort = prevLocation.port();
+        Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
+        HostLocation newLocation = event.subject().location();
+        DeviceId newDeviceId = newLocation.deviceId();
+        PortNumber newPort = newLocation.port();
+        Set<IpAddress> newIps = event.subject().ipAddresses();
+        log.debug("Host {}/{} is moved from {}:{} to {}:{}",
+                mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
+
+        if (!srManager.deviceConfiguration.suppressHost()
+                .contains(new ConnectPoint(prevDeviceId, prevPort))) {
+            // Revoke previous bridging table entry
+            ForwardingObjective.Builder prevFob =
+                    hostFwdObjBuilder(prevDeviceId, mac, vlanId, prevPort);
+            if (prevFob == null) {
+                log.warn("Fail to create fwd obj for host {}/{}. Abort.", mac, vlanId);
+                return;
+            }
+            ObjectiveContext context = new DefaultObjectiveContext(
+                    (objective) -> log.debug("Host rule for {} revoked", event.subject()),
+                    (objective, error) ->
+                            log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
+            flowObjectiveService.forward(prevDeviceId, prevFob.remove(context));
+
+            // Revoke previous IP table entry
+            prevIps.forEach(ip -> {
+                if (ip.isIp4()) {
+                    removePerHostRoute(prevLocation, ip.getIp4Address());
+                    srManager.routingRulePopulator.revokeIpRuleForHost(
+                            prevDeviceId, ip.getIp4Address(), mac, prevPort);
+                }
+            });
+        }
+
+        if (!srManager.deviceConfiguration.suppressHost()
+                .contains(new ConnectPoint(newDeviceId, newPort))) {
+            // Populate new bridging table entry
+            ForwardingObjective.Builder newFob =
+                    hostFwdObjBuilder(newDeviceId, mac, vlanId, newPort);
+            if (newFob == null) {
+                log.warn("Fail to create fwd obj for host {}/{}. Abort.", mac, vlanId);
+                return;
+            }
+            ObjectiveContext context = new DefaultObjectiveContext(
+                    (objective) -> log.debug("Host rule for {} populated", event.subject()),
+                    (objective, error) ->
+                            log.warn("Failed to populate host rule for {}: {}", event.subject(), error));
+            flowObjectiveService.forward(newDeviceId, newFob.add(context));
+
+            // Populate new IP table entry
+            newIps.forEach(ip -> {
+                if (ip.isIp4()) {
+                    addPerHostRoute(newLocation, ip.getIp4Address());
+                    srManager.routingRulePopulator.populateIpRuleForHost(
+                            newDeviceId, ip.getIp4Address(), mac, newPort);
+                }
+            });
+        }
+    }
+
+    protected void processHostUpdatedEvent(HostEvent event) {
+        MacAddress mac = event.subject().mac();
+        VlanId vlanId = event.subject().vlan();
+        HostLocation prevLocation = event.prevSubject().location();
+        DeviceId prevDeviceId = prevLocation.deviceId();
+        PortNumber prevPort = prevLocation.port();
+        Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
+        HostLocation newLocation = event.subject().location();
+        DeviceId newDeviceId = newLocation.deviceId();
+        PortNumber newPort = newLocation.port();
+        Set<IpAddress> newIps = event.subject().ipAddresses();
+        log.debug("Host {}/{} is updated", mac, vlanId);
+
+        if (!srManager.deviceConfiguration.suppressHost()
+                .contains(new ConnectPoint(prevDeviceId, prevPort))) {
+            // Revoke previous IP table entry
+            prevIps.forEach(ip -> {
+                if (ip.isIp4()) {
+                    removePerHostRoute(prevLocation, ip.getIp4Address());
+                    srManager.routingRulePopulator.revokeIpRuleForHost(
+                            prevDeviceId, ip.getIp4Address(), mac, prevPort);
+                }
+            });
+        }
+
+        if (!srManager.deviceConfiguration.suppressHost()
+                .contains(new ConnectPoint(newDeviceId, newPort))) {
+            // Populate new IP table entry
+            newIps.forEach(ip -> {
+                if (ip.isIp4()) {
+                    addPerHostRoute(newLocation, ip.getIp4Address());
+                    srManager.routingRulePopulator.populateIpRuleForHost(
+                            newDeviceId, ip.getIp4Address(), mac, newPort);
+                }
+            });
+        }
+    }
+
+    /**
+     * Generates the forwarding objective builder for the host rules.
+     *
+     * @param deviceId Device that host attaches to
+     * @param mac MAC address of the host
+     * @param vlanId VLAN ID of the host
+     * @param outport Port that host attaches to
+     * @return Forwarding objective builder
+     */
+    private ForwardingObjective.Builder hostFwdObjBuilder(
             DeviceId deviceId, MacAddress mac, VlanId vlanId,
             PortNumber outport) {
-        // Get assigned VLAN for the subnet
+        // Get assigned VLAN for the subnets
         VlanId outvlan = null;
         Ip4Prefix subnet = srManager.deviceConfiguration.getPortSubnet(deviceId, outport);
         if (subnet == null) {
@@ -115,10 +274,10 @@
         // match rule
         TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
         sbuilder.matchEthDst(mac);
-            /*
-             * Note: for untagged packets, match on the assigned VLAN.
-             *       for tagged packets, match on its incoming VLAN.
-             */
+        /*
+         * Note: for untagged packets, match on the assigned VLAN.
+         *       for tagged packets, match on its incoming VLAN.
+         */
         if (vlanId.equals(VlanId.NONE)) {
             sbuilder.matchVlanId(outvlan);
         } else {
@@ -151,150 +310,38 @@
                 .makePermanent();
     }
 
-    protected void processHostAddedEvent(HostEvent event) {
-        MacAddress mac = event.subject().mac();
-        VlanId vlanId = event.subject().vlan();
-        DeviceId deviceId = event.subject().location().deviceId();
-        PortNumber port = event.subject().location().port();
-        Set<IpAddress> ips = event.subject().ipAddresses();
-        log.info("Host {}/{} is added at {}:{}", mac, vlanId, deviceId, port);
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(deviceId, port))) {
-            // Populate bridging table entry
-            log.debug("Populate L2 table entry for host {} at {}:{}",
-                    mac, deviceId, port);
-            ForwardingObjective.Builder fob =
-                    getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Host rule for {} populated", event.subject()),
-                    (objective, error) ->
-                            log.warn("Failed to populate host rule for {}: {}", event.subject(), error));
-            flowObjectiveService.forward(deviceId, fob.add(context));
-
-            // Populate IP table entry
-            ips.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.populateIpRuleForHost(
-                            deviceId, ip.getIp4Address(), mac, port);
-                }
-            });
+    /**
+     * 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));
         }
     }
 
-    protected void processHostRemoveEvent(HostEvent event) {
-        MacAddress mac = event.subject().mac();
-        VlanId vlanId = event.subject().vlan();
-        DeviceId deviceId = event.subject().location().deviceId();
-        PortNumber port = event.subject().location().port();
-        Set<IpAddress> ips = event.subject().ipAddresses();
-        log.debug("Host {}/{} is removed from {}:{}", mac, vlanId, deviceId, port);
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(deviceId, port))) {
-            // Revoke bridging table entry
-            ForwardingObjective.Builder fob =
-                    getForwardingObjectiveBuilder(deviceId, mac, vlanId, port);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Host rule for {} revoked", event.subject()),
-                    (objective, error) ->
-                            log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
-            flowObjectiveService.forward(deviceId, fob.remove(context));
-
-            // Revoke IP table entry
-            ips.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.revokeIpRuleForHost(
-                            deviceId, ip.getIp4Address(), mac, port);
-                }
-            });
-        }
-    }
-
-    protected void processHostMovedEvent(HostEvent event) {
-        MacAddress mac = event.subject().mac();
-        VlanId vlanId = event.subject().vlan();
-        DeviceId prevDeviceId = event.prevSubject().location().deviceId();
-        PortNumber prevPort = event.prevSubject().location().port();
-        Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
-        DeviceId newDeviceId = event.subject().location().deviceId();
-        PortNumber newPort = event.subject().location().port();
-        Set<IpAddress> newIps = event.subject().ipAddresses();
-        log.debug("Host {}/{} is moved from {}:{} to {}:{}",
-                mac, vlanId, prevDeviceId, prevPort, newDeviceId, newPort);
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(prevDeviceId, prevPort))) {
-            // Revoke previous bridging table entry
-            ForwardingObjective.Builder prevFob =
-                    getForwardingObjectiveBuilder(prevDeviceId, mac, vlanId, prevPort);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Host rule for {} revoked", event.subject()),
-                    (objective, error) ->
-                            log.warn("Failed to revoke host rule for {}: {}", event.subject(), error));
-            flowObjectiveService.forward(prevDeviceId, prevFob.remove(context));
-
-            // Revoke previous IP table entry
-            prevIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.revokeIpRuleForHost(
-                            prevDeviceId, ip.getIp4Address(), mac, prevPort);
-                }
-            });
-        }
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(newDeviceId, newPort))) {
-            // Populate new bridging table entry
-            ForwardingObjective.Builder newFob =
-                    getForwardingObjectiveBuilder(newDeviceId, mac, vlanId, newPort);
-            ObjectiveContext context = new DefaultObjectiveContext(
-                    (objective) -> log.debug("Host rule for {} populated", event.subject()),
-                    (objective, error) ->
-                            log.warn("Failed to populate host rule for {}: {}", event.subject(), error));
-            flowObjectiveService.forward(newDeviceId, newFob.add(context));
-
-            // Populate new IP table entry
-            newIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.populateIpRuleForHost(
-                            newDeviceId, ip.getIp4Address(), mac, newPort);
-                }
-            });
-        }
-    }
-
-    protected void processHostUpdatedEvent(HostEvent event) {
-        MacAddress mac = event.subject().mac();
-        VlanId vlanId = event.subject().vlan();
-        DeviceId prevDeviceId = event.prevSubject().location().deviceId();
-        PortNumber prevPort = event.prevSubject().location().port();
-        Set<IpAddress> prevIps = event.prevSubject().ipAddresses();
-        DeviceId newDeviceId = event.subject().location().deviceId();
-        PortNumber newPort = event.subject().location().port();
-        Set<IpAddress> newIps = event.subject().ipAddresses();
-        log.debug("Host {}/{} is updated", mac, vlanId);
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(prevDeviceId, prevPort))) {
-            // Revoke previous IP table entry
-            prevIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.revokeIpRuleForHost(
-                            prevDeviceId, ip.getIp4Address(), mac, prevPort);
-                }
-            });
-        }
-
-        if (!srManager.deviceConfiguration.suppressHost()
-                .contains(new ConnectPoint(newDeviceId, newPort))) {
-            // Populate new IP table entry
-            newIps.forEach(ip -> {
-                if (ip.isIp4()) {
-                    srManager.routingRulePopulator.populateIpRuleForHost(
-                            newDeviceId, ip.getIp4Address(), mac, newPort);
-                }
-            });
+    /**
+     * 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));
         }
     }
 }
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index e2a040a..00b3c01 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -212,22 +212,33 @@
      * Populates IP flow rules for the subnets of the destination router.
      *
      * @param deviceId switch ID to set the rules
-     * @param subnets subnet information
+     * @param subnets subnet being added
      * @param destSw destination switch ID
      * @param nextHops next hop switch ID list
      * @return true if all rules are set successfully, false otherwise
      */
-    public boolean populateIpRuleForSubnet(DeviceId deviceId,
-                                           Set<Ip4Prefix> subnets,
-                                           DeviceId destSw,
-                                           Set<DeviceId> nextHops) {
-
+    public boolean populateIpRuleForSubnet(DeviceId deviceId, Set<Ip4Prefix> subnets,
+            DeviceId destSw, Set<DeviceId> nextHops) {
         for (IpPrefix subnet : subnets) {
             if (!populateIpRuleForRouter(deviceId, subnet, destSw, nextHops)) {
                 return false;
             }
         }
+        return true;
+    }
 
+    /**
+     * Revokes IP flow rules for the subnets.
+     *
+     * @param subnets subnet being removed
+     * @return true if all rules are removed successfully, false otherwise
+     */
+    public boolean revokeIpRuleForSubnet(Set<Ip4Prefix> subnets) {
+        for (IpPrefix subnet : subnets) {
+            if (!revokeIpRuleForRouter(subnet)) {
+                return false;
+            }
+        }
         return true;
     }
 
@@ -310,6 +321,40 @@
     }
 
     /**
+     * Revokes IP flow rules for the router IP address.
+     *
+     * @param ipPrefix the IP address of the destination router
+     * @return true if all rules are removed successfully, false otherwise
+     */
+    public boolean revokeIpRuleForRouter(IpPrefix ipPrefix) {
+        TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
+        sbuilder.matchIPDst(ipPrefix);
+        sbuilder.matchEthType(Ethernet.TYPE_IPV4);
+        TrafficSelector selector = sbuilder.build();
+        TrafficTreatment dummyTreatment = DefaultTrafficTreatment.builder().build();
+
+        ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+                .builder()
+                .fromApp(srManager.appId)
+                .makePermanent()
+                .withSelector(selector)
+                .withTreatment(dummyTreatment)
+                .withPriority(getPriorityFromPrefix(ipPrefix))
+                .withFlag(ForwardingObjective.Flag.SPECIFIC);
+
+        ObjectiveContext context = new DefaultObjectiveContext(
+                (objective) -> log.debug("IP rule for router {} revoked", ipPrefix),
+                (objective, error) ->
+                        log.warn("Failed to revoke IP rule for router {}: {}", ipPrefix, error));
+
+        srManager.deviceService.getAvailableDevices().forEach(device -> {
+            srManager.flowObjectiveService.forward(device.id(), fwdBuilder.remove(context));
+        });
+
+        return true;
+    }
+
+    /**
      * Populates MPLS flow rules to all routers.
      *
      * @param deviceId target device ID of the switch to set the rules
@@ -471,6 +516,7 @@
      * that drivers can obtain other information (like Router MAC and IP).
      *
      * @param deviceId  the switch dpid for the router
+     * @return true if operation succeeds
      */
     public boolean populateRouterMacVlanFilters(DeviceId deviceId) {
         log.debug("Installing per-port filtering objective for untagged "
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 5eec207..c18ae30 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -153,7 +153,7 @@
     protected ApplicationId appId;
     protected DeviceConfiguration deviceConfiguration = null;
 
-    private DefaultRoutingHandler defaultRoutingHandler = null;
+    protected DefaultRoutingHandler defaultRoutingHandler = null;
     private TunnelHandler tunnelHandler = null;
     private PolicyHandler policyHandler = null;
     private InternalPacketProcessor processor = null;
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index 8fe00ba..d95efd2 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -46,6 +46,8 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 /**
  * Segment Routing configuration component that reads the
  * segment routing related configuration from Network Configuration Manager
@@ -167,7 +169,6 @@
                     }
                 }
             });
-
         });
     }
 
@@ -517,4 +518,38 @@
                 cfgService.getConfig(appId, SegmentRoutingAppConfig.class);
         return (appConfig != null) ? appConfig.suppressHost() : ImmutableSet.of();
     }
+
+    /**
+     * Add subnet to specific connect point.
+     *
+     * @param cp connect point
+     * @param ip4Prefix subnet being added to the device
+     */
+    public void addSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
+        checkNotNull(cp);
+        checkNotNull(ip4Prefix);
+        SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
+        if (srinfo == null) {
+            log.warn("Device {} is not configured. Abort.", cp.deviceId());
+            return;
+        }
+        srinfo.subnets.put(cp.port(), ip4Prefix);
+    }
+
+    /**
+     * Remove subnet from specific connect point.
+     *
+     * @param cp connect point
+     * @param ip4Prefix subnet being removed to the device
+     */
+    public void removeSubnet(ConnectPoint cp, Ip4Prefix ip4Prefix) {
+        checkNotNull(cp);
+        checkNotNull(ip4Prefix);
+        SegmentRouterInfo srinfo = deviceConfigMap.get(cp.deviceId());
+        if (srinfo == null) {
+            log.warn("Device {} is not configured. Abort.", cp.deviceId());
+            return;
+        }
+        srinfo.subnets.remove(cp.port(), ip4Prefix);
+    }
 }
diff --git a/tools/package/config/samples/network-cfg-fabric-2x2-all-readme.html b/tools/package/config/samples/network-cfg-fabric-2x2-all-readme.html
index 4e76263..bfe3a2c 100644
--- a/tools/package/config/samples/network-cfg-fabric-2x2-all-readme.html
+++ b/tools/package/config/samples/network-cfg-fabric-2x2-all-readme.html
@@ -18,10 +18,10 @@
     span.s1 {font-kerning: none}
     span.s2 {font-kerning: none; color: #0433ff; -webkit-text-stroke: 0px #0433ff}
     span.s3 {font-kerning: none; color: #000000; -webkit-text-stroke: 0px #000000}
-    span.s4 {font-kerning: none; color: #ff40ff; -webkit-text-stroke: 0px #ff40ff}
-    span.s5 {font-kerning: none; color: #ff9300; -webkit-text-stroke: 0px #ff9300}
-    span.s6 {font-kerning: none; color: #77bb41; -webkit-text-stroke: 0px #77bb41}
-    span.s7 {font-kerning: none; color: #00c7fc; -webkit-text-stroke: 0px #00c7fc}
+    span.s4 {font-kerning: none; color: #ff9300; -webkit-text-stroke: 0px #ff9300}
+    span.s5 {font-kerning: none; color: #77bb41; -webkit-text-stroke: 0px #77bb41}
+    span.s6 {font-kerning: none; color: #00c7fc; -webkit-text-stroke: 0px #00c7fc}
+    span.s7 {font-kerning: none; color: #ff40ff; -webkit-text-stroke: 0px #ff40ff}
     span.s8 {font-kerning: none; color: #ff2600; -webkit-text-stroke: 0px #ff2600}
     span.s9 {font-kerning: none; color: #000000}
     span.s10 {font-kerning: none; color: #669c35; -webkit-text-stroke: 0px #669c35}
@@ -49,12 +49,6 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>},</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
 <p class="p2"><span class="s3"><span class="Apple-converted-space">                </span>"vlan" : "222" </span><span class="s1">// cross-connect s-tag 222 to PMC OLT</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips" : [ "A.A.A.A/32" ] </span><span class="s4">// vSG1 public IP address /32</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips" : [ "B.B.B.B/32" ] </span><span class="s4">// vSG2 public IP address /32</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>},</span></p>
@@ -65,25 +59,18 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>},</span></p>
-<p class="p3"><span class="s3"><span class="Apple-converted-space">    </span>"of:0000000000000001/30" : { </span><span class="s1">// connect to vSG3 directly without OLT (temporary)</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000001/65" : { </span><span class="s4">// connect to Fujitsu OLT</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"interfaces" : [</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips" : [ "C.C.C.C/32" ] </span><span class="s4">// vSG3 /32 public IP address</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000001/65" : { </span><span class="s5">// connect to Fujitsu OLT</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"interfaces" : [</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "fujitsu-olt", </span><span class="s5">// unused</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "fujitsu-olt", </span><span class="s4">// unused</span></p>
 <p class="p2"><span class="s3"><span class="Apple-converted-space">                </span>"vlan" : "69" </span><span class="s1">// cross-connect s-tag 69<span class="Apple-converted-space">  </span>to vSG</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000001/73" : { </span><span class="s5">// connect to PMC OLT</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000001/73" : { </span><span class="s4">// connect to PMC OLT</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"interfaces" : [</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "pmc-olt", </span><span class="s5">// unused</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "pmc-olt", </span><span class="s4">// unused</span></p>
 <p class="p2"><span class="s3"><span class="Apple-converted-space">                </span>"vlan" : "222" </span><span class="s1">// cross-connect s-tag 222 to vSG</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
@@ -95,16 +82,16 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>]</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000002/32" : { </span><span class="s6">// connect to Internet router</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>"of:0000000000000002/32" : { </span><span class="s5">// connect to Internet router</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"interfaces" : [</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>{</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "external-quagga", </span><span class="s6">// Internet router interface name</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips" : [ "10.231.254.202/30", "10.231.254.223/32" ], </span><span class="s6">// Quagga IP addresses</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"mac" : "00:16:3e:56:2b:48" </span><span class="s6">// Quagga WAN MAC</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"name" : "external-quagga", </span><span class="s5">// Internet router interface name</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips" : [ "10.231.254.202/30", "10.231.254.223/32" ], </span><span class="s5">// Quagga IP addresses</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"mac" : "00:16:3e:56:2b:48" </span><span class="s5">// Quagga WAN MAC</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>],</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"pimInterface" : { </span><span class="s7">// PIM configuration</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"interfaceName" : "external-quagga", </span><span class="s7">// port that faces the Internet router</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"pimInterface" : { </span><span class="s6">// PIM configuration</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"interfaceName" : "external-quagga", </span><span class="s6">// port that faces the Internet router</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"enabled" : true,</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"helloInterval" : 1,</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"holdTime" : 3,</span></p>
@@ -162,15 +149,15 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"location": "of:0000000000000001/5" </span><span class="s2">// node 1 location</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"02:42:cf:8d:c0:82/-1" : { </span><span class="s4">// vSG1</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"02:42:cf:8d:c0:82/-1" : { </span><span class="s7">// vSG1</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"basic": {</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["A.A.A.A"], </span><span class="s4">// vSG1 public IP address</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["A.A.A.A"], </span><span class="s7">// vSG1 public IP address</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"location": "of:0000000000000001/5"</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"02:42:cf:8d:c0:83/-1" : { </span><span class="s4">// vSG2</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"02:42:cf:8d:c0:83/-1" : { </span><span class="s7">// vSG2</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"basic": {</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["B.B.B.B"], </span><span class="s4">// vSG2 public IP address</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["B.B.B.B"], </span><span class="s7">// vSG2 public IP address</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"location": "of:0000000000000001/5"</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
@@ -180,9 +167,9 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"location": "of:0000000000000001/7"</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"74:44:01:74:61:92/-1" : { </span><span class="s4">// vSG3</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"74:44:01:74:61:92/-1" : { </span><span class="s7">// vSG3</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"basic": {</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["C.C.C.C"], </span><span class="s4">// vSG3 public IP address</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ips": ["C.C.C.C"], </span><span class="s7">// vSG3 public IP address</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"location": "of:0000000000000001/30"</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
@@ -234,7 +221,7 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"vRouterMacs" : [</span></p>
 <p class="p3"><span class="s3"><span class="Apple-converted-space">                    </span>"a4:23:05:34:56:78" </span><span class="s1">// vRouter LAN MAC (vSG’s default gateway)</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>],</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"vRouterId" : "of:0000000000000002", </span><span class="s4">// vRouter DPID (0/0 is replaced by this)</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"vRouterId" : "of:0000000000000002", </span><span class="s7">// vRouter DPID (0/0 is replaced by this)</span></p>
 <p class="p4"><span class="s3"><span class="Apple-converted-space">                 </span>"suppressSubnet" : [ </span><span class="s1">// Do not push subnet rules for these ports</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                    </span>"of:0000000000000002/31", "of:0000000000000002/32"</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>],</span></p>
@@ -246,10 +233,10 @@
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>},</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>"org.onosproject.router" : {</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>"router" : {</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"controlPlaneConnectPoint" : "of:0000000000000002/31", </span><span class="s6">// location of Quagga</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ospfEnabled" : "true", </span><span class="s6">// enable OSPF</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"pimEnabled" : "true", </span><span class="s7">// enable PIM</span></p>
-<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"interfaces" : [ "external-quagga" ] </span><span class="s10">// </span><span class="s6">VR only handles peers on these ports</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"controlPlaneConnectPoint" : "of:0000000000000002/31", </span><span class="s5">// location of Quagga</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"ospfEnabled" : "true", </span><span class="s5">// enable OSPF</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"pimEnabled" : "true", </span><span class="s6">// enable PIM</span></p>
+<p class="p7"><span class="s1"><span class="Apple-converted-space">                </span>"interfaces" : [ "external-quagga" ] </span><span class="s10">// </span><span class="s5">VR only handles peers on these ports</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">            </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">        </span>}</span></p>
 <p class="p7"><span class="s1"><span class="Apple-converted-space">    </span>}</span></p>
diff --git a/tools/package/config/samples/network-cfg-fabric-2x2-all.json b/tools/package/config/samples/network-cfg-fabric-2x2-all.json
index 5b6f036..b12d4dc 100644
--- a/tools/package/config/samples/network-cfg-fabric-2x2-all.json
+++ b/tools/package/config/samples/network-cfg-fabric-2x2-all.json
@@ -13,12 +13,6 @@
             },
             {
                 "vlan" : "222"
-            },
-            {
-                "ips" : [
-                    "A.A.A.146/32", "A.A.A.147/32", "A.A.A.148/32", "A.A.A.149/32",
-                    "A.A.A.150/32", "A.A.A.151/32", "A.A.A.152/32", "A.A.A.153/32"
-                ]
             }
         ]
     },
@@ -52,9 +46,6 @@
         "interfaces" : [
             {
                 "ips" : [ "10.0.2.254/24" ]
-            },
-            {
-                "ips" : [ "A.A.A.130/32", "A.A.A.131/32" ]
             }
         ]
     },