merged
diff --git a/cluster-mgmt/template/onsdemo_edge_template.py b/cluster-mgmt/template/onsdemo_edge_template.py
index e340f38..c3d0287 100755
--- a/cluster-mgmt/template/onsdemo_edge_template.py
+++ b/cluster-mgmt/template/onsdemo_edge_template.py
@@ -65,7 +65,7 @@
             switch.append(sw)
 
         for i in range (NR_NODES):
-            host.append(self.addHost( 'host%d' % (int(i)+1) ))
+            host.append(self.addHost( 'host%d.%d' % (NWID, int(i)+1) ))
 
         for i in range (NR_NODES):
             self.addLink(host[i], switch[i])
@@ -117,7 +117,7 @@
 
     host = []
     for i in range (NR_NODES):
-      host.append(net.get( 'host%d' % (int(i)+1) ))
+      host.append(net.get( 'host%d.%d' % (NWID, (int(i)+1)) ))
 
     net.start()
 
diff --git a/kryo2/pom.xml b/kryo2/pom.xml
index 1beb87d..788f952 100644
--- a/kryo2/pom.xml
+++ b/kryo2/pom.xml
@@ -7,7 +7,7 @@
   <version>2.22</version>
   <packaging>jar</packaging>
 
-  <name>kyro2</name>
+  <name>kryo2</name>
   <url>http://maven.apache.org</url>
 
   <properties>
diff --git a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
index 180cbe9..775f952 100644
--- a/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/datagrid/HazelcastDatagrid.java
@@ -607,6 +607,29 @@
     }
 
     /**
+     * Get a Flow for a given Flow ID.
+     *
+     * @param flowId the Flow ID of the Flow to get.
+     * @return the Flow if found, otherwise null.
+     */
+    @Override
+    public FlowPath getFlow(FlowId flowId) {
+	byte[] valueBytes = mapFlow.get(flowId.value());
+	if (valueBytes == null)
+	    return null;
+
+	Kryo kryo = kryoFactory.newKryo();
+	//
+	// Decode the value
+	//
+	Input input = new Input(valueBytes);
+	FlowPath flowPath = kryo.readObject(input, FlowPath.class);
+	kryoFactory.deleteKryo(kryo);
+
+	return flowPath;
+    }
+
+    /**
      * Send a notification that a Flow is added.
      *
      * @param flowPath the Flow that is added.
@@ -702,6 +725,29 @@
     }
 
     /**
+     * Get a Flow Entry for a given Flow Entry ID.
+     *
+     * @param flowEntryId the Flow Entry ID of the Flow Entry to get.
+     * @return the Flow Entry if found, otherwise null.
+     */
+    @Override
+    public FlowEntry getFlowEntry(FlowEntryId flowEntryId) {
+	byte[] valueBytes = mapFlowEntry.get(flowEntryId.value());
+	if (valueBytes == null)
+	    return null;
+
+	Kryo kryo = kryoFactory.newKryo();
+	//
+	// Decode the value
+	//
+	Input input = new Input(valueBytes);
+	FlowEntry flowEntry = kryo.readObject(input, FlowEntry.class);
+	kryoFactory.deleteKryo(kryo);
+
+	return flowEntry;
+    }
+
+    /**
      * Send a notification that a FlowEntry is added.
      *
      * @param flowEntry the FlowEntry that is added.
diff --git a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
index 9361341..034fe25 100644
--- a/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
+++ b/src/main/java/net/onrc/onos/datagrid/IDatagridService.java
@@ -50,7 +50,7 @@
      * @param arpEventHandler The ARP event handler to de-register.
      */
     public void deregisterArpEventHandler(IArpEventHandler arpEventHandler);
