Merge branch 'master' of https://github.com/OPENNETWORKINGLAB/ONOS
diff --git a/start-cassandra.sh b/start-cassandra.sh
index 3f92779..011c09d 100755
--- a/start-cassandra.sh
+++ b/start-cassandra.sh
@@ -2,19 +2,19 @@
 
 CASSANDRA_DIR=${HOME}/apache-cassandra-1.1.4
 LOGDIR=${HOME}/ONOS/onos-logs
-CASSANDRA_LOG=$LOGDIR/cassandara.onos1vpc.log
+CASSANDRA_LOG=$LOGDIR/cassandara.`hostname`.log
 
 function lotate {
-logfile=$1
-nr_max=$2
-if [ -f $logfile ]; then
-  for i in `seq $(expr 10 - 1) -1 1`; do
-    if [ -f ${logfile}.${i} ]; then
-      mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
+    logfile=$1
+    nr_max=${2:-10}
+    if [ -f $logfile ]; then
+	for i in `seq $(expr $nr_max - 1) -1 1`; do
+	    if [ -f ${logfile}.${i} ]; then
+		mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
+	    fi
+	done
+	mv $logfile $logfile.1
     fi
-  done
-  mv $logfile $logfile.1
-fi
 }
 
 function start {
diff --git a/start-onos.sh b/start-onos.sh
index a3c0c43..19834af 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -51,16 +51,16 @@
 #<appender-ref ref="STDOUT" />
 
 function lotate {
-logfile=$1
-nr_max=$2
-if [ -f $logfile ]; then
-for i in `seq $(expr 10 - 1) -1 1`; do
-if [ -f ${logfile}.${i} ]; then
-mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
-fi
-done
-mv $logfile $logfile.1
-fi
+    logfile=$1
+    nr_max=${2:-10}
+    if [ -f $logfile ]; then
+	for i in `seq $(expr $nr_max - 1) -1 1`; do
+	    if [ -f ${logfile}.${i} ]; then
+		mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
+	    fi
+	done
+	mv $logfile $logfile.1
+    fi
 }
 
 function start {
diff --git a/start-rest.sh b/start-rest.sh
new file mode 100755
index 0000000..28ea0f7
--- /dev/null
+++ b/start-rest.sh
@@ -0,0 +1,68 @@
+#! /bin/bash
+
+# Change this accordingly
+ONOSDIR=${HOME}/ONOS
+script_name="topology_rest.py"
+
+#######################
+WEBDIR=${ONOSDIR}/web
+restscript=${WEBDIR}/$script_name
+LOGDIR=${ONOSDIR}/onos-logs
+REST_LOG="${LOGDIR}/rest.`hostname`.log"
+#######################
+
+function lotate {
+    logfile=$1
+    nr_max=${2:-10}
+    if [ -f $logfile ]; then
+	for i in `seq $(expr $nr_max - 1) -1 1`; do
+	    if [ -f ${logfile}.${i} ]; then
+		mv -f ${logfile}.${i} ${logfile}.`expr $i + 1`
+	    fi
+	done
+	mv $logfile $logfile.1
+    fi
+}
+
+function stop {
+    pids=`ps -edalf |grep ${script_name} | grep python | grep -v grep | awk '{print $4}'`
+    for p in ${pids}; do
+	if [ x$p != "x" ]; then
+	    sudo kill -KILL $p
+	    echo "Killed existing prosess (pid: $p)"
+	fi
+    done
+}
+
+function status {
+    nr_process=`ps -edalf |grep ${script_name} | grep python | grep -v grep | wc -l` 
+    if [ x${nr_process} == "x" ] ; then
+      nr_process=0
+    fi
+    echo "${nr_process} instance of rest server is running"
+}
+
+function start {
+    lotate $REST_LOG 10 
+    cd $WEBDIR
+    $restscript > $REST_LOG 2>&1 &
+}
+
+case "$1" in
+  start)
+    stop
+    start 
+    ;;
+  stop)
+    stop
+    ;;
+  deldb)
+    deldb
+    ;;
+  status)
+    status
+    ;;
+  *)
+    echo "Usage: $0 {start|stop|restart|status}"
+    exit 1
+esac
diff --git a/test-network/mininet/onos-nw.py b/test-network/mininet/onos-nw.template.py
similarity index 100%
rename from test-network/mininet/onos-nw.py
rename to test-network/mininet/onos-nw.template.py
diff --git a/test-network/mininet/tunnel.sh b/test-network/mininet/tunnel.template.sh
similarity index 100%
rename from test-network/mininet/tunnel.sh
rename to test-network/mininet/tunnel.template.sh
diff --git a/web/hello.html b/web/hello.html
new file mode 100644
index 0000000..36a444f
--- /dev/null
+++ b/web/hello.html
@@ -0,0 +1,3 @@
+<html>
+Hello
+</html>
diff --git a/web/js/onos-topology-route.js b/web/js/onos-topology-route.js
new file mode 100644
index 0000000..e94d1aa
--- /dev/null
+++ b/web/js/onos-topology-route.js
@@ -0,0 +1,390 @@
+function gui(data_source){
+    var width = 960,
+    height = 500;
+    var color = d3.scale.category20();
+
+    var svg = d3.select("body").append("svg:svg")
+	.attr("width", width)
+	.attr("height", height);
+
+    var force = d3.layout.force()
+	.charge(-500)
+	.linkDistance(100)
+	.size([width, height]);
+
+    var path = svg.selectAll("path");
+    var circle = svg.selectAll("circle");
+    var text = svg.selectAll("g");
+    var pathlen = 0;
+    var from;
+    var to;
+    var path_set = 0;
+
+
+    d3.json(data_source,init);
+
+    function init(json){
+        nodes = force.nodes();
+        links = force.links();
+
+	json.nodes.forEach(function(item) {
+            nodes.push(item);
+	});
+/*
+        nodes.sort(function(a,b) {
+            if (a.name > b.name) {return 1;}
+            else if (a.name < b.name) {return -1;}
+            else {return 0;}
+        });
+*/
+	json.links.forEach(function(item) {
+            links.push(item);
+	});
+	draw(nodes, links);
+    }
+
+    function update(json) {
+	Array.prototype.diff2 = function(arr) {
+	    return this.filter(function(i) {
+		for (var j = 0; j < arr.length ; j++) {
+		    if (arr[j].source === i.source.index && 
+			arr[j].target === i.target.index)
+			return false;
+		}
+		return true;
+	    });
+	};
+
+	Array.prototype.diff = function(arr) {
+	    return this.filter(function(i) {
+		for (var j = 0; j < arr.length ; j++) {
+		    if (arr[j].source.index === i.source && 
+			arr[j].target.index === i.target)
+			return false;
+		}
+		return true;
+	    });
+	};
+
+	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;
+	    });
+	};
+
+
+        links.sort(function(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;}
+                if (a.target < b.target) {return -1;}
+                else {return 0;}
+            }
+        });
+
+//        for (var i=0; i<links.length; i++) {
+//          if (i != 0 &&
+//            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 cdiff(topo) {
+            var changed = false;
+
+            var n_adds = topo.nodes.node_diff(nodes);
+            var n_rems = nodes.node_diff(topo.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 = [];
+            var l_rems = [];
+	    l_adds = added_links(topo, links, l_adds);
+            l_rems = gone_links(topo, links, l_rems);
+
+            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;
+                    }
+		}
+            }
+            for (var i = 0; i < l_adds.length; i++) {
+		var s;
+		var t;
+		for (var j = 0; j < nodes.length; j++) {
+		    if ( json.nodes[l_adds[i].source].name == nodes[j].name ){
+			s = j;
+			break;
+		    }
+		}
+		for (var j = 0; j < nodes.length; j++) {
+		    if ( json.nodes[l_adds[i].target].name == nodes[j].name ){
+			t = j;
+			break;
+		    }
+		}
+		l_adds[i].source = s;
+		l_adds[i].target = t;
+		links.push(l_adds[i]);
+		changed = true;
+            }
+	    return changed
+	}
+
+
+	var changed = cdiff(json);
+
+        for (var i = 0; i < json.nodes.length; i++) {
+	    nodes[i].group = json.nodes[i].group
+	}
+	var rewrite = 0;
+	for (var i = 0; i < links.length; i++) {
+            for (var j = 0; j < json.links.length; j++) {
+	/*	
+		console.log("link" + i);
+		console.log(links[i].source.name + "->" + links[i].target.name);
+		console.log("type " + links[i].type);
+		console.log("json link" + j);
+		console.log(json.nodes[json.links[j].source].name + "->" + json.nodes[json.links[j].target].name);
+	*/
+		if (links[i].target.name == json.nodes[json.links[j].target].name && 
+		    links[i].source.name == json.nodes[json.links[j].source].name ){
+		    links[i].type = json.links[j].type;
+		    rewrite ++;
+		}
+	    }
+	}
+	console.log("changed?" + changed);
+	if (changed){
+	    console.log(nodes);
+	    console.log(links);
+            path = svg.selectAll("path").data(links)
+            circle = svg.selectAll("circle").data(nodes);
+	    text = svg.selectAll("text").data(nodes);
+
+	    force.stop();
+
+            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", 8)
+/*		.on("click", function(d,i) {
+		    if ( path_set == 0 || path_set == 2 ){
+			fm = d.name;
+			path_set = 1;
+			alert("from set to " + d.name);
+		    }else if ( path_set == 1 ){
+			to = d.name;
+			path_set = 2;
+			alert("to set to " + d.name);
+		    }
+		}) */
+               .call(force.drag);
+
+/*	    text.enter().append("svg:text")
+		.attr("x", 8)
+		.attr("y", ".31em")
+		.attr("class", "shadow")
+		.text(function(d) { return d.name.split(":")[7]; }); */
+
+	    text.enter().append("svg:text")
+		.attr("x", 8)
+		.attr("y", ".31em")
+		.text(function(d) { return d.name.split(":")[7]; }); 
+
+            circle.append("title")
+	      .text(function(d) { return d.name; });
+
+	    path.attr("stroke", function(d) {
+		if(d.type == 1){
+		    return "red"
+		} else {
+		    return "black"
+		}
+	    })
+	    .attr("stroke-width", function(d) {
+		if(d.type == 1){
+		    return "4px";
+		} else {
+		    return "1.5px";
+		}
+	    });
+
+
+	    path.exit().remove();
+            circle.exit().remove();
+            text.exit().remove();
+	    force.on("tick", tick);
+            force.start();
+	}
+    }
+    function draw(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);
+
+        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)";
+		}
+	    });
+
+	path.attr("stroke", function(d) {
+	    if(d.type == 1){
+		return "red"
+	    } else {
+		return "black"
+	    }
+	}).attr("stroke-width", function(d) {
+	    if(d.type == 1){
+		return "4px";
+	    } else {
+		return "1.5px";
+	    }
+	}).attr("marker-end", function(d) {
+	    if(d.type == 1){
+		return "url(#TriangleRed)";
+	    } else {
+		return "url(#Triangle)";
+	    }
+	});
+
+
+        circle.enter().append("svg:circle")
+          .attr("r", 8)
+/*	    .on("click", function(d,i) {
+		if ( path_set == 0 || path_set == 2 ){
+		    fm = d.name;
+		    path_set = 1;
+		    alert("from set to " + d.name);
+		}else if ( path_set == 1 ){
+		    to = d.name;
+		    path_set = 2;
+		    alert("to set to " + d.name);
+		}
+	    }) */
+          .call(force.drag);
+
+/*	text.enter().append("svg:text")
+	    .attr("x", 8)
+	    .attr("y", ".31em")
+	    .attr("class", "shadow")
+	    .text(function(d) { return d.name.split(":")[7]; }); */
+
+	text.enter().append("svg:text")
+	    .attr("x", 8)
+	    .attr("y", ".31em")
+	    .text(function(d) { return d.name.split(":")[7]; }); 
+
+	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{ return "gray"; }
+	});
+
+
+	force.on("tick", tick);
+	path.exit().remove();
+        circle.exit().remove();
+//        text.exit().remove();
+
+	force.start();
+
+	setInterval(function() {
+            $.ajax({
+//		url: 'http://onosnat.onlab.us:8080/topology',
+		url: data_source,
+		success: function(json) {
+		    update(json)
+		},
+		dataType: "json"
+            });
+	}, 3000); 
+    }
+    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 = 300;
+	    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 "4px";
+	    } 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) {
+	    return "translate(" + d.x + "," + d.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{ return "gray"; }
+	});
+//	text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
+//	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 + ")";
+	});
+    }
+}
diff --git a/web/js/onos-topology.js b/web/js/onos-topology.js
index aee3eaf..61eb9da 100644
--- a/web/js/onos-topology.js
+++ b/web/js/onos-topology.js
@@ -15,9 +15,43 @@
     var path = svg.selectAll("path");
     var circle = svg.selectAll("circle");
     var text = svg.selectAll("g");
