Deleted device manager's inside global cache and changed to use the topo cache.
The reason is it caused some unmatched condition with the topo cache when link and port status was changed.
The DeviceEvent timing is changed.
The old one sends it when it is appeared, or attachment point or IP is changed, but now it sends every packet-in to update last-time-seen.

Note:
Looks like there is some vulnerability for changing the mastership of switches.
During mastership changes, the intent reroute is occured, and for a short period of time links or ports haven't found,
so the intent cann't calcurate its path.

Change-Id: I311fa5ad368ca833915999ad112274f1a7979387
diff --git a/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceManagerTest.java b/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceManagerTest.java
index 0b9defb..22900cc 100644
--- a/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceManagerTest.java
+++ b/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceManagerTest.java
@@ -7,7 +7,6 @@
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
 
 import java.util.Date;
 
@@ -16,12 +15,12 @@
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IUpdate;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.test.FloodlightTestCase;
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.core.datagrid.IDatagridService;
 import net.onrc.onos.core.datagrid.IEventChannel;
 import net.onrc.onos.core.datagrid.IEventChannelListener;
-import net.onrc.onos.core.intent.MockTopology;
 import net.onrc.onos.core.packet.ARP;
 import net.onrc.onos.core.packet.DHCP;
 import net.onrc.onos.core.packet.Data;
@@ -32,6 +31,7 @@
 import net.onrc.onos.core.registry.IControllerRegistryService;
 import net.onrc.onos.core.topology.ITopologyListener;
 import net.onrc.onos.core.topology.ITopologyService;
+import net.onrc.onos.core.topology.MockTopology;
 
 import org.easymock.EasyMock;
 import org.junit.After;
@@ -51,9 +51,9 @@
     private IPacket pkt0, pkt1, pkt2, pkt3, pkt4;
     private IOFSwitch sw1;
     private long sw1Dpid;
-    private short sw1DevPort;
+    private long sw1DevPort, sw1DevPort2;
     private OnosDeviceManager odm;
-    private OFPacketIn pktIn;
+    private OFPacketIn pktIn, pktIn2;
     private FloodlightModuleContext modContext;
     private ITopologyService networkGraphService;
     private IEventChannel<Long, OnosDevice> eventChannel;
@@ -69,7 +69,7 @@
         IDatagridService datagridService;
         IControllerRegistryService controllerRegistryService;
 
-        topology.createSampleTopology1();
+        topology.createSampleTopology2();
         modContext = new FloodlightModuleContext();
 
         floodLightProvider = createMock(IFloodlightProviderService.class);
@@ -104,6 +104,7 @@
         replay(sw1);
 
         sw1DevPort = 100;
+        sw1DevPort2 = 12L;
 
         odm = new OnosDeviceManager();
         /*
@@ -201,13 +202,11 @@
                 .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
 
 
-        this.pktIn = new OFPacketIn()
-        .setInPort(sw1DevPort);
+        this.pktIn = new OFPacketIn().setInPort((short) sw1DevPort);
+
+        this.pktIn2 = new OFPacketIn().setInPort((short) sw1DevPort2);
 
         lastSeenTimestamp = new Date(1);
-
-        odm.init(modContext);
-        odm.startUp(modContext);
     }
 
     @Override
@@ -264,30 +263,46 @@
 
     /**
      * This test will invoke addOnosDevice to add a new device through Packet pkt1.
+     * @throws FloodlightModuleException
      */
     @Test
-    public void testProcessPacketInAddNewDevice() {
-        Ethernet eth = (Ethernet) pkt1;
-        Long longmac = eth.getSourceMAC().toLong();
-        OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
-
-        floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN), EasyMock.isA(OnosDeviceManager.class));
-        EasyMock.expectLastCall();
-        eventChannel.addEntry(longmac, srcDevice);
+    public void testProcessPacketInAddNewDevice() throws FloodlightModuleException {
+        floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
+                EasyMock.isA(OnosDeviceManager.class));
         EasyMock.expectLastCall();
         floodLightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
         EasyMock.expectLastCall();
-        replay(floodLightProvider, eventChannel);
+        replay(floodLightProvider);
 
+        odm.init(modContext);
+        odm.startUp(modContext);
         Command cmd = odm.processPacketIn(sw1, pktIn, (Ethernet) pkt1);
         assertEquals(Command.CONTINUE, cmd);
 
