Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/scripts/switch.sh b/scripts/switch.sh
new file mode 100755
index 0000000..eba0f34
--- /dev/null
+++ b/scripts/switch.sh
@@ -0,0 +1,29 @@
+#! /bin/bash
+controller=`hostname`
+switches=`ifconfig -a | grep sw |grep -v eth | awk '{print $1}'`
+
+function host2ip (){
+   ip=`grep $1 /etc/hosts |grep -v "ip6"|  awk '{print $1}'`
+   echo $ip
+}
+
+url=""
+for c in $controller; do
+  url="$url tcp:`host2ip $c`:6633"
+done
+
+for s in $switches; do
+    dpid=`sudo ovs-ofctl  show  $s |grep dpid | awk '{split($4,x,":"); print x[2]}'`
+    if [  "x$dpid" == "x$1" ]; then
+        if [ x$2 == "xup" ]; then
+           sudo ovs-vsctl set-controller $s $url 
+           echo "$s up"
+        elif [ x$2 == "xdown" ]; then
+           sudo ovs-vsctl set-controller $s
+           echo "$s down"
+        else
+           echo -n "$s controller: "
+           sudo ovs-vsctl get-controller $s
+        fi
+    fi
+done
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 2528ddd..405af1a 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -5,6 +5,7 @@
 import java.util.Collection;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -255,44 +256,54 @@
 
     final Runnable mapReader = new Runnable() {
 	    public void run() {
-		// log.debug("Reading Flow Entries from the Network Map...");
 		if (floodlightProvider == null) {
 		    log.debug("FloodlightProvider service not found!");
 		    return;
 		}
 
-		Map<Long, IOFSwitch> mySwitches = floodlightProvider.getSwitches();
-
-		Map<Long, IFlowEntry> myFlowEntries = new TreeMap<Long, IFlowEntry>();
+		Map<Long, IOFSwitch> mySwitches =
+		    floodlightProvider.getSwitches();
+		Map<Long, IFlowEntry> myFlowEntries =
+		    new TreeMap<Long, IFlowEntry>();
+		LinkedList<IFlowEntry> deleteFlowEntries =
+		    new LinkedList<IFlowEntry>();
 
 		//
 		// Fetch all Flow Entries and select only my Flow Entries
+		// that need to be undated into the switches.
 		//
-		Iterable<IFlowEntry> allFlowEntries = conn.utils().getAllFlowEntries(conn);
+		Iterable<IFlowEntry> allFlowEntries =
+		    conn.utils().getAllFlowEntries(conn);
 		for (IFlowEntry flowEntryObj : allFlowEntries) {
-		    FlowEntryId flowEntryId =
-			new FlowEntryId(flowEntryObj.getFlowEntryId());
+		    String flowEntryIdStr = flowEntryObj.getFlowEntryId();
 		    String userState = flowEntryObj.getUserState();
 		    String switchState = flowEntryObj.getSwitchState();
+		    String dpidStr = flowEntryObj.getSwitchDpid();
+		    if ((flowEntryIdStr == null) ||
+			(userState == null) ||
+			(switchState == null) ||
+			(dpidStr == null)) {
+			log.debug("IGNORING Flow Entry entry with null fields");
+			continue;
+		    }
+		    FlowEntryId flowEntryId = new FlowEntryId(flowEntryIdStr);
+		    Dpid dpid = new Dpid(dpidStr);
 
-		    /**
-		    log.debug("Found Flow Entry {}: {}",
+		    /*
+		    log.debug("Found Flow Entry Id = {} {}",
 			      flowEntryId.toString(),
-			      "User State: " + userState +
+			      "DPID = " + dpid.toString() +
+			      " User State: " + userState +
 			      " Switch State: " + switchState);
-		     */
-		    
-		    if (! switchState.equals("FE_SWITCH_NOT_UPDATED")) {
-			// Ignore the entry: nothing to do
-			continue;
-		    }
+		    */
 
-		    Dpid dpid = new Dpid(flowEntryObj.getSwitchDpid());
+		    if (! switchState.equals("FE_SWITCH_NOT_UPDATED"))
+			continue;	// Ignore the entry: nothing to do
+
 		    IOFSwitch mySwitch = mySwitches.get(dpid.value());
-		    if (mySwitch == null) {
-			log.debug("Flow Entry ignored: not my switch (FlowEntryId = {} DPID = {})", flowEntryId.toString(), dpid.toString());
-			continue;
-		    }
+		    if (mySwitch == null)
+			continue;	// Ignore the entry: not my switch
+
 		    myFlowEntries.put(flowEntryId.value(), flowEntryObj);
 		}
 
@@ -323,10 +334,8 @@
 		    String userState = flowEntryObj.getUserState();
 		    String switchState = flowEntryObj.getSwitchState();
 		    IOFSwitch mySwitch = mySwitches.get(dpid.value());
-		    if (mySwitch == null) {
-			log.debug("Flow Entry ignored: not my switch");
-			continue;
-		    }
+		    if (mySwitch == null)
+			continue;		// Shouldn't happen
 
 		    //
 		    // Create the Open Flow Flow Modification Entry to push
@@ -421,36 +430,53 @@
 		    try {
 			messageDamper.write(mySwitch, fm, null);
 			mySwitch.flush();
+			//
+			// TODO: We should use the OpenFlow Barrier mechanism
+			// to check for errors, and update the SwitchState
+			// for a flow entry after the Barrier message is
+			// is received.
+			//
 			flowEntryObj.setSwitchState("FE_SWITCH_UPDATED");
 			if (userState.equals("FE_USER_DELETE")) {
-			    // Delete the entry
-			    IFlowPath flowObj = null;
-			    flowObj = conn.utils().getFlowPathByFlowEntry(conn,
-					flowEntryObj);
-			    if (flowObj != null)
-				log.debug("Found FlowPath to be deleted");
-			    else
-				log.debug("Did not find FlowPath to be deleted");
-			    flowObj.removeFlowEntry(flowEntryObj);
-			    conn.utils().removeFlowEntry(conn, flowEntryObj);
-
-			    // Test whether the last flow entry
-			    Iterable<IFlowEntry> tmpflowEntries =
-				flowObj.getFlowEntries();
-			    boolean found = false;
-			    for (IFlowEntry tmpflowEntryObj : tmpflowEntries) {
-				found = true;
-				break;
-			    }
-			    if (! found) {
-				// Remove the Flow Path as well
-				conn.utils().removeFlowPath(conn, flowObj);
-			    }
+			    // An entry that needs to be deleted.
+			    deleteFlowEntries.add(flowEntryObj);
 			}
 		    } catch (IOException e) {
 			log.error("Failure writing flow mod from network map", e);
 		    }
 		}
+
+		//
+		// Delete all entries marked for deletion
+		//
+		// TODO: We should use the OpenFlow Barrier mechanism
+		// to check for errors, and delete the Flow Entries after the
+		// Barrier message is received.
+		//
+		while (! deleteFlowEntries.isEmpty()) {
+		    IFlowEntry flowEntryObj = deleteFlowEntries.poll();
+		    IFlowPath flowObj =
+			conn.utils().getFlowPathByFlowEntry(conn, flowEntryObj);
+		    if (flowObj == null) {
+			log.debug("Did not find FlowPath to be deleted");
+			continue;
+		    }
+		    flowObj.removeFlowEntry(flowEntryObj);
+		    conn.utils().removeFlowEntry(conn, flowEntryObj);
+
+		    // Test whether the last flow entry
+		    Iterable<IFlowEntry> tmpflowEntries =
+			flowObj.getFlowEntries();
+		    boolean found = false;
+		    for (IFlowEntry tmpflowEntryObj : tmpflowEntries) {
+			found = true;
+			break;
+		    }
+		    if (! found) {
+			// Remove the Flow Path as well
+			conn.utils().removeFlowPath(conn, flowObj);
+		    }
+		}
 		conn.endTx(Transaction.COMMIT);
 
 		if (processed_measurement_flow) {
@@ -594,7 +620,9 @@
 		      flowPath.flowId().toString());
 	}
 	if (flowObj == null) {
-	    conn.endTx(Transaction.COMMIT);
+	    log.error(":addFlow FlowId:{} failed: Flow object not created",
+		      flowPath.flowId().toString());
+	    conn.endTx(Transaction.ROLLBACK);
 	    return false;
 	}
 
