[SDFAB-633][SDFAB-634][SDFAB-445] Collection of improvements for SR

Firstly, this patch deeply rewrites the load sharing of the SR instances,
before we were using an hybrid approach based on MastershipService.
With this patch we get rid of completely of the MastershipService
for any task. We just use the MastershipEvent as way to perform rerouting
if it happens near a cluster event. The aim is to make more stable the forwarding,
and the phased recovery.

Then, the patch contains a fix for an issue related to the phased recovery.
pr.init() can be called when there are still no masters (on device config
for example) and when this happens the portstate commands are dropped.

Last but not least, there is a fix for missing device routes in DefaultRoutingHandler.
Device routes (seenBeforeRoutes) are cleaned on DEVICE UP/ADDED events, this can lead
to purge some routes when the device events are handled in different moments by the
ONOS instances and there already some programmed routes.

Change-Id: Ia03b7c7c5b8a1b80c4b6d17053c2e2e7abf13d17
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java b/impl/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
index 059b9ca..10c20bd 100644
--- a/impl/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
+++ b/impl/src/test/java/org/onosproject/segmentrouting/DefaultRoutingHandlerTest.java
@@ -15,20 +15,22 @@
  */
 package org.onosproject.segmentrouting;
 
-import com.google.common.collect.Sets;
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.IpAddress;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.DefaultControllerNode;
+import org.onosproject.cluster.Leader;
+import org.onosproject.cluster.Leadership;
+import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
-import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.TestConsistentMap;
 import org.onosproject.store.service.TestConsistentMultimap;
 
+import java.util.List;
 import java.util.Optional;
 
 import static org.easymock.EasyMock.createMock;
@@ -36,15 +38,21 @@
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.reset;
 import static org.junit.Assert.*;
+import static org.onosproject.segmentrouting.DefaultRoutingHandler.HASH_FUNCTION;
 
 public class DefaultRoutingHandlerTest {
     private SegmentRoutingManager srManager;
     private DefaultRoutingHandler dfh;
+    private MockWorkPartitionService mockWps;
 
     private static final DeviceId DEV1A = DeviceId.deviceId("of:1a");
     private static final DeviceId DEV1B = DeviceId.deviceId("of:1b");
     private static final DeviceId DEV2 = DeviceId.deviceId("of:2");
 
+    private static final EdgePair EDGE_PAIR_1 = new EdgePair(DEV1A, DEV1B);
+    private static final EdgePair EDGE_PAIR_2 = new EdgePair(DEV1B, DEV1A);
+    private static final EdgePair EDGE_PAIR_3 = new EdgePair(DEV2, DeviceId.NONE);
+
     private static final NodeId NODE1 = NodeId.nodeId("192.168.1.1");
     private static final NodeId NODE2 = NodeId.nodeId("192.168.1.2");
     private static final NodeId NODE3 = NodeId.nodeId("192.168.1.3");
@@ -52,35 +60,50 @@
     private static final IpAddress IP2 = IpAddress.valueOf("192.168.1.2");
     private static final IpAddress IP3 = IpAddress.valueOf("192.168.1.3");
 
+    /* This is generated by manually applying the hash function.
+       It depends on the number of partitions defined in the MockWorkPartitionService */
+    private static final String DEV1A_PARTITION_ID = String.valueOf(Math.abs(HASH_FUNCTION.apply(
+            EDGE_PAIR_1).intValue()) % MockWorkPartitionService.NUM_PARTITIONS);
+    private static final String DEV1B_PARTITION_ID = String.valueOf(Math.abs(HASH_FUNCTION.apply(
+            EDGE_PAIR_2).intValue()) % MockWorkPartitionService.NUM_PARTITIONS);
+    private static final String DEV2_PARTITION_ID = String.valueOf(Math.abs(HASH_FUNCTION.apply(
+            EDGE_PAIR_3).intValue()) % MockWorkPartitionService.NUM_PARTITIONS);
+
     @Before
     public void setUp() {
         srManager = createMock(SegmentRoutingManager.class);
         srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
+        expect(srManager.storageService.consistentMapBuilder()).andReturn(
+                new TestConsistentMap.Builder<>()).anyTimes();
         expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
                 new TestConsistentMultimap.Builder<>()).anyTimes();
         replay(srManager.storageService);
         srManager.routingRulePopulator = createMock(RoutingRulePopulator.class);
         srManager.deviceService = createMock(DeviceService.class);
         srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
-        srManager.mastershipService = createMock(MastershipService.class);
+        mockWps = new MockWorkPartitionService();
+        mockWps.leadershipService = createMock(LeadershipService.class);
+        srManager.workPartitionService = mockWps;
         srManager.clusterService = createMock(ClusterService.class);
         dfh = new DefaultRoutingHandler(srManager);
     }
 
