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 --"