@@ -645,7 +673,9 @@
 			  flowEntry.flowEntryId().toString());
 	    }
 	    if (flowEntryObj == null) {
-		conn.endTx(Transaction.COMMIT);
+		log.error(":addFlow FlowEntryId:{} failed: FlowEntry object not created",
+		      flowEntry.flowEntryId().toString());
+		conn.endTx(Transaction.ROLLBACK);
 		return false;
 	    }
 
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntry.java b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
index 717be4e..56a1631 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntry.java
+++ b/src/main/java/net/floodlightcontroller/util/FlowEntry.java
@@ -13,6 +13,7 @@
 import net.floodlightcontroller.util.MACAddress;
 import net.floodlightcontroller.util.IPv4;
 
+import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
 
 /**
@@ -22,6 +23,7 @@
  * support multiple in-ports and multiple out-ports.
  */
 public class FlowEntry {
+	private FlowId flowId;                  //FlowID of flowEntry
     private FlowEntryId flowEntryId;		// The Flow Entry ID
     private FlowEntryMatch flowEntryMatch;	// The Flow Entry Match
     private ArrayList<FlowEntryAction> flowEntryActions; // The Flow Entry Actions
@@ -327,4 +329,19 @@
 
 	return ret;
     }
+
+	/**
+	 * @return the flowId
+	 */
+    @JsonIgnore
+	public FlowId getFlowId() {
+		return flowId;
+	}
+
+	/**
+	 * @param flowId the flowId to set
+	 */
+	public void setFlowId(FlowId flowId) {
+		this.flowId = flowId;
+	}
 }