-    private void clearCache() {
-        dfh.invalidateShouldProgramCache(DEV1A);
-        dfh.invalidateShouldProgramCache(DEV1B);
-        dfh.invalidateShouldProgramCache(DEV2);
+    private void clearShouldProgram() {
+        dfh.invalidateShouldProgram(DEV1A);
+        dfh.invalidateShouldProgram(DEV1B);
+        dfh.invalidateShouldProgram(DEV2);
     }
 
-    // Node 1 is the master of switch 1A, 1B, and 2
+    // Node 1 is the leader of switch 1A, 1B, and 2
     @Test
     public void testShouldHandleRoutingCase1() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE1).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV2_PARTITION_ID)).andReturn(new Leadership(
+                DEV2_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -90,39 +113,64 @@
         // Node 1 should program every device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+
+        // shouldProgram is initially empty
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
         assertTrue(dfh.shouldProgram(DEV2));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 2 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 3 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV2));
     }
 
-    // Node 1 is the master of switch 1A, 1B
-    // Node 2 is the master of switch 2
+    /*
+     * Node 1 is the leader of switch 1A, 1B
+     * Node 2 is the leader of switch 2
+     */
     @Test
     public void testShouldHandleRoutingCase2() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE2).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV2_PARTITION_ID)).andReturn(new Leadership(
+                DEV2_PARTITION_ID, new Leader(NODE2, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -132,40 +180,62 @@
         // Node 1 should program 1A, 1B
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 2 should program 2
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertTrue(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1B));
+        assertEquals(NODE2, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 3 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV2));
     }
 
-    // Node 1 is the master of switch 1A
-    // Node 2 is the master of switch 1B
-    // Node 3 is the master of switch 2
+    /*
+     * Node 1 is the leader of switch 1A, 1B
+     * Node 3 is the leader of switch 2
+     */
     @Test
     public void testShouldHandleRoutingCase3() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV2_PARTITION_ID)).andReturn(new Leadership(
+                DEV2_PARTITION_ID, new Leader(NODE3, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -175,39 +245,62 @@
         // Node 1 should program 1A, 1B
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 2 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 3 should program 2
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertTrue(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1B));
+        assertEquals(NODE3, dfh.shouldProgram.get(DEV2));
     }
 
-    // Node 3 is the master of switch 1A, 1B, 2
-    // Later on, node 1 becomes the master of 1A; Node 2 becomes the master of 1B.
+    /*
+     * Node 2 is the leader of switch 1A, 1B and Node 3 is the leader of 2.
+     * Later on, node 1 becomes the leader of 1A, 1B
+     */
     @Test
     public void testShouldHandleRoutingCase4() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE3).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE3).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE2, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE2, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV2_PARTITION_ID)).andReturn(new Leadership(
+                DEV2_PARTITION_ID, new Leader(NODE3, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -217,75 +310,119 @@
         // Node 1 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
-        // Node 2 should program no device
+        // Node 2 should program 1A and 1B
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 3 should program 1A, 1B and 2
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
-        replay(srManager.clusterService);
-        assertTrue(dfh.shouldProgram(DEV1A));
-        assertTrue(dfh.shouldProgram(DEV1B));
-        assertTrue(dfh.shouldProgram(DEV2));
-
-        // Mastership of switch 1A moves to Node 1
-        reset(srManager.mastershipService);
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV2)).andReturn(NODE3).anyTimes();
-        replay(srManager.mastershipService);
-
-        reset(srManager.clusterService);
-        clearCache();
-
-        // Node 1 should program 1A, 1B
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
-        replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
         assertFalse(dfh.shouldProgram(DEV2));
+        assertEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE2, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV2));
 
         reset(srManager.clusterService);
