Merge remote-tracking branch 'upstream/master'
diff --git a/web/ons-demo/RELEASE_NOTES.txt b/web/ons-demo/RELEASE_NOTES.txt
index bfe6059..369e9c4 100644
--- a/web/ons-demo/RELEASE_NOTES.txt
+++ b/web/ons-demo/RELEASE_NOTES.txt
@@ -1,3 +1,7 @@
+** April 9, 2013 **
+- display number of flows for each core<->core link
+- graphics tweaks
+
** April 8, 2013 **
- map view
- onos nodes at top
diff --git a/web/ons-demo/css/skin.default.css b/web/ons-demo/css/skin.default.css
index f6086a3..f9aa830 100644
--- a/web/ons-demo/css/skin.default.css
+++ b/web/ons-demo/css/skin.default.css
@@ -106,6 +106,34 @@
border-bottom: 1px solid #AAA;;
}
+#onos {
+ background-color: #333;
+}
+
+#cluster-label {
+ font-size: 22px;
+ display: -webkit-box;
+ -webkit-box-align: center;
+ padding-left: .5em;
+ padding-right: .5em;
+ color: #EEE;
+}
+
+#actions {
+ padding-right: .25em;
+ padding-left: .25em;
+ border-left: 1px solid white;
+ display: -webkit-box;
+ -webkit-box-align: center;
+}
+
+#controllers {
+ padding: .25em;
+ background-color: black;
+ margin: .25em;
+ border-radius: 8px;
+}
+
#flowChooser .selectedFlow {
background-color: rgba(255, 255, 255, .75);
color: black;
@@ -208,6 +236,7 @@
border: 1px solid #444;
color: white;
position: relative;
+ border-radius: 8px;
}
.controller:hover {
@@ -395,19 +424,21 @@
.action {
margin: .25em;
- padding: .25em;
- padding-left: 1em;
- padding-right: 1em;
- border: 1px solid #AAA;
+ border: 2px solid #AAA;
+ height: 2em;
+ width: 2em;
background-color: #444;
display: -webkit-box;
-webkit-box-pack: center;
-webkit-box-align: center;
- color: white;
+ color: #AAA;
+ border-radius: 50%;
+ -webkit-box-sizing: border-box;
}
.action:hover {
- border: 1px solid #FFF;
+ border: 2px solid #FFF;
+ color: white;
}
.action:active {
@@ -437,3 +468,8 @@
stroke: black;
}
+.flowCount {
+ font-size: 20px;
+ fill: rgba(255, 255, 255, .75);
+}
+
diff --git a/web/ons-demo/index.html b/web/ons-demo/index.html
index ca930ec..12ac5f9 100644
--- a/web/ons-demo/index.html
+++ b/web/ons-demo/index.html
@@ -20,11 +20,13 @@
</div>
<div id='onos'>
+ <div id='cluster-label'>ONOS Node Cluster</div>
<div id='controllers'></div>
<div id='actions'>
- <div id='action-all' class='action'>ALL</div>
- <div id='action-local' class='action'>LOCAL</div>
- <div id='action-scale' class='action'>SCALE</div>
+ <div id='action-all' class='action'>A</div>
+ <div id='action-local' class='action'>1</div>
+ <div id='action-scale' class='action'>S</div>
+ <div id='action-reset' class='action'>R</div>
</div>
</div>
diff --git a/web/ons-demo/js/init.js b/web/ons-demo/js/init.js
index dd11bf8..a412440 100644
--- a/web/ons-demo/js/init.js
+++ b/web/ons-demo/js/init.js
@@ -25,5 +25,9 @@
alert('scale')
});
+ d3.select('#action-reset').on('click', function () {
+ alert('reset')
+ });
+
createTopologyView(cb);
}
diff --git a/web/ons-demo/js/map.js b/web/ons-demo/js/map.js
index 7662aaf..3849b8d 100644
--- a/web/ons-demo/js/map.js
+++ b/web/ons-demo/js/map.js
@@ -120,6 +120,64 @@
});
}
+function drawCoreFlowCounts() {
+ var links = {};
+ model.links.forEach(function (l) {
+ links[makeLinkKey(l)] = l;
+ });
+
+ var flowCounts = [];
+ countCoreLinkFlows().forEach(function (count) {
+ var l = links[count.key];
+ if (l) {
+ var src = d3.select(document.getElementById(l['src-switch']));
+ var dst = d3.select(document.getElementById(l['dst-switch']));
+
+ if (!src.empty() && !dst.empty()) {
+ var x1 = parseFloat(src.attr('x'));
+ var x2 = parseFloat(dst.attr('x'));
+ var y1 = parseFloat(src.attr('y'));
+ var y2 = parseFloat(dst.attr('y'));
+
+ var slope = (y2 - y1)/(x2 - x1);
+
+ var offset = 15;
+ var xOffset = offset;
+ var yOffset = slope*offset;
+
+ var d = Math.sqrt(xOffset*xOffset + yOffset*yOffset);
+ var scaler = offset/d;
+
+ count.pt = {
+ x: x1 + (x2 - x1)/2 + xOffset*scaler,
+ y: y1 + (y2 - y1)/2 + yOffset*scaler
+ }
+ }
+ flowCounts.push(count);
+ }
+ });
+
+
+ var counts = linksLayer.selectAll('.flowCount').data(flowCounts, function (d) {
+ return d.key;
+ });
+
+ counts.enter().append('svg:text')
+ .attr('class', 'flowCount')
+ .attr('x', function (d) {
+ return d.pt.x;
+ })
+ .attr('y', function (d) {
+ return d.pt.y;
+ });
+
+ counts.text(function (d) {
+ return d.value;
+ });
+
+ counts.exit().remove();
+}
+
function drawLinkLines() {
// key on link dpids since these will come/go during demo
@@ -163,6 +221,7 @@
linkLines.exit().remove();
}
+
var fanOutAngles = {
aggregation: 100,
edge: 5
@@ -252,9 +311,13 @@
g.append('svg:text')
.classed('label', true)
.text(d.label)
- .attr("text-anchor", "end")
- .attr('x', d.x - width)
- .attr('y', d.y - width);
+ .attr("text-anchor", function (d) {
+ return d.x > 500 ? "end" : "start";
+ })
+ .attr('x', function (d) {
+ return d.x > 500 ? d.x - width*.8 : d.x + width*.8;
+ })
+ .attr('y', d.y - width*.8);
}
}
@@ -333,6 +396,8 @@
drawLinkLines();
+ drawCoreFlowCounts();
+
labelsEnter(switches);
}
diff --git a/web/ons-demo/js/model.js b/web/ons-demo/js/model.js
index f251c87..df4a751 100644
--- a/web/ons-demo/js/model.js
+++ b/web/ons-demo/js/model.js
@@ -5,13 +5,20 @@
edgeSwitches: [],
aggregationSwitches: [],
coreSwitches: [],
- flows: results.flows,
+ flows: [],
controllers: results.controllers,
activeControllers: results.activeControllers,
links: results.links,
configuration: results.configuration
};
+ // remove bad flows;
+ results.flows.forEach(function (f) {
+ if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
+ model.flows.push(f);
+ }
+ })
+
// sort the switches
results.switches.sort(function (a, b) {
var aA = a.dpid.split(':');
diff --git a/web/ons-demo/js/utils.js b/web/ons-demo/js/utils.js
index be7cf53..65117f5 100644
--- a/web/ons-demo/js/utils.js
+++ b/web/ons-demo/js/utils.js
@@ -81,24 +81,27 @@
function updateHeader() {
d3.select('#lastUpdate').text(new Date());
- var count = 0;
+ var activeSwitchCount = 0;
model.edgeSwitches.forEach(function (s) {
if (s.state === 'ACTIVE') {
- count += 1;
+ activeSwitchCount += 1;
}
});
model.aggregationSwitches.forEach(function (s) {
if (s.state === 'ACTIVE') {
- count += 1;
+ activeSwitchCount += 1;
}
});
model.coreSwitches.forEach(function (s) {
if (s.state === 'ACTIVE') {
- count += 1;
+ activeSwitchCount += 1;
}
});
- d3.select('#activeSwitches').text(count);
+ d3.select('#activeSwitches').text(activeSwitchCount);
+
+
+
d3.select('#activeFlows').text(model.flows.length);
}
@@ -153,4 +156,51 @@
return svg;
}
+/***************************************************************************************************
+counts the number of flows which pass through each core<->core link
+***************************************************************************************************/
+function countCoreLinkFlows() {
+ var allCounts = {};
+ model.flows.forEach(function (f) {
+ if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
+ var flowEntries = f.dataPath.flowEntries;
+ var i;
+
+ for (i = 0; i < flowEntries.length - 1; i += 1) {
+ var linkKey = flowEntries[i].dpid.value + '=>' + flowEntries[i+1].dpid.value;
+ if (!allCounts[linkKey]) {
+ allCounts[linkKey] = 1;
+ } else {
+ allCounts[linkKey] += 1;
+ }
+ }
+ }
+ });
+
+ var coreCounts = {};
+ var i, j;
+ for (i = 0; i < model.coreSwitches.length - 1; i += 1) {
+ for (j = i + 1; j < model.coreSwitches.length; j += 1) {
+ var si = model.coreSwitches[i];
+ var sj = model.coreSwitches[j];
+ var key1 = si.dpid + '=>' + sj.dpid;
+ var key2 = sj.dpid + '=>' + si.dpid;
+ var linkCount = 0;
+ if (allCounts[key1]) {
+ linkCount += allCounts[key1];
+ }
+ if (allCounts[key2]) {
+ linkCount += allCounts[key2];
+ }
+
+ coreCounts[key1] = linkCount;
+ }
+ }
+
+ return d3.entries(coreCounts);
+}
+
+
+
+