blob: d7220c55d64972d5ca547814edc3c6ea6e0192cb [file] [log] [blame]
Paul Greyson7a300822013-04-09 12:57:49 -07001/***************************************************************************************************
2extract url parameters into a map
3***************************************************************************************************/
Paul Greysonbcd3c772013-03-21 13:16:44 -07004function parseURLParameters() {
5 var parameters = {};
6
7 var search = location.href.split('?')[1];
8 if (search) {
9 search.split('&').forEach(function (param) {
10 var key = param.split('=')[0];
11 var value = param.split('=')[1];
12 parameters[key] = decodeURIComponent(value);
13 });
14 }
15
16 return parameters;
Paul Greyson5cc35f02013-03-28 10:07:36 -070017}
18
Paul Greyson7a300822013-04-09 12:57:49 -070019/***************************************************************************************************
20convenience function for moving an SVG element to the front so that it draws on top
21***************************************************************************************************/
22d3.selection.prototype.moveToFront = function() {
23 return this.each(function(){
24 this.parentNode.appendChild(this);
25 });
26};
27
28/***************************************************************************************************
29standard function for generating the 'd' attribute for a path from an array of points
30***************************************************************************************************/
31var line = d3.svg.line()
32 .x(function(d) {
33 return d.x;
34 })
35 .y(function(d) {
36 return d.y;
37 });
38
39
40/***************************************************************************************************
41starts the "pending" animation
42***************************************************************************************************/
43function setPending(selection) {
44 selection.classed('pending', false);
45 setTimeout(function () {
46 selection.classed('pending', true);
47 }, 0);
48}
49
50/***************************************************************************************************
51convert angle in degrees to radians
52***************************************************************************************************/
53function toRadians (degrees) {
54 return degrees * (Math.PI / 180);
55}
56
57/***************************************************************************************************
58used to generate DOM element id for this link
59***************************************************************************************************/
60function makeLinkKey(link) {
61 return link['src-switch'] + '=>' + link['dst-switch'];
62}
63
64/***************************************************************************************************
65used to generate DOM element id for this flow in the topology view
66***************************************************************************************************/
67function makeFlowKey(flow) {
68 return flow.srcDpid + '=>' + flow.dstDpid;
69}
70
71/***************************************************************************************************
72used to generate DOM element id for this flow in the selected flows table
73***************************************************************************************************/
74function makeSelectedFlowKey(flow) {
75 return 'S' + makeFlowKey(flow);
76}
77
78/***************************************************************************************************
79update the app header using the current model
80***************************************************************************************************/
81function updateHeader() {
Jonathan Harte865f9b2013-04-13 12:08:42 -070082 d3.select('#lastUpdate').text(new Date().toLocaleString());
Paul Greysonbbd708b2013-04-09 22:37:31 -070083
Paul Greyson4a73a8b2013-04-10 11:47:25 -070084 var activeSwitchCount = 0;
Paul Greysonbbd708b2013-04-09 22:37:31 -070085 model.edgeSwitches.forEach(function (s) {
86 if (s.state === 'ACTIVE') {
Paul Greyson4a73a8b2013-04-10 11:47:25 -070087 activeSwitchCount += 1;
Paul Greysonbbd708b2013-04-09 22:37:31 -070088 }
89 });
90 model.aggregationSwitches.forEach(function (s) {
91 if (s.state === 'ACTIVE') {
Paul Greyson4a73a8b2013-04-10 11:47:25 -070092 activeSwitchCount += 1;
Paul Greysonbbd708b2013-04-09 22:37:31 -070093 }
94 });
95 model.coreSwitches.forEach(function (s) {
96 if (s.state === 'ACTIVE') {
Paul Greyson4a73a8b2013-04-10 11:47:25 -070097 activeSwitchCount += 1;
Paul Greysonbbd708b2013-04-09 22:37:31 -070098 }
99 });
100
Paul Greyson4a73a8b2013-04-10 11:47:25 -0700101 d3.select('#activeSwitches').text(activeSwitchCount);
102
103
104
Paul Greyson7a300822013-04-09 12:57:49 -0700105 d3.select('#activeFlows').text(model.flows.length);
Masayoshi Kobayashi84b1bbb2013-06-20 11:47:00 -0700106 d3.select('#activeLinks').text(model.links.length);
Paul Greyson7a300822013-04-09 12:57:49 -0700107}
108
Paul Greysone15c4392013-04-09 15:05:31 -0700109/***************************************************************************************************
110update the global linkmap
111***************************************************************************************************/
112function updateLinkMap(links) {
113 linkMap = {};
114 links.forEach(function (link) {
115 var srcDPID = link['src-switch'];
116 var dstDPID = link['dst-switch'];
117
118 var srcMap = linkMap[srcDPID] || {};
119
120 srcMap[dstDPID] = link;
121
122 linkMap[srcDPID] = srcMap;
123 });
124}
125
126/***************************************************************************************************
127// removes links from the pending list that are now in the model
128***************************************************************************************************/
129function reconcilePendingLinks(model) {
130 links = [];
131 model.links.forEach(function (link) {
132 links.push(link);
133 delete pendingLinks[makeLinkKey(link)]
134 })
135 var linkId;
136 for (linkId in pendingLinks) {
137 links.push(pendingLinks[linkId]);
138 }
139}
140
Paul Greyson981e8c22013-04-09 17:43:59 -0700141/***************************************************************************************************
142used by both ring and map models
143***************************************************************************************************/
144function createRootSVG() {
145 var svg = d3.select('#svg-container').append('svg:svg');
146
147 svg.append("svg:defs").append("svg:marker")
148 .attr("id", "arrow")
149 .attr("viewBox", "0 -5 10 10")
150 .attr("refX", -1)
151 .attr("markerWidth", 5)
152 .attr("markerHeight", 5)
153 .attr("orient", "auto")
154 .append("svg:path")
155 .attr("d", "M0,-3L10,0L0,3");
156
157 return svg;
158}
159
Paul Greyson4a73a8b2013-04-10 11:47:25 -0700160/***************************************************************************************************
161counts the number of flows which pass through each core<->core link
162***************************************************************************************************/
163function countCoreLinkFlows() {
164 var allCounts = {};
165 model.flows.forEach(function (f) {
166 if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
167 var flowEntries = f.dataPath.flowEntries;
168 var i;
169
170 for (i = 0; i < flowEntries.length - 1; i += 1) {
171 var linkKey = flowEntries[i].dpid.value + '=>' + flowEntries[i+1].dpid.value;
172 if (!allCounts[linkKey]) {
173 allCounts[linkKey] = 1;
174 } else {
175 allCounts[linkKey] += 1;
176 }
177 }
178 }
179 });
180
181 var coreCounts = {};
182 var i, j;
183 for (i = 0; i < model.coreSwitches.length - 1; i += 1) {
184 for (j = i + 1; j < model.coreSwitches.length; j += 1) {
185 var si = model.coreSwitches[i];
186 var sj = model.coreSwitches[j];
187 var key1 = si.dpid + '=>' + sj.dpid;
188 var key2 = sj.dpid + '=>' + si.dpid;
189 var linkCount = 0;
190 if (allCounts[key1]) {
191 linkCount += allCounts[key1];
192 }
193 if (allCounts[key2]) {
194 linkCount += allCounts[key2];
195 }
196
197 coreCounts[key1] = linkCount;
198 }
199 }
200
201 return d3.entries(coreCounts);
202}
203
204
Paul Greyson28cf92b2013-04-10 13:15:06 -0700205/***************************************************************************************************
206
207***************************************************************************************************/
Paul Greyson0ad75202013-04-11 12:29:32 -0700208function doConfirm(prompt, cb, options) {
Paul Greyson28cf92b2013-04-10 13:15:06 -0700209 var confirm = d3.select('#confirm');
210 confirm.select('#confirm-prompt').text(prompt);
211
Paul Greyson0ad75202013-04-11 12:29:32 -0700212 var select = d3.select(document.getElementById('confirm-select'));
213 if (options) {
214 select.style('display', 'block');
215 select.text('');
216 select.selectAll('option').
217 data(options)
218 .enter()
219 .append('option')
220 .attr('value', function (d) {return d})
221 .text(function (d) {return d});
222 } else {
223 select.style('display', 'none');
224 }
225
Paul Greyson28cf92b2013-04-10 13:15:06 -0700226 function show() {
227 confirm.style('display', '-webkit-box');
228 confirm.style('opacity', 0);
229 setTimeout(function () {
230 confirm.style('opacity', 1);
231 }, 0);
232 }
233
234 function dismiss() {
235 confirm.style('opacity', 0);
236 confirm.on('webkitTransitionEnd', function () {
237 confirm.style('display', 'none');
238 confirm.on('webkitTransitionEnd', null);
239 });
240 }
241
242 confirm.select('#confirm-ok').on('click', function () {
243 d3.select(this).on('click', null);
244 dismiss();
Paul Greyson0ad75202013-04-11 12:29:32 -0700245 if (options) {
246 cb(select[0][0].value);
247 } else {
248 cb(true);
249 }
Paul Greyson28cf92b2013-04-10 13:15:06 -0700250 });
251
252 confirm.select('#confirm-cancel').on('click', function () {
253 d3.select(this).on('click', null);
254 dismiss();
255 cb(false);
256 });
257
258 show();
259}
260
261
Paul Greyson4a73a8b2013-04-10 11:47:25 -0700262
263
Paul Greyson7a300822013-04-09 12:57:49 -0700264