-        verify(eventChannel);
+        EasyMock.verify(floodLightProvider);
     }
 
     /**
-     * This test will test return Command.STOP path in processPacketIn method
-     * by injecting a broadcast packet.
+     * Test ProcessPacket function.
+     * @throws FloodlightModuleException
+     */
+    @Test
+    public void testProcessPacketInHasLink() throws FloodlightModuleException {
+        floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN),
+                EasyMock.isA(OnosDeviceManager.class));
+        EasyMock.expectLastCall();
+        replay(floodLightProvider);
+
+        odm.init(modContext);
+        odm.startUp(modContext);
+        Command cmd = odm.processPacketIn(sw1, pktIn2, (Ethernet) pkt1);
+        assertEquals(Command.CONTINUE, cmd);
+
+        EasyMock.verify(floodLightProvider);
+    }
+
+    /**
+     * Test return Command.STOP path in processPacketIn method by injecting a broadcast packet.
      */
     @Test
     public void testProcessPacketInStop() {
@@ -296,99 +311,69 @@
     }
 
     /**
-     * This tests same packet received case.
-     */
-    @Test
-    public void testProcessPacketInSamePacket() {
-        Ethernet eth = (Ethernet) pkt2;
-        OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
-        odm.entryAdded(srcDevice);
-        srcDevice.setLastSeenTimestamp(lastSeenTimestamp);
-
-        Command cmd = odm.processPacketIn(sw1, pktIn, (Ethernet) pkt2);
-        assertEquals(Command.CONTINUE, cmd);
-        assertTrue(lastSeenTimestamp.before(srcDevice.getLastSeenTimestamp()));
-    }
-
-    /**
-     * This tests the packet with the same MAC but the second one without IP address.
-     */
-    @Test
-    public void testProcessPacketInNoIpAddress() {
-        Ethernet eth = (Ethernet) pkt3;
-        OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
-        odm.entryAdded(srcDevice);
-        srcDevice.setLastSeenTimestamp(lastSeenTimestamp);
-
-        Command cmd = odm.processPacketIn(sw1, pktIn, (Ethernet) pkt2);
-        assertEquals(Command.CONTINUE, cmd);
-        assertTrue(lastSeenTimestamp.before(srcDevice.getLastSeenTimestamp()));
-    }
-
-    /**
      * Test add a device from the information from packet.
+     * @throws FloodlightModuleException
      */
     @Test
-    public void testAddOnosDevice() {
+    public void testAddOnosDevice() throws FloodlightModuleException {
         Ethernet eth = (Ethernet) pkt1;
         Long longmac = eth.getSourceMAC().toLong();
         OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
 
         floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN), EasyMock.isA(OnosDeviceManager.class));
         EasyMock.expectLastCall();
-        eventChannel.addEntry(longmac, srcDevice);
-        EasyMock.expectLastCall();
         floodLightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
         EasyMock.expectLastCall();
-        replay(floodLightProvider, eventChannel);
+        replay(floodLightProvider);
 
+        odm.init(modContext);
+        odm.startUp(modContext);
         odm.addOnosDevice(longmac, srcDevice);
 
-        verify(eventChannel);
+        EasyMock.verify(floodLightProvider);
     }
 
     /**
      * Test delete a device.
+     * @throws FloodlightModuleException
      */
     @Test
-    public void testDeleteOnosDevice() {
+    public void testDeleteOnosDevice() throws FloodlightModuleException {
         Ethernet eth = (Ethernet) pkt1;
-        Long longmac = eth.getSourceMAC().toLong();
         OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
 
         floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN), EasyMock.isA(OnosDeviceManager.class));
         EasyMock.expectLastCall();
-        eventChannel.removeEntry(longmac);
-        EasyMock.expectLastCall();
         floodLightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
         EasyMock.expectLastCall();
-        replay(floodLightProvider, eventChannel);
+        replay(floodLightProvider);
 
+        odm.init(modContext);
+        odm.startUp(modContext);
         odm.deleteOnosDevice(srcDevice);
 
-        verify(eventChannel);
+        EasyMock.verify(floodLightProvider);
     }
 
     /**
      * Test delete a device by using its source mac address.
+     * @throws FloodlightModuleException
      */
     @Test
