backing up
[vsorcdistro/.git] / ryu / build / lib.linux-armv7l-2.7 / ryu / app / gui_topology / html / ryu.topology.js
1 var CONF = {
2     image: {
3         width: 50,
4         height: 40
5     },
6     force: {
7         width: 1000,
8         height: 500,
9         dist: 200,
10         charge: -600
11     }
12 };
13 var ws = new WebSocket("ws://" + location.host + "/v1.0/topology/ws"); //Crea un websocket
14 ws.onmessage = function(event) {
15     var data = JSON.parse(event.data);
16
17     var result = rpc[data.method](data.params);
18
19     var ret = {"id": data.id, "jsonrpc": "2.0", "result": result};
20     this.send(JSON.stringify(ret));
21 }
22
23 function trim_zero(obj) {
24     return String(obj).replace(/^0+/, "");
25 }
26
27 function dpid_to_int(dpid) {
28     return Number("0x" + dpid);
29 }
30
31 var elem = {
32     force: d3.layout.force()
33         .size([CONF.force.width, CONF.force.height])
34         .charge(CONF.force.charge)
35         .linkDistance(CONF.force.dist)
36         .on("tick", _tick),
37     svg: d3.select("body").append("svg")
38         .attr("id", "topology")
39         .attr("width", CONF.force.width)
40         .attr("height", CONF.force.height),
41     console: d3.select("body").append("div")
42         .attr("id", "console")
43         .attr("width", CONF.force.width)
44         .attr("style","background-color: white;")
45 };
46 function _tick() {
47     elem.link.attr("x1", function(d) { return d.source.x; })
48         .attr("y1", function(d) { return d.source.y; })
49         .attr("x2", function(d) { return d.target.x; })
50         .attr("y2", function(d) { return d.target.y; });
51
52     elem.node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
53
54     elem.port.attr("transform", function(d) {
55         var p = topo.get_port_point(d);
56         return "translate(" + p.x + "," + p.y + ")";
57     });
58 }
59 elem.drag = elem.force.drag().on("dragstart", _dragstart);
60 function _dragstart(d) {
61     var dpid = dpid_to_int(d.dpid)
62     d3.json("/stats/flow/" + dpid, function(e, data) {
63         flows = data[dpid];
64         console.log(flows);
65         elem.console.selectAll("ul").remove();
66       /*  li = elem.console.append("ul")
67             .selectAll("li");
68         li.data(flows).enter().append("li")
69             .text(function (d) { return JSON.stringify(d, null, " "); });*/ /*Esto es para poner el string de los flows al final de la pagina*/
70     });
71     d3.select(this).classed("fixed", d.fixed = true);
72 }
73 elem.node = elem.svg.selectAll(".node");
74 elem.link = elem.svg.selectAll(".link");
75 elem.port = elem.svg.selectAll(".port");
76 elem.update = function () {
77     this.force
78         .nodes(topo.nodes)
79         .links(topo.links)
80         .start();
81
82     this.link = this.link.data(topo.links);
83     this.link.exit().remove();
84     this.link.enter().append("line")
85         .attr("class", "link");
86
87     this.node = this.node.data(topo.nodes);
88     this.node.exit().remove();
89     var nodeEnter = this.node.enter().append("g")
90         .attr("class", "node")
91         .on("dblclick", function(d) { d3.select(this).classed("fixed", d.fixed = false); })
92         .call(this.drag);
93     nodeEnter.append("image")
94         .attr("xlink:href", "./router.svg")
95         .attr("x", -CONF.image.width/2)
96         .attr("y", -CONF.image.height/2)
97         .attr("width", CONF.image.width)
98         .attr("height", CONF.image.height);
99     nodeEnter.append("text")
100         .attr("dx", -CONF.image.width/2)
101         .attr("dy", CONF.image.height-10)
102         .text(function(d) { return "dpid: " + trim_zero(d.dpid); });
103
104     var ports = topo.get_ports();
105     this.port.remove();
106     this.port = this.svg.selectAll(".port").data(ports);
107     var portEnter = this.port.enter().append("g")
108         .attr("class", "port");
109     portEnter.append("circle")
110         .attr("r", 8);
111     portEnter.append("text")
112         .attr("dx", -3)
113         .attr("dy", 3)
114         .text(function(d) { return trim_zero(d.port_no); });
115 };
116
117 function is_valid_link(link) {
118     return (link.src.dpid < link.dst.dpid) //retorna true or false
119 }
120
121 var topo = { //Objeto Topologia
122     nodes: [], //arreglo de nodos
123     links: [], //arreglo de links
124
125     node_index: {}, // dpid -> index of nodes array
126     initialize: function (data) {
127         this.add_nodes(data.switches);
128         this.add_links(data.links);
129     }, //El valor initialize es una funcion que recive una data y ejecuta las dos funciones de dentro
130     add_nodes: function (nodes) {
131         for (var i = 0; i < nodes.length; i++) {
132             this.nodes.push(nodes[i]); //Agrega al arreglo de nodos los que recibe por parametro
133         }
134         this.refresh_node_index();
135     },
136     add_links: function (links) {
137         for (var i = 0; i < links.length; i++) {
138             if (!is_valid_link(links[i])) continue;
139             console.log("add link: " + JSON.stringify(links[i]));
140
141             var src_dpid = links[i].src.dpid;
142             var dst_dpid = links[i].dst.dpid;
143             var src_index = this.node_index[src_dpid];
144             var dst_index = this.node_index[dst_dpid];
145             var link = {
146                 source: src_index,
147                 target: dst_index,
148                 port: {
149                     src: links[i].src,
150                     dst: links[i].dst
151                 }
152             }
153             this.links.push(link);
154         }
155     },
156     delete_nodes: function (nodes) {
157         for (var i = 0; i < nodes.length; i++) {
158             console.log("delete switch: " + JSON.stringify(nodes[i]));
159
160             node_index = this.get_node_index(nodes[i]);
161             this.nodes.splice(node_index, 1);
162         }
163         this.refresh_node_index();
164     },
165     delete_links: function (links) {
166         for (var i = 0; i < links.length; i++) {
167             if (!is_valid_link(links[i])) continue;
168             console.log("delete link: " + JSON.stringify(links[i]));
169
170             link_index = this.get_link_index(links[i]);
171             this.links.splice(link_index, 1);
172         }
173     },
174     get_node_index: function (node) {
175         for (var i = 0; i < this.nodes.length; i++) {
176             if (node.dpid == this.nodes[i].dpid) {
177                 return i;
178             }
179         }
180         return null;
181     },
182     get_link_index: function (link) {
183         for (var i = 0; i < this.links.length; i++) {
184             if (link.src.dpid == this.links[i].port.src.dpid &&
185                     link.src.port_no == this.links[i].port.src.port_no &&
186                     link.dst.dpid == this.links[i].port.dst.dpid &&
187                     link.dst.port_no == this.links[i].port.dst.port_no) {
188                 return i;
189             }
190         }
191         return null;
192     },
193     get_ports: function () {
194         var ports = [];
195         var pushed = {};
196         for (var i = 0; i < this.links.length; i++) {
197             function _push(p, dir) {
198                 key = p.dpid + ":" + p.port_no;
199                 if (key in pushed) {
200                     return 0;
201                 }
202
203                 pushed[key] = true;
204                 p.link_idx = i;
205                 p.link_dir = dir;
206                 return ports.push(p);
207             }
208             _push(this.links[i].port.src, "source");
209             _push(this.links[i].port.dst, "target");
210         }
211
212         return ports;
213     },
214     get_port_point: function (d) {
215         var weight = 0.88;
216
217         var link = this.links[d.link_idx];
218         var x1 = link.source.x;
219         var y1 = link.source.y;
220         var x2 = link.target.x;
221         var y2 = link.target.y;
222
223         if (d.link_dir == "target") weight = 1.0 - weight;
224
225         var x = x1 * weight + x2 * (1.0 - weight);
226         var y = y1 * weight + y2 * (1.0 - weight);
227
228         return {x: x, y: y};
229     },
230     refresh_node_index: function(){
231         this.node_index = {};
232         for (var i = 0; i < this.nodes.length; i++) {
233             this.node_index[this.nodes[i].dpid] = i;
234         }
235     },
236 }
237
238 var rpc = {
239     event_switch_enter: function (params) {
240         var switches = [];
241         for(var i=0; i < params.length; i++){
242             switches.push({"dpid":params[i].dpid,"ports":params[i].ports});
243         }
244         topo.add_nodes(switches);
245         elem.update();
246         return "";
247     },
248     event_switch_leave: function (params) {
249         var switches = [];
250         for(var i=0; i < params.length; i++){
251             switches.push({"dpid":params[i].dpid,"ports":params[i].ports});
252         }
253         topo.delete_nodes(switches);
254         elem.update();
255         return "";
256     },
257     event_link_add: function (links) {
258         topo.add_links(links);
259         elem.update();
260         return "";
261     },
262     event_link_delete: function (links) {
263         topo.delete_links(links);
264         elem.update();
265         return "";
266     },
267 }
268
269 function initialize_topology() {
270     d3.json("/v1.0/topology/switches", function(error, switches) {
271         d3.json("/v1.0/topology/links", function(error, links) {
272             topo.initialize({switches: switches, links: links});
273             elem.update();
274         });
275     });
276 }
277
278 function main() {
279     initialize_topology();
280 }
281
282 main();