+    var node_drag = d3.behavior.drag()
+        .on("dragstart", dragstart)
+        .on("drag", dragmove)
+        .on("dragend", dragend);
 
+    d3.json(data_source, init);
 
-    d3.json(data_source,init);
+/* For debugging  */
+    $("#more").click( function() {
+        $.ajax({
+	    url: 'http://onosnat.onlab.us:8080/topology_more',
+	    success: function(json) {
+		update(json)
+	    },
+	    dataType: "json"
+        });
+    });
+    $("#less").click( function() {
+        $.ajax({
+	    url: 'http://onosnat.onlab.us:8080/topology_less',
+	    success: function(json) {
+		update(json)
+	    },
+	    dataType: "json"
+        });
+    });
+/**/
+
+    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 ;}
+            if (a.target < b.target) {return -1;}
+            else {return 0;}
+        }
+    }
 
     function init(json){
         nodes = force.nodes();
@@ -29,176 +63,169 @@
 	json.links.forEach(function(item) {
             links.push(item);
 	});
-	draw(nodes, links);
+
+        links.sort(compare_link);
+        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;
+	  };
+        };
+	init_draw(nodes, links);
     }
 
-    function update(json) {
-	Array.prototype.diff2 = function(arr) {
-	    return this.filter(function(i) {
-		for (var j = 0; j < arr.length ; j++) {
-		    if (arr[j].source === i.source.index && 
-			arr[j].target === i.target.index)
-			return false;
+    /* 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 (json, links, gone) {
+	for (var i = 0; i < links.length ; i ++){
+	    var found = 0;
+	    for (var j = 0; j < json.links.length ; j ++){
+		if (links[i].source.name == json.nodes[json.links[j].source].name && 
+		    links[i].target.name == json.nodes[json.links[j].target].name ){
+		    found = 1;
+		    break;
 		}
-		return true;
-	    });
-	};
+	    }
+	    if ( found == 0 ){
+		gone.push(links[i]);
+	    }
+	}
+	return gone;
+    }
 
-	Array.prototype.diff = function(arr) {
-	    return this.filter(function(i) {
-		for (var j = 0; j < arr.length ; j++) {
-		    if (arr[j].source.index === i.source && 
-			arr[j].target.index === i.target)
-			return false;
+    /* Return added links */
+    function added_links (json, links, added) {
+	for (var j = 0; j < json.links.length ; j ++){
+	    var found = 0;
+	    for (var i = 0; i < links.length ; i ++){
+		if (links[i].source.name == json.nodes[json.links[j].source].name && 
+		    links[i].target.name == json.nodes[json.links[j].target].name ){
+		    found = 1;
+		    break;
 		}
-		return true;
-	    });
-	};
+	    }
+	    if ( found == 0 ){
+		added.push(json.links[j]);
+	    }
+	}
+	return added;
+    }
 
-	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;
+    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();
+    }
+
+    /* check if toplogy has changed and update node[] and link[] accordingly */
+    function cdiff(json) {
+        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;
 		}
-		return true;
-	    });
-	};
+	    }
+        }
+        var l_adds = [];
+        var l_rems = [];
+	l_adds = added_links(json, links, l_adds);
+        l_rems = gone_links(json, links, l_rems);
+        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;
+        }
 
