| /* |
| * Copyright 2018-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 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.NodeId; |
| import org.onosproject.mastership.MastershipService; |
| import org.onosproject.net.DeviceId; |
| import org.onosproject.net.device.DeviceService; |
| import org.onosproject.segmentrouting.config.DeviceConfiguration; |
| import org.onosproject.store.service.StorageService; |
| import org.onosproject.store.service.TestConsistentMap; |
| import org.onosproject.store.service.TestConsistentMultimap; |
| |
| import java.util.Optional; |
| |
| import static org.easymock.EasyMock.createMock; |
| import static org.easymock.EasyMock.expect; |
| import static org.easymock.EasyMock.replay; |
| import static org.easymock.EasyMock.reset; |
| import static org.junit.Assert.*; |
| |
| public class DefaultRoutingHandlerTest { |
| private SegmentRoutingManager srManager; |
| private DefaultRoutingHandler dfh; |
| |
| 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 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"); |
| private static final IpAddress IP1 = IpAddress.valueOf("192.168.1.1"); |
| private static final IpAddress IP2 = IpAddress.valueOf("192.168.1.2"); |
| private static final IpAddress IP3 = IpAddress.valueOf("192.168.1.3"); |
| |
| @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.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); |
| srManager.clusterService = createMock(ClusterService.class); |
| dfh = new DefaultRoutingHandler(srManager); |
| } |
| |
| private void clearCache() { |
| dfh.invalidateShouldProgramCache(DEV1A); |
| dfh.invalidateShouldProgramCache(DEV1B); |
| dfh.invalidateShouldProgramCache(DEV2); |
| } |
| |
| // Node 1 is the master 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(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program every device |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| assertTrue(dfh.shouldProgram(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(); |
| |
| // Node 3 should program no device |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(DEV2)); |
| } |
| |
| // Node 1 is the master of switch 1A, 1B |
| // Node 2 is the master 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(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program 1A, 1B |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(DEV2)); |
| |
| reset(srManager.clusterService); |
| clearCache(); |
| |
| // Node 2 should program 2 |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE2, IP2)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertTrue(dfh.shouldProgram(DEV2)); |
| |
| reset(srManager.clusterService); |
| clearCache(); |
| |
| // Node 3 should program no device |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(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 |
| @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(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program 1A, 1B |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(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(); |
| |
| // Node 3 should program 2 |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertTrue(dfh.shouldProgram(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. |
| @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(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV2)).andReturn(Optional.empty()).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program no device |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(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(); |
| |
| // 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); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| assertFalse(dfh.shouldProgram(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(); |
| |
| // Node 3 should program 2 |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE3, IP3)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| assertTrue(dfh.shouldProgram(DEV2)); |
| } |
| |
| // Node 1 is the master of 1A. 1B has no master |
| // Node 2 becomes the master of 1B later |
| @Test |
| public void testShouldHandleRoutingCase5() { |
| expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(NODE1).anyTimes(); |
| expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes(); |
| replay(srManager.mastershipService); |
| |
| expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program both 1A and 1B |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| |
| 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)); |
| |
| // 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); |
| |
| reset(srManager.clusterService); |
| clearCache(); |
| |
| // Node 1 should program 1A, 1B |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertTrue(dfh.shouldProgram(DEV1A)); |
| assertTrue(dfh.shouldProgram(DEV1B)); |
| |
| 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)); |
| } |
| |
| // Neither 1A or 1B has master |
| @Test |
| public void testShouldHandleRoutingCase6() { |
| expect(srManager.mastershipService.getMasterFor(DEV1A)).andReturn(null).anyTimes(); |
| expect(srManager.mastershipService.getMasterFor(DEV1B)).andReturn(null).anyTimes(); |
| replay(srManager.mastershipService); |
| |
| expect(srManager.getPairDeviceId(DEV1A)).andReturn(Optional.of(DEV1B)).anyTimes(); |
| expect(srManager.getPairDeviceId(DEV1B)).andReturn(Optional.of(DEV1A)).anyTimes(); |
| replay(srManager); |
| |
| // Node 1 should program no device |
| expect(srManager.clusterService.getLocalNode()).andReturn(new DefaultControllerNode(NODE1, IP1)).anyTimes(); |
| replay(srManager.clusterService); |
| assertFalse(dfh.shouldProgram(DEV1A)); |
| assertFalse(dfh.shouldProgram(DEV1B)); |
| |
| 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.containsKey(Sets.newHashSet(DEV1A, DEV1B))); |
| } |
| } |