Merge "Specify RAMCloud thread config in startup script" into dev/ramcloud-new-datamodel
diff --git a/pom.xml b/pom.xml
index ef5aee1..6803d4c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -258,6 +258,24 @@
</reportSets>
</plugin>
<plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>2.5.3</version>
+ <configuration>
+ <reportPlugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ </plugin>
+ </reportPlugins>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-pmd-plugin</artifactId>
+ <version>3.0.1</version>
+ </plugin>
+ <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<version>2.3</version>
diff --git a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
index 0e8300a..82a1157 100755
--- a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
+++ b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
@@ -21,6 +21,7 @@
router.attach("/get/intents/json", IntentResource.class);
router.attach("/get/intent/{intent_id}/json", IntentResource.class);
router.attach("/get/ng-events/json", GetNGEventsResource.class);
+ router.attach("/get/ng-flows/summary/json", GetNGFlowsSummaryResource.class);
router.attach("/get/intents/{category}/json", IntentResource.class);
router.attach("/get/intent/{category}/{intent_id}/json", IntentResource.class);
router.attach("/delete/intents/json", IntentResource.class);
diff --git a/src/main/java/net/onrc/onos/datagrid/web/GetNGFlowsSummaryResource.java b/src/main/java/net/onrc/onos/datagrid/web/GetNGFlowsSummaryResource.java
new file mode 100644
index 0000000..cf02a12
--- /dev/null
+++ b/src/main/java/net/onrc/onos/datagrid/web/GetNGFlowsSummaryResource.java
@@ -0,0 +1,117 @@
+package net.onrc.onos.datagrid.web;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import net.onrc.onos.intent.Intent;
+import net.onrc.onos.intent.PathIntent;
+import net.onrc.onos.intent.ShortestPathIntent;
+import net.onrc.onos.intent.Intent.IntentState;
+import net.onrc.onos.intent.IntentMap;
+import net.onrc.onos.intent.runtime.IPathCalcRuntimeService;
+
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.util.CallerId;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.FlowPathType;
+import net.onrc.onos.ofcontroller.util.FlowPathUserState;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * REST API call to get a summary of Flow Paths.
+ *
+ * NOTE: This REST API call is needed for the ONOS GUI.
+ *
+ * GET /wm/onos/datagrid/get/ng-flows/summary/json
+ */
+public class GetNGFlowsSummaryResource extends ServerResource {
+ public static final Logger log = LoggerFactory.getLogger(GetNGFlowsSummaryResource.class);
+
+ @Get("json")
+ public ArrayList<FlowPath> retrieve() {
+ ArrayList<FlowPath> result = new ArrayList<>();
+ SortedMap<Long, FlowPath> sortedFlowPaths = new TreeMap<>();
+
+ IPathCalcRuntimeService pathRuntime =
+ (IPathCalcRuntimeService)getContext().
+ getAttributes().get(IPathCalcRuntimeService.class.getCanonicalName());
+ log.debug("Get NG Flows Summary");
+
+
+ IntentMap parentIntentMap = pathRuntime.getHighLevelIntents();
+ IntentMap intentMap = pathRuntime.getPathIntents();
+ for (Intent parentIntent : parentIntentMap.getAllIntents()) {
+ // Get only installed Shortest Paths
+ if (parentIntent.getState() != IntentState.INST_ACK)
+ continue;
+ if (! (parentIntent instanceof ShortestPathIntent))
+ continue;
+ ShortestPathIntent spIntent = (ShortestPathIntent)parentIntent;
+
+ // Get the Path Intent
+ Intent intent = intentMap.getIntent(spIntent.getPathIntentId());
+ if (! (intent instanceof PathIntent))
+ continue;
+ PathIntent pathIntent = (PathIntent)intent;
+
+ // Decode the Shortest Path ID
+ String applnIntentId = parentIntent.getId();
+ String intentId = applnIntentId.split(":")[1];
+ // A hack for Flow IDs that are not routable
+ intentId = intentId.replace("F", "");
+
+ // Create the Flow Path
+ FlowId flowId = new FlowId(intentId);
+ FlowPath flowPath = new FlowPath();
+ flowPath.setFlowId(flowId);
+ sortedFlowPaths.put(flowPath.flowId().value(), flowPath);
+
+ flowPath.setInstallerId(new CallerId("E"));
+ flowPath.setFlowEntryActions(null);
+ flowPath.setFlowPathType(FlowPathType.FP_TYPE_SHORTEST_PATH);
+ flowPath.setFlowPathUserState(FlowPathUserState.FP_USER_ADD);
+
+ // Setup the Source and Destination DPID and Port
+ SwitchPort srcPort = flowPath.dataPath().srcPort();
+ SwitchPort dstPort = flowPath.dataPath().dstPort();
+ srcPort.setDpid(new Dpid(spIntent.getSrcSwitchDpid()));
+ srcPort.setPort(new Port((short)spIntent.getSrcPortNumber()));
+ dstPort.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
+ dstPort.setPort(new Port((short)spIntent.getDstPortNumber()));
+
+ // Extract the Flow Entries
+ Path path = pathIntent.getPath();
+ FlowEntry flowEntry;
+ ArrayList<FlowEntry> flowEntries = new ArrayList<>();
+ for (LinkEvent linkEvent : path) {
+ Dpid dpid = new Dpid(linkEvent.getSrc().getDpid());
+ flowEntry = new FlowEntry();
+ flowEntry.setDpid(dpid);
+ flowEntries.add(flowEntry);
+ }
+ // Add the final Flow Entry
+ flowEntry = new FlowEntry();
+ flowEntry.setDpid(new Dpid(spIntent.getDstSwitchDpid()));
+ flowEntries.add(flowEntry);
+ flowPath.dataPath().setFlowEntries(flowEntries);
+ }
+
+ // Prepare the return result
+ for (FlowPath flowPath : sortedFlowPaths.values())
+ result.add(flowPath);
+
+ return result;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
index 7f38883..a1edb20 100644
--- a/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
+++ b/src/main/java/net/onrc/onos/intent/ConstrainedBFSTree.java
@@ -60,7 +60,7 @@
if (path == null && switchSearched.contains(leafSwitch)) {
path = new Path();
Long sw = leafSwitch.getDpid();
- while (sw != rootSwitchDpid) {
+ while (!sw.equals(rootSwitchDpid)) {
LinkEvent upstreamLink = upstreamLinks.get(sw);
path.add(0, upstreamLink);
sw = upstreamLink.getSrc().getDpid();
diff --git a/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java b/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
index 380a0f2..602762b 100755
--- a/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
+++ b/src/main/java/net/onrc/onos/intent/persist/PersistIntent.java
@@ -17,6 +17,7 @@
import net.onrc.onos.intent.IntentOperationList;
import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
import net.onrc.onos.registry.controller.IControllerRegistryService;
import net.onrc.onos.registry.controller.IdBlock;
import org.slf4j.Logger;
@@ -34,7 +35,7 @@
private final static String intentJournal = "G:IntentJournal";
private final static int valueStoreLimit = 1024 * 1024;
private RCTable table;
- private Kryo kryo = new Kryo();
+ private Kryo kryo;
private ByteArrayOutputStream stream;
private Output output = null;
private AtomicLong nextId = null;
@@ -48,6 +49,7 @@
table = RCTable.getTable(intentJournal);
stream = new ByteArrayOutputStream(1024);
output = new Output(stream);
+ kryo = (new KryoFactory()).newKryo();
}
public long getKey() {
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
index 6ff92db..3de671e 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntime.java
@@ -45,6 +45,7 @@
// TODO optimize locking of NetworkGraph
graph.acquireReadLock();
+ log.debug("NetworkGraph: {}", graph.getLinks());
for (IntentOperation intentOp: intentOpList) {
switch (intentOp.operator) {
@@ -62,9 +63,10 @@
Switch srcSwitch = graph.getSwitch(spIntent.getSrcSwitchDpid());
Switch dstSwitch = graph.getSwitch(spIntent.getDstSwitchDpid());
if (srcSwitch == null || dstSwitch == null) {
- log.error("Switch not found: {}, {}",
+ log.error("Switch not found. src:{}, dst:{}, NetworkGraph:{}",
spIntent.getSrcSwitchDpid(),
- spIntent.getDstSwitchDpid());
+ spIntent.getDstSwitchDpid(),
+ graph.getLinks());
pathIntentOpList.add(Operator.ERROR, new ErrorIntent(
ErrorType.SWITCH_NOT_FOUND,
"Switch not found.",
@@ -87,7 +89,7 @@
}
Path path = tree.getPath(dstSwitch);
if (path == null) {
- log.error("Path not found: {}", spIntent.toString());
+ log.error("Path not found. Intent: {}, NetworkGraph:{}", spIntent.toString(), graph.getLinks());
pathIntentOpList.add(Operator.ERROR, new ErrorIntent(
ErrorType.PATH_NOT_FOUND,
"Path not found.",
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
index 37015cb..1101dc9 100755
--- a/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PathCalcRuntimeModule.java
@@ -84,6 +84,7 @@
private IEventChannel<Long, IntentOperationList> opEventChannel;
private final ReentrantLock lock = new ReentrantLock();
+ private HashSet<LinkEvent> unmatchedLinkEvents = new HashSet<>();
private static final String INTENT_OP_EVENT_CHANNEL_NAME = "onos.pathintent";
private static final String INTENT_STATE_EVENT_CHANNEL_NAME = "onos.pathintent_state";
private static final Logger log = LoggerFactory.getLogger(PathCalcRuntimeModule.class);
@@ -99,8 +100,10 @@
IntentOperationList reroutingOperation = new IntentOperationList();
for (Intent intent : oldPaths) {
PathIntent pathIntent = (PathIntent) intent;
- if (pathIntent.getState().equals(IntentState.INST_ACK) &&
- !reroutingOperation.contains(pathIntent)) {
+ if (pathIntent.getId().startsWith("1:F")) // XXX: demo special, the intent start with "F" is skipped
+ continue;
+ if (pathIntent.getState().equals(IntentState.INST_ACK) && // XXX: path intents in flight
+ !reroutingOperation.contains(pathIntent.getParentIntent())) {
reroutingOperation.add(Operator.ADD, pathIntent.getParentIntent());
}
}
@@ -173,6 +176,8 @@
for (IntentOperation op : list) {
if (op.intent.getState().equals(IntentState.INST_ACK))
states.put(op.intent.getId(), IntentState.REROUTE_REQ);
+ if (op.intent.getState().equals(IntentState.CREATED))
+ states.put(op.intent.getId(), IntentState.INST_REQ); // XXX
}
highLevelIntents.changeStates(states);
p.log("end_updateInMemoryIntents");
@@ -207,7 +212,7 @@
pathIntents.executeOperations(pathIntentOperations);
p.log("end_updateInMemoryPathIntents");
- // Demo special: add a complete path to remove operation
+ // XXX Demo special: add a complete path to remove operation
p.log("begin_addPathToRemoveOperation");
for (IntentOperation op: pathIntentOperations) {
if(op.operator.equals(Operator.REMOVE)) {
@@ -221,9 +226,11 @@
// send notification
p.log("begin_sendNotification");
- opEventChannel.addEntry(key, pathIntentOperations);
+ // XXX: Send notifications using the same key every time
+ // and receive them by entryAdded() and entryUpdated()
+ opEventChannel.addEntry(0L, pathIntentOperations);
p.log("end_sendNotification");
- opEventChannel.removeEntry(key);
+ //opEventChannel.removeEntry(key);
return pathIntentOperations;
}
finally {
@@ -265,14 +272,39 @@
PerfLogger p = new PerfLogger("networkGraphEvents");
HashSet<Intent> affectedPaths = new HashSet<>();
- if (addedLinkEvents.size() > 0) { // ||
+ boolean rerouteAll = false;
+ for(LinkEvent le : addedLinkEvents) {
+ LinkEvent rev = new LinkEvent(le.getDst().getDpid(), le.getDst().getNumber(), le.getSrc().getDpid(), le.getSrc().getNumber());
+ if(unmatchedLinkEvents.contains(rev)) {
+ rerouteAll = true;
+ unmatchedLinkEvents.remove(rev);
+ log.debug("Found matched LinkEvent: {} {}", rev, le);
+ }
+ else {
+ unmatchedLinkEvents.add(le);
+ log.debug("Adding unmatched LinkEvent: {}", le);
+ }
+ }
+ for(LinkEvent le : removedLinkEvents) {
+ if (unmatchedLinkEvents.contains(le)) {
+ unmatchedLinkEvents.remove(le);
+ log.debug("Removing LinkEvent: {}", le);
+ }
+ }
+ if(unmatchedLinkEvents.size() > 0) {
+ log.debug("Unmatched link events: {} events", unmatchedLinkEvents.size());
+ }
+
+ if ( rerouteAll ) {//addedLinkEvents.size() > 0) { // ||
// addedPortEvents.size() > 0 ||
// addedSwitchEvents.size() > 0) {
p.log("begin_getAllIntents");
affectedPaths.addAll(getPathIntents().getAllIntents());
p.log("end_getAllIntents");
}
- else {
+ else if (removedSwitchEvents.size() > 0 ||
+ removedLinkEvents.size() > 0 ||
+ removedPortEvents.size() > 0) {
p.log("begin_getIntentsByLink");
for (LinkEvent linkEvent: removedLinkEvents)
affectedPaths.addAll(pathIntents.getIntentsByLink(linkEvent));
@@ -288,7 +320,9 @@
affectedPaths.addAll(pathIntents.getIntentsByDpid(switchEvent.getDpid()));
p.log("end_getIntentsByDpid");
}
+ p.log("begin_reroutePaths");
reroutePaths(affectedPaths);
+ p.log("end_reroutePaths");
p.flushLog();
}
@@ -314,7 +348,8 @@
try {
// reflect state changes of path-level intent into application-level intents
p.log("begin_changeStateByNotification");
- IntentStateList parentStates = new IntentStateList();
+ IntentStateList highLevelIntentStates = new IntentStateList();
+ IntentStateList pathIntentStates = new IntentStateList();
for (Entry<String, IntentState> entry: value.entrySet()) {
PathIntent pathIntent = (PathIntent) pathIntents.getIntent(entry.getKey());
if (pathIntent == null) continue;
@@ -327,20 +362,21 @@
IntentState state = entry.getValue();
switch (state) {
- case INST_REQ:
+ //case INST_REQ:
case INST_ACK:
case INST_NACK:
- case DEL_REQ:
+ //case DEL_REQ:
case DEL_ACK:
case DEL_PENDING:
- parentStates.put(parentIntent.getId(), state);
+ highLevelIntentStates.put(parentIntent.getId(), state);
+ pathIntentStates.put(entry.getKey(), entry.getValue());
break;
default:
break;
}
}
- highLevelIntents.changeStates(parentStates);
- pathIntents.changeStates(value);
+ highLevelIntents.changeStates(highLevelIntentStates);
+ pathIntents.changeStates(pathIntentStates);
p.log("end_changeStateByNotification");
}
finally {
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
index b12711a..5691c53 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanCalcRuntime.java
@@ -5,13 +5,11 @@
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.Set;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.intent.FlowEntry;
import net.onrc.onos.intent.Intent;
@@ -23,6 +21,9 @@
import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
//import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
/**
*
* @author Brian O'Connor <bocon@onlab.us>
@@ -40,7 +41,7 @@
public List<Set<FlowEntry>> computePlan(IntentOperationList intentOps) {
long start = System.nanoTime();
- Set<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
+ List<Collection<FlowEntry>> flowEntries = computeFlowEntries(intentOps);
long step1 = System.nanoTime();
List<Set<FlowEntry>> plan = buildPhases(flowEntries);
long step2 = System.nanoTime();
@@ -49,8 +50,8 @@
return plan;
}
- private Set<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
- Set<Collection<FlowEntry>> flowEntries = new HashSet<>();
+ private List<Collection<FlowEntry>> computeFlowEntries(IntentOperationList intentOps) {
+ List<Collection<FlowEntry>> flowEntries = new LinkedList<>();
for(IntentOperation i : intentOps) {
if(!(i.intent instanceof PathIntent)) {
log.warn("Not a path intent: {}", i);
@@ -106,7 +107,7 @@
return flowEntries;
}
- private List<Set<FlowEntry>> buildPhases(Set<Collection<FlowEntry>> flowEntries) {
+ private List<Set<FlowEntry>> buildPhases(List<Collection<FlowEntry>> flowEntries) {
Map<FlowEntry, Integer> map = new HashMap<>();
List<Set<FlowEntry>> plan = new ArrayList<>();
for(Collection<FlowEntry> c : flowEntries) {
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
index b8bed85..293a33d 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallModule.java
@@ -43,7 +43,7 @@
private static final String PATH_INTENT_CHANNEL_NAME = "onos.pathintent";
private static final String INTENT_STATE_EVENT_CHANNEL_NAME = "onos.pathintent_state";
-
+
@Override
public void init(FloodlightModuleContext context)
throws FloodlightModuleException {
@@ -59,27 +59,27 @@
class EventListener extends Thread
implements IEventChannelListener<Long, IntentOperationList> {
-
+
private BlockingQueue<IntentOperationList> intentQueue = new LinkedBlockingQueue<>();
private Long key = Long.valueOf(0);
-
+
@Override
public void run() {
while(true) {
try {
IntentOperationList intents = intentQueue.take();
- //TODO: consider draining the remaining intent lists
+ //TODO: consider draining the remaining intent lists
// and processing in one big batch
// List<IntentOperationList> remaining = new LinkedList<>();
// intentQueue.drainTo(remaining);
-
+
processIntents(intents);
} catch (InterruptedException e) {
log.warn("Error taking from intent queue: {}", e.getMessage());
}
}
}
-
+
private void processIntents(IntentOperationList intents) {
log("start_processIntents");
log.debug("Processing OperationList {}", intents);
@@ -90,13 +90,13 @@
log("begin_installPlan");
boolean success = planInstall.installPlan(plan);
log("end_installPlan");
-
+
log("begin_sendInstallNotif");
sendNotifications(intents, true, success);
log("end_sendInstallNotif");
log("finish");
}
-
+
private void sendNotifications(IntentOperationList intents, boolean installed, boolean success) {
IntentStateList states = new IntentStateList();
for(IntentOperation i : intents) {
@@ -123,11 +123,23 @@
states.put(i.intent.getId(), newState);
}
intentStateChannel.addEntry(key, states);
- key += 1;
+ // XXX: Send notifications using the same key every time
+ // and receive them by entryAdded() and entryUpdated()
+ // key += 1;
}
-
+
@Override
public void entryAdded(IntentOperationList value) {
+ entryUpdated(value);
+ }
+
+ @Override
+ public void entryRemoved(IntentOperationList value) {
+ // This channel is a queue, so this method is not needed
+ }
+
+ @Override
+ public void entryUpdated(IntentOperationList value) {
log("start_intentNotifRecv");
log("begin_sendReceivedNotif");
sendNotifications(value, false, false);
@@ -141,36 +153,26 @@
log.warn("Error putting to intent queue: {}", e.getMessage());
}
}
-
- @Override
- public void entryRemoved(IntentOperationList value) {
- // This channel is a queue, so this method is not needed
- }
-
- @Override
- public void entryUpdated(IntentOperationList value) {
- // This channel is a queue, so this method is not needed
- }
}
-
+
public static void log(String step) {
log.error("Time:{}, Step:{}", System.nanoTime(), step);
}
-
+
@Override
public void startUp(FloodlightModuleContext context) {
// start subscriber
- datagridService.addListener(PATH_INTENT_CHANNEL_NAME,
- eventListener,
- Long.class,
+ datagridService.addListener(PATH_INTENT_CHANNEL_NAME,
+ eventListener,
+ Long.class,
IntentOperationList.class);
eventListener.start();
// start publisher
- intentStateChannel = datagridService.createChannel(INTENT_STATE_EVENT_CHANNEL_NAME,
- Long.class,
+ intentStateChannel = datagridService.createChannel(INTENT_STATE_EVENT_CHANNEL_NAME,
+ Long.class,
IntentStateList.class);
}
-
+
@Override
public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
Collection<Class<? extends IFloodlightService>> l =
@@ -181,7 +183,7 @@
l.add(IFlowPusherService.class);
return l;
}
-
+
@Override
public Collection<Class<? extends IFloodlightService>> getModuleServices() {
// no services, for now
diff --git a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
index abd82ed..e8d498f 100644
--- a/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
+++ b/src/main/java/net/onrc/onos/intent/runtime/PlanInstallRuntime.java
@@ -1,6 +1,7 @@
package net.onrc.onos.intent.runtime;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -38,15 +39,73 @@
this.provider = provider;
this.pusher = pusher;
}
+
+ private static class FlowModCount {
+ IOFSwitch sw;
+ long modFlows = 0;
+ long delFlows = 0;
+ long errors = 0;
+
+ FlowModCount(IOFSwitch sw) {
+ this.sw = sw;
+ }
+
+ void addFlowEntry(FlowEntry entry) {
+ switch(entry.getOperator()){
+ case ADD:
+ modFlows++;
+ break;
+ case ERROR:
+ errors++;
+ break;
+ case REMOVE:
+ delFlows++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ public String toString() {
+ return "sw:" + sw.getStringId() + ": modify " + modFlows + " delete " + delFlows + " error " + errors;
+ }
+
+ static Map<IOFSwitch, FlowModCount> map = new HashMap<>();
+ static void countFlowEntry(IOFSwitch sw, FlowEntry entry) {
+ FlowModCount count = map.get(sw);
+ if(count == null) {
+ count = new FlowModCount(sw);
+ map.put(sw, count);
+ }
+ count.addFlowEntry(entry);
+ }
+ static void startCount() {
+ map.clear();
+ }
+ static void printCount() {
+ String result = "FLOWMOD COUNT:\n";
+ for(FlowModCount count : map.values()) {
+ result += count.toString() + '\n';
+ }
+ if(map.values().isEmpty()) {
+ result += "No flow mods installed\n";
+ }
+ log.error(result);
+ }
+ }
public boolean installPlan(List<Set<FlowEntry>> plan) {
long start = System.nanoTime();
Map<Long,IOFSwitch> switches = provider.getSwitches();
+
log.debug("IOFSwitches: {}", switches);
+
+ FlowModCount.startCount();
for(Set<FlowEntry> phase : plan) {
Set<Pair<IOFSwitch, net.onrc.onos.ofcontroller.util.FlowEntry>> entries = new HashSet<>();
Set<IOFSwitch> modifiedSwitches = new HashSet<>();
-
+
+ long step1 = System.nanoTime();
// convert flow entries and create pairs
for(FlowEntry entry : phase) {
IOFSwitch sw = switches.get(entry.getSwitch());
@@ -55,13 +114,16 @@
log.debug("Skipping flow entry: {}", entry);
continue;
}
- entries.add(new Pair<>(sw, entry.getFlowEntry()));
+ entries.add(new Pair<>(sw, entry.getFlowEntry()));
modifiedSwitches.add(sw);
+ FlowModCount.countFlowEntry(sw, entry);
}
+ long step2 = System.nanoTime();
// push flow entries to switches
log.debug("Pushing flow entries: {}", entries);
pusher.pushFlowEntries(entries);
+ long step3 = System.nanoTime();
// TODO: insert a barrier after each phase on each modifiedSwitch
// TODO: wait for confirmation messages before proceeding
@@ -78,9 +140,14 @@
log.error("Barrier message not received for sw: {}", sw);
}
}
+ long step4 = System.nanoTime();
+ log.error("MEASUREMENT: convert: {} ns, push: {} ns, barrierWait: {} ns",
+ step2 - step1, step3 - step2, step4 - step3);
+
}
long end = System.nanoTime();
log.error("MEASUREMENT: Install plan: {} ns", (end-start));
+ FlowModCount.printCount();
// TODO: we assume that the plan installation succeeds for now
return true;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
index 38f164a..3f3af2d 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/TopologyManager.java
@@ -480,10 +480,12 @@
addDevice(deviceEvent);
}
- /* ******************************
- * NetworkGraphDiscoveryInterface methods
- * ******************************/
-
+ /**
+ * Switch discovered event.
+ *
+ * @param switchEvent the switch event.
+ * @param portEvents the corresponding port events for the switch.
+ */
@Override
public void putSwitchDiscoveryEvent(SwitchEvent switchEvent,
Collection<PortEvent> portEvents) {
@@ -533,6 +535,11 @@
}
}
+ /**
+ * Switch removed event.
+ *
+ * @param switchEvent the switch event.
+ */
@Override
public void removeSwitchDiscoveryEvent(SwitchEvent switchEvent) {
// Get the old Port Events
@@ -578,6 +585,11 @@
}
}
+ /**
+ * Port discovered event.
+ *
+ * @param portEvent the port event.
+ */
@Override
public void putPortDiscoveryEvent(PortEvent portEvent) {
if (datastore.addPort(portEvent)) {
@@ -598,6 +610,11 @@
}
}
+ /**
+ * Port removed event.
+ *
+ * @param portEvent the port event.
+ */
@Override
public void removePortDiscoveryEvent(PortEvent portEvent) {
if (datastore.deactivatePort(portEvent)) {
@@ -645,6 +662,11 @@
}
}
+ /**
+ * Link discovered event.
+ *
+ * @param linkEvent the link event.
+ */
@Override
public void putLinkDiscoveryEvent(LinkEvent linkEvent) {
if (datastore.addLink(linkEvent)) {
@@ -665,6 +687,11 @@
}
}
+ /**
+ * Link removed event.
+ *
+ * @param linkEvent the link event.
+ */
@Override
public void removeLinkDiscoveryEvent(LinkEvent linkEvent) {
if (datastore.removeLink(linkEvent)) {
@@ -681,6 +708,11 @@
}
}
+ /**
+ * Device discovered event.
+ *
+ * @param deviceEvent the device event.
+ */
@Override
public void putDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
if (datastore.addDevice(deviceEvent)) {
@@ -704,6 +736,11 @@
}
}
+ /**
+ * Device removed event.
+ *
+ * @param deviceEvent the device event.
+ */
@Override
public void removeDeviceDiscoveryEvent(DeviceEvent deviceEvent) {
if (datastore.removeDevice(deviceEvent)) {
@@ -723,9 +760,11 @@
}
}
- /* ************************************************
- * Internal methods to maintain the network graph
- * ************************************************/
+ /**
+ * Add a switch to the Network Graph.
+ *
+ * @param switchEvent the Switch Event with the switch to add.
+ */
private void addSwitch(SwitchEvent switchEvent) {
Switch sw = networkGraph.getSwitch(switchEvent.getDpid());
if (sw == null) {
@@ -738,6 +777,11 @@
apiAddedSwitchEvents.add(switchEvent);
}
+ /**
+ * Remove a switch from the Network Graph.
+ *
+ * @param switchEvent the Switch Event with the switch to remove.
+ */
private void removeSwitch(SwitchEvent switchEvent) {
Switch sw = networkGraph.getSwitch(switchEvent.getDpid());
if (sw == null) {
@@ -763,6 +807,11 @@
apiRemovedSwitchEvents.add(switchEvent);
}
+ /**
+ * Add a port to the Network Graph.
+ *
+ * @param portEvent the Port Event with the port to add.
+ */
private void addPort(PortEvent portEvent) {
Switch sw = networkGraph.getSwitch(portEvent.getDpid());
if (sw == null) {
@@ -783,6 +832,11 @@
apiAddedPortEvents.add(portEvent);
}
+ /**
+ * Remove a port from the Network Graph.
+ *
+ * @param portEvent the Port Event with the port to remove.
+ */
private void removePort(PortEvent portEvent) {
Switch sw = networkGraph.getSwitch(portEvent.getDpid());
if (sw == null) {
@@ -839,6 +893,11 @@
apiRemovedPortEvents.add(portEvent);
}
+ /**
+ * Add a link to the Network Graph.
+ *
+ * @param linkEvent the Link Event with the link to add.
+ */
private void addLink(LinkEvent linkEvent) {
Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
linkEvent.getSrc().number);
@@ -888,6 +947,11 @@
apiAddedLinkEvents.add(linkEvent);
}
+ /**
+ * Remove a link from the Network Graph.
+ *
+ * @param linkEvent the Link Event with the link to remove.
+ */
private void removeLink(LinkEvent linkEvent) {
Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
linkEvent.getSrc().number);
@@ -923,7 +987,15 @@
apiRemovedLinkEvents.add(linkEvent);
}
- // TODO: Device-related work is incomplete
+ /**
+ * Add a device to the Network Graph.
+ *
+ * TODO: Device-related work is incomplete.
+ * TODO: Eventually, we might need to consider reordering
+ * or addLink() and addDevice() events on the same port.
+ *
+ * @param deviceEvent the Device Event with the device to add.
+ */
private void addDevice(DeviceEvent deviceEvent) {
Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
if (device == null) {
@@ -969,6 +1041,13 @@
}
}
+ /**
+ * Remove a device from the Network Graph.
+ *
+ * TODO: Device-related work is incomplete.
+ *
+ * @param deviceEvent the Device Event with the device to remove.
+ */
private void removeDevice(DeviceEvent deviceEvent) {
Device device = networkGraph.getDeviceByMac(deviceEvent.getMac());
if (device == null) {
@@ -997,218 +1076,63 @@
}
/**
+ * Get the SwitchImpl-casted switch implementation.
*
- * @param switchEvent
- * @return true if ready to accept event.
+ * @param sw the Switch to cast.
+ * @return the SwitchImpl-casted switch implementation.
*/
- private boolean prepareForAddSwitchEvent(SwitchEvent switchEvent) {
- // No show stopping precondition
- return true;
- }
-
- private boolean prepareForRemoveSwitchEvent(SwitchEvent switchEvent) {
- // No show stopping precondition
- return true;
- }
-
- private boolean prepareForAddPortEvent(PortEvent portEvent) {
- // Parent Switch must exist
- if (networkGraph.getSwitch(portEvent.getDpid()) == null) {
- log.warn("Dropping add port event because switch doesn't exist: {}",
- portEvent);
- return false;
- }
- // Prep: None
- return true;
- }
-
- private boolean prepareForRemovePortEvent(PortEvent portEvent) {
- Port port = networkGraph.getPort(portEvent.getDpid(),
- portEvent.getNumber());
- if (port == null) {
- log.debug("Port already removed? {}", portEvent);
- // let it pass
- return true;
- }
-
- // Prep: Remove Link and Device Attachment
- ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
- for (Device device : port.getDevices()) {
- log.debug("Removing Device {} on Port {}", device, portEvent);
- DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
- devEvent.addAttachmentPoint(new SwitchPort(port.getSwitch().getDpid(),
- port.getNumber()));
- deviceEvents.add(devEvent);
- }
- for (DeviceEvent devEvent : deviceEvents) {
- // calling Discovery API to wipe from DB, etc.
- removeDeviceDiscoveryEvent(devEvent);
- }
-
- Set<Link> links = new HashSet<>();
- links.add(port.getOutgoingLink());
- links.add(port.getIncomingLink());
- for (Link link : links) {
- if (link == null) {
- continue;
- }
- log.debug("Removing Link {} on Port {}", link, portEvent);
- LinkEvent linkEvent =
- new LinkEvent(link.getSrcSwitch().getDpid(),
- link.getSrcPort().getNumber(),
- link.getDstSwitch().getDpid(),
- link.getDstPort().getNumber());
- // calling Discovery API to wipe from DB, etc.
-
- // Call internal remove Link, which will check
- // ownership of DST dpid and modify DB only if it is the owner
- removeLinkDiscoveryEvent(linkEvent, true);
- }
- return true;
- }
-
- private boolean prepareForAddLinkEvent(LinkEvent linkEvent) {
- // Src/Dst Port must exist
- Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
- linkEvent.getSrc().number);
- Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
- linkEvent.getDst().number);
- if (srcPort == null || dstPort == null) {
- log.warn("Dropping add link event because port doesn't exist: {}",
- linkEvent);
- return false;
- }
-
- // Prep: remove Device attachment on both Ports
- ArrayList<DeviceEvent> deviceEvents = new ArrayList<>();
- for (Device device : srcPort.getDevices()) {
- DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
- devEvent.addAttachmentPoint(new SwitchPort(srcPort.getSwitch().getDpid(), srcPort.getNumber()));
- deviceEvents.add(devEvent);
- }
- for (Device device : dstPort.getDevices()) {
- DeviceEvent devEvent = new DeviceEvent(device.getMacAddress());
- devEvent.addAttachmentPoint(new SwitchPort(dstPort.getSwitch().getDpid(),
- dstPort.getNumber()));
- deviceEvents.add(devEvent);
- }
- for (DeviceEvent devEvent : deviceEvents) {
- // calling Discovery API to wipe from DB, etc.
- removeDeviceDiscoveryEvent(devEvent);
- }
-
- return true;
- }
-
- private boolean prepareForRemoveLinkEvent(LinkEvent linkEvent) {
- // Src/Dst Port must exist
- Port srcPort = networkGraph.getPort(linkEvent.getSrc().dpid,
- linkEvent.getSrc().number);
- Port dstPort = networkGraph.getPort(linkEvent.getDst().dpid,
- linkEvent.getDst().number);
- if (srcPort == null || dstPort == null) {
- log.warn("Dropping remove link event because port doesn't exist {}", linkEvent);
- return false;
- }
-
- Link link = srcPort.getOutgoingLink();
-
- // Link is already gone, or different Link exist in memory
- // XXX Check if we should reject or just accept these cases.
- // it should be harmless to remove the Link on event from DB anyways
- if (link == null ||
- !link.getDstPort().getNumber().equals(linkEvent.getDst().number)
- || !link.getDstSwitch().getDpid().equals(linkEvent.getDst().dpid)) {
- log.warn("Dropping remove link event because link doesn't exist: {}", linkEvent);
- return false;
- }
- // Prep: None
- return true;
- }
-
- /**
- *
- * @param deviceEvent Event will be modified to remove inapplicable attachemntPoints/ipAddress
- * @return false if this event should be dropped.
- */
- private boolean prepareForAddDeviceEvent(DeviceEvent deviceEvent) {
- boolean preconditionBroken = false;
- ArrayList<PortEvent.SwitchPort> failedSwitchPort = new ArrayList<>();
- for ( PortEvent.SwitchPort swp : deviceEvent.getAttachmentPoints() ) {
- // Attached Ports must exist
- Port port = networkGraph.getPort(swp.dpid, swp.number);
- if (port == null) {
- preconditionBroken = true;
- failedSwitchPort.add(swp);
- continue;
- }
- // Attached Ports must not have Link
- if (port.getOutgoingLink() != null ||
- port.getIncomingLink() != null) {
- preconditionBroken = true;
- failedSwitchPort.add(swp);
- continue;
- }
- }
-
- // Rewriting event to exclude failed attachmentPoint
- // XXX Assumption behind this is that inapplicable device event should
- // be dropped, not deferred. If we decide to defer Device event,
- // rewriting can become a problem
- List<SwitchPort> attachmentPoints = deviceEvent.getAttachmentPoints();
- attachmentPoints.removeAll(failedSwitchPort);
- deviceEvent.setAttachmentPoints(attachmentPoints);
-
- if (deviceEvent.getAttachmentPoints().isEmpty() &&
- deviceEvent.getIpAddresses().isEmpty()) {
- // return false to represent: Nothing left to do for this event.
- // Caller should drop event
- return false;
- }
-
- // Should we return false to tell caller that the event was trimmed?
- // if ( preconditionBroken ) {
- // return false;
- // }
-
- return true;
- }
-
- private boolean prepareForRemoveDeviceEvent(DeviceEvent deviceEvent) {
- // No show stopping precondition?
- // Prep: none
- return true;
- }
-
private SwitchImpl getSwitchImpl(Switch sw) {
if (sw instanceof SwitchImpl) {
- return (SwitchImpl) sw;
+ return (SwitchImpl)sw;
}
throw new ClassCastException("SwitchImpl expected, but found: " + sw);
}
- private PortImpl getPortImpl(Port p) {
- if (p instanceof PortImpl) {
- return (PortImpl) p;
+ /**
+ * Get the PortImpl-casted port implementation.
+ *
+ * @param port the Port to cast.
+ * @return the PortImpl-casted port implementation.
+ */
+ private PortImpl getPortImpl(Port port) {
+ if (port instanceof PortImpl) {
+ return (PortImpl)port;
}
- throw new ClassCastException("PortImpl expected, but found: " + p);
+ throw new ClassCastException("PortImpl expected, but found: " + port);
}
- private LinkImpl getLinkImpl(Link l) {
- if (l instanceof LinkImpl) {
- return (LinkImpl) l;
+ /**
+ * Get the LinkImpl-casted link implementation.
+ *
+ * @param link the Link to cast.
+ * @return the LinkImpl-casted link implementation.
+ */
+ private LinkImpl getLinkImpl(Link link) {
+ if (link instanceof LinkImpl) {
+ return (LinkImpl)link;
}
- throw new ClassCastException("LinkImpl expected, but found: " + l);
+ throw new ClassCastException("LinkImpl expected, but found: " + link);
}
- private DeviceImpl getDeviceImpl(Device d) {
- if (d instanceof DeviceImpl) {
- return (DeviceImpl) d;
+ /**
+ * Get the DeviceImpl-casted device implementation.
+ *
+ * @param device the Device to cast.
+ * @return the DeviceImpl-casted device implementation.
+ */
+ private DeviceImpl getDeviceImpl(Device device) {
+ if (device instanceof DeviceImpl) {
+ return (DeviceImpl)device;
}
- throw new ClassCastException("DeviceImpl expected, but found: " + d);
+ throw new ClassCastException("DeviceImpl expected, but found: " + device);
}
- @Deprecated
+ /**
+ * Read the whole topology from the database.
+ *
+ * @return a collection of EventEntry-encapsulated Topology Events for
+ * the whole topology.
+ */
private Collection<EventEntry<TopologyEvent>> readWholeTopologyFromDB() {
Collection<EventEntry<TopologyEvent>> collection =
new LinkedList<EventEntry<TopologyEvent>>();
@@ -1266,25 +1190,4 @@
return collection;
}
-
- @Deprecated
- private void removeLinkDiscoveryEvent(LinkEvent linkEvent,
- boolean dstCheckBeforeDBmodify) {
- if (prepareForRemoveLinkEvent(linkEvent)) {
- if (dstCheckBeforeDBmodify) {
- // write to DB only if it is owner of the dst dpid
- // XXX this will cause link remove events to be dropped
- // if the dst switch just disconnected
- if (registryService.hasControl(linkEvent.getDst().dpid)) {
- datastore.removeLink(linkEvent);
- }
- } else {
- datastore.removeLink(linkEvent);
- }
- removeLink(linkEvent);
- // Send out notification
- eventChannel.removeEntry(linkEvent.getID());
- }
- // TODO handle invariant violation
- }
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java
new file mode 100644
index 0000000..43e5806
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java
@@ -0,0 +1,81 @@
+package net.onrc.onos.ofcontroller.networkgraph.web;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.onrc.onos.intent.ConstrainedBFSTree;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.networkgraph.serializers.LinkSerializer;
+import net.onrc.onos.ofcontroller.util.Dpid;
+
+import org.codehaus.jackson.Version;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.module.SimpleModule;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetworkGraphShortestPathResource extends ServerResource {
+
+ private static final Logger log = LoggerFactory.getLogger(NetworkGraphShortestPathResource.class);
+
+ @Get("json")
+ public String retrieve() {
+ INetworkGraphService networkGraphService =
+ (INetworkGraphService)getContext().getAttributes().
+ get(INetworkGraphService.class.getCanonicalName());
+
+ NetworkGraph graph = networkGraphService.getNetworkGraph();
+
+ ObjectMapper mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null));
+ module.addSerializer(new LinkSerializer());
+ mapper.registerModule(module);
+
+ //
+ // Fetch the attributes
+ //
+ String srcDpidStr = (String)getRequestAttributes().get("src-dpid");
+ String dstDpidStr = (String)getRequestAttributes().get("dst-dpid");
+ Dpid srcDpid = new Dpid(srcDpidStr);
+ Dpid dstDpid = new Dpid(dstDpidStr);
+ log.debug("Getting Shortest Path {}--{}", srcDpidStr, dstDpidStr);
+
+ //
+ // Do the Shortest Path computation and return the result: list of
+ // links.
+ //
+ try {
+ graph.acquireReadLock();
+ Switch srcSwitch = graph.getSwitch(srcDpid.value());
+ Switch dstSwitch = graph.getSwitch(dstDpid.value());
+ if ((srcSwitch == null) || (dstSwitch == null))
+ return "";
+ ConstrainedBFSTree bfsTree = new ConstrainedBFSTree(srcSwitch);
+ Path path = bfsTree.getPath(dstSwitch);
+ List<Link> links = new LinkedList<>();
+ for (LinkEvent linkEvent : path) {
+ Link link = graph.getLink(linkEvent.getSrc().getDpid(),
+ linkEvent.getSrc().getNumber(),
+ linkEvent.getDst().getDpid(),
+ linkEvent.getDst().getNumber());
+ if (link == null)
+ return "";
+ links.add(link);
+ }
+ return mapper.writeValueAsString(links);
+ } catch (IOException e) {
+ log.error("Error writing Shortest Path to JSON", e);
+ return "";
+ } finally {
+ graph.releaseReadLock();
+ }
+ }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
index 6a7ab99..e245801 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
@@ -16,6 +16,7 @@
router.attach("/rc/ports/json", RamcloudPortsResource.class);
router.attach("/ng/switches/json", NetworkGraphSwitchesResource.class);
router.attach("/ng/links/json", NetworkGraphLinksResource.class);
+ router.attach("/ng/shortest-path/{src-dpid}/{dst-dpid}/json", NetworkGraphShortestPathResource.class);
return router;
}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
index df93614..f020a8f 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/KryoFactory.java
@@ -178,16 +178,17 @@
kryo.register(TopologyEvent.class);
// Intent-related classes
- kryo.register(IntentOperationList.class);
- kryo.register(IntentOperation.class);
- kryo.register(PathIntent.class);
+ kryo.register(Path.class);
kryo.register(Intent.class);
- kryo.register(ErrorIntent.class);
+ kryo.register(Intent.IntentState.class);
+ kryo.register(PathIntent.class);
kryo.register(ShortestPathIntent.class);
kryo.register(ConstrainedShortestPathIntent.class);
- kryo.register(Intent.IntentState.class);
- kryo.register(Path.class);
+ kryo.register(ErrorIntent.class);
+ kryo.register(ErrorIntent.ErrorType.class);
+ kryo.register(IntentOperation.class);
kryo.register(IntentOperation.Operator.class);
+ kryo.register(IntentOperationList.class);
kryo.register(IntentStateList.class);
return kryo;
diff --git a/src/main/resources/hazelcast.xml b/src/main/resources/hazelcast.xml
deleted file mode 120000
index f8f4972..0000000
--- a/src/main/resources/hazelcast.xml
+++ /dev/null
@@ -1 +0,0 @@
-/home/mininet/ONOS/conf/hazelcast.xml
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/intent/ConstrainedBFSTreeTest.java b/src/test/java/net/onrc/onos/intent/ConstrainedBFSTreeTest.java
new file mode 100644
index 0000000..f4413b8
--- /dev/null
+++ b/src/test/java/net/onrc/onos/intent/ConstrainedBFSTreeTest.java
@@ -0,0 +1,144 @@
+package net.onrc.onos.intent;
+
+import static org.junit.Assert.*;
+import net.onrc.onos.intent.IntentOperation.Operator;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Toshio Koide (t-koide@onlab.us)
+ */
+public class ConstrainedBFSTreeTest {
+ static long LOCAL_PORT = 0xFFFEL;
+
+ @Before
+ public void setUp() throws Exception {
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ }
+
+ @Test
+ public void testCreate() {
+ MockNetworkGraph graph = new MockNetworkGraph();
+ graph.createSampleTopology1();
+ ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L));
+ assertNotNull(tree);
+ }
+
+ @Test
+ public void testCreateConstrained() {
+ MockNetworkGraph graph = new MockNetworkGraph();
+ graph.createSampleTopology1();
+ PathIntentMap intents = new PathIntentMap();
+ ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 1000.0);
+ assertNotNull(tree);
+ }
+
+ @Test
+ public void testGetPath() {
+ MockNetworkGraph graph = new MockNetworkGraph();
+ graph.createSampleTopology1();
+ ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L));
+ Path path11 = tree.getPath(graph.getSwitch(1L));
+ Path path12 = tree.getPath(graph.getSwitch(2L));
+ Path path13 = tree.getPath(graph.getSwitch(3L));
+ Path path14 = tree.getPath(graph.getSwitch(4L));
+
+ assertNotNull(path11);
+ assertEquals(0, path11.size());
+
+ assertNotNull(path12);
+ assertEquals(1, path12.size());
+ assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path12.get(0));
+
+ assertNotNull(path13);
+ assertEquals(2, path13.size());
+ if (path13.get(0).getDst().getDpid() == 2L) {
+ assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path13.get(0));
+ assertEquals(new LinkEvent(graph.getLink(2L, 23L)), path13.get(1));
+ }
+ else {
+ assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path13.get(0));
+ assertEquals(new LinkEvent(graph.getLink(4L, 43L)), path13.get(1));
+ }
+
+ assertNotNull(path14);
+ assertEquals(1, path14.size());
+ assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path14.get(0));
+ }
+
+ @Test
+ public void testGetPathNull() {
+ MockNetworkGraph graph = new MockNetworkGraph();
+ graph.createSampleTopology1();
+ graph.removeLink(1L, 12L, 2L, 21L);
+ graph.removeLink(1L, 14L, 4L, 41L);
+ // now, there is no path from switch 1, but to switch1
+
+ ConstrainedBFSTree tree1 = new ConstrainedBFSTree(graph.getSwitch(1L));
+ Path path12 = tree1.getPath(graph.getSwitch(2L));
+ Path path13 = tree1.getPath(graph.getSwitch(3L));
+ Path path14 = tree1.getPath(graph.getSwitch(4L));
+
+ ConstrainedBFSTree tree2 = new ConstrainedBFSTree(graph.getSwitch(2L));
+ Path path21 = tree2.getPath(graph.getSwitch(1L));
+
+ assertNull(path12);
+ assertNull(path13);
+ assertNull(path14);
+ assertNotNull(path21);
+ assertEquals(1, path21.size());
+ assertEquals(new LinkEvent(graph.getLink(2L, 21L)), path21.get(0));
+ }
+
+ @Test
+ public void testGetConstrainedPath() {
+ MockNetworkGraph graph = new MockNetworkGraph();
+ graph.createSampleTopology1();
+ PathIntentMap intents = new PathIntentMap();
+ IntentOperationList intentOps = new IntentOperationList();
+
+ // create constrained shortest path intents that have the same source destination ports
+ ConstrainedShortestPathIntent intent1 = new ConstrainedShortestPathIntent(
+ "1", 1L, LOCAL_PORT, 0x111L, 2L, LOCAL_PORT, 0x222L, 600.0);
+ ConstrainedShortestPathIntent intent2 = new ConstrainedShortestPathIntent(
+ "2", 1L, LOCAL_PORT, 0x333L, 2L, LOCAL_PORT, 0x444L, 600.0);
+
+ // calculate path of the intent1
+ ConstrainedBFSTree tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+ Path path1 = tree.getPath(graph.getSwitch(2L));
+
+ assertNotNull(path1);
+ assertEquals(1, path1.size());
+ assertEquals(new LinkEvent(graph.getLink(1L, 12L)), path1.get(0));
+
+ PathIntent pathIntent1 = new PathIntent("pi1", path1, 600.0, intent1);
+ intentOps.add(Operator.ADD, pathIntent1);
+ intents.executeOperations(intentOps);
+
+ // calculate path of the intent2
+ tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+ Path path2 = tree.getPath(graph.getSwitch(2L));
+
+ assertNotNull(path2);
+ assertEquals(2, path2.size());
+ assertEquals(new LinkEvent(graph.getLink(1L, 14L)), path2.get(0));
+ assertEquals(new LinkEvent(graph.getLink(4L, 42L)), path2.get(1));
+
+ PathIntent pathIntent2 = new PathIntent("pi2", path2, 600.0, intent2);
+ intentOps.add(Operator.ADD, pathIntent2);
+ intents.executeOperations(intentOps);
+
+ // calculate path of the intent3
+ tree = new ConstrainedBFSTree(graph.getSwitch(1L), intents, 600.0);
+ Path path3 = tree.getPath(graph.getSwitch(2L));
+
+ assertNull(path3);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/intent/ConstrainedShortestPathIntentTest.java b/src/test/java/net/onrc/onos/intent/ConstrainedShortestPathIntentTest.java
index aba4c11..99fa0b3 100644
--- a/src/test/java/net/onrc/onos/intent/ConstrainedShortestPathIntentTest.java
+++ b/src/test/java/net/onrc/onos/intent/ConstrainedShortestPathIntentTest.java
@@ -1,6 +1,7 @@
package net.onrc.onos.intent;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import net.onrc.onos.ofcontroller.util.serializers.KryoFactory;
import org.junit.After;
import org.junit.Before;
@@ -23,21 +24,36 @@
}
@Test
- public void test() {
- Kryo kryo = new Kryo();
- Output output = new Output(1024);
-
+ public void testCreate() {
ConstrainedShortestPathIntent intent1 =
new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
+ assertEquals("1", intent1.getId());
+ assertEquals(2L, intent1.getSrcSwitchDpid());
+ assertEquals(3L, intent1.getSrcPortNumber());
+ assertEquals(4L, intent1.getSrcMac());
+ assertEquals(5L, intent1.getDstSwitchDpid());
+ assertEquals(6L, intent1.getDstPortNumber());
+ assertEquals(7L, intent1.getDstMac());
+ assertEquals(1000.0, intent1.getBandwidth(), 0.0);
+ }
+
+ @Test
+ public void testKryo() {
+ KryoFactory factory = new KryoFactory();
+ Kryo kryo = factory.newKryo();
+ Output output = new Output(1000);
+
+ ConstrainedShortestPathIntent intent1 =
+ new ConstrainedShortestPathIntent("1", 2L, 3L, 4L, 5L, 6L, 7L, 1000.0);
kryo.writeObject(output, intent1);
+
output.close();
+ byte bytes[] = output.toBytes();
- Input input = new Input(output.toBytes());
- ConstrainedShortestPathIntent intent2 =
- kryo.readObject(input, ConstrainedShortestPathIntent.class);
+ Input input = new Input(bytes);
+ ConstrainedShortestPathIntent intent2 = kryo.readObject(input, ConstrainedShortestPathIntent.class);
input.close();
-
assertEquals("1", intent2.getId());
assertEquals(2L, intent2.getSrcSwitchDpid());
assertEquals(3L, intent2.getSrcPortNumber());
diff --git a/src/test/java/net/onrc/onos/intent/MockNetworkGraph.java b/src/test/java/net/onrc/onos/intent/MockNetworkGraph.java
index 5ae7b13..9d85e6f 100644
--- a/src/test/java/net/onrc/onos/intent/MockNetworkGraph.java
+++ b/src/test/java/net/onrc/onos/intent/MockNetworkGraph.java
@@ -9,9 +9,15 @@
import net.onrc.onos.ofcontroller.networkgraph.SwitchImpl;
/**
+ * A mock class of NetworkGraph.
+ * This class should be used only by test codes.
+ *
* @author Toshio Koide (t-koide@onlab.us)
*/
public class MockNetworkGraph extends NetworkGraphImpl {
+ public static Long LOCAL_PORT = 0xFFFEL;
+ public SwitchImpl sw1, sw2, sw3, sw4;
+
class DetachableLinkImpl extends LinkImpl {
public DetachableLinkImpl(NetworkGraph graph, Port srcPort, Port dstPort) {
super(graph, srcPort, dstPort);
@@ -25,7 +31,6 @@
SwitchImpl sw = new SwitchImpl(this, switchId);
this.putSwitch(sw);
return sw;
-
}
public Link addLink(Long srcDpid, Long srcPortNo, Long dstDpid, Long dstPortNo) {
@@ -43,34 +48,41 @@
return links;
}
- public void createSampleTopology() {
- // add 10 switches (24 ports switch)
- for (Long dpid=1L; dpid<10L; dpid++) {
- SwitchImpl sw = (SwitchImpl) addSwitch(dpid);
- for (Long j=1L; j<=24L; j++) {
- sw.addPort(j);
- }
- }
+ /**
+ * create sample topology of 4 switches and 5 bidirectional links.
+ * <pre>
+ * [1] --- [2]
+ * | / |
+ * | / |
+ * [4] --- [3]
+ * </pre>
+ */
+ public void createSampleTopology1() {
+ sw1 = (SwitchImpl) addSwitch(1L);
+ sw1.addPort(LOCAL_PORT);
+ sw2 = (SwitchImpl) addSwitch(2L);
+ sw2.addPort(LOCAL_PORT);
+ sw3 = (SwitchImpl) addSwitch(3L);
+ sw3.addPort(LOCAL_PORT);
+ sw4 = (SwitchImpl) addSwitch(4L);
+ sw4.addPort(LOCAL_PORT);
- // add loop path
- addBidirectionalLinks(1L, 1L, 2L, 2L);
- addBidirectionalLinks(2L, 1L, 3L, 2L);
- addBidirectionalLinks(3L, 1L, 4L, 2L);
- addBidirectionalLinks(4L, 1L, 5L, 2L);
- addBidirectionalLinks(5L, 1L, 6L, 2L);
- addBidirectionalLinks(6L, 1L, 7L, 2L);
- addBidirectionalLinks(7L, 1L, 8L, 2L);
- addBidirectionalLinks(8L, 1L, 9L, 2L);
- addBidirectionalLinks(9L, 1L, 1L, 2L);
+ sw1.addPort(12L); // sw1 -> sw2
+ sw1.addPort(14L); // sw1 -> sw4
+ sw2.addPort(21L); // sw2 -> sw1
+ sw2.addPort(23L); // sw2 -> sw3
+ sw2.addPort(24L); // sw2 -> sw4
+ sw3.addPort(32L); // sw3 -> sw2
+ sw3.addPort(34L); // sw3 -> sw4
+ sw4.addPort(41L); // sw4 -> sw1
+ sw4.addPort(42L); // sw4 -> sw2
+ sw4.addPort(43L); // sw4 -> sw3
- // add other links
- addBidirectionalLinks(1L, 3L, 5L, 3L);
- addBidirectionalLinks(2L, 4L, 5L, 4L);
- addBidirectionalLinks(2L, 5L, 7L, 5L);
- addBidirectionalLinks(3L, 6L, 7L, 6L);
- addBidirectionalLinks(3L, 7L, 8L, 7L);
- addBidirectionalLinks(3L, 8L, 9L, 8L);
- addBidirectionalLinks(4L, 9l, 9L, 9L);
+ addBidirectionalLinks(1L, 12L, 2L, 21L);
+ addBidirectionalLinks(2L, 23L, 3L, 32L);
+ addBidirectionalLinks(3L, 34L, 4L, 43L);
+ addBidirectionalLinks(4L, 41L, 1L, 14L);
+ addBidirectionalLinks(2L, 24L, 4L, 42L);
// set capacity of all links to 1000Mbps
for (Link link: getLinks()) {
diff --git a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
index 0c1746f..f24fc99 100755
--- a/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
+++ b/src/test/java/net/onrc/onos/intent/runtime/UseCaseTest.java
@@ -54,11 +54,13 @@
@SuppressWarnings("rawtypes")
private IEventChannel eventChannel;
+ private static Long LOCAL_PORT = 0xFFFEL;
+
@SuppressWarnings("unchecked")
@Before
public void setUp() throws Exception {
MockNetworkGraph graph = new MockNetworkGraph();
- graph.createSampleTopology();
+ graph.createSampleTopology1();
g = graph;
datagridService = createMock(IDatagridService.class);
@@ -124,9 +126,9 @@
public void createShortestPaths() throws FloodlightModuleException {
// create shortest path intents
IntentOperationList opList = new IntentOperationList();
- opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 20L, 1L, 4L, 20L, 4L));
- opList.add(Operator.ADD, new ShortestPathIntent("2", 2L, 20L, 2L, 6L, 20L, 5L));
- opList.add(Operator.ADD, new ShortestPathIntent("3", 4L, 20L, 3L, 8L, 20L, 6L));
+ opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
// compile high-level intent operations into low-level intent operations (calculate paths)
PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
@@ -147,11 +149,11 @@
public void createConstrainedShortestPaths() throws FloodlightModuleException {
// create constrained shortest path intents
IntentOperationList opList = new IntentOperationList();
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 20L, 1L, 4L, 20L, 17L, 400.0));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 2L, 20L, 2L, 6L, 20L, 18L, 400.0));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("3", 4L, 20L, 3L, 8L, 20L, 19L, 400.0));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("4", 3L, 20L, 4L, 8L, 20L, 20L, 400.0));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 4L, 20L, 5L, 8L, 20L, 21L, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));
// compile high-level intent operations into low-level intent operations (calculate paths)
PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
@@ -172,11 +174,11 @@
public void createMixedShortestPaths() throws FloodlightModuleException {
// create constrained & best effort shortest path intents
IntentOperationList opList = new IntentOperationList();
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 20L, 1L, 4L, 20L, 6L, 600.0));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 2L, 20L, 2L, 6L, 20L, 7L, 600.0));
- opList.add(Operator.ADD, new ShortestPathIntent("3", 4L, 20L, 3L, 8L, 20L, 8L));
- opList.add(Operator.ADD, new ShortestPathIntent("4", 4L, 20L, 4L, 8L, 20L, 9L));
- opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 4L, 20L, 5L, 8L, 20L, 10L, 600.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT, 400.0));
+ opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 24L, LOCAL_PORT, 4L, 42L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ShortestPathIntent("4", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ConstrainedShortestPathIntent("5", 3L, 34L, LOCAL_PORT, 4L, 43L, LOCAL_PORT, 400.0));
// compile high-level intent operations into low-level intent operations (calculate paths)
PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
@@ -206,9 +208,9 @@
// create shortest path intents
IntentOperationList opList = new IntentOperationList();
- opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 20L, 1L, 4L, 20L, 4L));
- opList.add(Operator.ADD, new ShortestPathIntent("2", 2L, 20L, 2L, 6L, 20L, 5L));
- opList.add(Operator.ADD, new ShortestPathIntent("3", 4L, 20L, 3L, 8L, 20L, 6L));
+ opList.add(Operator.ADD, new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L, LOCAL_PORT));
+ opList.add(Operator.ADD, new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L, LOCAL_PORT));
// compile high-level intent operations into low-level intent operations (calculate paths)
PathCalcRuntimeModule runtime1 = new PathCalcRuntimeModule();
@@ -237,10 +239,10 @@
runtime1.getPathIntents().changeStates(states);
// link down
- ((MockNetworkGraph)g).removeLink(1L, 2L, 9L, 1L); // This link is used by the intent "1"
- ((MockNetworkGraph)g).removeLink(9L, 1L, 1L, 2L);
- LinkEvent linkEvent1 = new LinkEvent(1L, 2L, 9L, 1L);
- LinkEvent linkEvent2 = new LinkEvent(9L, 1L, 1L, 2L);
+ ((MockNetworkGraph)g).removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
+ ((MockNetworkGraph)g).removeLink(2L, 21L, 1L, 12L);
+ LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
+ LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
removedLinkEvents.clear();
removedLinkEvents.add(linkEvent1);
removedLinkEvents.add(linkEvent2);
diff --git a/start-rest.sh b/start-rest.sh
index 94bbd46..a79a415 100755
--- a/start-rest.sh
+++ b/start-rest.sh
@@ -1,13 +1,13 @@
#! /bin/bash
# Change this accordingly
-ONOSDIR=${HOME}/ONOS
+ONOSDIR=${ONOS_HOME:-${HOME}/ONOS}
script_name="topology_rest.py"
#######################
WEBDIR=${ONOSDIR}/web
restscript=${WEBDIR}/$script_name
-LOGDIR=${ONOSDIR}/onos-logs
+LOGDIR=${ONOS_LOGDIR:-${ONOSDIR}/onos-logs}
REST_LOG="${LOGDIR}/rest.`hostname`.log"
#######################
diff --git a/web/get_datagrid_ngevents.py b/web/get_datagrid_ngevents.py
index 34c3338..f7ef7d4 100755
--- a/web/get_datagrid_ngevents.py
+++ b/web/get_datagrid_ngevents.py
@@ -33,7 +33,7 @@
# Sample output:
def print_datagrid_map(parsedResult):
- print '%s' % (parsedResult)
+ print '%s' % (parsedResult),
def get_datagrid_map():
try:
diff --git a/web/get_network_graph.py b/web/get_network_graph.py
new file mode 100755
index 0000000..375e5ff
--- /dev/null
+++ b/web/get_network_graph.py
@@ -0,0 +1,149 @@
+#! /usr/bin/env python
+# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
+
+#
+# Get Network Graph Information:
+# - Switches
+# - Links
+# - Shortest Path
+#
+
+import pprint
+import os
+import sys
+import subprocess
+import json
+import collections
+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/onos/ng/links/json ")
+# @app.route("/wm/onos/ng/switches/json ")
+# @app.route("/wm/onos/ng/shortest-path/<src-dpid>/<dst-dpid>/json ")
+# Sample output:
+
+def print_parsed_result(parsedResult):
+ print '%s' % (parsedResult),
+
+def get_network_switches():
+ try:
+ command = "curl -s \"http://%s:%s/wm/onos/ng/switches/json\"" % (ControllerIP, ControllerPort)
+ debug("get_network_switches %s" % command)
+
+ result = os.popen(command).read()
+ debug("result %s" % result)
+ if len(result) == 0:
+ print "No Switches found"
+ return;
+
+ # parsedResult = result
+ # parsedResult = json.loads(result)
+ parsedResult = json.dumps(json.loads(result), indent=4)
+ debug("parsed %s" % parsedResult)
+ except:
+ log_error("Controller IF has issue")
+ exit(1)
+
+ print_parsed_result(parsedResult)
+
+def get_network_links():
+ try:
+ command = "curl -s \"http://%s:%s/wm/onos/ng/links/json\"" % (ControllerIP, ControllerPort)
+ debug("get_network_links %s" % command)
+
+ result = os.popen(command).read()
+ debug("result %s" % result)
+ if len(result) == 0:
+ print "No Links found"
+ return;
+
+ # parsedResult = result
+ # parsedResult = json.loads(result)
+ parsedResult = json.dumps(json.loads(result), indent=4)
+ debug("parsed %s" % parsedResult)
+ except:
+ log_error("Controller IF has issue")
+ exit(1)
+
+ print_parsed_result(parsedResult)
+
+def get_network_shortest_path(src_dpid, dst_dpid):
+ try:
+ command = "curl -s \"http://%s:%s/wm/onos/ng/shortest-path/%s/%s/json\"" % (ControllerIP, ControllerPort, src_dpid, dst_dpid)
+ debug("get_network_switches %s" % command)
+
+ result = os.popen(command).read()
+ debug("result %s" % result)
+ if len(result) == 0:
+ print "No Path found"
+ return;
+
+ # parsedResult = result
+ parsedResult = json.loads(result, object_pairs_hook=collections.OrderedDict)
+ parsedResult = json.dumps(parsedResult, indent=4)
+ debug("parsed %s" % parsedResult)
+ except:
+ log_error("Controller IF has issue")
+ exit(1)
+
+ print_parsed_result(parsedResult)
+
+
+if __name__ == "__main__":
+ usage_msg1 = "Usage:\n"
+ usage_msg2 = "%s <arguments> : Print network information\n" % (sys.argv[0])
+ usage_msg3 = " Valid element names:\n"
+ usage_msg4 = " all : Print all network elements\n"
+ usage_msg5 = " switches : Print all switches and ports\n"
+ usage_msg6 = " links : Print all links\n"
+ usage_msg7 = " shortest-path <src-dpid> <dst-dpid> : Print shortest-path\n"
+ usage_msg8 = " (links between <src-dpid> and <dst-dpid>)\n"
+ usage_msg = usage_msg1 + usage_msg2 + usage_msg3 + usage_msg4 + usage_msg5
+ usage_msg = usage_msg + usage_msg6 + usage_msg7 + usage_msg8
+
+ # 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)
+
+ if (sys.argv[1] != "all" and sys.argv[1] != "switches" and sys.argv[1] != "links" and sys.argv[1] != "shortest-path"):
+ log_error(usage_msg)
+ exit(1)
+
+ if (sys.argv[1] == "shortest-path"):
+ if len(sys.argv) < 4:
+ log_error(usage_msg)
+ exit(1)
+
+ # Do the work
+ if (sys.argv[1] == "all" or sys.argv[1] == "switches"):
+ get_network_switches()
+ if (sys.argv[1] == "all" or sys.argv[1] == "links"):
+ get_network_links()
+ if (sys.argv[1] == "shortest-path"):
+ get_network_shortest_path(sys.argv[2], sys.argv[3])
diff --git a/web/rest-intent/intent-installer.rb b/web/rest-intent/intent-installer.rb
index b2d21d8..41361be 100755
--- a/web/rest-intent/intent-installer.rb
+++ b/web/rest-intent/intent-installer.rb
@@ -72,6 +72,9 @@
opts.on('b', '--bulk_limit bulk_limit', 'bulk request upto this limit') do |bulk_limit|
options[:bulk_limit] = bulk_limit
end
+ opts.on('f', '--freeze_intents', 'freeze dont reroute intents') do
+ options[:freeze] = "F"
+ end
opts.on('-h', '--help', 'Display help') do
puts opts
exit
@@ -173,13 +176,15 @@
@port ||= 8080
@bulk_limit = options[:bulk_limit]
@bulk_limit ||= 10000
+ @freeze = options[:freeze]
+ @freeze ||= ""
end
def _create_intent json_intents
(0...@max_switches).each do |idx|
intent = {
- :intent_id => "#{@intent_id}",
+ :intent_id => "#{@freeze}#{@intent_id}",
:intent_type => @intent_type,
:intent_op => @intent_op,
:srcSwitch => "258".to_s,
diff --git a/web/topology_rest_napi.py b/web/topology_rest_napi.py
index 45fc814..e16c197 100755
--- a/web/topology_rest_napi.py
+++ b/web/topology_rest_napi.py
@@ -5,6 +5,7 @@
from flask import Flask, json, Response, render_template, make_response, request
## Global Var for ON.Lab local REST ##
+# The GUI can be accessed at <this_host>:9000/onos-topology.html
RestIP="localhost"
RestPort=8080
ONOS_DEFAULT_HOST="localhost" ;# Has to set if LB=False