diff options
Diffstat (limited to 'www/js/network.js')
-rw-r--r-- | www/js/network.js | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/www/js/network.js b/www/js/network.js new file mode 100644 index 00000000..ec9b81a7 --- /dev/null +++ b/www/js/network.js @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +var LENGTH_MAIN = 350, // unused + LENGTH_SERVER = 150, // unused + LENGTH_SUB = 50, // unused + WIDTH_SCALE = 2, + EDGE_WIDTH_MIN = 2, + EDGE_WIDTH_MID = 15 + EDGE_WIDTH_MAX = 35, + BW_MID = 50, + EDGE_RATE_MAX = 250000, // kbps + COORDINATE_SCALE = 50, + CACHE_RADIUS = 120, + GREEN = 'green', + MAX_COLOR_VALUE = 16777215 + MAX_BW_VALUE = 1200 + RED = '#C5000B', + BLUE = '#0B00C5', + ORANGE = 'orange', + GRAY = 'gray', + BLACK = '#2B1B17', + CYAN = 'cyan', + COLOR_RED = '#fa5858', + COLOR_RED_SHADED = '#F8E0E0', + COLOR_BLUE = '#0080ff', + COLOR_BLUE_SHADED = '#CEE3F6', + COLOR_GREEN = '#04B404', + COLOR_GREEN_SHADED = '#E0F8E0'; + +var DIR = 'img/'; + +/* Network color scales */ + +var color_scale_lin = d3.scaleLinear().domain([0, 10, 20, 30, 40, 50]).range(['gray', 'green', 'blue', 'purple', 'black', 'yellow']); +var color_scale_log = d3.scaleLog().domain([50, 200, 1000]).range(['yellow', 'orange', 'red']); + +DEFAULT_VIS_OPTIONS = { + nodes: { + size: 70, // unused + font:{color:'black'}, + scaling:{ + label: { + min:0, + max: 35 // unused// This defines the label size of the node + } + } + }, + edges: { + color: GRAY, + smooth: false + }, + physics:{ + barnesHut:{gravitationalConstant:-30000}, + stabilization: {iterations:2500} + }, + groups: { + 'switch': { + shape: 'triangle', + color: '#FF9900' // orange + }, + desktop: { + shape: 'dot', + color: "#2B7CE9" // blue + }, + mobile: { + shape: 'dot', + color: "#5A1E5C" // purple + }, + server: { + shape: 'square', + color: "#C5000B" // red + }, + internet: { + shape: 'square', + color: "#109618" // green + } + } +} + +var Network = Class.extend({ + + /** + * @brief Class constructor + */ + init: function(id) + { + + this._id = id; + this._server = new ServerEventsDispatcher(URL); + + this._server.bind('insert', 'local.connection', this.on_connect.bind(this)); + this._server.bind("insert", "node", this.on_insert_node.bind(this)); + this._server.bind("insert", "channel", this.on_insert_channel.bind(this)); + this._server.bind("update", "node", this.on_update_node.bind(this)); + this._server.bind("update", "channel", this.on_update_channel.bind(this)); + + this._map_interface_node = new Object(); + this._map_id_type = new Object(); + + var body = document.body, + html = document.documentElement; + + var HEIGTH = Math.max( body.scrollHeight, body.offsetHeight, + html.clientHeight, html.scrollHeight, html.offsetHeight ); + var WIDTH = Math.max( body.scrollWidth, body.offsetWidth, + html.clientWidth, html.scrollWidth, html.offsetWidth ); + + this._nodes = new vis.DataSet({}); + this._edges = new vis.DataSet({}); + this._edgesInfo = []; + + this._map_id_name = new Object(); + this._map_name_id = new Object(); + + this._pending_edges = Array(); + this._pending_nodes = Array(); + + var container = document.getElementById(id); + var data = { + nodes: this._nodes, + edges: this._edges + }; + + vis.Network.prototype.setScale = function (scale) { + var options = { + nodes: [] + }; + var animationOptions = { + scale: scale, + animation: options.animation + }; + this.view.moveTo(animationOptions); + }; + + this._network = new vis.Network(container, data, DEFAULT_VIS_OPTIONS); + window.onresize = this.do_fit.bind(this); + + this.intervalID = setInterval( + (function(self) { //Self-executing func which takes 'this' as self + return function() { //Return a function in the context of 'self' + self._tick(); + } + })(this), + 500); + }, + + _tick: function() + { + this._edges.update(this._pending_edges); + this._pending_edges.length = 0; + + this._nodes.update(this._pending_nodes); + this._pending_nodes.length = 0; + }, + + do_fit: function() + { + this._network.fit(); + }, + + on_connect: function() + { + // Request nodes with interfaces, and later, links + var node_query = new Query('select', 'node'); + this._server.send(node_query.to_dict()); + }, + + on_insert_node: function(query) + { + data = query.params + // Update mac->node map + if (data.interfaces) { + for (var i=0; i<data.interfaces.length; i++) { + this._map_interface_node[data.interfaces[i]] = data.id; + } + } + + // RIGHT PLOTS + this._map_id_name[data.id] = data.name; + this._map_name_id[data.name] = data.id; + + font = new Object(); + font.size = 40; + font.color = 'black'; + //font.background = 'black'; + font.strokeColor = 'white'; + font.strokeWidth = 2; + font.align = 'top'; + //font.vadjust = -10; + + // Update node + var node = new Object(); + node.id = data.id; + node.font = font; + + node.font.color = '#000000'; + + node.shape = 'image' + + node.x = data.x * COORDINATE_SCALE; + node.y = data.y * COORDINATE_SCALE; + node.size = 0.75 * COORDINATE_SCALE; + + node.image = DIR + data.category + '.png'; + + node.physics = false; + node.has_producer = false; // FIB entry + if (data.groups.length > 0) { + this._nodes.add(node); + } + if (query.last) { + this.do_fit(); + var link_query = new Query('select', 'channel'); + this._server.send(link_query.to_dict()); + } + }, + + on_update_node: function(query) + { + var data = query.params; + var node = new Object(); + + var filter_dict = {}; + query.filter.forEach(function(filter) { + [key, op, value] = filter; + if (op == '==') { + filter_dict[key] = value; + } + }); + + if (filter_dict.id === undefined) { + if (filter_dict.name === undefined) { + console.log("Wrong update query"); + return; + } + node.id = this._map_name_id[filter_dict.name]; + } else { + node.id = filter_dict.id; + } + node.image = DIR + data.category + '.png'; + + this._pending_nodes.push(node); + }, + + on_insert_channel: function(query) + { + data = query.params; + + font = new Object(); + font.size = 35; + font.color = 'black'; + //font.background = 'black'; + font.strokeColor = 'white'; + font.strokeWidth = 2; + font.align = 'top'; + font.vadjust = -20; + + if ((data.type.indexOf('wiredchannel') !== -1) || (data.type.indexOf('link') !== -1) || (data.type.indexOf('phylink') !== -1) || (data.type.indexOf('memiflink') !== -1)) { + var edgeu = new Object(); + edgeu.id = data.id; + edgeu.width = EDGE_WIDTH_MIN; + edgeu.color = GRAY + edgeu.fontColor = RED; + edgeu.font = font; + + if ((data.type.indexOf('link') !== -1) || (data.type.indexOf('memiflink') !== -1)) { + edgeu.from = data.src_node; + edgeu.to = data.dst_node; + } else { + edgeu.from = this._map_interface_node[data.src]; + edgeu.to = this._map_interface_node[data.dst]; + + } + + //this._edges.update(edgeu); + this._pending_edges.push(edgeu); + this._edgesInfo[edgeu.id] = data.capacity; + + } else if (data.type.indexOf('emulatedchannel') !== -1) { + if (data.stations !== undefined) { + data.stations.forEach(function(station) { + var edgeu = new Object(); + station_name = this._map_id_name[station]; + edgeu.id = 'tap-' + station_name + '-' + data.name; + edgeu.width = EDGE_WIDTH_MIN; + edgeu.color = GRAY; + edgeu.fontColor = RED; + + edgeu.from = station; + edgeu.to = data.ap; + edgeu.dashes = [10,10]; + edgeu.font = font; + this._pending_edges.push(edgeu); + + this._edgesInfo[edgeu.id] = data.capacity; + }.bind(this)); + } + } + }, + + on_update_channel: function(query) + { + data = query.params; + if (data.bw_upstream === undefined) + return; + + var id = query.filter[0][2]; + var bw = parseFloat(Math.round((parseFloat(data.bw_upstream) + parseFloat(data.bw_downstream)) / 1024 / 1024 * 8 * 10) /10).toFixed(1); + + var edgeu = new Object(); + edgeu.id = id; + if (bw < BW_MID) { + // 0 MIN + // x ?? + // BW_MID EDGE_WIDTH_MID + edgeu.color = color_scale_lin(bw); + edgeu.width = (EDGE_WIDTH_MID * bw) / BW_MID; + } else { + // BW_MID 0 -> 0 + EDGE_WIDTH_MID + // log() = 0 -> 0 + EDGE_WIDTH_MID + // = x -> ?? + // log() = 4 -> EDGE_WIDTH_MAX - EDGE_WIDTH_MID + EDGE_WIDTH_MID + edgeu.color = color_scale_log(bw); + edgeu.width = EDGE_WIDTH_MID + Math.log10(bw - BW_MID) * (EDGE_WIDTH_MAX - EDGE_WIDTH_MID) / 4 + } + + if (bw != 0.0) { + if (bw > 1000) + edgeu.label = Math.round(bw/10)/100 + " Gbps"; + else + edgeu.label = bw + " Mbps"; + } else { + edgeu.label = ""; + } + + + this._pending_edges.push(edgeu); + + }, + +}); |