-
-//        links.sort(function(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;}
-//                if (a.target < b.target) {return -1;}
-//                else {return 0;}
-//            }
-//        });
-//        for (var i=0; i<links.length; i++) {
-//          if (i != 0 &&
-//            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 cdiff(topo) {
-            var changed = false;
-            var l_adds = topo.links.diff(links);
-            var l_rems = links.diff2(topo.links);
-
-            var n_adds = topo.nodes.node_diff(nodes);
-            var n_rems = nodes.node_diff(topo.nodes);
-
-            for (var i = 0; i < l_rems.length ; i++) {
-		for (var j = 0; j < links.length; j++) {
-                    if (links[j].source.index == l_rems[i].source.index &&
-			links[j].target.index == l_rems[i].target.index) {
-			links.splice(j,1);
+	// 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;
-			break;
-                    }
-		}
-            }
-            for (var i = 0; i < l_adds.length; i++) {
-		links.push(l_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;
 		    }
 		}
-            }
-            for (var i = 0; i < n_adds.length; i++) {
-		nodes.push(n_adds[i]);
-		changed = true;
-            }
-	    return changed
+	    }
 	}
-
- 
-
-	var changed = cdiff(json);
-        for (var i = 0; i < json.nodes.length; i++) {
-	    nodes[i].group = json.nodes[i].group
-	}
-
-	console.log(circle);
-
-	console.log("changed?");
-	console.log(changed);
-
-
-	if (changed){
-            path = svg.selectAll("path").data(links)
-            circle = svg.selectAll("circle").data(nodes);
-	    text = svg.selectAll("text").data(nodes);
-
-	    force.stop();
-
-            path.enter().append("svg:path")
-		.attr("class", function(d) { return "link"; })
-		.attr("marker-end", "url(#Triangle)");
-
-            circle.enter().append("svg:circle")
-               .attr("r", 6)
-               .call(force.drag);
-
-/*	    text.enter().append("svg:text")
-		.attr("x", 8)
-		.attr("y", ".31em")
-		.attr("class", "shadow")
-		.text(function(d) { return d.name.split(":")[7]; }); */
-
-	    text.enter().append("svg:text")
-		.attr("x", 8)
-		.attr("y", ".31em")
-		.text(function(d) { return d.name.split(":")[7]; }); 
-
-            circle.append("title")
-	      .text(function(d) { return d.name; });
-
-	    path.exit().remove();
-            circle.exit().remove();
-            text.exit().remove();
-
-	    force.on("tick", tick);
-            force.start();
-	}
+	return changed
     }
