CORD-1719 Cleanup old flows properly if the switch moves to a inexistent location

Change-Id: I8ffe970aaa9cec9ac3d4c266e460538bfd07c4fc
diff --git a/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index f8428a7..5029b30 100644
--- a/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -50,6 +50,8 @@
  * Handles host-related events.
  */
 public class HostHandler {
+    private static final String NOT_MASTER = "Current instance is not the master of {}. Ignore.";
+
     private static final Logger log = LoggerFactory.getLogger(HostHandler.class);
     protected final SegmentRoutingManager srManager;
     private HostService hostService;
@@ -85,6 +87,11 @@
     void processHostAddedAtLocation(Host host, HostLocation location) {
         checkArgument(host.locations().contains(location), "{} is not a location of {}", location, host);
 
+        if (!isMasterOf(location)) {
+            log.debug(NOT_MASTER, location);
+            return;
+        }
+
         MacAddress mac = host.mac();
         VlanId vlanId = host.vlan();
         Set<HostLocation> locations = host.locations();
@@ -108,7 +115,7 @@
         Set<IpAddress> ips = host.ipAddresses();
         log.info("Host {}/{} is removed from {}", hostMac, hostVlanId, locations);
 
-        locations.forEach(location -> {
+        locations.stream().filter(this::isMasterOf).forEach(location -> {
             processBridgingRule(location.deviceId(), location.port(), hostMac, hostVlanId, true);
             ips.forEach(ip ->
                 processRoutingRule(location.deviceId(), location.port(), hostMac, hostVlanId, ip, true)
@@ -143,7 +150,8 @@
                 .collect(Collectors.toSet());
 
         // For each old location
-        Sets.difference(prevLocations, newLocations).forEach(prevLocation -> {
+        Sets.difference(prevLocations, newLocations).stream().filter(this::isMasterOf)
+                .forEach(prevLocation -> {
             // Remove routing rules for old IPs
             Sets.difference(prevIps, newIps).forEach(ip ->
                     processRoutingRule(prevLocation.deviceId(), prevLocation.port(), hostMac, hostVlanId,
@@ -203,7 +211,8 @@
         });
 
         // For each new location, add all new IPs.
-        Sets.difference(newLocations, prevLocations).forEach(newLocation -> {
+        Sets.difference(newLocations, prevLocations).stream().filter(this::isMasterOf)
+                .forEach(newLocation -> {
             processBridgingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId, false);
             newIps.forEach(ip ->
                     processRoutingRule(newLocation.deviceId(), newLocation.port(), hostMac, hostVlanId,
@@ -212,7 +221,8 @@
         });
 
         // For each unchanged location, add new IPs and remove old IPs.
-        Sets.intersection(newLocations, prevLocations).forEach(unchangedLocation -> {
+        Sets.intersection(newLocations, prevLocations).stream().filter(this::isMasterOf)
+                .forEach(unchangedLocation -> {
             Sets.difference(prevIps, newIps).forEach(ip ->
                     processRoutingRule(unchangedLocation.deviceId(), unchangedLocation.port(), hostMac,
                             hostVlanId, ip, true)
@@ -233,7 +243,7 @@
         Set<IpAddress> newIps = event.subject().ipAddresses();
         log.info("Host {}/{} is updated", mac, vlanId);
 
-        locations.forEach(location -> {
+        locations.stream().filter(this::isMasterOf).forEach(location -> {
             Sets.difference(prevIps, newIps).forEach(ip ->
                     processRoutingRule(location.deviceId(), location.port(), mac, vlanId, ip, true)
             );
@@ -373,4 +383,15 @@
             srManager.routingRulePopulator.populateRoute(deviceId, ip.toIpPrefix(), mac, vlanId, port);
         }
     }
+
+    /**
+     * Determine if current instance is the master of given connect point.
+     *
+     * @param cp connect point
+     * @return true if current instance is the master of given connect point
+     */
+    private boolean isMasterOf(ConnectPoint cp) {
+        log.debug(NOT_MASTER, cp);
+        return srManager.mastershipService.isLocalMaster(cp.deviceId());
+    }
 }
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 9f6ecd4..0e23a26 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -1478,12 +1478,6 @@
     private class InternalHostListener implements HostListener {
         @Override
         public void event(HostEvent event) {
-            // Do not proceed without mastership
-            DeviceId deviceId = event.subject().location().deviceId();
-            if (!mastershipService.isLocalMaster(deviceId)) {
-                return;
-            }
-
             switch (event.type()) {
                 case HOST_ADDED:
                     hostHandler.processHostAddedEvent(event);