-        clearCache();
-
-        // Node 2 should program no device
-        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
-        replay(srManager.clusterService);
-        assertFalse(dfh.shouldProgram(DEV1A));
-        assertFalse(dfh.shouldProgram(DEV1B));
-        assertFalse(dfh.shouldProgram(DEV2));
-
-        reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 3 should program 2
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
         assertTrue(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1B));
+        assertEquals(NODE3, dfh.shouldProgram.get(DEV2));
+
+        // Partition of switch 1A moves to Node 1. This can happen for a cluster event
+        reset(mockWps.leadershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV2_PARTITION_ID)).andReturn(new Leadership(
+                DEV2_PARTITION_ID, new Leader(NODE3, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
+
+        reset(srManager.clusterService);
+        clearShouldProgram();
+
+        // Node 1 should program 1A, 1B
+        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
+        replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
+        assertTrue(dfh.shouldProgram(DEV1A));
+        assertTrue(dfh.shouldProgram(DEV1B));
+        assertFalse(dfh.shouldProgram(DEV2));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE1, dfh.shouldProgram.get(DEV2));
+
+        reset(srManager.clusterService);
+        clearShouldProgram();
+
+        // Node 2 should program no device
+        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
+        replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
+        assertFalse(dfh.shouldProgram(DEV1A));
+        assertFalse(dfh.shouldProgram(DEV1B));
+        assertFalse(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1B));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV2));
+
+        reset(srManager.clusterService);
+        clearShouldProgram();
+
+        // Node 3 should program 2
+        expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes();
+        replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV2));
+        assertFalse(dfh.shouldProgram(DEV1A));
+        assertFalse(dfh.shouldProgram(DEV1B));
+        assertTrue(dfh.shouldProgram(DEV2));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE3, dfh.shouldProgram.get(DEV1B));
+        assertEquals(NODE3, dfh.shouldProgram.get(DEV2));
     }
 
-    // Node 1 is the master of 1A. 1B has no master
-    // Node 2 becomes the master of 1B later
+    /*
+     * Node 1 is the leader of 1A, 1B. Node 2 becomes the leader of 1A, 1B later
+     * shouldP is not purged in time. This can easily happen if we dont get in
+     * time cluster/mastership events. shouldProgram absorbs this negative scenario.
+     */
     @Test
     public void testShouldHandleRoutingCase5() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE1, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -294,49 +431,65 @@
         // Node 1 should program both 1A and 1B
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 2 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1A));
+        assertNotEquals(NODE2, dfh.shouldProgram.get(DEV1B));
 
-        // Mastership of switch 1B moves to Node 2
-        reset(srManager.mastershipService);
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(NODE2).anyTimes();
-        replay(srManager.mastershipService);
+        // Leadership moves to Node 2
+        reset(mockWps.leadershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(new Leadership(
+                DEV1A_PARTITION_ID, new Leader(NODE2, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(new Leadership(
+                DEV1B_PARTITION_ID, new Leader(NODE2, 0, 0), List.of(NODE2, NODE3))).anyTimes();
+        replay(mockWps.leadershipService);
 
         reset(srManager.clusterService);
-        clearCache();
 
         // Node 1 should program 1A, 1B
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNotNull(dfh.shouldProgram.get(DEV1A));
+        assertNotNull(dfh.shouldProgram.get(DEV1B));
         assertTrue(dfh.shouldProgram(DEV1A));
         assertTrue(dfh.shouldProgram(DEV1B));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
 
         reset(srManager.clusterService);
-        clearCache();
 
         // Node 2 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNotNull(dfh.shouldProgram.get(DEV1A));
+        assertNotNull(dfh.shouldProgram.get(DEV1B));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1A));
+        assertEquals(NODE1, dfh.shouldProgram.get(DEV1B));
     }
 
-    // Neither 1A or 1B has master
-    @Test
+    // There is no leadership for 1A, 1B. Super-damaged cluster.
+    @Test(expected = NullPointerException.class)
     public void testShouldHandleRoutingCase6() {
-        expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(null).anyTimes();
-        expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes();
-        replay(srManager.mastershipService);
+        expect(mockWps.leadershipService.getLeadership(DEV1A_PARTITION_ID)).andReturn(null).anyTimes();
+        expect(mockWps.leadershipService.getLeadership(DEV1B_PARTITION_ID)).andReturn(null).anyTimes();
+        replay(mockWps.leadershipService);
 
         expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes();
         expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes();
@@ -345,18 +498,27 @@
         // Node 1 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
 
         reset(srManager.clusterService);
-        clearCache();
+        clearShouldProgram();
 
         // Node 2 should program no device
         expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes();
         replay(srManager.clusterService);
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
         assertFalse(dfh.shouldProgram(DEV1A));
         assertFalse(dfh.shouldProgram(DEV1B));
+        assertNull(dfh.shouldProgram.get(DEV1A));
+        assertNull(dfh.shouldProgram.get(DEV1B));
 
-        assertFalse(dfh.shouldProgram.containsKey(Sets.newHashSet(DEV1A, DEV1B)));
+        assertFalse(dfh.shouldProgram.containsKey(DEV1A));
+        assertFalse(dfh.shouldProgram.containsKey(DEV1B));
     }
 }
