diff --git a/web/js/topo.js b/web/js/topo.js
new file mode 100644
index 0000000..b518bd2
--- /dev/null
+++ b/web/js/topo.js
@@ -0,0 +1,435 @@
+function convert_to_topodata(switches, links, registry){
+    var controllers={};
+    var nr_controllers=0;
+    var sws=[];
+    var ls=[];
+    var topo = new Array();
+    switches.forEach(function(item) {
+	var sw={}
+	sw.name=item.dpid;
+	sw.group=-1;
+	sws.push(sw);
+    });
+    for (var r in registry){
+	if ( ! (registry[r][0]['controllerId'] in controllers) ){
+	    controllers[registry[r][0]['controllerId']] = ++nr_controllers;
+	}
+    }
+    for (var i = 0; i < sws.length; i++){
+	if (sws[i].name in registry){
+	    sws[i].group=controllers[registry[sws[i].name][0]['controllerId']];
+	    sws[i].controller=registry[sws[i].name][0]['controllerId'];
+	}
+    }
+    links.forEach(function(item) {
+	var link={};
+	for (var i = 0; i < sws.length; i++){
+	    if(sws[i].name == item['src-switch'])
+		break;
+	}
+	link.source=i;
+	for (var i = 0; i < sws.length; i++){
+	    if(sws[i].name == item['dst-switch'])
+		break;
+	}
+	link.target=i;
+	ls.push(link);
+    });
+    topo['nodes']=sws;
+    topo['links']=ls;
+    return topo;
+}
+
+var width = 1280;
+var height = 1280;
+var radius = 8;
+function gui(switch_url, link_url, registry_url){
+    var svg = d3.select("#topology")
+	.append("svg:svg")
+	.attr("width", width)
+	.attr("height", height);
+
+    var force = d3.layout.force()
+	.charge(-500)
+	.linkDistance(100)
+	.size([width, height]);
+
+    var node_drag = d3.behavior.drag()
+        .on("dragstart", dragstart)
+        .on("drag", dragmove)
+        .on("dragend", dragend);
+
+    var color = d3.scale.category20();
+    var topodata;
+    var nodes = force.nodes();
+    var links = force.links();
+
+    d3.json(switch_url, function(error, rest_switches) {
+	d3.json(link_url, function(error, rest_links) { 
+	    d3.json(registry_url, function(error, rest_registry) { 
+		topodata = convert_to_topodata(rest_switches, rest_links, rest_registry);
+		init(topodata, nodes, links);
+		path = svg.append("svg:g").selectAll("path").data(links);
+		circle = svg.append("svg:g").selectAll("circle").data(nodes);
+		text = svg.append("svg:g").selectAll("text").data(nodes);
+		draw();
+	    });
+	}); 
+    }); 
+
+    setInterval(function(){ 
+	d3.json(switch_url, function(error, rest_switches) {
+	    d3.json(link_url, function(error, rest_links) { 
+		d3.json(registry_url, function(error, rest_registry) { 
+		    topodata = convert_to_topodata(rest_switches, rest_links, rest_registry);
+		    var changed = update(topodata, nodes, links);
+		    path = svg.selectAll("path").data(links)
+		    circle = svg.selectAll("circle").data(nodes);
+		    text = svg.selectAll("text").data(nodes);
+		    if ( changed ){
+			draw();
+		    }
+		});
+	    }); 
+	}); 
+    }, 3000); 
+
+    function draw(){
+	force.stop();
+	svg.append("svg:text")
+	    .attr("x", 50)
+	    .attr("y", 20)
+            .text(function(){return "Switch: " + force.nodes().length + " (Active: " + nr_active_sw()  + ")/ Link: " + force.links().length});
+    
+	path.enter().append("svg:path")
+	    .attr("class", function(d) { return "link"; })
+	    .attr("marker-end", function(d) {
+		if(d.type == 1){
+		    return "url(#TriangleRed)";
+		} else {
+		    return "url(#Triangle)";
+		}
+	    });
+	
+	circle.enter().append("svg:circle")
+	    .attr("r", function(d) { 
+		if (d.group == 1000){
+		    return radius;
+		}else{
+		    return radius;
+		}
+	    })
+	    .call(node_drag);
+    
+	text.enter().append("svg:text")
+	    .attr("x", radius)
+	    .attr("y", ".31em")
+	    .text(function(d) { 
+		l=d.name.split(":").length
+		return d.name.split(":")[l-2] + ":" + d.name.split(":")[l-1]
+	    });
+    
+	circle.append("title")
+	    .text(function(d) { return d.name; });
+    
+	circle.attr("fill", function(d) {
+            if (d.group == 1){
+		return "red"
+            }else if (d.group == 2){
+		return "blue"
+            }else if (d.group == 3){
+		return "green"
+            }else if (d.group == 4){
+		return "orange"
+            }else if (d.group == 5){
+		return "cyan"
+            }else if (d.group == 6){
+		return "magenta"
+            }else if (d.group == 7){
+		return "yellow"
+            }else if (d.group == 8){
+		return "purple"
+            }else{
+		return "gray"
+            }
+	});
+
+        circle.on('mouseover', function(d){
+   	 var nodeSelection = d3.select(this).style({opacity:'0.8'});
+  	  nodeSelection.select("text").style({opacity:'1.0'});
+	});
+
+
+	path.attr("stroke", function(d) {
+	    if(d.type == 1){
+		return "red"
+	    } else {
+		return "black"
+	    }
+	}).attr("stroke-width", function(d) {
+	    if(d.type == 1){
+		return "2px";
+	    } else {
+		return "1.5px";
+	    }
+	}).attr("marker-end", function(d) {
+	    if(d.type == 1){
+		return "url(#TriangleRed)";
+	    } else {
+		return "url(#Triangle)";
+	    }
+	});
+	path.exit().remove();
+	circle.exit().remove();
+	text.exit().remove();
+	force.on("tick", tick);
+	force.start();
+    }
+    function nr_active_sw(){
+        var n=0; 
+        var nodes = force.nodes();
+        for(var i=0;i<nodes.length;i++){
+          if(nodes[i].group!=0)
+            n++;
+        }; 
+        return n;
+    }
+    function dragstart(d, i) {
+        force.stop() // stops the force auto positioning before you start dragging
+    }
+    function dragmove(d, i) {
+        d.px += d3.event.dx;
+        d.py += d3.event.dy;
+        d.x += d3.event.dx;
+        d.y += d3.event.dy; 
+        tick(); // this is the key to make it work together with updating both px,py,x,y on d !
+    }
+
+    function dragend(d, i) {
+        d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
+        tick();
+        force.resume();
+    }
+    function tick() {
+	path.attr("d", function(d) {
+	    var dx = d.target.x - d.source.x,
+	    dy = d.target.y - d.source.y,
+	    dr = 1/d.linknum;  //linknum is defined above
+	    dr = 0;  // 0 for direct line
+	    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
+	});
+	path.attr("stroke", function(d) {
+	    if(d.type == 1){
+		return "red"
+	    } else {
+		return "black"
+	    }
+	}).attr("stroke-width", function(d) {
+	    if(d.type == 1){
+		return "3px";
+	    } else {
+		return "1.5px";
+	    }
+	}).attr("marker-end", function(d) {
+	    if(d.type == 1){
+		return "url(#TriangleRed)";
+	    } else {
+		return "url(#Triangle)";
+	    }
+	});
+//	circle.attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; });
+	circle.attr("transform", function(d) {
+	    x = Math.max(radius, Math.min(width - radius, d.x));
+	    y = Math.max(radius, Math.min(height - radius, d.y)); 
+//	    return "translate(" + d.x + "," + d.y + ")";
+	    return "translate(" + x + "," + y + ")";
+	})
+	circle.attr("fill", function(d) {
+                if (d.group == 1){
+                    return "red"
+                }else if (d.group == 2){
+                    return "blue"
+                }else if (d.group == 3){
+                    return "green"
+                }else if (d.group == 4){
+                    return "orange"
+                }else if (d.group == 5){
+                    return "cyan"
+                }else if (d.group == 6){
+                    return "magenta"
+                }else if (d.group == 7){
+                    return "yellow"
+                }else if (d.group == 8){
+                    return "purple"
+                }else{
+                    return "gray"
+                }
+	});
+//	text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
+	text.attr("transform", function(d) {
+	    return "translate(" + d.x + "," + d.y + ")";
+	});
+    }
+
+}
+
+
+function init(topodata, nodes, links){
+    topodata.nodes.forEach(function(item) {
+        nodes.push(item);
+    });
+    topodata.links.forEach(function(item) {
+        links.push(item);
+    });
+    links.sort(compare_link);
+    // distinguish links that have the same src & dst node by 'linknum'
+    for (var i=1; i < links.length; i++) {
+        if (links[i].source == links[i-1].source &&
+            links[i].target == links[i-1].target) {
+            links[i].linknum = links[i-1].linknum + 1;
+        } else {
+	    links[i].linknum = 1;
+	};
+    };
+}
+
+function compare_link (a, b){
+    if (a.source > b.source)
+	return 1;
+    else if (a.source < b.source)
+	return -1;
+    else {
+        if (a.target > b.target)
+	    return 1;
+        else if (a.target < b.target)
+	    return -1;
+        else
+	    return 0;
+    }
+}
+
+/* Return nodes that is not in the current list of nodes */
+Array.prototype.node_diff = function(arr) {
+    return this.filter(function(i) {
+	for (var j = 0; j < arr.length ; j++) {
+	    if (arr[j].name === i.name)
+		return false;
+	}
+	return true;
+    });
+};
+
+/* Return removed links */
+function gone_links (topo_json, links){
+    gone = []
+    for (var i = 0; i < links.length ; i ++){
+	var found = 0;
+	for (var j = 0; j < topo_json.links.length ; j ++){
+	    if (links[i].source.name == topo_json.nodes[topo_json.links[j].source].name && 
+		links[i].target.name == topo_json.nodes[topo_json.links[j].target].name ){
+		found = 1;
+		break;
+	    }
+	}
+	if ( found == 0 ){
+	    gone.push(links[i]);
+	}
+    }
+    return gone;
+}
+
+/* Return added links */
+function added_links (topo_json, links) {
+    added = [];
+    for (var j = 0; j < topo_json.links.length ; j ++){
+	var found = 0;
+	for (var i = 0; i < links.length ; i ++){
+	    if (links[i].source.name == topo_json.nodes[topo_json.links[j].source].name && 
+		links[i].target.name == topo_json.nodes[topo_json.links[j].target].name ){
+		found = 1;
+		break;
+	    }
+	}
+	if ( found == 0 ){
+	    added.push(topo_json.links[j]);
+	}
+    }
+    return added;
+}
+
+/* check if toplogy has changed and update node[] and link[] accordingly */
+function update(json, nodes, links){
+    var changed = false;
+    var n_adds = json.nodes.node_diff(nodes);
+    var n_rems = nodes.node_diff(json.nodes);
+    for (var i = 0; i < n_adds.length; i++) {
+	nodes.push(n_adds[i]);
+	changed = true;
+    }
+    for (var i = 0; i < n_rems.length; i++) {
+	for (var j = 0; j < nodes.length; j++) {
+	    if ( nodes[j].name == n_rems[i].name ){
+		nodes.splice(j,1);
+		changed = true;
+		break;
+	    }
+	}
+    }
+    var l_adds = added_links(json, links);
+    var l_rems = gone_links(json, links);
+    for (var i = 0; i < l_rems.length ; i++) {
+	for (var j = 0; j < links.length; j++) {
+            if (links[j].source.name == l_rems[i].source.name &&
+		links[j].target.name == l_rems[i].target.name) {
+		links.splice(j,1);
+		changed = true;
+		break;
+            }
+	}
+    }
+    // Sorce/target of an element of l_adds[] are corresponding to the index of json.node[]
+    // which is different from the index of node[] (new nodes are always added to the last)
+    // So update soure/target node indexes of l_add[] need to be fixed to point to the proper
+    // node in node[];
+    for (var i = 0; i < l_adds.length; i++) {
+	for (var j = 0; j < nodes.length; j++) {
+	    if ( json.nodes[l_adds[i].source].name == nodes[j].name ){
+		l_adds[i].source = j; 
+		break;
+	    }
+	}
+	for (var j = 0; j < nodes.length; j++) {
+	    if ( json.nodes[l_adds[i].target].name == nodes[j].name ){
+		l_adds[i].target = j;
+		break;
+	    }
+	}
+	links.push(l_adds[i]);
+	changed = true;
+    }
+
+    // Update "group" attribute of nodes
+    for (var i = 0; i < nodes.length; i++) {
+        for (var j = 0; j < json.nodes.length; j++) {
+	    if ( nodes[i].name == json.nodes[j].name ){
+		if (nodes[i].group != json.nodes[j].group){
+		    nodes[i].group = json.nodes[j].group;
+		    changed = true;
+		}
+	    }
+	}
+    }
+    for (var i = 0; i < links.length; i++) {
+        for (var j = 0; j < json.links.length; j++) {
+	    if (links[i].target.name == json.nodes[json.links[j].target].name && 
+		links[i].source.name == json.nodes[json.links[j].source].name ){
+		if (links[i].type != json.links[j].type){
+		    links[i].type = json.links[j].type;
+		    changed = true;
+		}
+	    }
+	}
+    }
+    return changed
+}
+