-    
+
     /**
      * Get all Flows that are currently in the datagrid.
      *
@@ -59,6 +59,14 @@
     Collection<FlowPath> getAllFlows();
 
     /**
+     * Get a Flow for a given Flow ID.
+     *
+     * @param flowId the Flow ID of the Flow to get.
+     * @return the Flow if found, otherwise null.
+     */
+    FlowPath getFlow(FlowId flowId);
+
+    /**
      * Send a notification that a Flow is added.
      *
      * @param flowPath the Flow that is added.
@@ -92,6 +100,14 @@
     Collection<FlowEntry> getAllFlowEntries();
 
     /**
+     * Get a Flow Entry for a given Flow Entry ID.
+     *
+     * @param flowEntryId the Flow Entry ID of the Flow Entry to get.
+     * @return the Flow Entry if found, otherwise null.
+     */
+    FlowEntry getFlowEntry(FlowEntryId flowEntryId);
+
+    /**
      * Send a notification that a FlowEntry is added.
      *
      * @param flowEntry the FlowEntry that is added.
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
deleted file mode 100644
index 9865deb..0000000
--- a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
+++ /dev/null
@@ -1,331 +0,0 @@
-package net.onrc.onos.flow;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Vertex;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.onrc.onos.graph.GraphDBOperation;
-import net.onrc.onos.graph.LocalTopologyEventListener;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
-import net.onrc.onos.ofcontroller.util.DataPath;
-import net.onrc.onos.ofcontroller.util.Dpid;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowEntryAction;
-import net.onrc.onos.ofcontroller.util.FlowEntryActions;
-import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-import net.onrc.onos.ofcontroller.util.Port;
-import net.onrc.onos.ofcontroller.util.SwitchPort;
-
-public class FlowManagerImpl implements IFlowManager {
-	
-	protected final static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
-	protected GraphDBOperation op;
-
-	@Override
-	public void createFlow(IPortObject src_port, IPortObject dest_port) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public Iterable<FlowPath> getFlows(IPortObject src_port,
-			IPortObject dest_port) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public Iterable<FlowPath> getOutFlows(IPortObject port) {
-		// TODO Auto-generated method stub
-		List<FlowPath> flowPaths = new ArrayList<FlowPath> ();
-		Iterable<IFlowEntry> flowEntries = port.getOutFlowEntries();
-
-		for(IFlowEntry fe: flowEntries) {
-			IFlowPath flow = fe.getFlow();
-			FlowPath flowPath = new FlowPath(flow);
-			flowPaths.add(flowPath);
-		}
-		return flowPaths;
-	}
-
-	@Override
-	public void reconcileFlows(IPortObject src_port) {
-		// TODO Auto-generated method stub
-
-		log.debug("Reconcile Flows for Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
-		Iterable<IFlowEntry> flowEntries = src_port.getOutFlowEntries();
-
-		for(IFlowEntry fe: flowEntries) {
-			IFlowPath flow = fe.getFlow();
-			reconcileFlow(flow);
-		}
-	}
-
-	private void reconcileFlow(IFlowPath flow) {
-		// TODO Auto-generated method stub
-		String src_dpid = flow.getSrcSwitch();
-		String dst_dpid = flow.getDstSwitch();
-		Short src_port = flow.getSrcPort();
-		Short dst_port = flow.getDstPort();
-		IPortObject src = null;
-		IPortObject dst = null;
-		src = op.searchPort(src_dpid, src_port);
-		dst = op.searchPort(dst_dpid, dst_port);
-		if (src != null && dst != null) {
-			FlowPath newFlow = this.computeFlowPath(src,dst);
-			installFlow(newFlow);
-			removeFlow(flow);
-		}
-		
-	}
-
-	private void removeFlow(IFlowPath flow) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	private void installFlow(FlowPath newFlow) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public void reconcileFlow(IPortObject src_port, IPortObject dest_port) {
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port) {
-		// TODO Auto-generated method stub
-		DataPath dataPath = new DataPath(); 
-		
-		// FIXME: Bad idea to use FloodLight data structures (SwitchPort)
-		
-		dataPath.setSrcPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
-						new Port(src_port.getNumber())));
-		dataPath.setDstPort(new SwitchPort(new Dpid(src_port.getSwitch().getDPID()),
-				new Port(src_port.getNumber())));
-		
-		if (src_port.getSwitch().equals(dest_port.getSwitch())) {
-			// on same switch create quick path
-			FlowEntry flowEntry = new FlowEntry();
-		    flowEntry.setDpid(new Dpid(src_port.getSwitch().getDPID()));
-		    flowEntry.setInPort(new Port(src_port.getNumber()));
-		    flowEntry.setOutPort(new Port(src_port.getNumber()));
-		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
-		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
-
-		    // Set the outgoing port output action
-		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
-		    FlowEntryAction flowEntryAction = new FlowEntryAction();
-		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.addAction(flowEntryAction);
-		    dataPath.flowEntries().add(flowEntry);
-		    
-		    FlowPath flowPath = new FlowPath();
-			flowPath.setDataPath(dataPath);
-
-			return flowPath;
-		}
-		Vertex v_src = src_port.getSwitch().asVertex();	
-		Vertex v_dest = dest_port.getSwitch().asVertex();
-
-		//
-		// Implement the Shortest Path computation by using Breath First Search
-		//
-		Set<Vertex> visitedSet = new HashSet<Vertex>();
-		Queue<Vertex> processingList = new LinkedList<Vertex>();
-		Map<Vertex, Vertex> previousVertexMap = new HashMap<Vertex, Vertex>();
-
-		processingList.add(v_src);
-		visitedSet.add(v_src);
-		Boolean path_found = false;
-		while (! processingList.isEmpty()) {
-		    Vertex nextVertex = processingList.poll();
-		    if (v_dest.equals(nextVertex)) {
-			path_found = true;
-			break;
-		    }
-		    for (Vertex parentPort : nextVertex.getVertices(Direction.OUT, "on")) {
-			for (Vertex childPort : parentPort.getVertices(Direction.OUT, "link")) {
-			    for (Vertex child : childPort.getVertices(Direction.IN, "on")) {
-				// Ignore inactive switches
-				String state = child.getProperty("state").toString();
-				if (! state.equals(SwitchState.ACTIVE.toString()))
-				    continue;
-
-				if (! visitedSet.contains(child)) {
-				    previousVertexMap.put(parentPort, nextVertex);
-				    previousVertexMap.put(childPort, parentPort);
-				    previousVertexMap.put(child, childPort);
-				    visitedSet.add(child);
-				    processingList.add(child);
-				}
-			    }
-			}
-		    }
-		}
-		if (! path_found) {
-		    return null;		// No path found
-		}
-
-		List<Vertex> resultPath = new LinkedList<Vertex>();
-		Vertex previousVertex = v_dest;
-		resultPath.add(v_dest);
-		while (! v_src.equals(previousVertex)) {
-		    Vertex currentVertex = previousVertexMap.get(previousVertex);
-		    resultPath.add(currentVertex);
-		    previousVertex = currentVertex;
-		}
-		Collections.reverse(resultPath);
-		
-		// Loop through the result and prepare the return result
-		// as a list of Flow Entries.
-		//
-		long nodeId = 0;
-		short portId = 0;
-		Port inPort = new Port(src_port.getNumber());
-		Port outPort = new Port();
-		int idx = 0;
-		for (Vertex v: resultPath) {
-		    String type = v.getProperty("type").toString();
-		    // System.out.println("type: " + type);
-		    if (type.equals("port")) {
-			//String number = v.getProperty("number").toString();
-			// System.out.println("number: " + number);
-
-			Object obj = v.getProperty("number");
-			// String class_str = obj.getClass().toString();
-			if (obj instanceof Short) {
-			    portId = (Short)obj;
-			} else if (obj instanceof Integer) {
-			    Integer int_nodeId = (Integer)obj;
-			    portId = int_nodeId.shortValue();
-			    // int int_nodeId = (Integer)obj;
-			    // portId = (short)int_nodeId.;
-			}
-		    } else if (type.equals("switch")) {
-			String dpid = v.getProperty("dpid").toString();
-			nodeId = HexString.toLong(dpid);
-
-			// System.out.println("dpid: " + dpid);
-		    }
-		    idx++;
-		    if (idx == 1) {
-			continue;
-		    }
-		    int mod = idx % 3;
-		    if (mod == 0) {
-			// Setup the incoming port
-			inPort = new Port(portId);
-			continue;
-		    }
-		    if (mod == 2) {
-			// Setup the outgoing port, and add the Flow Entry
-			outPort = new Port(portId);
-
-			FlowEntry flowEntry = new FlowEntry();
-			flowEntry.setDpid(new Dpid(nodeId));
-			flowEntry.setInPort(inPort);
-			flowEntry.setOutPort(outPort);
-			flowEntry.setFlowEntryMatch(new FlowEntryMatch());
-		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
-		    
-		    // Set the outgoing port output action
-		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
-		    FlowEntryAction flowEntryAction = new FlowEntryAction();
-		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.addAction(flowEntryAction);
-		    dataPath.flowEntries().add(flowEntry);
-			continue;
-		    }
-		}
-		if (idx > 0) {
-		    // Add the last Flow Entry
-		    FlowEntry flowEntry = new FlowEntry();
-		    flowEntry.setDpid(new Dpid(nodeId));
-		    flowEntry.setInPort(inPort);
-		    flowEntry.setOutPort(new Port(dest_port.getNumber()));
-		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
-		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
-		    
-		    // Set the outgoing port output action
-		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
-		    FlowEntryAction flowEntryAction = new FlowEntryAction();
-		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.addAction(flowEntryAction);
-		    dataPath.flowEntries().add(flowEntry);
-		    // TODO (BOC): why is this twice?
-		    dataPath.flowEntries().add(flowEntry);
-		}
-
-	
-		if (dataPath.flowEntries().size() > 0) {
-		    FlowPath flowPath = new FlowPath();
-			flowPath.setDataPath(dataPath);
-
-			return flowPath;
-		}
-		return null;		
-		
-	}
-
-	@Override
-	public Iterable<FlowEntry> getFlowEntries(FlowPath flow) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-
-	@Override
-	public boolean installRemoteFlowEntry(FlowPath flowPath,
-					      FlowEntry entry) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean removeRemoteFlowEntry(FlowPath flowPath,
-					     FlowEntry entry) {
-		return false;
-		// TODO Auto-generated method stub
-
-	}
-
-	@Override
-	public boolean installFlowEntry(IOFSwitch mySwitch,
-					FlowPath flowPath,
-					FlowEntry flowEntry) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public boolean removeFlowEntry(IOFSwitch mySwitch,
-				       FlowPath flowPath,
-				       FlowEntry flowEntry) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-	
-
-}
diff --git a/src/main/java/net/onrc/onos/flow/IFlowManager.java b/src/main/java/net/onrc/onos/flow/IFlowManager.java
deleted file mode 100644
index 598da85..0000000
--- a/src/main/java/net/onrc/onos/flow/IFlowManager.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package net.onrc.onos.flow;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.onrc.onos.ofcontroller.util.FlowEntry;
-import net.onrc.onos.ofcontroller.util.FlowPath;
-
-public interface IFlowManager {
-    /**
-     * Create a Flow from port to port.
-     *
-     * TODO: We don't need it for now.
-     *
-     * @param src_port the source port.
-     * @param dest_port the destination port.
-     */
-    public void createFlow(IPortObject src_port, IPortObject dest_port);
-
-    /**
-     * Get all Flows matching a source and a destination port.
-     *
-     * TODO: Pankaj might be implementing it later.
-     *
-     * @param src_port the source port to match.
-     * @param dest_port the destination port to match.
-     * @return all flows matching the source and the destination port.
-     */
-    public Iterable<FlowPath> getFlows(IPortObject src_port,
-				       IPortObject dest_port);
-
-    /**
-     * Get all Flows going out from a port.
-     *
-     * TODO: We need it now: Pankaj
-     *
-     * @param port the port to match.
-     * @return the list of flows that are going out from the port.
-     */
-    public Iterable<FlowPath> getOutFlows(IPortObject port);
-
-    /**
-     * Reconcile all flows on inactive switch port.
-     *
-     * @param portObject the port that has become inactive.
-     */
-    public void reconcileFlows(IPortObject portObject);
-
-    /**
-     * Reconcile all flows between a source and a destination port.
-     *
-     * TODO: We don't need it for now.
-     *
-     * @param src_port the source port.
-     * @param dest_port the destination port.
-     */
-    public void reconcileFlow(IPortObject src_port, IPortObject dest_port);
-
-    /**
-     * Compute the shortest path between a source and a destination ports.
-     *
-     * @param src_port the source port.
-     * @param dest_port the destination port.
-     * @return the computed shortest path between the source and the
-     * destination ports. The flow entries in the path itself would
-     * contain the incoming port matching and the outgoing port output
-     * actions set. However, the path itself will NOT have the Flow ID,
-     * Installer ID, and any additional matching conditions for the
-     * flow entries (e.g., source or destination MAC address, etc).
-     */
-    public FlowPath computeFlowPath(IPortObject src_port,
-				    IPortObject dest_port);
-
-    /**
-     * Get all Flow Entries of a Flow.
-     *
-     * @param flow the flow whose flow entries should be returned.
-     * @return the flow entries of the flow.
-     */
-    public Iterable<FlowEntry> getFlowEntries(FlowPath flow);
-
-    /**
-     * Install a Flow Entry on a switch.
-     *
-     * @param mySwitch the switch to install the Flow Entry into.
-     * @param flowPath the flow path for the flow entry to install.
-     * @param flowEntry the flow entry to install.
-     * @return true on success, otherwise false.
-     */
-    public boolean installFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
-				    FlowEntry flowEntry);
-
-    /**
-     * Remove a Flow Entry from a switch.
-     *
-     * @param mySwitch the switch to remove the Flow Entry from.
-     * @param flowPath the flow path for the flow entry to remove.
-     * @param flowEntry the flow entry to remove.
-     * @return true on success, otherwise false.
-     */
-    public boolean removeFlowEntry(IOFSwitch mySwitch, FlowPath flowPath,
-				   FlowEntry flowEntry);
-
-    /**
-     * Install a Flow Entry on a remote controller.
-     *
-     * TODO: We need it now: Jono
-     * - For now it will make a REST call to the remote controller.
-     * - Internally, it needs to know the name of the remote controller.
-     *
-     * @param flowPath the flow path for the flow entry to install.
-     * @param flowEntry the flow entry to install.
-     * @return true on success, otherwise false.
-     */
-    public boolean installRemoteFlowEntry(FlowPath flowPath,
-					  FlowEntry flowEntry);
-
-    /**
-     * Remove a flow entry on a remote controller.
-     *
-     * @param flowPath the flow path for the flow entry to remove.
-     * @param flowEntry the flow entry to remove.
-     * @return true on success, otherwise false.
-     */
-    public boolean removeRemoteFlowEntry(FlowPath flowPath,
-					 FlowEntry flowEntry);
-}
diff --git a/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java b/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
index 6b955b6..8544486 100644
--- a/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
+++ b/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
@@ -1,9 +1,5 @@
 package net.onrc.onos.graph;
 
