Merge branch ARP and DeviceStorageImpl fixes branch.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
index 483fbda..c8312d4 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
@@ -43,7 +43,17 @@
 	 *  If only dpid is set all links associated with Switch are retrieved
 	 */
 	public List<Link> getLinks(Long dpid, short port);
+
 	public List<Link> getLinks(String dpid);
+
+	/**
+	 * Get list of all reverse links connected to the switch specified by
+	 * given DPID.
+	 * @param dpid DPID of desired switch.
+	 * @return List of reverse links. Empty list if no port was found.
+	 */
+	public List<Link> getReverseLinks(String dpid);
+
 	public List<Link> getActiveLinks();
 
 	public LinkInfo getLinkInfo(Link link);
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
index 160587f..869333b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
@@ -128,6 +128,10 @@
 		@JsonIgnore
 		@Adjacency(label="link")
 		public Iterable<IPortObject> getLinkedPorts();
+
+		@JsonIgnore
+		@Adjacency(label="link",direction = Direction.IN)
+		public Iterable<IPortObject> getReverseLinkedPorts();
 		
 		@Adjacency(label="link")
 		public void removeLink(final IPortObject dest_port);
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java
index 68e2c6f..09e87ca 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java
@@ -306,6 +306,38 @@
 	}
 
 	/**
+	 * Get list of all reverse links connected to the switch specified by
+	 * given DPID.
+	 * @param dpid DPID of desired switch.
+	 * @return List of reverse links. Empty list if no port was found.
+	 */
+	@Override
+	public List<Link> getReverseLinks(String dpid) {
+		List<Link> links = new ArrayList<Link>();
+
+		ISwitchObject srcSw = op.searchSwitch(dpid);
+		
+		if(srcSw != null) {
+			for(IPortObject srcPort : srcSw.getPorts()) {
+				for(IPortObject dstPort : srcPort.getReverseLinkedPorts()) {
+					ISwitchObject dstSw = dstPort.getSwitch();
+					if(dstSw != null) {
+		        		Link link = new Link(
+							HexString.toLong(dstSw.getDPID()),
+							dstPort.getNumber(),
+					
+							HexString.toLong(srcSw.getDPID()),
+							srcPort.getNumber());
+		        		links.add(link);
+					}
+				}
+			}
+		}
+		
+		return links;
+	}
+
+	/**
 	 * Get list of all links whose state is ACTIVE.
 	 * @return List of active links. Empty list if no port was found.
 	 */
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java
index 1735a36..c01a3cb 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java
@@ -306,6 +306,7 @@
 	        		op.commit();
 	        	}
 	        }
+		success = true;
 		} catch (Exception e) {
 			op.rollback();
 			e.printStackTrace();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index c1f66d9..26292d9 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -3,6 +3,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -212,11 +213,29 @@
 			    // TODO publish ADD_SWITCH event here
 			    TopologyElement topologyElement =
 				new TopologyElement(sw.getId());
+			    datagridService.notificationSendTopologyElementAdded(topologyElement);
+			    // Add the ports
 			    // TODO: Add only ports that are UP?
 			    for (OFPhysicalPort port : sw.getPorts()) {
-				topologyElement.addSwitchPort(port.getPortNumber());
+				TopologyElement topologyElementPort =
+				    new TopologyElement(sw.getId(),
+							port.getPortNumber());
+				datagridService.notificationSendTopologyElementAdded(topologyElementPort);
 			    }
-			    datagridService.notificationSendTopologyElementAdded(topologyElement);
+
+			    // Add all links that might be connected already
+			    List<Link> links = linkStore.getLinks(HexString.toHexString(sw.getId()));
+			    // Add all reverse links as well
+			    List<Link> reverseLinks = linkStore.getReverseLinks(HexString.toHexString(sw.getId()));
+			    links.addAll(reverseLinks);
+			    for (Link link : links) {
+				TopologyElement topologyElementLink =
+				    new TopologyElement(link.getSrc(),
+							link.getSrcPort(),
+							link.getDst(),
+							link.getDstPort());
+				datagridService.notificationSendTopologyElementAdded(topologyElementLink);
+			    }
 			}
 		}
 	}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
