/*
* Copyright (c) 2013 Big Switch Networks, Inc.
*
* Licensed under the Eclipse Public License, Version 1.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.eclipse.org/legal/epl-v10.html
*
* 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.sdnplatform.topology;
import static org.easymock.EasyMock.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.openflow.protocol.OFPhysicalPort;
import org.openflow.util.HexString;
import org.sdnplatform.core.IControllerService;
import org.sdnplatform.core.IOFSwitch;
import org.sdnplatform.core.module.ModuleContext;
import org.sdnplatform.core.test.MockThreadPoolService;
import org.sdnplatform.linkdiscovery.BetterLinkDiscoveryManager;
import org.sdnplatform.linkdiscovery.ILinkDiscovery;
import org.sdnplatform.linkdiscovery.ILinkDiscoveryService;
import org.sdnplatform.linkdiscovery.ILinkDiscovery.LDUpdate;
import org.sdnplatform.linkdiscovery.ILinkDiscovery.UpdateOperation;
import org.sdnplatform.restserver.IRestApiService;
import org.sdnplatform.test.PlatformTestCase;
import org.sdnplatform.threadpool.IThreadPoolService;
import org.sdnplatform.topology.BetterTopologyManager;
import org.sdnplatform.topology.OrderedNodePair;
import org.sdnplatform.topology.TunnelEvent;
import org.sdnplatform.topology.TunnelEvent.TunnelLinkStatus;
import org.sdnplatform.tunnelmanager.ITunnelManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BetterTopologyManagerTest extends PlatformTestCase {
protected static Logger log = LoggerFactory.getLogger(TopologyManagerTest.class);
protected BetterTopologyManager tm;
protected ModuleContext fmc;
protected BetterLinkDiscoveryManager ldm;
protected ILinkDiscoveryService linkDiscoveryService;
protected ITunnelManagerService tunnelService;
protected IRestApiService restApiService;
private IOFSwitch createMockSwitch(Long id) {
IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class);
expect(mockSwitch.getId()).andReturn(id).anyTimes();
return mockSwitch;
}
@Before
public void setUp() throws Exception {
super.setUp();
fmc = new ModuleContext();
ldm = new BetterLinkDiscoveryManager();
tm = new BetterTopologyManager();
tunnelService = createMock(ITunnelManagerService.class);
restApiService = createMock(IRestApiService.class);
fmc.addService(IControllerService.class, getMockControllerProvider());
fmc.addService(ILinkDiscoveryService.class, ldm);
fmc.addService(ITunnelManagerService.class, tunnelService);
fmc.addService(IRestApiService.class, restApiService);
MockThreadPoolService tp = new MockThreadPoolService();
fmc.addService(IThreadPoolService.class, tp);
// Set the timers shorter for faster completion of unit tests.
tm.setTopologyComputeInterval(30);
tm.setTunnelDetectionTimeout(90);
tm.setTunnelVerificationTimeout(90);
ldm.init(fmc);
tp.init(fmc);
tm.init(fmc);
ldm.startUp(fmc);
tp.startUp(fmc);
tm.startUp(fmc);
// Create two physical ports.
OFPhysicalPort p1 = new OFPhysicalPort();
p1.setHardwareAddress(HexString.fromHexString("5c:16:c7:00:00:01"));
p1.setCurrentFeatures(0);
OFPhysicalPort p2 = new OFPhysicalPort();
p2.setHardwareAddress(HexString.fromHexString("5c:16:c7:00:00:02"));
p2.setCurrentFeatures(0);
// Create mock switches.
IOFSwitch sw1 = createMockSwitch(1L);
IOFSwitch sw2 = createMockSwitch(2L);
Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
switches.put(1L, sw1);
switches.put(2L, sw2);
getMockControllerProvider().setSwitches(switches);
Set<Short> ports = new HashSet<Short>();
ports.add((short)1);
expect(sw1.getEnabledPortNumbers()).andReturn(ports).anyTimes();
expect(sw2.getEnabledPortNumbers()).andReturn(ports).anyTimes();
expect(sw1.getPort(EasyMock.anyShort())).andReturn(p1).anyTimes();
expect(sw2.getPort(EasyMock.anyShort())).andReturn(p2).anyTimes();
replay(sw1, sw2);
// Set tunnel manager expectations. Switches 1 and 2 contain
// one tunnel port, the port number is 1.
expect(tunnelService.getTunnelPortNumber(EasyMock.anyLong())).andReturn(new Short((short)1)).anyTimes();
expect(tunnelService.getTunnelIPAddr(2L)).andReturn(1).anyTimes();
expect(tunnelService.isTunnelActiveByDpid(EasyMock.anyLong())).andReturn(true).anyTimes();
replay(tunnelService);
}
/**
* This test ensures that when a tunnel event is removed properly from
* the tunnel detection queue.
* @throws Exception
*/
@Test
public void testDetectionCorrectness() throws Exception {
BlockingQueue<OrderedNodePair> dqueue;
tm.detectTunnelSource(1L, 2L);
dqueue = tm.getTunnelDetectionQueue();
assertTrue(dqueue.contains(new OrderedNodePair(1L, 2L)));
tm.detectTunnelDestination(1L, 2L);
assertTrue(dqueue.isEmpty());
}
/**
* This test ensures that when a tunnel event is removed properly from
* the tunnel verification queue.
* @throws Exception
*/
@Test
public void testTunnelVerificationCorrectness() throws Exception {
BlockingQueue<OrderedNodePair> dqueue, vqueue;
tm.detectTunnelSource(1L, 2L);
dqueue = tm.getTunnelDetectionQueue();
vqueue = tm.getTunnelVerificationQueue();
assertTrue(dqueue.contains(new OrderedNodePair(1L, 2L)));
Thread.sleep(tm.TUNNEL_DETECTION_TIMEOUT_MS+ tm.getTopologyComputeInterval());
assertTrue(dqueue.isEmpty());
assertTrue(vqueue.contains(new OrderedNodePair(1L, 2L)));
// This addOrUpdateTunnelLink is generated by LinkDiscoveryManager.
LDUpdate update = new LDUpdate(1L, (short)1, 2L, (short)1,
ILinkDiscovery.LinkType.TUNNEL,
UpdateOperation.LINK_UPDATED);
tm.linkDiscoveryUpdate(update);
Thread.sleep(tm.getTopologyComputeInterval());
assertTrue(vqueue.isEmpty());
}
/**
* This test ensures that the entire sequence of tunnel liveness detection
* goes through all the three queues.
* @throws Exception
*/
@Test
public void testDetectFailureSequence() throws Exception {
BlockingQueue<OrderedNodePair> dqueue, vqueue;
List<TunnelEvent> statusList;
tm.detectTunnelSource(1L, 2L);
dqueue = tm.getTunnelDetectionQueue();
vqueue = tm.getTunnelVerificationQueue();
assertTrue(dqueue.contains(new OrderedNodePair(1L, 2L)));
Thread.sleep(tm.TUNNEL_DETECTION_TIMEOUT_MS+ tm.getTopologyComputeInterval());
assertTrue(dqueue.isEmpty());
assertTrue(vqueue.contains(new OrderedNodePair(1L, 2L)));
Thread.sleep(tm.TUNNEL_VERIFICATION_TIMEOUT_MS+tm.getTopologyComputeInterval());
statusList = tm.getTunnelLivenessState();
assertTrue(vqueue.isEmpty());
assertTrue(statusList.size() == 1);
assertTrue(statusList.get(0).getSrcDPID() == 1);
assertTrue(statusList.get(0).getDstDPID() == 2);
assertTrue(statusList.get(0).getStatus() == TunnelLinkStatus.DOWN);
}
}