-import java.util.Map;
-
-import net.onrc.onos.flow.FlowManagerImpl;
-import net.onrc.onos.flow.IFlowManager;
 import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
 
 import org.slf4j.Logger;
@@ -54,9 +50,12 @@
 																src_port.getNumber(),
 																dest_port.getSwitch().getDPID(),
 																dest_port.getNumber()});
-			IFlowManager manager = new FlowManagerImpl();
 			// TODO: Find the flows and add to reconcile queue
-			manager.reconcileFlows(src_port);
+			//
+			// NOTE: Old code/logic.
+			//
+			// IFlowService flowManager = ...
+			// flowManager.reconcileFlows(src_port);
 		}
 	}
 
@@ -83,8 +82,11 @@
 			
 			IPortObject src_port = conn.getFramedGraph().frame(vertex, IPortObject.class);
 			log.debug("TopologyEvents: Port removed: {}:{}",src_port.getSwitch().getDPID(),src_port.getNumber());
-			IFlowManager manager = new FlowManagerImpl();
-			manager.reconcileFlows(src_port);			
+
+			// NOTE: Old code/logic.
+			//
+			// IFlowService flowManager = ...
+			// flowManager.reconcileFlows(src_port);
 		}
 	}
 
@@ -103,6 +105,4 @@
 		
 	}
 