-    public void testDeleteOnosDeviceByMac() {
+    public void testDeleteOnosDeviceByMac() throws FloodlightModuleException {
         Ethernet eth = (Ethernet) pkt1;
         MACAddress mac = eth.getSourceMAC();
-        Long longmac = mac.toLong();
-        OnosDevice srcDevice = odm.getSourceDeviceFromPacket(eth, sw1Dpid, sw1DevPort);
 
         floodLightProvider.addOFMessageListener(EasyMock.eq(OFType.PACKET_IN), EasyMock.isA(OnosDeviceManager.class));
         EasyMock.expectLastCall();
-        eventChannel.removeEntry(longmac);
-        EasyMock.expectLastCall();
         floodLightProvider.publishUpdate(EasyMock.isA(IUpdate.class));
         EasyMock.expectLastCall();
-        replay(floodLightProvider, eventChannel);
+        replay(floodLightProvider);
 
-        odm.entryAdded(srcDevice);
+        odm.init(modContext);
+        odm.startUp(modContext);
         odm.deleteOnosDeviceByMac(mac);
-        verify(eventChannel);
+
+        EasyMock.verify(floodLightProvider);
     }
 }
diff --git a/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceTest.java b/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceTest.java
new file mode 100644
index 0000000..6c79bf0
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/devicemanager/OnosDeviceTest.java
@@ -0,0 +1,65 @@
+package net.onrc.onos.core.devicemanager;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+
+import net.floodlightcontroller.util.MACAddress;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/*
+ * This is the test for OnosDevice.class.
+ */
+public class OnosDeviceTest {
+
+    MACAddress mac1;
+    MACAddress mac2;
+    Long dpid1;
+    Long dpid2;
+    Long portNum1;
+    Long portNum2;
+    Date date1;
+    Date date2;
+
+    @Before
+    public void setUp() throws Exception {
+        mac1 = MACAddress.valueOf("00:00:00:00:00:01");
+        mac2 = MACAddress.valueOf("00:00:00:00:00:01");
+        dpid1 = 1L;
+        dpid2 = 1L;
+        portNum1 = 1L;
+        portNum2 = 1L;
+        date1 = new Date(1L);
+        date2 = new Date(2L);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    /*
+     * Test for making sure hashCode function works properly.
+     */
+    @Test
+    public void testHashCode() {
+        OnosDevice dev1 = new OnosDevice(mac1, null, dpid1, portNum1, date1);
+        OnosDevice dev2 = new OnosDevice(mac2, null, dpid2, portNum2, date2);
+
+        assertTrue(dev1.hashCode() == dev2.hashCode());
+    }
+
+    /*
+     * Test for making sure equals function works properly.
+     */
+    @Test
+    public void testEqualsObject() {
+        OnosDevice dev1 = new OnosDevice(mac1, null, dpid1, portNum1, date1);
+        OnosDevice dev2 = new OnosDevice(mac2, null, dpid2, portNum2, date2);
+
+        assertTrue(dev1.equals(dev2));
+    }
+
+}
diff --git a/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
index 4a58b90..9a3aaa2 100644
--- a/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
@@ -5,6 +5,7 @@
 import static org.junit.Assert.assertNull;
 import net.onrc.onos.core.intent.IntentOperation.Operator;
 import net.onrc.onos.core.topology.LinkEvent;
+import net.onrc.onos.core.topology.MockTopology;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/src/test/java/net/onrc/onos/core/intent/MockTopology.java b/src/test/java/net/onrc/onos/core/intent/MockTopology.java
deleted file mode 100644
index ddbdbe7..0000000
--- a/src/test/java/net/onrc/onos/core/intent/MockTopology.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package net.onrc.onos.core.intent;
-
-import net.onrc.onos.core.topology.Link;
-import net.onrc.onos.core.topology.LinkImpl;
-import net.onrc.onos.core.topology.Switch;
-import net.onrc.onos.core.topology.SwitchImpl;
-import net.onrc.onos.core.topology.TopologyImpl;
-
-/**
- * A mock class of Topology.
- * This class should be used only by test codes.
- */
-public class MockTopology extends TopologyImpl {
-    // TODO this class doesn't seem like it should extend TopologyImpl. It
-    // isn't a Topology, it's more of a TopologyBuilder - methods to
-    // create an populate a fake topology that's not based on discovery
-    // data from the driver modules.
-    // We may well need a MockTopology, but that's not what this class is
-    // doing.
-
-    public static final Long LOCAL_PORT = 0xFFFEL;
-    public SwitchImpl sw1, sw2, sw3, sw4;
-
-    public Switch addSwitch(Long switchId) {
-        SwitchImpl sw = new SwitchImpl(this, switchId);
-        this.putSwitch(sw);
-        return sw;
-    }
-
-    public Link[] addBidirectionalLinks(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
-        Link[] links = new Link[2];
-        links[0] = new LinkImpl(this, getPort(srcDpid, srcPortNo), getPort(dstDpid, dstPortNo));
-        links[1] = new LinkImpl(this, getPort(dstDpid, dstPortNo), getPort(srcDpid, srcPortNo));
-
-        putLink(links[0]);
-        putLink(links[1]);
-
-        return links;
-    }
-
-    /**
-     * create sample topology of 4 switches and 5 bidirectional links.
-     * <pre>
-     * [1] --- [2]
-     *  |    /  |
-     *  |  /    |
-     * [4] --- [3]
-     * </pre>
-     */
-    public void createSampleTopology1() {
-        sw1 = (SwitchImpl) addSwitch(1L);
-        sw1.addPort(LOCAL_PORT);
-        sw2 = (SwitchImpl) addSwitch(2L);
-        sw2.addPort(LOCAL_PORT);
-        sw3 = (SwitchImpl) addSwitch(3L);
-        sw3.addPort(LOCAL_PORT);
-        sw4 = (SwitchImpl) addSwitch(4L);
-        sw4.addPort(LOCAL_PORT);
-
-        sw1.addPort(12L); // sw1 -> sw2
-        sw1.addPort(14L); // sw1 -> sw4
-        sw2.addPort(21L); // sw2 -> sw1
-        sw2.addPort(23L); // sw2 -> sw3
-        sw2.addPort(24L); // sw2 -> sw4
-        sw3.addPort(32L); // sw3 -> sw2
-        sw3.addPort(34L); // sw3 -> sw4
-        sw4.addPort(41L); // sw4 -> sw1
-        sw4.addPort(42L); // sw4 -> sw2
-        sw4.addPort(43L); // sw4 -> sw3
-
-        addBidirectionalLinks(1L, 12L, 2L, 21L);
-        addBidirectionalLinks(2L, 23L, 3L, 32L);
-        addBidirectionalLinks(3L, 34L, 4L, 43L);
-        addBidirectionalLinks(4L, 41L, 1L, 14L);
-        addBidirectionalLinks(2L, 24L, 4L, 42L);
-
-        // set capacity of all links to 1000Mbps
-        for (Link link : getLinks()) {
-            ((LinkImpl) link).setCapacity(1000.0);
-        }
-    }
-
-    public void removeLink(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
-        removeLink(getLink(srcDpid, srcPortNo, dstDpid, dstPortNo));
-    }
-}
diff --git a/src/test/java/net/onrc/onos/core/intent/runtime/IntentTestMocks.java b/src/test/java/net/onrc/onos/core/intent/runtime/IntentTestMocks.java
index 1a2e1c5..a6dde8b 100644
--- a/src/test/java/net/onrc/onos/core/intent/runtime/IntentTestMocks.java
+++ b/src/test/java/net/onrc/onos/core/intent/runtime/IntentTestMocks.java
@@ -1,19 +1,5 @@
 package net.onrc.onos.core.intent.runtime;
 
-
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.onrc.onos.core.datagrid.IDatagridService;
-import net.onrc.onos.core.datagrid.IEventChannel;
-import net.onrc.onos.core.datagrid.IEventChannelListener;
-import net.onrc.onos.core.intent.IntentOperationList;
-import net.onrc.onos.core.intent.MockTopology;
-import net.onrc.onos.core.intent.runtime.web.IntentWebRoutable;
-import net.onrc.onos.core.registry.IControllerRegistryService;
-import net.onrc.onos.core.topology.ITopologyListener;
-import net.onrc.onos.core.topology.ITopologyService;
-import org.powermock.api.easymock.PowerMock;
-
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.eq;
@@ -21,6 +7,19 @@
 import static org.easymock.EasyMock.expectLastCall;
 import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.core.datagrid.IDatagridService;
+import net.onrc.onos.core.datagrid.IEventChannel;
+import net.onrc.onos.core.datagrid.IEventChannelListener;
+import net.onrc.onos.core.intent.IntentOperationList;
+import net.onrc.onos.core.intent.runtime.web.IntentWebRoutable;
+import net.onrc.onos.core.registry.IControllerRegistryService;
+import net.onrc.onos.core.topology.ITopologyListener;
+import net.onrc.onos.core.topology.ITopologyService;
+import net.onrc.onos.core.topology.MockTopology;
+
+import org.powermock.api.easymock.PowerMock;
 
 /**
  * This class contains all of the mocked code required to run a test that uses
diff --git a/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java b/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java
index 9623436..5d4adb8 100644
--- a/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/runtime/PathCalcRuntimeModuleTest.java
@@ -17,10 +17,10 @@
 import net.onrc.onos.core.intent.IntentMap;
 import net.onrc.onos.core.intent.IntentOperation.Operator;
 import net.onrc.onos.core.intent.IntentOperationList;
-import net.onrc.onos.core.intent.MockTopology;
 import net.onrc.onos.core.intent.ShortestPathIntent;
 import net.onrc.onos.core.topology.DeviceEvent;
 import net.onrc.onos.core.topology.LinkEvent;
+import net.onrc.onos.core.topology.MockTopology;
 import net.onrc.onos.core.topology.PortEvent;
 import net.onrc.onos.core.topology.SwitchEvent;
 
diff --git a/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java b/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java
index d911d2f..76af2ec 100644
--- a/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/runtime/UseCaseTest.java
@@ -24,7 +24,6 @@
 import net.onrc.onos.core.intent.Intent.IntentState;
 import net.onrc.onos.core.intent.IntentOperation.Operator;
 import net.onrc.onos.core.intent.IntentOperationList;
-import net.onrc.onos.core.intent.MockTopology;
 import net.onrc.onos.core.intent.PathIntent;
 import net.onrc.onos.core.intent.PathIntentMap;
 import net.onrc.onos.core.intent.ShortestPathIntent;
@@ -34,6 +33,7 @@
 import net.onrc.onos.core.topology.ITopologyListener;
 import net.onrc.onos.core.topology.ITopologyService;
 import net.onrc.onos.core.topology.LinkEvent;
+import net.onrc.onos.core.topology.MockTopology;
 import net.onrc.onos.core.topology.PortEvent;
 import net.onrc.onos.core.topology.SwitchEvent;
 import net.onrc.onos.core.topology.Topology;
diff --git a/src/test/java/net/onrc/onos/core/topology/MockTopology.java b/src/test/java/net/onrc/onos/core/topology/MockTopology.java
new file mode 100644
index 0000000..888779a
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/topology/MockTopology.java
@@ -0,0 +1,140 @@
+package net.onrc.onos.core.topology;
+
+import net.floodlightcontroller.util.MACAddress;
+
+/**
+ * A mock class of Topology.
+ * This class should be used only by test codes.
+ */
+public class MockTopology extends TopologyImpl {
+    // TODO this class doesn't seem like it should extend TopologyImpl. It
+    // isn't a Topology, it's more of a TopologyBuilder - methods to
+    // create an populate a fake topology that's not based on discovery
+    // data from the driver modules.
+    // We may well need a MockTopology, but that's not what this class is
+    // doing.
+
+    public static final Long LOCAL_PORT = 0xFFFEL;
+    public SwitchImpl sw1, sw2, sw3, sw4;
+
+    public Switch addSwitch(Long switchId) {
+        SwitchImpl sw = new SwitchImpl(this, switchId);
+        this.putSwitch(sw);
+        return sw;
+    }
+
+    public Link[] addBidirectionalLinks(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
+        Link[] links = new Link[2];
+        links[0] = new LinkImpl(this, getPort(srcDpid, srcPortNo), getPort(dstDpid, dstPortNo));
+        links[1] = new LinkImpl(this, getPort(dstDpid, dstPortNo), getPort(srcDpid, srcPortNo));
+
+        putLink(links[0]);
+        putLink(links[1]);
+
+        return links;
+    }
+
+    /**
+     * create sample topology of 4 switches and 5 bidirectional links.
+     * <pre>
+     * [1] --- [2]
+     *  |    /  |
+     *  |  /    |
+     * [4] --- [3]
+     * </pre>
+     */
+    public void createSampleTopology1() {
+        sw1 = (SwitchImpl) addSwitch(1L);
+        sw1.addPort(LOCAL_PORT);
+        sw2 = (SwitchImpl) addSwitch(2L);
+        sw2.addPort(LOCAL_PORT);
+        sw3 = (SwitchImpl) addSwitch(3L);
+        sw3.addPort(LOCAL_PORT);
+        sw4 = (SwitchImpl) addSwitch(4L);
+        sw4.addPort(LOCAL_PORT);
+
+        sw1.addPort(12L); // sw1 -> sw2
+        sw1.addPort(14L); // sw1 -> sw4
+        sw2.addPort(21L); // sw2 -> sw1
+        sw2.addPort(23L); // sw2 -> sw3
+        sw2.addPort(24L); // sw2 -> sw4
+        sw3.addPort(32L); // sw3 -> sw2
+        sw3.addPort(34L); // sw3 -> sw4
+        sw4.addPort(41L); // sw4 -> sw1
+        sw4.addPort(42L); // sw4 -> sw2
+        sw4.addPort(43L); // sw4 -> sw3
+
+        addBidirectionalLinks(1L, 12L, 2L, 21L);
+        addBidirectionalLinks(2L, 23L, 3L, 32L);
+        addBidirectionalLinks(3L, 34L, 4L, 43L);
+        addBidirectionalLinks(4L, 41L, 1L, 14L);
+        addBidirectionalLinks(2L, 24L, 4L, 42L);
+
+        // set capacity of all links to 1000Mbps
+        for (Link link : getLinks()) {
+            ((LinkImpl) link).setCapacity(1000.0);
+        }
+    }
+
+    /**
+     * create sample topology of 4 switches and 5 bidirectional links.
+     * <pre>
+     *
+     *
+     * [H1]-[1] --- [2]
+     *       |    /  |
+     *       |  /    |
+     *      [4] --- [3]-[H3]
+     * </pre>
+     */
+    public void createSampleTopology2() {
+        sw1 = (SwitchImpl) addSwitch(1L);
+        sw1.addPort(LOCAL_PORT);
+        sw2 = (SwitchImpl) addSwitch(2L);
+        sw2.addPort(LOCAL_PORT);
+        sw3 = (SwitchImpl) addSwitch(3L);
+        sw3.addPort(LOCAL_PORT);
+        sw4 = (SwitchImpl) addSwitch(4L);
+        sw4.addPort(LOCAL_PORT);
+
+        Port port12 = sw1.addPort(12L); // sw1 -> sw2
+        Port port14 = sw1.addPort(14L); // sw1 -> sw4
+        Port port15 = sw1.addPort(15L); // sw1 -> h1
+        Port port21 = sw2.addPort(21L); // sw2 -> sw1
+        Port port23 = sw2.addPort(23L); // sw2 -> sw3
+        Port port24 = sw2.addPort(24L); // sw2 -> sw4
+        Port port32 = sw3.addPort(32L); // sw3 -> sw2
+        Port port34 = sw3.addPort(34L); // sw3 -> sw4
+        Port port35 = sw3.addPort(35L); // sw3 -> h3
+        Port port41 = sw4.addPort(41L); // sw4 -> sw1
+        Port port42 = sw4.addPort(42L); // sw4 -> sw2
+        Port port43 = sw4.addPort(43L); // sw4 -> sw3
+
+        MACAddress mac1 = MACAddress.valueOf("00:44:33:22:11:00");
+        DeviceImpl dev1 = new DeviceImpl(this, mac1);
+        dev1.addAttachmentPoint(port15);
+        dev1.setLastSeenTime(1L);
+        this.putDevice(dev1);
+
+        MACAddress mac3 = MACAddress.valueOf("00:11:22:33:44:55");
+        DeviceImpl dev3 = new DeviceImpl(this, mac3);
+        dev3.addAttachmentPoint(port35);
+        dev3.setLastSeenTime(1L);
+        this.putDevice(dev3);
+
+        addBidirectionalLinks(1L, 12L, 2L, 21L);
+        addBidirectionalLinks(2L, 23L, 3L, 32L);
+        addBidirectionalLinks(3L, 34L, 4L, 43L);
+        addBidirectionalLinks(4L, 41L, 1L, 14L);
+        addBidirectionalLinks(2L, 24L, 4L, 42L);
+
+        // set capacity of all links to 1000Mbps
+        for (Link link : getLinks()) {
+            ((LinkImpl) link).setCapacity(1000.0);
+        }
+    }
+
+    public void removeLink(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
+        removeLink(getLink(srcDpid, srcPortNo, dstDpid, dstPortNo));
+    }
+}