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);
17 var result = rpc[data.method](data.params);
19 var ret = {"id": data.id, "jsonrpc": "2.0", "result": result};
20 this.send(JSON.stringify(ret));
23 function trim_zero(obj) {
24 return String(obj).replace(/^0+/, "");
27 function dpid_to_int(dpid) {
28 return Number("0x" + dpid);
32 force: d3.layout.force()
33 .size([CONF.force.width, CONF.force.height])
34 .charge(CONF.force.charge)
35 .linkDistance(CONF.force.dist)
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;")
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; });
52 elem.node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
54 elem.port.attr("transform", function(d) {
55 var p = topo.get_port_point(d);
56 return "translate(" + p.x + "," + p.y + ")";
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) {
65 elem.console.selectAll("ul").remove();
66 /* li = elem.console.append("ul")
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*/
71 d3.select(this).classed("fixed", d.fixed = true);
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 () {
82 this.link = this.link.data(topo.links);
83 this.link.exit().remove();
84 this.link.enter().append("line")
85 .attr("class", "link");
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); })
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); });
104 var ports = topo.get_ports();
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")
111 portEnter.append("text")
114 .text(function(d) { return trim_zero(d.port_no); });
117 function is_valid_link(link) {
118 return (link.src.dpid < link.dst.dpid) //retorna true or false
121 var topo = { //Objeto Topologia
122 nodes: [], //arreglo de nodos
123 links: [], //arreglo de links
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
134 this.refresh_node_index();
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]));
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];
153 this.links.push(link);
156 delete_nodes: function (nodes) {
157 for (var i = 0; i < nodes.length; i++) {
158 console.log("delete switch: " + JSON.stringify(nodes[i]));
160 node_index = this.get_node_index(nodes[i]);
161 this.nodes.splice(node_index, 1);
163 this.refresh_node_index();
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]));
170 link_index = this.get_link_index(links[i]);
171 this.links.splice(link_index, 1);
174 get_node_index: function (node) {
175 for (var i = 0; i < this.nodes.length; i++) {
176 if (node.dpid == this.nodes[i].dpid) {
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) {
193 get_ports: function () {
196 for (var i = 0; i < this.links.length; i++) {
197 function _push(p, dir) {
198 key = p.dpid + ":" + p.port_no;
206 return ports.push(p);
208 _push(this.links[i].port.src, "source");
209 _push(this.links[i].port.dst, "target");
214 get_port_point: function (d) {
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;
223 if (d.link_dir == "target") weight = 1.0 - weight;
225 var x = x1 * weight + x2 * (1.0 - weight);
226 var y = y1 * weight + y2 * (1.0 - weight);
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;
239 event_switch_enter: function (params) {
241 for(var i=0; i < params.length; i++){
242 switches.push({"dpid":params[i].dpid,"ports":params[i].ports});
244 topo.add_nodes(switches);
248 event_switch_leave: function (params) {
250 for(var i=0; i < params.length; i++){
251 switches.push({"dpid":params[i].dpid,"ports":params[i].ports});
253 topo.delete_nodes(switches);
257 event_link_add: function (links) {
258 topo.add_links(links);
262 event_link_delete: function (links) {
263 topo.delete_links(links);
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});
279 initialize_topology();