basic iperf data display
diff --git a/web/ons-demo/css/layout.default.css b/web/ons-demo/css/layout.default.css
index 018e728..5e1f1ce 100644
--- a/web/ons-demo/css/layout.default.css
+++ b/web/ons-demo/css/layout.default.css
@@ -76,6 +76,15 @@
 .iperf {
 	width: 100%;
 	-webkit-box-flex: 1.0;
+	position: relative;
+	display: -webkit-box;
+}
+
+.iperf-container {
+	position: absolute;
+	top: 0px;
+	height: 100%;
+	width: 100%;
 }
 
 #controllers {
diff --git a/web/ons-demo/css/skin.default.css b/web/ons-demo/css/skin.default.css
index 1ce4897..1d656b0 100644
--- a/web/ons-demo/css/skin.default.css
+++ b/web/ons-demo/css/skin.default.css
@@ -145,6 +145,12 @@
 	border-top: 1px solid #AAA;
 }
 
+path.iperfdata {
+	fill: none;
+	stroke-width: 2px;
+	stroke: rgba(255, 255, 255, .75);
+}
+
 #flowChooser {
 	pointer-events: none;
 	background-color: rgba(0, 0, 0, .25);
diff --git a/web/ons-demo/js/app.js b/web/ons-demo/js/app.js
index c150b9f..28e4da7 100644
--- a/web/ons-demo/js/app.js
+++ b/web/ons-demo/js/app.js
@@ -153,6 +153,16 @@
 		row.append('div').classed('dstDPID', true);
 		row.append('div').classed('iperf', true);
 
+		row.select('.iperf')
+			.append('div')
+			.attr('class', 'iperf-container')
+			.append('svg:svg')
+			.attr('viewBox', '0 0 1000 32')
+			.attr('preserveAspectRatio', 'none')
+			.append('svg:g')
+			.append('svg:path')
+			.attr('class', 'iperfdata');
+
 		row.on('mouseover', function (d) {
 			if (d) {
 				var path = document.getElementById(makeFlowKey(d));
@@ -164,11 +174,16 @@
 				var path = document.getElementById(makeFlowKey(d));
 				d3.select(path).classed('highlight', false);
 			}
-		})
+		});
 	}
 
 	function rowUpdate(d) {
 		var row = d3.select(this);
+		row.attr('id', function (d) {
+			if (d) {
+				return makeSelectedFlowKey(d);
+			}
+		});
 		row.select('.deleteFlow').on('click', function () {
 			selectedFlows[selectedFlows.indexOf(d)] = null;
 			updateSelectedFlows();
@@ -234,7 +249,7 @@
 
 // TODO: cancel the interval when the flow is desel
 function startIPerfForFlow(flow) {
-	var duration = 10; // seconds
+	var duration = 10000; // seconds
 	var interval = 100; // ms. this is defined by the server
 	var updateRate = 1000; // ms
 
@@ -243,9 +258,33 @@
 		startIPerf(flow, duration, updateRate/interval);
 		flow.iperfInterval = setInterval(function () {
 			getIPerfData(flow, function (data) {
-				console.log(data);
+				try {
+					var iperfData = JSON.parse(data);
+					// if the data is fresh
+					if (flow.iperfData && iperfData.timeStamp != flow.iperfData.timestamp) {
+						var iperfPath = d3.select(document.getElementById(makeSelectedFlowKey(flow))).select('path');
+						var pts = [];
+						var i;
+						for (i = 0; i < iperfData.samples.length; i += 1) {
+							var sample = iperfData.samples[i];
+							var height = 32 * sample/100000000;
+							if (height > 32)
+								height = 32;
+							pts.push({
+								x: i * 1000/(iperfData.samples.length-1),
+								y: height
+							})
+						}
+						iperfPath.attr('d', line(pts));
+
+					}
+					flow.iperfData = iperfData;
+				} catch (e) {
+					console.log('bad iperf data: ' + data);
+				}
+//				console.log(data);
 			});
-		});
+		}, updateRate);
 	}
 }
 
@@ -502,6 +541,10 @@
 	return flow.dataPath.srcPort.dpid.value + '=>' + flow.dataPath.dstPort.dpid.value;
 }
 
+function makeSelectedFlowKey(flow) {
+	return 'S' + makeFlowKey(flow);
+}
+
 function createLinkMap(links) {
 	var linkMap = {};
 	links.forEach(function (link) {
diff --git a/web/ons-demo/js/controller.js b/web/ons-demo/js/controller.js
index 929e21b..c7c80ec 100644
--- a/web/ons-demo/js/controller.js
+++ b/web/ons-demo/js/controller.js
@@ -8,7 +8,7 @@
 			if (cb) {
 				cb(result);
 			}
-			console.log(result);
+//			console.log(result);
 		}
 	});
 }
@@ -43,7 +43,7 @@
 	},
 	startIPerfCmd: function (flow, duration, numSamples) {
 		var flowId = parseInt(flow.flowId.value, 16);
-		var url = '/proxy/guid/iperf/start/' + [flowId, duration, numSamples].join('/');
+		var url = '/proxy/gui/iperf/start/' + [flowId, duration, numSamples].join('/');
 		callURL(url)
 	},
 	getIPerfDataCmd: function (flow, cb) {