-    function draw(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);
 
+    function draw(force, path, circle, text){
+	force.stop();
         path.enter().append("svg:path")
-	    .attr("class", function(d) { return "link"; })
-	    .attr("marker-end", "url(#Triangle)");
+	    .attr("class", function(d) { return "link"; });
 
         circle.enter().append("svg:circle")
-          .attr("r", 8)
-          .call(force.drag);
-
-/*	text.enter().append("svg:text")
-	    .attr("x", 8)
-	    .attr("y", ".31em")
-	    .attr("class", "shadow")
-	    .text(function(d) { return d.name.split(":")[7]; }); */
+	    .attr("r", 8)
+	    .call(node_drag);
+//            .call(force.drag);
 
 	text.enter().append("svg:text")
 	    .attr("x", 8)
 	    .attr("y", ".31em")
-	    .text(function(d) { return d.name.split(":")[7]; }); 
+	    .text(function(d) { return d.name.split(":")[6] + d.name.split(":")[7] });
 
-	circle.append("title")
+        circle.append("title")
 	    .text(function(d) { return d.name; });
 
 	circle.attr("fill", function(d) {
@@ -208,12 +235,57 @@
 	    else{ return "gray"; }
 	});
 
-	force.on("tick", tick);
+	path.attr("stroke", function(d) {
+	    if(d.type == 1){
+		return "red"
+	    } else {
+		return "black"
+	    }
+	}).attr("stroke-width", function(d) {
+	    if(d.type == 1){
+		return "4px";
+	    } 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();
+        text.exit().remove();
+	
+	force.on("tick", tick);
+        force.start();
 
-	force.start();
+    }
+
+    function update(json) {
+	var changed = cdiff(json);
+
+	console.log("changed? " + changed);
+
+	if (changed){
+
+            path = svg.selectAll("path").data(links)
+            circle = svg.selectAll("circle").data(nodes);
+	    text = svg.selectAll("text").data(nodes);
+
+	    draw(force, path, circle, text);
+	}
+    }
+
+    function init_draw(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(force, path, circle, text);
 
 	setInterval(function() {
             $.ajax({
@@ -226,12 +298,14 @@
             });
 	}, 3000); 
     }
+
+
     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 = 300;
+	    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;
 	});
 //	circle.attr("cx", function(d) { return d.x; }).attr("cy", function(d) { return d.y; });