-
-
 }
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 0e9887a..eccf40b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowEventHandler.java
@@ -171,18 +171,28 @@
 		//  - EventEntry<FlowEntry>
 		//
 		for (EventEntry<?> event : collection) {
+		    // Topology event
 		    if (event.eventData() instanceof TopologyElement) {
 			EventEntry<TopologyElement> topologyEventEntry =
 			    (EventEntry<TopologyElement>)event;
 			topologyEvents.add(topologyEventEntry);
-		    } else if (event.eventData() instanceof FlowPath) {
+			continue;
+		    }
+
+		    // FlowPath event
+		    if (event.eventData() instanceof FlowPath) {
 			EventEntry<FlowPath> flowPathEventEntry =
 			    (EventEntry<FlowPath>)event;
 			flowPathEvents.add(flowPathEventEntry);
-		    } else if (event.eventData() instanceof FlowEntry) {
+			continue;
+		    }
+
+		    // FlowEntry event
+		    if (event.eventData() instanceof FlowEntry) {
 			EventEntry<FlowEntry> flowEntryEventEntry =
 			    (EventEntry<FlowEntry>)event;
 			flowEntryEvents.add(flowEntryEventEntry);
+			continue;
 		    }
 		}
 		collection.clear();
@@ -710,9 +720,18 @@
 	    //
 	    newFlowEntry.setFlowId(new FlowId(flowPath.flowId().value()));
 
-	    // Set the incoming port matching
-	    FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
+	    //
+	    // Allocate the FlowEntryMatch by copying the default one
+	    // from the FlowPath (if set).
+	    //
+	    FlowEntryMatch flowEntryMatch = null;
+	    if (flowPath.flowEntryMatch() != null)
+		flowEntryMatch = new FlowEntryMatch(flowPath.flowEntryMatch());
+	    else
+		flowEntryMatch = new FlowEntryMatch();
 	    newFlowEntry.setFlowEntryMatch(flowEntryMatch);
+
+	    // Set the incoming port matching
 	    flowEntryMatch.enableInPort(newFlowEntry.inPort());
 
 	    //
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 8414e68..f82a06d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -40,7 +40,7 @@
  */
 public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
     // flag to use FlowPusher instead of FlowSwitchOperation/MessageDamper
-    private final static boolean enableFlowPusher = false;
+    private final static boolean enableFlowPusher = true;
 
     protected GraphDBOperation dbHandlerApi;
     protected GraphDBOperation dbHandlerInner;
@@ -451,9 +451,10 @@
     /**
      * Inform the Flow Manager that a Flow Entry on switch expired.
      *
+     * @param sw the switch the Flow Entry expired on.
      * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
      */
-    public void flowEntryOnSwitchExpired(FlowEntryId flowEntryId) {
+    public void flowEntryOnSwitchExpired(IOFSwitch sw, FlowEntryId flowEntryId) {
 	// TODO: Not implemented yet
     }
 
@@ -517,6 +518,9 @@
 	for (FlowPathEntryPair flowPair : modifiedFlowEntries) {
 	    FlowEntry flowEntry = flowPair.flowEntry;
 
+	    if (! flowEntry.isValidFlowEntryId())
+		continue;
+
 	    IOFSwitch mySwitch = mySwitches.get(flowEntry.dpid().value());
 
 	    //
@@ -535,8 +539,6 @@
 		    FlowEntryUserState.FE_USER_DELETE) {
 		    continue;
 		}
-		if (! flowEntry.isValidFlowEntryId())
-		    continue;
 	    }
 
 	    log.debug("Pushing Flow Entry To Datagrid: {}", flowEntry.toString());
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 ed7f7bd..8d2b797 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
@@ -2,6 +2,7 @@
 
 import java.util.ArrayList;
 
+import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.onrc.onos.ofcontroller.topology.Topology;
 import net.onrc.onos.ofcontroller.util.CallerId;
@@ -117,7 +118,8 @@
     /**
      * Inform the Flow Manager that a Flow Entry on switch expired.
      *
+     * @param sw the switch the Flow Entry expired on.
      * @param flowEntryId the Flow Entry ID of the expired Flow Entry.
      */