index d06c62c..926788f 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowDatabaseOperation.java
@@ -326,6 +326,44 @@
     }
 
     /**
+     * Delete a flow entry from the Network MAP.
+     *
+     * @param dbHandler the Graph Database handler to use.
+     * @param flowObj the corresponding Flow Path object for the Flow Entry.
+     * @param flowEntry the Flow Entry to delete.
+     * @return true on success, otherwise false.
+     */
+    static boolean deleteFlowEntry(GraphDBOperation dbHandler,
+				   IFlowPath flowObj,
+				   FlowEntry flowEntry) {
+	IFlowEntry flowEntryObj = null;
+	try {
+	    flowEntryObj = dbHandler.searchFlowEntry(flowEntry.flowEntryId());
+	} catch (Exception e) {
+	    log.error(":deleteFlowEntry FlowEntryId:{} failed",
+		      flowEntry.flowEntryId().toString());
+	    return false;
+	}
+	//
+	// TODO: Don't print an error for now, because multiple controller
+	// instances might be deleting the same flow entry.
+	//
+	/*
+	if (flowEntryObj == null) {
+	    log.error(":deleteFlowEntry FlowEntryId:{} failed: FlowEntry object not found",
+		      flowEntry.flowEntryId().toString());
+	    return false;
+	}
+	*/
+	if (flowEntryObj == null)
+	    return true;
+
+	flowObj.removeFlowEntry(flowEntryObj);
+	dbHandler.removeFlowEntry(flowEntryObj);
+	return true;
+    }
+
+    /**
      * Delete all previously added flows.
      *
      * @param dbHandler the Graph Database handler to use.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
index 0a6cd76..cb1e678 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
@@ -74,6 +74,13 @@
     }
 
     /**
+     * Get the network topology.
+     *
+     * @return the network topology.
+     */
+    protected Topology getTopology() { return this.topology; }
+
+    /**
      * Run the thread.
      */
     @Override
@@ -107,7 +114,7 @@
 	    flowEntryEvents.add(eventEntry);
 	}
 
-	// Process the events (if any)
+	// Process the initial events (if any)
 	processEvents();
 
 	//