@@ -245,9 +319,9 @@
 	    else{ return "gray"; }
 	});
 //	text.attr("x", function(d) { return d.x; }).attr("y", function(d) { return d.y; });
-//	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 + ")";
 	});
     }
 }
+
diff --git a/web/onos-topology-route.html b/web/onos-topology-route.html
new file mode 100644
index 0000000..860a096
--- /dev/null
+++ b/web/onos-topology-route.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<style>
+path.link {
+  fill: none;
+}
+circle {
+  stroke: #333;
+  stroke-width: 1.5px;
+}
+
+text {
+  font: 20px sans-serif;
+  pointer-events: none;
+}
+</style>
+<head>
+<title>ONOS GUI</title>
+<script src="http://d3js.org/d3.v3.min.js"></script>
+<script type="text/javascript" src="js/onos-topology-route.js"></script>
+<script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
+</head>
+<body>
+<svg width="4in" height="2in" 
+     viewBox="0 0 4000 2000" version="1.1"
+     xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <marker id="Triangle"
+      viewBox="0 -5 10 10" refX="15" refY="-1.5" 
+      markerUnits="strokeWidth"
+      markerWidth="6" markerHeight="6"
+      orient="auto">
+      <path d="M0,-5L10,0L0,5"/>
+    </marker>
+    <marker id="TriangleRed"
+      viewBox="0 -5 10 10" refX="10" refY="-0.2" 
+      markerUnits="strokeWidth"
+      markerWidth="6" markerHeight="6"
+      orient="auto">
+      <path d="M0,-5L10,0L0,5" fill="red" stroke="red"/>
+    </marker>
+  </defs>
+<script type="text/javascript">
+gui("http://onosnat.onlab.us:8080/wm/topology/toporoute/00:00:00:00:00:a1/2/00:00:00:00:00:c1/3/json");
+</script>
+</svg>
+</body>
+</html>
diff --git a/web/onos-topology.html b/web/onos-topology.html
index 1edbaee..0b5c313 100644
--- a/web/onos-topology.html
+++ b/web/onos-topology.html
@@ -25,6 +25,8 @@
 <script type="text/javascript" src="js/jquery-1.7.2.min.js"></script>
 </head>
 <body>
