Add backend support for collecting the time it takes to
install each Flow.
The new REST call is "wm/flow/measurement-get-per-flow-install-time/json"
The result is returned in a multi-line string with the following format
per line:
ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
index 1020eab..8aec20f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
@@ -99,6 +99,7 @@
private long measurementStartTimeProcessingPaths = 0;
private long measurementEndTimeProcessingPaths = 0;
Map<Long, ?> measurementShortestPathTopo = null;
+ private String measurementPerFlowStr = new String();
/** The logger. */
private static Logger log = LoggerFactory.getLogger(FlowManager.class);
@@ -815,7 +816,7 @@
thread.start();
}
- // Want for all threads to complete
+ // Wait for all threads to complete
for (Thread thread : threads) {
try {
thread.join();
@@ -1960,12 +1961,39 @@
*/
@Override
public boolean measurementInstallPaths(Integer numThreads) {
- List<Thread> threads = new LinkedList<Thread>();
-
// Create a copy of the Flow Paths to install
final ConcurrentLinkedQueue<FlowPath> measurementProcessingPaths =
new ConcurrentLinkedQueue<FlowPath>(measurementStoredPaths);
+ /**
+ * A Thread-wrapper class for executing the threads and collecting
+ * the measurement data.
+ */
+ class MyThread extends Thread {
+ public long[] execTime = new long[2000];
+ public int samples = 0;
+ public int threadId = -1;
+ @Override
+ public void run() {
+ while (true) {
+ FlowPath flowPath = measurementProcessingPaths.poll();
+ if (flowPath == null)
+ return;
+ // Install the Flow Path
+ FlowId flowId = new FlowId();
+ String dataPathSummaryStr =
+ flowPath.dataPath().dataPathSummary();
+ long startTime = System.nanoTime();
+ addFlow(flowPath, flowId, dataPathSummaryStr);
+ long endTime = System.nanoTime();
+ execTime[samples] = endTime - startTime;
+ samples++;
+ }
+ }
+ };
+
+ List<MyThread> threads = new LinkedList<MyThread>();
+
log.debug("Measurement Installing {} flows",
measurementProcessingPaths.size());
@@ -1973,20 +2001,8 @@
// Create the threads to install the Flow Paths
//
for (int i = 0; i < numThreads; i++) {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- while (true) {
- FlowPath flowPath = measurementProcessingPaths.poll();
- if (flowPath == null)
- return;
- // Install the Flow Path
- FlowId flowId = new FlowId();
- String dataPathSummaryStr =
- flowPath.dataPath().dataPathSummary();
- addFlow(flowPath, flowId, dataPathSummaryStr);
- }
- }}, "Measurement Add Flow Path");
+ MyThread thread = new MyThread();
+ thread.threadId = i;
threads.add(thread);
}
@@ -1999,7 +2015,7 @@
thread.start();
}
- // Want for all threads to complete
+ // Wait for all threads to complete
for (Thread thread : threads) {
try {
thread.join();
@@ -2011,6 +2027,20 @@
// Record the end of processing
measurementEndTimeProcessingPaths = System.nanoTime();
+ //
+ // Prepare the string with measurement data per each Flow Path
+ // installation.
+ // The string is multiple lines: one line per Flow Path installation:
+ // ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+ //
+ measurementPerFlowStr = new String();
+ String eol = System.getProperty("line.separator");
+ for (MyThread thread : threads) {
+ for (int i = 0; i < thread.samples; i++) {
+ measurementPerFlowStr += "ThreadAndTimePerFlow " + thread.threadId + " " + numThreads + " " + thread.execTime[i] + eol;
+ }
+ }
+
return true;
}
@@ -2027,6 +2057,17 @@
}
/**
+ * Get the measurement install time per Flow.
+ *
+ * @return a multi-line string with the following format per line:
+ * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+ */
+ @Override
+ public String measurementGetPerFlowInstallTime() {
+ return new String(measurementPerFlowStr);
+ }
+
+ /**
* Clear the path flows stored for measurement purpose.
*
* @return true on success, otherwise false.
@@ -2037,6 +2078,7 @@
topoRouteService.dropShortestPathTopo(measurementShortestPathTopo);
measurementStartTimeProcessingPaths = 0;
measurementEndTimeProcessingPaths = 0;
+ measurementPerFlowStr = new String();
return true;
}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
index 5e0db35..6c19fd0 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
@@ -145,6 +145,14 @@
public Long measurementGetInstallPathsTimeNsec();
/**
+ * Get the measurement install time per Flow.
+ *
+ * @return a multi-line string with the following format per line:
+ * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+ */
+ public String measurementGetPerFlowInstallTime();
+
+ /**
* Clear the path flows stored for measurement purpose.
*
* @return true on success, otherwise false.
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java b/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
index 9fa5e63..fd9a319 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
@@ -25,6 +25,7 @@
router.attach("/measurement-store-path/json", MeasurementStorePathFlowResource.class);
router.attach("/measurement-install-paths/{num-threads}/json", MeasurementInstallPathsFlowResource.class);
router.attach("/measurement-get-install-paths-time-nsec/json", MeasurementGetInstallPathsTimeNsecFlowResource.class);
+ router.attach("/measurement-get-per-flow-install-time/json", MeasurementGetPerFlowInstallTimeFlowResource.class);
router.attach("/measurement-clear-all-paths/json", MeasurementClearAllPathsFlowResource.class);
return router;
}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetPerFlowInstallTimeFlowResource.java b/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetPerFlowInstallTimeFlowResource.java
new file mode 100644
index 0000000..adaecc8
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetPerFlowInstallTimeFlowResource.java
@@ -0,0 +1,37 @@
+package net.floodlightcontroller.flowcache.web;
+
+import net.floodlightcontroller.flowcache.IFlowService;
+import net.floodlightcontroller.util.FlowId;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MeasurementGetPerFlowInstallTimeFlowResource extends ServerResource {
+ protected static Logger log = LoggerFactory.getLogger(MeasurementGetPerFlowInstallTimeFlowResource.class);
+
+ @Get("json")
+ public String retrieve() {
+ String result = null;
+
+ IFlowService flowService =
+ (IFlowService)getContext().getAttributes().
+ get(IFlowService.class.getCanonicalName());
+
+ if (flowService == null) {
+ log.debug("ONOS Flow Service not found");
+ return result;
+ }
+
+ // Extract the arguments
+
+ // Process the request
+ result = flowService.measurementGetPerFlowInstallTime();
+
+ log.debug("Measurement Get Install Paths Time (nsec): " + result);
+
+ return result;
+ }
+}