\ No newline at end of file
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java b/impl/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
index e9cde67..a4c6fdc 100644
--- a/impl/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
+++ b/impl/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
@@ -88,8 +88,10 @@
     // Host Mac, VLAN
     private static final ProviderId PROVIDER_ID = ProviderId.NONE;
     private static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
+    private static final MacAddress HOST_5_MAC = MacAddress.valueOf("00:00:00:00:00:05");
     private static final VlanId HOST_VLAN_UNTAGGED = VlanId.NONE;
     private static final HostId HOST_ID_UNTAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_UNTAGGED);
+    private static final HostId HOST_5_ID_UNTAGGED = HostId.hostId(HOST_5_MAC, HOST_VLAN_UNTAGGED);
     private static final VlanId HOST_VLAN_TAGGED = VlanId.vlanId((short) 20);
     private static final HostId HOST_ID_TAGGED = HostId.hostId(HOST_MAC, HOST_VLAN_TAGGED);
     // Host IP
@@ -99,6 +101,7 @@
     private static final IpAddress HOST_IP13 = IpAddress.valueOf("10.0.1.3");
     private static final IpAddress HOST_IP14 = IpAddress.valueOf("10.0.1.4");
     private static final IpAddress HOST_IP33 = IpAddress.valueOf("10.0.3.3");
+    private static final IpAddress HOST_IP51 = IpAddress.valueOf("10.0.5.1");
     // Device
     private static final DeviceId DEV1 = DeviceId.deviceId("of:0000000000000001");
     private static final DeviceId DEV2 = DeviceId.deviceId("of:0000000000000002");
@@ -135,7 +138,7 @@
     private static final HostLocation HOST_LOC42 = new HostLocation(CP42, 0);
     private static final ConnectPoint CP39 = new ConnectPoint(DEV3, P9);
     private static final ConnectPoint CP49 = new ConnectPoint(DEV4, P9);
-    // Conenct Point for mastership test
+    // Connect Point for leadership test and move to invalid locations
     private static final ConnectPoint CP51 = new ConnectPoint(DEV5, P1);
     private static final HostLocation HOST_LOC51 = new HostLocation(CP51, 0);
     private static final ConnectPoint CP61 = new ConnectPoint(DEV6, P1);
@@ -199,11 +202,14 @@
     private static final Host HOST1 = new DefaultHost(PROVIDER_ID, HOST_ID_UNTAGGED, HOST_MAC,
             HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC11, HOST_LOC21), Sets.newHashSet(HOST_IP11),
             false);
+    private static final Host HOST5 = new DefaultHost(PROVIDER_ID, HOST_5_ID_UNTAGGED, HOST_5_MAC,
+            HOST_VLAN_UNTAGGED, Sets.newHashSet(HOST_LOC51), Sets.newHashSet(HOST_IP51),
+            false);
 
     // A set of hosts
-    private static final Set<Host> HOSTS = Sets.newHashSet(HOST1);
-    // A set of devices of which we have mastership
-    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
+    private static final Set<Host> HOSTS = Sets.newHashSet(HOST1, HOST5);
+    // A set of devices of which we have leadership
+    private static final Set<DeviceId> LED_DEVICES = Sets.newHashSet(DEV1, DEV2, DEV3, DEV4);
     // A set of interfaces
     private static final Set<Interface> INTERFACES = Sets.newHashSet(INTF11, INTF12, INTF13, INTF21,
             INTF22, INTF31, INTF32, INTF33, INTF39, INTF41, INTF42, INTF49);
