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/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index e2a040a..00b3c01 100644
--- a/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/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 "