diff --git a/src/main/java/net/onrc/onos/flow/IFlowManager.java b/src/main/java/net/onrc/onos/flow/IFlowManager.java
new file mode 100644
index 0000000..da6448c
--- /dev/null
+++ b/src/main/java/net/onrc/onos/flow/IFlowManager.java
@@ -0,0 +1,53 @@
+package net.onrc.onos.flow;
+
+import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.floodlightcontroller.util.FlowEntry;
+import net.floodlightcontroller.util.FlowPath;
+
+public interface IFlowManager {
+	
+	/*
+	 * Generic create Flow from port to port
+	 */
+	public void createFlow(IPortObject src_port, IPortObject dest_port);
+	/*
+	 * get Flows matching a src_port & dest_port
+	 */
+	public Iterable<FlowPath> getFlows(IPortObject src_port, IPortObject dest_port);
+	/*
+	 * get all Flows going out from port
+	 */
+	public Iterable<FlowPath> getFlows(IPortObject port);
+	/*
+	 * Reconcile all flows on inactive port (src port of link which might be broken)
+	 */
+	public void reconcileFlows(IPortObject src_port);
+	/*
+	 * Reconcile flow based on flow
+	 */
+	public void reconcileFlow(IPortObject src_port, IPortObject dest_port);
+	/*
+	 * compute a flow path using src/dest port
+	 */
+	public FlowPath computeFlowPath(IPortObject src_port, IPortObject dest_port);
+	/*
+	 * Get all FlowEntries of a Flow
+	 */
+    public Iterable<FlowEntry> getFlowEntries(FlowPath flow);
+    /*
+     * install a flow entry on switch
+     */
+    public void installFlowEntry(FlowEntry entry);
+    /*
+     * remove a flowEntry from switch
+     */
+    public void removeFlowEntry(FlowEntry entry);
+    /*
+     * install flow entry on remote controller
+     */
+    public void installFlowEntry(String ctrlId, FlowEntry entry);
+    /*
+     * remove flow entry on remote controller
+     */
+    public void removeFlowEntry(String ctrlId, FlowEntry entry);        
+}
diff --git a/web/topology_rest.py b/web/topology_rest.py
index cdfdf24..5aa4e7a 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -8,6 +8,8 @@
 import io
 import time
 
+import re
+
 from flask import Flask, json, Response, render_template, make_response, request
 
 ## Global Var ##
@@ -633,6 +635,52 @@
   pp.pprint(js)
   return resp
 
+@app.route("/gui/controller/<cmd>/<controller_name>")
+def controller_status_change(cmd, 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)
+
+  if cmd == "up":
+    onos=os.popen(start_onos).read()
+    ret = "controller %s is up" % (controller_name)
+  elif cmd == "down":
+    onos=os.popen(stop_onos).read()
+    ret = "controller %s is down" % (controller_name)
+
+  return ret
+
+@app.route("/gui/switch/<cmd>/<dpid>")
+def switch_status_change(cmd, dpid):
+  r = re.compile(':')
+  dpid = re.sub(r, '', dpid)
+  cmd_string="ssh -i ~/.ssh/onlabkey.pem onosgui1 'cd ONOS/scripts; ./switch.sh %s %s'" % (dpid, cmd)
+  get_status="ssh -i ~/.ssh/onlabkey.pem onosgui1 'cd ONOS/scripts; ./switch.sh %s'" % (dpid)
+  print "cmd_string"
+
+  if cmd =="up" or cmd=="down":
+    print "make dpid %s %s" % (dpid, cmd)
+    onos=os.popen(cmd_string).read()
+    onos=os.popen(get_status).read()
+
+  return onos
+
+#* Switch Up/Down
+#http://localhost:9000/gui/switch/up/<dpid>
+#http://localhost:9000/gui/switch/down/<dpid>
+#* Link Up/Down
+#http://localhost:9000/gui/link/up/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>
+#http://localhost:9000/gui/link/down/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>
+#* Create Flow
+#http://localhost:9000/gui/addflow/<src_dpid>/<src_port>/<dst_dpid>/<dst_port>/<srcMAC>/<dstMAC>
+#* Delete Flow
+#http://localhost:9000/gui/delflow/<flow_id>
+#* Start Iperf Througput
+#http://localhost:9000/gui/iperf/start/<flow_id>
+#* Get Iperf Throughput
+#http://localhost:9000/gui/iperf/rate/<flow_id>
+
+
+
 if __name__ == "__main__":
   if len(sys.argv) > 1 and sys.argv[1] == "-d":
     print "-- query all switches --"