@@ -233,7 +239,8 @@
         // Initialize Segment Routing Manager
         SegmentRoutingManager srManager = new MockSegmentRoutingManager(NEXT_TABLE, Maps.newHashMap());
         srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
+        expect(srManager.storageService.consistentMapBuilder()).andReturn(
+                new TestConsistentMap.Builder<>()).anyTimes();
         expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
                 new TestConsistentMultimap.Builder<>()).anyTimes();
         replay(srManager.storageService);
@@ -241,9 +248,9 @@
         srManager.deviceConfiguration = new DeviceConfiguration(srManager);
         srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
         srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
-        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
+        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE,
+                ROUTING_TABLE, LED_DEVICES);
         srManager.interfaceService = new MockInterfaceService(INTERFACES);
-        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
         srManager.hostService = new MockHostService(HOSTS);
         srManager.cfgService = mockNetworkConfigRegistry;
         mockLocationProbingService = new MockHostProbingService();
@@ -1016,4 +1023,15 @@
         assertEquals(Sets.newHashSet(HOST_LOC11, HOST_LOC12), hostHandler.effectiveLocations(regularHost));
         assertEquals(Sets.newHashSet(HOST_LOC21, HOST_LOC22), hostHandler.effectiveLocations(auxHost));
     }
+
+    @Test
+    public void initOfNonLedDevices() {
+        hostHandler.init(DEV5);
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
+
+        hostHandler.init(DEV6);
+        assertEquals(0, ROUTING_TABLE.size());
+        assertEquals(0, BRIDGING_TABLE.size());
+    }
 }
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java b/impl/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
index 0002948..d82908c 100644
--- a/impl/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
+++ b/impl/src/test/java/org/onosproject/segmentrouting/MockDefaultRoutingHandler.java
@@ -29,13 +29,16 @@
 public class MockDefaultRoutingHandler extends DefaultRoutingHandler {
     private Map<ConnectPoint, Set<IpPrefix>> subnetTable;
     private Map<MockRoutingTableKey, MockRoutingTableValue> routingTable;
+    private Set<DeviceId> ledDevices;
 
     MockDefaultRoutingHandler(SegmentRoutingManager srManager,
                               Map<ConnectPoint, Set<IpPrefix>> subnetTable,
-                              Map<MockRoutingTableKey, MockRoutingTableValue> routingTable) {
+                              Map<MockRoutingTableKey, MockRoutingTableValue> routingTable,
+                              Set<DeviceId> ledDevices) {
         super(srManager);
         this.subnetTable = subnetTable;
         this.routingTable = routingTable;
+        this.ledDevices = ledDevices;
     }
 
     @Override
@@ -65,7 +68,7 @@
     }
 
     @Override
-    protected boolean shouldProgram(DeviceId deviceId) {
-        return true;
+    public boolean shouldProgram(DeviceId deviceId) {
+        return ledDevices.contains(deviceId);
     }
 }
\ No newline at end of file
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/MockWorkPartitionService.java b/impl/src/test/java/org/onosproject/segmentrouting/MockWorkPartitionService.java
new file mode 100644
index 0000000..b2d48a6
--- /dev/null
+++ b/impl/src/test/java/org/onosproject/segmentrouting/MockWorkPartitionService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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 org.onosproject.cluster.LeadershipService;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.PartitionId;
+import org.onosproject.net.intent.WorkPartitionServiceAdapter;
+
+import java.util.function.Function;
+
+public class MockWorkPartitionService extends WorkPartitionServiceAdapter {
+
+    LeadershipService leadershipService;
+    static final int NUM_PARTITIONS = 14;
+
+    @Override
+    public <K> NodeId getLeader(K id, Function<K, Long> hasher) {
+        int partition = Math.abs(hasher.apply(id).intValue()) % NUM_PARTITIONS;
+        PartitionId partitionId = new PartitionId(partition);
+        return leadershipService.getLeadership(partitionId.toString()).leaderNodeId();
+    }
+
+}
diff --git a/impl/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java b/impl/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
index e09aaa7..2ab4d01 100644
--- a/impl/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
+++ b/impl/src/test/java/org/onosproject/segmentrouting/RouteHandlerTest.java
@@ -137,8 +137,8 @@
     private static final Set<Host> HOSTS = Sets.newHashSet(H1, H2, H3D, H4);
     private static final Set<Host> HOSTS_ONE_FAIL = Sets.newHashSet(H1, H2, H3S);
     private static final Set<Host> HOSTS_BOTH_FAIL = Sets.newHashSet(H1, H2);