-    public void flowEntryOnSwitchExpired(FlowEntryId flowEntryId);
+    public void flowEntryOnSwitchExpired(IOFSwitch sw, FlowEntryId flowEntryId);
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowProgrammer.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowProgrammer.java
index 33c9a6a..461d231 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowProgrammer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowProgrammer.java
@@ -20,6 +20,10 @@
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.ofcontroller.flowprogrammer.web.FlowProgrammerWebRoutable;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 
 /**
@@ -44,6 +48,8 @@
     protected static Logger log = LoggerFactory.getLogger(FlowProgrammer.class);
     protected volatile IFloodlightProviderService floodlightProvider;
     protected volatile IControllerRegistryService registryService;
+    protected volatile IRestApiService restApi;
+    protected volatile IFlowService flowManager;
 
     protected FlowPusher pusher;
     private static final int NUM_PUSHER_THREAD = 1;
@@ -62,6 +68,8 @@
 	    throws FloodlightModuleException {
 	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
 	registryService = context.getServiceImpl(IControllerRegistryService.class);
+	restApi = context.getServiceImpl(IRestApiService.class);
+	flowManager = context.getServiceImpl(IFlowService.class);
 	pusher.init(null, context, floodlightProvider.getOFMessageFactory(), null);
 	if (enableFlowSync) {
 	    synchronizer.init(pusher);
@@ -70,6 +78,7 @@
 
     @Override
     public void startUp(FloodlightModuleContext context) {
+    restApi.addRestletRoutable(new FlowProgrammerWebRoutable());
 	pusher.start();
 	floodlightProvider.addOFMessageListener(OFType.FLOW_REMOVED, this);
 	floodlightProvider.addOFSwitchListener(this);
@@ -104,6 +113,7 @@
 	Collection<Class<? extends IFloodlightService>> l =
 		new ArrayList<Class<? extends IFloodlightService>>();
 	l.add(IFloodlightProviderService.class);
+	l.add(IRestApiService.class);
 	return l;
     }
 
@@ -131,6 +141,8 @@
 	case FLOW_REMOVED:
 	    OFFlowRemoved flowMsg = (OFFlowRemoved) msg;
 	    log.debug("Got flow removed from "+ sw.getId() +": "+ flowMsg.getCookie());
+	    FlowEntryId id = new FlowEntryId(flowMsg.getCookie());
+	    flowManager.flowEntryOnSwitchExpired(sw, id);
 	    break;
 	default:
 	    break;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
index 6f85c5d..8f2469b 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowPusher.java
@@ -5,6 +5,7 @@
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -146,6 +147,7 @@
 		private Map<IOFSwitch,SwitchQueue> queues
 			= new HashMap<IOFSwitch,SwitchQueue>();
 		
+		// reusable latch used for waiting for arrival of message
 		private Semaphore mutex = new Semaphore(0);
 		
 		@Override
@@ -160,14 +162,16 @@
 					return;
 				}
 				
-				Set< Map.Entry<IOFSwitch,SwitchQueue> > entries;
+				// for safety of concurrent access, copy all key objects
+				Set<IOFSwitch> keys = new HashSet<IOFSwitch>(queues.size());
 				synchronized (queues) {
-					entries = queues.entrySet();
+					for (IOFSwitch sw : queues.keySet()) {
+						keys.add(sw);
+					}
 				}
 				
-				for (Map.Entry<IOFSwitch,SwitchQueue> entry : entries) {
-					IOFSwitch sw = entry.getKey();
-					SwitchQueue queue = entry.getValue();
+				for (IOFSwitch sw : keys) {
+					SwitchQueue queue = queues.get(sw);
 
 					// Skip if queue is suspended
 					if (sw == null || queue == null ||
@@ -175,48 +179,62 @@
 						continue;
 					}
 					
-					// check sending rate and determine it to be sent or not
-					long current_time = System.currentTimeMillis();
-					long size = 0;
-					
 					synchronized (queue) {
-						if (queue.isSendable(current_time)) {
-							int i = 0;
-							while (! queue.isEmpty()) {
-								// Number of messages excess the limit
-								if (i >= MAX_MESSAGE_SEND) {
-									// Messages remains in queue
-									mutex.release();
-									break;
-								}
-								++i;
-								
-								OFMessage msg = queue.poll();
-								try {
-									messageDamper.write(sw, msg, context);
-									log.debug("Pusher sends message : {}", msg);
-									size += msg.getLength();
-								} catch (IOException e) {
-									e.printStackTrace();
-									log.error("Exception in sending message ({}) : {}", msg, e);
+						processQueue(sw, queue, MAX_MESSAGE_SEND);
+						if (queue.isEmpty()) {
+							// remove queue if flagged to be.
+							if (queue.toBeDeleted) {
+								synchronized (queues) {
+									queues.remove(sw);
 								}
 							}
-							sw.flush();
-							queue.logSentData(current_time, size);
-							
-							if (queue.isEmpty()) {
-								// remove queue if flagged to be.
-								if (queue.toBeDeleted) {
-									synchronized (queues) {
-										queues.remove(sw);
-									}
-								}
+						} else {
+							// if some messages remains in queue, latch down
+							if (mutex.availablePermits() == 0) {
+								mutex.release();
 							}
 						}
 					}
 				}
 			}
 		}
+		
+		/**
+		 * Read messages from queue and send them to the switch.
+		 * If number of messages excess the limit, stop sending messages.
+		 * @param sw Switch to which messages will be sent.
+		 * @param queue Queue of messages.
+		 * @param max_msg Limitation of number of messages to be sent. If set to 0,
+		 *                all messages in queue will be sent.
+		 */
+		private void processQueue(IOFSwitch sw, SwitchQueue queue, long max_msg) {
+			// check sending rate and determine it to be sent or not
+			long current_time = System.currentTimeMillis();
+			long size = 0;
+			
+			if (queue.isSendable(current_time)) {
+				int i = 0;
+				while (! queue.isEmpty()) {
+					// Number of messages excess the limit
+					if (0 < max_msg && max_msg <= i) {
+						break;
+					}
+					++i;
+					
+					OFMessage msg = queue.poll();
+					try {
+						messageDamper.write(sw, msg, context);
+						log.debug("Pusher sends message : {}", msg);
+						size += msg.getLength();
+					} catch (IOException e) {
+						e.printStackTrace();
+						log.error("Exception in sending message ({}) : {}", msg, e);
+					}
+				}
+				sw.flush();
+				queue.logSentData(current_time, size);
+			}
+		}
 	}
 	
 	/**
@@ -348,6 +366,7 @@
 		}
 		
 		if (rate > 0) {
+			log.debug("rate for {} is set to {}", sw.getId(), rate);
 			queue.max_rate = rate;
 		}
 	}
@@ -362,7 +381,7 @@
 		FlowPusherThread proc = getProcess(sw);
 		queue = new SwitchQueue();
 		queue.state = QueueState.READY;
-		synchronized (proc) {
+		synchronized (proc.queues) {
 			proc.queues.put(sw, queue);
 		}
 		
@@ -759,7 +778,6 @@
 		//
 		OFMatch match = new OFMatch();
 		match.setWildcards(OFMatch.OFPFW_ALL);
-		FlowEntryMatch flowPathMatch = flowPath.flowEntryMatch();
 		FlowEntryMatch flowEntryMatch = flowEntry.flowEntryMatch();
 
 		// Match the Incoming Port
@@ -771,9 +789,6 @@
 
 		// Match the Source MAC address
 		MACAddress matchSrcMac = flowEntryMatch.srcMac();
-		if ((matchSrcMac == null) && (flowPathMatch != null)) {
-			matchSrcMac = flowPathMatch.srcMac();
-		}
 		if (matchSrcMac != null) {
 			match.setDataLayerSource(matchSrcMac.toString());
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
@@ -781,9 +796,6 @@
 
 		// Match the Destination MAC address
 		MACAddress matchDstMac = flowEntryMatch.dstMac();
-		if ((matchDstMac == null) && (flowPathMatch != null)) {
-			matchDstMac = flowPathMatch.dstMac();
-		}
 		if (matchDstMac != null) {
 			match.setDataLayerDestination(matchDstMac.toString());
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
@@ -791,9 +803,6 @@
 
 		// Match the Ethernet Frame Type
 		Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
-		if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
-			matchEthernetFrameType = flowPathMatch.ethernetFrameType();
-		}
 		if (matchEthernetFrameType != null) {
 			match.setDataLayerType(matchEthernetFrameType);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
@@ -801,9 +810,6 @@
 
 		// Match the VLAN ID
 		Short matchVlanId = flowEntryMatch.vlanId();
-		if ((matchVlanId == null) && (flowPathMatch != null)) {
-			matchVlanId = flowPathMatch.vlanId();
-		}
 		if (matchVlanId != null) {
 			match.setDataLayerVirtualLan(matchVlanId);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
@@ -811,9 +817,6 @@
 
 		// Match the VLAN priority
 		Byte matchVlanPriority = flowEntryMatch.vlanPriority();
-		if ((matchVlanPriority == null) && (flowPathMatch != null)) {
-			matchVlanPriority = flowPathMatch.vlanPriority();
-		}
 		if (matchVlanPriority != null) {
 			match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
 			match.setWildcards(match.getWildcards()
@@ -822,27 +825,18 @@
 
 		// Match the Source IPv4 Network prefix
 		IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
-		if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
-			matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
-		}
 		if (matchSrcIPv4Net != null) {
 			match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
 		}
 
 		// Natch the Destination IPv4 Network prefix
 		IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
-		if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
-			matchDstIPv4Net = flowPathMatch.dstIPv4Net();
-		}
 		if (matchDstIPv4Net != null) {
 			match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
 		}
 
 		// Match the IP protocol
 		Byte matchIpProto = flowEntryMatch.ipProto();
-		if ((matchIpProto == null) && (flowPathMatch != null)) {
-			matchIpProto = flowPathMatch.ipProto();
-		}
 		if (matchIpProto != null) {
 			match.setNetworkProtocol(matchIpProto);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
@@ -850,9 +844,6 @@
 
 		// Match the IP ToS (DSCP field, 6 bits)
 		Byte matchIpToS = flowEntryMatch.ipToS();
-		if ((matchIpToS == null) && (flowPathMatch != null)) {
-			matchIpToS = flowPathMatch.ipToS();
-		}
 		if (matchIpToS != null) {
 			match.setNetworkTypeOfService(matchIpToS);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
@@ -860,9 +851,6 @@
 
 		// Match the Source TCP/UDP port
 		Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
-		if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
-			matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
-		}
 		if (matchSrcTcpUdpPort != null) {
 			match.setTransportSource(matchSrcTcpUdpPort);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
@@ -870,9 +858,6 @@
 
 		// Match the Destination TCP/UDP port
 		Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
-		if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
-			matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
-		}
 		if (matchDstTcpUdpPort != null) {
 			match.setTransportDestination(matchDstTcpUdpPort);
 			match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
@@ -1068,11 +1053,8 @@
 		
 		OFBarrierRequest msg = (OFBarrierRequest) factory.getMessage(OFType.BARRIER_REQUEST);
 		msg.setXid(sw.getNextTransactionId());
-		add(sw, msg);
 
-		// TODO create Future object of message
 		OFBarrierReplyFuture future = new OFBarrierReplyFuture(threadPool, sw, msg.getXid());
-
 		synchronized (barrierFutures) {
 			Map<Integer,OFBarrierReplyFuture> map = barrierFutures.get(sw.getId());
 			if (map == null) {
@@ -1082,6 +1064,8 @@
 			map.put(msg.getXid(), future);
 		}
 		
+		add(sw, msg);
+		
 		return future;
 	}
 
@@ -1139,11 +1123,13 @@
 	public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
 		Map<Integer,OFBarrierReplyFuture> map = barrierFutures.get(sw.getId());
 		if (map == null) {
+			log.debug("null map for {} : {}", sw.getId(), barrierFutures);
 			return Command.CONTINUE;
 		}
 		
 		OFBarrierReplyFuture future = map.get(msg.getXid());
 		if (future == null) {
+			log.debug("null future for {} : {}", msg.getXid(), map);
 			return Command.CONTINUE;
 		}
 		
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
index 0d6b0e8..b3c8e84 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/FlowSynchronizer.java
@@ -30,9 +30,9 @@
 
 /**
  * FlowSynchronizer is an implementation of FlowSyncService.
- * In addition to IFlowSyncService, FlowSynchronizer periodically reads flow tables from
- * switches and compare them with GraphDB to drop unnecessary flows and/or to install
- * missing flows.
+ * In addition to IFlowSyncService, FlowSynchronizer periodically reads flow
+ * tables from switches and compare them with GraphDB to drop unnecessary
+ * flows and/or to install missing flows.
  * @author Brian
  *
  */