+<button id="more">more</button>
+<button id="less">lesse</button>
 <svg width="4in" height="2in" 
      viewBox="0 0 4000 2000" version="1.1"
      xmlns="http://www.w3.org/2000/svg">
@@ -38,7 +40,7 @@
     </marker>
   </defs>
 <script type="text/javascript">
-gui("http://onosnat.onlab.us:8080/topology");
+gui("http://gui.onlab.us:8080/topology");
 </script>
 </svg>
 </body>
diff --git a/web/topology_rest.py b/web/topology_rest.py
index cdc8a4d..0a6c756 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -99,7 +99,7 @@
 
   return id
 
-@app.route("/topology")
+@app.route('/topology', methods=['GET'])
 def topology_for_gui():
   try:
     command = "curl -s \'http://%s:%s/wm/core/topology/switches/all/json\'" % (RestIP, RestPort)
@@ -122,9 +122,15 @@
       sw = {}
       sw['name']=dpid
       if str(v['state']) == "ACTIVE":
-         sw['group']=0
-      if str(v['state']) == "INACTIVE":
+        if dpid[-2:-1] == "a":
          sw['group']=1
+        if dpid[-2:-1] == "b":
+         sw['group']=2
+        if dpid[-2:-1] == "c":
+         sw['group']=3
+      if str(v['state']) == "INACTIVE":
+         sw['group']=0
+
 
       switches.append(sw)
   
@@ -254,6 +260,7 @@
   try:
     command = "curl -s \'http://%s:%s/wm/core/topology/switches/all/json\'" % (RestIP, RestPort)
 #    http://localhost:8080/wm/core/topology/switches/active/json
+    print command
     result = os.popen(command).read()
     parsedResult = json.loads(result)
   except:
@@ -346,6 +353,7 @@
 def query_links():
   try:
     command = 'curl -s http://%s:%s/graphs/%s/vertices?key=type\&value=port' % (RestIP, RestPort, DBName)
+    print command
     result = os.popen(command).read()
     parsedResult = json.loads(result)['results']
   except:
@@ -401,5 +409,4 @@
 #    devices()
   else:
     app.debug = True
-#    app.run(host="10.0.1.29", port=9000)
-    app.run(host="0.0.0.0", port=9000)
+    app.run(threaded=True, host="0.0.0.0", port=9000)