-    // A set of devices of which we have mastership
-    private static final Set<DeviceId> LOCAL_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
+    // A set of devices of which we have leadership
+    private static final Set<DeviceId> LED_DEVICES = Sets.newHashSet(CP1.deviceId(), CP2.deviceId());
     // A set of interfaces
     private static final InterfaceIpAddress IF_IP1 =
             new InterfaceIpAddress(IpAddress.valueOf("10.0.1.254"), IpPrefix.valueOf("10.0.1.254/24"));
@@ -180,7 +180,8 @@
         // Initialize Segment Routing Manager
         srManager = new MockSegmentRoutingManager(NEXT_TABLE, ROUTER_MACS);
         srManager.storageService = createMock(StorageService.class);
-        expect(srManager.storageService.consistentMapBuilder()).andReturn(new TestConsistentMap.Builder<>()).anyTimes();
+        expect(srManager.storageService.consistentMapBuilder()).andReturn(
+                new TestConsistentMap.Builder<>()).anyTimes();
         expect(srManager.storageService.consistentMultimapBuilder()).andReturn(
                 new TestConsistentMultimap.Builder<>()).anyTimes();
         replay(srManager.storageService);
@@ -188,9 +189,9 @@
         srManager.deviceConfiguration = createMock(DeviceConfiguration.class);
         srManager.flowObjectiveService = new MockFlowObjectiveService(BRIDGING_TABLE, NEXT_TABLE);
         srManager.routingRulePopulator = new MockRoutingRulePopulator(srManager, ROUTING_TABLE);
-        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE);
+        srManager.defaultRoutingHandler = new MockDefaultRoutingHandler(srManager, SUBNET_TABLE, ROUTING_TABLE,
+                LED_DEVICES);
         srManager.interfaceService = new MockInterfaceService(INTERFACES);
-        srManager.mastershipService = new MockMastershipService(LOCAL_DEVICES);
         hostService = new MockHostService(HOSTS);
         srManager.hostService = hostService;
         srManager.cfgService = mockNetworkConfigRegistry;
@@ -845,19 +846,17 @@
         expectLastCall().once();
         replay(srManager.deviceConfiguration);
 
+        // We don't lead of:0000000000000004 where RR4 next hop is attached
         re = new RouteEvent(RouteEvent.Type.ALTERNATIVE_ROUTES_CHANGED, RR1, null,
                 Sets.newHashSet(RR2, RR4), Sets.newHashSet(RR1, RR2, RR4));
         routeHandler.processAlternativeRoutesChanged(re);
 
-        assertEquals(2, ROUTING_TABLE.size());
+        assertEquals(1, ROUTING_TABLE.size());
         rtv1 = ROUTING_TABLE.get(new MockRoutingTableKey(CP2.deviceId(), P1));
         assertEquals(M2, rtv1.macAddress);
         assertEquals(V2, rtv1.vlanId);
         assertEquals(CP2.port(), rtv1.portNumber);
-        rtv2 = ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1));
-        assertEquals(M4, rtv2.macAddress);
-        assertEquals(V4, rtv2.vlanId);
-        assertEquals(CP4.port(), rtv2.portNumber);
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1)));
 
         assertEquals(2, SUBNET_TABLE.size());
         assertTrue(SUBNET_TABLE.get(CP2).contains(P1));
@@ -865,4 +864,19 @@
 
         verify(srManager.deviceConfiguration);
     }
+
+    @Test
+    public void initOfNonLedDevices() {
+        // We dont lead CP4
+        ROUTE_STORE.put(P1, Sets.newHashSet(RR4));
+
+        routeHandler.init(CP4.deviceId());
+
+        // No routes programmed in the devices
+        assertEquals(0, ROUTING_TABLE.size());
+        assertNull(ROUTING_TABLE.get(new MockRoutingTableKey(CP4.deviceId(), P1)));
+
+        // But we still store the subnets
+        assertEquals(1, SUBNET_TABLE.size());
+    }
 }