blob: 68e567ffeb22413fbee2cc665a316ccf23ee9eb8 [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);
106}
107
Paul Greysone15c4392013-04-09 15:05:31 -0700108/***************************************************************************************************
109update the global linkmap
110***************************************************************************************************/
111function updateLinkMap(links) {
112 linkMap = {};
113 links.forEach(function (link) {
114 var srcDPID = link['src-switch'];
115 var dstDPID = link['dst-switch'];
116
117 var srcMap = linkMap[srcDPID] || {};
118
119 srcMap[dstDPID] = link;
120
121 linkMap[srcDPID] = srcMap;
122 });
123}
124
125/***************************************************************************************************
126// removes links from the pending list that are now in the model
127***************************************************************************************************/
128function reconcilePendingLinks(model) {
129 links = [];
130 model.links.forEach(function (link) {
131 links.push(link);
132 delete pendingLinks[makeLinkKey(link)]
133 })
134 var linkId;
135 for (linkId in pendingLinks) {
136 links.push(pendingLinks[linkId]);
137 }
138}
139
Paul Greyson981e8c22013-04-09 17:43:59 -0700140/***************************************************************************************************
141used by both ring and map models
142***************************************************************************************************/
143function createRootSVG() {
144 var svg = d3.select('#svg-container').append('svg:svg');
145
146 svg.append("svg:defs").append("svg:marker")
147 .attr("id", "arrow")
148 .attr("viewBox", "0 -5 10 10")
149 .attr("refX", -1)
150 .attr("markerWidth", 5)
151 .attr("markerHeight", 5)
152 .attr("orient", "auto")
153 .append("svg:path")
154 .attr("d", "M0,-3L10,0L0,3");
155
156 return svg;
157}
158
Paul Greyson4a73a8b2013-04-10 11:47:25 -0700159/***************************************************************************************************
160counts the number of flows which pass through each core<->core link
161***************************************************************************************************/
162function countCoreLinkFlows() {
163 var allCounts = {};
164 model.flows.forEach(function (f) {
165 if (f.dataPath && f.dataPath.flowEntries && f.dataPath.flowEntries.length > 1) {
166 var flowEntries = f.dataPath.flowEntries;
167 var i;
168
169 for (i = 0; i < flowEntries.length - 1; i += 1) {
170 var linkKey = flowEntries[i].dpid.value + '=>' + flowEntries[i+1].dpid.value;
171 if (!allCounts[linkKey]) {
172 allCounts[linkKey] = 1;
173 } else {
174 allCounts[linkKey] += 1;
175 }
176 }
177 }
178 });
179
180 var coreCounts = {};
181 var i, j;
182 for (i = 0; i < model.coreSwitches.length - 1; i += 1) {
183 for (j = i + 1; j < model.coreSwitches.length; j += 1) {
184 var si = model.coreSwitches[i];
185 var sj = model.coreSwitches[j];
186 var key1 = si.dpid + '=>' + sj.dpid;
187 var key2 = sj.dpid + '=>' + si.dpid;
188 var linkCount = 0;
189 if (allCounts[key1]) {
190 linkCount += allCounts[key1];
191 }
192 if (allCounts[key2]) {
193 linkCount += allCounts[key2];
194 }
195
196 coreCounts[key1] = linkCount;
197 }
198 }
199
200 return d3.entries(coreCounts);
201}
202
203
Paul Greyson28cf92b2013-04-10 13:15:06 -0700204/***************************************************************************************************
205
206***************************************************************************************************/
Paul Greyson0ad75202013-04-11 12:29:32 -0700207function doConfirm(prompt, cb, options) {
Paul Greyson28cf92b2013-04-10 13:15:06 -0700208 var confirm = d3.select('#confirm');
209 confirm.select('#confirm-prompt').text(prompt);
210
Paul Greyson0ad75202013-04-11 12:29:32 -0700211 var select = d3.select(document.getElementById('confirm-select'));
212 if (options) {
213 select.style('display', 'block');
214 select.text('');
215 select.selectAll('option').
216 data(options)
217 .enter()
218 .append('option')
219 .attr('value', function (d) {return d})
220 .text(function (d) {return d});
221 } else {
222 select.style('display', 'none');
223 }
224
Paul Greyson28cf92b2013-04-10 13:15:06 -0700225 function show() {
226 confirm.style('display', '-webkit-box');
227 confirm.style('opacity', 0);
228 setTimeout(function () {
229 confirm.style('opacity', 1);
230 }, 0);
231 }
232
233 function dismiss() {
234 confirm.style('opacity', 0);
235 confirm.on('webkitTransitionEnd', function () {
236 confirm.style('display', 'none');
237 confirm.on('webkitTransitionEnd', null);
238 });
239 }
240
241 confirm.select('#confirm-ok').on('click', function () {
242 d3.select(this).on('click', null);
243 dismiss();
Paul Greyson0ad75202013-04-11 12:29:32 -0700244 if (options) {
245 cb(select[0][0].value);
246 } else {
247 cb(true);
248 }
Paul Greyson28cf92b2013-04-10 13:15:06 -0700249 });
250
251 confirm.select('#confirm-cancel').on('click', function () {
252 d3.select(this).on('click', null);
253 dismiss();
254 cb(false);
255 });
256
257 show();
258}
259
260
Paul Greyson4a73a8b2013-04-10 11:47:25 -0700261
262
Paul Greyson7a300822013-04-09 12:57:49 -0700263