@@ -170,6 +177,9 @@
 	for (EventEntry<FlowPath> eventEntry : flowPathEvents) {
 	    FlowPath flowPath = eventEntry.eventData();
 
+	    log.debug("Flow Event: {} {}", eventEntry.eventType(),
+		      flowPath.toString());
+
 	    switch (eventEntry.eventType()) {
 	    case ENTRY_ADD: {
 		//
@@ -240,6 +250,10 @@
 	boolean isTopologyModified = false;
 	for (EventEntry<TopologyElement> eventEntry : topologyEvents) {
 	    TopologyElement topologyElement = eventEntry.eventData();
+
+	    log.debug("Topology Event: {} {}", eventEntry.eventType(),
+		      topologyElement.toString());
+
 	    switch (eventEntry.eventType()) {
 	    case ENTRY_ADD:
 		isTopologyModified |= topology.addTopologyElement(topologyElement);
@@ -462,7 +476,7 @@
 	    FlowEntry newFlowEntry =
 		newFlowEntriesMap.get(oldFlowEntry.dpid().value());
 	    if (newFlowEntry == null) {
-		// The old Flow Entry should be deleted
+		// The old Flow Entry should be deleted: not on the path
 		oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
 		oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
 		deletedFlowEntries.add(oldFlowEntry);
@@ -490,7 +504,7 @@
 
 	    if (oldFlowEntry != null) {
 		//
-		// The old Flow Entry should be deleted
+		// The old Flow Entry should be deleted: path diverges
 		//
 		oldFlowEntry.setFlowEntryUserState(FlowEntryUserState.FE_USER_DELETE);
 		oldFlowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED);
@@ -545,8 +559,7 @@
 	// Note that the Flow Entries that will be deleted are added at
 	// the end.
 	//
-	for (FlowEntry flowEntry : deletedFlowEntries)
-	    finalFlowEntries.add(flowEntry);
+	finalFlowEntries.addAll(deletedFlowEntries);
 	flowPath.dataPath().setFlowEntries(finalFlowEntries);
 
 	return hasChanged;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index 4465835..c22b916 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -551,6 +551,18 @@
     }
 
     /**
+     * Delete a flow entry from the Network MAP.
+     *
+     * @param flowObj the corresponding Flow Path object for the Flow Entry.
+     * @param flowEntry the Flow Entry to delete.
+     * @return true on success, otherwise false.
+     */
+    private boolean deleteFlowEntry(IFlowPath flowObj, FlowEntry flowEntry) {
+	return FlowDatabaseOperation.deleteFlowEntry(dbHandler, flowObj,
+						     flowEntry);
+    }
+
+    /**
      * Delete all previously added flows.
      *
      * @return true on success, otherwise false.
@@ -702,6 +714,15 @@
     }
 
     /**
+     * Get the network topology.
+     *
+     * @return the network topology.
+     */
+    public Topology getTopology() {
+	return flowEventHandler.getTopology();
+    }
+
+    /**
      * Reconcile a flow.
      *
      * @param flowObj the flow that needs to be reconciliated.
@@ -840,7 +861,6 @@
      * Flow Entries.
      */
     public void pushModifiedFlowEntries(Collection<FlowPath> modifiedFlowPaths) {
-
 	// TODO: For now, the pushing of Flow Entries is disabled
 	if (true)
 	    return;
@@ -848,57 +868,83 @@
 	Map<Long, IOFSwitch> mySwitches = floodlightProvider.getSwitches();
 
 	for (FlowPath flowPath : modifiedFlowPaths) {
+	    //
+	    // Find the Flow Path in the Network MAP.
+	    // NOTE: The Flow Path might not be found if the Flow was just
+	    // removed by some other controller instance.
+	    //
 	    IFlowPath flowObj = dbHandler.searchFlowPath(flowPath.flowId());
-	    if (flowObj == null) {
-		String logMsg = "Cannot find Network MAP entry for Flow Path " +
-		    flowPath.flowId();
-		log.error(logMsg);
-		continue;
-	    }
 
+	    boolean isFlowEntryDeleted = false;
 	    for (FlowEntry flowEntry : flowPath.flowEntries()) {
+		log.debug("Updating Flow Entry: {}", flowEntry.toString());
+
 		if (flowEntry.flowEntrySwitchState() !=
 		    FlowEntrySwitchState.FE_SWITCH_NOT_UPDATED) {
 		    continue;		// No need to update the entry
 		}
+		if (flowEntry.flowEntryUserState() ==
+		    FlowEntryUserState.FE_USER_DELETE) {
+		    isFlowEntryDeleted = true;
+		}
 
+		//
+		// Install the Flow Entries into my switches
+		//
 		IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
-		if (mySwitch == null)
-		    continue;		// Ignore the entry: not my switch
+		if (mySwitch != null) {
+		    //
+		    // Assign the FlowEntry ID if needed
+		    //
+		    if (! flowEntry.isValidFlowEntryId()) {
+			long id = getNextFlowEntryId();
+			flowEntry.setFlowEntryId(new FlowEntryId(id));
+		    }
 
-		//
-		// Assign the FlowEntry ID if needed
-		//
-		if (! flowEntry.isValidFlowEntryId()) {
-		    long id = getNextFlowEntryId();
-		    flowEntry.setFlowEntryId(new FlowEntryId(id));
+		    //
+		    // Install the Flow Entry into the switch
+		    //
+		    if (! installFlowEntry(mySwitch, flowPath, flowEntry)) {
+			String logMsg = "Cannot install Flow Entry " +
+			    flowEntry.flowEntryId() +
+			    " from Flow Path " + flowPath.flowId() +
+			    " on switch " + flowEntry.dpid();
+			log.error(logMsg);
+			continue;
+		    }
+
+		    //
+		    // NOTE: Here we assume that the switch has been
+		    // successfully updated.
+		    //
+		    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
 		}
 
 		//
-		// Install the Flow Entry into the switch
+		// TODO: For now Flow Entries are removed from the Datagrid
+		// and from the Network Map by all instances, even if this
+		// Flow Entry is not for our switches.
 		//
-		if (! installFlowEntry(mySwitch, flowPath, flowEntry)) {
-		    String logMsg = "Cannot install Flow Entry " +
-			flowEntry.flowEntryId() +
-			" from Flow Path " + flowPath.flowId() +
-			" on switch " + flowEntry.dpid();
-		    log.error(logMsg);
-		    continue;
-		}
+		// This is needed to handle the case a switch going down:
+		// it has no Master controller instance, hence no
+		// controller instance will cleanup its flow entries.
+		// This is sub-optimal: we need to elect a controller
+		// instance to handle the cleanup of such orphaned flow
+		// entries.
+		//
 
 		//
-		// NOTE: Here we assume that the switch has been successfully
-		// updated.
-		//
-		flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.FE_SWITCH_UPDATED);
-		//
 		// Write the Flow Entry to the Datagrid
 		//
 		switch (flowEntry.flowEntryUserState()) {
 		case FE_USER_ADD:
+		    if (mySwitch == null)
+			break;	// Install only flow entries for my switches
 		    datagridService.notificationSendFlowEntryAdded(flowEntry);
 		    break;
 		case FE_USER_MODIFY:
+		    if (mySwitch == null)
+			break;	// Install only flow entries for my switches
 		    datagridService.notificationSendFlowEntryUpdated(flowEntry);
 		    break;
 		case FE_USER_DELETE:
@@ -909,15 +955,41 @@
 		//
 		// Write the Flow Entry to the Network Map
 		//
-		try {
-		    if (addFlowEntry(flowObj, flowEntry) == null) {
-			String logMsg = "Cannot write to Network MAP Flow Entry " +
-			    flowEntry.flowEntryId() +
-			    " from Flow Path " + flowPath.flowId() +
-			    " on switch " + flowEntry.dpid();
-			log.error(logMsg);
+		if (mySwitch == null) {
+		    if (flowEntry.flowEntryUserState() !=
+			FlowEntryUserState.FE_USER_DELETE) {
 			continue;
 		    }
+		    if (! flowEntry.isValidFlowEntryId())
+			continue;
+		}
+		if (flowObj == null) {
+		    String logMsg = "Cannot find Network MAP entry for Flow Path " + flowPath.flowId();
+		    continue;
+		}
+		try {
+		    switch (flowEntry.flowEntryUserState()) {
+		    case FE_USER_ADD:
+			// FALLTHROUGH
+		    case FE_USER_MODIFY:
+			if (addFlowEntry(flowObj, flowEntry) == null) {
+			    String logMsg = "Cannot write to Network MAP Flow Entry " +
+				flowEntry.flowEntryId() +
+				" from Flow Path " + flowPath.flowId() +
+				" on switch " + flowEntry.dpid();
+			    log.error(logMsg);
+			}
+			break;
+		    case FE_USER_DELETE:
+			if (deleteFlowEntry(flowObj, flowEntry) == false) {
+			    String logMsg = "Cannot remove from Network MAP Flow Entry " +
+				flowEntry.flowEntryId() +
+				" from Flow Path " + flowPath.flowId() +
+				" on switch " + flowEntry.dpid();
+			    log.error(logMsg);
+			}
+			break;
+		    }
 		} catch (Exception e) {
 		    String logMsg = "Exception writing Flow Entry to Network MAP";
 		    log.debug(logMsg);
@@ -925,6 +997,26 @@
 		    continue;
 		}
 	    }
+
+	    //
+	    // Remove Flow Entries that were deleted
+	    //
+	    // NOTE: We create a new ArrayList, and add only the Flow Entries
+	    // that are NOT FE_USER_DELETE.
+	    // This is sub-optimal: if it adds notable processing cost,
+	    // the Flow Entries container should be changed to LinkedList
+	    // or some other container that has O(1) cost of removing an entry.
+	    //
+	    if (isFlowEntryDeleted) {
+		ArrayList<FlowEntry> newFlowEntries = new ArrayList<FlowEntry>();
+		for (FlowEntry flowEntry : flowPath.flowEntries()) {
+		    if (flowEntry.flowEntryUserState() !=
+			FlowEntryUserState.FE_USER_DELETE) {
+			newFlowEntries.add(flowEntry);
+		    }
+		}
+		flowPath.dataPath().setFlowEntries(newFlowEntries);
+	    }
 	}
 
 	dbHandler.commit();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
index 1f8cd5b..8d362d1 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
@@ -4,6 +4,7 @@
 
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.topology.Topology;
 import net.onrc.onos.ofcontroller.util.CallerId;
 import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
 import net.onrc.onos.ofcontroller.util.FlowId;
@@ -112,4 +113,11 @@
      * @return the added shortest-path flow on success, otherwise null.
      */
     FlowPath addAndMaintainShortestPathFlow(FlowPath flowPath);
+
+    /**
+     * Get the network topology.
+     *
+     * @return the network topology.
+     */
+    Topology getTopology();
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
index d5ceb6a..7d7d739 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/Topology.java
@@ -213,14 +213,6 @@
 		node = addNode(topologyElement.getSwitch());
 		isModified = true;
 	    }
-	    // Add the ports for the switch
-	    for (Integer portId : topologyElement.getSwitchPorts().values()) {
-		Integer port = node.getPort(portId);
-		if (port == null) {
-		    node.addPort(portId);
-		    isModified = true;
-		}
-	    }
 	    break;
 	}
 	case ELEMENT_PORT: {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java
index 574946d..b01c7d3 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/TopologyElement.java
@@ -24,9 +24,6 @@
     private long toSwitchDpid = 0;	// The Neighbor Switch DPID
     private int toSwitchPort = 0;	// The Neighbor Switch Port
 
-    // All (known) ports for a Switch
-    private Map<Integer, Integer> switchPorts = new TreeMap<Integer, Integer>();
-
     /**
      * Default constructor.
      */
@@ -95,28 +92,6 @@
     }
 
     /**
-     * Get the Switch Ports.
-     *
-     * NOTE: Applies for Type.ELEMENT_SWITCH
-     *
-     * @return the collection of Switch Ports.
-     */
-    public Map<Integer, Integer> getSwitchPorts() {
-	return switchPorts;
-    }
-
-    /**
-     * Add a Switch Port.
-     *
-     * NOTE: Applies for Type.ELEMENT_SWITCH
-     *
-     * @param switchPort the Switch Port to add.
-     */
-    public void addSwitchPort(int switchPort) {
-	switchPorts.put(switchPort, switchPort);
-    }
-
-    /**
      * Get the Switch Port.
      *
      * NOTE: Applies for Type.ELEMENT_PORT
diff --git a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
index b340996..0d33b27 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
@@ -1,5 +1,6 @@
 package net.onrc.onos.ofcontroller.topology.web;
 
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 import net.onrc.onos.ofcontroller.topology.ITopologyNetService;
 import net.onrc.onos.ofcontroller.topology.TopologyManager;
 import net.onrc.onos.ofcontroller.util.DataPath;
@@ -18,11 +19,22 @@
 
     @Get("json")
     public DataPath retrieve() {
-        ITopologyNetService topologyNetService = new TopologyManager("");
+	// Get the services that are needed for the computation
+	ITopologyNetService topologyNetService =
+	    (ITopologyNetService)getContext().getAttributes().
+	    get(ITopologyNetService.class.getCanonicalName());
+	IFlowService flowService =
+	    (IFlowService)getContext().getAttributes().
+	    get(IFlowService.class.getCanonicalName());
+
 	if (topologyNetService == null) {
 	    log.debug("Topology Net Service not found");
 	    return null;
 	}
+	if (flowService == null) {
+	    log.debug("Flow Service not found");
+	    return null;
+	}
         
         String srcDpidStr = (String) getRequestAttributes().get("src-dpid");
         String srcPortStr = (String) getRequestAttributes().get("src-port");
@@ -37,7 +49,8 @@
 	Port dstPort = new Port(Short.parseShort(dstPortStr));
         
 	DataPath result =
-	    topologyNetService.getDatabaseShortestPath(
+	    topologyNetService.getTopologyShortestPath(
+		flowService.getTopology(),
 		new SwitchPort(srcDpid, srcPort),
 		new SwitchPort(dstDpid, dstPort));
 	if (result != null) {
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
index abb8809..4aea22a 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
@@ -256,6 +256,21 @@
 		Link linkToVerifyNot = createFeasibleLink();
 		assertFalse(links.contains(linkToVerifyNot));
 	}
+
+	/**
+	 * Test if {@link LinkStorageImpl#getReverseLinks(String)} can correctly return Links connected to specific MAC address.
+	 */
+	@Test
+	public void testGetReverseLinks_ByString() {
+		Link linkToVeryfy = createExistingLink();
+		String dpid = HexString.toHexString(linkToVeryfy.getDst());
+		
+		List<Link> links = linkStorage.getReverseLinks(dpid);
+		assertTrue(links.contains(linkToVeryfy));
+
+		Link linkToVerifyNot = createFeasibleLink();
+		assertFalse(links.contains(linkToVerifyNot));
+	}
 	
 	/**
 	 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
@@ -447,6 +462,35 @@
 	}
 
 	/**
+	 * Class defines a function called back when {@link IPortObject#getReverseLinkedPorts()} is called.
+	 * @author Naoki Shiota
+	 *
+	 */
+	private class GetReverseLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
+		private long dpid;
+		private short port;
+		
+		public GetReverseLinkedPortsCallback(long dpid, short port) {
+			this.dpid = dpid;
+			this.port = port;
+		}
+
+		@Override
+		public Iterable<IPortObject> answer() throws Throwable {
+			List<IPortObject> ports = new ArrayList<IPortObject>();
+
+			for(Link lk : links) {
+				if(lk.getDst() == dpid && lk.getDstPort() == port) {
+					ports.add(createMockPort(lk.getSrc(), lk.getSrcPort()));
+				}
+			}
+
+			return ports;
+		}
+		
+	}
+
+	/**
 	 * Class defines a function called back when {@link LinkStorageImplTest} is called.
 	 * @author Naoki Shiota
 	 *
@@ -567,6 +611,9 @@
 		
 		// Mock getLinkPorts() method
 		EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();
+
+		// Mock getReverseLinkPorts() method
+		EasyMock.expect(mockPort.getReverseLinkedPorts()).andAnswer(new GetReverseLinkedPortsCallback(dpid, number)).anyTimes();
 		
 		// Mock getSwitch() method
 		EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
index be9bca4..d7724ae 100644
--- a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
@@ -163,6 +163,7 @@
 		private ISwitchObject sw;
 		
 		private List<IPortObject> linkedPorts;
+		private List<IPortObject> reverseLinkedPorts;
 		private List<IDeviceObject> devices;
 		private List<IFlowEntry> inflows,outflows;
 		
@@ -180,6 +181,7 @@
 			type = "port";
 
 			linkedPorts = new ArrayList<IPortObject>();
+			reverseLinkedPorts = new ArrayList<IPortObject>();
 			linkedPortsToAdd = new ArrayList<IPortObject>();
 			linkedPortsToRemove = new ArrayList<IPortObject>();
 			devices = new ArrayList<IDeviceObject>();
@@ -290,6 +292,9 @@
 		public Iterable<IPortObject> getLinkedPorts() { return linkedPorts; }
 
 		@Override
+		public Iterable<IPortObject> getReverseLinkedPorts() { return reverseLinkedPorts; }
+
+		@Override
 		public void removeLink(IPortObject dest_port) { linkedPortsToRemove.add(dest_port); }
 
 		@Override