@@ -99,7 +99,8 @@
 	}
 
 	/**
-	 * Compare flows entries in GraphDB and switch to pick up necessary messages.
+	 * Compare flows entries in GraphDB and switch to pick up necessary
+	 * messages.
 	 * After picking up, picked messages are added to FlowPusher.
 	 * @param graphEntries Flow entries in GraphDB.
 	 * @param switchEntries Flow entries in switch.
@@ -191,24 +192,22 @@
     }
 
     /**
-     * FlowEntryWrapper represents abstract FlowEntry which is embodied by IFlowEntry
-     * (from GraphDB) or OFFlowStatisticsReply (from switch).
+     * FlowEntryWrapper represents abstract FlowEntry which is embodied
+     * by FlowEntryId (from GraphDB) or OFFlowStatisticsReply (from switch).
      * @author Brian
      *
      */
     class FlowEntryWrapper {
-	FlowEntryId id;
-	IFlowEntry iflowEntry;
+	FlowEntryId flowEntryId;
 	OFFlowStatisticsReply statisticsReply;
 
 	public FlowEntryWrapper(IFlowEntry entry) {
-	    iflowEntry = entry;
-	    id = new FlowEntryId(entry.getFlowEntryId());
+	    flowEntryId = new FlowEntryId(entry.getFlowEntryId());
 	}
 
 	public FlowEntryWrapper(OFFlowStatisticsReply entry) {
+	    flowEntryId = new FlowEntryId(entry.getCookie());
 	    statisticsReply = entry;
-	    id = new FlowEntryId(entry.getCookie());
 	}
 
 	/**
@@ -216,36 +215,51 @@
 	 * @param sw Switch to which flow will be installed.
 	 */
 	public void addToSwitch(IOFSwitch sw) {
-	    if(iflowEntry != null) {
-		pusher.add(sw, iflowEntry.getFlow(), iflowEntry);
-	    }
-	    else if(statisticsReply != null) {
-		log.error("Adding existing flow entry {} to sw {}", 
+	    if (statisticsReply != null) {
+		log.error("Error adding existing flow entry {} to sw {}", 
 			  statisticsReply.getCookie(), sw.getId());
+		return;
 	    }
+
+	    // Get the Flow Entry state from the Network Graph
+	    IFlowEntry iFlowEntry = null;
+	    try {
+		iFlowEntry = dbHandler.searchFlowEntry(flowEntryId);
+	    } catch (Exception e) {
+		log.error("Error finding flow entry {} in Network Graph",
+			  flowEntryId);
+		return;
+	    }
+	    if (iFlowEntry == null) {
+		log.error("Cannot add flow entry {} to sw {} : flow entry not found",
+			  flowEntryId, sw.getId());
+		return;
+	    }
+
+	    pusher.add(sw, iFlowEntry.getFlow(), iFlowEntry);
 	}
 	
 	/**
 	 * Remove this FlowEntry from a switch via FlowPusher.
 	 * @param sw Switch from which flow will be removed.
 	 */
-	public void removeFromSwitch(IOFSwitch sw){
-	    if(iflowEntry != null) {
-		log.error("Removing non-existent flow entry {} from sw {}", 
-			  iflowEntry.getFlowEntryId(), sw.getId());
+	public void removeFromSwitch(IOFSwitch sw) {
+	    if (statisticsReply == null) {
+		log.error("Error removing non-existent flow entry {} from sw {}", 
+			  flowEntryId, sw.getId());
+		return;
+	    }
 
-	    }
-	    else if(statisticsReply != null) {
-		// Convert Statistics Reply to Flow Mod, then write it
-		OFFlowMod fm = new OFFlowMod();
-		fm.setCookie(statisticsReply.getCookie());
-		fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
-		fm.setLengthU(OFFlowMod.MINIMUM_LENGTH);
-		fm.setMatch(statisticsReply.getMatch());
-		fm.setPriority(statisticsReply.getPriority());
-		fm.setOutPort(OFPort.OFPP_NONE);
-		pusher.add(sw, fm);
-	    }
+	    // Convert Statistics Reply to Flow Mod, then write it
+	    OFFlowMod fm = new OFFlowMod();
+	    fm.setCookie(statisticsReply.getCookie());
+	    fm.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
+	    fm.setLengthU(OFFlowMod.MINIMUM_LENGTH);
+	    fm.setMatch(statisticsReply.getMatch());
+	    fm.setPriority(statisticsReply.getPriority());
+	    fm.setOutPort(OFPort.OFPP_NONE);
+
+	    pusher.add(sw, fm);
 	}
 
 	/**
@@ -253,7 +267,7 @@
 	 */
 	@Override
 	public int hashCode() {
-	    return id.hashCode();
+	    return flowEntryId.hashCode();
 	}
 
 	/**
@@ -268,18 +282,14 @@
 	    if(obj.getClass() == this.getClass()) {
 		FlowEntryWrapper entry = (FlowEntryWrapper) obj;
 		// TODO: we need to actually compare the match + actions
-		return this.id.equals(entry.id);
+		return this.flowEntryId.equals(entry.flowEntryId);
 	    }
 	    return false;
 	}
 
 	@Override
 	public String toString() {
-	    return id.toString();
+	    return flowEntryId.toString();
 	}
     }
-
-
 }
-
-
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
new file mode 100644
index 0000000..21e5bfb
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
@@ -0,0 +1,26 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+public class FlowProgrammerWebRoutable implements RestletRoutable {
+
+	@Override
+	public Restlet getRestlet(Context context) {
+		Router router = new Router(context);
+		router.attach("/setrate/{dpid}/{rate}/json", SetPushRateResource.class);
+		router.attach("/suspend/{dpid}/json", SuspendPusherResource.class);
+		router.attach("/resume/{dpid}/json", ResumePusherResource.class);
+		router.attach("/barrier/{dpid}/json", SendBarrierResource.class);
+		return router;
+	}
+
+	@Override
+	public String basePath() {
+		return "/wm/fprog";
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/PusherResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/PusherResource.java
new file mode 100644
index 0000000..4e1c0fc
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/PusherResource.java
@@ -0,0 +1,33 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowPusherService;
+
+public class PusherResource extends ServerResource {
+    protected final static Logger log = LoggerFactory.getLogger(PusherResource.class);
+
+    protected IFloodlightProviderService provider;
+	protected IFlowPusherService pusher;
+	
+	protected boolean init() {
+    	provider = (IFloodlightProviderService)
+    			getContext().getAttributes().
+    			get(IFloodlightProviderService.class.getCanonicalName());
+    	if (provider == null) {
+		    log.debug("ONOS FloodlightProvider not found");
+		    return false;
+		}
+    	
+    	pusher = (IFlowPusherService)getContext().getAttributes().
+    			get(IFlowPusherService.class.getCanonicalName());
+    	if (pusher == null) {
+		    log.debug("ONOS FlowPusherService not found");
+		    return false;
+		}
+    	return true;
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/ResumePusherResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/ResumePusherResource.java
new file mode 100644
index 0000000..ca1ec00
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/ResumePusherResource.java
@@ -0,0 +1,41 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Resume sending message to switch.
+ *
+ *   GET /wm/fprog/resume/{dpid}/json"
+ */
+public class ResumePusherResource extends PusherResource {
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public boolean retrieve() {
+    	if (! init()) {
+    		return false;
+    	}
+    	
+    	long dpid;
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return false;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return false;
+    	}
+    	
+    	return pusher.resume(sw);
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SendBarrierResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SendBarrierResource.java
new file mode 100644
index 0000000..9c348ff
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SendBarrierResource.java
@@ -0,0 +1,41 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.protocol.OFBarrierReply;
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Send barrier message to switch.
+ *
+ *   GET /wm/fprog/barrier/{dpid}/json"
+ */
+public class SendBarrierResource extends PusherResource {
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public OFBarrierReply retrieve() {
+    	if (! init()) {
+    		return null;
+    	}
+    	long dpid;
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return null;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return null;
+    	}
+    	
+    	return pusher.barrier(sw);
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SetPushRateResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SetPushRateResource.java
new file mode 100644
index 0000000..08a728e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SetPushRateResource.java
@@ -0,0 +1,47 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Set sending rate to the switch.
+ *
+ *   GET /wm/fprog/setrate/{dpid}/{rate}/json"
+ */
+public class SetPushRateResource extends PusherResource {
+
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public boolean retrieve() {
+    	if (! init()) {
+    		return false;
+    	}
+    	
+    	long dpid;
+    	long rate;
+    	
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+        	rate = Long.valueOf((String)getRequestAttributes().get("rate"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return false;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return false;
+    	}
+    	
+    	pusher.setRate(sw, rate);
+    	
+    	return true;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SuspendPusherResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SuspendPusherResource.java
new file mode 100644
index 0000000..39d245b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SuspendPusherResource.java
@@ -0,0 +1,46 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FlowProgrammer REST API implementation: Suspend sending message to switch.
+ *
+ *   GET /wm/fprog/suspend/{dpid}/json"
+ */
+public class SuspendPusherResource extends PusherResource {
+
+    protected final static Logger log = LoggerFactory.getLogger(SetPushRateResource.class);
+
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public boolean retrieve() {
+    	if (! init()) {
+    		return false;
+    	}
+    	
+    	long dpid;
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return false;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return false;
+    	}
+    	
+    	return pusher.suspend(sw);
+    }
+}
diff --git a/web/ons-demo/js/app.js b/web/ons-demo/js/app.js
index 94c41e2..d869de7 100644
--- a/web/ons-demo/js/app.js
+++ b/web/ons-demo/js/app.js
@@ -1,6 +1,17 @@
 /*global d3, document∆*/
 
 
+function updateFlow(model) {
+    model.flows.forEach(function (flow) {
+	flow.flowId = flow.flowId.value;
+	flow.installerId = flow.installerId.value;
+	flow.dstDpid = flow.dataPath.dstPort.dpid.value;
+	flow.srcDpid = flow.dataPath.srcPort.dpid.value;
+	flow.dstPort = flow.dataPath.dstPort.port.value;
+	flow.srcPort = flow.dataPath.srcPort.port.value;
+    });
+}
+
 function sync() {
 	var d = Date.now();
 
@@ -8,6 +19,7 @@
 //		console.log('Update time: ' + (Date.now() - d)/1000 + 's');
 
 		if (newModel) {
+			updateFlow(newModel);
 			var modelChanged = false;
 			var newModelString = JSON.stringify(newModel);
 			if (!modelString || newModelString != modelString) {
diff --git a/web/pusher.py b/web/pusher.py
new file mode 100755
index 0000000..f53e3ea
--- /dev/null
+++ b/web/pusher.py
@@ -0,0 +1,145 @@
+#! /usr/bin/env python
+
+
+import pprint
+import os
+import sys
+import subprocess
+import json
+import argparse
+import io
+import time
+
+from flask import Flask, json, Response, render_template, make_response, request
+
+## Global Var ##
+ControllerIP="127.0.0.1"
+ControllerPort=8080
+
+DEBUG=0
+pp = pprint.PrettyPrinter(indent=4)
+
+app = Flask(__name__)
+
+## Worker Functions ##
+def log_error(txt):
+  print '%s' % (txt)
+
+def debug(txt):
+  if DEBUG:
+    print '%s' % (txt)
+
+# @app.route("/wm/fprog/setrate/<dpid>/<rate>/json")
+# Sample output:
+#  "true"
+
+
+def set_rate(dpid,rate):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/setrate/%s/%s/json\"" % (ControllerIP, ControllerPort, dpid, rate)
+    debug("set_rate %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to set rate"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "Sending rate to %s is successfully set to %s" % (dpid, rate)
+
+def suspend(dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/suspend/%s/json\"" % (ControllerIP, ControllerPort, dpid)
+    debug("suspend %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to suspend"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "DPID %s is successfully suspended" % dpid
+
+def resume(dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/resume/%s/json\"" % (ControllerIP, ControllerPort, dpid)
+    debug("resume %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to resume"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "DPID %s is successfully resumed" % dpid
+
+def barrier(dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/barrier/%s/json\"" % (ControllerIP, ControllerPort, dpid)
+    debug("barrier %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to send barrier"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "Barrier reply from %s : %s" % (dpid, result)
+
+
+if __name__ == "__main__":
+  usage_msg1 = "Usage:\n"
+  usage_msg2 = "%s rate <dpid> <rate> : Set sending rate[bytes/ms] to the switch\n" % (sys.argv[0])
+  usage_msg3 = "                   suspend <dpid>    : Suspend sending message to the switch\n"
+  usage_msg4 = "                   resume <dpid>     : Resume sending message to the switch\n"
+  usage_msg5 = "                   barrier <dpid>    : Send barrier message to the switch\n"
+  usage_msg = usage_msg1 + usage_msg2 + usage_msg3 + usage_msg4 + usage_msg5;
+
+  app.debug = True;
+
+  # Usage info
+  if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
+    print(usage_msg)
+    exit(0)
+
+  # Check arguments
+  if len(sys.argv) < 2:
+    log_error(usage_msg)
+    exit(1)
+
+  # Do the work
+  if sys.argv[1] == "rate":
+    if len(sys.argv) < 4:
+      log_error(usage_msg)
+      exit(1)
+    set_rate(sys.argv[2], sys.argv[3])
+  elif sys.argv[1] == "suspend":
+    if len(sys.argv) < 3:
+      log_error(usage_msg)
+      exit(1)
+    suspend(sys.argv[2])
+  elif sys.argv[1] == "resume":
+    if len(sys.argv) < 3:
+      log_error(usage_msg)
+      exit(1)
+    resume(sys.argv[2])
+  elif sys.argv[1] == "barrier":
+    if len(sys.argv) < 3:
+      log_error(usage_msg)
+      exit(1)
+    barrier(sys.argv[2])
+  else:
+    log_error(usage_msg)
+    exit(1)
diff --git a/web/topology_rest.py b/web/topology_rest.py
index bac3113..b3a415e 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -720,8 +720,8 @@
 #    print "Debug: Controller command %s called %s" % (cmd, controller_name)
   else:
     # No longer use -i to specify keys (use .ssh/config to specify it)
-    start_onos="ssh %s ONOS/start-onos.sh start" % (controller_name)
-    stop_onos="ssh %s ONOS/start-onos.sh stop" % (controller_name)
+    start_onos="ssh %s \"cd ONOS; ./start-onos.sh start\"" % (controller_name)
+    stop_onos="ssh %s \"cd ONOS; ./start-onos.sh stop\"" % (controller_name)
 #    start_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh start" % (controller_name)
 #    stop_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh stop" % (controller_name)
 
@@ -960,7 +960,7 @@
   parsedResult = json.loads(result)
   if len(parsedResult) > 0:
     if parsedResult[-1].has_key('flowId'):
-      flow_nr = int(parsedResult[-1]['flowId'], 16)
+      flow_nr = int(parsedResult[-1]['flowId']['value'], 16)
   else:
     flow_nr = -1  # first flow
     print "first flow"