Merge pull request #3 from OPENNETWORKINGLAB/master

Merge with Main
diff --git a/README.md b/README.md
index 6e65f51..495a2ed 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,92 @@
 ONOS
 ====
 
-Open Networking Operating System
\ No newline at end of file
+Open Networking Operating System
+
+BELOW TO BE WRITTEN IN DETAIL
+
+
+Building ONOS
+-------------
+
+0. Install custom jars and dependencies (Only need to be run only once)
+
+    $ ./setup-local-maven.sh
+
+1. Cleanly Build ONOS
+
+    $ mvn clean
+    $ mvn compile
+
+    NOTE: installing maven for the first time may switch java version from 1.7 to 1.6 causing cassandra to not run
+
+Dependencies
+------------
+1. Zookeeper
+    Download and install apache-zookeeper-3.4.5: http://zookeeper.apache.org/releases.html
+2. Cassandra
+    Download and install apache-cassandra-1.2.2: http://cassandra.apache.org/download/
+
+Running ONOS
+------------
+
+1. Start zookeeper
+
+    $ cd (ONOS-INSTALL-DIR)/
+
+    $ ./start-zk.sh
+
+2. Start cassandra
+
+    $ cd (ONOS-INSTALL-DIR)/
+
+    $ ./start-cassandra.sh start
+
+  1. Confirm cassandra is running
+  
+      $ ./start-cassandra.sh status
+
+3. Start ONOS instance
+
+    $ cd (ONOS-INSTALL-DIR)/
+
+    $ ./start-onos.sh start
+    
+4. Start ONOS rest apis
+
+    $ ./start-rest.sh start
+
+Running ONOS with Cassandra embedded (Optional)
+-----------------------------------------------
+
+1. Start Zookeeper
+
+    $ cd (ONOS-INSTALL-DIR)/
+
+    $ ./zkServer.sh start
+    
+2. Start ONOS and Cassandra embedded
+
+    $ cd (ONOS-INSTALL_DIR)/
+    
+    $ ./start-onos-embedded.sh start
+    
+3. Start ONOS rest apis
+
+    $ ./start-rest.sh start
+
+
+Running in offline mode (Optional)
+----------------------------------
+
+Maven is used to build and run ONOS. 
+By default, maven tries to reach the repositories.
+To suppress this behavior '-o' option should be given to `mvn` command.
+
+To give additional option to `mvn` commands used in ONOS, 
+use the MVN environment variable.
+
+* Example: Running in offline mode
+
+    $ env MVN="mvn -o" ./start-onos.sh start
+
diff --git a/build.xml b/build.xml
deleted file mode 100644
index c7b6449..0000000
--- a/build.xml
+++ /dev/null
@@ -1,315 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-
- <!--
-   Copyright 2011, Big Switch Networks, Inc.
-   
-   Licensed to the Apache Software Foundation (ASF) under one or more
-   contributor license agreements.  See the NOTICE file distributed with
-   this work for additional information regarding copyright ownership.
-   The ASF licenses this file to You 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.
--->
-
-<!--
-    The build uses pregenerated Thrift code by default to reduce build
-    dependencies. To generate it locally run the gen-thrift target.
-    If you change the Thrift files be sure to also commit the updated
-    generated code.
--->
-
-<project default="jar" name="Floodlight">
-    <property name="target" location="target"/>
-    <property name="build" location="${target}/bin"/>
-    <property name="build-test" location="${target}/bin-test"/>
-    <property name="build-coverage" location="${target}/bin-coverage"/>
-    <property name="test-output" location="${target}/test"/>
-    <property name="coverage-output" location="${target}/coverage"/>
-    <property name="source" location="src/main/java"/>
-    <property name="resources" location="src/main/resources/"/>
-    <property name="source-test" location="src/test/java"/>
-    <property name="python-src" location="src/main/python"/>
-    <property name="docs" location="${target}/docs"/>
-    <property name="main-class" value="net.floodlightcontroller.core.Main"/>
-    <property name="floodlight-jar" location="${target}/floodlight.jar"/>
-    <property name="floodlight-test-jar" location="${target}/floodlight-test.jar"/>
-    <property name="floodlight-only-jar" location="${target}/floodlight-only.jar"/>
-    <property name="thrift.dir" value="${basedir}/src/main/thrift"/>
-    <property name="thrift.out.dir" value="lib/gen-java"/>
-    <property name="thrift.package" value="net/floodlightcontroller/packetstreamer/thrift"/>
-    <property name="ant.build.javac.source" value="1.6"/>
-    <property name="ant.build.javac.target" value="1.6"/>
-    <property name="lib" location="lib"/>
-    <property name="titanlib" location="lib/titan/"/>
-
-    <patternset id="lib">
-        <include name="logback-classic-1.0.0.jar"/>
-        <include name="logback-core-1.0.0.jar"/>
-        <include name="jackson-core-asl-1.9.11.jar"/>
-        <include name="jackson-mapper-asl-1.9.11.jar"/>
-        <include name="slf4j-api-1.6.4.jar"/>
-        <include name="org.restlet-2.1-RC1.jar"/>
-        <include name="org.restlet.ext.jackson-2.1-RC1.jar"/>
-        <include name="org.restlet.ext.simple-2.1-RC1.jar"/>
-        <include name="org.restlet.ext.slf4j-2.1-RC1.jar"/>
-        <include name="simple-4.1.21.jar"/>
-        <include name="netty-3.2.6.Final.jar"/>
-        <include name="args4j-2.0.16.jar"/>
-        <include name="concurrentlinkedhashmap-lru-1.3.jar"/>
-        <include name="jython-2.5.2.jar"/>
-        <include name="libthrift-0.7.0.jar"/>
-	<include name="curator-client-1.3.5-SNAPSHOT.jar"/>
-	<include name="curator-framework-1.3.5-SNAPSHOT.jar"/>
-	<include name="curator-recipes-1.3.5-SNAPSHOT.jar"/>
-	<include name="curator-x-discovery-1.3.5-SNAPSHOT.jar"/>
-	<include name="zookeeper-3.4.5.jar"/>
-	<include name="ezmorph-1.0.6.jar"/>	
- 	<include name="json-lib-2.4-jdk15.jar"/>
-    </patternset>
-
-    <patternset id="titanlib">
-	<include name="**/*.jar"/>
-    </patternset>
-
-    <path id="classpath">
-        <fileset dir="${lib}">
-            <patternset refid="lib"/>
-        </fileset>
-        <fileset dir="${titanlib}">
-            <patternset refid="titanlib"/>
-        </fileset>
-    </path>
-
-    <patternset id="lib-cobertura">
-        <include name="cobertura-1.9.4.1.jar"/>
-        <include name="asm-3.0.jar"/>
-        <include name="asm-tree-3.0.jar"/>
-        <include name="oro/jakarta-oro-2.0.8.jar"/>
-        <include name="log4j-1.2.9.jar"/>
-    </patternset>
-    <path id="classpath-cobertura">
-        <fileset dir="${lib}">
-            <patternset refid="lib-cobertura"/>
-    </fileset>
-    </path>
-
-    <patternset id="lib-test">
-        <include name="junit-4.8.2.jar"/>
-        <include name="org.easymock-3.1.jar"/>
-        <include name="objenesis-1.2.jar"/>  <!-- required by easymock to mock classes -->
-        <include name="cglib-nodep-2.2.2.jar"/>    <!-- required by easymock to mock classes -->
-    </patternset>
-    <path id="classpath-test">
-        <fileset dir="${lib}">
-            <patternset refid="lib-test"/>
-            <patternset refid="lib-cobertura"/>
-            <patternset refid="lib"/>
-            <patternset refid="titanlib"/>
-        </fileset>
-    </path>
-
-    <target name="init">
-        <mkdir dir="${build}"/>
-        <mkdir dir="${build-test}"/>
-        <mkdir dir="${target}/lib"/>
-        <mkdir dir="${thrift.out.dir}"/>
-        <mkdir dir="${test-output}"/>
-    </target>
-
-    <target name="compile" depends="init">
-        <javac includeAntRuntime="false" 
-           classpathref="classpath" 
-           debug="true" 
-           srcdir="${source}:${thrift.out.dir}"
-           destdir="${build}">
-	  <compilerarg value="-Xlint:unchecked"/>
-        </javac>
-    </target>
-
-    <target name="compile-tests" depends="compile-test"/>
-    <target name="compile-test" depends="compile">
-        <fileset dir="${resources}"/>
-        <javac includeAntRuntime="false" debug="true" 
-           srcdir="${source-test}"
-           classpath="${build}"
-           classpathref="classpath-test"
-           destdir="${build-test}"/>
-    </target>
-
-    <!-- Thrift build based on http://www.flester.com/blog/2009/04/26/using-thrift-from-ant -->
-    <fileset id="thrift.files" dir="${thrift.dir}">
-        <include name="**/*.thrift"/>
-    </fileset>
-
-    <target name="gen-thrift" depends="init">
-        <pathconvert property="thrift.file.list" refid="thrift.files"
-            pathsep=" " dirsep="/">
-        </pathconvert>
-        <echo message="Running thrift generator on ${thrift.file.list}"/>
-        <exec executable="thrift" dir="${basedir}" failonerror="true">
-            <arg line="--strict -v --gen java -o ${thrift.out.dir}/.. ${thrift.file.list}"/>
-        </exec>
-        <!-- Get rid of annoying warnings in thrift java: at annotations -->
-        <echo message="Adding @SuppressWarning annotations"/>
-        <replaceregexp byline="true">
-            <regexp pattern="^public "/>
-            <substitution expression='@SuppressWarnings("all") public '/>
-            <fileset id="thrift.output.files" dir="${thrift.out.dir}/..">
-                <include name="**/*.java"/>
-            </fileset>
-        </replaceregexp>
-    </target>
-
-    <target name="clean">
-        <delete dir="${target}"/>
-    </target>
-
-    <target name="run" depends="dist">
-        <java fork="true" jar="${floodlight-jar}" classpathref="classpath">
-            <jvmarg value="-server"/>
-            <jvmarg value="-Xms1024M"/>
-            <jvmarg value="-Xmx1024M"/>
-        </java>
-    </target>
-
-    <target name="tests" depends="test"/>
-    <target name="test" depends="compile-test">
-        <junit fork="true" forkmode="once"
-           failureproperty="junit.failure"
-           printsummary="on">
-        <sysproperty key="net.sourceforge.cobertura.datafile"
-             file="${target}/cobertura.ser" />
-            <classpath>
-                <pathelement location="${build-coverage}"/>
-                <pathelement location="${build}"/>
-                <pathelement location="${build-test}"/>
-                <pathelement location="${floodlight-jar}"/>
-                <path refid="classpath-test"/>
-            </classpath>
-            <formatter type="brief" usefile="true" />
-            <batchtest todir="${test-output}">
-                <fileset dir="${source-test}">
-                    <exclude name="**/storage/tests/StorageTest.java"/>
-				    <include name="**/*Test*.java"/>
-                    <exclude name="**/core/test/**"/>
-                    <exclude name="**/core/module/**"/>
-                </fileset>
-            </batchtest>
-        </junit>
-        <fail if="junit.failure" message="Unit test(s) failed.  See reports!"/>
-    </target>
-
-    <taskdef classpathref="classpath-cobertura" resource="tasks.properties"/>
-    <target name="clean-instrument">
-        <delete file="${target}/cobertura.ser"/>
-        <delete dir="${build-coverage}"/>
-    </target>
-    <target name="instrument" depends="compile,compile-test,clean-instrument">
-      <cobertura-instrument datafile="${target}/cobertura.ser"
-                todir="${build-coverage}"
-                classpathref="classpath-cobertura">
-    <fileset dir="${build}">
-      <include name="**/*.class"/>
-    </fileset>
-      </cobertura-instrument>
-    </target>
-    <target name="coverage-report">
-        <cobertura-report format="html"
-              datafile="${target}/cobertura.ser"
-              destdir="${coverage-output}"
-              srcdir="${source}"/>
-        <cobertura-report format="xml"
-              datafile="${target}/cobertura.ser"
-              destdir="${coverage-output}"
-              srcdir="${source}"/>
-    </target>
-    <target name="coverage" depends="instrument,test,coverage-report"/>
-
-    <target name="jar" depends="compile">
-        <jar destfile="${floodlight-only-jar}">
-	    <fileset dir="${build}"/>
-	    <fileset dir="${resources}"/>
-	    <fileset dir="${python-src}">
-	        <include name="**/*.py"/>
-	    </fileset>
-        </jar>
-    </target>
-
-    <target name="dist" depends="compile,compile-test">
-        <jar destfile="${floodlight-jar}" filesetmanifest="mergewithoutmain">
-            <manifest>
-                <attribute name="Main-Class" value="${main-class}"/>
-                <attribute name="Class-Path" value="."/>
-            </manifest>
-            <fileset dir="${build}"/>
-            <fileset dir="${resources}"/>
-            <fileset dir="${python-src}">
-                <include name="**/*.py"/>
-            </fileset>
-            <zipgroupfileset dir="${titanlib}">
-                <patternset refid="titanlib"/>
-            </zipgroupfileset>
-            <zipgroupfileset dir="${lib}">
-                <patternset refid="lib"/>
-            </zipgroupfileset>
-        </jar>
-        <jar destfile="${floodlight-test-jar}" filesetmanifest="mergewithoutmain">
-            <manifest>
-                <attribute name="Class-Path" value="."/>
-            </manifest>
-            <fileset dir="${build-test}"/>
-            <fileset dir="${resources}"/>
-            <zipgroupfileset dir="${lib}">
-                <patternset refid="lib-test"/>
-                <patternset refid="lib-cobertura"/>
-            </zipgroupfileset>
-            <zipgroupfileset dir="${titanlib}">
-                <patternset refid="titanlib"/>
-            </zipgroupfileset>
-        </jar>
-    </target>
-
-    <target name="javadoc">
-        <javadoc access="protected"
-            author="true"
-            classpathref="classpath"
-            destdir="${docs}"
-            doctitle="Floodlight"
-            nodeprecated="false"
-            nodeprecatedlist="false"
-            noindex="false"
-            nonavbar="false"
-            notree="false"
-            source="1.6"
-            sourcepath="${source}"
-            splitindex="true"
-            use="true"
-            version="true"/>
-    </target>
-
-    <target name="eclipse" depends="init">
-        <pathconvert property="eclipse-lib">
-            <map from="${basedir}/" to=""/>
-            <fileset dir="${lib}">
-                <patternset refid="lib"/>
-                <patternset refid="lib-test"/>
-            </fileset>
-            <fileset dir="${titanlib}">
-                <patternset refid="titanlib"/>
-            </fileset>
-        </pathconvert>
-        <exec executable="${basedir}/setup-eclipse.sh">
-            <arg value="${main-class}"/>
-            <arg value="${eclipse-lib}"/>
-        </exec>
-    </target>
-
-</project>
diff --git a/cluster-mgmt/bin/bootup.sh b/cluster-mgmt/bin/bootup.sh
index e58e802..ca86f7e 100755
--- a/cluster-mgmt/bin/bootup.sh
+++ b/cluster-mgmt/bin/bootup.sh
@@ -1,5 +1,5 @@
 #! /bin/bash
-. $HOME/bin/func.sh
+. `dirname $0`/func.sh
 
 onos stop
 cassandra cleandb
diff --git a/cluster-mgmt/bin/cassandra b/cluster-mgmt/bin/cassandra
index 262c936..b2033ad 100755
--- a/cluster-mgmt/bin/cassandra
+++ b/cluster-mgmt/bin/cassandra
@@ -1,5 +1,5 @@
 #! /bin/bash
-. ${HOME}/bin/func.sh
+. `dirname $0`/func.sh
 
 #$0 $1 $2
 `basename $0` $1 $2
diff --git a/cluster-mgmt/bin/cmd b/cluster-mgmt/bin/cmd
index 262c936..b2033ad 100755
--- a/cluster-mgmt/bin/cmd
+++ b/cluster-mgmt/bin/cmd
@@ -1,5 +1,5 @@
 #! /bin/bash
-. ${HOME}/bin/func.sh
+. `dirname $0`/func.sh
 
 #$0 $1 $2
 `basename $0` $1 $2
diff --git a/cluster-mgmt/bin/config.sh b/cluster-mgmt/bin/config.sh
index 5baf2e0..19bfbf2 100755
--- a/cluster-mgmt/bin/config.sh
+++ b/cluster-mgmt/bin/config.sh
@@ -1,6 +1,6 @@
 #! /bin/sh
 
-. ${HOME}/bin/func.sh
+. `dirname $0`/func.sh
 
 basename=$ONOS_CLUSTER_BASENAME
 nr_nodes=$ONOS_CLUSTER_NR_NODES
diff --git a/cluster-mgmt/bin/func.sh b/cluster-mgmt/bin/func.sh
index 9785e66..b42ead1 100755
--- a/cluster-mgmt/bin/func.sh
+++ b/cluster-mgmt/bin/func.sh
@@ -1,7 +1,7 @@
-USERNAME=ubuntu
-CASSANDRA_DIR='/home/ubuntu/apache-cassandra-1.1.4'
-ZK_DIR='/home/ubuntu/zookeeper-3.4.5'
-ONOS_DIR='/home/ubuntu/ONOS'
+CASSANDRA_DIR='${HOME}/apache-cassandra-1.1.4'
+ZK_DIR='${HOME}/zookeeper-3.4.5'
+ONOS_DIR='${HOME}/ONOS'
+
 ZK_LIB='/var/lib/zookeeper'
 CASSANDRA_LIB='/var/lib/cassandra'
 
@@ -29,9 +29,11 @@
   case "$1" in
     start)
       echo "Starting ZK.."
-      dsh -g $basename "$ZK_DIR/bin/zkServer.sh start"
+#      dsh -g $basename "$ZK_DIR/bin/zkServer.sh start"
+      dsh -g $basename 'cd ONOS; ./start-zk.sh start'
       while [ 1 ]; do
-        nup=`dsh -g $basename "$ZK_DIR/bin/zkServer.sh status" | grep "Mode" | egrep "leader|follower" | wc -l`
+#        nup=`dsh -g $basename "$ZK_DIR/bin/zkServer.sh status" | grep "Mode" | egrep "leader|follower" | wc -l`
+        nup=`dsh -g $basename "cd ONOS; ./start-zk.sh status" | grep "Mode" | egrep "leader|follower|standalone" | wc -l`
         if [ $nup == $nr_nodes ]; then
           echo "everybody's up: $nup up of of $nr_nodes"
           echo "ZK started"
@@ -75,6 +77,32 @@
         sleep 1
       done
       ;;
+    bootup)
+      echo "Removing old Cassandra data and logs"
+      dsh -g ${basename} "rm -rf /var/lib/cassandra/*"
+      dsh -g ${basename} "rm -rf /var/log/cassandra/*"
+
+      echo "Starting Cassandra nodes one by one..."
+      for (( c=1; c<=$nr_nodes; c++ ))
+      do
+	echo "Starting node ${basename}${c}"
+	dsh -g ${basename} -w ${basename}${c} "cd $ONOS_DIR; ./start-cassandra.sh start"
+
+	#Wait until it's up
+	while [ 1 ]; do
+            echo $$
+            dsh -w ${basename}1 "cd $ONOS_DIR; ./start-cassandra.sh status" > .cassandra_check.$$
+            cat .cassandra_check.$$
+            nup=`cat .cassandra_check.$$ | grep Normal |grep Up| wc -l`
+            if [ $nup == $c ]; then
+		echo "New node up: $nup up of of $nr_nodes"
+		break;
+            fi
+            echo "Waiting for new node to come up: $nup up of of $nr_nodes"
+            sleep 5
+	done
+      done
+      ;;
     stop)
       echo "Stopping Cassandra.."
       dsh -g ${basename} "cd $ONOS_DIR; ./start-cassandra.sh stop"
@@ -99,7 +127,9 @@
     start)
       if [ x$2 == "x" -o x$2 == "xall" ]; then
         echo "Starting ONOS on all nodes"
-        dsh -g ${basename} "cd $ONOS_DIR; ./start-onos.sh start"
+        dsh -w ${basename}1 "cd $ONOS_DIR; ./start-onos.sh start"
+        sleep 3
+        dsh -g ${basename} -x ${basename}1 "cd $ONOS_DIR; ./start-onos.sh start"
         dsh -g ${basename} "cd $ONOS_DIR; ./start-rest.sh start"
       else
         echo "Starting ONOS on ${basename}$2"
diff --git a/cluster-mgmt/bin/onos b/cluster-mgmt/bin/onos
index 262c936..b2033ad 100755
--- a/cluster-mgmt/bin/onos
+++ b/cluster-mgmt/bin/onos
@@ -1,5 +1,5 @@
 #! /bin/bash
-. ${HOME}/bin/func.sh
+. `dirname $0`/func.sh
 
 #$0 $1 $2
 `basename $0` $1 $2
diff --git a/cluster-mgmt/bin/zk b/cluster-mgmt/bin/zk
index 262c936..b2033ad 100755
--- a/cluster-mgmt/bin/zk
+++ b/cluster-mgmt/bin/zk
@@ -1,5 +1,5 @@
 #! /bin/bash
-. ${HOME}/bin/func.sh
+. `dirname $0`/func.sh
 
 #$0 $1 $2
 `basename $0` $1 $2
diff --git a/cluster-mgmt/common/onos.properties b/cluster-mgmt/common/onos.properties
index 1828db7..13fca75 100644
--- a/cluster-mgmt/common/onos.properties
+++ b/cluster-mgmt/common/onos.properties
@@ -8,11 +8,11 @@
 net.floodlightcontroller.counter.CounterStore,\
 net.floodlightcontroller.perfmon.PktInProcessingTime,\
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
-net.floodlightcontroller.onoslistener.OnosPublisher, \
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.floodlightcontroller.restserver.RestApiServer.port = 8080
 net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
 net.floodlightcontroller.jython.JythonDebugInterface.port = 6655
 net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
 net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.floodlightcontroller.onoslistener.OnosPublisher.dbconf = /tmp/cassandra.titan
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/cassandra.titan
diff --git a/cluster-mgmt/make-mininet.sh b/cluster-mgmt/make-mininet.sh
index 8571ce0..207b89e 100755
--- a/cluster-mgmt/make-mininet.sh
+++ b/cluster-mgmt/make-mininet.sh
@@ -8,6 +8,9 @@
 fi
 
 basename=$ONOS_CLUSTER_BASENAME
+## Shell Var can't handle "-" so replace it with "_"
+basename_var=`echo $ONOS_CLUSTER_BASENAME | sed 's/\-/_/g'`
+
 NR_NODES=$ONOS_CLUSTER_NR_NODES
 hosts_file=$1
 
@@ -21,14 +24,16 @@
 done
 cp template/onsdemo_core.py ${basename}1/onsdemo.py
 
-cat $hosts_file  | awk '{printf("%s=%s\n",$2,$1)}' > .tmp
+## Shell var can't handle "-" so replace it with "_"
+cat $hosts_file | sed 's/\-/\_/g' | awk '{printf("%s=%s\n",$2,$1)}' > .tmp
+
 for n in `seq 2 $NR_NODES`; do
   cat template/tunnel_onsdemo_edge_template.sh | awk '{if(NR==2){system("cat .tmp")}else{print $0}}' |\
   sed "s/__NWID__/$n/g" |\
-  sed "s/__TUNNEL__/TUNNEL\=\(\"1 $n ${basename}1\"\)/g" > ${basename}${n}/tunnel_onsdemo.sh
+  sed "s/__TUNNEL__/TUNNEL\=\(\"1 $n ${basename_var}1\"\)/g" > ${basename}${n}/tunnel_onsdemo.sh
   chmod 755 ${basename}${n}/tunnel_onsdemo.sh
 done
 
 cat template/tunnel_onsdemo_core_template.sh | awk '{if(NR==2){system("cat .tmp")}else{print $0}}' |\
-  sed "s/__basename__/$basename/g" > ${basename}1/tunnel_onsdemo.sh 
+  sed "s/__basename__/${basename_var}/g" > ${basename}1/tunnel_onsdemo.sh 
   chmod 755 ${basename}1/tunnel_onsdemo.sh
diff --git a/cluster-mgmt/template/onsdemo_core.py b/cluster-mgmt/template/onsdemo_core.py
index 61d2dcc..a0e184e 100755
--- a/cluster-mgmt/template/onsdemo_core.py
+++ b/cluster-mgmt/template/onsdemo_core.py
@@ -65,14 +65,6 @@
         host5 = self.addHost( 'host5' )
         host6 = self.addHost( 'host6' )
 
-        root1 = self.addHost( 'root1', inNamespace=False )
-        root2 = self.addHost( 'root2', inNamespace=False )
-        root3 = self.addHost( 'root3', inNamespace=False )
-        root4 = self.addHost( 'root4', inNamespace=False )
-        root5 = self.addHost( 'root5', inNamespace=False )
-        root6 = self.addHost( 'root6', inNamespace=False )
-
-
         self.addLink( host1, sw1 )
         self.addLink( host2, sw2 )
         self.addLink( host3, sw3 )
@@ -80,7 +72,6 @@
         self.addLink( host5, sw5 )
         self.addLink( host6, sw6 )
 
-
         self.addLink( sw1, sw2 )
         self.addLink( sw1, sw6 )
         self.addLink( sw2, sw3 )
@@ -90,13 +81,6 @@
         self.addLink( sw5, sw6 )
         self.addLink( sw4, sw6 )
 
-        self.addLink( root1, host1 )
-        self.addLink( root2, host2 )
-        self.addLink( root3, host3 )
-        self.addLink( root4, host4 )
-        self.addLink( root5, host5 )
-        self.addLink( root6, host6 )
-
 def startsshd( host ):
     "Start sshd on host"
     info( '*** Starting sshd\n' )
@@ -154,25 +138,6 @@
     host5.defaultIntf().setIP('192.168.100.145/16')
     host6.defaultIntf().setIP('192.168.100.146/16')
 
-    root1, root2, root3, root4, root5, root6  = net.get( 'root1', 'root2', 'root3', 'root4', 'root5', 'root6' )
-    host1.intf('host1-eth1').setIP('1.1.1.1/24')
-    root1.intf('root1-eth0').setIP('1.1.1.2/24')
-
-    host2.intf('host2-eth1') .setIP('1.1.2.1/24')
-    root2.intf('root2-eth0').setIP('1.1.2.2/24')
-
-    host3.intf('host3-eth1') .setIP('1.1.3.1/24')
-    root3.intf('root3-eth0').setIP('1.1.3.2/24')
-
-    host4.intf('host4-eth1') .setIP('1.1.4.1/24')
-    root4.intf('root4-eth0').setIP('1.1.4.2/24')
-
-    host5.intf('host5-eth1') .setIP('1.1.5.1/24')
-    root5.intf('root5-eth0').setIP('1.1.5.2/24')
-
-    host6.intf('host6-eth1') .setIP('1.1.6.1/24')
-    root6.intf('root6-eth0').setIP('1.1.6.2/24')
-
     hosts = [ host1, host2, host3, host4, host5, host6 ]
     stopsshd ()
     startsshds ( hosts )
diff --git a/cluster-mgmt/template/onsdemo_core.py.devA b/cluster-mgmt/template/onsdemo_core.py.devA
new file mode 100755
index 0000000..ad74e4b
--- /dev/null
+++ b/cluster-mgmt/template/onsdemo_core.py.devA
@@ -0,0 +1,158 @@
+#!/usr/bin/python
+
+"""
+Start up a Simple topology
+"""
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info, error, warn, debug
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+from mininet.link import Link, TCLink
+
+from sys import exit
+import os.path
+from subprocess import Popen, STDOUT, PIPE
+
+import sys
+
+
+#import argparse
+
+class MyController( Controller ):
+    def __init__( self, name, ip='127.0.0.1', port=6633, **kwargs):
+        """Init.
+           name: name to give controller
+           ip: the IP address where the remote controller is
+           listening
+           port: the port where the remote controller is listening"""
+        Controller.__init__( self, name, ip=ip, port=port, **kwargs )
+
+    def start( self ):
+        "Overridden to do nothing."
+        return
+
+    def stop( self ):
+        "Overridden to do nothing."
+        return
+
+    def checkListening( self ):
+        "Warn if remote controller is not accessible"
+        listening = self.cmd( "echo A | telnet -e A %s %d" %
+                              ( self.ip, self.port ) )
+        if 'Unable' in listening:
+            warn( "Unable to contact the remote controller"
+                  " at %s:%d\n" % ( self.ip, self.port ) )
+
+class SDNTopo( Topo ):
+    "SDN Topology"
+
+    def __init__( self, *args, **kwargs ):
+        Topo.__init__( self, *args, **kwargs )
+
+        sw5 = self.addSwitch('sw5', dpid='00000000ba5eba13')
+        sw2 = self.addSwitch('sw2', dpid='00000000ba5eba11')
+        sw3 = self.addSwitch('sw3', dpid='00000008a208f901')
+        sw4 = self.addSwitch('sw4', dpid='000000000000ba12')
+        sw6 = self.addSwitch('sw6', dpid='0000204e7f518a35')
+        sw1 = self.addSwitch('sw1', dpid='0000001697089a46')
+
+        host1 = self.addHost( 'host1' )
+        host2 = self.addHost( 'host2' )
+        host3 = self.addHost( 'host3' )
+        host4 = self.addHost( 'host4' )
+        host5 = self.addHost( 'host5' )
+        host6 = self.addHost( 'host6' )
+
+        self.addLink( host1, sw1 )
+        self.addLink( host2, sw2 )
+        self.addLink( host3, sw3 )
+        self.addLink( host4, sw4 )
+        self.addLink( host5, sw5 )
+        self.addLink( host6, sw6 )
+
+        self.addLink( sw1, sw2 )
+        self.addLink( sw1, sw6 )
+        self.addLink( sw2, sw3 )
+        self.addLink( sw3, sw4 )
+        self.addLink( sw3, sw6 )
+        self.addLink( sw4, sw5 )
+        self.addLink( sw5, sw6 )
+        self.addLink( sw4, sw6 )
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd( ):
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def sdnnet(opt):
+#    os.system('/home/ubuntu/openflow/controller/controller ptcp: &')
+#    os.system('/home/ubuntu/openflow/controller/controller ptcp:7000 &')
+
+    topo = SDNTopo()
+    info( '*** Creating network\n' )
+#    net = Mininet( topo=topo, controller=RemoteController )
+    net = Mininet( topo=topo, controller=MyController, link=TCLink)
+#    dc = DebugController('c3', ip='127.0.0.1', port=7000)
+#    net.addController(dc)
+#    net.addController(controller=RemoteController)
+
+    host1, host2, host3, host4, host5, host6 = net.get( 'host1', 'host2', 'host3', 'host4', 'host5', 'host6')
+
+    ## Adding 2nd, 3rd and 4th interface to host1 connected to sw1 (for another BGP peering)
+    sw1 = net.get('sw1')
+    sw2 = net.get('sw2')
+    sw3 = net.get('sw3')
+    sw4 = net.get('sw4')
+    sw5 = net.get('sw5')
+    sw6 = net.get('sw6')
+
+    net.start()
+
+    sw2.attach('tap01_2')
+    sw3.attach('tap01_3')
+    sw4.attach('tap01_4')
+    sw4.attach('tap01_5')
+    sw5.attach('tap01_6')
+    sw6.attach('tap01_7')
+    sw1.attach('tap01_8')
+
+    host1.defaultIntf().setIP('192.168.100.141/16') 
+    host2.defaultIntf().setIP('192.168.100.142/16')
+    host3.defaultIntf().setIP('192.168.100.143/16')
+    host4.defaultIntf().setIP('192.168.100.144/16')
+    host5.defaultIntf().setIP('192.168.100.145/16')
+    host6.defaultIntf().setIP('192.168.100.146/16')
+
+    hosts = [ host1, host2, host3, host4, host5, host6 ]
+    stopsshd ()
+    startsshds ( hosts )
+
+    if opt=="cli":
+        CLI(net)
+        stopsshd()
+        net.stop()
+
+if __name__ == '__main__':
+    setLogLevel( 'info' )
+    if len(sys.argv) == 1:
+      sdnnet("cli")
+    elif len(sys.argv) == 2 and sys.argv[1] == "-n":
+      sdnnet("nocli")
+    else:
+      print "%s [-n]" % sys.argv[0]
diff --git a/cluster-mgmt/template/onsdemo_edge_template.py b/cluster-mgmt/template/onsdemo_edge_template.py
index 1f746f3..e340f38 100755
--- a/cluster-mgmt/template/onsdemo_edge_template.py
+++ b/cluster-mgmt/template/onsdemo_edge_template.py
@@ -56,7 +56,6 @@
 
         switch = []
         host = []
-        root = []
 
         for i in range (NR_NODES):
             name_suffix = '%02d' % NWID + "." + '%02d' % (int(i)+1)
@@ -67,7 +66,6 @@
 
         for i in range (NR_NODES):
             host.append(self.addHost( 'host%d' % (int(i)+1) ))
-            root.append(self.addHost( 'root%d' % (int(i)+1), inNamespace=False ))
 
         for i in range (NR_NODES):
             self.addLink(host[i], switch[i])
@@ -75,9 +73,6 @@
         for i in range (1, NR_NODES):
             self.addLink(switch[0], switch[i])
 
-        for i in range (NR_NODES):
-            self.addLink(root[i], host[i])
-
 def startsshd( host ):
     "Start sshd on host"
     info( '*** Starting sshd\n' )
@@ -139,14 +134,6 @@
          for h in range (25):
            host[i].setARP('192.168.%d.%d' % (n, (int(h)+1)), '00:00:%02x:%02x:%02x:%02x' % (192,168,n,(int(h)+1))) 
 
-    root = []
-    for i in range (NR_NODES):
-        root.append(net.get( 'root%d' % (int(i)+1) ))
-
-    for i in range (NR_NODES):
-        host[i].intf('host%d-eth1' % (int(i)+1)).setIP('1.1.%d.1/24' % (int(i)+1))
-        root[i].intf('root%d-eth0' % (int(i)+1)).setIP('1.1.%d.2/24' % (int(i)+1))
-
     stopsshd ()
 #    stopiperf ()
     startsshds ( host )
diff --git a/conf/README b/conf/README
new file mode 100644
index 0000000..f43d67b
--- /dev/null
+++ b/conf/README
@@ -0,0 +1 @@
+Please use onos-embedded.properties to start onos with embedded cassandra.
diff --git a/cassandra.titan b/conf/cassandra.titan
similarity index 100%
rename from cassandra.titan
rename to conf/cassandra.titan
diff --git a/cassandra.titan.nothrift b/conf/cassandra.titan.nothrift
similarity index 100%
rename from cassandra.titan.nothrift
rename to conf/cassandra.titan.nothrift
diff --git a/conf/cassandra.yaml b/conf/cassandra.yaml
new file mode 100644
index 0000000..277f03a
--- /dev/null
+++ b/conf/cassandra.yaml
@@ -0,0 +1,643 @@
+# Cassandra storage config YAML
+
+# NOTE:
+#   See http://wiki.apache.org/cassandra/StorageConfiguration for
+#   full explanations of configuration directives
+# /NOTE
+
+# The name of the cluster. This is mainly used to prevent machines in
+# one logical cluster from joining another.
+cluster_name: 'Test Cluster'
+
+# This defines the number of tokens randomly assigned to this node on the ring
+# The more tokens, relative to other nodes, the larger the proportion of data
+# that this node will store. You probably want all nodes to have the same number
+# of tokens assuming they have equal hardware capability.
+#
+# If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility,
+# and will use the initial_token as described below.
+#
+# Specifying initial_token will override this setting.
+#
+# If you already have a cluster with 1 token per node, and wish to migrate to
+# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations
+# num_tokens: 256
+
+# If you haven't specified num_tokens, or have set it to the default of 1 then
+# you should always specify InitialToken when setting up a production
+# cluster for the first time, and often when adding capacity later.
+# The principle is that each node should be given an equal slice of
+# the token ring; see http://wiki.apache.org/cassandra/Operations
+# for more details.
+#
+# If blank, Cassandra will request a token bisecting the range of
+# the heaviest-loaded existing node.  If there is no load information
+# available, such as is the case with a new cluster, it will pick
+# a random token, which will lead to hot spots.
+initial_token:
+
+# See http://wiki.apache.org/cassandra/HintedHandoff
+hinted_handoff_enabled: true
+# this defines the maximum amount of time a dead host will have hints
+# generated.  After it has been dead this long, hints will be dropped.
+max_hint_window_in_ms: 10800000 # 3 hours
+# throttle in KB's per second, per delivery thread
+hinted_handoff_throttle_in_kb: 1024
+# Number of threads with which to deliver hints;
+# Consider increasing this number when you have multi-dc deployments, since
+# cross-dc handoff tends to be slower
+max_hints_delivery_threads: 2
+
+# The following setting populates the page cache on memtable flush and compaction
+# WARNING: Enable this setting only when the whole node's data fits in memory.
+# Defaults to: false
+# populate_io_cache_on_flush: false
+
+# authentication backend, implementing IAuthenticator; used to identify users
+authenticator: org.apache.cassandra.auth.AllowAllAuthenticator
+
+# authorization backend, implementing IAuthorizer; used to limit access/provide permissions
+authorizer: org.apache.cassandra.auth.AllowAllAuthorizer
+
+# The partitioner is responsible for distributing rows (by key) across
+# nodes in the cluster.  Any IPartitioner may be used, including your
+# own as long as it is on the classpath.  Out of the box, Cassandra
+# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner
+# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}.
+# 
+# - RandomPartitioner distributes rows across the cluster evenly by md5.
+#   This is the default prior to 1.2 and is retained for compatibility.
+# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128
+#   Hash Function instead of md5.  When in doubt, this is the best option.
+# - ByteOrderedPartitioner orders rows lexically by key bytes.  BOP allows
+#   scanning rows in key order, but the ordering can generate hot spots
+#   for sequential insertion workloads.
+# - OrderPreservingPartitioner is an obsolete form of BOP, that stores
+# - keys in a less-efficient format and only works with keys that are
+#   UTF8-encoded Strings.
+# - CollatingOPP colates according to EN,US rules rather than lexical byte
+#   ordering.  Use this as an example if you need custom collation.
+#
+# See http://wiki.apache.org/cassandra/Operations for more on
+# partitioners and token selection.
+partitioner: org.apache.cassandra.dht.RandomPartitioner
+
+# directories where Cassandra should store data on disk.
+data_file_directories:
+    - /tmp/cassandra/data
+
+# commit log
+commitlog_directory: /tmp/cassandra/commitlog
+
+# policy for data disk failures:
+# stop: shut down gossip and Thrift, leaving the node effectively dead, but
+#       still inspectable via JMX.
+# best_effort: stop using the failed disk and respond to requests based on
+#              remaining available sstables.  This means you WILL see obsolete
+#              data at CL.ONE!
+# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra
+disk_failure_policy: stop
+
+# Maximum size of the key cache in memory.
+#
+# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the
+# minimum, sometimes more. The key cache is fairly tiny for the amount of
+# time it saves, so it's worthwhile to use it at large numbers.
+# The row cache saves even more time, but must store the whole values of
+# its rows, so it is extremely space-intensive. It's best to only use the
+# row cache if you have hot rows or static rows.
+#
+# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup.
+#
+# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache.
+key_cache_size_in_mb:
+
+# Duration in seconds after which Cassandra should
+# safe the keys cache. Caches are saved to saved_caches_directory as
+# specified in this configuration file.
+#
+# Saved caches greatly improve cold-start speeds, and is relatively cheap in
+# terms of I/O for the key cache. Row cache saving is much more expensive and
+# has limited use.
+#
+# Default is 14400 or 4 hours.
+key_cache_save_period: 14400
+
+# Number of keys from the key cache to save
+# Disabled by default, meaning all keys are going to be saved
+# key_cache_keys_to_save: 100
+
+# Maximum size of the row cache in memory.
+# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup.
+#
+# Default value is 0, to disable row caching.
+row_cache_size_in_mb: 0
+
+# Duration in seconds after which Cassandra should
+# safe the row cache. Caches are saved to saved_caches_directory as specified
+# in this configuration file.
+#
+# Saved caches greatly improve cold-start speeds, and is relatively cheap in
+# terms of I/O for the key cache. Row cache saving is much more expensive and
+# has limited use.
+#
+# Default is 0 to disable saving the row cache.
+row_cache_save_period: 0
+
+# Number of keys from the row cache to save
+# Disabled by default, meaning all keys are going to be saved
+# row_cache_keys_to_save: 100
+
+# The provider for the row cache to use.
+#
+# Supported values are: ConcurrentLinkedHashCacheProvider, SerializingCacheProvider
+#
+# SerializingCacheProvider serialises the contents of the row and stores
+# it in native memory, i.e., off the JVM Heap. Serialized rows take
+# significantly less memory than "live" rows in the JVM, so you can cache
+# more rows in a given memory footprint.  And storing the cache off-heap
+# means you can use smaller heap sizes, reducing the impact of GC pauses.
+#
+# It is also valid to specify the fully-qualified class name to a class
+# that implements org.apache.cassandra.cache.IRowCacheProvider.
+#
+# Defaults to SerializingCacheProvider
+row_cache_provider: SerializingCacheProvider
+
+# saved caches
+saved_caches_directory: /tmp/cassandra/saved_caches
+
+# commitlog_sync may be either "periodic" or "batch." 
+# When in batch mode, Cassandra won't ack writes until the commit log
+# has been fsynced to disk.  It will wait up to
+# commitlog_sync_batch_window_in_ms milliseconds for other writes, before
+# performing the sync.
+#
+# commitlog_sync: batch
+# commitlog_sync_batch_window_in_ms: 50
+#
+# the other option is "periodic" where writes may be acked immediately
+# and the CommitLog is simply synced every commitlog_sync_period_in_ms
+# milliseconds.
+commitlog_sync: periodic
+commitlog_sync_period_in_ms: 10000
+
+# The size of the individual commitlog file segments.  A commitlog
+# segment may be archived, deleted, or recycled once all the data
+# in it (potentally from each columnfamily in the system) has been 
+# flushed to sstables.  
+#
+# The default size is 32, which is almost always fine, but if you are
+# archiving commitlog segments (see commitlog_archiving.properties),
+# then you probably want a finer granularity of archiving; 8 or 16 MB
+# is reasonable.
+commitlog_segment_size_in_mb: 32
+
+# any class that implements the SeedProvider interface and has a
+# constructor that takes a Map<String, String> of parameters will do.
+seed_provider:
+    # Addresses of hosts that are deemed contact points. 
+    # Cassandra nodes use this list of hosts to find each other and learn
+    # the topology of the ring.  You must change this if you are running
+    # multiple nodes!
+    - class_name: org.apache.cassandra.locator.SimpleSeedProvider
+      parameters:
+          # seeds is actually a comma-delimited list of addresses.
+          # Ex: "<ip1>,<ip2>,<ip3>"
+          - seeds: "127.0.0.1"
+
+# emergency pressure valve: each time heap usage after a full (CMS)
+# garbage collection is above this fraction of the max, Cassandra will
+# flush the largest memtables.  
+#
+# Set to 1.0 to disable.  Setting this lower than
+# CMSInitiatingOccupancyFraction is not likely to be useful.
+#
+# RELYING ON THIS AS YOUR PRIMARY TUNING MECHANISM WILL WORK POORLY:
+# it is most effective under light to moderate load, or read-heavy
+# workloads; under truly massive write load, it will often be too
+# little, too late.
+flush_largest_memtables_at: 0.75
+
+# emergency pressure valve #2: the first time heap usage after a full
+# (CMS) garbage collection is above this fraction of the max,
+# Cassandra will reduce cache maximum _capacity_ to the given fraction
+# of the current _size_.  Should usually be set substantially above
+# flush_largest_memtables_at, since that will have less long-term
+# impact on the system.  
+# 
+# Set to 1.0 to disable.  Setting this lower than
+# CMSInitiatingOccupancyFraction is not likely to be useful.
+reduce_cache_sizes_at: 0.85
+reduce_cache_capacity_to: 0.6
+
+# For workloads with more data than can fit in memory, Cassandra's
+# bottleneck will be reads that need to fetch data from
+# disk. "concurrent_reads" should be set to (16 * number_of_drives) in
+# order to allow the operations to enqueue low enough in the stack
+# that the OS and drives can reorder them.
+#
+# On the other hand, since writes are almost never IO bound, the ideal
+# number of "concurrent_writes" is dependent on the number of cores in
+# your system; (8 * number_of_cores) is a good rule of thumb.
+concurrent_reads: 32
+concurrent_writes: 32
+
+# Total memory to use for memtables.  Cassandra will flush the largest
+# memtable when this much memory is used.
+# If omitted, Cassandra will set it to 1/3 of the heap.
+# memtable_total_space_in_mb: 2048
+
+# Total space to use for commitlogs.  Since commitlog segments are
+# mmapped, and hence use up address space, the default size is 32
+# on 32-bit JVMs, and 1024 on 64-bit JVMs.
+#
+# If space gets above this value (it will round up to the next nearest
+# segment multiple), Cassandra will flush every dirty CF in the oldest
+# segment and remove it.  So a small total commitlog space will tend
+# to cause more flush activity on less-active columnfamilies.
+# commitlog_total_space_in_mb: 4096
+
+# This sets the amount of memtable flush writer threads.  These will
+# be blocked by disk io, and each one will hold a memtable in memory
+# while blocked. If you have a large heap and many data directories,
+# you can increase this value for better flush performance.
+# By default this will be set to the amount of data directories defined.
+#memtable_flush_writers: 1
+
+# the number of full memtables to allow pending flush, that is,
+# waiting for a writer thread.  At a minimum, this should be set to
+# the maximum number of secondary indexes created on a single CF.
+memtable_flush_queue_size: 4
+
+# Whether to, when doing sequential writing, fsync() at intervals in
+# order to force the operating system to flush the dirty
+# buffers. Enable this to avoid sudden dirty buffer flushing from
+# impacting read latencies. Almost always a good idea on SSD:s; not
+# necessarily on platters.
+trickle_fsync: false
+trickle_fsync_interval_in_kb: 10240
+
+# TCP port, for commands and data
+storage_port: 7000
+
+# SSL port, for encrypted communication.  Unused unless enabled in
+# encryption_options
+ssl_storage_port: 7001
+
+# Address to bind to and tell other Cassandra nodes to connect to. You
+# _must_ change this if you want multiple nodes to be able to
+# communicate!
+# 
+# Leaving it blank leaves it up to InetAddress.getLocalHost(). This
+# will always do the Right Thing *if* the node is properly configured
+# (hostname, name resolution, etc), and the Right Thing is to use the
+# address associated with the hostname (it might not be).
+#
+# Setting this to 0.0.0.0 is always wrong.
+listen_address: localhost
+
+# Address to broadcast to other Cassandra nodes
+# Leaving this blank will set it to the same value as listen_address
+# broadcast_address: 1.2.3.4
+
+
+# Whether to start the native transport server.
+# Currently, only the thrift server is started by default because the native
+# transport is considered beta.
+# Please note that the address on which the native transport is bound is the
+# same as the rpc_address. The port however is different and specified below.
+start_native_transport: false
+# port for the CQL native transport to listen for clients on
+native_transport_port: 9042
+# The minimum and maximum threads for handling requests when the native
+# transport is used. The meaning is those is similar to the one of
+# rpc_min_threads and rpc_max_threads, though the default differ slightly and
+# are the ones below:
+# native_transport_min_threads: 16
+# native_transport_max_threads: 128
+
+
+# Whether to start the thrift rpc server.
+start_rpc: true
+# The address to bind the Thrift RPC service to -- clients connect
+# here. Unlike ListenAddress above, you *can* specify 0.0.0.0 here if
+# you want Thrift to listen on all interfaces.
+# 
+# Leaving this blank has the same effect it does for ListenAddress,
+# (i.e. it will be based on the configured hostname of the node).
+rpc_address: localhost
+# port for Thrift to listen for clients on
+rpc_port: 9160
+
+# enable or disable keepalive on rpc connections
+rpc_keepalive: true
+
+# Cassandra provides three out-of-the-box options for the RPC Server:
+#
+# sync  -> One thread per thrift connection. For a very large number of clients, memory
+#          will be your limiting factor. On a 64 bit JVM, 128KB is the minimum stack size
+#          per thread, and that will correspond to your use of virtual memory (but physical memory
+#          may be limited depending on use of stack space).
+#
+# hsha  -> Stands for "half synchronous, half asynchronous." All thrift clients are handled
+#          asynchronously using a small number of threads that does not vary with the amount
+#          of thrift clients (and thus scales well to many clients). The rpc requests are still
+#          synchronous (one thread per active request).
+#
+# The default is sync because on Windows hsha is about 30% slower.  On Linux,
+# sync/hsha performance is about the same, with hsha of course using less memory.
+#
+# Alternatively,  can provide your own RPC server by providing the fully-qualified class name
+# of an o.a.c.t.TServerFactory that can create an instance of it.
+rpc_server_type: sync
+
+# Uncomment rpc_min|max_thread to set request pool size limits.
+#
+# Regardless of your choice of RPC server (see above), the number of maximum requests in the
+# RPC thread pool dictates how many concurrent requests are possible (but if you are using the sync
+# RPC server, it also dictates the number of clients that can be connected at all).
+#
+# The default is unlimited and thus provide no protection against clients overwhelming the server. You are
+# encouraged to set a maximum that makes sense for you in production, but do keep in mind that
+# rpc_max_threads represents the maximum number of client requests this server may execute concurrently.
+#
+# rpc_min_threads: 16
+# rpc_max_threads: 2048
+
+# uncomment to set socket buffer sizes on rpc connections
+# rpc_send_buff_size_in_bytes:
+# rpc_recv_buff_size_in_bytes:
+
+# Frame size for thrift (maximum field length).
+thrift_framed_transport_size_in_mb: 15
+
+# The max length of a thrift message, including all fields and
+# internal thrift overhead.
+thrift_max_message_length_in_mb: 16
+
+# Set to true to have Cassandra create a hard link to each sstable
+# flushed or streamed locally in a backups/ subdirectory of the
+# Keyspace data.  Removing these links is the operator's
+# responsibility.
+incremental_backups: false
+
+# Whether or not to take a snapshot before each compaction.  Be
+# careful using this option, since Cassandra won't clean up the
+# snapshots for you.  Mostly useful if you're paranoid when there
+# is a data format change.
+snapshot_before_compaction: false
+
+# Whether or not a snapshot is taken of the data before keyspace truncation
+# or dropping of column families. The STRONGLY advised default of true 
+# should be used to provide data safety. If you set this flag to false, you will
+# lose data on truncation or drop.
+auto_snapshot: true
+
+# Add column indexes to a row after its contents reach this size.
+# Increase if your column values are large, or if you have a very large
+# number of columns.  The competing causes are, Cassandra has to
+# deserialize this much of the row to read a single column, so you want
+# it to be small - at least if you do many partial-row reads - but all
+# the index data is read for each access, so you don't want to generate
+# that wastefully either.
+column_index_size_in_kb: 64
+
+# Size limit for rows being compacted in memory.  Larger rows will spill
+# over to disk and use a slower two-pass compaction process.  A message
+# will be logged specifying the row key.
+in_memory_compaction_limit_in_mb: 64
+
+# Number of simultaneous compactions to allow, NOT including
+# validation "compactions" for anti-entropy repair.  Simultaneous
+# compactions can help preserve read performance in a mixed read/write
+# workload, by mitigating the tendency of small sstables to accumulate
+# during a single long running compactions. The default is usually
+# fine and if you experience problems with compaction running too
+# slowly or too fast, you should look at
+# compaction_throughput_mb_per_sec first.
+#
+# concurrent_compactors defaults to the number of cores.
+# Uncomment to make compaction mono-threaded, the pre-0.8 default.
+#concurrent_compactors: 1
+
+# Multi-threaded compaction. When enabled, each compaction will use
+# up to one thread per core, plus one thread per sstable being merged.
+# This is usually only useful for SSD-based hardware: otherwise, 
+# your concern is usually to get compaction to do LESS i/o (see:
+# compaction_throughput_mb_per_sec), not more.
+multithreaded_compaction: false
+
+# Throttles compaction to the given total throughput across the entire
+# system. The faster you insert data, the faster you need to compact in
+# order to keep the sstable count down, but in general, setting this to
+# 16 to 32 times the rate you are inserting data is more than sufficient.
+# Setting this to 0 disables throttling. Note that this account for all types
+# of compaction, including validation compaction.
+compaction_throughput_mb_per_sec: 16
+
+# Track cached row keys during compaction, and re-cache their new
+# positions in the compacted sstable.  Disable if you use really large
+# key caches.
+compaction_preheat_key_cache: true
+
+# Throttles all outbound streaming file transfers on this node to the
+# given total throughput in Mbps. This is necessary because Cassandra does
+# mostly sequential IO when streaming data during bootstrap or repair, which
+# can lead to saturating the network connection and degrading rpc performance.
+# When unset, the default is 400 Mbps or 50 MB/s.
+# stream_throughput_outbound_megabits_per_sec: 400
+
+# How long the coordinator should wait for read operations to complete
+read_request_timeout_in_ms: 10000
+# How long the coordinator should wait for seq or index scans to complete
+range_request_timeout_in_ms: 10000
+# How long the coordinator should wait for writes to complete
+write_request_timeout_in_ms: 10000
+# How long the coordinator should wait for truncates to complete
+# (This can be much longer, because unless auto_snapshot is disabled
+# we need to flush first so we can snapshot before removing the data.)
+truncate_request_timeout_in_ms: 60000
+# The default timeout for other, miscellaneous operations
+request_timeout_in_ms: 10000
+
+# Enable operation timeout information exchange between nodes to accurately
+# measure request timeouts, If disabled cassandra will assuming the request
+# was forwarded to the replica instantly by the coordinator
+#
+# Warning: before enabling this property make sure to ntp is installed
+# and the times are synchronized between the nodes.
+cross_node_timeout: false
+
+# Enable socket timeout for streaming operation.
+# When a timeout occurs during streaming, streaming is retried from the start
+# of the current file. This *can* involve re-streaming an important amount of
+# data, so you should avoid setting the value too low.
+# Default value is 0, which never timeout streams.
+# streaming_socket_timeout_in_ms: 0
+
+# phi value that must be reached for a host to be marked down.
+# most users should never need to adjust this.
+# phi_convict_threshold: 8
+
+# endpoint_snitch -- Set this to a class that implements
+# IEndpointSnitch.  The snitch has two functions:
+# - it teaches Cassandra enough about your network topology to route
+#   requests efficiently
+# - it allows Cassandra to spread replicas around your cluster to avoid
+#   correlated failures. It does this by grouping machines into
+#   "datacenters" and "racks."  Cassandra will do its best not to have
+#   more than one replica on the same "rack" (which may not actually
+#   be a physical location)
+#
+# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER,
+# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS
+# ARE PLACED.
+#
+# Out of the box, Cassandra provides
+#  - SimpleSnitch:
+#    Treats Strategy order as proximity. This improves cache locality
+#    when disabling read repair, which can further improve throughput.
+#    Only appropriate for single-datacenter deployments.
+#  - PropertyFileSnitch:
+#    Proximity is determined by rack and data center, which are
+#    explicitly configured in cassandra-topology.properties.
+#  - GossipingPropertyFileSnitch
+#    The rack and datacenter for the local node are defined in
+#    cassandra-rackdc.properties and propagated to other nodes via gossip.  If
+#    cassandra-topology.properties exists, it is used as a fallback, allowing
+#    migration from the PropertyFileSnitch.
+#  - RackInferringSnitch:
+#    Proximity is determined by rack and data center, which are
+#    assumed to correspond to the 3rd and 2nd octet of each node's
+#    IP address, respectively.  Unless this happens to match your
+#    deployment conventions (as it did Facebook's), this is best used
+#    as an example of writing a custom Snitch class.
+#  - Ec2Snitch:
+#    Appropriate for EC2 deployments in a single Region.  Loads Region
+#    and Availability Zone information from the EC2 API. The Region is
+#    treated as the Datacenter, and the Availability Zone as the rack.
+#    Only private IPs are used, so this will not work across multiple
+#    Regions.
+#  - Ec2MultiRegionSnitch:
+#    Uses public IPs as broadcast_address to allow cross-region
+#    connectivity.  (Thus, you should set seed addresses to the public
+#    IP as well.) You will need to open the storage_port or
+#    ssl_storage_port on the public IP firewall.  (For intra-Region
+#    traffic, Cassandra will switch to the private IP after
+#    establishing a connection.)
+#
+# You can use a custom Snitch by setting this to the full class name
+# of the snitch, which will be assumed to be on your classpath.
+endpoint_snitch: SimpleSnitch
+
+# controls how often to perform the more expensive part of host score
+# calculation
+dynamic_snitch_update_interval_in_ms: 100 
+# controls how often to reset all host scores, allowing a bad host to
+# possibly recover
+dynamic_snitch_reset_interval_in_ms: 600000
+# if set greater than zero and read_repair_chance is < 1.0, this will allow
+# 'pinning' of replicas to hosts in order to increase cache capacity.
+# The badness threshold will control how much worse the pinned host has to be
+# before the dynamic snitch will prefer other replicas over it.  This is
+# expressed as a double which represents a percentage.  Thus, a value of
+# 0.2 means Cassandra would continue to prefer the static snitch values
+# until the pinned host was 20% worse than the fastest.
+dynamic_snitch_badness_threshold: 0.1
+
+# request_scheduler -- Set this to a class that implements
+# RequestScheduler, which will schedule incoming client requests
+# according to the specific policy. This is useful for multi-tenancy
+# with a single Cassandra cluster.
+# NOTE: This is specifically for requests from the client and does
+# not affect inter node communication.
+# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place
+# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of
+# client requests to a node with a separate queue for each
+# request_scheduler_id. The scheduler is further customized by
+# request_scheduler_options as described below.
+request_scheduler: org.apache.cassandra.scheduler.NoScheduler
+
+# Scheduler Options vary based on the type of scheduler
+# NoScheduler - Has no options
+# RoundRobin
+#  - throttle_limit -- The throttle_limit is the number of in-flight
+#                      requests per client.  Requests beyond 
+#                      that limit are queued up until
+#                      running requests can complete.
+#                      The value of 80 here is twice the number of
+#                      concurrent_reads + concurrent_writes.
+#  - default_weight -- default_weight is optional and allows for
+#                      overriding the default which is 1.
+#  - weights -- Weights are optional and will default to 1 or the
+#               overridden default_weight. The weight translates into how
+#               many requests are handled during each turn of the
+#               RoundRobin, based on the scheduler id.
+#
+# request_scheduler_options:
+#    throttle_limit: 80
+#    default_weight: 5
+#    weights:
+#      Keyspace1: 1
+#      Keyspace2: 5
+
+# request_scheduler_id -- An identifer based on which to perform
+# the request scheduling. Currently the only valid option is keyspace.
+# request_scheduler_id: keyspace
+
+# index_interval controls the sampling of entries from the primrary
+# row index in terms of space versus time.  The larger the interval,
+# the smaller and less effective the sampling will be.  In technicial
+# terms, the interval coresponds to the number of index entries that
+# are skipped between taking each sample.  All the sampled entries
+# must fit in memory.  Generally, a value between 128 and 512 here
+# coupled with a large key cache size on CFs results in the best trade
+# offs.  This value is not often changed, however if you have many
+# very small rows (many to an OS page), then increasing this will
+# often lower memory usage without a impact on performance.
+index_interval: 128
+
+# Enable or disable inter-node encryption
+# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that
+# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher
+# suite for authentication, key exchange and encryption of the actual data transfers.
+# NOTE: No custom encryption options are enabled at the moment
+# The available internode options are : all, none, dc, rack
+#
+# If set to dc cassandra will encrypt the traffic between the DCs
+# If set to rack cassandra will encrypt the traffic between the racks
+#
+# The passwords used in these options must match the passwords used when generating
+# the keystore and truststore.  For instructions on generating these files, see:
+# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore
+#
+server_encryption_options:
+    internode_encryption: none
+    keystore: conf/.keystore
+    keystore_password: cassandra
+    truststore: conf/.truststore
+    truststore_password: cassandra
+    # More advanced defaults below:
+    # protocol: TLS
+    # algorithm: SunX509
+    # store_type: JKS
+    # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA]
+
+# enable or disable client/server encryption.
+client_encryption_options:
+    enabled: false
+    keystore: conf/.keystore
+    keystore_password: cassandra
+    # More advanced defaults below:
+    # protocol: TLS
+    # algorithm: SunX509
+    # store_type: JKS
+    # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA]
+
+# internode_compression controls whether traffic between nodes is
+# compressed.
+# can be:  all  - all traffic is compressed
+#          dc   - traffic between different datacenters is compressed
+#          none - nothing is compressed.
+internode_compression: all
diff --git a/conf/onos-embedded.properties b/conf/onos-embedded.properties
new file mode 100644
index 0000000..83e5ad3
--- /dev/null
+++ b/conf/onos-embedded.properties
@@ -0,0 +1,17 @@
+floodlight.modules = net.floodlightcontroller.storage.memory.MemoryStorageSource,\
+net.floodlightcontroller.core.FloodlightProvider,\
+net.floodlightcontroller.threadpool.ThreadPool,\
+net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl,\
+net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,\
+net.floodlightcontroller.counter.CounterStore,\
+net.floodlightcontroller.perfmon.PktInProcessingTime,\
+net.floodlightcontroller.ui.web.StaticWebRoutable,\
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
+net.onrc.onos.registry.controller.ZookeeperRegistry
+net.floodlightcontroller.restserver.RestApiServer.port = 8080
+net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
+net.floodlightcontroller.core.FloodlightProvider.workerthreads = 48
+net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
+net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = conf/titan-embedded.properties
+
diff --git a/conf/onos.properties b/conf/onos.properties
index 668da42..c1e2d27 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -6,13 +6,12 @@
 net.floodlightcontroller.counter.CounterStore,\
 net.floodlightcontroller.perfmon.PktInProcessingTime,\
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
-net.floodlightcontroller.onoslistener.OnosPublisher, \
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.floodlightcontroller.restserver.RestApiServer.port = 8080
 net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
 net.floodlightcontroller.core.FloodlightProvider.workerthreads = 16
-net.floodlightcontroller.jython.JythonDebugInterface.port = 6655
 net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
 net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.floodlightcontroller.onoslistener.OnosPublisher.dbconf = /tmp/cassandra.titan
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/cassandra.titan
 
diff --git a/conf/titan-embedded.properties b/conf/titan-embedded.properties
new file mode 100644
index 0000000..7a28afb
--- /dev/null
+++ b/conf/titan-embedded.properties
@@ -0,0 +1,6 @@
+storage.backend=embeddedcassandra
+storage.cassandra-config-dir=file:conf/cassandra.yaml
+storage.keyspace=onos
+storage.replication-factor=1
+storage.write-consistency-level=ALL
+storage.read-consistency-level=ONE
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java
deleted file mode 100644
index d1ef80b..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Constants.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.EnumMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.EnumSet;
-import java.util.Collections;
-import java.util.BitSet;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("all") public class Constants {
-
-  public static final String VERSION = "0.1.0";
-
-}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java
deleted file mode 100644
index 8e4d989..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Message.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.EnumMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.EnumSet;
-import java.util.Collections;
-import java.util.BitSet;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("all") public class Message implements org.apache.thrift.TBase<Message, Message._Fields>, java.io.Serializable, Cloneable {
-  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Message");
-
-  private static final org.apache.thrift.protocol.TField SESSION_IDS_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionIDs", org.apache.thrift.protocol.TType.LIST, (short)1);
-  private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)2);
-
-  public List<String> sessionIDs; // required
-  public Packet packet; // required
-
-  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-    SESSION_IDS((short)1, "sessionIDs"),
-    PACKET((short)2, "packet");
-
-    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-    static {
-      for (_Fields field : EnumSet.allOf(_Fields.class)) {
-        byName.put(field.getFieldName(), field);
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, or null if its not found.
-     */
-    public static _Fields findByThriftId(int fieldId) {
-      switch(fieldId) {
-        case 1: // SESSION_IDS
-          return SESSION_IDS;
-        case 2: // PACKET
-          return PACKET;
-        default:
-          return null;
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, throwing an exception
-     * if it is not found.
-     */
-    public static _Fields findByThriftIdOrThrow(int fieldId) {
-      _Fields fields = findByThriftId(fieldId);
-      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-      return fields;
-    }
-
-    /**
-     * Find the _Fields constant that matches name, or null if its not found.
-     */
-    public static _Fields findByName(String name) {
-      return byName.get(name);
-    }
-
-    private final short _thriftId;
-    private final String _fieldName;
-
-    _Fields(short thriftId, String fieldName) {
-      _thriftId = thriftId;
-      _fieldName = fieldName;
-    }
-
-    public short getThriftFieldId() {
-      return _thriftId;
-    }
-
-    public String getFieldName() {
-      return _fieldName;
-    }
-  }
-
-  // isset id assignments
-
-  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-  static {
-    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.SESSION_IDS, new org.apache.thrift.meta_data.FieldMetaData("sessionIDs", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
-            new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
-    tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Packet.class)));
-    metaDataMap = Collections.unmodifiableMap(tmpMap);
-    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Message.class, metaDataMap);
-  }
-
-  public Message() {
-  }
-
-  public Message(
-    List<String> sessionIDs,
-    Packet packet)
-  {
-    this();
-    this.sessionIDs = sessionIDs;
-    this.packet = packet;
-  }
-
-  /**
-   * Performs a deep copy on <i>other</i>.
-   */
-  public Message(Message other) {
-    if (other.isSetSessionIDs()) {
-      List<String> __this__sessionIDs = new ArrayList<String>();
-      for (String other_element : other.sessionIDs) {
-        __this__sessionIDs.add(other_element);
-      }
-      this.sessionIDs = __this__sessionIDs;
-    }
-    if (other.isSetPacket()) {
-      this.packet = new Packet(other.packet);
-    }
-  }
-
-  public Message deepCopy() {
-    return new Message(this);
-  }
-
-  @Override
-  public void clear() {
-    this.sessionIDs = null;
-    this.packet = null;
-  }
-
-  public int getSessionIDsSize() {
-    return (this.sessionIDs == null) ? 0 : this.sessionIDs.size();
-  }
-
-  public java.util.Iterator<String> getSessionIDsIterator() {
-    return (this.sessionIDs == null) ? null : this.sessionIDs.iterator();
-  }
-
-  public void addToSessionIDs(String elem) {
-    if (this.sessionIDs == null) {
-      this.sessionIDs = new ArrayList<String>();
-    }
-    this.sessionIDs.add(elem);
-  }
-
-  public List<String> getSessionIDs() {
-    return this.sessionIDs;
-  }
-
-  public Message setSessionIDs(List<String> sessionIDs) {
-    this.sessionIDs = sessionIDs;
-    return this;
-  }
-
-  public void unsetSessionIDs() {
-    this.sessionIDs = null;
-  }
-
-  /** Returns true if field sessionIDs is set (has been assigned a value) and false otherwise */
-  public boolean isSetSessionIDs() {
-    return this.sessionIDs != null;
-  }
-
-  public void setSessionIDsIsSet(boolean value) {
-    if (!value) {
-      this.sessionIDs = null;
-    }
-  }
-
-  public Packet getPacket() {
-    return this.packet;
-  }
-
-  public Message setPacket(Packet packet) {
-    this.packet = packet;
-    return this;
-  }
-
-  public void unsetPacket() {
-    this.packet = null;
-  }
-
-  /** Returns true if field packet is set (has been assigned a value) and false otherwise */
-  public boolean isSetPacket() {
-    return this.packet != null;
-  }
-
-  public void setPacketIsSet(boolean value) {
-    if (!value) {
-      this.packet = null;
-    }
-  }
-
-  public void setFieldValue(_Fields field, Object value) {
-    switch (field) {
-    case SESSION_IDS:
-      if (value == null) {
-        unsetSessionIDs();
-      } else {
-        setSessionIDs((List<String>)value);
-      }
-      break;
-
-    case PACKET:
-      if (value == null) {
-        unsetPacket();
-      } else {
-        setPacket((Packet)value);
-      }
-      break;
-
-    }
-  }
-
-  public Object getFieldValue(_Fields field) {
-    switch (field) {
-    case SESSION_IDS:
-      return getSessionIDs();
-
-    case PACKET:
-      return getPacket();
-
-    }
-    throw new IllegalStateException();
-  }
-
-  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-  public boolean isSet(_Fields field) {
-    if (field == null) {
-      throw new IllegalArgumentException();
-    }
-
-    switch (field) {
-    case SESSION_IDS:
-      return isSetSessionIDs();
-    case PACKET:
-      return isSetPacket();
-    }
-    throw new IllegalStateException();
-  }
-
-  @Override
-  public boolean equals(Object that) {
-    if (that == null)
-      return false;
-    if (that instanceof Message)
-      return this.equals((Message)that);
-    return false;
-  }
-
-  public boolean equals(Message that) {
-    if (that == null)
-      return false;
-
-    boolean this_present_sessionIDs = true && this.isSetSessionIDs();
-    boolean that_present_sessionIDs = true && that.isSetSessionIDs();
-    if (this_present_sessionIDs || that_present_sessionIDs) {
-      if (!(this_present_sessionIDs && that_present_sessionIDs))
-        return false;
-      if (!this.sessionIDs.equals(that.sessionIDs))
-        return false;
-    }
-
-    boolean this_present_packet = true && this.isSetPacket();
-    boolean that_present_packet = true && that.isSetPacket();
-    if (this_present_packet || that_present_packet) {
-      if (!(this_present_packet && that_present_packet))
-        return false;
-      if (!this.packet.equals(that.packet))
-        return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    return 0;
-  }
-
-  public int compareTo(Message other) {
-    if (!getClass().equals(other.getClass())) {
-      return getClass().getName().compareTo(other.getClass().getName());
-    }
-
-    int lastComparison = 0;
-    Message typedOther = (Message)other;
-
-    lastComparison = Boolean.valueOf(isSetSessionIDs()).compareTo(typedOther.isSetSessionIDs());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetSessionIDs()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionIDs, typedOther.sessionIDs);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetPacket()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    return 0;
-  }
-
-  public _Fields fieldForId(int fieldId) {
-    return _Fields.findByThriftId(fieldId);
-  }
-
-  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-    org.apache.thrift.protocol.TField field;
-    iprot.readStructBegin();
-    while (true)
-    {
-      field = iprot.readFieldBegin();
-      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-        break;
-      }
-      switch (field.id) {
-        case 1: // SESSION_IDS
-          if (field.type == org.apache.thrift.protocol.TType.LIST) {
-            {
-              org.apache.thrift.protocol.TList _list0 = iprot.readListBegin();
-              this.sessionIDs = new ArrayList<String>(_list0.size);
-              for (int _i1 = 0; _i1 < _list0.size; ++_i1)
-              {
-                String _elem2; // required
-                _elem2 = iprot.readString();
-                this.sessionIDs.add(_elem2);
-              }
-              iprot.readListEnd();
-            }
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        case 2: // PACKET
-          if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
-            this.packet = new Packet();
-            this.packet.read(iprot);
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        default:
-          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-      }
-      iprot.readFieldEnd();
-    }
-    iprot.readStructEnd();
-
-    // check for required fields of primitive type, which can't be checked in the validate method
-    validate();
-  }
-
-  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-    validate();
-
-    oprot.writeStructBegin(STRUCT_DESC);
-    if (this.sessionIDs != null) {
-      oprot.writeFieldBegin(SESSION_IDS_FIELD_DESC);
-      {
-        oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.sessionIDs.size()));
-        for (String _iter3 : this.sessionIDs)
-        {
-          oprot.writeString(_iter3);
-        }
-        oprot.writeListEnd();
-      }
-      oprot.writeFieldEnd();
-    }
-    if (this.packet != null) {
-      oprot.writeFieldBegin(PACKET_FIELD_DESC);
-      this.packet.write(oprot);
-      oprot.writeFieldEnd();
-    }
-    oprot.writeFieldStop();
-    oprot.writeStructEnd();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("Message(");
-    boolean first = true;
-
-    sb.append("sessionIDs:");
-    if (this.sessionIDs == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.sessionIDs);
-    }
-    first = false;
-    if (!first) sb.append(", ");
-    sb.append("packet:");
-    if (this.packet == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.packet);
-    }
-    first = false;
-    sb.append(")");
-    return sb.toString();
-  }
-
-  public void validate() throws org.apache.thrift.TException {
-    // check for required fields
-  }
-
-  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-    try {
-      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-    try {
-      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-}
-
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java
deleted file mode 100644
index b9b2843..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/OFMessageType.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-
-import java.util.Map;
-import java.util.HashMap;
-import org.apache.thrift.TEnum;
-
-/**
- * OFMessage type
- * 
- */
-@SuppressWarnings("all") public enum OFMessageType implements org.apache.thrift.TEnum {
-  HELLO(0),
-  ERROR(1),
-  ECHO_REQUEST(2),
-  ECHO_REPLY(3),
-  VENDOR(4),
-  FEATURES_REQUEST(5),
-  FEATURES_REPLY(6),
-  GET_CONFIG_REQUEST(7),
-  GET_CONFIG_REPLY(8),
-  SET_CONFIG(9),
-  PACKET_IN(10),
-  FLOW_REMOVED(11),
-  PORT_STATUS(12),
-  PACKET_OUT(13),
-  FLOW_MOD(14),
-  PORT_MOD(15),
-  STATS_REQUEST(16),
-  STATS_REPLY(17),
-  BARRIER_REQUEST(18),
-  BARRIER_REPLY(19);
-
-  private final int value;
-
-  private OFMessageType(int value) {
-    this.value = value;
-  }
-
-  /**
-   * Get the integer value of this enum value, as defined in the Thrift IDL.
-   */
-  public int getValue() {
-    return value;
-  }
-
-  /**
-   * Find a the enum type by its integer value, as defined in the Thrift IDL.
-   * @return null if the value is not found.
-   */
-  public static OFMessageType findByValue(int value) { 
-    switch (value) {
-      case 0:
-        return HELLO;
-      case 1:
-        return ERROR;
-      case 2:
-        return ECHO_REQUEST;
-      case 3:
-        return ECHO_REPLY;
-      case 4:
-        return VENDOR;
-      case 5:
-        return FEATURES_REQUEST;
-      case 6:
-        return FEATURES_REPLY;
-      case 7:
-        return GET_CONFIG_REQUEST;
-      case 8:
-        return GET_CONFIG_REPLY;
-      case 9:
-        return SET_CONFIG;
-      case 10:
-        return PACKET_IN;
-      case 11:
-        return FLOW_REMOVED;
-      case 12:
-        return PORT_STATUS;
-      case 13:
-        return PACKET_OUT;
-      case 14:
-        return FLOW_MOD;
-      case 15:
-        return PORT_MOD;
-      case 16:
-        return STATS_REQUEST;
-      case 17:
-        return STATS_REPLY;
-      case 18:
-        return BARRIER_REQUEST;
-      case 19:
-        return BARRIER_REPLY;
-      default:
-        return null;
-    }
-  }
-}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java
deleted file mode 100644
index 65c140f..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/Packet.java
+++ /dev/null
@@ -1,525 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.EnumMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.EnumSet;
-import java.util.Collections;
-import java.util.BitSet;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("all") public class Packet implements org.apache.thrift.TBase<Packet, Packet._Fields>, java.io.Serializable, Cloneable {
-  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Packet");
-
-  private static final org.apache.thrift.protocol.TField MESSAGE_TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("messageType", org.apache.thrift.protocol.TType.I32, (short)1);
-  private static final org.apache.thrift.protocol.TField SW_PORT_TUPLE_FIELD_DESC = new org.apache.thrift.protocol.TField("swPortTuple", org.apache.thrift.protocol.TType.STRUCT, (short)2);
-  private static final org.apache.thrift.protocol.TField DATA_FIELD_DESC = new org.apache.thrift.protocol.TField("data", org.apache.thrift.protocol.TType.STRING, (short)3);
-
-  /**
-   * 
-   * @see OFMessageType
-   */
-  public OFMessageType messageType; // required
-  public SwitchPortTuple swPortTuple; // required
-  public ByteBuffer data; // required
-
-  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-    /**
-     * 
-     * @see OFMessageType
-     */
-    MESSAGE_TYPE((short)1, "messageType"),
-    SW_PORT_TUPLE((short)2, "swPortTuple"),
-    DATA((short)3, "data");
-
-    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-    static {
-      for (_Fields field : EnumSet.allOf(_Fields.class)) {
-        byName.put(field.getFieldName(), field);
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, or null if its not found.
-     */
-    public static _Fields findByThriftId(int fieldId) {
-      switch(fieldId) {
-        case 1: // MESSAGE_TYPE
-          return MESSAGE_TYPE;
-        case 2: // SW_PORT_TUPLE
-          return SW_PORT_TUPLE;
-        case 3: // DATA
-          return DATA;
-        default:
-          return null;
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, throwing an exception
-     * if it is not found.
-     */
-    public static _Fields findByThriftIdOrThrow(int fieldId) {
-      _Fields fields = findByThriftId(fieldId);
-      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-      return fields;
-    }
-
-    /**
-     * Find the _Fields constant that matches name, or null if its not found.
-     */
-    public static _Fields findByName(String name) {
-      return byName.get(name);
-    }
-
-    private final short _thriftId;
-    private final String _fieldName;
-
-    _Fields(short thriftId, String fieldName) {
-      _thriftId = thriftId;
-      _fieldName = fieldName;
-    }
-
-    public short getThriftFieldId() {
-      return _thriftId;
-    }
-
-    public String getFieldName() {
-      return _fieldName;
-    }
-  }
-
-  // isset id assignments
-
-  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-  static {
-    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.MESSAGE_TYPE, new org.apache.thrift.meta_data.FieldMetaData("messageType", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, OFMessageType.class)));
-    tmpMap.put(_Fields.SW_PORT_TUPLE, new org.apache.thrift.meta_data.FieldMetaData("swPortTuple", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, SwitchPortTuple.class)));
-    tmpMap.put(_Fields.DATA, new org.apache.thrift.meta_data.FieldMetaData("data", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING        , true)));
-    metaDataMap = Collections.unmodifiableMap(tmpMap);
-    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Packet.class, metaDataMap);
-  }
-
-  public Packet() {
-  }
-
-  public Packet(
-    OFMessageType messageType,
-    SwitchPortTuple swPortTuple,
-    ByteBuffer data)
-  {
-    this();
-    this.messageType = messageType;
-    this.swPortTuple = swPortTuple;
-    this.data = data;
-  }
-
-  /**
-   * Performs a deep copy on <i>other</i>.
-   */
-  public Packet(Packet other) {
-    if (other.isSetMessageType()) {
-      this.messageType = other.messageType;
-    }
-    if (other.isSetSwPortTuple()) {
-      this.swPortTuple = new SwitchPortTuple(other.swPortTuple);
-    }
-    if (other.isSetData()) {
-      this.data = org.apache.thrift.TBaseHelper.copyBinary(other.data);
-;
-    }
-  }
-
-  public Packet deepCopy() {
-    return new Packet(this);
-  }
-
-  @Override
-  public void clear() {
-    this.messageType = null;
-    this.swPortTuple = null;
-    this.data = null;
-  }
-
-  /**
-   * 
-   * @see OFMessageType
-   */
-  public OFMessageType getMessageType() {
-    return this.messageType;
-  }
-
-  /**
-   * 
-   * @see OFMessageType
-   */
-  public Packet setMessageType(OFMessageType messageType) {
-    this.messageType = messageType;
-    return this;
-  }
-
-  public void unsetMessageType() {
-    this.messageType = null;
-  }
-
-  /** Returns true if field messageType is set (has been assigned a value) and false otherwise */
-  public boolean isSetMessageType() {
-    return this.messageType != null;
-  }
-
-  public void setMessageTypeIsSet(boolean value) {
-    if (!value) {
-      this.messageType = null;
-    }
-  }
-
-  public SwitchPortTuple getSwPortTuple() {
-    return this.swPortTuple;
-  }
-
-  public Packet setSwPortTuple(SwitchPortTuple swPortTuple) {
-    this.swPortTuple = swPortTuple;
-    return this;
-  }
-
-  public void unsetSwPortTuple() {
-    this.swPortTuple = null;
-  }
-
-  /** Returns true if field swPortTuple is set (has been assigned a value) and false otherwise */
-  public boolean isSetSwPortTuple() {
-    return this.swPortTuple != null;
-  }
-
-  public void setSwPortTupleIsSet(boolean value) {
-    if (!value) {
-      this.swPortTuple = null;
-    }
-  }
-
-  public byte[] getData() {
-    setData(org.apache.thrift.TBaseHelper.rightSize(data));
-    return data == null ? null : data.array();
-  }
-
-  public ByteBuffer bufferForData() {
-    return data;
-  }
-
-  public Packet setData(byte[] data) {
-    setData(data == null ? (ByteBuffer)null : ByteBuffer.wrap(data));
-    return this;
-  }
-
-  public Packet setData(ByteBuffer data) {
-    this.data = data;
-    return this;
-  }
-
-  public void unsetData() {
-    this.data = null;
-  }
-
-  /** Returns true if field data is set (has been assigned a value) and false otherwise */
-  public boolean isSetData() {
-    return this.data != null;
-  }
-
-  public void setDataIsSet(boolean value) {
-    if (!value) {
-      this.data = null;
-    }
-  }
-
-  public void setFieldValue(_Fields field, Object value) {
-    switch (field) {
-    case MESSAGE_TYPE:
-      if (value == null) {
-        unsetMessageType();
-      } else {
-        setMessageType((OFMessageType)value);
-      }
-      break;
-
-    case SW_PORT_TUPLE:
-      if (value == null) {
-        unsetSwPortTuple();
-      } else {
-        setSwPortTuple((SwitchPortTuple)value);
-      }
-      break;
-
-    case DATA:
-      if (value == null) {
-        unsetData();
-      } else {
-        setData((ByteBuffer)value);
-      }
-      break;
-
-    }
-  }
-
-  public Object getFieldValue(_Fields field) {
-    switch (field) {
-    case MESSAGE_TYPE:
-      return getMessageType();
-
-    case SW_PORT_TUPLE:
-      return getSwPortTuple();
-
-    case DATA:
-      return getData();
-
-    }
-    throw new IllegalStateException();
-  }
-
-  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-  public boolean isSet(_Fields field) {
-    if (field == null) {
-      throw new IllegalArgumentException();
-    }
-
-    switch (field) {
-    case MESSAGE_TYPE:
-      return isSetMessageType();
-    case SW_PORT_TUPLE:
-      return isSetSwPortTuple();
-    case DATA:
-      return isSetData();
-    }
-    throw new IllegalStateException();
-  }
-
-  @Override
-  public boolean equals(Object that) {
-    if (that == null)
-      return false;
-    if (that instanceof Packet)
-      return this.equals((Packet)that);
-    return false;
-  }
-
-  public boolean equals(Packet that) {
-    if (that == null)
-      return false;
-
-    boolean this_present_messageType = true && this.isSetMessageType();
-    boolean that_present_messageType = true && that.isSetMessageType();
-    if (this_present_messageType || that_present_messageType) {
-      if (!(this_present_messageType && that_present_messageType))
-        return false;
-      if (!this.messageType.equals(that.messageType))
-        return false;
-    }
-
-    boolean this_present_swPortTuple = true && this.isSetSwPortTuple();
-    boolean that_present_swPortTuple = true && that.isSetSwPortTuple();
-    if (this_present_swPortTuple || that_present_swPortTuple) {
-      if (!(this_present_swPortTuple && that_present_swPortTuple))
-        return false;
-      if (!this.swPortTuple.equals(that.swPortTuple))
-        return false;
-    }
-
-    boolean this_present_data = true && this.isSetData();
-    boolean that_present_data = true && that.isSetData();
-    if (this_present_data || that_present_data) {
-      if (!(this_present_data && that_present_data))
-        return false;
-      if (!this.data.equals(that.data))
-        return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    return 0;
-  }
-
-  public int compareTo(Packet other) {
-    if (!getClass().equals(other.getClass())) {
-      return getClass().getName().compareTo(other.getClass().getName());
-    }
-
-    int lastComparison = 0;
-    Packet typedOther = (Packet)other;
-
-    lastComparison = Boolean.valueOf(isSetMessageType()).compareTo(typedOther.isSetMessageType());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetMessageType()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.messageType, typedOther.messageType);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    lastComparison = Boolean.valueOf(isSetSwPortTuple()).compareTo(typedOther.isSetSwPortTuple());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetSwPortTuple()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.swPortTuple, typedOther.swPortTuple);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    lastComparison = Boolean.valueOf(isSetData()).compareTo(typedOther.isSetData());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetData()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.data, typedOther.data);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    return 0;
-  }
-
-  public _Fields fieldForId(int fieldId) {
-    return _Fields.findByThriftId(fieldId);
-  }
-
-  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-    org.apache.thrift.protocol.TField field;
-    iprot.readStructBegin();
-    while (true)
-    {
-      field = iprot.readFieldBegin();
-      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-        break;
-      }
-      switch (field.id) {
-        case 1: // MESSAGE_TYPE
-          if (field.type == org.apache.thrift.protocol.TType.I32) {
-            this.messageType = OFMessageType.findByValue(iprot.readI32());
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        case 2: // SW_PORT_TUPLE
-          if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
-            this.swPortTuple = new SwitchPortTuple();
-            this.swPortTuple.read(iprot);
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        case 3: // DATA
-          if (field.type == org.apache.thrift.protocol.TType.STRING) {
-            this.data = iprot.readBinary();
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        default:
-          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-      }
-      iprot.readFieldEnd();
-    }
-    iprot.readStructEnd();
-
-    // check for required fields of primitive type, which can't be checked in the validate method
-    validate();
-  }
-
-  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-    validate();
-
-    oprot.writeStructBegin(STRUCT_DESC);
-    if (this.messageType != null) {
-      oprot.writeFieldBegin(MESSAGE_TYPE_FIELD_DESC);
-      oprot.writeI32(this.messageType.getValue());
-      oprot.writeFieldEnd();
-    }
-    if (this.swPortTuple != null) {
-      oprot.writeFieldBegin(SW_PORT_TUPLE_FIELD_DESC);
-      this.swPortTuple.write(oprot);
-      oprot.writeFieldEnd();
-    }
-    if (this.data != null) {
-      oprot.writeFieldBegin(DATA_FIELD_DESC);
-      oprot.writeBinary(this.data);
-      oprot.writeFieldEnd();
-    }
-    oprot.writeFieldStop();
-    oprot.writeStructEnd();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("Packet(");
-    boolean first = true;
-
-    sb.append("messageType:");
-    if (this.messageType == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.messageType);
-    }
-    first = false;
-    if (!first) sb.append(", ");
-    sb.append("swPortTuple:");
-    if (this.swPortTuple == null) {
-      sb.append("null");
-    } else {
-      sb.append(this.swPortTuple);
-    }
-    first = false;
-    if (!first) sb.append(", ");
-    sb.append("data:");
-    if (this.data == null) {
-      sb.append("null");
-    } else {
-      org.apache.thrift.TBaseHelper.toString(this.data, sb);
-    }
-    first = false;
-    sb.append(")");
-    return sb.toString();
-  }
-
-  public void validate() throws org.apache.thrift.TException {
-    // check for required fields
-  }
-
-  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-    try {
-      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-    try {
-      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-}
-
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java
deleted file mode 100644
index f4e8ae5..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/PacketStreamer.java
+++ /dev/null
@@ -1,2427 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.EnumMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.EnumSet;
-import java.util.Collections;
-import java.util.BitSet;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@SuppressWarnings("all") public class PacketStreamer {
-
-  /**
-   * Packetstreamer API
-   */
-  public interface Iface {
-
-    /**
-     * Synchronous method to get packets for a given sessionid
-     * 
-     * @param sessionid
-     */
-    public List<ByteBuffer> getPackets(String sessionid) throws org.apache.thrift.TException;
-
-    /**
-     * Synchronous method to publish a packet.
-     * It ensure the order that the packets are pushed
-     * 
-     * @param packet
-     */
-    public int pushMessageSync(Message packet) throws org.apache.thrift.TException;
-
-    /**
-     * Asynchronous method to publish a packet.
-     * Order is not guaranteed.
-     * 
-     * @param packet
-     */
-    public void pushMessageAsync(Message packet) throws org.apache.thrift.TException;
-
-    /**
-     * Terminate a session
-     * 
-     * @param sessionid
-     */
-    public void terminateSession(String sessionid) throws org.apache.thrift.TException;
-
-  }
-
-  public interface AsyncIface {
-
-    public void getPackets(String sessionid, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.getPackets_call> resultHandler) throws org.apache.thrift.TException;
-
-    public void pushMessageSync(Message packet, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.pushMessageSync_call> resultHandler) throws org.apache.thrift.TException;
-
-    public void pushMessageAsync(Message packet, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.pushMessageAsync_call> resultHandler) throws org.apache.thrift.TException;
-
-    public void terminateSession(String sessionid, org.apache.thrift.async.AsyncMethodCallback<AsyncClient.terminateSession_call> resultHandler) throws org.apache.thrift.TException;
-
-  }
-
-  public static class Client extends org.apache.thrift.TServiceClient implements Iface {
-    public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
-      public Factory() {}
-      public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
-        return new Client(prot);
-      }
-      public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
-        return new Client(iprot, oprot);
-      }
-    }
-
-    public Client(org.apache.thrift.protocol.TProtocol prot)
-    {
-      super(prot, prot);
-    }
-
-    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
-      super(iprot, oprot);
-    }
-
-    public List<ByteBuffer> getPackets(String sessionid) throws org.apache.thrift.TException
-    {
-      send_getPackets(sessionid);
-      return recv_getPackets();
-    }
-
-    public void send_getPackets(String sessionid) throws org.apache.thrift.TException
-    {
-      getPackets_args args = new getPackets_args();
-      args.setSessionid(sessionid);
-      sendBase("getPackets", args);
-    }
-
-    public List<ByteBuffer> recv_getPackets() throws org.apache.thrift.TException
-    {
-      getPackets_result result = new getPackets_result();
-      receiveBase(result, "getPackets");
-      if (result.isSetSuccess()) {
-        return result.success;
-      }
-      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getPackets failed: unknown result");
-    }
-
-    public int pushMessageSync(Message packet) throws org.apache.thrift.TException
-    {
-      send_pushMessageSync(packet);
-      return recv_pushMessageSync();
-    }
-
-    public void send_pushMessageSync(Message packet) throws org.apache.thrift.TException
-    {
-      pushMessageSync_args args = new pushMessageSync_args();
-      args.setPacket(packet);
-      sendBase("pushMessageSync", args);
-    }
-
-    public int recv_pushMessageSync() throws org.apache.thrift.TException
-    {
-      pushMessageSync_result result = new pushMessageSync_result();
-      receiveBase(result, "pushMessageSync");
-      if (result.isSetSuccess()) {
-        return result.success;
-      }
-      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "pushMessageSync failed: unknown result");
-    }
-
-    public void pushMessageAsync(Message packet) throws org.apache.thrift.TException
-    {
-      send_pushMessageAsync(packet);
-    }
-
-    public void send_pushMessageAsync(Message packet) throws org.apache.thrift.TException
-    {
-      pushMessageAsync_args args = new pushMessageAsync_args();
-      args.setPacket(packet);
-      sendBase("pushMessageAsync", args);
-    }
-
-    public void terminateSession(String sessionid) throws org.apache.thrift.TException
-    {
-      send_terminateSession(sessionid);
-      recv_terminateSession();
-    }
-
-    public void send_terminateSession(String sessionid) throws org.apache.thrift.TException
-    {
-      terminateSession_args args = new terminateSession_args();
-      args.setSessionid(sessionid);
-      sendBase("terminateSession", args);
-    }
-
-    public void recv_terminateSession() throws org.apache.thrift.TException
-    {
-      terminateSession_result result = new terminateSession_result();
-      receiveBase(result, "terminateSession");
-      return;
-    }
-
-  }
-  public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
-    public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
-      private org.apache.thrift.async.TAsyncClientManager clientManager;
-      private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
-      public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
-        this.clientManager = clientManager;
-        this.protocolFactory = protocolFactory;
-      }
-      public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
-        return new AsyncClient(protocolFactory, clientManager, transport);
-      }
-    }
-
-    public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
-      super(protocolFactory, clientManager, transport);
-    }
-
-    public void getPackets(String sessionid, org.apache.thrift.async.AsyncMethodCallback<getPackets_call> resultHandler) throws org.apache.thrift.TException {
-      checkReady();
-      getPackets_call method_call = new getPackets_call(sessionid, resultHandler, this, ___protocolFactory, ___transport);
-      this.___currentMethod = method_call;
-      ___manager.call(method_call);
-    }
-
-    public static class getPackets_call extends org.apache.thrift.async.TAsyncMethodCall {
-      private String sessionid;
-      public getPackets_call(String sessionid, org.apache.thrift.async.AsyncMethodCallback<getPackets_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
-        super(client, protocolFactory, transport, resultHandler, false);
-        this.sessionid = sessionid;
-      }
-
-      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
-        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getPackets", org.apache.thrift.protocol.TMessageType.CALL, 0));
-        getPackets_args args = new getPackets_args();
-        args.setSessionid(sessionid);
-        args.write(prot);
-        prot.writeMessageEnd();
-      }
-
-      public List<ByteBuffer> getResult() throws org.apache.thrift.TException {
-        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
-          throw new IllegalStateException("Method call not finished!");
-        }
-        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
-        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
-        return (new Client(prot)).recv_getPackets();
-      }
-    }
-
-    public void pushMessageSync(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageSync_call> resultHandler) throws org.apache.thrift.TException {
-      checkReady();
-      pushMessageSync_call method_call = new pushMessageSync_call(packet, resultHandler, this, ___protocolFactory, ___transport);
-      this.___currentMethod = method_call;
-      ___manager.call(method_call);
-    }
-
-    public static class pushMessageSync_call extends org.apache.thrift.async.TAsyncMethodCall {
-      private Message packet;
-      public pushMessageSync_call(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageSync_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
-        super(client, protocolFactory, transport, resultHandler, false);
-        this.packet = packet;
-      }
-
-      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
-        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("pushMessageSync", org.apache.thrift.protocol.TMessageType.CALL, 0));
-        pushMessageSync_args args = new pushMessageSync_args();
-        args.setPacket(packet);
-        args.write(prot);
-        prot.writeMessageEnd();
-      }
-
-      public int getResult() throws org.apache.thrift.TException {
-        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
-          throw new IllegalStateException("Method call not finished!");
-        }
-        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
-        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
-        return (new Client(prot)).recv_pushMessageSync();
-      }
-    }
-
-    public void pushMessageAsync(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageAsync_call> resultHandler) throws org.apache.thrift.TException {
-      checkReady();
-      pushMessageAsync_call method_call = new pushMessageAsync_call(packet, resultHandler, this, ___protocolFactory, ___transport);
-      this.___currentMethod = method_call;
-      ___manager.call(method_call);
-    }
-
-    public static class pushMessageAsync_call extends org.apache.thrift.async.TAsyncMethodCall {
-      private Message packet;
-      public pushMessageAsync_call(Message packet, org.apache.thrift.async.AsyncMethodCallback<pushMessageAsync_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
-        super(client, protocolFactory, transport, resultHandler, true);
-        this.packet = packet;
-      }
-
-      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
-        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("pushMessageAsync", org.apache.thrift.protocol.TMessageType.CALL, 0));
-        pushMessageAsync_args args = new pushMessageAsync_args();
-        args.setPacket(packet);
-        args.write(prot);
-        prot.writeMessageEnd();
-      }
-
-      public void getResult() throws org.apache.thrift.TException {
-        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
-          throw new IllegalStateException("Method call not finished!");
-        }
-        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
-        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
-      }
-    }
-
-    public void terminateSession(String sessionid, org.apache.thrift.async.AsyncMethodCallback<terminateSession_call> resultHandler) throws org.apache.thrift.TException {
-      checkReady();
-      terminateSession_call method_call = new terminateSession_call(sessionid, resultHandler, this, ___protocolFactory, ___transport);
-      this.___currentMethod = method_call;
-      ___manager.call(method_call);
-    }
-
-    public static class terminateSession_call extends org.apache.thrift.async.TAsyncMethodCall {
-      private String sessionid;
-      public terminateSession_call(String sessionid, org.apache.thrift.async.AsyncMethodCallback<terminateSession_call> resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
-        super(client, protocolFactory, transport, resultHandler, false);
-        this.sessionid = sessionid;
-      }
-
-      public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
-        prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("terminateSession", org.apache.thrift.protocol.TMessageType.CALL, 0));
-        terminateSession_args args = new terminateSession_args();
-        args.setSessionid(sessionid);
-        args.write(prot);
-        prot.writeMessageEnd();
-      }
-
-      public void getResult() throws org.apache.thrift.TException {
-        if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
-          throw new IllegalStateException("Method call not finished!");
-        }
-        org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
-        org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
-        (new Client(prot)).recv_terminateSession();
-      }
-    }
-
-  }
-
-  public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor implements org.apache.thrift.TProcessor {
-    private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
-    public Processor(I iface) {
-      super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
-    }
-
-    protected Processor(I iface, Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
-      super(iface, getProcessMap(processMap));
-    }
-
-    private static <I extends Iface> Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> getProcessMap(Map<String,  org.apache.thrift.ProcessFunction<I, ? extends  org.apache.thrift.TBase>> processMap) {
-      processMap.put("getPackets", new getPackets());
-      processMap.put("pushMessageSync", new pushMessageSync());
-      processMap.put("pushMessageAsync", new pushMessageAsync());
-      processMap.put("terminateSession", new terminateSession());
-      return processMap;
-    }
-
-    private static class getPackets<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getPackets_args> {
-      public getPackets() {
-        super("getPackets");
-      }
-
-      protected getPackets_args getEmptyArgsInstance() {
-        return new getPackets_args();
-      }
-
-      protected getPackets_result getResult(I iface, getPackets_args args) throws org.apache.thrift.TException {
-        getPackets_result result = new getPackets_result();
-        result.success = iface.getPackets(args.sessionid);
-        return result;
-      }
-    }
-
-    private static class pushMessageSync<I extends Iface> extends org.apache.thrift.ProcessFunction<I, pushMessageSync_args> {
-      public pushMessageSync() {
-        super("pushMessageSync");
-      }
-
-      protected pushMessageSync_args getEmptyArgsInstance() {
-        return new pushMessageSync_args();
-      }
-
-      protected pushMessageSync_result getResult(I iface, pushMessageSync_args args) throws org.apache.thrift.TException {
-        pushMessageSync_result result = new pushMessageSync_result();
-        result.success = iface.pushMessageSync(args.packet);
-        result.setSuccessIsSet(true);
-        return result;
-      }
-    }
-
-    private static class pushMessageAsync<I extends Iface> extends org.apache.thrift.ProcessFunction<I, pushMessageAsync_args> {
-      public pushMessageAsync() {
-        super("pushMessageAsync");
-      }
-
-      protected pushMessageAsync_args getEmptyArgsInstance() {
-        return new pushMessageAsync_args();
-      }
-
-      protected org.apache.thrift.TBase getResult(I iface, pushMessageAsync_args args) throws org.apache.thrift.TException {
-        iface.pushMessageAsync(args.packet);
-        return null;
-      }
-    }
-
-    private static class terminateSession<I extends Iface> extends org.apache.thrift.ProcessFunction<I, terminateSession_args> {
-      public terminateSession() {
-        super("terminateSession");
-      }
-
-      protected terminateSession_args getEmptyArgsInstance() {
-        return new terminateSession_args();
-      }
-
-      protected terminateSession_result getResult(I iface, terminateSession_args args) throws org.apache.thrift.TException {
-        terminateSession_result result = new terminateSession_result();
-        iface.terminateSession(args.sessionid);
-        return result;
-      }
-    }
-
-  }
-
-  public static class getPackets_args implements org.apache.thrift.TBase<getPackets_args, getPackets_args._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPackets_args");
-
-    private static final org.apache.thrift.protocol.TField SESSIONID_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionid", org.apache.thrift.protocol.TType.STRING, (short)1);
-
-    public String sessionid; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      SESSIONID((short)1, "sessionid");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 1: // SESSIONID
-            return SESSIONID;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.SESSIONID, new org.apache.thrift.meta_data.FieldMetaData("sessionid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPackets_args.class, metaDataMap);
-    }
-
-    public getPackets_args() {
-    }
-
-    public getPackets_args(
-      String sessionid)
-    {
-      this();
-      this.sessionid = sessionid;
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public getPackets_args(getPackets_args other) {
-      if (other.isSetSessionid()) {
-        this.sessionid = other.sessionid;
-      }
-    }
-
-    public getPackets_args deepCopy() {
-      return new getPackets_args(this);
-    }
-
-    @Override
-    public void clear() {
-      this.sessionid = null;
-    }
-
-    public String getSessionid() {
-      return this.sessionid;
-    }
-
-    public getPackets_args setSessionid(String sessionid) {
-      this.sessionid = sessionid;
-      return this;
-    }
-
-    public void unsetSessionid() {
-      this.sessionid = null;
-    }
-
-    /** Returns true if field sessionid is set (has been assigned a value) and false otherwise */
-    public boolean isSetSessionid() {
-      return this.sessionid != null;
-    }
-
-    public void setSessionidIsSet(boolean value) {
-      if (!value) {
-        this.sessionid = null;
-      }
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case SESSIONID:
-        if (value == null) {
-          unsetSessionid();
-        } else {
-          setSessionid((String)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case SESSIONID:
-        return getSessionid();
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case SESSIONID:
-        return isSetSessionid();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof getPackets_args)
-        return this.equals((getPackets_args)that);
-      return false;
-    }
-
-    public boolean equals(getPackets_args that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_sessionid = true && this.isSetSessionid();
-      boolean that_present_sessionid = true && that.isSetSessionid();
-      if (this_present_sessionid || that_present_sessionid) {
-        if (!(this_present_sessionid && that_present_sessionid))
-          return false;
-        if (!this.sessionid.equals(that.sessionid))
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(getPackets_args other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      getPackets_args typedOther = (getPackets_args)other;
-
-      lastComparison = Boolean.valueOf(isSetSessionid()).compareTo(typedOther.isSetSessionid());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetSessionid()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionid, typedOther.sessionid);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 1: // SESSIONID
-            if (field.type == org.apache.thrift.protocol.TType.STRING) {
-              this.sessionid = iprot.readString();
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      validate();
-
-      oprot.writeStructBegin(STRUCT_DESC);
-      if (this.sessionid != null) {
-        oprot.writeFieldBegin(SESSIONID_FIELD_DESC);
-        oprot.writeString(this.sessionid);
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("getPackets_args(");
-      boolean first = true;
-
-      sb.append("sessionid:");
-      if (this.sessionid == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.sessionid);
-      }
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class getPackets_result implements org.apache.thrift.TBase<getPackets_result, getPackets_result._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getPackets_result");
-
-    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.LIST, (short)0);
-
-    public List<ByteBuffer> success; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      SUCCESS((short)0, "success");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 0: // SUCCESS
-            return SUCCESS;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, 
-              new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING              , true))));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getPackets_result.class, metaDataMap);
-    }
-
-    public getPackets_result() {
-    }
-
-    public getPackets_result(
-      List<ByteBuffer> success)
-    {
-      this();
-      this.success = success;
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public getPackets_result(getPackets_result other) {
-      if (other.isSetSuccess()) {
-        List<ByteBuffer> __this__success = new ArrayList<ByteBuffer>();
-        for (ByteBuffer other_element : other.success) {
-          ByteBuffer temp_binary_element = org.apache.thrift.TBaseHelper.copyBinary(other_element);
-;
-          __this__success.add(temp_binary_element);
-        }
-        this.success = __this__success;
-      }
-    }
-
-    public getPackets_result deepCopy() {
-      return new getPackets_result(this);
-    }
-
-    @Override
-    public void clear() {
-      this.success = null;
-    }
-
-    public int getSuccessSize() {
-      return (this.success == null) ? 0 : this.success.size();
-    }
-
-    public java.util.Iterator<ByteBuffer> getSuccessIterator() {
-      return (this.success == null) ? null : this.success.iterator();
-    }
-
-    public void addToSuccess(ByteBuffer elem) {
-      if (this.success == null) {
-        this.success = new ArrayList<ByteBuffer>();
-      }
-      this.success.add(elem);
-    }
-
-    public List<ByteBuffer> getSuccess() {
-      return this.success;
-    }
-
-    public getPackets_result setSuccess(List<ByteBuffer> success) {
-      this.success = success;
-      return this;
-    }
-
-    public void unsetSuccess() {
-      this.success = null;
-    }
-
-    /** Returns true if field success is set (has been assigned a value) and false otherwise */
-    public boolean isSetSuccess() {
-      return this.success != null;
-    }
-
-    public void setSuccessIsSet(boolean value) {
-      if (!value) {
-        this.success = null;
-      }
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case SUCCESS:
-        if (value == null) {
-          unsetSuccess();
-        } else {
-          setSuccess((List<ByteBuffer>)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case SUCCESS:
-        return getSuccess();
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case SUCCESS:
-        return isSetSuccess();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof getPackets_result)
-        return this.equals((getPackets_result)that);
-      return false;
-    }
-
-    public boolean equals(getPackets_result that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_success = true && this.isSetSuccess();
-      boolean that_present_success = true && that.isSetSuccess();
-      if (this_present_success || that_present_success) {
-        if (!(this_present_success && that_present_success))
-          return false;
-        if (!this.success.equals(that.success))
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(getPackets_result other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      getPackets_result typedOther = (getPackets_result)other;
-
-      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetSuccess()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 0: // SUCCESS
-            if (field.type == org.apache.thrift.protocol.TType.LIST) {
-              {
-                org.apache.thrift.protocol.TList _list4 = iprot.readListBegin();
-                this.success = new ArrayList<ByteBuffer>(_list4.size);
-                for (int _i5 = 0; _i5 < _list4.size; ++_i5)
-                {
-                  ByteBuffer _elem6; // required
-                  _elem6 = iprot.readBinary();
-                  this.success.add(_elem6);
-                }
-                iprot.readListEnd();
-              }
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      oprot.writeStructBegin(STRUCT_DESC);
-
-      if (this.isSetSuccess()) {
-        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
-        {
-          oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, this.success.size()));
-          for (ByteBuffer _iter7 : this.success)
-          {
-            oprot.writeBinary(_iter7);
-          }
-          oprot.writeListEnd();
-        }
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("getPackets_result(");
-      boolean first = true;
-
-      sb.append("success:");
-      if (this.success == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.success);
-      }
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class pushMessageSync_args implements org.apache.thrift.TBase<pushMessageSync_args, pushMessageSync_args._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageSync_args");
-
-    private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)1);
-
-    public Message packet; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      PACKET((short)1, "packet");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 1: // PACKET
-            return PACKET;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Message.class)));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageSync_args.class, metaDataMap);
-    }
-
-    public pushMessageSync_args() {
-    }
-
-    public pushMessageSync_args(
-      Message packet)
-    {
-      this();
-      this.packet = packet;
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public pushMessageSync_args(pushMessageSync_args other) {
-      if (other.isSetPacket()) {
-        this.packet = new Message(other.packet);
-      }
-    }
-
-    public pushMessageSync_args deepCopy() {
-      return new pushMessageSync_args(this);
-    }
-
-    @Override
-    public void clear() {
-      this.packet = null;
-    }
-
-    public Message getPacket() {
-      return this.packet;
-    }
-
-    public pushMessageSync_args setPacket(Message packet) {
-      this.packet = packet;
-      return this;
-    }
-
-    public void unsetPacket() {
-      this.packet = null;
-    }
-
-    /** Returns true if field packet is set (has been assigned a value) and false otherwise */
-    public boolean isSetPacket() {
-      return this.packet != null;
-    }
-
-    public void setPacketIsSet(boolean value) {
-      if (!value) {
-        this.packet = null;
-      }
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case PACKET:
-        if (value == null) {
-          unsetPacket();
-        } else {
-          setPacket((Message)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case PACKET:
-        return getPacket();
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case PACKET:
-        return isSetPacket();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof pushMessageSync_args)
-        return this.equals((pushMessageSync_args)that);
-      return false;
-    }
-
-    public boolean equals(pushMessageSync_args that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_packet = true && this.isSetPacket();
-      boolean that_present_packet = true && that.isSetPacket();
-      if (this_present_packet || that_present_packet) {
-        if (!(this_present_packet && that_present_packet))
-          return false;
-        if (!this.packet.equals(that.packet))
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(pushMessageSync_args other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      pushMessageSync_args typedOther = (pushMessageSync_args)other;
-
-      lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetPacket()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 1: // PACKET
-            if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
-              this.packet = new Message();
-              this.packet.read(iprot);
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      validate();
-
-      oprot.writeStructBegin(STRUCT_DESC);
-      if (this.packet != null) {
-        oprot.writeFieldBegin(PACKET_FIELD_DESC);
-        this.packet.write(oprot);
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("pushMessageSync_args(");
-      boolean first = true;
-
-      sb.append("packet:");
-      if (this.packet == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.packet);
-      }
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class pushMessageSync_result implements org.apache.thrift.TBase<pushMessageSync_result, pushMessageSync_result._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageSync_result");
-
-    private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
-
-    public int success; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      SUCCESS((short)0, "success");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 0: // SUCCESS
-            return SUCCESS;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-    private static final int __SUCCESS_ISSET_ID = 0;
-    private BitSet __isset_bit_vector = new BitSet(1);
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageSync_result.class, metaDataMap);
-    }
-
-    public pushMessageSync_result() {
-    }
-
-    public pushMessageSync_result(
-      int success)
-    {
-      this();
-      this.success = success;
-      setSuccessIsSet(true);
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public pushMessageSync_result(pushMessageSync_result other) {
-      __isset_bit_vector.clear();
-      __isset_bit_vector.or(other.__isset_bit_vector);
-      this.success = other.success;
-    }
-
-    public pushMessageSync_result deepCopy() {
-      return new pushMessageSync_result(this);
-    }
-
-    @Override
-    public void clear() {
-      setSuccessIsSet(false);
-      this.success = 0;
-    }
-
-    public int getSuccess() {
-      return this.success;
-    }
-
-    public pushMessageSync_result setSuccess(int success) {
-      this.success = success;
-      setSuccessIsSet(true);
-      return this;
-    }
-
-    public void unsetSuccess() {
-      __isset_bit_vector.clear(__SUCCESS_ISSET_ID);
-    }
-
-    /** Returns true if field success is set (has been assigned a value) and false otherwise */
-    public boolean isSetSuccess() {
-      return __isset_bit_vector.get(__SUCCESS_ISSET_ID);
-    }
-
-    public void setSuccessIsSet(boolean value) {
-      __isset_bit_vector.set(__SUCCESS_ISSET_ID, value);
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case SUCCESS:
-        if (value == null) {
-          unsetSuccess();
-        } else {
-          setSuccess((Integer)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case SUCCESS:
-        return Integer.valueOf(getSuccess());
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case SUCCESS:
-        return isSetSuccess();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof pushMessageSync_result)
-        return this.equals((pushMessageSync_result)that);
-      return false;
-    }
-
-    public boolean equals(pushMessageSync_result that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_success = true;
-      boolean that_present_success = true;
-      if (this_present_success || that_present_success) {
-        if (!(this_present_success && that_present_success))
-          return false;
-        if (this.success != that.success)
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(pushMessageSync_result other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      pushMessageSync_result typedOther = (pushMessageSync_result)other;
-
-      lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(typedOther.isSetSuccess());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetSuccess()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, typedOther.success);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 0: // SUCCESS
-            if (field.type == org.apache.thrift.protocol.TType.I32) {
-              this.success = iprot.readI32();
-              setSuccessIsSet(true);
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      oprot.writeStructBegin(STRUCT_DESC);
-
-      if (this.isSetSuccess()) {
-        oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
-        oprot.writeI32(this.success);
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("pushMessageSync_result(");
-      boolean first = true;
-
-      sb.append("success:");
-      sb.append(this.success);
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
-        __isset_bit_vector = new BitSet(1);
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class pushMessageAsync_args implements org.apache.thrift.TBase<pushMessageAsync_args, pushMessageAsync_args._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushMessageAsync_args");
-
-    private static final org.apache.thrift.protocol.TField PACKET_FIELD_DESC = new org.apache.thrift.protocol.TField("packet", org.apache.thrift.protocol.TType.STRUCT, (short)1);
-
-    public Message packet; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      PACKET((short)1, "packet");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 1: // PACKET
-            return PACKET;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.PACKET, new org.apache.thrift.meta_data.FieldMetaData("packet", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Message.class)));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushMessageAsync_args.class, metaDataMap);
-    }
-
-    public pushMessageAsync_args() {
-    }
-
-    public pushMessageAsync_args(
-      Message packet)
-    {
-      this();
-      this.packet = packet;
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public pushMessageAsync_args(pushMessageAsync_args other) {
-      if (other.isSetPacket()) {
-        this.packet = new Message(other.packet);
-      }
-    }
-
-    public pushMessageAsync_args deepCopy() {
-      return new pushMessageAsync_args(this);
-    }
-
-    @Override
-    public void clear() {
-      this.packet = null;
-    }
-
-    public Message getPacket() {
-      return this.packet;
-    }
-
-    public pushMessageAsync_args setPacket(Message packet) {
-      this.packet = packet;
-      return this;
-    }
-
-    public void unsetPacket() {
-      this.packet = null;
-    }
-
-    /** Returns true if field packet is set (has been assigned a value) and false otherwise */
-    public boolean isSetPacket() {
-      return this.packet != null;
-    }
-
-    public void setPacketIsSet(boolean value) {
-      if (!value) {
-        this.packet = null;
-      }
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case PACKET:
-        if (value == null) {
-          unsetPacket();
-        } else {
-          setPacket((Message)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case PACKET:
-        return getPacket();
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case PACKET:
-        return isSetPacket();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof pushMessageAsync_args)
-        return this.equals((pushMessageAsync_args)that);
-      return false;
-    }
-
-    public boolean equals(pushMessageAsync_args that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_packet = true && this.isSetPacket();
-      boolean that_present_packet = true && that.isSetPacket();
-      if (this_present_packet || that_present_packet) {
-        if (!(this_present_packet && that_present_packet))
-          return false;
-        if (!this.packet.equals(that.packet))
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(pushMessageAsync_args other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      pushMessageAsync_args typedOther = (pushMessageAsync_args)other;
-
-      lastComparison = Boolean.valueOf(isSetPacket()).compareTo(typedOther.isSetPacket());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetPacket()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.packet, typedOther.packet);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 1: // PACKET
-            if (field.type == org.apache.thrift.protocol.TType.STRUCT) {
-              this.packet = new Message();
-              this.packet.read(iprot);
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      validate();
-
-      oprot.writeStructBegin(STRUCT_DESC);
-      if (this.packet != null) {
-        oprot.writeFieldBegin(PACKET_FIELD_DESC);
-        this.packet.write(oprot);
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("pushMessageAsync_args(");
-      boolean first = true;
-
-      sb.append("packet:");
-      if (this.packet == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.packet);
-      }
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class terminateSession_args implements org.apache.thrift.TBase<terminateSession_args, terminateSession_args._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("terminateSession_args");
-
-    private static final org.apache.thrift.protocol.TField SESSIONID_FIELD_DESC = new org.apache.thrift.protocol.TField("sessionid", org.apache.thrift.protocol.TType.STRING, (short)1);
-
-    public String sessionid; // required
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-      SESSIONID((short)1, "sessionid");
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          case 1: // SESSIONID
-            return SESSIONID;
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-
-    // isset id assignments
-
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      tmpMap.put(_Fields.SESSIONID, new org.apache.thrift.meta_data.FieldMetaData("sessionid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-          new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(terminateSession_args.class, metaDataMap);
-    }
-
-    public terminateSession_args() {
-    }
-
-    public terminateSession_args(
-      String sessionid)
-    {
-      this();
-      this.sessionid = sessionid;
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public terminateSession_args(terminateSession_args other) {
-      if (other.isSetSessionid()) {
-        this.sessionid = other.sessionid;
-      }
-    }
-
-    public terminateSession_args deepCopy() {
-      return new terminateSession_args(this);
-    }
-
-    @Override
-    public void clear() {
-      this.sessionid = null;
-    }
-
-    public String getSessionid() {
-      return this.sessionid;
-    }
-
-    public terminateSession_args setSessionid(String sessionid) {
-      this.sessionid = sessionid;
-      return this;
-    }
-
-    public void unsetSessionid() {
-      this.sessionid = null;
-    }
-
-    /** Returns true if field sessionid is set (has been assigned a value) and false otherwise */
-    public boolean isSetSessionid() {
-      return this.sessionid != null;
-    }
-
-    public void setSessionidIsSet(boolean value) {
-      if (!value) {
-        this.sessionid = null;
-      }
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      case SESSIONID:
-        if (value == null) {
-          unsetSessionid();
-        } else {
-          setSessionid((String)value);
-        }
-        break;
-
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      case SESSIONID:
-        return getSessionid();
-
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      case SESSIONID:
-        return isSetSessionid();
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof terminateSession_args)
-        return this.equals((terminateSession_args)that);
-      return false;
-    }
-
-    public boolean equals(terminateSession_args that) {
-      if (that == null)
-        return false;
-
-      boolean this_present_sessionid = true && this.isSetSessionid();
-      boolean that_present_sessionid = true && that.isSetSessionid();
-      if (this_present_sessionid || that_present_sessionid) {
-        if (!(this_present_sessionid && that_present_sessionid))
-          return false;
-        if (!this.sessionid.equals(that.sessionid))
-          return false;
-      }
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(terminateSession_args other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      terminateSession_args typedOther = (terminateSession_args)other;
-
-      lastComparison = Boolean.valueOf(isSetSessionid()).compareTo(typedOther.isSetSessionid());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetSessionid()) {
-        lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.sessionid, typedOther.sessionid);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          case 1: // SESSIONID
-            if (field.type == org.apache.thrift.protocol.TType.STRING) {
-              this.sessionid = iprot.readString();
-            } else { 
-              org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      validate();
-
-      oprot.writeStructBegin(STRUCT_DESC);
-      if (this.sessionid != null) {
-        oprot.writeFieldBegin(SESSIONID_FIELD_DESC);
-        oprot.writeString(this.sessionid);
-        oprot.writeFieldEnd();
-      }
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("terminateSession_args(");
-      boolean first = true;
-
-      sb.append("sessionid:");
-      if (this.sessionid == null) {
-        sb.append("null");
-      } else {
-        sb.append(this.sessionid);
-      }
-      first = false;
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-  public static class terminateSession_result implements org.apache.thrift.TBase<terminateSession_result, terminateSession_result._Fields>, java.io.Serializable, Cloneable   {
-    private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("terminateSession_result");
-
-
-
-    /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-    public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-;
-
-      private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-      static {
-        for (_Fields field : EnumSet.allOf(_Fields.class)) {
-          byName.put(field.getFieldName(), field);
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, or null if its not found.
-       */
-      public static _Fields findByThriftId(int fieldId) {
-        switch(fieldId) {
-          default:
-            return null;
-        }
-      }
-
-      /**
-       * Find the _Fields constant that matches fieldId, throwing an exception
-       * if it is not found.
-       */
-      public static _Fields findByThriftIdOrThrow(int fieldId) {
-        _Fields fields = findByThriftId(fieldId);
-        if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-        return fields;
-      }
-
-      /**
-       * Find the _Fields constant that matches name, or null if its not found.
-       */
-      public static _Fields findByName(String name) {
-        return byName.get(name);
-      }
-
-      private final short _thriftId;
-      private final String _fieldName;
-
-      _Fields(short thriftId, String fieldName) {
-        _thriftId = thriftId;
-        _fieldName = fieldName;
-      }
-
-      public short getThriftFieldId() {
-        return _thriftId;
-      }
-
-      public String getFieldName() {
-        return _fieldName;
-      }
-    }
-    public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-    static {
-      Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-      metaDataMap = Collections.unmodifiableMap(tmpMap);
-      org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(terminateSession_result.class, metaDataMap);
-    }
-
-    public terminateSession_result() {
-    }
-
-    /**
-     * Performs a deep copy on <i>other</i>.
-     */
-    public terminateSession_result(terminateSession_result other) {
-    }
-
-    public terminateSession_result deepCopy() {
-      return new terminateSession_result(this);
-    }
-
-    @Override
-    public void clear() {
-    }
-
-    public void setFieldValue(_Fields field, Object value) {
-      switch (field) {
-      }
-    }
-
-    public Object getFieldValue(_Fields field) {
-      switch (field) {
-      }
-      throw new IllegalStateException();
-    }
-
-    /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-    public boolean isSet(_Fields field) {
-      if (field == null) {
-        throw new IllegalArgumentException();
-      }
-
-      switch (field) {
-      }
-      throw new IllegalStateException();
-    }
-
-    @Override
-    public boolean equals(Object that) {
-      if (that == null)
-        return false;
-      if (that instanceof terminateSession_result)
-        return this.equals((terminateSession_result)that);
-      return false;
-    }
-
-    public boolean equals(terminateSession_result that) {
-      if (that == null)
-        return false;
-
-      return true;
-    }
-
-    @Override
-    public int hashCode() {
-      return 0;
-    }
-
-    public int compareTo(terminateSession_result other) {
-      if (!getClass().equals(other.getClass())) {
-        return getClass().getName().compareTo(other.getClass().getName());
-      }
-
-      int lastComparison = 0;
-      terminateSession_result typedOther = (terminateSession_result)other;
-
-      return 0;
-    }
-
-    public _Fields fieldForId(int fieldId) {
-      return _Fields.findByThriftId(fieldId);
-    }
-
-    public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-      org.apache.thrift.protocol.TField field;
-      iprot.readStructBegin();
-      while (true)
-      {
-        field = iprot.readFieldBegin();
-        if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-          break;
-        }
-        switch (field.id) {
-          default:
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-        }
-        iprot.readFieldEnd();
-      }
-      iprot.readStructEnd();
-
-      // check for required fields of primitive type, which can't be checked in the validate method
-      validate();
-    }
-
-    public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-      oprot.writeStructBegin(STRUCT_DESC);
-
-      oprot.writeFieldStop();
-      oprot.writeStructEnd();
-    }
-
-    @Override
-    public String toString() {
-      StringBuilder sb = new StringBuilder("terminateSession_result(");
-      boolean first = true;
-
-      sb.append(")");
-      return sb.toString();
-    }
-
-    public void validate() throws org.apache.thrift.TException {
-      // check for required fields
-    }
-
-    private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-      try {
-        write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-    private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-      try {
-        read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-      } catch (org.apache.thrift.TException te) {
-        throw new java.io.IOException(te);
-      }
-    }
-
-  }
-
-}
diff --git a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java b/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java
deleted file mode 100644
index 8fe8191..0000000
--- a/lib/gen-java/net/floodlightcontroller/packetstreamer/thrift/SwitchPortTuple.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/**
- * Autogenerated by Thrift Compiler (0.7.0)
- *
- * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
- */
-package net.floodlightcontroller.packetstreamer.thrift;
-
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.EnumMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.EnumSet;
-import java.util.Collections;
-import java.util.BitSet;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A struct that defines switch port tuple
- */
-@SuppressWarnings("all") public class SwitchPortTuple implements org.apache.thrift.TBase<SwitchPortTuple, SwitchPortTuple._Fields>, java.io.Serializable, Cloneable {
-  private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("SwitchPortTuple");
-
-  private static final org.apache.thrift.protocol.TField DPID_FIELD_DESC = new org.apache.thrift.protocol.TField("dpid", org.apache.thrift.protocol.TType.I64, (short)1);
-  private static final org.apache.thrift.protocol.TField PORT_FIELD_DESC = new org.apache.thrift.protocol.TField("port", org.apache.thrift.protocol.TType.I16, (short)2);
-
-  public long dpid; // required
-  public short port; // required
-
-  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
-  public enum _Fields implements org.apache.thrift.TFieldIdEnum {
-    DPID((short)1, "dpid"),
-    PORT((short)2, "port");
-
-    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
-
-    static {
-      for (_Fields field : EnumSet.allOf(_Fields.class)) {
-        byName.put(field.getFieldName(), field);
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, or null if its not found.
-     */
-    public static _Fields findByThriftId(int fieldId) {
-      switch(fieldId) {
-        case 1: // DPID
-          return DPID;
-        case 2: // PORT
-          return PORT;
-        default:
-          return null;
-      }
-    }
-
-    /**
-     * Find the _Fields constant that matches fieldId, throwing an exception
-     * if it is not found.
-     */
-    public static _Fields findByThriftIdOrThrow(int fieldId) {
-      _Fields fields = findByThriftId(fieldId);
-      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
-      return fields;
-    }
-
-    /**
-     * Find the _Fields constant that matches name, or null if its not found.
-     */
-    public static _Fields findByName(String name) {
-      return byName.get(name);
-    }
-
-    private final short _thriftId;
-    private final String _fieldName;
-
-    _Fields(short thriftId, String fieldName) {
-      _thriftId = thriftId;
-      _fieldName = fieldName;
-    }
-
-    public short getThriftFieldId() {
-      return _thriftId;
-    }
-
-    public String getFieldName() {
-      return _fieldName;
-    }
-  }
-
-  // isset id assignments
-  private static final int __DPID_ISSET_ID = 0;
-  private static final int __PORT_ISSET_ID = 1;
-  private BitSet __isset_bit_vector = new BitSet(2);
-
-  public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
-  static {
-    Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
-    tmpMap.put(_Fields.DPID, new org.apache.thrift.meta_data.FieldMetaData("dpid", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I64)));
-    tmpMap.put(_Fields.PORT, new org.apache.thrift.meta_data.FieldMetaData("port", org.apache.thrift.TFieldRequirementType.DEFAULT, 
-        new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I16)));
-    metaDataMap = Collections.unmodifiableMap(tmpMap);
-    org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(SwitchPortTuple.class, metaDataMap);
-  }
-
-  public SwitchPortTuple() {
-  }
-
-  public SwitchPortTuple(
-    long dpid,
-    short port)
-  {
-    this();
-    this.dpid = dpid;
-    setDpidIsSet(true);
-    this.port = port;
-    setPortIsSet(true);
-  }
-
-  /**
-   * Performs a deep copy on <i>other</i>.
-   */
-  public SwitchPortTuple(SwitchPortTuple other) {
-    __isset_bit_vector.clear();
-    __isset_bit_vector.or(other.__isset_bit_vector);
-    this.dpid = other.dpid;
-    this.port = other.port;
-  }
-
-  public SwitchPortTuple deepCopy() {
-    return new SwitchPortTuple(this);
-  }
-
-  @Override
-  public void clear() {
-    setDpidIsSet(false);
-    this.dpid = 0;
-    setPortIsSet(false);
-    this.port = 0;
-  }
-
-  public long getDpid() {
-    return this.dpid;
-  }
-
-  public SwitchPortTuple setDpid(long dpid) {
-    this.dpid = dpid;
-    setDpidIsSet(true);
-    return this;
-  }
-
-  public void unsetDpid() {
-    __isset_bit_vector.clear(__DPID_ISSET_ID);
-  }
-
-  /** Returns true if field dpid is set (has been assigned a value) and false otherwise */
-  public boolean isSetDpid() {
-    return __isset_bit_vector.get(__DPID_ISSET_ID);
-  }
-
-  public void setDpidIsSet(boolean value) {
-    __isset_bit_vector.set(__DPID_ISSET_ID, value);
-  }
-
-  public short getPort() {
-    return this.port;
-  }
-
-  public SwitchPortTuple setPort(short port) {
-    this.port = port;
-    setPortIsSet(true);
-    return this;
-  }
-
-  public void unsetPort() {
-    __isset_bit_vector.clear(__PORT_ISSET_ID);
-  }
-
-  /** Returns true if field port is set (has been assigned a value) and false otherwise */
-  public boolean isSetPort() {
-    return __isset_bit_vector.get(__PORT_ISSET_ID);
-  }
-
-  public void setPortIsSet(boolean value) {
-    __isset_bit_vector.set(__PORT_ISSET_ID, value);
-  }
-
-  public void setFieldValue(_Fields field, Object value) {
-    switch (field) {
-    case DPID:
-      if (value == null) {
-        unsetDpid();
-      } else {
-        setDpid((Long)value);
-      }
-      break;
-
-    case PORT:
-      if (value == null) {
-        unsetPort();
-      } else {
-        setPort((Short)value);
-      }
-      break;
-
-    }
-  }
-
-  public Object getFieldValue(_Fields field) {
-    switch (field) {
-    case DPID:
-      return Long.valueOf(getDpid());
-
-    case PORT:
-      return Short.valueOf(getPort());
-
-    }
-    throw new IllegalStateException();
-  }
-
-  /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
-  public boolean isSet(_Fields field) {
-    if (field == null) {
-      throw new IllegalArgumentException();
-    }
-
-    switch (field) {
-    case DPID:
-      return isSetDpid();
-    case PORT:
-      return isSetPort();
-    }
-    throw new IllegalStateException();
-  }
-
-  @Override
-  public boolean equals(Object that) {
-    if (that == null)
-      return false;
-    if (that instanceof SwitchPortTuple)
-      return this.equals((SwitchPortTuple)that);
-    return false;
-  }
-
-  public boolean equals(SwitchPortTuple that) {
-    if (that == null)
-      return false;
-
-    boolean this_present_dpid = true;
-    boolean that_present_dpid = true;
-    if (this_present_dpid || that_present_dpid) {
-      if (!(this_present_dpid && that_present_dpid))
-        return false;
-      if (this.dpid != that.dpid)
-        return false;
-    }
-
-    boolean this_present_port = true;
-    boolean that_present_port = true;
-    if (this_present_port || that_present_port) {
-      if (!(this_present_port && that_present_port))
-        return false;
-      if (this.port != that.port)
-        return false;
-    }
-
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    return 0;
-  }
-
-  public int compareTo(SwitchPortTuple other) {
-    if (!getClass().equals(other.getClass())) {
-      return getClass().getName().compareTo(other.getClass().getName());
-    }
-
-    int lastComparison = 0;
-    SwitchPortTuple typedOther = (SwitchPortTuple)other;
-
-    lastComparison = Boolean.valueOf(isSetDpid()).compareTo(typedOther.isSetDpid());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetDpid()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.dpid, typedOther.dpid);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    lastComparison = Boolean.valueOf(isSetPort()).compareTo(typedOther.isSetPort());
-    if (lastComparison != 0) {
-      return lastComparison;
-    }
-    if (isSetPort()) {
-      lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.port, typedOther.port);
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-    }
-    return 0;
-  }
-
-  public _Fields fieldForId(int fieldId) {
-    return _Fields.findByThriftId(fieldId);
-  }
-
-  public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
-    org.apache.thrift.protocol.TField field;
-    iprot.readStructBegin();
-    while (true)
-    {
-      field = iprot.readFieldBegin();
-      if (field.type == org.apache.thrift.protocol.TType.STOP) { 
-        break;
-      }
-      switch (field.id) {
-        case 1: // DPID
-          if (field.type == org.apache.thrift.protocol.TType.I64) {
-            this.dpid = iprot.readI64();
-            setDpidIsSet(true);
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        case 2: // PORT
-          if (field.type == org.apache.thrift.protocol.TType.I16) {
-            this.port = iprot.readI16();
-            setPortIsSet(true);
-          } else { 
-            org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-          }
-          break;
-        default:
-          org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);
-      }
-      iprot.readFieldEnd();
-    }
-    iprot.readStructEnd();
-
-    // check for required fields of primitive type, which can't be checked in the validate method
-    validate();
-  }
-
-  public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
-    validate();
-
-    oprot.writeStructBegin(STRUCT_DESC);
-    oprot.writeFieldBegin(DPID_FIELD_DESC);
-    oprot.writeI64(this.dpid);
-    oprot.writeFieldEnd();
-    oprot.writeFieldBegin(PORT_FIELD_DESC);
-    oprot.writeI16(this.port);
-    oprot.writeFieldEnd();
-    oprot.writeFieldStop();
-    oprot.writeStructEnd();
-  }
-
-  @Override
-  public String toString() {
-    StringBuilder sb = new StringBuilder("SwitchPortTuple(");
-    boolean first = true;
-
-    sb.append("dpid:");
-    sb.append(this.dpid);
-    first = false;
-    if (!first) sb.append(", ");
-    sb.append("port:");
-    sb.append(this.port);
-    first = false;
-    sb.append(")");
-    return sb.toString();
-  }
-
-  public void validate() throws org.apache.thrift.TException {
-    // check for required fields
-  }
-
-  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
-    try {
-      write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
-    try {
-      // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
-      __isset_bit_vector = new BitSet(1);
-      read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
-    } catch (org.apache.thrift.TException te) {
-      throw new java.io.IOException(te);
-    }
-  }
-
-}
-
diff --git a/onos-embedded.sh b/onos-embedded.sh
index b5cfed6..fe0db44 100755
--- a/onos-embedded.sh
+++ b/onos-embedded.sh
@@ -1,9 +1,9 @@
 #!/bin/sh
 
 # Set paths
-FL_HOME=`dirname $0`
-FL_JAR="${FL_HOME}/target/floodlight.jar"
-FL_LOGBACK="${FL_HOME}/logback.xml"
+ONOS_HOME=`dirname $0`
+ONOS_JAR="${ONOS_HOME}/target/floodlight.jar"
+ONOS_LOGBACK="${ONOS_HOME}/logback.xml"
 TITAN_CONFIG="/tmp/cassandra.titan"
 CASSANDRA_CONFIG="/home/`whoami`/apache-cassandra-1.1.4/conf/cassandra.yaml"
 
@@ -17,15 +17,15 @@
 #JVM_OPTS="$JVM_OPTS -Dpython.security.respectJavaAccessibility=false"
 
 # Set classpath to include titan libs
-#CLASSPATH=`echo ${FL_HOME}/lib/*.jar ${FL_HOME}/lib/titan/*.jar | sed 's/ /:/g'`
-CLASSPATH="${FL_HOME}/lib/*.jar:${FL_HOME}/lib/titan/*.jar"
+#CLASSPATH=`echo ${ONOS_HOME}/lib/*.jar ${ONOS_HOME}/lib/titan/*.jar | sed 's/ /:/g'`
+CLASSPATH="${ONOS_HOME}/lib/*.jar:${ONOS_HOME}/lib/titan/*.jar"
 
 CASSANDRA_OPTS="-Dcom.sun.management.jmxremote.port=7199"
 CASSANDRA_OPTS="$CASSANDRA_OPTS -Dcom.sun.management.jmxremote.ssl=false"
 CASSANDRA_OPTS="$CASSANDRA_OPTS -Dcom.sun.management.jmxremote.authenticate=false"
 
 # Create a logback file if required
-cat <<EOF_LOGBACK >${FL_LOGBACK}
+cat <<EOF_LOGBACK >${ONOS_LOGBACK}
 <configuration scan="true" debug="true">
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
     <encoder>
@@ -64,5 +64,5 @@
 # Run floodlight
 echo "Starting ONOS controller ..."
 echo 
-#java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -Xbootclasspath/a:$CLASSPATH -jar ${FL_JAR} -cf ./onos.properties
-java ${JVM_OPTS} ${CASSANDRA_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -jar ${FL_JAR}
+#java ${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -Xbootclasspath/a:$CLASSPATH -jar ${ONOS_JAR} -cf ./onos.properties
+java ${JVM_OPTS} ${CASSANDRA_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -jar ${ONOS_JAR}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..44b7f07
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,382 @@
+<?xml version="1.0"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.0.4</maven>
+  </prerequisites>
+  <groupId>net.onrc.onos</groupId>
+  <artifactId>onos</artifactId>
+  <version>0.1.0</version>
+  <packaging>jar</packaging>
+  <name>ONOS</name>
+  <url>http://onlab.us/</url>
+  <repositories>
+    <repository>
+      <id>central</id>
+      <name>Maven Central repository</name>
+      <url>http://repo1.maven.org/maven2</url>
+    </repository>
+    <repository>
+      <id>maven-restlet</id>
+      <name>Public online Restlet repository</name>
+      <url>http://maven.restlet.org</url>
+    </repository>
+    <repository>
+      <id>tinkerpop-repository</id>
+      <name>TinkerPop Maven2 Repository</name>
+      <url>http://tinkerpop.com/maven2</url>
+      <snapshots>
+	<enabled>false</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <powermock.version>1.5</powermock.version>
+    <restlet.version>2.1-RC1</restlet.version>
+  </properties>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <version>2.3.1</version>
+        <executions>
+        </executions>
+      </plugin>
+      <!-- guice maven plugin for dependency injection inside maven -->
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>guice-maven-plugin</artifactId>
+        <version>2.11.0</version>
+      </plugin>
+      <!-- compile -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+          <encoding>UTF-8</encoding>
+        </configuration>
+        <executions>
+        </executions>
+      </plugin>
+      <!-- test -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.12</version>
+        <configuration>
+          <excludes>
+            <!-- exclude all test cases for now -->
+            <!-- <exclude>**/storage/tests/StorageTest.java</exclude> -->
+            <!-- <exclude>**/test/*</exclude> -->
+          <!--
+            <exclude>**/test/*</exclude>
+            <exclude>**/Test*.java</exclude>
+            <exclude>**/*Test.java</exclude>
+            <exclude>**/*TestCase.java</exclude>
+          -->
+          </excludes>
+        </configuration>
+      </plugin>
+      <!-- exec:java -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <version>1.2.1</version>
+        <configuration>
+          <mainClass>net.onrc.onos.ofcontroller.core.Main</mainClass>
+        </configuration>
+        <executions>
+        </executions>
+      </plugin>
+      <!--<plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <version>1.7</version>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>lib/gen-java</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>-->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.9</version>
+        <configuration>
+          <charset>UTF-8</charset>
+          <locale>en</locale>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+        <version>0.6.3.201306030806</version>
+        <configuration>
+          <destfile>${basedir}/target/jacoco/jacoco.exec</destfile>
+          <datafile>${basedir}/target/jacoco/jacoco.exec</datafile>
+        </configuration>
+        <executions>
+          <execution>
+            <id>jacoco-initialize</id>
+            <goals>
+              <goal>prepare-agent</goal>
+            </goals>
+          </execution>
+          <execution>
+            <id>jacoco-site</id>
+            <phase>package</phase>
+            <goals>
+              <goal>report</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  <!-- for getting visualization reporting   -->
+  <reporting>
+    <excludeDefaults>true</excludeDefaults>
+    <outputDirectory>${project.build.directory}/site</outputDirectory>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>guice-maven-plugin</artifactId>
+        <version>2.11.0</version>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <dependencyDetailsEnabled>false</dependencyDetailsEnabled>
+          <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>dependencies</report>
+              <report>maven-emma-plugin</report>
+              <report>scm</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.9</version>
+        <configuration>
+          <charset>UTF-8</charset>
+          <locale>en</locale>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+  <dependencies>
+    <!-- ONOS's direct dependencies -->
+    <dependency>
+      <groupId>org.apache.cassandra</groupId>
+      <artifactId>apache-cassandra</artifactId>
+      <version>1.2.4</version>
+      <type>pom</type>
+    </dependency>
+    <dependency>
+      <groupId>com.thinkaurelius.titan</groupId>
+      <artifactId>titan-all</artifactId>
+      <version>0.2.1</version>
+      <exclusions>
+	<exclusion>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-log4j12</artifactId>
+	</exclusion>
+      </exclusions>
+    </dependency>
+    <dependency>
+      <groupId>com.tinkerpop</groupId>
+      <artifactId>frames</artifactId>
+      <version>2.3.1</version>
+    </dependency>
+    <!--
+    <dependency>
+      <groupId>com.tinkerpop.blueprints</groupId>
+      <artifactId>blueprints-core</artifactId>
+      <version>2.3.0</version>
+    </dependency>
+    -->
+    <dependency>
+      <groupId>net.sf.json-lib</groupId>
+      <artifactId>json-lib</artifactId>
+      <version>2.4</version>
+      <classifier>jdk15</classifier>
+    </dependency>
+    <dependency>
+      <groupId>org.restlet.jse</groupId>
+      <artifactId>org.restlet</artifactId>
+      <version>${restlet.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.restlet.jse</groupId>
+      <artifactId>org.restlet.ext.slf4j</artifactId>
+      <version>${restlet.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.jackson</groupId>
+      <artifactId>jackson-core-asl</artifactId>
+      <version>1.9.11</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.jackson</groupId>
+      <artifactId>jackson-mapper-asl</artifactId>
+      <version>1.9.11</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <version>1.0.0</version>
+      <scope>runtime</scope>
+    </dependency>
+    <!-- Floodlight's dependencies -->
+    <dependency>
+      <groupId>net.sourceforge.cobertura</groupId>
+      <artifactId>cobertura</artifactId>
+      <version>1.9.4.1</version>
+    </dependency>
+    <!--
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>13.0.1</version>
+    </dependency>
+    -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.6.4</version>
+    </dependency>
+    <dependency>
+      <groupId>org.restlet.jse</groupId>
+      <artifactId>org.restlet.ext.jackson</artifactId>
+      <version>${restlet.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.restlet.jse</groupId>
+      <artifactId>org.restlet.ext.simple</artifactId>
+      <version>${restlet.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.simpleframework</groupId>
+      <artifactId>simple</artifactId>
+      <version>4.1.21</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.netty</groupId>
+      <artifactId>netty</artifactId>
+      <version>3.2.6.Final</version>
+    </dependency>
+    <dependency>
+      <groupId>args4j</groupId>
+      <artifactId>args4j</artifactId>
+      <version>2.0.16</version>
+    </dependency>
+    <dependency>
+      <groupId>com.googlecode.concurrentlinkedhashmap</groupId>
+      <artifactId>concurrentlinkedhashmap-lru</artifactId>
+      <version>1.3</version>
+    </dependency>
+    <!--<dependency>
+      <groupId>org.python</groupId>
+      <artifactId>jython-standalone</artifactId>
+      <version>2.5.2</version>
+    </dependency>-->
+    <!--<dependency>
+      <groupId>org.apache.thrift</groupId>
+      <artifactId>libthrift</artifactId>
+      <version>0.7.0</version>
+    </dependency>-->
+    <dependency>
+      <groupId>com.google.inject</groupId>
+      <artifactId>guice</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <!-- Dependency for libraries used for testing -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.11</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.easymock</groupId>
+      <artifactId>easymock</artifactId>
+      <version>3.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-easymock</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <!--
+    <dependency>
+      <groupId>org.objenesis</groupId>
+      <artifactId>objenesis</artifactId>
+      <version>1.2</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>cglib</groupId>
+      <artifactId>cglib-nodep</artifactId>
+      <version>2.2.2</version>
+    </dependency>
+    -->
+    <!-- dependency to locally modified version -->
+    <dependency>
+      <groupId>com.netflix.curator</groupId>
+      <artifactId>curator-framework</artifactId>
+      <version>1.3.5-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>com.netflix.curator</groupId>
+      <artifactId>curator-client</artifactId>
+      <version>1.3.5-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>com.netflix.curator</groupId>
+      <artifactId>curator-recipes</artifactId>
+      <version>1.3.5-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>com.netflix.curator</groupId>
+      <artifactId>curator-x-discovery</artifactId>
+      <version>1.3.5-SNAPSHOT</version>
+    </dependency>
+    <!--
+    <dependency>
+      <groupId>net.floodlightcontroller</groupId>
+      <artifactId>packetstreamer-thrift</artifactId>
+      <version>0.1.0</version>
+    </dependency>
+    -->
+  </dependencies>
+</project>
diff --git a/scripts/run-onos-simple.sh b/scripts/run-onos-simple.sh
deleted file mode 100755
index 41b2cc6..0000000
--- a/scripts/run-onos-simple.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-basedir=`dirname $0`
-onosdir="${basedir}/.."
-
-logfile="${onosdir}/logback.xml"
-jarfile="${onosdir}/target/floodlight-only.jar"
-classpath="${jarfile}:${onosdir}/lib/*:${onosdir}/lib/titan/*"
-mainclass="net.floodlightcontroller.core.Main"
-propfile="${onosdir}/onos.properties"
-
-#java -Dlogback.configurationFile=logback.xml -cp target/floodlight-only.jar:lib/*:lib/titan/* net.floodlightcontroller.core.Main -cf onos.properties
-java -Dlogback.configurationFile=${logfile} -cp ${classpath} ${mainclass} -cf ${propfile}
diff --git a/scripts/runiperf.sh b/scripts/runiperf.sh
index 4e26bd2..6233986 100755
--- a/scripts/runiperf.sh
+++ b/scripts/runiperf.sh
@@ -2,11 +2,17 @@
 import sys
 import os
 
+ONOSDIR=os.getenv("HOME") + "/ONOS"
+IPERF=ONOSDIR + "/scripts/iperf"
+IPERFLOGDIR=ONOSDIR + "/web/log"
+
 # Usage: flowid src_dpid dst_dpid params
 def usage():
   print "%s flowid src_dpid dst_dpid hw:svr|sw:svr|hw:client|sw:client <proto>/<duration>/<interval>/<samples>" % sys.argv[0]
   sys.exit()
 
+
+
 def main():
   flowid = sys.argv[1]
   src_dpid = sys.argv[2]
@@ -24,9 +30,16 @@
   src_hostid=int(src_dpid.split(':')[-1], 16)
   dst_hostid=int(dst_dpid.split(':')[-1], 16)
 
+  if (testbed == "SW"):
+    MRUN=ONOSDIR + "/test-network/mininet/mrun"
+    HOST_FMT="host%d.%d"
+  else:
+    MRUN=ONOSDIR + "$HOME/mininet/util/m"
+    HOST_FMT="g%sh%02d"
+
   if (proto == "tcp"):
-    if (testbed == "SW"):
-      cmd="ssh -o StrictHostKeyChecking=no 1.1.%d.1 '/home/ubuntu/ONOS/scripts/iperf -t%s -i%s -k%s -yJ -o /home/ubuntu/ONOS/web/log/iperf_%s.out -c 192.168.%d.%d 2>&1 &' &" % (src_hostid, duration, interval, samples, flowid, dst_nwid, dst_hostid)
+      mininet_host = HOST_FMT % (dst_nwid, dst_hostid)
+      cmd="%s %s \'%s -t%s -i%s -k%s -yJ -o %s/iperf_%s.out -c 192.168.%d.%d 2>&1 &\' &" % (MRUN, mininet_host, IPERF, src_hostid, duration, interval, samples, IPERFLOGDIR, flowid, dst_nwid, dst_hostid)
       killcmd='sudo pkill -KILL -f \"iperf .* -o .*/iperf_%s.out\"' % (flowid)
       print killcmd
       print cmd
@@ -34,21 +47,18 @@
       os.popen(cmd)
   else:
     if (server == 'S'):
-      if (testbed == "SW"): 
-        cmd="ssh -o StrictHostKeyChecking=no 1.1.%d.1 '/home/ubuntu/ONOS/scripts/iperf -us -i%s -k%s -yJ -o /home/ubuntu/ONOS/web/log/iperfsvr_%s.out 2>&1 &' &" % (dst_hostid, interval, samples, flowid)
-      else:
-        cmd="~/mininet/util/m g%sh%02d '/home/ubuntu/ONOS/scripts/iperf -us -i%s -k%s -yJ -o /home/ubuntu/ONOS/web/log/iperfsvr_%s.out 2>&1 &' &" % (dst_nwid, dst_hostid, interval, samples, flowid)
+      mininet_host = HOST_FMT % (dst_nwid, dst_hostid)
+      cmd="%s %s \'%s -us -i%s -k%s -yJ -o %s/iperfsvr_%s.out 2>&1 &\' &" % (MRUN, mininet_host, IPERF, interval, samples, IPERFLOGDIR, flowid)
       killcmd='sudo pkill -KILL -f \"iperf .* -o .*/iperfsvr_%s.out\"' % (flowid)
       print killcmd
       print cmd
     else:
-      if (testbed == "SW"): 
-        cmd="ssh -o StrictHostKeyChecking=no 1.1.%d.1 '/home/ubuntu/ONOS/scripts/iperf -u -t%s -i%s -k%s -yJ -o /home/ubuntu/ONOS/web/log/iperfclient_%s.out -c 192.168.%d.%d 2>&1 &' &" % (src_hostid, duration, interval, samples, flowid, dst_nwid, dst_hostid)
-      else:
-        cmd="~/mininet/util/m g%sh%02d '/home/ubuntu/ONOS/scripts/iperf -u -t%s -i%s -k%s -yJ -o /home/ubuntu/ONOS/web/log/iperfclient_%s.out -c 192.168.%d.%d 2>&1 &' &" % (src_nwid, src_hostid, duration, interval, samples, flowid, dst_nwid, dst_hostid )
+      mininet_host = HOST_FMT % (src_nwid, src_hostid)
+      cmd="%s %s \'%s -u  -t%s -i%s -k%s -yJ -o %s/iperfclient_%s.out -c 192.168.%d.%d 2>&1 &\' &" % (MRUN, mininet_host, IPERF, duration, interval, samples, IPERFLOGDIR, flowid, dst_nwid, dst_hostid)
       killcmd='sudo pkill -KILL -f \"iperf .* -o .*/iperfclient_%s.out\"' % (flowid)
       print killcmd
       print cmd
+
     os.popen(killcmd)
     os.popen(cmd)
 
diff --git a/setup-eclipse.sh b/setup-eclipse.sh
index a39dc62..8cf8ed3 100755
--- a/setup-eclipse.sh
+++ b/setup-eclipse.sh
@@ -1,50 +1,6 @@
 #!/bin/bash
+if [ -z "${MVN}" ]; then
+    MVN="mvn"
+fi
+${MVN} eclipse:eclipse
 
-d=$(dirname $0)
-MAIN_CLASS=$1
-LIBRARIES=$2
-[ "${MAIN_CLASS}" ] || { echo "Run 'ant eclipse' to generate Eclipse project files"; exit 1; }
-
-
-cat >$d/.project <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>floodlight</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-	</natures>
-</projectDescription>
-EOF
-
-
-cat >$d/.classpath <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry kind="src" path="src/main/java" output="target/bin"/>
-	<classpathentry kind="src" path="src/main/resources"/>
-        <classpathentry kind="src" path="src/test/java" output="target/bin-test"/>
-        <classpathentry kind="src" path="lib/gen-java" output="target/bin"/>
-EOF
-(
-IFS=":"
-for l in ${LIBRARIES}; do
-cat >>$d/.classpath <<EOF
-	<classpathentry exported="true" kind="lib" path="$l"/>
-EOF
-done
-)
-cat >>$d/.classpath <<EOF
-	<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-	<classpathentry kind="output" path="target/bin"/>
-</classpath>
-EOF
diff --git a/setup-local-maven.sh b/setup-local-maven.sh
new file mode 100755
index 0000000..3a2538c
--- /dev/null
+++ b/setup-local-maven.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+if [ -z "${MVN}" ]; then
+    MVN="mvn"
+fi
+
+${MVN} install:install-file -Dfile=./lib/curator-framework-1.3.5-SNAPSHOT.jar -DgroupId=com.netflix.curator -DartifactId=curator-framework -Dversion=1.3.5-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
+${MVN} install:install-file -Dfile=./lib/curator-client-1.3.5-SNAPSHOT.jar -DgroupId=com.netflix.curator -DartifactId=curator-client -Dversion=1.3.5-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
+${MVN} install:install-file -Dfile=./lib/curator-recipes-1.3.5-SNAPSHOT.jar -DgroupId=com.netflix.curator -DartifactId=curator-recipes -Dversion=1.3.5-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
+${MVN} install:install-file -Dfile=./lib/curator-x-discovery-1.3.5-SNAPSHOT.jar -DgroupId=com.netflix.curator -DartifactId=curator-x-discovery -Dversion=1.3.5-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
+
+# download package dependencies
+${MVN} dependency:go-offline
+
+# run goals to download required plugins
+${MVN} -q test -Dtest=DoNotTest -DfailIfNoTests=false > /dev/null
+${MVN} clean compile
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java
deleted file mode 100644
index 47f3d1a..0000000
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRoute.java
+++ /dev/null
@@ -1,313 +0,0 @@
-package net.floodlightcontroller.bgproute;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Map;
-import java.util.ArrayList;
-import java.util.HashMap;
-
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.topology.ITopologyListener;
-import net.floodlightcontroller.topology.ITopologyService;
-import net.floodlightcontroller.restclient.RestClient;
-
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import net.sf.json.JSONSerializer;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BgpRoute implements IFloodlightModule, IBgpRouteService, ITopologyListener {
-	
-	protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
-
-	protected IFloodlightProviderService floodlightProvider;
-	protected ITopologyService topology;
-	
-	protected static Ptree ptree;
-	protected static String BGPdRestIp;
-	protected static String RouterId;
-	
-	
-	
-	@Override
-	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
-		l.add(IBgpRouteService.class);
-		return l;
-	}
-
-	@Override
-	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
-		Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
-		m.put(IBgpRouteService.class, this);
-		return m;
-	}
-
-	protected IRestApiService restApi;
-	
-	@Override
-	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-		Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
-		l.add(IFloodlightProviderService.class);
-		l.add(ITopologyService.class);
-		l.add(IBgpRouteService.class);
-		return l;
-	}
-	
-	@Override
-	public void init(FloodlightModuleContext context)
-			throws FloodlightModuleException {
-	    
-	    ptree = new Ptree(32);
-		
-		// Register floodlight provider and REST handler.
-		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-		restApi = context.getServiceImpl(IRestApiService.class);
-		topology = context.getServiceImpl(ITopologyService.class);
-		
-		// Test.
-		//test();
-		  
-	}
-
-	public Ptree getPtree() {
-		return ptree;
-	}
-	public void  clearPtree() {
-		ptree = null;
-		ptree = new Ptree(32);
-		
-	}
-	public String getBGPdRestIp() {
-		return BGPdRestIp;
-	}
-	public String getRouterId() {
-		return RouterId;
-	}
-	
-	// Return nexthop address as byte array.
-	public Rib lookupRib(byte[] dest) {
-		if (ptree == null) {
-		    log.debug("lookupRib: ptree null");
-		    return null;
-		}
-		
-		PtreeNode node = ptree.match(dest, 32);
-		if (node == null) {
-            log.debug("lookupRib: ptree node null");
-			return null;
-		}
-		if (node.rib == null) {
-            log.debug("lookupRib: ptree rib null");
-			return null;
-		}
-		ptree.delReference(node);
-		
-		return node.rib;
-	}
-	
-	@SuppressWarnings("unused")
-    private void test() {
-		System.out.println("Here it is");
-		Prefix p = new Prefix("128.0.0.0", 8);
-		Prefix q = new Prefix("8.0.0.0", 8);
-		Prefix r = new Prefix("10.0.0.0", 24);
-		Prefix a = new Prefix("10.0.0.1", 32);
-	
-		ptree.acquire(p.getAddress(), p.masklen);
-		ptree.acquire(q.getAddress(), q.masklen);
-		ptree.acquire(r.getAddress(), r.masklen);
-	
-		System.out.println("Traverse start");
-		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
-			Prefix p_result = new Prefix(node.key, node.keyBits);
-		}
-	
-		PtreeNode n = ptree.match(a.getAddress(), a.masklen);
-		if (n != null) {
-			System.out.println("Matched prefix for 10.0.0.1:");
-			Prefix x = new Prefix(n.key, n.keyBits);
-			ptree.delReference(n);
-		}
-		
-		n = ptree.lookup(p.getAddress(), p.masklen);
-		if (n != null) {
-			ptree.delReference(n);
-			ptree.delReference(n);
-		}
-		System.out.println("Traverse start");
-		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
-			Prefix p_result = new Prefix(node.key, node.keyBits);
-		}
-		
-		n = ptree.lookup(q.getAddress(), q.masklen);
-		if (n != null) {
-			ptree.delReference(n);
-			ptree.delReference(n);
-		}
-		System.out.println("Traverse start");
-		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
-			Prefix p_result = new Prefix(node.key, node.keyBits);
-		}
-		
-		n = ptree.lookup(r.getAddress(), r.masklen);
-		if (n != null) {
-			ptree.delReference(n);
-			ptree.delReference(n);
-		}
-		System.out.println("Traverse start");
-		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
-			Prefix p_result = new Prefix(node.key, node.keyBits);
-		}
-
-	}
-	
-	@Override
-	public void startUp(FloodlightModuleContext context) {
-		restApi.addRestletRoutable(new BgpRouteWebRoutable());
-		topology.addListener((ITopologyListener) this);
-		
-		 // get the BGPdRestIp and RouterId from transit-route-pusher.py
-  		File file = new File("/home/ubuntu/sdn/transit-route-pusher.py");  
-       
-        
-    try{  
-        BufferedReader input = new BufferedReader (new FileReader(file));  
-        String text; 
-        int is_BGPdRestIp=0;
-        int is_RouterId=0;
-        								                         
-        while((text = input.readLine()) != null && (is_BGPdRestIp == 0) || (is_RouterId == 0) ){  
-        					  
-        		if(is_BGPdRestIp == 1 && is_RouterId ==1)
-        		{break;}
-        		
-        				if(is_BGPdRestIp == 0 && text.contains("BGPdRestIp") ){
-		        				String[] temp =	text.split("\"");
-		        				BGPdRestIp = temp[1];
-		        				is_BGPdRestIp = 1;
-		        				
-        				
-            	}else if (is_RouterId == 0 && text.contains("RouterId") ){
-												
-		            	String[] temp =	text.split("\"");
-		    							RouterId = temp[1];
-		    							is_RouterId = 1;
-		    							
-    							
-									}
-        						
-        					}
-    
-                   
-    }  catch(Exception e){  
-       e.printStackTrace();
-           }  
-      
-		        
-			// automatically get the rib from bgpd at the ONOS initiation process.
-    String dest=RouterId;
-    String str="http://"+BGPdRestIp+"/wm/bgp/"+dest;
-	 		
-	          
-	try {
-	       	 
-				URL url = new URL(str);
-				HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-				conn.setRequestMethod("GET");
-				conn.setRequestProperty("Accept", "application/json");
-		 
-				if (conn.getResponseCode() != 200) {
-					throw new RuntimeException("Failed : HTTP error code : "
-							+ conn.getResponseCode());
-				}
-	
-			 BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 
-			 StringBuffer res = new StringBuffer();
-			 String line;
-			 while ((line = br.readLine()) != null) {
-				 	res.append(line);
-			 	}	   
-			 
-			 String res2=res.toString().replaceAll("\"", "'");
-			 JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(res2);  
-			 JSONArray rib_json_array = jsonObj.getJSONArray("rib");
-			 String router_id = jsonObj.getString("router-id");
-			       
-			 int size = rib_json_array.size();
-			 System.out.print("size:"+size+"\n");
-			 for (int j = 0; j < size; j++) {
-	        JSONObject second_json_object = rib_json_array.getJSONObject(j);
-	        String prefix = second_json_object.getString("prefix");
-	        String nexthop = second_json_object.getString("nexthop");
-	        
-	        //insert each rib entry into the local rib;
-	        String[] substring= prefix.split("/");
-	        String prefix1=substring[0];
-	        String mask1=substring[1];
-	        			
-						Prefix p = new Prefix(prefix1, Integer.valueOf(mask1));
-						PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
-						Rib rib = new Rib(router_id, nexthop, p.masklen);
-			
-						if (node.rib != null) {
-							node.rib = null;
-							ptree.delReference(node);
-						}
-						node.rib = rib;
-      
-			 }  
-			 br.close();
-			 conn.disconnect();
-
-			} catch (MalformedURLException e) {
-
-				e.printStackTrace();
-
-			} catch (IOException e) {
-
-				e.printStackTrace();
-
-			}
-	
-
-	}
-
-	@Override
-	public void topologyChanged() {
-		boolean change = false;
-		String changelog = "";
-		
-		for (LDUpdate ldu : topology.getLastLinkUpdates()) {
-			if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_DOWN)) {
-				change = true;
-				changelog = changelog + " down ";
-			} else if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.PORT_UP)) {
-				change = true;
-				changelog = changelog + " up ";
-			}
-		}
-		log.info ("received topo change" + changelog);
-
-		if (change) {
-			RestClient.get ("http://localhost:5000/topo_change");
-		}
-	}
-}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java
deleted file mode 100644
index 28d9621..0000000
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResource.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package net.floodlightcontroller.bgproute;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.Post;
-import org.restlet.resource.Delete;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import net.floodlightcontroller.restclient.RestClient;
-import java.io.UnsupportedEncodingException;  
-import java.nio.ByteBuffer;  
-
-public class BgpRouteResource extends ServerResource {
-    
-	protected static Logger log = LoggerFactory
-            .getLogger(BgpRouteResource.class);
-	
-	private String addrToString(byte [] addr) {
-	    String str = "";
-		
-		for (int i = 0; i < 4; i++) {
-			int val = (addr[i] & 0xff);
-			str += val;
-			if (i != 3)
-				str += ".";
-		}
-		
-		return str;
-	}
-	
-	@SuppressWarnings("unused")
-	@Get
-		public String get(String fmJson) {		
-		String linpp=fmJson;
-			String dest = (String) getRequestAttributes().get("dest");
-			String output = "";
-			IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
-	                get(IBgpRouteService.class.getCanonicalName());
-			
-			if (dest != null) {
-				Prefix p = new Prefix(dest, 32);
-				if (p == null) {
-					return "[GET]: dest address format is wrong";
-				}
-							
-				// the dest here refers to router-id
-				//BGPdRestIp includes port number, such as 1.1.1.1:8080
-				String BGPdRestIp = bgpRoute.getBGPdRestIp();
-				String url="http://"+BGPdRestIp+"/wm/bgp/"+dest;
-				
-							
-				
-				RestClient.get(url);
-				output="Get rib from bgpd finished!\n";
-				return output;
-			
-			} else {
-				Ptree ptree = bgpRoute.getPtree();
-				output += "{\n  \"rib\": [\n";
-				boolean printed = false;
-				for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
-					if (node.rib == null) {
-						continue;
-					}
-					if (printed == true) {
-						output += ",\n";
-					}
-					output += "    {\"prefix\": \"" + addrToString(node.key) + "/" + node.keyBits +"\", ";
-					output += "\"nexthop\": \"" + addrToString(node.rib.nextHop.getAddress()) +"\"}";
-					printed = true;
-				}
-				//output += "{\"router_id\": \"" + addrToString(node.rib.routerId.getAddress()) +"\"}\n";
-				output += "\n  ]\n}\n";
-	   
-			}
-			return output;
-		}
-
-	public static ByteBuffer toByteBuffer(String value) throws UnsupportedEncodingException
-	  {
-	  return ByteBuffer.wrap(value.getBytes("UTF-8"));
-	  }
-
-public static String toString(ByteBuffer buffer) throws UnsupportedEncodingException
-	 {
-	    byte[] bytes = new byte[buffer.remaining()];
-	    buffer.get(bytes);
-	    return new String(bytes, "UTF-8");
-	    
-	   }
-
-	
-	@Post
-	public String store(String fmJson) {
-        IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
-                get(IBgpRouteService.class.getCanonicalName());
- 	
-	  Ptree ptree = bgpRoute.getPtree();
-	
-		String router_id = (String) getRequestAttributes().get("routerid");
-		String prefix = (String) getRequestAttributes().get("prefix");
-		String mask = (String) getRequestAttributes().get("mask");
-		String nexthop = (String) getRequestAttributes().get("nexthop");
-		String capability = (String) getRequestAttributes().get("capability");
-		
-	
-		String reply = "";
-		
-		if (capability == null) {
-		
-			// this is a prefix add
-			Prefix p = new Prefix(prefix, Integer.valueOf(mask));
-			PtreeNode node = ptree.acquire(p.getAddress(), p.masklen);
-			Rib rib = new Rib(router_id, nexthop, p.masklen);
-
-			if (node.rib != null) {
-				node.rib = null;
-				ptree.delReference(node);
-			}
-			node.rib = rib;
-			
-			reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "]";
-			log.info(reply);
-	
-			
-		}else if(capability.equals("1")){
-			reply = "[POST-capability: " + capability + "]\n";
-			log.info(reply);
-			// to store the number in the top node of the Ptree	
-			
-		}else{			
-			reply = "[POST-capability: " + capability + "]\n";
-			log.info(reply);
-			// to store the number in the top node of the Ptree	
-	
-		}
-		
-		
-		return reply + "\n";
-		
-	
-	}
-	
-	@Delete
-	public String delete(String fmJson) {
-		IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
-                get(IBgpRouteService.class.getCanonicalName());
-
-   Ptree ptree = bgpRoute.getPtree();
-      	
-		String routerId = (String) getRequestAttributes().get("routerid");
-		String prefix = (String) getRequestAttributes().get("prefix");
-		String mask = (String) getRequestAttributes().get("mask");
-		String nextHop = (String) getRequestAttributes().get("nexthop");
-		String capability = (String) getRequestAttributes().get("capability");
-		
-		String reply = "";
-		
-		if (capability == null) {
-					// this is a prefix delete
-					Prefix p = new Prefix(prefix, Integer.valueOf(mask));
-										
-					PtreeNode node = ptree.lookup(p.getAddress(), p.masklen);
-									
-					Rib r = new Rib(routerId, nextHop, p.masklen);
-					
-					if (node != null && node.rib != null) {
-						
-						if (r.equals(node.rib)) {
-							
-							node.rib = null;
-							ptree.delReference(node);					
-						}
-					}
-					
-							
-					reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
-					
-		}else {
-			
-			// clear the local rib: Ptree			
-			bgpRoute.clearPtree();
-			reply = "[DELE-capability: " + capability + "; The local Rib is cleared!]\n";
-			
-			
-			// to store the number in the top node of the Ptree	
-				
-		}	
-		log.info(reply);
-	
-		return reply + "\n";
-	}
-}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java b/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java
deleted file mode 100644
index a6025ef..0000000
--- a/src/main/java/net/floodlightcontroller/bgproute/IBgpRouteService.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.floodlightcontroller.bgproute;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-public interface IBgpRouteService extends IFloodlightService {
-
-    public Rib lookupRib(byte[] dest);
-    
-    public Ptree getPtree();
-    
-    public String getBGPdRestIp();
-    
-    public String getRouterId();
-    
-	  public void  clearPtree() ;
-       
-    
-}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/Prefix.java b/src/main/java/net/floodlightcontroller/bgproute/Prefix.java
deleted file mode 100644
index 7ba014b..0000000
--- a/src/main/java/net/floodlightcontroller/bgproute/Prefix.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.floodlightcontroller.bgproute;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-public class Prefix {
-	public int masklen;
-	protected InetAddress address;
-
-	Prefix(byte[] addr, int masklen) {
-		try {
-			address = InetAddress.getByAddress(addr);
-		} catch (UnknownHostException e) {
-			System.out.println("InetAddress exception");
-			return;
-		}
-		this.masklen = masklen;
-		System.out.println(address.toString() + "/" + masklen);
-	}
-	
-	Prefix(String str, int masklen) {
-		try {
-			address = InetAddress.getByName(str);
-			//System.out.println(address.toString());
-		} catch (UnknownHostException e) {
-			System.out.println("InetAddress exception");
-			return;
-		}
-		this.masklen = masklen;
-	}
-	
-	public byte [] getAddress() {
-		return address.getAddress();
-	}
-}
diff --git a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
index cd15927..c821339 100644
--- a/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
+++ b/src/main/java/net/floodlightcontroller/core/FloodlightProvider.java
@@ -10,13 +10,12 @@
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
 import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.flowcache.IFlowService;
 import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.storage.IStorageSourceService;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 
 public class FloodlightProvider implements IFloodlightModule {
@@ -52,8 +51,8 @@
         dependencies.add(IRestApiService.class);
         dependencies.add(ICounterStoreService.class);
         dependencies.add(IThreadPoolService.class);
+        // Following added by ONOS
         dependencies.add(IFlowService.class);
-        dependencies.add(ITopoRouteService.class);
         dependencies.add(IControllerRegistryService.class);
 
         return dependencies;
@@ -71,8 +70,8 @@
            context.getServiceImpl(IRestApiService.class));
        controller.setThreadPoolService(
            context.getServiceImpl(IThreadPoolService.class));
+       // Following added by ONOS
        controller.setFlowService(context.getServiceImpl(IFlowService.class));
-       controller.setTopoRouteService(context.getServiceImpl(ITopoRouteService.class));
        controller.setMastershipService(
     		   context.getServiceImpl(IControllerRegistryService.class));
 
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapService.java b/src/main/java/net/floodlightcontroller/core/INetMapService.java
deleted file mode 100644
index fcc542a..0000000
--- a/src/main/java/net/floodlightcontroller/core/INetMapService.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package net.floodlightcontroller.core;
-
-public interface INetMapService {
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java b/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java
deleted file mode 100644
index 36b5be3..0000000
--- a/src/main/java/net/floodlightcontroller/core/IOFMessageFilterManagerService.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.floodlightcontroller.core;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-public interface IOFMessageFilterManagerService extends IFloodlightService {
-    // empty for now
-}
diff --git a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
index df609e7..d63624c 100644
--- a/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOFSwitch.java
@@ -338,12 +338,6 @@
     Object removeAttribute(String name);
 
     /**
-     * Setup an unconnected switch with the info required.
-     * @param dpid of the switch
-     */
-    public void setupRemoteSwitch(Long dpid);
-    
-    /**
      * Clear all flowmods on this switch
      */
     public void clearAllFlowMods();
diff --git a/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java b/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java
deleted file mode 100644
index 1219aac..0000000
--- a/src/main/java/net/floodlightcontroller/core/ISwitchStorage.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package net.floodlightcontroller.core;
-
-import java.util.Collection;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-
-import org.openflow.protocol.OFPhysicalPort;
-
-public interface ISwitchStorage extends INetMapStorage {
-	
-	public enum SwitchState {
-		INACTIVE,
-		ACTIVE
-	}
-	
-	/*
-	 * Update the switch details
-	 */
-	public void update(String dpid,SwitchState state, DM_OPERATION op);
-	/*
-	 * Associate a port on switch
-	 */
-	public void addPort(String dpid, OFPhysicalPort port);
-	/*
-	 * Get all ports associated on a switch
-	 */
-	public Collection<OFPhysicalPort> getPorts(long dpid);
-	/*
-	 * Get Port by Number
-	 */
-	public OFPhysicalPort getPort(String dpid, short portnum);
-	/*
-	 * Get port by name
-	 */
-	public OFPhysicalPort getPort(String dpid, String portName);
-	/*
-	 * Add a switch
-	 */
-	public void addSwitch(String dpid);
-	/*
-	 * Delete switch and associated ports
-	 */
-	public void deleteSwitch(String dpid);
-	/*
-	 * Delete a port on a switch by num
-	 */
-	public void deletePort(String dpid, short port);
-	/*
-	 * Delete port on a switch by name
-	 */
-	public void deletePort(String dpid, String portName);
-	
-	
-	/*
-	 * Initialize
-	 */
-	public void init(String conf);
-	
-
-}
diff --git a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java b/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java
deleted file mode 100644
index 391c002..0000000
--- a/src/main/java/net/floodlightcontroller/core/OFMessageFilterManager.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/**
- *    Copyright 2011, Big Switch Networks, Inc.
- *    Originally created by David Erickson, Stanford University
- *
- *    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.
- **/
-
-package net.floodlightcontroller.core;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ScheduledExecutorService;
-
-import org.jboss.netty.buffer.ChannelBuffer;
-import org.jboss.netty.buffer.ChannelBuffers;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFType;
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.ArrayList;
-import org.apache.thrift.TException;
-import org.apache.thrift.transport.TFramedTransport;
-import org.apache.thrift.transport.TTransport;
-import org.apache.thrift.transport.TSocket;
-import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.protocol.TProtocol;
-
-import net.floodlightcontroller.core.annotations.LogMessageCategory;
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packetstreamer.thrift.*;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-
-@LogMessageCategory("OpenFlow Message Tracing")
-public class OFMessageFilterManager 
-        implements IOFMessageListener, IFloodlightModule, IOFMessageFilterManagerService {
-
-    /**
-     * @author Srini
-     */
-    protected static Logger log = LoggerFactory.getLogger(OFMessageFilterManager.class);
-
-    // The port and client reference for packet streaming
-    protected int serverPort = 9090;
-    protected final int MaxRetry = 1;
-    protected static TTransport transport = null;
-    protected static PacketStreamer.Client packetClient = null;
-
-    protected IFloodlightProviderService floodlightProvider = null;
-    protected IThreadPoolService threadPool = null;
-    // filter List is a key value pair.  Key is the session id, 
-    // value is the filter rules.
-    protected ConcurrentHashMap<String, 
-                                ConcurrentHashMap<String,
-                                                  String>> filterMap = null;
-    protected ConcurrentHashMap<String, Long> filterTimeoutMap = null;
-    protected Timer timer = null;
-
-    protected int MAX_FILTERS=5;
-    protected long MAX_FILTER_TIME= 300000; // maximum filter time is 5 minutes.
-    protected int TIMER_INTERVAL = 1000;  // 1 second time interval.
-
-    public static final String SUCCESS                     = "0";
-    public static final String FILTER_SETUP_FAILED         = "-1001"; 
-    public static final String FILTER_NOT_FOUND            = "-1002";
-    public static final String FILTER_LIMIT_REACHED        = "-1003";
-    public static final String FILTER_SESSION_ID_NOT_FOUND = "-1004";
-    public static final String SERVICE_UNAVAILABLE         = "-1005";
-
-    public enum FilterResult {
-        /*
-         * FILTER_NOT_DEFINED: Filter is not defined
-         * FILTER_NO_MATCH:    Filter is defined and the packet doesn't 
-         *                     match the filter
-         * FILTER_MATCH:       Filter is defined and the packet matches
-         *                     the filter
-         */
-        FILTER_NOT_DEFINED, FILTER_NO_MATCH, FILTER_MATCH
-    }
-
-    protected String addFilter(ConcurrentHashMap<String,String> f, long delta) {
-
-        // Create unique session ID.  
-        int prime = 33791;
-        String s = null;
-        int i;
-
-        if ((filterMap == null) || (filterTimeoutMap == null))
-            return  String.format("%d", FILTER_SETUP_FAILED);
-
-        for (i=0; i<MAX_FILTERS; ++i) {
-            Integer x = prime + i;
-            s = String.format("%d", x.hashCode());
-            // implies you can use this key for session id.    
-            if (!filterMap.containsKey(s)) break; 
-        }
-
-        if (i==MAX_FILTERS) {
-            return FILTER_LIMIT_REACHED;
-        }
-
-        filterMap.put(s, f);
-        if (filterTimeoutMap.containsKey(s))  filterTimeoutMap.remove(s);
-        filterTimeoutMap.put(s, delta);
-
-        // set the timer as there will be no existing timers. 
-        if (filterMap.size() == 1) { 
-            TimeoutFilterTask task = new TimeoutFilterTask(this);
-            Timer timer = new Timer();
-            timer.schedule (task, TIMER_INTERVAL);                
-            // Keep the listeners to avoid race condition
-            //startListening();
-        }   
-        return s;  // the return string is the session ID.
-    }
-
-    public String setupFilter(String sid, 
-                              ConcurrentHashMap<String,String> f, 
-                              int deltaInMilliSeconds) {
-
-        if (sid == null) {
-            // Delta in filter needs to be milliseconds
-            log.debug("Adding new filter: {} for {} ms", f, deltaInMilliSeconds);
-            return addFilter(f, deltaInMilliSeconds);
-        } else {// this is the session id.
-            // we will ignore the hash map features.
-            if (deltaInMilliSeconds > 0)  
-                return refreshFilter(sid, deltaInMilliSeconds);
-            else 
-                return deleteFilter(sid);
-        }
-    }
-
-    public int timeoutFilters() {                
-        Iterator<String> i = filterTimeoutMap.keySet().iterator();
-
-        while(i.hasNext()) {
-            String s = i.next();
-
-            Long t = filterTimeoutMap.get(s);
-            if (t != null) {
-                i.remove();
-                t -= TIMER_INTERVAL;
-                if (t > 0) {
-                    filterTimeoutMap.put(s, t);
-                } else deleteFilter(s);
-            } else deleteFilter(s);
-        }
-        return filterMap.size();
-    }
-
-    protected String refreshFilter(String s, int delta) {
-        Long t = filterTimeoutMap.get(s);
-        if (t != null) {
-            filterTimeoutMap.remove(s);
-            t += delta;  // time is in milliseconds
-            if (t > MAX_FILTER_TIME) t = MAX_FILTER_TIME;
-            filterTimeoutMap.put(s, t);
-            return SUCCESS;
-        } else return FILTER_SESSION_ID_NOT_FOUND;
-    }
-
-    @LogMessageDoc(level="ERROR",
-                   message="Error while terminating packet " +
-                           "filter session",
-                   explanation="An unknown error occurred while terminating " +
-                   		"a packet filter session.",
-                   recommendation=LogMessageDoc.GENERIC_ACTION)
-    protected String deleteFilter(String sessionId) {
-
-        if (filterMap.containsKey(sessionId)) {
-            filterMap.remove(sessionId);
-            try {
-                if (packetClient != null)
-                    packetClient.terminateSession(sessionId);
-            } catch (TException e) {
-                log.error("Error while terminating packet " +
-                		  "filter session", e);
-            }
-            log.debug("Deleted Filter {}.  # of filters" +
-            		 " remaining: {}", sessionId, filterMap.size());
-            return SUCCESS;
-        } else return FILTER_SESSION_ID_NOT_FOUND;
-    }
-
-    public HashSet<String> getMatchedFilters(OFMessage m, FloodlightContext cntx) {  
-
-        HashSet<String> matchedFilters = new HashSet<String>();
-
-        // This default function is written to match on packet ins and 
-        // packet outs.
-        Ethernet eth = null;
-
-        if (m.getType() == OFType.PACKET_IN) {
-            eth = IFloodlightProviderService.bcStore.get(cntx, 
-                    IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-        } else if (m.getType() == OFType.PACKET_OUT) {
-            eth = new Ethernet();
-            OFPacketOut p = (OFPacketOut) m;
-            
-            // No MAC match if packetOut doesn't have the packet.
-            if (p.getPacketData() == null) return null;
-            
-            eth.deserialize(p.getPacketData(), 0, p.getPacketData().length);
-        } else if (m.getType() == OFType.FLOW_MOD) {
-            // flow-mod can't be matched by mac.
-            return null;
-        }
-
-        if (eth == null) return null;
-
-        Iterator<String> filterIt = filterMap.keySet().iterator();
-        while (filterIt.hasNext()) {   // for every filter
-            boolean filterMatch = false;
-            String filterSessionId = filterIt.next();
-            Map<String,String> filter = filterMap.get(filterSessionId);
-
-            // If the filter has empty fields, then it is not considered as a match.
-            if (filter == null || filter.isEmpty()) continue;                  
-            Iterator<String> fieldIt = filter.keySet().iterator();
-            while (fieldIt.hasNext()) {   
-                String filterFieldType = fieldIt.next();
-                String filterFieldValue = filter.get(filterFieldType);
-                if (filterFieldType.equals("mac")) {
-
-                    String srcMac = HexString.toHexString(eth.getSourceMACAddress());
-                    String dstMac = HexString.toHexString(eth.getDestinationMACAddress());
-                    log.debug("srcMac: {}, dstMac: {}", srcMac, dstMac);
-
-                    if (filterFieldValue.equals(srcMac) || 
-                            filterFieldValue.equals(dstMac)){
-                        filterMatch = true; 
-                    } else {
-                        filterMatch = false;
-                        break;
-                    }
-                }
-            }
-            if (filterMatch) {
-                matchedFilters.add(filterSessionId);
-            }
-        }
-
-        if (matchedFilters.isEmpty())
-            return null;    
-        else 
-            return matchedFilters;
-    }
-    
-    @LogMessageDoc(level="ERROR",
-                   message="Failed to establish connection with the " +
-                           "packetstreamer server.",
-                   explanation="The message tracing server is not running " +
-                   		"or otherwise unavailable.",
-                   recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    public boolean connectToPSServer() {
-        int numRetries = 0;
-        if (transport != null && transport.isOpen()) {
-            return true;
-        }
-
-        while (numRetries++ < MaxRetry) {
-            try {
-                transport = new TFramedTransport(new TSocket("localhost", 
-                                                             serverPort));
-                transport.open();
-
-                TProtocol protocol = new  TBinaryProtocol(transport);
-                packetClient = new PacketStreamer.Client(protocol);
-
-                log.debug("Have a connection to packetstreamer server " +
-                		  "localhost:{}", serverPort);
-                break;
-            } catch (TException x) {
-                try {
-                    // Wait for 1 second before retry
-                    if (numRetries < MaxRetry) {
-                        Thread.sleep(1000);
-                    }
-                } catch (Exception e) {}
-            } 
-        }
-
-        if (numRetries > MaxRetry) {
-            log.error("Failed to establish connection with the " +
-            		  "packetstreamer server.");
-            return false;
-        }
-        return true;
-    }
-
-    public void disconnectFromPSServer() {
-        if (transport != null && transport.isOpen()) {
-            log.debug("Close the connection to packetstreamer server" +
-            		  " localhost:{}", serverPort);
-            transport.close();
-        }
-    }
-
-    @Override
-    public String getName() {
-        return "messageFilterManager";
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        return (type == OFType.PACKET_IN && name.equals("devicemanager"));
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        return (type == OFType.PACKET_IN && name.equals("learningswitch"));
-    }
-
-    @Override
-    @LogMessageDoc(level="ERROR",
-                   message="Error while sending packet",
-                   explanation="Failed to send a message to the message " +
-                   		"tracing server",
-                   recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    public Command receive(IOFSwitch sw, OFMessage msg, 
-                           FloodlightContext cntx) {
-
-        if (filterMap == null || filterMap.isEmpty()) return Command.CONTINUE;
-
-        HashSet<String> matchedFilters = null;
-        if (log.isDebugEnabled()) {
-            log.debug("Received packet {} from switch {}", 
-                      msg, sw.getStringId());
-        }
-
-        matchedFilters = getMatchedFilters(msg, cntx);
-        if (matchedFilters == null) {
-            return Command.CONTINUE;
-        } else {
-            try {
-                sendPacket(matchedFilters, sw, msg, cntx, true);
-            } catch (Exception e) {
-                log.error("Error while sending packet", e);
-            }
-        }
-        
-        return Command.CONTINUE;
-    }
-
-
-    public class TimeoutFilterTask extends TimerTask {
-
-        OFMessageFilterManager filterManager;
-        ScheduledExecutorService ses = threadPool.getScheduledExecutor();
-
-        public TimeoutFilterTask(OFMessageFilterManager manager) {
-            filterManager = manager;
-        }
-
-        public void run() {
-            int x = filterManager.timeoutFilters();
-
-            if (x > 0) {  // there's at least one filter still active.
-                Timer timer = new Timer();
-                timer.schedule(new TimeoutFilterTask(filterManager), 
-                               TIMER_INTERVAL);
-            } else {
-                // Don't stop the listener to avoid race condition
-                //stopListening();
-            }
-        }
-    }
-
-    public int getNumberOfFilters() {
-        return filterMap.size();
-    }
-
-    public int getMaxFilterSize() {
-        return MAX_FILTERS;
-    }
-
-    protected void sendPacket(HashSet<String> matchedFilters, IOFSwitch sw, 
-            OFMessage msg, FloodlightContext cntx, boolean sync) 
-                    throws TException {
-        Message sendMsg = new Message();
-        Packet packet = new Packet();
-        ChannelBuffer bb;
-        sendMsg.setPacket(packet);
-
-        List<String> sids = new ArrayList<String>(matchedFilters);
-
-        sendMsg.setSessionIDs(sids);
-        packet.setMessageType(OFMessageType.findByValue((msg.getType().ordinal())));
-
-        switch (msg.getType()) {
-            case PACKET_IN:
-                OFPacketIn pktIn = (OFPacketIn)msg;
-                packet.setSwPortTuple(new SwitchPortTuple(sw.getId(), 
-                                                          pktIn.getInPort()));
-                bb = ChannelBuffers.buffer(pktIn.getLength());
-                pktIn.writeTo(bb);
-                packet.setData(OFMessage.getData(sw, msg, cntx));
-                break;
-            case PACKET_OUT:
-                OFPacketOut pktOut = (OFPacketOut)msg;
-                packet.setSwPortTuple(new SwitchPortTuple(sw.getId(), 
-                                                          pktOut.getInPort()));
-                bb = ChannelBuffers.buffer(pktOut.getLength());
-                pktOut.writeTo(bb);
-                packet.setData(OFMessage.getData(sw, msg, cntx));
-                break;
-            case FLOW_MOD:
-                OFFlowMod offlowMod = (OFFlowMod)msg;
-                packet.setSwPortTuple(new SwitchPortTuple(sw.getId(), 
-                                                          offlowMod.
-                                                          getOutPort()));
-                bb = ChannelBuffers.buffer(offlowMod.getLength());
-                offlowMod.writeTo(bb);
-                packet.setData(OFMessage.getData(sw, msg, cntx));
-                break;
-            default:
-                packet.setSwPortTuple(new SwitchPortTuple(sw.getId(), 
-                                                          (short)0));
-                String strData = "Unknown packet";
-                packet.setData(strData.getBytes());
-                break;
-        }
-
-        try {
-            if (transport == null || 
-                !transport.isOpen() || 
-                packetClient == null) {
-                if (!connectToPSServer()) {
-                    // No need to sendPacket if can't make connection to 
-                    // the server
-                    return;
-                }
-            }
-            if (sync) {
-                log.debug("Send packet sync: {}", packet.toString());
-                packetClient.pushMessageSync(sendMsg);
-            } else {
-                log.debug("Send packet sync: ", packet.toString());
-                packetClient.pushMessageAsync(sendMsg);
-            }
-        } catch (Exception e) {
-            log.error("Error while sending packet", e);
-            disconnectFromPSServer();
-            connectToPSServer();
-        }
-    }
-
-    // IFloodlightModule methods
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IOFMessageFilterManagerService.class);
-        return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-        IFloodlightService> m = 
-            new HashMap<Class<? extends IFloodlightService>,
-                        IFloodlightService>();
-        // We are the class that implements the service
-        m.put(IOFMessageFilterManagerService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        l.add(IThreadPoolService.class);
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context) 
-            throws FloodlightModuleException {
-        this.floodlightProvider = 
-                context.getServiceImpl(IFloodlightProviderService.class);
-        this.threadPool =
-                context.getServiceImpl(IThreadPoolService.class);
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        // This is our 'constructor'
-        
-        filterMap = new ConcurrentHashMap<String, ConcurrentHashMap<String,String>>();
-        filterTimeoutMap = new ConcurrentHashMap<String, Long>();
-        serverPort = 
-                Integer.parseInt(System.getProperty("net.floodlightcontroller." +
-                		"packetstreamer.port", "9090"));
-        
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        floodlightProvider.addOFMessageListener(OFType.PACKET_OUT, this);
-        floodlightProvider.addOFMessageListener(OFType.FLOW_MOD, this);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 0d49c03..ac29983 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -54,20 +54,16 @@
 import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IListener.Command;
-import net.floodlightcontroller.core.INetMapStorage.DM_OPERATION;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchFilter;
 import net.floodlightcontroller.core.IOFSwitchListener;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.annotations.LogMessageDoc;
 import net.floodlightcontroller.core.annotations.LogMessageDocs;
 import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState;
 import net.floodlightcontroller.core.util.ListenerDispatcher;
 import net.floodlightcontroller.core.web.CoreWebRoutable;
 import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.flowcache.IFlowService;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.perfmon.IPktInProcessingTimeService;
 import net.floodlightcontroller.restserver.IRestApiService;
@@ -77,6 +73,8 @@
 import net.floodlightcontroller.storage.OperatorPredicate;
 import net.floodlightcontroller.storage.StorageException;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.registry.controller.RegistryException;
@@ -140,15 +138,20 @@
 import org.slf4j.LoggerFactory;
 
 
-
 /**
  * The main controller class.  Handles all setup and network listeners
+ * 
+ * Extensions made by ONOS are:
+ * - Detailed Port event: PORTCHANGED -> {PORTCHANGED, PORTADDED, PORTREMOVED} 
+ *    Available as net.onrc.onos.ofcontroller.core.IOFSwitchPortListener
+ * - Distributed ownership control of switch through RegistryService(IControllerRegistryService)
+ * - Register ONOS services. (IFlowService, IControllerRegistryService)
+ * - Additional DEBUG logs
+ * - Try using hostname as controller ID, when ID was not explicitly given.
  */
 public class Controller implements IFloodlightProviderService, 
             IStorageSourceListener {
-   	
-	protected SwitchStorageImpl swStore;;
-	
+    
     protected static Logger log = LoggerFactory.getLogger(Controller.class);
 
     private static final String ERROR_DATABASE = 
@@ -185,7 +188,6 @@
     protected IPktInProcessingTimeService pktinProcTime;
     protected IThreadPoolService threadPool;
     protected IFlowService flowService;
-    protected ITopoRouteService topoRouteService;
     protected IControllerRegistryService registryService;
     
     // Configuration options
@@ -265,18 +267,27 @@
     public enum SwitchUpdateType {
         ADDED,
         REMOVED,
-        PORTCHANGED
+        PORTCHANGED,
+        PORTADDED,
+        PORTREMOVED
     }
     /**
      * Update message indicating a switch was added or removed 
+     * ONOS: This message extended to indicate Port add or removed event.
      */
     protected class SwitchUpdate implements IUpdate {
         public IOFSwitch sw;
+        public OFPhysicalPort port; // Added by ONOS
         public SwitchUpdateType switchUpdateType;
         public SwitchUpdate(IOFSwitch sw, SwitchUpdateType switchUpdateType) {
             this.sw = sw;
             this.switchUpdateType = switchUpdateType;
         }
+        public SwitchUpdate(IOFSwitch sw, OFPhysicalPort port, SwitchUpdateType switchUpdateType) {
+            this.sw = sw;
+            this.port = port;
+            this.switchUpdateType = switchUpdateType;
+        }
         public void dispatch() {
             if (log.isTraceEnabled()) {
                 log.trace("Dispatching switch update {} {}",
@@ -294,6 +305,18 @@
                         case PORTCHANGED:
                             listener.switchPortChanged(sw.getId());
                             break;
+                        case PORTADDED:
+                        	if (listener instanceof IOFSwitchPortListener) {
+                        		((IOFSwitchPortListener) listener).switchPortAdded(sw.getId(), port);
+                        	}
+                        	break;
+                        case PORTREMOVED:
+                        	if (listener instanceof IOFSwitchPortListener) {
+                        		((IOFSwitchPortListener) listener).switchPortRemoved(sw.getId(), port);
+                        	}
+                        	break;
+                        default:
+                        	break;
                     }
                 }
             }
@@ -393,10 +416,6 @@
 	this.flowService = serviceImpl;		
     }
 
-    public void setTopoRouteService(ITopoRouteService serviceImpl) {
-	this.topoRouteService = serviceImpl;		
-    }
-
 	public void setMastershipService(IControllerRegistryService serviceImpl) {
 		this.registryService = serviceImpl;		
 	}
@@ -789,10 +808,9 @@
                     dfuture);
 
         }
- 
+        
       	volatile Boolean controlRequested = Boolean.FALSE;
         protected void checkSwitchReady() {
-  
             if (state.hsState == HandshakeState.FEATURES_REPLY &&
                     state.hasDescription && state.hasGetConfigReply) {
                 
@@ -1128,7 +1146,7 @@
                             }
                             state.firstRoleReplyReceived = true;
                             Role requestedRole = 
-                            		sw.deliverRoleRequestNotSupported(error.getXid());
+                            		sw.deliverRoleRequestNotSupportedEx(error.getXid());
                             synchronized(roleChanger) {
                                 if (sw.role == null && Controller.this.role==Role.SLAVE) {
                                 	//This will now never happen. The Controller's role
@@ -1269,23 +1287,43 @@
             		((OFPortState.OFPPS_LINK_DOWN.getValue() & port.getState()) > 0);
             sw.setPort(port);
            if (!portDown) {
-               swStore.addPort(sw.getStringId(), port);
+               SwitchUpdate update = new SwitchUpdate(sw, port, SwitchUpdateType.PORTADDED);
+               try {
+                   this.updates.put(update);
+               } catch (InterruptedException e) {
+                   log.error("Failure adding update to queue", e);
+               }
            } else {
-        	   swStore.deletePort(sw.getStringId(), port.getPortNumber());
+               SwitchUpdate update = new SwitchUpdate(sw, port, SwitchUpdateType.PORTREMOVED);
+               try {
+                   this.updates.put(update);
+               } catch (InterruptedException e) {
+                   log.error("Failure adding update to queue", e);
+               }
            }
             if (updateStorage)
                 updatePortInfo(sw, port);
             log.debug("Port #{} modified for {}", portNumber, sw);
         } else if (m.getReason() == (byte)OFPortReason.OFPPR_ADD.ordinal()) {
             sw.setPort(port);
-            swStore.addPort(sw.getStringId(), port);
+            SwitchUpdate update = new SwitchUpdate(sw, port, SwitchUpdateType.PORTADDED);
+            try {
+                this.updates.put(update);
+            } catch (InterruptedException e) {
+                log.error("Failure adding update to queue", e);
+            }
             if (updateStorage)
                 updatePortInfo(sw, port);
             log.debug("Port #{} added for {}", portNumber, sw);
         } else if (m.getReason() == 
                    (byte)OFPortReason.OFPPR_DELETE.ordinal()) {
             sw.deletePort(portNumber);
-            swStore.deletePort(sw.getStringId(), portNumber);
+            SwitchUpdate update = new SwitchUpdate(sw, port, SwitchUpdateType.PORTREMOVED);
+            try {
+                this.updates.put(update);
+            } catch (InterruptedException e) {
+                log.error("Failure adding update to queue", e);
+            }
             if (updateStorage)
                 removePortInfo(sw, portNumber);
             log.debug("Port #{} deleted for {}", portNumber, sw);
@@ -1559,12 +1597,6 @@
         }
         
         updateActiveSwitchInfo(sw);
-        if (registryService.hasControl(sw.getId())) {
-        	swStore.update(sw.getStringId(), SwitchState.ACTIVE, DM_OPERATION.UPDATE);
-        	for (OFPhysicalPort port: sw.getPorts()) {
-        		swStore.addPort(sw.getStringId(), port);
-        	}
-        }
         SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.ADDED);
         try {
             this.updates.put(update);
@@ -1584,14 +1616,6 @@
         // this method is only called after netty has processed all
         // pending messages
         log.debug("removeSwitch: {}", sw);
- //
- //     Cannot set sw to inactive in network map due to race condition
- //     Need a cleanup thread to periodically check switches not active in registry
- //     and acquire control to set to inactive state in network map and release it       
- //
- //       if (registryService.hasControl(sw.getId())) {
- //      	swStore.update(sw.getStringId(), SwitchState.INACTIVE, DM_OPERATION.UPDATE);
- //       }
         if (!this.activeSwitches.remove(sw.getId(), sw) || !sw.isConnected()) {
             log.debug("Not removing switch {}; already removed", sw);
             return;
@@ -1601,7 +1625,6 @@
         // from slave controllers. Then we need to move this cancelation
         // to switch disconnect
         sw.cancelAllStatisticsReplies();
-        
             
         // FIXME: I think there's a race condition if we call updateInactiveSwitchInfo
         // here if role support is enabled. In that case if the switch is being
@@ -1613,7 +1636,6 @@
         // of the switch state that's written to storage.
         
         updateInactiveSwitchInfo(sw);
-        
         SwitchUpdate update = new SwitchUpdate(sw, SwitchUpdateType.REMOVED);
         try {
             this.updates.put(update);
@@ -2207,22 +2229,11 @@
         this.updates = new LinkedBlockingQueue<IUpdate>();
         this.factory = new BasicFactory();
         this.providerMap = new HashMap<String, List<IInfoProvider>>();
-        
         setConfigParams(configParams);
         //this.role = getInitialRole(configParams);
         //Set the controller's role to MASTER so it always tries to do role requests.
         this.role = Role.MASTER;
         this.roleChanger = new RoleChanger();
-        
-		String conf = configParams.get("dbconf");
-		if (conf == null || conf.isEmpty()) {
-			conf = "/tmp/cassandra.titan";
-			log.debug("did not get DB config setting using default {}", conf);
-		}
-		log.debug("setting DB config {}", conf);
-		this.swStore = new SwitchStorageImpl();
-		this.swStore.init(conf);
-		
         initVendorMessages();
         this.systemStartTime = System.currentTimeMillis();
     }
diff --git a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
index e0ff8c3..467c74a 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/OFSwitchImpl.java
@@ -44,6 +44,7 @@
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.util.TimedCache;
+import net.onrc.onos.ofcontroller.core.IOnosRemoteSwitch;
 
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
@@ -75,7 +76,7 @@
 /**
  * This is the internal representation of an openflow switch.
  */
-public class OFSwitchImpl implements IOFSwitch {
+public class OFSwitchImpl implements IOFSwitch, IOnosRemoteSwitch {
     // TODO: should we really do logging in the class or should we throw
     // exception that can then be handled by callers?
     protected static Logger log = LoggerFactory.getLogger(OFSwitchImpl.class);
@@ -268,7 +269,7 @@
     public void disconnectOutputStream() {
         channel.close();
     }
-    
+
     @Override
     @JsonIgnore
     public void setFeaturesReply(OFFeaturesReply featuresReply) {
@@ -401,7 +402,7 @@
      */
     @Override
     public String toString() {
-        return "OFSwitchImpl [" + channel.getRemoteAddress() + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
+        return "OFSwitchImpl [" + ((channel != null) ? channel.getRemoteAddress() : "?") + " DPID[" + ((stringId != null) ? stringId : "?") + "]]";
     }
 
     @Override
@@ -787,7 +788,18 @@
      * Otherwise we ignore it.
      * @param xid
      */
-    protected Role deliverRoleRequestNotSupported(int xid) {
+    protected void deliverRoleRequestNotSupported(int xid) {
+        deliverRoleRequestNotSupportedEx(xid);
+    }
+
+    /**
+     * ONOS Extension to deliverRoleRequestNotSupported().
+     * This version return the Roll request made.
+     * @see deliverRoleRequestNotSupported
+     * @param xid
+     * @return Role of attempted RoleRequest.
+     */
+    protected Role deliverRoleRequestNotSupportedEx(int xid) {
         synchronized(pendingRoleRequests) {
             PendingRoleRequestEntry head = pendingRoleRequests.poll();
             this.role = null;
diff --git a/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java b/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java
index b2de649..4924fbc 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/RoleChanger.java
@@ -277,8 +277,9 @@
                     // Handle cases #1 and #2
                 	log.debug("Sending NxRoleRequest to {}", sw);
                     sw.sendNxRoleRequest(role, cookie);
-                } else {         
+                } else {
                 	if (role == Role.MASTER) {
+                		// ONOS extension:
                 		log.debug("Switch {} doesn't support NxRoleRequests, but sending " + 
                 					"{} request anyway", sw, role);
                 		//Send the role request anyway, even though we know the switch
diff --git a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java b/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
deleted file mode 100644
index b8197b7..0000000
--- a/src/main/java/net/floodlightcontroller/core/internal/SwitchStorageImpl.java
+++ /dev/null
@@ -1,228 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import java.util.Collection;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.ISwitchStorage;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.GenerateEvent;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
-
-import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
-import org.openflow.protocol.OFPhysicalPort.OFPortState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SwitchStorageImpl implements ISwitchStorage {
-	protected GraphDBConnection conn;
-	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
-
-	@Override
-	public void update(String dpid, SwitchState state, DM_OPERATION op) {
-		// TODO Auto-generated method stub
-		log.info("SwitchStorage:update dpid:{} state: {} ", dpid, state);
-        switch(op) {
-
-        	case UPDATE:
-        	case INSERT:
-        	case CREATE:
-                addSwitch(dpid);
-                if (state != SwitchState.ACTIVE) {
-                	setStatus(dpid, state);
-                }
-                break;
-        	case DELETE:
-                deleteSwitch(dpid);
-                break;
-        	default:
-        }
-	}
-
-	private void setStatus(String dpid, SwitchState state) {
-		ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
-		if (sw != null) {
-			sw.setState(state.toString());
-			conn.endTx(Transaction.COMMIT);
-			log.info("SwitchStorage:setStatus dpid:{} state: {} done", dpid, state);
-		} 	else {
-			conn.endTx(Transaction.ROLLBACK);
-			log.info("SwitchStorage:setStatus dpid:{} state: {} failed: switch not found", dpid, state);
-		}
-	}
-
-	@Override
-	public void addPort(String dpid, OFPhysicalPort port) {
-		// TODO Auto-generated method stub
-		
-        boolean portDown = ((OFPortConfig.OFPPC_PORT_DOWN.getValue() & port.getConfig()) > 0) ||
-        		((OFPortState.OFPPS_LINK_DOWN.getValue() & port.getState()) > 0);
-       if (portDown) {
-             deletePort(dpid, port.getPortNumber());
-             return;
-       }
-             
-		try {
-			ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
-
-            if (sw != null) {
-            	IPortObject p = conn.utils().searchPort(conn, dpid, port.getPortNumber());
-            	log.info("SwitchStorage:addPort dpid:{} port:{}", dpid, port.getPortNumber());
-            	if (p != null) {
-            		log.error("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
-            	} else {
-            		p = conn.utils().newPort(conn);
-
-            		p.setType("port");
-            		p.setNumber(port.getPortNumber());
-            		p.setState("ACTIVE");
-            		p.setPortState(port.getState());
-            		p.setDesc(port.getName());
-            		sw.addPort(p);
-            		conn.endTx(Transaction.COMMIT);
-  
-            	}
-            } else {
-        		log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, port.getPortNumber());
-            }
-		} catch (Exception e) {
-             // TODO: handle exceptions
-			e.printStackTrace();
-			conn.endTx(Transaction.ROLLBACK);
-			log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, port.getPortNumber());
-		}	
-
-	}
-
-	@Override
-	public Collection<OFPhysicalPort> getPorts(long dpid) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public OFPhysicalPort getPort(String dpid, short portnum) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public OFPhysicalPort getPort(String dpid, String portName) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void addSwitch(String dpid) {
-		
-		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
-		
-		try {
-			ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
-			if (sw != null) {
-				/*
-				 *  Do nothing or throw exception?
-				 */
-
-				log.info("SwitchStorage:addSwitch dpid:{} already exists", dpid);
-				sw.setState(SwitchState.ACTIVE.toString());
-				conn.endTx(Transaction.COMMIT);
-			} else {
-				sw = conn.utils().newSwitch(conn);
-
-				if (sw != null) {
-					sw.setType("switch");
-					sw.setDPID(dpid);
-					sw.setState(SwitchState.ACTIVE.toString());
-					conn.endTx(Transaction.COMMIT);
-					log.info("SwitchStorage:addSwitch dpid:{} added", dpid);
-				} else {
-					log.error("switchStorage:addSwitch dpid:{} failed -> newSwitch failed", dpid);
-				}
-			}
-		} catch (Exception e) {
-			/*
-			 * retry?
-			 */
-			e.printStackTrace();
-			conn.endTx(Transaction.ROLLBACK);
-			log.info("SwitchStorage:addSwitch dpid:{} failed", dpid);
-		}
-
-
-	}
-
-	@Override
-	public void deleteSwitch(String dpid) {
-		// TODO Setting inactive but we need to eventually remove data
-
-		try {
-
-			ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
-            if (sw  != null) {
-            	conn.utils().removeSwitch(conn, sw);
- 
-            	conn.endTx(Transaction.COMMIT);
-            	log.info("SwitchStorage:DeleteSwitch dpid:{} done", dpid);
-            }
-		} catch (Exception e) {
-             // TODO: handle exceptions
-			e.printStackTrace();
-			conn.endTx(Transaction.ROLLBACK);			
-			log.error("SwitchStorage:deleteSwitch {} failed", dpid);
-		}
-
-	}
-
-	@Override
-	public void deletePort(String dpid, short port) {
-		// TODO Auto-generated method stub
-		try {
-			ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
-
-            if (sw != null) {
-            	IPortObject p = conn.utils().searchPort(conn, dpid, port);
-                if (p != null) {
-            		log.info("SwitchStorage:deletePort dpid:{} port:{} found and deleted", dpid, port);
-            		sw.removePort(p);
-            		conn.utils().removePort(conn, p);
-            		conn.endTx(Transaction.COMMIT);
-            	}
-            }
-		} catch (Exception e) {
-             // TODO: handle exceptions
-			e.printStackTrace();
-			conn.endTx(Transaction.ROLLBACK);
-			log.info("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
-		}	
-	}
-
-	@Override
-	public void deletePort(String dpid, String portName) {
-		// TODO Auto-generated method stub
-
-	}
-
-
-
-	@Override
-	public void init(String conf) {
-
-		conn = GraphDBConnection.getInstance(conf);
-        
-	}
-
-
-
-	public void finalize() {
-		close();
-	}
-	
-	@Override
-	public void close() {
-		conn.close();		
-	}
-
-	
-}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
deleted file mode 100644
index 502fad6..0000000
--- a/src/main/java/net/floodlightcontroller/core/internal/TopoSwitchServiceImpl.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoSwitchService;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TopoSwitchServiceImpl implements ITopoSwitchService {
-	
-	private GraphDBConnection conn;
-	protected static Logger log = LoggerFactory.getLogger(TopoSwitchServiceImpl.class);
-
-
-	public void finalize() {
-		close();
-	}
-	
-	@Override
-	public void close() {
-
-		conn.close();
-	}
-	
-	@Override
-	public Iterable<ISwitchObject> getActiveSwitches() {
-		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
-		conn.close(); //Commit to ensure we see latest data
-		return conn.utils().getActiveSwitches(conn);
-	}
-
-	@Override
-	public Iterable<ISwitchObject> getAllSwitches() {
-		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
-		conn.close(); //Commit to ensure we see latest data
-		return conn.utils().getAllSwitches(conn);
-	}
-
-	@Override
-	public Iterable<ISwitchObject> getInactiveSwitches() {
-		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("/tmp/cassandra.titan");
-		conn.close(); //Commit to ensure we see latest data
-		return conn.utils().getInactiveSwitches(conn);
-	}
-
-	@Override
-	public Iterable<IPortObject> getPortsOnSwitch(String dpid) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public IPortObject getPortOnSwitch(String dpid, short port_num) {
-		// TODO Auto-generated method stub
-		return null;
-	}	
-}
diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
index 2bb39ef..7604d7c 100644
--- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
@@ -18,9 +18,11 @@
 package net.floodlightcontroller.core.web;
 
 import net.floodlightcontroller.core.module.ModuleLoaderResource;
-import net.floodlightcontroller.linkdiscovery.web.TopoLinksResource;
-import net.floodlightcontroller.devicemanager.web.TopoDevicesResource;
 import net.floodlightcontroller.restserver.RestletRoutable;
+import net.onrc.onos.ofcontroller.core.web.ClearFlowTableResource;
+import net.onrc.onos.ofcontroller.core.web.TopoLinksResource;
+import net.onrc.onos.ofcontroller.core.web.TopoSwitchesResource;
+import net.onrc.onos.ofcontroller.devicemanager.web.TopoDevicesResource;
 
 import org.restlet.Context;
 import org.restlet.Restlet;
@@ -49,7 +51,6 @@
         router.attach("/counter/{switchId}/{counterName}/json", SwitchCounterResource.class);
         router.attach("/counter/categories/{switchId}/{counterName}/{layer}/json", SwitchCounterCategoriesResource.class);
         router.attach("/memory/json", ControllerMemoryResource.class);
-        router.attach("/packettrace/json", PacketTraceResource.class);
         // Get the last {count} events from the event histories
         router.attach("/event-history/topology-switch/{count}/json",
                 EventHistoryTopologySwitchResource.class);
@@ -62,6 +63,7 @@
         router.attach("/role/json", ControllerRoleResource.class);
         router.attach("/health/json", HealthCheckResource.class);
         router.attach("/system/uptime/json", SystemUptimeResource.class);
+        // Following added by ONOS
         router.attach("/topology/switches/{filter}/json", TopoSwitchesResource.class);
         router.attach("/topology/links/json", TopoLinksResource.class);
         router.attach("/topology/devices/json", TopoDevicesResource.class);
diff --git a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyClusterResource.java b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyClusterResource.java
index 1be942c..648866f 100644
--- a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyClusterResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyClusterResource.java
@@ -1,9 +1,9 @@
 package net.floodlightcontroller.core.web;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.internal.EventHistoryTopologyCluster;
-import net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 import net.floodlightcontroller.util.EventHistory;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.EventHistoryTopologyCluster;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyLinkResource.java b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyLinkResource.java
index 4a21070..79c4006 100644
--- a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyLinkResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologyLinkResource.java
@@ -1,9 +1,9 @@
 package net.floodlightcontroller.core.web;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.internal.EventHistoryTopologyLink;
-import net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 import net.floodlightcontroller.util.EventHistory;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.EventHistoryTopologyLink;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologySwitchResource.java b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologySwitchResource.java
index 1c95e2c..4a81db4 100644
--- a/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologySwitchResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/EventHistoryTopologySwitchResource.java
@@ -1,9 +1,9 @@
 package net.floodlightcontroller.core.web;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.internal.EventHistoryTopologySwitch;
-import net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 import net.floodlightcontroller.util.EventHistory;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.EventHistoryTopologySwitch;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java b/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java
deleted file mode 100644
index 85da942..0000000
--- a/src/main/java/net/floodlightcontroller/core/web/PacketTraceResource.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package net.floodlightcontroller.core.web;
-
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.restlet.data.Status;
-import org.restlet.resource.Post;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.floodlightcontroller.core.OFMessageFilterManager;
-
-public class PacketTraceResource extends ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(PacketTraceResource.class);
-    
-    public static class FilterParameters {
-
-        protected String sessionId = null;
-        protected String mac = null;
-        protected Integer period = null;
-        protected String direction = null;
-        protected String output = null;
-        
-        public String getSessionId() {
-            return sessionId;
-        }
-        public void setSessionId(String sessionId) {
-            this.sessionId = sessionId;
-        }
-        public String getMac() {
-            return mac;
-        }
-        public void setMac(String mac) {
-            this.mac = mac;
-        }
-        public Integer getPeriod() {
-            return period;
-        }
-        public void setPeriod(Integer period) {
-            this.period = period;
-        }
-        public String getDirection() {
-            return direction;
-        }
-        public void setDirection(String direction) {
-            this.direction = direction;
-        }
-        public String getOutput() {
-            return output;
-        }
-        public void setOutput(String output) {
-            this.output = output;
-        }
-
-        public String toString() {
-            return "SessionID: " + sessionId +
-                   "\tmac" + mac +
-                   "\tperiod" + period +
-                   "\tdirection" + direction +
-                   "\toutput" + output;
-        }
-    }
-    
-    public static class PacketTraceOutput {
-        protected String sessionId = null;
-
-        public String getSessionId() {
-            return sessionId;
-        }
-
-        public void setSessionId(String sessionId) {
-            this.sessionId = sessionId;
-        }
-    }
-    
-    @Post("json")
-    public PacketTraceOutput packettrace(FilterParameters fp) {
-        
-        ConcurrentHashMap <String,String> filter = new ConcurrentHashMap<String,String> ();
-        String sid = null;
-        PacketTraceOutput output = new PacketTraceOutput();
-        OFMessageFilterManager manager = 
-                (OFMessageFilterManager)getContext()
-                    .getAttributes().
-                        get(OFMessageFilterManager.class.getCanonicalName());
-
-        if (manager == null) {
-            sid = null;
-            setStatus(Status.SERVER_ERROR_SERVICE_UNAVAILABLE);
-        }
-        
-        if (fp.getSessionId() != null) {
-            filter.put("sessionId", fp.getSessionId());
-        }
-        if (fp.getMac() != null) {
-            filter.put("mac", fp.getMac());
-        }
-        if (fp.getDirection() != null) {
-            filter.put("direction", fp.getDirection());
-        }
-        
-        if (filter.isEmpty()) {
-            setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
-        } else {
-            if (log.isDebugEnabled()) {
-                log.debug ("Call setupFilter: sid:{} filter:{}, period:{}", 
-                           new Object[] {fp.getSessionId(), filter, 
-                                         fp.getPeriod()*1000});
-            }
-            sid = manager.setupFilter(fp.getSessionId(), filter, 
-                                      fp.getPeriod()*1000);
-            output.setSessionId(sid);
-            setStatus(Status.SUCCESS_OK);
-        }
-        
-        return output;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index feccdc4..04543ac 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -59,7 +59,6 @@
 import net.floodlightcontroller.flowcache.IFlowReconcileListener;
 import net.floodlightcontroller.flowcache.IFlowReconcileService;
 import net.floodlightcontroller.flowcache.OFMatchReconcile;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
 import net.floodlightcontroller.packet.ARP;
 import net.floodlightcontroller.packet.DHCP;
 import net.floodlightcontroller.packet.Ethernet;
@@ -71,6 +70,7 @@
 import net.floodlightcontroller.topology.ITopologyListener;
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.util.MultiIterator;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
 import static net.floodlightcontroller.devicemanager.internal.
 DeviceManagerImpl.DeviceUpdate.Change.*;
 
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceStorageImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceStorageImpl.java
deleted file mode 100644
index e964b8e..0000000
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceStorageImpl.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package net.floodlightcontroller.devicemanager.internal;
-
-import java.util.List;
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Lists;
-import com.thinkaurelius.titan.core.TitanException;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.internal.SwitchStorageImpl;
-import net.floodlightcontroller.devicemanager.IDevice;
-import net.floodlightcontroller.devicemanager.IDeviceStorage;
-import net.floodlightcontroller.devicemanager.SwitchPort;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
-
-public class DeviceStorageImpl implements IDeviceStorage {
-	
-	public GraphDBConnection conn;
-	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
-
-	@Override
-	public void init(String conf) {
-		conn = GraphDBConnection.getInstance(conf);
-	}	
-
-	public void finalize() {		
-		close();
-	}
-	
-	@Override
-	public void close() {
-		conn.close();
-	}
-
-	@Override
-	public IDeviceObject addDevice(IDevice device) {
-		// TODO Auto-generated method stub
-		IDeviceObject obj = null;
- 		try {
-            if ((obj = conn.utils().searchDevice(conn, device.getMACAddressString())) != null) {
-                log.debug("Adding device {}: found existing device",device.getMACAddressString());
-            } else {
-            	obj = conn.utils().newDevice(conn);
-                log.debug("Adding device {}: creating new device",device.getMACAddressString());
-            }
-            changeDeviceAttachments(device, obj);
-            
- 			obj.setIPAddress(device.getIPv4Addresses().toString());
- 			obj.setMACAddress(device.getMACAddressString());
- 			obj.setType("device");
- 			obj.setState("ACTIVE");
- 			conn.endTx(Transaction.COMMIT);
- 			
- 			log.debug("Adding device {}",device.getMACAddressString());
-		} catch (Exception e) {
-            // TODO: handle exceptions
-          	conn.endTx(Transaction.ROLLBACK);
-			log.error(":addDevice mac:{} failed", device.getMACAddressString());
-		}	
-		
-		return obj;
-	}
-
-	@Override
-	public IDeviceObject updateDevice(IDevice device) {
-		return addDevice(device);
-	}
-
-	@Override
-	public void removeDevice(IDevice device) {
-		// TODO Auto-generated method stub
-		IDeviceObject dev;
-		try {
-			if ((dev = conn.utils().searchDevice(conn, device.getMACAddressString())) != null) {
-             	conn.utils().removeDevice(conn, dev);
-              	conn.endTx(Transaction.COMMIT);
-            	log.error("DeviceStorage:removeDevice mac:{} done", device.getMACAddressString());
-            }
-		} catch (Exception e) {
-             // TODO: handle exceptions
-          	conn.endTx(Transaction.ROLLBACK);
-			log.error("DeviceStorage:removeDevice mac:{} failed", device.getMACAddressString());
-		}
-	}
-
-	@Override
-	public IDeviceObject getDeviceByMac(String mac) {
-		return conn.utils().searchDevice(conn, mac);
-	}
-
-	@Override
-	public IDeviceObject getDeviceByIP(String ip) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	@Override
-	public void changeDeviceAttachments(IDevice device) {
-		// TODO Auto-generated method stub
-		IDeviceObject obj = null;
- 		try {
-            if ((obj = conn.utils().searchDevice(conn, device.getMACAddressString())) != null) {
-                log.debug("Changing device ports {}: found existing device",device.getMACAddressString());
-                changeDeviceAttachments(device, obj);
-     			conn.endTx(Transaction.COMMIT);
-           } else {
-   				log.debug("failed to search device...now adding {}",device.getMACAddressString());
-   				addDevice(device);
-           }            			
-		} catch (Exception e) {
-            // TODO: handle exceptions
-          	conn.endTx(Transaction.ROLLBACK);
-			log.error(":addDevice mac:{} failed", device.getMACAddressString());
-		}	
-	}
-	
-	public void changeDeviceAttachments(IDevice device, IDeviceObject obj) {
-		SwitchPort[] attachmentPoints = device.getAttachmentPoints();
-		List<IPortObject> attachedPorts = Lists.newArrayList(obj.getAttachedPorts());
-
-        for (SwitchPort ap : attachmentPoints) {
-       	 IPortObject port = conn.utils().searchPort(conn,
-       			 									HexString.toHexString(ap.getSwitchDPID()),
-       												(short) ap.getPort());
-       	if (attachedPorts.contains(port)) {
-       		attachedPorts.remove(port);
-       	} else {
-               log.debug("Adding device {}: attaching to port",device.getMACAddressString());
-               port.setDevice(obj);
-       		//obj.setHostPort(port);
-       	}            		
-       }
-       for (IPortObject port: attachedPorts) {
-       		port.removeDevice(obj);
-       	//	obj.removeHostPort(port);
-       }	
-	}
-
-	@Override
-	public void changeDeviceIPv4Address(IDevice device) {
-		// TODO Auto-generated method stub
-		IDeviceObject obj;
-  		try {
-  			if ((obj = conn.utils().searchDevice(conn, device.getMACAddressString())) != null) {
-            	obj.setIPAddress(device.getIPv4Addresses().toString());
-              	conn.endTx(Transaction.COMMIT); 
-  			} else {
-            	log.error(":changeDeviceIPv4Address mac:{} failed", device.getMACAddressString());
-             }		
-  		} catch (TitanException e) {
-            // TODO: handle exceptions
-          	conn.endTx(Transaction.ROLLBACK);
-			log.error(":changeDeviceIPv4Address mac:{} failed due to exception {}", device.getMACAddressString(),e);
-		}
-	}
-
-}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/TopoDevicesResource.java b/src/main/java/net/floodlightcontroller/devicemanager/web/TopoDevicesResource.java
deleted file mode 100644
index db7059f..0000000
--- a/src/main/java/net/floodlightcontroller/devicemanager/web/TopoDevicesResource.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package net.floodlightcontroller.devicemanager.web;
-
-import java.util.Iterator;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
-import net.onrc.onos.util.GraphDBConnection;
-
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-
-public class TopoDevicesResource extends ServerResource {
-	
-	@Get("json")
-	public Iterator<IDeviceObject> retrieve() {
-		
-		GraphDBConnection conn = GraphDBConnection.getInstance("");
-		
-		return conn.utils().getDevices(conn).iterator();
-		
-	}
-	
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/Firewall.java b/src/main/java/net/floodlightcontroller/firewall/Firewall.java
deleted file mode 100644
index 3f8ff6c..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/Firewall.java
+++ /dev/null
@@ -1,667 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFType;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.devicemanager.IDeviceService;
-
-import java.util.ArrayList;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.routing.IRoutingDecision;
-import net.floodlightcontroller.routing.RoutingDecision;
-import net.floodlightcontroller.storage.IResultSet;
-import net.floodlightcontroller.storage.IStorageSourceService;
-import net.floodlightcontroller.storage.StorageException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Stateless firewall implemented as a Google Summer of Code project.
- * Configuration done through REST API
- * 
- * @author Amer Tahir
- * @edited KC Wang
- */
-public class Firewall implements IFirewallService, IOFMessageListener,
-        IFloodlightModule {
-
-    // service modules needed
-    protected IFloodlightProviderService floodlightProvider;
-    protected IStorageSourceService storageSource;
-    protected IRestApiService restApi;
-    protected static Logger logger;
-
-    protected List<FirewallRule> rules; // protected by synchronized
-    protected boolean enabled;
-    protected int subnet_mask = IPv4.toIPv4Address("255.255.255.0");
-
-    // constant strings for storage/parsing
-    public static final String TABLE_NAME = "controller_firewallrules";
-    public static final String COLUMN_RULEID = "ruleid";
-    public static final String COLUMN_DPID = "dpid";
-    public static final String COLUMN_IN_PORT = "in_port";
-    public static final String COLUMN_DL_SRC = "dl_src";
-    public static final String COLUMN_DL_DST = "dl_dst";
-    public static final String COLUMN_DL_TYPE = "dl_type";
-    public static final String COLUMN_NW_SRC_PREFIX = "nw_src_prefix";
-    public static final String COLUMN_NW_SRC_MASKBITS = "nw_src_maskbits";
-    public static final String COLUMN_NW_DST_PREFIX = "nw_dst_prefix";
-    public static final String COLUMN_NW_DST_MASKBITS = "nw_dst_maskbits";
-    public static final String COLUMN_NW_PROTO = "nw_proto";
-    public static final String COLUMN_TP_SRC = "tp_src";
-    public static final String COLUMN_TP_DST = "tp_dst";
-    public static final String COLUMN_WILDCARD_DPID = "wildcard_dpid";
-    public static final String COLUMN_WILDCARD_IN_PORT = "wildcard_in_port";
-    public static final String COLUMN_WILDCARD_DL_SRC = "wildcard_dl_src";
-    public static final String COLUMN_WILDCARD_DL_DST = "wildcard_dl_dst";
-    public static final String COLUMN_WILDCARD_DL_TYPE = "wildcard_dl_type";
-    public static final String COLUMN_WILDCARD_NW_SRC = "wildcard_nw_src";
-    public static final String COLUMN_WILDCARD_NW_DST = "wildcard_nw_dst";
-    public static final String COLUMN_WILDCARD_NW_PROTO = "wildcard_nw_proto";
-    public static final String COLUMN_WILDCARD_TP_SRC = "wildcard_tp_src";
-    public static final String COLUMN_WILDCARD_TP_DST = "wildcard_tp_dst";
-    public static final String COLUMN_PRIORITY = "priority";
-    public static final String COLUMN_ACTION = "action";
-    public static String ColumnNames[] = { COLUMN_RULEID, COLUMN_DPID,
-            COLUMN_IN_PORT, COLUMN_DL_SRC, COLUMN_DL_DST, COLUMN_DL_TYPE,
-            COLUMN_NW_SRC_PREFIX, COLUMN_NW_SRC_MASKBITS, COLUMN_NW_DST_PREFIX,
-            COLUMN_NW_DST_MASKBITS, COLUMN_NW_PROTO, COLUMN_TP_SRC,
-            COLUMN_TP_DST, COLUMN_WILDCARD_DPID, COLUMN_WILDCARD_IN_PORT,
-            COLUMN_WILDCARD_DL_SRC, COLUMN_WILDCARD_DL_DST,
-            COLUMN_WILDCARD_DL_TYPE, COLUMN_WILDCARD_NW_SRC,
-            COLUMN_WILDCARD_NW_DST, COLUMN_WILDCARD_NW_PROTO, COLUMN_PRIORITY,
-            COLUMN_ACTION };
-
-    @Override
-    public String getName() {
-        return "firewall";
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        // no prereq
-        return false;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFirewallService.class);
-        return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
-        Map<Class<? extends IFloodlightService>, IFloodlightService> m = new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
-        // We are the class that implements the service
-        m.put(IFirewallService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        l.add(IStorageSourceService.class);
-        l.add(IRestApiService.class);
-        return l;
-    }
-
-    /**
-     * Reads the rules from the storage and creates a sorted arraylist of
-     * FirewallRule from them.
-     * 
-     * Similar to getStorageRules(), which only reads contents for REST GET and
-     * does no parsing, checking, nor putting into FirewallRule objects
-     * 
-     * @return the sorted arraylist of FirewallRule instances (rules from
-     *         storage)
-     */
-    protected ArrayList<FirewallRule> readRulesFromStorage() {
-        ArrayList<FirewallRule> l = new ArrayList<FirewallRule>();
-
-        try {
-            Map<String, Object> row;
-
-            // (..., null, null) for no predicate, no ordering
-            IResultSet resultSet = storageSource.executeQuery(TABLE_NAME,
-                    ColumnNames, null, null);
-
-            // put retrieved rows into FirewallRules
-            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
-                row = it.next().getRow();
-                // now, parse row
-                FirewallRule r = new FirewallRule();
-                if (!row.containsKey(COLUMN_RULEID)
-                        || !row.containsKey(COLUMN_DPID)) {
-                    logger.error(
-                            "skipping entry with missing required 'ruleid' or 'switchid' entry: {}",
-                            row);
-                    return l;
-                }
-                try {
-                    r.ruleid = Integer
-                            .parseInt((String) row.get(COLUMN_RULEID));
-                    r.dpid = Long.parseLong((String) row.get(COLUMN_DPID));
-
-                    for (String key : row.keySet()) {
-                        if (row.get(key) == null)
-                            continue;
-                        if (key.equals(COLUMN_RULEID)
-                                || key.equals(COLUMN_DPID)
-                                || key.equals("id")) {
-                            continue; // already handled
-                        } 
-                        
-                        else if (key.equals(COLUMN_IN_PORT)) {
-                            r.in_port = Short.parseShort((String) row
-                                    .get(COLUMN_IN_PORT));
-                        } 
-                        
-                        else if (key.equals(COLUMN_DL_SRC)) {
-                            r.dl_src = Long.parseLong((String) row
-                                    .get(COLUMN_DL_SRC));
-                        } 
-                        
-                        else if (key.equals(COLUMN_DL_DST)) {
-                            r.dl_dst = Long.parseLong((String) row
-                                    .get(COLUMN_DL_DST));
-                        } 
-                        
-                        else if (key.equals(COLUMN_DL_TYPE)) {
-                            r.dl_type = Short.parseShort((String) row
-                                    .get(COLUMN_DL_TYPE));
-                        } 
-                        
-                        else if (key.equals(COLUMN_NW_SRC_PREFIX)) {
-                            r.nw_src_prefix = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_SRC_PREFIX));
-                        } 
-                        
-                        else if (key.equals(COLUMN_NW_SRC_MASKBITS)) {
-                            r.nw_src_maskbits = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_SRC_MASKBITS));
-                        } 
-                        
-                        else if (key.equals(COLUMN_NW_DST_PREFIX)) {
-                            r.nw_dst_prefix = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_DST_PREFIX));
-                        } 
-                        
-                        else if (key.equals(COLUMN_NW_DST_MASKBITS)) {
-                            r.nw_dst_maskbits = Integer.parseInt((String) row
-                                    .get(COLUMN_NW_DST_MASKBITS));
-                        } 
-                        
-                        else if (key.equals(COLUMN_NW_PROTO)) {
-                            r.nw_proto = Short.parseShort((String) row
-                                    .get(COLUMN_NW_PROTO));
-                        } 
-                        
-                        else if (key.equals(COLUMN_TP_SRC)) {
-                            r.tp_src = Short.parseShort((String) row
-                                    .get(COLUMN_TP_SRC));
-                        } 
-                        
-                        else if (key.equals(COLUMN_TP_DST)) {
-                            r.tp_dst = Short.parseShort((String) row
-                                    .get(COLUMN_TP_DST));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_DPID)) {
-                            r.wildcard_dpid = Boolean.parseBoolean((String) row
-                                    .get(COLUMN_WILDCARD_DPID));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_IN_PORT)) {
-                            r.wildcard_in_port = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_IN_PORT));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_DL_SRC)) {
-                            r.wildcard_dl_src = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_DL_SRC));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_DL_DST)) {
-                            r.wildcard_dl_dst = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_DL_DST));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_DL_TYPE)) {
-                            r.wildcard_dl_type = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_DL_TYPE));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_NW_SRC)) {
-                            r.wildcard_nw_src = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_NW_SRC));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_NW_DST)) {
-                            r.wildcard_nw_dst = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_NW_DST));
-                        } 
-                        
-                        else if (key.equals(COLUMN_WILDCARD_NW_PROTO)) {
-                            r.wildcard_nw_proto = Boolean
-                                    .parseBoolean((String) row
-                                            .get(COLUMN_WILDCARD_NW_PROTO));
-                        } 
-                        
-                        else if (key.equals(COLUMN_PRIORITY)) {
-                            r.priority = Integer.parseInt((String) row
-                                    .get(COLUMN_PRIORITY));
-                        } 
-                        
-                        else if (key.equals(COLUMN_ACTION)) {
-                            int tmp = Integer.parseInt((String) row.get(COLUMN_ACTION));
-                            if (tmp == FirewallRule.FirewallAction.DENY.ordinal())
-                                r.action = FirewallRule.FirewallAction.DENY;
-                            else if (tmp == FirewallRule.FirewallAction.ALLOW.ordinal())
-                                r.action = FirewallRule.FirewallAction.ALLOW;
-                            else {
-                                r.action = null;
-                                logger.error("action not recognized");
-                            }
-                        }
-                    }
-                } catch (ClassCastException e) {
-                    logger.error(
-                            "skipping rule {} with bad data : "
-                                    + e.getMessage(), r.ruleid);
-                }
-                if (r.action != null)
-                    l.add(r);
-            }
-        } catch (StorageException e) {
-            logger.error("failed to access storage: {}", e.getMessage());
-            // if the table doesn't exist, then wait to populate later via
-            // setStorageSource()
-        }
-
-        // now, sort the list based on priorities
-        Collections.sort(l);
-
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-        floodlightProvider = context
-                .getServiceImpl(IFloodlightProviderService.class);
-        storageSource = context.getServiceImpl(IStorageSourceService.class);
-        restApi = context.getServiceImpl(IRestApiService.class);
-        rules = new ArrayList<FirewallRule>();
-        logger = LoggerFactory.getLogger(Firewall.class);
-
-        // start disabled
-        enabled = false;
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        // register REST interface
-        restApi.addRestletRoutable(new FirewallWebRoutable());
-
-        // always place firewall in pipeline at bootup
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-
-        // storage, create table and read rules
-        storageSource.createTable(TABLE_NAME, null);
-        storageSource.setTablePrimaryKeyName(TABLE_NAME, COLUMN_RULEID);
-        synchronized (rules) {
-            this.rules = readRulesFromStorage();
-        }
-    }
-
-    @Override
-    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        if (!this.enabled)
-            return Command.CONTINUE;
-
-        switch (msg.getType()) {
-        case PACKET_IN:
-            IRoutingDecision decision = null;
-            if (cntx != null) {
-                decision = IRoutingDecision.rtStore.get(cntx,
-                        IRoutingDecision.CONTEXT_DECISION);
-
-                return this.processPacketInMessage(sw, (OFPacketIn) msg,
-                        decision, cntx);
-            }
-            break;
-        default:
-            break;
-        }
-
-        return Command.CONTINUE;
-    }
-
-    @Override
-    public void enableFirewall(boolean enabled) {
-        logger.info("Setting firewall to {}", enabled);
-        this.enabled = enabled;
-    }
-
-    @Override
-    public List<FirewallRule> getRules() {
-        return this.rules;
-    }
-
-    // Only used to serve REST GET
-    // Similar to readRulesFromStorage(), which actually checks and stores
-    // record into FirewallRule list
-    @Override
-    public List<Map<String, Object>> getStorageRules() {
-        ArrayList<Map<String, Object>> l = new ArrayList<Map<String, Object>>();
-        try {
-            // null1=no predicate, null2=no ordering
-            IResultSet resultSet = storageSource.executeQuery(TABLE_NAME,
-                    ColumnNames, null, null);
-            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
-                l.add(it.next().getRow());
-            }
-        } catch (StorageException e) {
-            logger.error("failed to access storage: {}", e.getMessage());
-            // if the table doesn't exist, then wait to populate later via
-            // setStorageSource()
-        }
-        return l;
-    }
-
-    @Override
-    public String getSubnetMask() {
-        return IPv4.fromIPv4Address(this.subnet_mask);
-    }
-
-    @Override
-    public void setSubnetMask(String newMask) {
-        if (newMask.trim().isEmpty())
-            return;
-        this.subnet_mask = IPv4.toIPv4Address(newMask.trim());
-    }
-
-    @Override
-    public synchronized void addRule(FirewallRule rule) {
-        
-        // generate random ruleid for each newly created rule
-        // may want to return to caller if useful
-        // may want to check conflict
-        rule.ruleid = rule.genID();
-        
-        int i = 0;
-        // locate the position of the new rule in the sorted arraylist
-        for (i = 0; i < this.rules.size(); i++) {
-            if (this.rules.get(i).priority >= rule.priority)
-                break;
-        }
-        // now, add rule to the list
-        if (i <= this.rules.size()) {
-            this.rules.add(i, rule);
-        } else {
-            this.rules.add(rule);
-        }
-        // add rule to database
-        Map<String, Object> entry = new HashMap<String, Object>();
-        entry.put(COLUMN_RULEID, Integer.toString(rule.ruleid));
-        entry.put(COLUMN_DPID, Long.toString(rule.dpid));
-        entry.put(COLUMN_IN_PORT, Short.toString(rule.in_port));
-        entry.put(COLUMN_DL_SRC, Long.toString(rule.dl_src));
-        entry.put(COLUMN_DL_DST, Long.toString(rule.dl_dst));
-        entry.put(COLUMN_DL_TYPE, Short.toString(rule.dl_type));
-        entry.put(COLUMN_NW_SRC_PREFIX, Integer.toString(rule.nw_src_prefix));
-        entry.put(COLUMN_NW_SRC_MASKBITS, Integer.toString(rule.nw_src_maskbits));
-        entry.put(COLUMN_NW_DST_PREFIX, Integer.toString(rule.nw_dst_prefix));
-        entry.put(COLUMN_NW_DST_MASKBITS, Integer.toString(rule.nw_dst_maskbits));
-        entry.put(COLUMN_NW_PROTO, Short.toString(rule.nw_proto));
-        entry.put(COLUMN_TP_SRC, Integer.toString(rule.tp_src));
-        entry.put(COLUMN_TP_DST, Integer.toString(rule.tp_dst));
-        entry.put(COLUMN_WILDCARD_DPID,
-                Boolean.toString(rule.wildcard_dpid));
-        entry.put(COLUMN_WILDCARD_IN_PORT,
-                Boolean.toString(rule.wildcard_in_port));
-        entry.put(COLUMN_WILDCARD_DL_SRC,
-                Boolean.toString(rule.wildcard_dl_src));
-        entry.put(COLUMN_WILDCARD_DL_DST,
-                Boolean.toString(rule.wildcard_dl_dst));
-        entry.put(COLUMN_WILDCARD_DL_TYPE,
-                Boolean.toString(rule.wildcard_dl_type));
-        entry.put(COLUMN_WILDCARD_NW_SRC,
-                Boolean.toString(rule.wildcard_nw_src));
-        entry.put(COLUMN_WILDCARD_NW_DST,
-                Boolean.toString(rule.wildcard_nw_dst));
-        entry.put(COLUMN_WILDCARD_NW_PROTO,
-                Boolean.toString(rule.wildcard_nw_proto));
-        entry.put(COLUMN_WILDCARD_TP_SRC,
-                Boolean.toString(rule.wildcard_tp_src));
-        entry.put(COLUMN_WILDCARD_TP_DST,
-                Boolean.toString(rule.wildcard_tp_dst));
-        entry.put(COLUMN_PRIORITY, Integer.toString(rule.priority));
-        entry.put(COLUMN_ACTION, Integer.toString(rule.action.ordinal()));
-        storageSource.insertRow(TABLE_NAME, entry);
-    }
-
-    @Override
-    public synchronized void deleteRule(int ruleid) {
-        Iterator<FirewallRule> iter = this.rules.iterator();
-        while (iter.hasNext()) {
-            FirewallRule r = iter.next();
-            if (r.ruleid == ruleid) {
-                // found the rule, now remove it
-                iter.remove();
-                break;
-            }
-        }
-        // delete from database
-        storageSource.deleteRow(TABLE_NAME, Integer.toString(ruleid));
-    }
-
-    /**
-     * Iterates over the firewall rules and tries to match them with the
-     * incoming packet (flow). Uses the FirewallRule class's matchWithFlow
-     * method to perform matching. It maintains a pair of wildcards (allow and
-     * deny) which are assigned later to the firewall's decision, where 'allow'
-     * wildcards are applied if the matched rule turns out to be an ALLOW rule
-     * and 'deny' wildcards are applied otherwise. Wildcards are applied to
-     * firewall decision to optimize flows in the switch, ensuring least number
-     * of flows per firewall rule. So, if a particular field is not "ANY" (i.e.
-     * not wildcarded) in a higher priority rule, then if a lower priority rule
-     * matches the packet and wildcards it, it can't be wildcarded in the
-     * switch's flow entry, because otherwise some packets matching the higher
-     * priority rule might escape the firewall. The reason for keeping different
-     * two different wildcards is that if a field is not wildcarded in a higher
-     * priority allow rule, the same field shouldn't be wildcarded for packets
-     * matching the lower priority deny rule (non-wildcarded fields in higher
-     * priority rules override the wildcarding of those fields in lower priority
-     * rules of the opposite type). So, to ensure that wildcards are
-     * appropriately set for different types of rules (allow vs. deny), separate
-     * wildcards are maintained. Iteration is performed on the sorted list of
-     * rules (sorted in decreasing order of priority).
-     * 
-     * @param sw
-     *            the switch instance
-     * @param pi
-     *            the incoming packet data structure
-     * @param cntx
-     *            the floodlight context
-     * @return an instance of RuleWildcardsPair that specify rule that matches
-     *         and the wildcards for the firewall decision
-     */
-    protected RuleWildcardsPair matchWithRule(IOFSwitch sw, OFPacketIn pi,
-            FloodlightContext cntx) {
-        FirewallRule matched_rule = null;
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
-                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-        WildcardsPair wildcards = new WildcardsPair();
-
-        synchronized (rules) {
-            Iterator<FirewallRule> iter = this.rules.iterator();
-            FirewallRule rule = null;
-            // iterate through list to find a matching firewall rule
-            while (iter.hasNext()) {
-                // get next rule from list
-                rule = iter.next();
-
-                // check if rule matches
-                if (rule.matchesFlow(sw.getId(), pi.getInPort(), eth, wildcards) == true) {
-                    matched_rule = rule;
-                    break;
-                }
-            }
-        }
-
-        // make a pair of rule and wildcards, then return it
-        RuleWildcardsPair ret = new RuleWildcardsPair();
-        ret.rule = matched_rule;
-        if (matched_rule == null || matched_rule.action == FirewallRule.FirewallAction.DENY) {
-            ret.wildcards = wildcards.drop;
-        } else {
-            ret.wildcards = wildcards.allow;
-        }
-        return ret;
-    }
-
-    /**
-     * Checks whether an IP address is a broadcast address or not (determines
-     * using subnet mask)
-     * 
-     * @param IPAddress
-     *            the IP address to check
-     * @return true if it is a broadcast address, false otherwise
-     */
-    protected boolean IPIsBroadcast(int IPAddress) {
-        // inverted subnet mask
-        int inv_subnet_mask = ~this.subnet_mask;
-        return ((IPAddress & inv_subnet_mask) == inv_subnet_mask);
-    }
-
-    public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi,
-            IRoutingDecision decision, FloodlightContext cntx) {
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx,
-                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-
-        // Allowing L2 broadcast + ARP broadcast request (also deny malformed
-        // broadcasts -> L2 broadcast + L3 unicast)
-        if (eth.isBroadcast() == true) {
-            boolean allowBroadcast = true;
-            // the case to determine if we have L2 broadcast + L3 unicast
-            // don't allow this broadcast packet if such is the case (malformed
-            // packet)
-            if (eth.getEtherType() == Ethernet.TYPE_IPv4
-                    && this.IPIsBroadcast(((IPv4) eth.getPayload())
-                            .getDestinationAddress()) == false) {
-                allowBroadcast = false;
-            }
-            if (allowBroadcast == true) {
-                if (logger.isTraceEnabled())
-                    logger.trace("Allowing broadcast traffic for PacketIn={}",
-                            pi);
-                                        
-                decision = new RoutingDecision(sw.getId(), pi.getInPort()
-                		, IDeviceService.fcStore.
-                        get(cntx, IDeviceService.CONTEXT_SRC_DEVICE),
-                        IRoutingDecision.RoutingAction.MULTICAST);
-                decision.addToContext(cntx);
-            } else {
-                if (logger.isTraceEnabled())
-                    logger.trace(
-                            "Blocking malformed broadcast traffic for PacketIn={}",
-                            pi);
-
-                decision = new RoutingDecision(sw.getId(), pi.getInPort()
-                		, IDeviceService.fcStore.
-                        get(cntx, IDeviceService.CONTEXT_SRC_DEVICE),
-                        IRoutingDecision.RoutingAction.DROP);
-                decision.addToContext(cntx);
-            }
-            return Command.CONTINUE;
-        }
-        /*
-         * ARP response (unicast) can be let through without filtering through
-         * rules by uncommenting the code below
-         */
-        /*
-         * else if (eth.getEtherType() == Ethernet.TYPE_ARP) {
-         * logger.info("allowing ARP traffic"); decision = new
-         * FirewallDecision(IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
-         * decision.addToContext(cntx); return Command.CONTINUE; }
-         */
-
-        // check if we have a matching rule for this packet/flow
-        // and no decision is taken yet
-        if (decision == null) {
-            RuleWildcardsPair match_ret = this.matchWithRule(sw, pi, cntx);
-            FirewallRule rule = match_ret.rule;
-
-            if (rule == null || rule.action == FirewallRule.FirewallAction.DENY) {
-                decision = new RoutingDecision(sw.getId(), pi.getInPort()
-                		, IDeviceService.fcStore.
-                        get(cntx, IDeviceService.CONTEXT_SRC_DEVICE),
-                        IRoutingDecision.RoutingAction.DROP);
-                decision.setWildcards(match_ret.wildcards);
-                decision.addToContext(cntx);
-                if (logger.isTraceEnabled()) {
-                    if (rule == null)
-                        logger.trace(
-                                "No firewall rule found for PacketIn={}, blocking flow",
-                                pi);
-                    else if (rule.action == FirewallRule.FirewallAction.DENY) {
-                        logger.trace("Deny rule={} match for PacketIn={}",
-                                rule, pi);
-                    }
-                }
-            } else {
-                decision = new RoutingDecision(sw.getId(), pi.getInPort()
-                		, IDeviceService.fcStore.
-                        get(cntx, IDeviceService.CONTEXT_SRC_DEVICE),
-                        IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
-                decision.setWildcards(match_ret.wildcards);
-                decision.addToContext(cntx);
-                if (logger.isTraceEnabled())
-                    logger.trace("Allow rule={} match for PacketIn={}", rule,
-                            pi);
-            }
-        }
-
-        return Command.CONTINUE;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java
deleted file mode 100644
index 1f4d71a..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallResource.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import java.io.IOException;
-
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.map.MappingJsonFactory;
-import org.restlet.resource.Post;
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FirewallResource extends ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(FirewallResource.class);
-    
-    @Get("json")
-    public Object handleRequest() {
-        IFirewallService firewall = 
-                (IFirewallService)getContext().getAttributes().
-                get(IFirewallService.class.getCanonicalName());
-
-        String op = (String) getRequestAttributes().get("op");
-
-        // REST API check status
-        if (op.equalsIgnoreCase("status")) {
-            if (firewall.isEnabled())
-                return "{\"result\" : \"firewall enabled\"}";
-            else
-                return "{\"result\" : \"firewall disabled\"}";
-        }
-
-        // REST API enable firewall
-        if (op.equalsIgnoreCase("enable")) {
-            firewall.enableFirewall(true);
-            return "{\"status\" : \"success\", \"details\" : \"firewall running\"}";
-        } 
-        
-        // REST API disable firewall
-        if (op.equalsIgnoreCase("disable")) {
-            firewall.enableFirewall(false);
-            return "{\"status\" : \"success\", \"details\" : \"firewall stopped\"}";
-        } 
-        
-        // REST API retrieving rules from storage
-        // currently equivalent to /wm/firewall/rules/json
-        if (op.equalsIgnoreCase("storageRules")) {
-            return firewall.getStorageRules();
-        } 
-        
-        // REST API set local subnet mask -- this only makes sense for one subnet
-        // will remove later
-        if (op.equalsIgnoreCase("subnet-mask")) {
-            return firewall.getSubnetMask();
-        }
-
-        // no known options found
-        return "{\"status\" : \"failure\", \"details\" : \"invalid operation\"}";
-    }
-    
-    /**
-     * Allows setting of subnet mask
-     * @param fmJson The Subnet Mask in JSON format.
-     * @return A string status message
-     */
-    @Post
-    public String handlePost(String fmJson) {
-        IFirewallService firewall = 
-                (IFirewallService)getContext().getAttributes().
-                get(IFirewallService.class.getCanonicalName());
-
-        String newMask;
-        try {
-            newMask = jsonExtractSubnetMask(fmJson);
-        } catch (IOException e) {
-            log.error("Error parsing new subnet mask: " + fmJson, e);
-            e.printStackTrace();
-            return "{\"status\" : \"Error! Could not parse new subnet mask, see log for details.\"}";
-        }
-        firewall.setSubnetMask(newMask);
-        return ("{\"status\" : \"subnet mask set\"}");
-    }
-    
-    /**
-     * Extracts subnet mask from a JSON string
-     * @param fmJson The JSON formatted string
-     * @return The subnet mask
-     * @throws IOException If there was an error parsing the JSON
-     */
-    public static String jsonExtractSubnetMask(String fmJson) throws IOException {
-        String subnet_mask = "";
-        MappingJsonFactory f = new MappingJsonFactory();
-        JsonParser jp;
-
-        try {
-            jp = f.createJsonParser(fmJson);
-        } catch (JsonParseException e) {
-            throw new IOException(e);
-        }
-
-        jp.nextToken();
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw new IOException("Expected START_OBJECT");
-        }
-
-        while (jp.nextToken() != JsonToken.END_OBJECT) {
-            if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
-                throw new IOException("Expected FIELD_NAME");
-            }
-
-            String n = jp.getCurrentName();
-            jp.nextToken();
-            if (jp.getText().equals("")) 
-                continue;
-
-            if (n == "subnet-mask") {
-                subnet_mask = jp.getText();
-                break;
-            }
-        }
-
-        return subnet_mask;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java
deleted file mode 100644
index d9b2612..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallRule.java
+++ /dev/null
@@ -1,392 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import org.openflow.protocol.OFMatch;
-
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.packet.TCP;
-import net.floodlightcontroller.packet.UDP;
-
-public class FirewallRule implements Comparable<FirewallRule> {
-    public int ruleid;
-
-    public long dpid; 
-    public short in_port; 
-    public long dl_src; 
-    public long dl_dst; 
-    public short dl_type; 
-    public int nw_src_prefix; 
-    public int nw_src_maskbits;
-    public int nw_dst_prefix;
-    public int nw_dst_maskbits;
-    public short nw_proto;
-    public short tp_src;
-    public short tp_dst;
-
-    public boolean wildcard_dpid;
-    public boolean wildcard_in_port; 
-    public boolean wildcard_dl_src;
-    public boolean wildcard_dl_dst;
-    public boolean wildcard_dl_type;
-    public boolean wildcard_nw_src;
-    public boolean wildcard_nw_dst;
-    public boolean wildcard_nw_proto;
-    public boolean wildcard_tp_src;
-    public boolean wildcard_tp_dst;
-
-    public int priority = 0;
-
-    public FirewallAction action;
-
-    public enum FirewallAction {
-        /*
-         * DENY: Deny rule
-         * ALLOW: Allow rule
-         */
-        DENY, ALLOW
-    }
-
-    public FirewallRule() {
-        this.in_port = 0; 
-        this.dl_src = 0;
-        this.nw_src_prefix = 0;
-        this.nw_src_maskbits = 0; 
-        this.dl_dst = 0;
-        this.nw_proto = 0;
-        this.tp_src = 0;
-        this.tp_dst = 0;
-        this.dl_dst = 0;
-        this.nw_dst_prefix = 0;
-        this.nw_dst_maskbits = 0; 
-        this.dpid = -1;
-        this.wildcard_dpid = true; 
-        this.wildcard_in_port = true; 
-        this.wildcard_dl_src = true; 
-        this.wildcard_dl_dst = true; 
-        this.wildcard_dl_type = true; 
-        this.wildcard_nw_src = true; 
-        this.wildcard_nw_dst = true; 
-        this.wildcard_nw_proto = true; 
-        this.wildcard_tp_src = true; 
-        this.wildcard_tp_dst = true; 
-        this.priority = 0; 
-        this.action = FirewallAction.ALLOW; 
-        this.ruleid = 0; 
-    }
-
-    /**
-     * Generates a unique ID for the instance
-     * 
-     * @return int representing the unique id
-     */
-    public int genID() {
-        int uid = this.hashCode();
-        if (uid < 0) {
-            uid = Math.abs(uid);
-            uid = uid * 15551;
-        }
-        return uid;
-    }
-
-    /**
-     * Comparison method for Collections.sort method
-     * 
-     * @param rule
-     *            the rule to compare with
-     * @return number representing the result of comparison 0 if equal negative
-     *         if less than 'rule' greater than zero if greater priority rule
-     *         than 'rule'
-     */
-    @Override
-    public int compareTo(FirewallRule rule) {
-        return this.priority - rule.priority;
-    }
-
-    /**
-     * Determines if this instance matches an existing rule instance
-     * 
-     * @param r
-     *            : the FirewallRule instance to compare with
-     * @return boolean: true if a match is found
-     **/
-    public boolean isSameAs(FirewallRule r) {
-        if (this.action != r.action
-                || this.wildcard_dl_type != r.wildcard_dl_type
-                || (this.wildcard_dl_type == false && this.dl_type == r.dl_type)
-                || this.wildcard_tp_src != r.wildcard_tp_src
-                || (this.wildcard_tp_src == false && this.tp_src != r.tp_src)
-                || this.wildcard_tp_dst != r.wildcard_tp_dst
-                || (this.wildcard_tp_dst == false &&this.tp_dst != r.tp_dst)
-                || this.wildcard_dpid != r.wildcard_dpid
-                || (this.wildcard_dpid == false && this.dpid != r.dpid)
-                || this.wildcard_in_port != r.wildcard_in_port
-                || (this.wildcard_in_port == false && this.in_port != r.in_port)
-                || this.wildcard_nw_src != r.wildcard_nw_src
-                || (this.wildcard_nw_src == false && (this.nw_src_prefix != r.nw_src_prefix || this.nw_src_maskbits != r.nw_src_maskbits))
-                || this.wildcard_dl_src != r.wildcard_dl_src
-                || (this.wildcard_dl_src == false && this.dl_src != r.dl_src)
-                || this.wildcard_nw_proto != r.wildcard_nw_proto
-                || (this.wildcard_nw_proto == false && this.nw_proto != r.nw_proto)
-                || this.wildcard_nw_dst != r.wildcard_nw_dst
-                || (this.wildcard_nw_dst == false && (this.nw_dst_prefix != r.nw_dst_prefix || this.nw_dst_maskbits != r.nw_dst_maskbits))
-                || this.wildcard_dl_dst != r.wildcard_dl_dst                
-                || (this.wildcard_dl_dst == false && this.dl_dst != r.dl_dst)) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Matches this rule to a given flow - incoming packet
-     * 
-     * @param switchDpid
-     *            the Id of the connected switch
-     * @param inPort
-     *            the switch port where the packet originated from
-     * @param packet
-     *            the Ethernet packet that arrives at the switch
-     * @param wildcards
-     *            the pair of wildcards (allow and deny) given by Firewall
-     *            module that is used by the Firewall module's matchWithRule
-     *            method to derive wildcards for the decision to be taken
-     * @return true if the rule matches the given packet-in, false otherwise
-     */
-    public boolean matchesFlow(long switchDpid, short inPort, Ethernet packet,
-            WildcardsPair wildcards) {
-        IPacket pkt = packet.getPayload();
-
-        // dl_type type
-        IPv4 pkt_ip = null;
-
-        // nw_proto types
-        TCP pkt_tcp = null;
-        UDP pkt_udp = null;
-
-        // tp_src and tp_dst (tp port numbers)
-        short pkt_tp_src = 0;
-        short pkt_tp_dst = 0;
-
-        // switchID matches?
-        if (wildcard_dpid == false && dpid != switchDpid)
-            return false;
-
-        // in_port matches?
-        if (wildcard_in_port == false && in_port != inPort)
-            return false;
-        if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_IN_PORT;
-        } else {
-            wildcards.allow &= ~OFMatch.OFPFW_IN_PORT;
-        }
-
-        // mac address (src and dst) match?
-        if (wildcard_dl_src == false
-                && dl_src != packet.getSourceMAC().toLong())
-            return false;
-        if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_SRC;
-        } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_SRC;
-        }
-
-        if (wildcard_dl_dst == false
-                && dl_dst != packet.getDestinationMAC().toLong())
-            return false;
-        if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_DST;
-        } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_DST;
-        }
-
-        // dl_type check: ARP, IP
-
-        // if this is not an ARP rule but the pkt is ARP,
-        // return false match - no need to continue protocol specific check
-        if (wildcard_dl_type == false) {
-            if (dl_type == Ethernet.TYPE_ARP) {
-                if (packet.getEtherType() != Ethernet.TYPE_ARP)
-                    return false;
-                else {
-                    if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
-                    } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
-                    }
-                }
-            } else if (dl_type == Ethernet.TYPE_IPv4) {
-                if (packet.getEtherType() != Ethernet.TYPE_IPv4)
-                    return false;
-                else {
-                    if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
-                    } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
-                    }
-                    // IP packets, proceed with ip address check
-                    pkt_ip = (IPv4) pkt;
-
-                    // IP addresses (src and dst) match?
-                    if (wildcard_nw_src == false
-                            && this.matchIPAddress(nw_src_prefix,
-                                    nw_src_maskbits, pkt_ip.getSourceAddress()) == false)
-                        return false;
-                    if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_SRC_ALL;
-                        wildcards.drop |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
-                    } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_SRC_ALL;
-                        wildcards.allow |= (nw_src_maskbits << OFMatch.OFPFW_NW_SRC_SHIFT);
-                    }
-
-                    if (wildcard_nw_dst == false
-                            && this.matchIPAddress(nw_dst_prefix,
-                                    nw_dst_maskbits,
-                                    pkt_ip.getDestinationAddress()) == false)
-                        return false;
-                    if (action == FirewallRule.FirewallAction.DENY) {
-                        wildcards.drop &= ~OFMatch.OFPFW_NW_DST_ALL;
-                        wildcards.drop |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
-                    } else {
-                        wildcards.allow &= ~OFMatch.OFPFW_NW_DST_ALL;
-                        wildcards.allow |= (nw_dst_maskbits << OFMatch.OFPFW_NW_DST_SHIFT);
-                    }
-
-                    // nw_proto check
-                    if (wildcard_nw_proto == false) {
-                        if (nw_proto == IPv4.PROTOCOL_TCP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_TCP)
-                                return false;
-                            else {
-                                pkt_tcp = (TCP) pkt_ip.getPayload();
-                                pkt_tp_src = pkt_tcp.getSourcePort();
-                                pkt_tp_dst = pkt_tcp.getDestinationPort();
-                            }
-                        } else if (nw_proto == IPv4.PROTOCOL_UDP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_UDP)
-                                return false;
-                            else {
-                                pkt_udp = (UDP) pkt_ip.getPayload();
-                                pkt_tp_src = pkt_udp.getSourcePort();
-                                pkt_tp_dst = pkt_udp.getDestinationPort();
-                            }
-                        } else if (nw_proto == IPv4.PROTOCOL_ICMP) {
-                            if (pkt_ip.getProtocol() != IPv4.PROTOCOL_ICMP)
-                                return false;
-                            else {
-                                // nothing more needed for ICMP
-                            }
-                        }
-                        if (action == FirewallRule.FirewallAction.DENY) {
-                            wildcards.drop &= ~OFMatch.OFPFW_NW_PROTO;
-                        } else {
-                            wildcards.allow &= ~OFMatch.OFPFW_NW_PROTO;
-                        }
-
-                        // TCP/UDP source and destination ports match?
-                        if (pkt_tcp != null || pkt_udp != null) {
-                            // does the source port match?
-                            if (tp_src != 0 && tp_src != pkt_tp_src)
-                                return false;
-                            if (action == FirewallRule.FirewallAction.DENY) {
-                                wildcards.drop &= ~OFMatch.OFPFW_TP_SRC;
-                            } else {
-                                wildcards.allow &= ~OFMatch.OFPFW_TP_SRC;
-                            }
-
-                            // does the destination port match?
-                            if (tp_dst != 0 && tp_dst != pkt_tp_dst)
-                                return false;
-                            if (action == FirewallRule.FirewallAction.DENY) {
-                                wildcards.drop &= ~OFMatch.OFPFW_TP_DST;
-                            } else {
-                                wildcards.allow &= ~OFMatch.OFPFW_TP_DST;
-                            }
-                        }
-                    }
-
-                }
-            } else {
-                // non-IP packet - not supported - report no match
-                return false;
-            }
-        }
-        if (action == FirewallRule.FirewallAction.DENY) {
-            wildcards.drop &= ~OFMatch.OFPFW_DL_TYPE;
-        } else {
-            wildcards.allow &= ~OFMatch.OFPFW_DL_TYPE;
-        }
-
-        // all applicable checks passed
-        return true;
-    }
-
-    /**
-     * Determines if rule's CIDR address matches IP address of the packet
-     * 
-     * @param rulePrefix
-     *            prefix part of the CIDR address
-     * @param ruleBits
-     *            the size of mask of the CIDR address
-     * @param packetAddress
-     *            the IP address of the incoming packet to match with
-     * @return true if CIDR address matches the packet's IP address, false
-     *         otherwise
-     */
-    protected boolean matchIPAddress(int rulePrefix, int ruleBits,
-            int packetAddress) {
-        boolean matched = true;
-
-        int rule_iprng = 32 - ruleBits;
-        int rule_ipint = rulePrefix;
-        int pkt_ipint = packetAddress;
-        // if there's a subnet range (bits to be wildcarded > 0)
-        if (rule_iprng > 0) {
-            // right shift bits to remove rule_iprng of LSB that are to be
-            // wildcarded
-            rule_ipint = rule_ipint >> rule_iprng;
-            pkt_ipint = pkt_ipint >> rule_iprng;
-            // now left shift to return to normal range, except that the
-            // rule_iprng number of LSB
-            // are now zeroed
-            rule_ipint = rule_ipint << rule_iprng;
-            pkt_ipint = pkt_ipint << rule_iprng;
-        }
-        // check if we have a match
-        if (rule_ipint != pkt_ipint)
-            matched = false;
-
-        return matched;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 2521;
-        int result = super.hashCode();
-        result = prime * result + (int) dpid;
-        result = prime * result + in_port;
-        result = prime * result + (int) dl_src;
-        result = prime * result + (int) dl_dst;
-        result = prime * result + dl_type;
-        result = prime * result + nw_src_prefix;
-        result = prime * result + nw_src_maskbits;
-        result = prime * result + nw_dst_prefix;
-        result = prime * result + nw_dst_maskbits;
-        result = prime * result + nw_proto;
-        result = prime * result + tp_src;
-        result = prime * result + tp_dst;
-        result = prime * result + action.ordinal();
-        result = prime * result + priority;
-        result = prime * result + (new Boolean(wildcard_dpid)).hashCode();
-        result = prime * result + (new Boolean(wildcard_in_port)).hashCode();
-        result = prime * result + (new Boolean(wildcard_dl_src)).hashCode();
-        result = prime * result + (new Boolean(wildcard_dl_dst)).hashCode();
-        result = prime * result + (new Boolean(wildcard_dl_type)).hashCode();
-        result = prime * result + (new Boolean(wildcard_nw_src)).hashCode();
-        result = prime * result + (new Boolean(wildcard_nw_dst)).hashCode();
-        result = prime * result + (new Boolean(wildcard_nw_proto)).hashCode();
-        result = prime * result + (new Boolean(wildcard_tp_src)).hashCode();
-        result = prime * result + (new Boolean(wildcard_tp_dst)).hashCode();
-        return result;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java b/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java
deleted file mode 100644
index 7a31d38..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallRulesResource.java
+++ /dev/null
@@ -1,292 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.map.MappingJsonFactory;
-import org.openflow.util.HexString;
-import org.restlet.resource.Delete;
-import org.restlet.resource.Post;
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPv4;
-
-public class FirewallRulesResource extends ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(FirewallRulesResource.class);
-
-    @Get("json")
-    public Object handleRequest() {
-        IFirewallService firewall = 
-                (IFirewallService)getContext().getAttributes().
-                get(IFirewallService.class.getCanonicalName());
-
-        return firewall.getRules();
-    }
-
-    /**
-     * Takes a Firewall Rule string in JSON format and parses it into
-     * our firewall rule data structure, then adds it to the firewall.
-     * @param fmJson The Firewall rule entry in JSON format.
-     * @return A string status message
-     */
-    @Post
-    public String store(String fmJson) {
-        IFirewallService firewall = 
-                (IFirewallService)getContext().getAttributes().
-                get(IFirewallService.class.getCanonicalName());
-
-        FirewallRule rule;
-        try {
-            rule = jsonToFirewallRule(fmJson);
-        } catch (IOException e) {
-            log.error("Error parsing firewall rule: " + fmJson, e);
-            e.printStackTrace();
-            return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}";
-        }
-        String status = null;
-        if (checkRuleExists(rule, firewall.getRules())) {
-            status = "Error! A similar firewall rule already exists.";
-            log.error(status);
-        } else {
-            // add rule to firewall
-            firewall.addRule(rule);
-            status = "Rule added";
-        }
-        return ("{\"status\" : \"" + status + "\"}");
-    }
-
-    /**
-     * Takes a Firewall Rule string in JSON format and parses it into
-     * our firewall rule data structure, then deletes it from the firewall.
-     * @param fmJson The Firewall rule entry in JSON format.
-     * @return A string status message
-     */
-    
-    @Delete
-    public String remove(String fmJson) {
-        IFirewallService firewall = 
-                (IFirewallService)getContext().getAttributes().
-                get(IFirewallService.class.getCanonicalName());
-
-        FirewallRule rule;
-        try {
-            rule = jsonToFirewallRule(fmJson);
-        } catch (IOException e) {
-            log.error("Error parsing firewall rule: " + fmJson, e);
-            e.printStackTrace();
-            return "{\"status\" : \"Error! Could not parse firewall rule, see log for details.\"}";
-        }
-        String status = null;
-        boolean exists = false;
-        Iterator<FirewallRule> iter = firewall.getRules().iterator();
-        while (iter.hasNext()) {
-            FirewallRule r = iter.next();
-            if (r.ruleid == rule.ruleid) {
-                exists = true;
-                break;
-            }
-        }
-        if (!exists) {
-            status = "Error! Can't delete, a rule with this ID doesn't exist.";
-            log.error(status);
-        } else {
-            // delete rule from firewall
-            firewall.deleteRule(rule.ruleid);
-            status = "Rule deleted";
-        }
-        return ("{\"status\" : \"" + status + "\"}");
-    }
-
-    /**
-     * Turns a JSON formatted Firewall Rule string into a FirewallRule instance
-     * @param fmJson The JSON formatted static firewall rule
-     * @return The FirewallRule instance
-     * @throws IOException If there was an error parsing the JSON
-     */
-     
-    public static FirewallRule jsonToFirewallRule(String fmJson) throws IOException {
-        FirewallRule rule = new FirewallRule();
-        MappingJsonFactory f = new MappingJsonFactory();
-        JsonParser jp;
-
-        try {
-            jp = f.createJsonParser(fmJson);
-        } catch (JsonParseException e) {
-            throw new IOException(e);
-        }
-
-        jp.nextToken();
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw new IOException("Expected START_OBJECT");
-        }
-
-        while (jp.nextToken() != JsonToken.END_OBJECT) {
-            if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
-                throw new IOException("Expected FIELD_NAME");
-            }
-
-            String n = jp.getCurrentName();
-            jp.nextToken();
-            if (jp.getText().equals("")) 
-                continue;
-
-            String tmp;
-            
-            // This is currently only applicable for remove().  In store(), ruleid takes a random number
-            if (n == "ruleid") {
-                rule.ruleid = Integer.parseInt((String)jp.getText());
-            }
-            
-            // This assumes user having dpid info for involved switches
-            else if (n == "switchid") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("-1") == false) {
-                    // user inputs hex format dpid 
-                    rule.dpid = HexString.toLong(tmp);                    
-                    rule.wildcard_dpid = false;
-                }
-            } 
-            
-            else if (n == "src-inport") {
-                rule.in_port = Short.parseShort(jp.getText());
-                rule.wildcard_in_port = false;
-            } 
-            
-            else if (n == "src-mac") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("ANY") == false) {
-                    rule.wildcard_dl_src = false;
-                    rule.dl_src = Ethernet.toLong(Ethernet.toMACAddress(tmp));
-                }
-            } 
-            
-            else if (n == "dst-mac") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("ANY") == false) {
-                    rule.wildcard_dl_dst = false;
-                    rule.dl_dst = Ethernet.toLong(Ethernet.toMACAddress(tmp));
-                }
-            } 
-            
-            else if (n == "dl-type") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("ARP")) {
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_ARP;
-                }
-            } 
-            
-            else if (n == "src-ip") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("ANY") == false) {
-                    rule.wildcard_nw_src = false;
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                    int[] cidr = IPCIDRToPrefixBits(tmp);
-                    rule.nw_src_prefix = cidr[0];
-                    rule.nw_src_maskbits = cidr[1];
-                }
-            } 
-            
-            else if (n == "dst-ip") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("ANY") == false) {
-                    rule.wildcard_nw_dst = false;
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                    int[] cidr = IPCIDRToPrefixBits(tmp);
-                    rule.nw_dst_prefix = cidr[0];
-                    rule.nw_dst_maskbits = cidr[1];
-                }
-            } 
-            
-            else if (n == "nw-proto") {
-                tmp = jp.getText();
-                if (tmp.equalsIgnoreCase("TCP")) {
-                    rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_TCP;
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                } else if (tmp.equalsIgnoreCase("UDP")) {
-                    rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_UDP;
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                } else if (tmp.equalsIgnoreCase("ICMP")) {
-                    rule.wildcard_nw_proto = false;
-                    rule.nw_proto = IPv4.PROTOCOL_ICMP;
-                    rule.wildcard_dl_type = false;
-                    rule.dl_type = Ethernet.TYPE_IPv4;
-                } 
-            } 
-            
-            else if (n == "tp-src") {
-                rule.wildcard_tp_src = false;
-                rule.tp_src = Short.parseShort(jp.getText());
-            } 
-            
-            else if (n == "tp-dst") {
-                rule.wildcard_tp_dst = false;
-                rule.tp_dst = Short.parseShort(jp.getText());
-            } 
-            
-            else if (n == "priority") {
-                rule.priority = Integer.parseInt(jp.getText());
-            } 
-            
-            else if (n == "action") {
-                if (jp.getText().equalsIgnoreCase("allow") == true) {
-                    rule.action = FirewallRule.FirewallAction.ALLOW;
-                } else if (jp.getText().equalsIgnoreCase("deny") == true) {
-                    rule.action = FirewallRule.FirewallAction.DENY;
-                }
-            }
-        }
-
-        return rule;
-    }
-
-    public static int[] IPCIDRToPrefixBits(String cidr) {
-        int ret[] = new int[2];
-
-        // as IP can also be a prefix rather than an absolute address
-        // split it over "/" to get the bit range
-        String[] parts = cidr.split("/");
-        String cidr_prefix = parts[0].trim();
-        int cidr_bits = 0;
-        if (parts.length == 2) {
-            try {
-                cidr_bits = Integer.parseInt(parts[1].trim());
-            } catch (Exception exp) {
-                cidr_bits = 32;
-            }
-        }
-        ret[0] = IPv4.toIPv4Address(cidr_prefix);
-        ret[1] = cidr_bits;
-
-        return ret;
-    }
-
-    public static boolean checkRuleExists(FirewallRule rule, List<FirewallRule> rules) {
-        Iterator<FirewallRule> iter = rules.iterator();
-        while (iter.hasNext()) {
-            FirewallRule r = iter.next();
-
-            // check if we find a similar rule
-            if (rule.isSameAs(r)) {
-                return true;
-            }
-        }
-
-        // no rule matched, so it doesn't exist in the rules
-        return false;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/FirewallWebRoutable.java b/src/main/java/net/floodlightcontroller/firewall/FirewallWebRoutable.java
deleted file mode 100644
index 3a9beab..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/FirewallWebRoutable.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-import org.restlet.Context;
-import org.restlet.routing.Router;
-
-public class FirewallWebRoutable implements RestletRoutable {
-    /**
-     * Create the Restlet router and bind to the proper resources.
-     */
-    @Override
-    public Router getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/module/{op}/json", FirewallResource.class);
-        router.attach("/rules/json", FirewallRulesResource.class);
-        return router;
-    }
-
-    /**
-     * Set the base path for the Firewall
-     */
-    @Override
-    public String basePath() {
-        return "/wm/firewall";
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/IFirewallService.java b/src/main/java/net/floodlightcontroller/firewall/IFirewallService.java
deleted file mode 100644
index ae9d89f..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/IFirewallService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import java.util.List;
-import java.util.Map;
-
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-public interface IFirewallService extends IFloodlightService {
-
-    /**
-     * Enables/disables the firewall.
-     * @param enable Whether to enable or disable the firewall.
-     */
-    public void enableFirewall(boolean enable);
-
-    /**
-     * Returns operational status of the firewall
-     * @return boolean enabled;
-     */
-    public boolean isEnabled();
- 
-    /**
-     * Returns all of the firewall rules
-     * @return List of all rules
-     */
-    public List<FirewallRule> getRules();
-    
-    /**
-     * Returns the subnet mask
-     * @return subnet mask
-     */
-    public String getSubnetMask();
-    
-    /**
-     * Sets the subnet mask
-     * @param newMask The new subnet mask
-     */
-    public void setSubnetMask(String newMask);
-
-    /**
-     * Returns all of the firewall rules in storage
-     * for debugging and unit-testing purposes
-     * @return List of all rules in storage
-     */
-    public List<Map<String, Object>> getStorageRules();
-
-    /**
-     * Adds a new Firewall rule
-     */
-    public void addRule(FirewallRule rule);
-
-    /**
-     * Deletes a Firewall rule
-     */
-    public void deleteRule(int ruleid);
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java
deleted file mode 100644
index 3fab409..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/RuleWildcardsPair.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import org.openflow.protocol.OFMatch;
-
-public class RuleWildcardsPair {
-    public FirewallRule rule;
-    public int wildcards = OFMatch.OFPFW_ALL;
-}
diff --git a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java b/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java
deleted file mode 100644
index 2e5f123..0000000
--- a/src/main/java/net/floodlightcontroller/firewall/WildcardsPair.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import org.openflow.protocol.OFMatch;
-
-public class WildcardsPair {
-    public int allow = OFMatch.OFPFW_ALL;
-    public int drop = OFMatch.OFPFW_ALL;
-}
diff --git a/src/main/java/net/floodlightcontroller/hub/Hub.java b/src/main/java/net/floodlightcontroller/hub/Hub.java
deleted file mode 100644
index 3618351..0000000
--- a/src/main/java/net/floodlightcontroller/hub/Hub.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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.
-**/
-
-package net.floodlightcontroller.hub;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-import org.openflow.util.U16;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu) - 04/04/10
- */
-public class Hub implements IFloodlightModule, IOFMessageListener {
-    protected static Logger log = LoggerFactory.getLogger(Hub.class);
-
-    protected IFloodlightProviderService floodlightProvider;
-
-    /**
-     * @param floodlightProvider the floodlightProvider to set
-     */
-    public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) {
-        this.floodlightProvider = floodlightProvider;
-    }
-
-    @Override
-    public String getName() {
-        return Hub.class.getPackage().getName();
-    }
-
-    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        OFPacketIn pi = (OFPacketIn) msg;
-        OFPacketOut po = (OFPacketOut) floodlightProvider.getOFMessageFactory()
-                .getMessage(OFType.PACKET_OUT);
-        po.setBufferId(pi.getBufferId())
-            .setInPort(pi.getInPort());
-
-        // set actions
-        OFActionOutput action = new OFActionOutput()
-            .setPort((short) OFPort.OFPP_FLOOD.getValue());
-        po.setActions(Collections.singletonList((OFAction)action));
-        po.setActionsLength((short) OFActionOutput.MINIMUM_LENGTH);
-
-        // set data if is is included in the packetin
-        if (pi.getBufferId() == 0xffffffff) {
-            byte[] packetData = pi.getPacketData();
-            po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH
-                    + po.getActionsLength() + packetData.length));
-            po.setPacketData(packetData);
-        } else {
-            po.setLength(U16.t(OFPacketOut.MINIMUM_LENGTH
-                    + po.getActionsLength()));
-        }
-        try {
-            sw.write(po, cntx);
-        } catch (IOException e) {
-            log.error("Failure writing PacketOut", e);
-        }
-
-        return Command.CONTINUE;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        return false;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        return false;
-    }
-
-    // IFloodlightModule
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        // We don't provide any services, return null
-        return null;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        // We don't provide any services, return null
-        return null;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-        floodlightProvider =
-                context.getServiceImpl(IFloodlightProviderService.class);
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/jython/JythonDebugInterface.java b/src/main/java/net/floodlightcontroller/jython/JythonDebugInterface.java
deleted file mode 100644
index 19a97b5..0000000
--- a/src/main/java/net/floodlightcontroller/jython/JythonDebugInterface.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package net.floodlightcontroller.jython;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-
-public class JythonDebugInterface implements IFloodlightModule {
-    protected static Logger log = LoggerFactory.getLogger(JythonDebugInterface.class);
-    protected JythonServer debug_server;
-    protected static int JYTHON_PORT = 6655;
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        // We don't export services
-        return null;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        // We don't export services
-        return null;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        // We don't have any dependencies
-        return null;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-             throws FloodlightModuleException {
-        // no-op
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        Map<String, Object> locals = new HashMap<String, Object>();     
-        // add all existing module references to the debug server
-        for (Class<? extends IFloodlightService> s : context.getAllServices()) {
-            // Put only the last part of the name
-            String[] bits = s.getCanonicalName().split("\\.");
-            String name = bits[bits.length-1];
-            locals.put(name, context.getServiceImpl(s));
-        }
-        
-        // read our config options
-        Map<String, String> configOptions = context.getConfigParams(this);
-        int port = JYTHON_PORT;
-        String portNum = configOptions.get("port");
-        if (portNum != null) {
-            port = Integer.parseInt(portNum);
-        }
-        
-        JythonServer debug_server = new JythonServer(port, locals);
-        debug_server.start();
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/jython/JythonServer.java b/src/main/java/net/floodlightcontroller/jython/JythonServer.java
deleted file mode 100644
index fc35b15..0000000
--- a/src/main/java/net/floodlightcontroller/jython/JythonServer.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package net.floodlightcontroller.jython;
-
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.python.util.PythonInterpreter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class starts a thread that runs a jython interpreter that
- * can be used for debug (or even development).
- *
- * @author mandeepdhami
- *
- */
-public class JythonServer extends Thread {
-    protected static Logger log = LoggerFactory.getLogger(JythonServer.class);
-
-	int port;
-	Map<String, Object> locals;
-	
-	/**
-	 * @param port_ Port to use for jython server
-	 * @param locals_ Locals to add to the interpreters top level name space
-	 */
-	public JythonServer(int port_, Map<String, Object> locals_) {
-		this.port = port_ ;
-		this.locals = locals_;
-		if (this.locals == null) {
-			this.locals = new HashMap<String, Object>();
-		}
-		this.locals.put("log", JythonServer.log);
-		this.setName("debugserver");
-	}
-
-    /**
-     * The main thread for this class invoked by Thread.run()
-     *
-     * @see java.lang.Thread#run()
-     */
-    public void run() {
-        PythonInterpreter p = new PythonInterpreter();
-        for (String name : this.locals.keySet()) {
-            p.set(name, this.locals.get(name));
-        }
-
-        URL jarUrl = JythonServer.class.getProtectionDomain().getCodeSource().getLocation();
-        String jarPath = jarUrl.getPath();
-        if (jarUrl.getProtocol().equals("file")) {
-            // If URL is of type file, assume that we are in dev env and set path to python dir.
-            // else use the jar file as is
-            jarPath = jarPath + "../../src/main/python/";
-        }
-
-        p.exec("import sys");
-        p.exec("sys.path.append('" + jarPath + "')");
-        p.exec("from debugserver import run_server");
-        p.exec("run_server(" + this.port + ", '0.0.0.0', locals())");
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/learningswitch/ILearningSwitchService.java b/src/main/java/net/floodlightcontroller/learningswitch/ILearningSwitchService.java
deleted file mode 100644
index 71f6625..0000000
--- a/src/main/java/net/floodlightcontroller/learningswitch/ILearningSwitchService.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package net.floodlightcontroller.learningswitch;
-
-import java.util.Map;
-
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.types.MacVlanPair;
-
-public interface ILearningSwitchService extends IFloodlightService {
-    /**
-     * Returns the LearningSwitch's learned host table
-     * @return The learned host table
-     */
-    public Map<IOFSwitch, Map<MacVlanPair,Short>> getTable();
-}
diff --git a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java
deleted file mode 100644
index 005708d..0000000
--- a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitch.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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.
-**/
-
-/**
- * Floodlight
- * A BSD licensed, Java based OpenFlow controller
- *
- * Floodlight is a Java based OpenFlow controller originally written by David Erickson at Stanford
- * University. It is available under the BSD license.
- *
- * For documentation, forums, issue tracking and more visit:
- *
- * http://www.openflowhub.org/display/Floodlight/Floodlight+Home
- **/
-
-package net.floodlightcontroller.learningswitch;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.types.MacVlanPair;
-import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.restserver.IRestApiService;
-
-import org.openflow.protocol.OFError;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFFlowRemoved;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-import org.openflow.util.HexString;
-import org.openflow.util.LRULinkedHashMap;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LearningSwitch 
-    implements IFloodlightModule, ILearningSwitchService, IOFMessageListener {
-    protected static Logger log = LoggerFactory.getLogger(LearningSwitch.class);
-    
-    // Module dependencies
-    protected IFloodlightProviderService floodlightProvider;
-    protected ICounterStoreService counterStore;
-    protected IRestApiService restApi;
-    
-    // Stores the learned state for each switch
-    protected Map<IOFSwitch, Map<MacVlanPair,Short>> macVlanToSwitchPortMap;
-
-    // flow-mod - for use in the cookie
-    public static final int LEARNING_SWITCH_APP_ID = 1;
-    // LOOK! This should probably go in some class that encapsulates
-    // the app cookie management
-    public static final int APP_ID_BITS = 12;
-    public static final int APP_ID_SHIFT = (64 - APP_ID_BITS);
-    public static final long LEARNING_SWITCH_COOKIE = (long) (LEARNING_SWITCH_APP_ID & ((1 << APP_ID_BITS) - 1)) << APP_ID_SHIFT;
-    
-    // more flow-mod defaults 
-    protected static final short IDLE_TIMEOUT_DEFAULT = 5;
-    protected static final short HARD_TIMEOUT_DEFAULT = 0;
-    protected static final short PRIORITY_DEFAULT = 100;
-    
-    // for managing our map sizes
-    protected static final int MAX_MACS_PER_SWITCH  = 1000;    
-
-    // normally, setup reverse flow as well. Disable only for using cbench for comparison with NOX etc.
-    protected static final boolean LEARNING_SWITCH_REVERSE_FLOW = true;
-    
-    /**
-     * @param floodlightProvider the floodlightProvider to set
-     */
-    public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) {
-        this.floodlightProvider = floodlightProvider;
-    }
-    
-    @Override
-    public String getName() {
-        return "learningswitch";
-    }
-
-    /**
-     * Adds a host to the MAC/VLAN->SwitchPort mapping
-     * @param sw The switch to add the mapping to
-     * @param mac The MAC address of the host to add
-     * @param vlan The VLAN that the host is on
-     * @param portVal The switchport that the host is on
-     */
-    protected void addToPortMap(IOFSwitch sw, long mac, short vlan, short portVal) {
-        Map<MacVlanPair,Short> swMap = macVlanToSwitchPortMap.get(sw);
-        
-        if (vlan == (short) 0xffff) {
-            // OFMatch.loadFromPacket sets VLAN ID to 0xffff if the packet contains no VLAN tag;
-            // for our purposes that is equivalent to the default VLAN ID 0
-            vlan = 0;
-        }
-        
-        if (swMap == null) {
-            // May be accessed by REST API so we need to make it thread safe
-            swMap = Collections.synchronizedMap(new LRULinkedHashMap<MacVlanPair,Short>(MAX_MACS_PER_SWITCH));
-            macVlanToSwitchPortMap.put(sw, swMap);
-        }
-        swMap.put(new MacVlanPair(mac, vlan), portVal);
-    }
-    
-    /**
-     * Removes a host from the MAC/VLAN->SwitchPort mapping
-     * @param sw The switch to remove the mapping from
-     * @param mac The MAC address of the host to remove
-     * @param vlan The VLAN that the host is on
-     */
-    protected void removeFromPortMap(IOFSwitch sw, long mac, short vlan) {
-        if (vlan == (short) 0xffff) {
-            vlan = 0;
-        }
-        Map<MacVlanPair,Short> swMap = macVlanToSwitchPortMap.get(sw);
-        if (swMap != null)
-            swMap.remove(new MacVlanPair(mac, vlan));
-    }
-
-    /**
-     * Get the port that a MAC/VLAN pair is associated with
-     * @param sw The switch to get the mapping from
-     * @param mac The MAC address to get
-     * @param vlan The VLAN number to get
-     * @return The port the host is on
-     */
-    public Short getFromPortMap(IOFSwitch sw, long mac, short vlan) {
-        if (vlan == (short) 0xffff) {
-            vlan = 0;
-        }
-        Map<MacVlanPair,Short> swMap = macVlanToSwitchPortMap.get(sw);
-        if (swMap != null)
-            return swMap.get(new MacVlanPair(mac, vlan));
-        
-        // if none found
-        return null;
-    }
-    
-    /**
-     * Clears the MAC/VLAN -> SwitchPort map for all switches
-     */
-    public void clearLearnedTable() {
-        macVlanToSwitchPortMap.clear();
-    }
-    
-    /**
-     * Clears the MAC/VLAN -> SwitchPort map for a single switch
-     * @param sw The switch to clear the mapping for
-     */
-    public void clearLearnedTable(IOFSwitch sw) {
-        Map<MacVlanPair, Short> swMap = macVlanToSwitchPortMap.get(sw);
-        if (swMap != null)
-            swMap.clear();
-    }
-    
-    @Override
-    public synchronized Map<IOFSwitch, Map<MacVlanPair,Short>> getTable() {
-        return macVlanToSwitchPortMap;
-    }
-    
-    /**
-     * Writes a OFFlowMod to a switch.
-     * @param sw The switch tow rite the flowmod to.
-     * @param command The FlowMod actions (add, delete, etc).
-     * @param bufferId The buffer ID if the switch has buffered the packet.
-     * @param match The OFMatch structure to write.
-     * @param outPort The switch port to output it to.
-     */
-    private void writeFlowMod(IOFSwitch sw, short command, int bufferId,
-            OFMatch match, short outPort) {
-        // from openflow 1.0 spec - need to set these on a struct ofp_flow_mod:
-        // struct ofp_flow_mod {
-        //    struct ofp_header header;
-        //    struct ofp_match match; /* Fields to match */
-        //    uint64_t cookie; /* Opaque controller-issued identifier. */
-        //
-        //    /* Flow actions. */
-        //    uint16_t command; /* One of OFPFC_*. */
-        //    uint16_t idle_timeout; /* Idle time before discarding (seconds). */
-        //    uint16_t hard_timeout; /* Max time before discarding (seconds). */
-        //    uint16_t priority; /* Priority level of flow entry. */
-        //    uint32_t buffer_id; /* Buffered packet to apply to (or -1).
-        //                           Not meaningful for OFPFC_DELETE*. */
-        //    uint16_t out_port; /* For OFPFC_DELETE* commands, require
-        //                          matching entries to include this as an
-        //                          output port. A value of OFPP_NONE
-        //                          indicates no restriction. */
-        //    uint16_t flags; /* One of OFPFF_*. */
-        //    struct ofp_action_header actions[0]; /* The action length is inferred
-        //                                            from the length field in the
-        //                                            header. */
-        //    };
-           
-        OFFlowMod flowMod = (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD);
-        flowMod.setMatch(match);
-        flowMod.setCookie(LearningSwitch.LEARNING_SWITCH_COOKIE);
-        flowMod.setCommand(command);
-        flowMod.setIdleTimeout(LearningSwitch.IDLE_TIMEOUT_DEFAULT);
-        flowMod.setHardTimeout(LearningSwitch.HARD_TIMEOUT_DEFAULT);
-        flowMod.setPriority(LearningSwitch.PRIORITY_DEFAULT);
-        flowMod.setBufferId(bufferId);
-        flowMod.setOutPort((command == OFFlowMod.OFPFC_DELETE) ? outPort : OFPort.OFPP_NONE.getValue());
-        flowMod.setFlags((command == OFFlowMod.OFPFC_DELETE) ? 0 : (short) (1 << 0)); // OFPFF_SEND_FLOW_REM
-
-        // set the ofp_action_header/out actions:
-        // from the openflow 1.0 spec: need to set these on a struct ofp_action_output:
-        // uint16_t type; /* OFPAT_OUTPUT. */
-        // uint16_t len; /* Length is 8. */
-        // uint16_t port; /* Output port. */
-        // uint16_t max_len; /* Max length to send to controller. */
-        // type/len are set because it is OFActionOutput,
-        // and port, max_len are arguments to this constructor
-        flowMod.setActions(Arrays.asList((OFAction) new OFActionOutput(outPort, (short) 0xffff)));
-        flowMod.setLength((short) (OFFlowMod.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH));
-
-        if (log.isTraceEnabled()) {
-            log.trace("{} {} flow mod {}", 
-                      new Object[]{ sw, (command == OFFlowMod.OFPFC_DELETE) ? "deleting" : "adding", flowMod });
-        }
-
-        counterStore.updatePktOutFMCounterStore(sw, flowMod);
-        
-        // and write it out
-        try {
-            sw.write(flowMod, null);
-        } catch (IOException e) {
-            log.error("Failed to write {} to switch {}", new Object[]{ flowMod, sw }, e);
-        }
-    }
-    
-    /**
-     * Writes an OFPacketOut message to a switch.
-     * @param sw The switch to write the PacketOut to.
-     * @param packetInMessage The corresponding PacketIn.
-     * @param egressPort The switchport to output the PacketOut.
-     */
-    private void writePacketOutForPacketIn(IOFSwitch sw, 
-                                          OFPacketIn packetInMessage, 
-                                          short egressPort) {
-        // from openflow 1.0 spec - need to set these on a struct ofp_packet_out:
-        // uint32_t buffer_id; /* ID assigned by datapath (-1 if none). */
-        // uint16_t in_port; /* Packet's input port (OFPP_NONE if none). */
-        // uint16_t actions_len; /* Size of action array in bytes. */
-        // struct ofp_action_header actions[0]; /* Actions. */
-        /* uint8_t data[0]; */ /* Packet data. The length is inferred
-                                  from the length field in the header.
-                                  (Only meaningful if buffer_id == -1.) */
-        
-        OFPacketOut packetOutMessage = (OFPacketOut) floodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
-        short packetOutLength = (short)OFPacketOut.MINIMUM_LENGTH; // starting length
-
-        // Set buffer_id, in_port, actions_len
-        packetOutMessage.setBufferId(packetInMessage.getBufferId());
-        packetOutMessage.setInPort(packetInMessage.getInPort());
-        packetOutMessage.setActionsLength((short)OFActionOutput.MINIMUM_LENGTH);
-        packetOutLength += OFActionOutput.MINIMUM_LENGTH;
-        
-        // set actions
-        List<OFAction> actions = new ArrayList<OFAction>(1);      
-        actions.add(new OFActionOutput(egressPort, (short) 0));
-        packetOutMessage.setActions(actions);
-
-        // set data - only if buffer_id == -1
-        if (packetInMessage.getBufferId() == OFPacketOut.BUFFER_ID_NONE) {
-            byte[] packetData = packetInMessage.getPacketData();
-            packetOutMessage.setPacketData(packetData); 
-            packetOutLength += (short)packetData.length;
-        }
-        
-        // finally, set the total length
-        packetOutMessage.setLength(packetOutLength);              
-            
-        // and write it out
-        try {
-        	counterStore.updatePktOutFMCounterStore(sw, packetOutMessage);
-            sw.write(packetOutMessage, null);
-        } catch (IOException e) {
-            log.error("Failed to write {} to switch {}: {}", new Object[]{ packetOutMessage, sw, e });
-        }
-    }
-    
-    /**
-     * Processes a OFPacketIn message. If the switch has learned the MAC/VLAN to port mapping
-     * for the pair it will write a FlowMod for. If the mapping has not been learned the 
-     * we will flood the packet.
-     * @param sw
-     * @param pi
-     * @param cntx
-     * @return
-     */
-    private Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
-        // Read in packet data headers by using OFMatch
-        OFMatch match = new OFMatch();
-        match.loadFromPacket(pi.getPacketData(), pi.getInPort());
-        Long sourceMac = Ethernet.toLong(match.getDataLayerSource());
-        Long destMac = Ethernet.toLong(match.getDataLayerDestination());
-        Short vlan = match.getDataLayerVirtualLan();
-        if ((destMac & 0xfffffffffff0L) == 0x0180c2000000L) {
-            if (log.isTraceEnabled()) {
-                log.trace("ignoring packet addressed to 802.1D/Q reserved addr: switch {} vlan {} dest MAC {}",
-                          new Object[]{ sw, vlan, HexString.toHexString(destMac) });
-            }
-            return Command.STOP;
-        }
-        if ((sourceMac & 0x010000000000L) == 0) {
-            // If source MAC is a unicast address, learn the port for this MAC/VLAN
-            this.addToPortMap(sw, sourceMac, vlan, pi.getInPort());
-        }
-        
-        // Now output flow-mod and/or packet
-        Short outPort = getFromPortMap(sw, destMac, vlan);
-        if (outPort == null) {
-            // If we haven't learned the port for the dest MAC/VLAN, flood it
-            // Don't flood broadcast packets if the broadcast is disabled.
-            // XXX For LearningSwitch this doesn't do much. The sourceMac is removed
-            //     from port map whenever a flow expires, so you would still see
-            //     a lot of floods.
-            this.writePacketOutForPacketIn(sw, pi, OFPort.OFPP_FLOOD.getValue());
-        } else if (outPort == match.getInputPort()) {
-            log.trace("ignoring packet that arrived on same port as learned destination:"
-                    + " switch {} vlan {} dest MAC {} port {}",
-                    new Object[]{ sw, vlan, HexString.toHexString(destMac), outPort });
-        } else {
-            // Add flow table entry matching source MAC, dest MAC, VLAN and input port
-            // that sends to the port we previously learned for the dest MAC/VLAN.  Also
-            // add a flow table entry with source and destination MACs reversed, and
-            // input and output ports reversed.  When either entry expires due to idle
-            // timeout, remove the other one.  This ensures that if a device moves to
-            // a different port, a constant stream of packets headed to the device at
-            // its former location does not keep the stale entry alive forever.
-            // FIXME: current HP switches ignore DL_SRC and DL_DST fields, so we have to match on
-            // NW_SRC and NW_DST as well
-            match.setWildcards(((Integer)sw.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).intValue()
-                    & ~OFMatch.OFPFW_IN_PORT
-                    & ~OFMatch.OFPFW_DL_VLAN & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_DL_DST
-                    & ~OFMatch.OFPFW_NW_SRC_MASK & ~OFMatch.OFPFW_NW_DST_MASK);
-            this.writeFlowMod(sw, OFFlowMod.OFPFC_ADD, pi.getBufferId(), match, outPort);
-            if (LEARNING_SWITCH_REVERSE_FLOW) {
-                this.writeFlowMod(sw, OFFlowMod.OFPFC_ADD, -1, match.clone()
-                    .setDataLayerSource(match.getDataLayerDestination())
-                    .setDataLayerDestination(match.getDataLayerSource())
-                    .setNetworkSource(match.getNetworkDestination())
-                    .setNetworkDestination(match.getNetworkSource())
-                    .setTransportSource(match.getTransportDestination())
-                    .setTransportDestination(match.getTransportSource())
-                    .setInputPort(outPort),
-                    match.getInputPort());
-            }
-        }
-        return Command.CONTINUE;
-    }
-
-    /**
-     * Processes a flow removed message. We will delete the learned MAC/VLAN mapping from
-     * the switch's table.
-     * @param sw The switch that sent the flow removed message.
-     * @param flowRemovedMessage The flow removed message.
-     * @return Whether to continue processing this message or stop.
-     */
-    private Command processFlowRemovedMessage(IOFSwitch sw, OFFlowRemoved flowRemovedMessage) {
-        if (flowRemovedMessage.getCookie() != LearningSwitch.LEARNING_SWITCH_COOKIE) {
-            return Command.CONTINUE;
-        }
-        if (log.isTraceEnabled()) {
-            log.trace("{} flow entry removed {}", sw, flowRemovedMessage);
-        }
-        OFMatch match = flowRemovedMessage.getMatch();
-        // When a flow entry expires, it means the device with the matching source
-        // MAC address and VLAN either stopped sending packets or moved to a different
-        // port.  If the device moved, we can't know where it went until it sends
-        // another packet, allowing us to re-learn its port.  Meanwhile we remove
-        // it from the macVlanToPortMap to revert to flooding packets to this device.
-        this.removeFromPortMap(sw, Ethernet.toLong(match.getDataLayerSource()),
-            match.getDataLayerVirtualLan());
-        
-        // Also, if packets keep coming from another device (e.g. from ping), the
-        // corresponding reverse flow entry will never expire on its own and will
-        // send the packets to the wrong port (the matching input port of the
-        // expired flow entry), so we must delete the reverse entry explicitly.
-        this.writeFlowMod(sw, OFFlowMod.OFPFC_DELETE, -1, match.clone()
-                .setWildcards(((Integer)sw.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).intValue()
-                        & ~OFMatch.OFPFW_DL_VLAN & ~OFMatch.OFPFW_DL_SRC & ~OFMatch.OFPFW_DL_DST
-                        & ~OFMatch.OFPFW_NW_SRC_MASK & ~OFMatch.OFPFW_NW_DST_MASK)
-                .setDataLayerSource(match.getDataLayerDestination())
-                .setDataLayerDestination(match.getDataLayerSource())
-                .setNetworkSource(match.getNetworkDestination())
-                .setNetworkDestination(match.getNetworkSource())
-                .setTransportSource(match.getTransportDestination())
-                .setTransportDestination(match.getTransportSource()),
-                match.getInputPort());
-        return Command.CONTINUE;
-    }
-    
-    // IOFMessageListener
-    
-    @Override
-    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        switch (msg.getType()) {
-            case PACKET_IN:
-                return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx);
-            case FLOW_REMOVED:
-                return this.processFlowRemovedMessage(sw, (OFFlowRemoved) msg);
-            case ERROR:
-                log.info("received an error {} from switch {}", (OFError) msg, sw);
-                return Command.CONTINUE;
-            default:
-            	break;
-        }
-        log.error("received an unexpected message {} from switch {}", msg, sw);
-        return Command.CONTINUE;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        return false;
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        return false;
-    }
-
-    // IFloodlightModule
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(ILearningSwitchService.class);
-        return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-            IFloodlightService> m = 
-                new HashMap<Class<? extends IFloodlightService>,
-                    IFloodlightService>();
-        m.put(ILearningSwitchService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>>
-            getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        l.add(ICounterStoreService.class);
-        l.add(IRestApiService.class);
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-            throws FloodlightModuleException {
-        macVlanToSwitchPortMap = 
-                new ConcurrentHashMap<IOFSwitch, Map<MacVlanPair,Short>>();
-        floodlightProvider =
-                context.getServiceImpl(IFloodlightProviderService.class);
-        counterStore =
-                context.getServiceImpl(ICounterStoreService.class);
-        restApi =
-                context.getServiceImpl(IRestApiService.class);
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        floodlightProvider.addOFMessageListener(OFType.FLOW_REMOVED, this);
-        floodlightProvider.addOFMessageListener(OFType.ERROR, this);
-        restApi.addRestletRoutable(new LearningSwitchWebRoutable());
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchTable.java b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchTable.java
deleted file mode 100644
index 19f8bf5..0000000
--- a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchTable.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package net.floodlightcontroller.learningswitch;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.types.MacVlanPair;
-
-import org.openflow.util.HexString;
-import org.restlet.data.Status;
-import org.restlet.resource.Get;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class LearningSwitchTable extends ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(LearningSwitchTable.class);
-    
-    protected Map<String, Object> formatTableEntry(MacVlanPair key, short port) {
-        Map<String, Object> entry = new HashMap<String, Object>();
-        entry.put("mac", HexString.toHexString(key.mac));
-        entry.put("vlan", key.vlan);
-        entry.put("port", port);
-        return entry;
-    }
-    
-    protected List<Map<String, Object>> getOneSwitchTable(Map<MacVlanPair, Short> switchMap) {
-        List<Map<String, Object>> switchTable = new ArrayList<Map<String, Object>>();
-        for (Entry<MacVlanPair, Short> entry : switchMap.entrySet()) {
-            switchTable.add(formatTableEntry(entry.getKey(), entry.getValue()));
-        }
-        return switchTable;
-    }
-    
-    @Get("json")
-    public Map<String, List<Map<String, Object>>> getSwitchTableJson() {
-        ILearningSwitchService lsp = 
-                (ILearningSwitchService)getContext().getAttributes().
-                    get(ILearningSwitchService.class.getCanonicalName());
-
-        Map<IOFSwitch, Map<MacVlanPair,Short>> table = lsp.getTable();
-        Map<String, List<Map<String, Object>>> allSwitchTableJson = new HashMap<String, List<Map<String, Object>>>();
-        
-        String switchId = (String) getRequestAttributes().get("switch");
-        if (switchId.toLowerCase().equals("all")) {
-            for (IOFSwitch sw : table.keySet()) {
-                allSwitchTableJson.put(HexString.toHexString(sw.getId()), getOneSwitchTable(table.get(sw)));
-            }
-        } else {
-            try {
-                IFloodlightProviderService floodlightProvider = 
-                        (IFloodlightProviderService)getContext().getAttributes().
-                            get(IFloodlightProviderService.class.getCanonicalName());
-                long dpid = HexString.toLong(switchId);
-                IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
-                allSwitchTableJson.put(HexString.toHexString(sw.getId()), getOneSwitchTable(table.get(sw)));
-            } catch (NumberFormatException e) {
-                log.error("Could not decode switch ID = " + switchId);
-                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
-            }
-        }
-            
-        return allSwitchTableJson;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchWebRoutable.java b/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchWebRoutable.java
deleted file mode 100644
index 76c30cb..0000000
--- a/src/main/java/net/floodlightcontroller/learningswitch/LearningSwitchWebRoutable.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package net.floodlightcontroller.learningswitch;
-
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-
-public class LearningSwitchWebRoutable implements RestletRoutable {
-
-    @Override
-    public Restlet getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/table/{switch}/json", LearningSwitchTable.class);
-        return router;
-    }
-
-    @Override
-    public String basePath() {
-        return "/wm/learningswitch";
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
deleted file mode 100644
index d62d65b..0000000
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImpl.java
+++ /dev/null
@@ -1,270 +0,0 @@
-package net.floodlightcontroller.linkdiscovery.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoSwitchService;
-import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
-import net.floodlightcontroller.linkdiscovery.ILinkStorage;
-import net.floodlightcontroller.linkdiscovery.LinkInfo;
-import net.floodlightcontroller.routing.Link;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
-
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.thinkaurelius.titan.core.TitanException;
-import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.Edge;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.gremlin.java.GremlinPipeline;
-import com.tinkerpop.pipes.PipeFunction;
-import com.tinkerpop.pipes.transform.PathPipe;
-
-public class LinkStorageImpl implements ILinkStorage {
-	
-	protected static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
-	protected String conf;
-
-	@Override
-	public void update(Link link, DM_OPERATION op) {
-		update(link, (LinkInfo)null, op);
-	}
-
-	@Override
-	public void update(List<Link> links, DM_OPERATION op) {
-		for (Link lt: links) {
-			update(lt, (LinkInfo)null, op);
-		}
-	}
-
-	@Override
-	public void update(Link link, LinkInfo linkinfo, DM_OPERATION op) {
-		switch (op) {
-		case UPDATE:
-		case CREATE:
-		case INSERT:
-			addOrUpdateLink(link, linkinfo, op);
-			break;
-		case DELETE:
-			deleteLink(link);
-			break;
-		}
-	}
-	
-	public void addOrUpdateLink(Link lt, LinkInfo linkinfo, DM_OPERATION op) {
-		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
-		IPortObject vportSrc = null, vportDst = null;
-	
-		log.trace("addOrUpdateLink(): op {} {} {}", new Object[]{op, lt, linkinfo});
-		
-        try {
-            // get source port vertex
-        	String dpid = HexString.toHexString(lt.getSrc());
-        	short port = lt.getSrcPort();
-        	vportSrc = conn.utils().searchPort(conn, dpid, port);
-            
-            // get dest port vertex
-            dpid = HexString.toHexString(lt.getDst());
-            port = lt.getDstPort();
-            vportDst = conn.utils().searchPort(conn, dpid, port);
-                        
-            if (vportSrc != null && vportDst != null) {
-         	       	
-            	// check if the link exists
-            	
-            	Iterable<IPortObject> currPorts = vportSrc.getLinkedPorts();
-            	List<IPortObject> currLinks = new ArrayList<IPortObject>();
-            	for (IPortObject V : currPorts) {
-            		currLinks.add(V);
-            	}
-            	
-            	if (currLinks.contains(vportDst)) {
-            		// TODO: update linkinfo
-            		if (op.equals(DM_OPERATION.INSERT) || op.equals(DM_OPERATION.CREATE)) {
-            			log.debug("addOrUpdateLink(): failed link exists {} {} src {} dst {}", 
-            					new Object[]{op, lt, vportSrc, vportDst});
-            		}
-            	} else {
-            		vportSrc.setLinkPort(vportDst);
-
-            		conn.endTx(Transaction.COMMIT);
-            		log.debug("addOrUpdateLink(): link added {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
-            	}
-            } else {
-            	log.error("addOrUpdateLink(): failed invalid vertices {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
- //           	conn.endTx(Transaction.ROLLBACK);
-            }
-        } catch (TitanException e) {
-            /*
-             * retry till we succeed?
-             */
-        	e.printStackTrace();
-        	log.error("addOrUpdateLink(): titan exception {} {} {}", new Object[]{op, lt, e.toString()});
-        }
-	}
-	
-	@Override
-	public void deleteLinks(List<Link> links) {
-
-		for (Link lt : links) {
-			deleteLink(lt);
-		}
-	}
-	
-
-	@Override
-	public void deleteLink(Link lt) {
-		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
-		IPortObject vportSrc = null, vportDst = null;
-		int count = 0;
-		
-		log.debug("deleteLink(): {}", lt);
-		
-        try {
-            // get source port vertex
-         	String dpid = HexString.toHexString(lt.getSrc());
-         	short port = lt.getSrcPort();
-         	vportSrc = conn.utils().searchPort(conn, dpid, port);
-            
-            // get dst port vertex
-         	dpid = HexString.toHexString(lt.getDst());
-         	port = lt.getDstPort();
-         	vportDst = conn.utils().searchPort(conn, dpid, port);
-     		// FIXME: This needs to remove all edges
-         	
-         	if (vportSrc != null && vportDst != null) {
-
-   /*      		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
-         			log.debug("deleteLink(): {} in {} out {}", 
-         					new Object[]{e.getLabel(), e.getVertex(Direction.IN), e.getVertex(Direction.OUT)});
-         			if (e.getLabel().equals("link") && e.getVertex(Direction.IN).equals(vportDst)) {
-         				graph.removeEdge(e);
-         				count++;
-         			}
-         		}*/
-         		vportSrc.removeLink(vportDst);
-        		conn.endTx(Transaction.COMMIT);
-            	log.debug("deleteLink(): deleted edges src {} dst {}", new Object[]{
-            			lt, vportSrc, vportDst});
-            	
-            } else {
-            	log.error("deleteLink(): failed invalid vertices {} src {} dst {}", new Object[]{lt, vportSrc, vportDst});
-//            	conn.endTx(Transaction.ROLLBACK);
-            }
-         	
-        } catch (TitanException e) {
-            /*
-             * retry till we succeed?
-             */
-        	log.error("deleteLink(): titan exception {} {}", new Object[]{lt, e.toString()});
-        	e.printStackTrace();
-        }
-	}
-
-	// TODO: Fix me
-	@Override
-	public List<Link> getLinks(Long dpid, short port) {
-		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
-		IPortObject vportSrc, vportDst;
-    	List<Link> links = null;
-    	Link lt;
-    	
-		vportSrc = conn.utils().searchPort(conn, HexString.toHexString(dpid), port);
-		if (vportSrc != null) {
-			
-     		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
-     			if (e.getLabel().equals("link")) {
-     				break;
-     			}
-     		}
-		}
-     	return null;
-	}
-	
-	@Override
-	public void init(String conf) {
-		//TODO extract the DB location from properties
-	
-		this.conf = conf;
-		
-	}
-
-	@Override
-	public void deleteLinksOnPort(Long dpid, short port) {
-		// TODO Auto-generated method stub
-		
-	}
-
-	@Override
-	public List<Link> getLinks(String dpid) {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public List<Link> getActiveLinks() {
-
-		GraphDBConnection conn = GraphDBConnection.getInstance(this.conf);
-		
-		Iterable<ISwitchObject> switches = conn.utils().getActiveSwitches(conn);
-
-		List<Link> links = new ArrayList<Link>(); 
-		for (ISwitchObject sw : switches) {
-			GremlinPipeline<Vertex, Link> pipe = new GremlinPipeline<Vertex, Link>();
-			ExtractLink extractor = new ExtractLink();
-
-			pipe.start(sw.asVertex());
-			pipe.enablePath(true);
-			pipe.out("on").out("link").in("on").path().step(extractor);
-					
-			while (pipe.hasNext() ) {
-				Link l = pipe.next();
-				links.add(l);
-			}
-						
-		}
-		return links;
-	}
-	
-	static class ExtractLink implements PipeFunction<PathPipe<Vertex>, Link> {
-	
-		@Override
-		public Link compute(PathPipe<Vertex> pipe ) {
-			// TODO Auto-generated method stub
-			long s_dpid = 0;
-			long d_dpid = 0;
-			short s_port = 0;
-			short d_port = 0;
-			List<Vertex> V = new ArrayList<Vertex>();
-			V = pipe.next();
-			Vertex src_sw = V.get(0);
-			Vertex dest_sw = V.get(3);
-			Vertex src_port = V.get(1);
-			Vertex dest_port = V.get(2);
-			s_dpid = HexString.toLong((String) src_sw.getProperty("dpid"));
-			d_dpid = HexString.toLong((String) dest_sw.getProperty("dpid"));
-			s_port = (Short) src_port.getProperty("number");
-			d_port = (Short) dest_port.getProperty("number");
-			
-			Link l = new Link(s_dpid,s_port,d_dpid,d_port);
-			
-			return l;
-		}
-	}
-	
-	public void finalize() {
-		close();
-	}
-
-	@Override
-	public void close() {
-		// TODO Auto-generated method stub
-//		graph.shutdown();		
-	}
-
-
-}
diff --git a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerClient.java b/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerClient.java
deleted file mode 100644
index abed853..0000000
--- a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerClient.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package net.floodlightcontroller.packetstreamer;
-
-import net.floodlightcontroller.packetstreamer.thrift.*;
-
-import java.util.List;
-import java.util.ArrayList;
-
-import org.apache.thrift.TException;
-import org.apache.thrift.transport.TFramedTransport;
-import org.apache.thrift.transport.TTransport;
-import org.apache.thrift.transport.TSocket;
-import org.apache.thrift.transport.TTransportException;
-import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.protocol.TProtocol;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The PacketStreamer Sample Client.
- */
-public class PacketStreamerClient {
-    protected static Logger log = LoggerFactory.getLogger(PacketStreamerClient.class);
-
-    /** 
-     * Main function entry point;
-     * @param args
-     */
-    public static void main(String [] args) {
-        try {
-            int serverPort = Integer.parseInt(System.getProperty("net.floodlightcontroller.packetstreamer.port", "9090"));
-            TTransport transport;
-            transport = new TFramedTransport(new TSocket("localhost", serverPort));
-            transport.open();
-  
-
-            TProtocol protocol = new  TBinaryProtocol(transport);
-            PacketStreamer.Client client = new PacketStreamer.Client(protocol);
-
-            sendPackets(client, (short)2, OFMessageType.PACKET_IN, true);
-            log.debug("Terminate session1");
-            client.terminateSession("session1");
-
-            transport.close();
-        } catch (TException x) {
-            x.printStackTrace();
-        } 
-    }
-
-    /** 
-     * Send test packets of the given OFMessageType to the packetstreamer server;
-     * @param client Packetstreamer client object
-     * @param numPackets number of test packets to be sent
-     * @param ofType OFMessageType of the test packets
-     * @param sync true if send with synchronous interface, false for asynchronous interface
-     * @throws TException
-     */
-    private static void sendPackets(PacketStreamer.Client client, short numPackets, OFMessageType ofType, boolean sync) 
-    throws TException {
-        while (numPackets-- > 0) {
-            Message msg = new Message();
-            Packet packet = new Packet();
-    
-            List<String> sids = new ArrayList<String>();
-            sids.add("session1");
-            sids.add("session2");
-            msg.setSessionIDs(sids);
-            packet.setMessageType(ofType);
-            long sw_dpid = numPackets/40 + 1;
-            packet.setSwPortTuple(new SwitchPortTuple(sw_dpid, (short)(numPackets - (sw_dpid-1)*40)));
-    
-            String strData = "New data, sequence " + numPackets;
-            packet.setData(strData.getBytes());
-            msg.setPacket(packet);
-
-            try {
-                if (sync) {
-                      client.pushMessageSync(msg);
-                      log.debug("Send packet sync: " + msg.toString());
-                } else {
-                      client.pushMessageAsync(msg);
-                      log.debug("Send packet sync: " + msg.toString());
-                }
-            } catch (TTransportException e) {
-                log.error(e.toString());
-            }
-            
-            try {
-                Thread.sleep(100);
-            } catch (Exception e) {}
-        }
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerHandler.java b/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerHandler.java
deleted file mode 100644
index 903295e..0000000
--- a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerHandler.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package net.floodlightcontroller.packetstreamer;
-
-import net.floodlightcontroller.core.annotations.LogMessageCategory;
-import net.floodlightcontroller.core.annotations.LogMessageDoc;
-import net.floodlightcontroller.core.annotations.LogMessageDocs;
-import net.floodlightcontroller.packetstreamer.thrift.*;
-
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The PacketStreamer handler class that implements the service APIs.
- */
-@LogMessageCategory("OpenFlow Message Tracing")
-public class PacketStreamerHandler implements PacketStreamer.Iface {
-
-	/**
-	 * The queue wrapper class that contains the queue for the streamed packets.
-	 */
-    protected class SessionQueue {
-        protected BlockingQueue<ByteBuffer> pQueue;
-
-        /**
-         * The queue wrapper constructor
-         */
-        public SessionQueue() {
-            this.pQueue = new LinkedBlockingQueue<ByteBuffer>();
-        }
-
-        /**
-         * The access method to get to the internal queue.
-         */
-        public BlockingQueue<ByteBuffer> getQueue() {
-            return this.pQueue;
-        }
-    }
-    
-    /**
-     * The class logger object
-     */
-    protected static Logger log = 
-            LoggerFactory.getLogger(PacketStreamerServer.class);
-    
-    /**
-     * A sessionId-to-queue mapping
-     */
-    protected Map<String, SessionQueue> msgQueues;
-
-    /**
-     * The handler's constructor
-     */
-    public PacketStreamerHandler() {
-        this.msgQueues = new ConcurrentHashMap<String, SessionQueue>();
-    }
-
-    /**
-     * The implementation for getPackets() function.
-     * This is a blocking API.
-     * 
-     * @param sessionid
-     * @return A list of packets associated with the session
-     */
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Interrupted while waiting for session start",
-                explanation="The thread was interrupted waiting " +
-                     "for the packet streamer session to start",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER),
-        @LogMessageDoc(level="ERROR",
-                message="Interrupted while waiting for packets",
-                explanation="The thread was interrupted waiting " +
-                        "for packets",
-                recommendation=LogMessageDoc.CHECK_CONTROLLER)
-    })
-    public List<ByteBuffer> getPackets(String sessionid)
-            throws org.apache.thrift.TException {
-        List<ByteBuffer> packets = new ArrayList<ByteBuffer>();
-        int count = 0;
-        
-        while (!msgQueues.containsKey(sessionid) && count++ < 100) {
-            log.debug("Queue for session {} doesn't exist yet.", sessionid);
-            try {
-                Thread.sleep(100);    // Wait 100 ms to check again.
-            } catch (InterruptedException e) {
-                log.error("Interrupted while waiting for session start");
-            }
-        }
-
-        if (count < 100) {
-	        SessionQueue pQueue = msgQueues.get(sessionid);
-	        BlockingQueue<ByteBuffer> queue = pQueue.getQueue();
-	        // Block if queue is empty
-	        try {
-	            packets.add(queue.take());
-	            queue.drainTo(packets);
-	        } catch (InterruptedException e) {
-	            log.error("Interrupted while waiting for packets");
-	        }
-        }
-
-        return packets;
-    }
-
-    /**
-     * The implementation for pushMessageSync() function.
-     * 
-     * @param msg
-     * @return 1 for success, 0 for failure
-     * @throws TException
-     */
-    @Override
-    @LogMessageDocs({
-        @LogMessageDoc(level="ERROR",
-                message="Could not push empty message",
-                explanation="An empty message was sent to the packet streamer",
-                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG),
-        @LogMessageDoc(level="ERROR",
-                message="queue for session {sessionId} is null",
-                explanation="The queue for the packet streamer session " +
-                		"is missing",
-                recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
-    })
-
-    public int pushMessageSync(Message msg)
-            throws org.apache.thrift.TException {
-
-        if (msg == null) {
-            log.error("Could not push empty message");
-            return 0;
-        }
-
-        List<String> sessionids = msg.getSessionIDs();
-        for (String sid : sessionids) {
-            SessionQueue pQueue = null;
-
-            if (!msgQueues.containsKey(sid)) {
-                pQueue = new SessionQueue();
-                msgQueues.put(sid, pQueue);
-            } else {
-                pQueue = msgQueues.get(sid);
-            }
-
-            log.debug("pushMessageSync: SessionId: " + sid + 
-                      " Receive a message, " + msg.toString() + "\n");
-            ByteBuffer bb = ByteBuffer.wrap(msg.getPacket().getData());
-            //ByteBuffer dst = ByteBuffer.wrap(msg.getPacket().toString().getBytes());
-            BlockingQueue<ByteBuffer> queue = pQueue.getQueue();
-            if (queue != null) {
-                if (!queue.offer(bb)) {
-                    log.error("Failed to queue message for session: " + sid);
-                } else {
-                    log.debug("insert a message to session: " + sid);
-                }
-            } else {
-                log.error("queue for session {} is null", sid);
-            }
-        }
-
-        return 1;
-    }
-
-    /**
-     * The implementation for pushMessageAsync() function.
-     * 
-     * @param msg
-     * @throws TException
-     */
-    @Override
-    public void pushMessageAsync(Message msg)
-            throws org.apache.thrift.TException {
-        pushMessageSync(msg);
-        return;
-    }
-
-    /**
-     * The implementation for terminateSession() function.
-     * It removes the session to queue association.
-     * @param sessionid
-     * @throws TException
-     */
-    @Override
-    public void terminateSession(String sessionid)
-            throws org.apache.thrift.TException {
-        if (!msgQueues.containsKey(sessionid)) {
-            return;
-        }
-
-        SessionQueue pQueue = msgQueues.get(sessionid);
-
-        log.debug("terminateSession: SessionId: " + sessionid + "\n");
-        String data = "FilterTimeout";
-        ByteBuffer bb = ByteBuffer.wrap(data.getBytes());
-        BlockingQueue<ByteBuffer> queue = pQueue.getQueue();
-        if (queue != null) {
-            if (!queue.offer(bb)) {
-                log.error("Failed to queue message for session: " + sessionid);
-            }
-            msgQueues.remove(sessionid);
-        } else {
-            log.error("queue for session {} is null", sessionid);
-        }
-    }
-}
-
diff --git a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerServer.java b/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerServer.java
deleted file mode 100644
index 4a425e0..0000000
--- a/src/main/java/net/floodlightcontroller/packetstreamer/PacketStreamerServer.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package net.floodlightcontroller.packetstreamer;
-
-import org.apache.thrift.protocol.TBinaryProtocol;
-import org.apache.thrift.server.TServer;
-import org.apache.thrift.server.THsHaServer;
-import org.apache.thrift.transport.TFramedTransport;
-import org.apache.thrift.transport.TNonblockingServerSocket;
-import org.apache.thrift.transport.TNonblockingServerTransport;
-
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.floodlightcontroller.core.annotations.LogMessageCategory;
-// Generated code
-import net.floodlightcontroller.packetstreamer.thrift.*;
-
-/**
- * The PacketStreamer Server that brokers the packet streaming service.
- */
-@LogMessageCategory("OpenFlow Message Tracing")
-public class PacketStreamerServer {
-    protected static Logger log = LoggerFactory.getLogger(PacketStreamerServer.class);
-    protected static int port = 9090;
-    protected static PacketStreamerHandler handler;
-    protected static PacketStreamer.Processor<PacketStreamerHandler> processor;
-
-    
-    /** 
-     * Main function entry point;
-     * @param args
-     */
-    public static void main(String [] args) {
-        try {
-            port = Integer.parseInt(System.getProperty("net.floodlightcontroller.packetstreamer.port", "9090"));
-            
-            handler = new PacketStreamerHandler();
-            processor = new PacketStreamer.Processor<PacketStreamerHandler>(handler);
-
-            Runnable simple = new Runnable() {
-                public void run() {
-                    hshaServer(processor);
-                }
-            };
-
-            new Thread(simple).start();
-        } catch (Exception x) {
-            x.printStackTrace();
-        }
-    }
-
-    
-    /** 
-     * The function to create a thrift Half-Sync and Half-Async Server.
-     * @param processor
-     */
-    public static void hshaServer(PacketStreamer.Processor<PacketStreamerHandler> processor) {
-        try {
-            TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(port);
-            THsHaServer.Args args = new THsHaServer.Args(serverTransport);
-            args.processor(processor);
-            args.transportFactory(new TFramedTransport.Factory());
-            args.protocolFactory(new TBinaryProtocol.Factory(true, true));
-            TServer server = new THsHaServer(args);
-    
-            log.info("Starting the packetstreamer hsha server on port {} ...", port);
-            server.serve();
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/restclient/RestClient.java b/src/main/java/net/floodlightcontroller/restclient/RestClient.java
deleted file mode 100644
index 541b42d..0000000
--- a/src/main/java/net/floodlightcontroller/restclient/RestClient.java
+++ /dev/null
@@ -1,142 +0,0 @@
-package net.floodlightcontroller.restclient;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import net.sf.json.JSONArray;
-import net.sf.json.JSONObject;
-import net.sf.json.JSONSerializer;
-
-
-public class RestClient {
-
-	public static void get (String str) {
-		
-		if (str == null)
-			return;
-	
-		try {
-	 
-			URL url = new URL(str);
-			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-			conn.setRequestMethod("GET");
-			conn.setRequestProperty("Accept", "application/json");
-	 
-			if (conn.getResponseCode() != 200) {
-				throw new RuntimeException("Failed : HTTP error code : "
-						+ conn.getResponseCode());
-			}
-	 
-			if (conn.getContentType().equals("application/json")) 
-			{	}else{
-				System.out.print("The content received is not json format!");				
-			}		
-			
-		 BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 
-		 StringBuffer res = new StringBuffer();
-		 String line;
-		 while ((line = br.readLine()) != null) {
-			 	res.append(line);
-		 	}	   
-		 
-		 String res2=res.toString().replaceAll("\"", "'");
-		 JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(res2);  
-		 JSONArray rib_json_array = jsonObj.getJSONArray("rib");
-		 String router_id = jsonObj.getString("router-id");
-		       
-		 int size = rib_json_array.size();
-		 System.out.print("size:"+size+"\n");
-		 for (int j = 0; j < size; j++) {
-        JSONObject second_json_object = rib_json_array.getJSONObject(j);
-        String prefix = second_json_object.getString("prefix");
-        String nexthop = second_json_object.getString("nexthop");
-              			
-     		//insert each rib entry into the local rib;
-        RestClient.post("http://127.0.0.1:8090/wm/bgp/"+router_id+"/"+prefix+"/"+nexthop);
-          
-        
-        
-		 }
-		 br.close();
-		 conn.disconnect();
-
-		} catch (MalformedURLException e) {
-
-			e.printStackTrace();
-
-		} catch (IOException e) {
-
-			e.printStackTrace();
-
-		}
-	}
-	
-public static void post (String str) {
-		
-		if (str == null)
-			return;
-	
-		try {
-	 
-			URL url = new URL(str);
-			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-			conn.setDoOutput(true);
-			conn.setRequestMethod("POST");
-			conn.setRequestProperty("Content-Type", "application/json");		
-	 
-			if (conn.getResponseCode() != 200) {
-				throw new RuntimeException("Failed : HTTP error code : "
-						+ conn.getResponseCode());
-			}
-					
-			conn.disconnect();
-
-		} catch (MalformedURLException e) {
-
-			e.printStackTrace();
-
-		} catch (IOException e) {
-
-			e.printStackTrace();
-
-		}
-	}
-	
-
-public static void delete (String str) {
-	
-	if (str == null)
-		return;
-
-	try {
- 
-		URL url = new URL(str);
-		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
-		conn.setRequestMethod("DELETE");
-		conn.setRequestProperty("Accept", "application/json");
-		
- 
-		if (conn.getResponseCode() != 200) {
-			throw new RuntimeException("Failed : HTTP error code : "
-					+ conn.getResponseCode());
-		}
- 
-		conn.disconnect();
-
-	} catch (MalformedURLException e) {
-
-		e.printStackTrace();
-
-	} catch (IOException e) {
-
-		e.printStackTrace();
-
-	}
-}
-	
-	
-}
diff --git a/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
index 2ca8483..c158fdd 100644
--- a/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
+++ b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
@@ -6,12 +6,18 @@
 import java.util.List;
 import java.util.Map;
 
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+
 import org.restlet.Application;
 import org.restlet.Component;
 import org.restlet.Context;
 import org.restlet.Request;
 import org.restlet.Response;
 import org.restlet.Restlet;
+import org.restlet.Server;
 import org.restlet.data.Protocol;
 import org.restlet.data.Reference;
 import org.restlet.data.Status;
@@ -24,17 +30,13 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-
 public class RestApiServer
     implements IFloodlightModule, IRestApiService {
     protected static Logger logger = LoggerFactory.getLogger(RestApiServer.class);
     protected List<RestletRoutable> restlets;
     protected FloodlightModuleContext fmlContext;
     protected int restPort = 8080;
+    protected String numThreads = null;
     
     // ***********
     // Application
@@ -98,7 +100,11 @@
             // Start listening for REST requests
             try {
                 final Component component = new Component();
-                component.getServers().add(Protocol.HTTP, restPort);
+                Server server = component.getServers().add(Protocol.HTTP, restPort);
+                if (numThreads != null){
+                	logger.debug("Setting number of REST API threads to {}", numThreads);
+                	server.getContext().getParameters().add("defaultThreads", numThreads);
+                }
                 component.getClients().add(Protocol.CLAP);
                 component.getDefaultHost().attach(this);
                 component.start();
@@ -179,6 +185,11 @@
             restPort = Integer.parseInt(port);
         }
         logger.debug("REST port set to {}", restPort);
+        
+        String numThreads = configOptions.get("dispatcherthreads");
+        if (numThreads != null) {
+        	this.numThreads = numThreads;
+        }
     }
 
     @Override
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
index cc62e82..31032c9 100644
--- a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
@@ -5,7 +5,7 @@
 import java.util.Set;
 
 import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
 
 public interface ITopologyService extends IFloodlightService  {
 
diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
index 6ac8f29..4983529 100644
--- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
+++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java
@@ -18,16 +18,6 @@
     protected short portId; // switch port id
 
     /**
-     * A copy constructor for NodePortTuple.
-     *
-     * @param other the object to copy the state from.
-     */
-    public NodePortTuple(NodePortTuple other) {
-	this.nodeId = other.nodeId;
-	this.portId = other.portId;
-    }
-
-    /**
      * Creates a NodePortTuple
      * @param nodeId The DPID of the switch
      * @param portId The port of the switch
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index ba17483..a47a5f2 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -28,8 +28,6 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
 import net.floodlightcontroller.counter.ICounterStoreService;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
 import net.floodlightcontroller.packet.BSN;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.LLDP;
@@ -39,6 +37,8 @@
 import net.floodlightcontroller.routing.Route;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.topology.web.TopologyWebRoutable;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
 
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFPacketIn;
@@ -871,7 +871,8 @@
             if (log.isTraceEnabled()) {
                 log.trace("Applying update: {}", update);
             }
-            if (update.getOperation() == UpdateOperation.LINK_UPDATED) {
+            if (update.getOperation() == UpdateOperation.LINK_UPDATED ||
+            		update.getOperation() == UpdateOperation.LINK_ADDED	) {
                 addOrUpdateLink(update.getSrc(), update.getSrcPort(),
                                 update.getDst(), update.getDstPort(),
                                 update.getType());
diff --git a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
index 7989413..4f844b2 100644
--- a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
@@ -3,8 +3,9 @@
 import org.restlet.Context;
 import org.restlet.routing.Router;
 
-import net.floodlightcontroller.linkdiscovery.web.LinksResource;
 import net.floodlightcontroller.restserver.RestletRoutable;
+import net.onrc.onos.ofcontroller.linkdiscovery.web.LinksResource;
+import net.onrc.onos.ofcontroller.topology.web.RouteResource;
 
 public class TopologyWebRoutable implements RestletRoutable {
     /**
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryAction.java b/src/main/java/net/floodlightcontroller/util/FlowEntryAction.java
deleted file mode 100644
index 1fc1783..0000000
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryAction.java
+++ /dev/null
@@ -1,1015 +0,0 @@
-package net.floodlightcontroller.util;
-
-import net.floodlightcontroller.util.IPv4;
-import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.util.Port;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-/**
- * The class representing a single Flow Entry action.
- *
- * A set of Flow Entry actions need to be applied to each packet.
- */
-public class FlowEntryAction {
-    /**
-     * Special action values.
-     *
-     * Those values are taken as-is from the OpenFlow-v1.0.0 specification
-     * (pp 21-22).
-     */
-    public enum ActionValues {
-	ACTION_OUTPUT		((short)0x0),	// Output to switch port
-	ACTION_SET_VLAN_VID	((short)0x1),	// Set the 802.1q VLAN id
-	ACTION_SET_VLAN_PCP	((short)0x2),	// Set the 802.1q priority
-	ACTION_STRIP_VLAN	((short)0x3),	// Strip the 802.1q header
-	ACTION_SET_DL_SRC	((short)0x4),	// Ethernet source address
-	ACTION_SET_DL_DST	((short)0x5),	// Ethernet destination address
-	ACTION_SET_NW_SRC	((short)0x6),	// IP source address
-	ACTION_SET_NW_DST	((short)0x7),	// IP destination address
-	ACTION_SET_NW_TOS	((short)0x8),	// IP ToS (DSCP field, 6 bits)
-	ACTION_SET_TP_SRC	((short)0x9),	// TCP/UDP source port
-	ACTION_SET_TP_DST	((short)0xa),	// TCP/UDP destination port
-	ACTION_ENQUEUE		((short)0xb),	// Output to queue on port
-	ACTION_VENDOR		((short)0xffff); // Vendor-specific
-
-	private final short value;	// The value
-
-	/**
-	 * Constructor for a given value.
-	 *
-	 * @param value the value to use for the initialization.
-	 */
-	private ActionValues(short value) {
-	    this.value = value;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_OUTPUT: Output to switch port.
-     */
-    public class ActionOutput {
-	private Port port;	// Output port
-	private short maxLen;	// Max. length (in bytes) to send to controller
-				// if the port is set to PORT_CONTROLLER
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionOutput() {
-	    this.port = null;
-	    this.maxLen = 0;
-	}
-
-
-	/**
-	 * Constructor for a given output port and maximum length.
-	 *
-	 * @param port the output port to set.
-	 * @param maxLen the maximum length (in bytes) to send to controller
-	 * if the port is set to PORT_CONTROLLER.
-	 */
-	public ActionOutput(Port port, short maxLen) {
-	    this.port = port;
-	    this.maxLen = maxLen;
-	}
-
-	/**
-	 * Constructor for a given output port.
-	 *
-	 * @param port the output port to set.
-	 */
-	public ActionOutput(Port port) {
-	    this.port = port;
-	    this.maxLen = 0;
-	}
-
-	/**
-	 * Get the output port.
-	 *
-	 * @return the output port.
-	 */
-	@JsonProperty("port")
-	public Port port() {
-	    return this.port;
-	}
-
-	/**
-	 * Get the maximum length (in bytes) to send to controller if the
-	 * port is set to PORT_CONTROLLER.
-	 *
-	 * @return the maximum length (in bytes) to send to controller if the
-	 * port is set to PORT_CONTROLLER.
-	 */
-	@JsonProperty("maxLen")
-	public short maxLen() {
-	    return this.maxLen;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [port=XXX maxLen=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "port=" + port.toString();
-	    ret += " maxLen=" + maxLen;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_VLAN_VID: Set the 802.1q VLAN id
-     */
-    public class ActionSetVlanId {
-	private short vlanId;		// The VLAN ID to set
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetVlanId() {
-	    this.vlanId = 0;
-	}
-
-	/**
-	 * Constructor for a given VLAN ID.
-	 *
-	 * @param vlanId the VLAN ID to set.
-	 */
-	public ActionSetVlanId(short vlanId) {
-	    this.vlanId = vlanId;
-	}
-
-	/**
-	 * Get the VLAN ID.
-	 *
-	 * @return the VLAN ID.
-	 */
-	@JsonProperty("vlanId")
-	public short vlanId() {
-	    return this.vlanId;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [vlanId=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "vlanId=" + this.vlanId;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_VLAN_PCP: Set the 802.1q priority
-     */
-    public class ActionSetVlanPriority {
-	private byte vlanPriority;	// The VLAN priority to set
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetVlanPriority() {
-	    this.vlanPriority = 0;
-	}
-
-	/**
-	 * Constructor for a given VLAN priority.
-	 *
-	 * @param vlanPriority the VLAN priority to set.
-	 */
-	public ActionSetVlanPriority(byte vlanPriority) {
-	    this.vlanPriority = vlanPriority;
-	}
-
-	/**
-	 * Get the VLAN priority.
-	 *
-	 * @return the VLAN priority.
-	 */
-	@JsonProperty("vlanPriority")
-	public byte vlanPriority() {
-	    return this.vlanPriority;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [vlanPriority=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "vlanPriority=" + this.vlanPriority;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_STRIP_VLAN: Strip the 802.1q header
-     */
-    public class ActionStripVlan {
-	private boolean stripVlan;	// If true, strip the VLAN header
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionStripVlan() {
-	    this.stripVlan = false;
-	}
-
-	/**
-	 * Constructor for a given boolean flag.
-	 *
-	 * @param stripVlan if true, strip the VLAN header.
-	 */
-	public ActionStripVlan(boolean stripVlan) {
-	    this.stripVlan = stripVlan;
-	}
-
-	/**
-	 * Get the boolean flag whether the VLAN header should be stripped.
-	 *
-	 * @return the boolean flag whether the VLAN header should be stripped.
-	 */
-	@JsonProperty("stripVlan")
-	public boolean stripVlan() {
-	    return this.stripVlan;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [stripVlan=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "stripVlan=" + this.stripVlan;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_DL_SRC and ACTION_SET_DL_DST:
-     * Set the Ethernet source/destination address.
-     */
-    public class ActionSetEthernetAddr {
-	private MACAddress addr;	// The MAC address to set
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetEthernetAddr() {
-	    this.addr = null;
-	}
-
-	/**
-	 * Constructor for a given MAC address.
-	 *
-	 * @param addr the MAC address to set.
-	 */
-	public ActionSetEthernetAddr(MACAddress addr) {
-	    this.addr = addr;
-	}
-
-	/**
-	 * Get the MAC address.
-	 *
-	 * @return the MAC address.
-	 */
-	@JsonProperty("addr")
-	public MACAddress addr() {
-	    return this.addr;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [addr=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "addr=" + addr.toString();
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_NW_SRC and ACTION_SET_NW_DST:
-     * Set the IPv4 source/destination address.
-     */
-    public class ActionSetIPv4Addr {
-	private IPv4 addr;		// The IPv4 address to set
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetIPv4Addr() {
-	    this.addr = null;
-	}
-
-	/**
-	 * Constructor for a given IPv4 address.
-	 *
-	 * @param addr the IPv4 address to set.
-	 */
-	public ActionSetIPv4Addr(IPv4 addr) {
-	    this.addr = addr;
-	}
-
-	/**
-	 * Get the IPv4 address.
-	 *
-	 * @return the IPv4 address.
-	 */
-	@JsonProperty("addr")
-	public IPv4 addr() {
-	    return this.addr;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [addr=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "addr=" + addr.toString();
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_NW_TOS:
-     * Set the IP ToS (DSCP field, 6 bits).
-     */
-    public class ActionSetIpToS {
-	private byte ipToS;	// The IP ToS to set DSCP field, 6 bits)
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetIpToS() {
-	    this.ipToS = 0;
-	}
-
-	/**
-	 * Constructor for a given IP ToS (DSCP field, 6 bits).
-	 *
-	 * @param ipToS the IP ToS (DSCP field, 6 bits) to set.
-	 */
-	public ActionSetIpToS(byte ipToS) {
-	    this.ipToS = ipToS;
-	}
-
-	/**
-	 * Get the IP ToS (DSCP field, 6 bits).
-	 *
-	 * @return the IP ToS (DSCP field, 6 bits).
-	 */
-	@JsonProperty("ipToS")
-	public byte ipToS() {
-	    return this.ipToS;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [ipToS=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "ipToS=" + ipToS;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_SET_TP_SRC and ACTION_SET_TP_DST:
-     * Set the TCP/UDP source/destination port.
-     */
-    public class ActionSetTcpUdpPort {
-	private short port;		// The TCP/UDP port to set
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionSetTcpUdpPort() {
-	    this.port = 0;
-	}
-
-	/**
-	 * Constructor for a given TCP/UDP port.
-	 *
-	 * @param port the TCP/UDP port to set.
-	 */
-	public ActionSetTcpUdpPort(short port) {
-	    this.port = port;
-	}
-
-	/**
-	 * Get the TCP/UDP port.
-	 *
-	 * @return the TCP/UDP port.
-	 */
-	@JsonProperty("port")
-	public short port() {
-	    return this.port;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [port=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "port=" + port;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    /**
-     * Action structure for ACTION_ENQUEUE: Output to queue on port.
-     */
-    public class ActionEnqueue {
-	private Port port;	// Port that queue belongs. Should
-				// refer to a valid physical port
-				// (i.e. < PORT_MAX) or PORT_IN_PORT
-	private int queueId;	// Where to enqueue the packets
-
-	/**
-	 * Default constructor.
-	 */
-	public ActionEnqueue() {
-	    this.port = null;
-	    this.queueId = 0;
-	}
-
-	/**
-	 * Constructor for a given port and queue ID.
-	 *
-	 * @param port the port to set.
-	 * @param queueId the queue ID on the port.
-	 */
-	public ActionEnqueue(Port port, int queueId) {
-	    this.port = port;
-	    this.queueId = queueId;
-	}
-
-	/**
-	 * Get the port.
-	 *
-	 * @return the port.
-	 */
-	@JsonProperty("port")
-	public Port port() {
-	    return this.port;
-	}
-
-	/**
-	 * Get the queue ID.
-	 *
-	 * @return the queue ID.
-	 */
-	@JsonProperty("queueId")
-	public int queueId() {
-	    return this.queueId;
-	}
-
-	/**
-	 * Convert the action to a string.
-	 *
-	 * The string has the following form:
-	 *  [port=XXX queueId=XXX]
-	 *
-	 * @return the action as a string.
-	 */
-	@Override
-	public String toString() {
-	    String ret = "[";
-	    ret += "port=" + port.toString();
-	    ret += " queueId=" + queueId;
-	    ret += "]";
-
-	    return ret;
-	}
-    }
-
-    private ActionValues actionType;	// The action type
-
-    //
-    // The actions.
-    // NOTE: Only one action should be set.
-    //
-    private ActionOutput actionOutput;
-    private ActionSetVlanId actionSetVlanId;
-    private ActionSetVlanPriority actionSetVlanPriority;
-    private ActionStripVlan actionStripVlan;
-    private ActionSetEthernetAddr actionSetEthernetSrcAddr;
-    private ActionSetEthernetAddr actionSetEthernetDstAddr;
-    private ActionSetIPv4Addr actionSetIPv4SrcAddr;
-    private ActionSetIPv4Addr actionSetIPv4DstAddr;
-    private ActionSetIpToS actionSetIpToS;
-    private ActionSetTcpUdpPort actionSetTcpUdpSrcPort;
-    private ActionSetTcpUdpPort actionSetTcpUdpDstPort;
-    private ActionEnqueue actionEnqueue;
-
-    /**
-     * Default constructor.
-     */
-    public FlowEntryAction() {
-	actionType = ActionValues.ACTION_VENDOR;	// XXX: Initial value
-    }
-
-    /**
-     * Get the action type.
-     *
-     * @return the action type.
-     */
-    @JsonProperty("actionType")
-    public ActionValues actionType() { return actionType; }
-
-    /**
-     * Get the output action.
-     *
-     * @return the output action.
-     */
-    @JsonProperty("actionOutput")
-    public ActionOutput actionOutput() { return actionOutput; }
-
-    /**
-     * Set the output action on a port.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionOutput")
-    public void setActionOutput(ActionOutput action) {
-	actionOutput = action;
-	actionType = ActionValues.ACTION_OUTPUT;
-    }
-
-    /**
-     * Set the output action on a port.
-     *
-     * @param port the output port to set.
-     */
-    public void setActionOutput(Port port) {
-	actionOutput = new ActionOutput(port);
-	actionType = ActionValues.ACTION_OUTPUT;
-    }
-
-    /**
-     * Set the output action to controller.
-     *
-     * @param maxLen the maximum length (in bytes) to send to controller.
-     */
-    public void setActionOutputToController(short maxLen) {
-	Port port = new Port(Port.PortValues.PORT_CONTROLLER);
-	actionOutput = new ActionOutput(port, maxLen);
-	actionType = ActionValues.ACTION_OUTPUT;
-    }
-
-    /**
-     * Get the action to set the VLAN ID.
-     *
-     * @return the action to set the VLAN ID.
-     */
-    @JsonProperty("actionSetVlanId")
-    public ActionSetVlanId actionSetVlanId() { return actionSetVlanId; }
-
-    /**
-     * Set the action to set the VLAN ID.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetVlanId")
-    public void setActionSetVlanId(ActionSetVlanId action) {
-	actionSetVlanId = action;
-	actionType = ActionValues.ACTION_SET_VLAN_VID;
-    }
-
-    /**
-     * Set the action to set the VLAN ID.
-     *
-     * @param vlanId the VLAN ID to set.
-     */
-    public void setActionSetVlanId(short vlanId) {
-	actionSetVlanId = new ActionSetVlanId(vlanId);
-	actionType = ActionValues.ACTION_SET_VLAN_VID;
-    }
-
-    /**
-     * Get the action to set the VLAN priority.
-     *
-     * @return the action to set the VLAN priority.
-     */
-    @JsonProperty("actionSetVlanPriority")
-    public ActionSetVlanPriority actionSetVlanPriority() {
-	return actionSetVlanPriority;
-    }
-
-    /**
-     * Set the action to set the VLAN priority.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetVlanPriority")
-    public void setActionSetVlanPriority(ActionSetVlanPriority action) {
-	actionSetVlanPriority = action;
-	actionType = ActionValues.ACTION_SET_VLAN_PCP;
-    }
-
-    /**
-     * Set the action to set the VLAN priority.
-     *
-     * @param vlanPriority the VLAN priority to set.
-     */
-    public void setActionSetVlanPriority(byte vlanPriority) {
-	actionSetVlanPriority = new ActionSetVlanPriority(vlanPriority);
-	actionType = ActionValues.ACTION_SET_VLAN_PCP;
-    }
-
-    /**
-     * Get the action to strip the VLAN header.
-     *
-     * @return the action to strip the VLAN header.
-     */
-    @JsonProperty("actionStripVlan")
-    public ActionStripVlan actionStripVlan() {
-	return actionStripVlan;
-    }
-
-    /**
-     * Set the action to strip the VLAN header.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionStripVlan")
-    public void setActionStripVlan(ActionStripVlan action) {
-	actionStripVlan = action;
-	actionType = ActionValues.ACTION_STRIP_VLAN;
-    }
-
-    /**
-     * Set the action to strip the VLAN header.
-     *
-     * @param stripVlan if true, strip the VLAN header.
-     */
-    public void setActionStripVlan(boolean stripVlan) {
-	actionStripVlan = new ActionStripVlan(stripVlan);
-	actionType = ActionValues.ACTION_STRIP_VLAN;
-    }
-
-    /**
-     * Get the action to set the Ethernet source address.
-     *
-     * @return the action to set the Ethernet source address.
-     */
-    @JsonProperty("actionSetEthernetSrcAddr")
-    public ActionSetEthernetAddr actionSetEthernetSrcAddr() {
-	return actionSetEthernetSrcAddr;
-    }
-
-    /**
-     * Set the action to set the Ethernet source address.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetEthernetSrcAddr")
-    public void setActionSetEthernetSrcAddr(ActionSetEthernetAddr action) {
-	actionSetEthernetSrcAddr = action;
-	actionType = ActionValues.ACTION_SET_DL_SRC;
-    }
-
-    /**
-     * Set the action to set the Ethernet source address.
-     *
-     * @param addr the MAC address to set as the Ethernet source address.
-     */
-    public void setActionSetEthernetSrcAddr(MACAddress addr) {
-	actionSetEthernetSrcAddr = new ActionSetEthernetAddr(addr);
-	actionType = ActionValues.ACTION_SET_DL_SRC;
-    }
-
-    /**
-     * Get the action to set the Ethernet destination address.
-     *
-     * @return the action to set the Ethernet destination address.
-     */
-    @JsonProperty("actionSetEthernetDstAddr")
-    public ActionSetEthernetAddr actionSetEthernetDstAddr() {
-	return actionSetEthernetDstAddr;
-    }
-
-    /**
-     * Set the action to set the Ethernet destination address.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetEthernetDstAddr")
-    public void setActionSetEthernetDstAddr(ActionSetEthernetAddr action) {
-	actionSetEthernetDstAddr = action;
-	actionType = ActionValues.ACTION_SET_DL_DST;
-    }
-
-    /**
-     * Set the action to set the Ethernet destination address.
-     *
-     * @param addr the MAC address to set as the Ethernet destination address.
-     */
-    public void setActionSetEthernetDstAddr(MACAddress addr) {
-	actionSetEthernetDstAddr = new ActionSetEthernetAddr(addr);
-	actionType = ActionValues.ACTION_SET_DL_DST;
-    }
-
-    /**
-     * Get the action to set the IPv4 source address.
-     *
-     * @return the action to set the IPv4 source address.
-     */
-    @JsonProperty("actionSetIPv4SrcAddr")
-    public ActionSetIPv4Addr actionSetIPv4SrcAddr() {
-	return actionSetIPv4SrcAddr;
-    }
-
-    /**
-     * Set the action to set the IPv4 source address.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetIPv4SrcAddr")
-    public void setActionSetIPv4SrcAddr(ActionSetIPv4Addr action) {
-	actionSetIPv4SrcAddr = action;
-	actionType = ActionValues.ACTION_SET_NW_SRC;
-    }
-
-    /**
-     * Set the action to set the IPv4 source address.
-     *
-     * @param addr the IPv4 address to set as the IPv4 source address.
-     */
-    public void setActionSetIPv4SrcAddr(IPv4 addr) {
-	actionSetIPv4SrcAddr = new ActionSetIPv4Addr(addr);
-	actionType = ActionValues.ACTION_SET_NW_SRC;
-    }
-
-    /**
-     * Get the action to set the IPv4 destination address.
-     *
-     * @return the action to set the IPv4 destination address.
-     */
-    @JsonProperty("actionSetIPv4DstAddr")
-    public ActionSetIPv4Addr actionSetIPv4DstAddr() {
-	return actionSetIPv4DstAddr;
-    }
-
-    /**
-     * Set the action to set the IPv4 destination address.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetIPv4DstAddr")
-    public void setActionSetIPv4DstAddr(ActionSetIPv4Addr action) {
-	actionSetIPv4DstAddr = action;
-	actionType = ActionValues.ACTION_SET_NW_DST;
-    }
-
-    /**
-     * Set the action to set the IPv4 destination address.
-     *
-     * @param addr the IPv4 address to set as the IPv4 destination address.
-     */
-    public void setActionSetIPv4DstAddr(IPv4 addr) {
-	actionSetIPv4DstAddr = new ActionSetIPv4Addr(addr);
-	actionType = ActionValues.ACTION_SET_NW_DST;
-    }
-
-    /**
-     * Get the action to set the IP ToS (DSCP field, 6 bits).
-     *
-     * @return the action to set the IP ToS (DSCP field, 6 bits).
-     */
-    @JsonProperty("actionSetIpToS")
-    public ActionSetIpToS actionSetIpToS() {
-	return actionSetIpToS;
-    }
-
-    /**
-     * Set the action to set the IP ToS (DSCP field, 6 bits).
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetIpToS")
-    public void setActionSetIpToS(ActionSetIpToS action) {
-	actionSetIpToS = action;
-	actionType = ActionValues.ACTION_SET_NW_TOS;
-    }
-
-    /**
-     * Set the action to set the IP ToS (DSCP field, 6 bits).
-     *
-     * @param ipToS the IP ToS (DSCP field, 6 bits) to set.
-     */
-    public void setActionSetIpToS(byte ipToS) {
-	actionSetIpToS = new ActionSetIpToS(ipToS);
-	actionType = ActionValues.ACTION_SET_NW_TOS;
-    }
-
-    /**
-     * Get the action to set the TCP/UDP source port.
-     *
-     * @return the action to set the TCP/UDP source port.
-     */
-    @JsonProperty("actionSetTcpUdpSrcPort")
-    public ActionSetTcpUdpPort actionSetTcpUdpSrcPort() {
-	return actionSetTcpUdpSrcPort;
-    }
-
-    /**
-     * Set the action to set the TCP/UDP source port.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetTcpUdpSrcPort")
-    public void setActionSetTcpUdpSrcPort(ActionSetTcpUdpPort action) {
-	actionSetTcpUdpSrcPort = action;
-	actionType = ActionValues.ACTION_SET_TP_SRC;
-    }
-
-    /**
-     * Set the action to set the TCP/UDP source port.
-     *
-     * @param port the TCP/UDP port to set as the TCP/UDP source port.
-     */
-    public void setActionSetTcpUdpSrcPort(short port) {
-	actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(port);
-	actionType = ActionValues.ACTION_SET_TP_SRC;
-    }
-
-    /**
-     * Get the action to set the TCP/UDP destination port.
-     *
-     * @return the action to set the TCP/UDP destination port.
-     */
-    @JsonProperty("actionSetTcpUdpDstPort")
-    public ActionSetTcpUdpPort actionSetTcpUdpDstPort() {
-	return actionSetTcpUdpDstPort;
-    }
-
-    /**
-     * Set the action to set the TCP/UDP destination port.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionSetTcpUdpDstPort")
-    public void setActionSetTcpUdpDstPort(ActionSetTcpUdpPort action) {
-	actionSetTcpUdpDstPort = action;
-	actionType = ActionValues.ACTION_SET_TP_DST;
-    }
-
-    /**
-     * Set the action to set the TCP/UDP destination port.
-     *
-     * @param port the TCP/UDP port to set as the TCP/UDP destination port.
-     */
-    public void setActionSetTcpUdpDstPort(short port) {
-	actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(port);
-	actionType = ActionValues.ACTION_SET_TP_DST;
-    }
-
-    /**
-     * Get the action to output to queue on a port.
-     *
-     * @return the action to output to queue on a port.
-     */
-    @JsonProperty("actionEnqueue")
-    public ActionEnqueue actionEnqueue() { return actionEnqueue; }
-
-    /**
-     * Set the action to output to queue on a port.
-     *
-     * @param action the action to set.
-     */
-    @JsonProperty("actionEnqueue")
-    public void setActionEnqueue(ActionEnqueue action) {
-	actionEnqueue = action;
-	actionType = ActionValues.ACTION_ENQUEUE;
-    }
-
-    /**
-     * Set the action to output to queue on a port.
-     *
-     * @param port the port to set.
-     * @param int queueId the queue ID to set.
-     */
-    public void setActionEnqueue(Port port, int queueId) {
-	actionEnqueue = new ActionEnqueue(port, queueId);
-	actionType = ActionValues.ACTION_ENQUEUE;
-    }
-
-    /**
-     * Convert the set of actions to a string.
-     *
-     * The string has the following form:
-     *  [type=XXX action=XXX]
-     *
-     * @return the set of actions as a string.
-     */
-    @Override
-    public String toString() {
-	String ret = "[";
-	ret += "type=" + actionType;
-	switch (actionType) {
-	case ACTION_OUTPUT:
-	    ret += " action=" + actionOutput.toString();
-	    break;
-	case ACTION_SET_VLAN_VID:
-	    ret += " action=" + actionSetVlanId.toString();
-	    break;
-	case ACTION_SET_VLAN_PCP:
-	    ret += " action=" + actionSetVlanPriority.toString();
-	    break;
-	case ACTION_STRIP_VLAN:
-	    ret += " action=" + actionStripVlan.toString();
-	    break;
-	case ACTION_SET_DL_SRC:
-	    ret += " action=" + actionSetEthernetSrcAddr.toString();
-	    break;
-	case ACTION_SET_DL_DST:
-	    ret += " action=" + actionSetEthernetDstAddr.toString();
-	    break;
-	case ACTION_SET_NW_SRC:
-	    ret += " action=" + actionSetIPv4SrcAddr.toString();
-	    break;
-	case ACTION_SET_NW_DST:
-	    ret += " action=" + actionSetIPv4DstAddr.toString();
-	    break;
-	case ACTION_SET_NW_TOS:
-	    ret += " action=" + actionSetIpToS.toString();
-	    break;
-	case ACTION_SET_TP_SRC:
-	    ret += " action=" + actionSetTcpUdpSrcPort.toString();
-	    break;
-	case ACTION_SET_TP_DST:
-	    ret += " action=" + actionSetTcpUdpDstPort.toString();
-	    break;
-	case ACTION_ENQUEUE:
-	    ret += " action=" + actionEnqueue.toString();
-	    break;
-	}
-	ret += "]";
-
-	return ret;
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowPath.java b/src/main/java/net/floodlightcontroller/util/FlowPath.java
deleted file mode 100644
index b171b88..0000000
--- a/src/main/java/net/floodlightcontroller/util/FlowPath.java
+++ /dev/null
@@ -1,223 +0,0 @@
-package net.floodlightcontroller.util;
-
-import java.util.ArrayList;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.util.CallerId;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.FlowEntryMatch;
-import net.floodlightcontroller.util.FlowId;
-
-import org.codehaus.jackson.annotate.JsonProperty;
-
-/**
- * The class representing the Flow Path.
- */
-public class FlowPath implements Comparable<FlowPath> {
-    private FlowId flowId;		// The Flow ID
-    private CallerId installerId;	// The Caller ID of the path installer
-    private DataPath dataPath;		// The data path
-    private FlowEntryMatch flowEntryMatch; // Common Flow Entry Match for all
-					// Flow Entries
-
-    /**
-     * Default constructor.
-     */
-    public FlowPath() {
-	dataPath = new DataPath();
-    }
-
-    /**
-     * Constructor to instantiate from object in Network Map
-     */
-    public FlowPath(IFlowPath flowObj) {
-    	dataPath = new DataPath();
-    	this.setFlowId(new FlowId(flowObj.getFlowId()));
-    	this.setInstallerId(new CallerId(flowObj.getInstallerId()));
-    	this.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
-    	this.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
-    	this.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
-    	this.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
-	//
-	// Extract the match conditions that are common for all Flow Entries
-	//
-	{
-    	    FlowEntryMatch match = new FlowEntryMatch();
-    	    Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
-    	    if (matchEthernetFrameType != null)
-    		match.enableEthernetFrameType(matchEthernetFrameType);
-    	    String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
-    	    if (matchSrcIPv4Net != null)
-    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
-    	    String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
-    	    if (matchDstIPv4Net != null)
-    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
-    	    String matchSrcMac = flowObj.getMatchSrcMac();
-    	    if (matchSrcMac != null)
-    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
-    	    String matchDstMac = flowObj.getMatchDstMac();
-    	    if (matchDstMac != null)
-    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
-    	    this.setFlowEntryMatch(match);
-	}
-
-    	//
-    	// Extract all Flow Entries
-    	//
-    	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
-    	for (IFlowEntry flowEntryObj : flowEntries) {
-    	    FlowEntry flowEntry = new FlowEntry();
-    	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
-    	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
-
-    	    //
-    	    // Extract the match conditions
-    	    //
-    	    FlowEntryMatch match = new FlowEntryMatch();
-    	    Short matchInPort = flowEntryObj.getMatchInPort();
-    	    if (matchInPort != null)
-    		match.enableInPort(new Port(matchInPort));
-    	    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
-    	    if (matchEthernetFrameType != null)
-    		match.enableEthernetFrameType(matchEthernetFrameType);
-    	    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
-    	    if (matchSrcIPv4Net != null)
-    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
-    	    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
-    	    if (matchDstIPv4Net != null)
-    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
-    	    String matchSrcMac = flowEntryObj.getMatchSrcMac();
-    	    if (matchSrcMac != null)
-    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
-    	    String matchDstMac = flowEntryObj.getMatchDstMac();
-    	    if (matchDstMac != null)
-    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
-    	    flowEntry.setFlowEntryMatch(match);
-
-    	    //
-    	    // Extract the actions
-    	    //
-    	    ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
-    	    Short actionOutputPort = flowEntryObj.getActionOutput();
-    	    if (actionOutputPort != null) {
-    		FlowEntryAction action = new FlowEntryAction();
-    		action.setActionOutput(new Port(actionOutputPort));
-    		actions.add(action);
-    	    }
-    	    flowEntry.setFlowEntryActions(actions);
-
-    	    String userState = flowEntryObj.getUserState();
-    	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
-    	    String switchState = flowEntryObj.getSwitchState();
-    	    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
-    	    //
-    	    // TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
-    	    // and FlowEntryErrorState.
-    	    //
-    	    this.dataPath().flowEntries().add(flowEntry);
-    	}
-    }
-
-    /**
-     * Get the flow path Flow ID.
-     *
-     * @return the flow path Flow ID.
-     */
-    @JsonProperty("flowId")
-    public FlowId flowId() { return flowId; }
-
-    /**
-     * Set the flow path Flow ID.
-     *
-     * @param flowId the flow path Flow ID to set.
-     */
-    @JsonProperty("flowId")
-    public void setFlowId(FlowId flowId) {
-	this.flowId = flowId;
-    }
-
-    /**
-     * Get the Caller ID of the flow path installer.
-     *
-     * @return the Caller ID of the flow path installer.
-     */
-    @JsonProperty("installerId")
-    public CallerId installerId() { return installerId; }
-
-    /**
-     * Set the Caller ID of the flow path installer.
-     *
-     * @param installerId the Caller ID of the flow path installer.
-     */
-    @JsonProperty("installerId")
-    public void setInstallerId(CallerId installerId) {
-	this.installerId = installerId;
-    }
-
-    /**
-     * Get the flow path's data path.
-     *
-     * @return the flow path's data path.
-     */
-    @JsonProperty("dataPath")
-    public DataPath dataPath() { return dataPath; }
-
-    /**
-     * Set the flow path's data path.
-     *
-     * @param dataPath the flow path's data path to set.
-     */
-    @JsonProperty("dataPath")
-    public void setDataPath(DataPath dataPath) {
-	this.dataPath = dataPath;
-    }
-
-    /**
-     * Get the flow path's match conditions common for all Flow Entries.
-     *
-     * @return the flow path's match conditions common for all Flow Entries.
-     */
-    @JsonProperty("flowEntryMatch")
-    public FlowEntryMatch flowEntryMatch() { return flowEntryMatch; }
-
-    /**
-     * Set the flow path's match conditions common for all Flow Entries.
-     *
-     * @param flowEntryMatch the flow path's match conditions common for all
-     * Flow Entries.
-     */
-    @JsonProperty("flowEntryMatch")
-    public void setFlowEntryMatch(FlowEntryMatch flowEntryMatch) {
-	this.flowEntryMatch = flowEntryMatch;
-    }
-
-    /**
-     * Convert the flow path to a string.
-     *
-     * The string has the following form:
-     *  [flowId=XXX installerId=XXX dataPath=XXX]
-     *
-     * @return the flow path as a string.
-     */
-    @Override
-    public String toString() {
-	String ret = "[flowId=" + this.flowId.toString();
-	ret += " installerId=" + this.installerId.toString();
-	if (dataPath != null)
-	    ret += " dataPath=" + this.dataPath.toString();
-	if (flowEntryMatch != null)
-	    ret += " flowEntryMatch=" + this.flowEntryMatch.toString();
-	ret += "]";
-	return ret;
-    }
-    
-    /**
-     * CompareTo method to order flowPath by Id
-     */
-    @Override
-    public int compareTo(FlowPath f) {
-    	return (int) (this.flowId.value() - f.flowId.value());
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/util/MACAddress.java b/src/main/java/net/floodlightcontroller/util/MACAddress.java
index 743dc5b..88dbda2 100644
--- a/src/main/java/net/floodlightcontroller/util/MACAddress.java
+++ b/src/main/java/net/floodlightcontroller/util/MACAddress.java
@@ -2,10 +2,9 @@
 
 import java.util.Arrays;
 
-import net.floodlightcontroller.util.serializers.MACAddressDeserializer;
-import net.floodlightcontroller.util.serializers.MACAddressSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.MACAddressDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.MACAddressSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/HostResource.java b/src/main/java/net/floodlightcontroller/virtualnetwork/HostResource.java
deleted file mode 100644
index 6021e3d..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/HostResource.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.io.IOException;
-
-import net.floodlightcontroller.util.MACAddress;
-
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.map.MappingJsonFactory;
-import org.restlet.data.Status;
-import org.restlet.resource.Delete;
-import org.restlet.resource.Put;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class HostResource extends org.restlet.resource.ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(HostResource.class);
-    
-    public class HostDefinition {
-        String port = null; // Logical port name
-        String guid = null; // Network ID
-        String mac = null; // MAC Address
-        String attachment = null; // Attachment name
-    }
-    
-    protected void jsonToHostDefinition(String json, HostDefinition host) throws IOException {
-        MappingJsonFactory f = new MappingJsonFactory();
-        JsonParser jp;
-        
-        try {
-            jp = f.createJsonParser(json);
-        } catch (JsonParseException e) {
-            throw new IOException(e);
-        }
-        
-        jp.nextToken();
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw new IOException("Expected START_OBJECT");
-        }
-        
-        while (jp.nextToken() != JsonToken.END_OBJECT) {
-            if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
-                throw new IOException("Expected FIELD_NAME");
-            }
-            
-            String n = jp.getCurrentName();
-            jp.nextToken();
-            if (jp.getText().equals("")) 
-                continue;
-            else if (n.equals("attachment")) {
-                while (jp.nextToken() != JsonToken.END_OBJECT) {
-                    String field = jp.getCurrentName();
-                    if (field.equals("id")) {
-                        host.attachment = jp.getText();
-                    } else if (field.equals("mac")) {
-                        host.mac = jp.getText();
-                    }
-                }
-            }
-        }
-        
-        jp.close();
-    }
-    
-    @Put
-    public String addHost(String postData) {
-        IVirtualNetworkService vns =
-                (IVirtualNetworkService)getContext().getAttributes().
-                    get(IVirtualNetworkService.class.getCanonicalName());
-        HostDefinition host = new HostDefinition();
-        host.port = (String) getRequestAttributes().get("port");
-        host.guid = (String) getRequestAttributes().get("network");
-        try {
-            jsonToHostDefinition(postData, host);
-        } catch (IOException e) {
-            log.error("Could not parse JSON {}", e.getMessage());
-        }
-        vns.addHost(MACAddress.valueOf(host.mac), host.guid, host.port);
-        setStatus(Status.SUCCESS_OK);
-        return "{\"status\":\"ok\"}";
-    }
-    
-    
-    @Delete
-    public String deleteHost() {
-        String port = (String) getRequestAttributes().get("port");
-        IVirtualNetworkService vns =
-                (IVirtualNetworkService)getContext().getAttributes().
-                    get(IVirtualNetworkService.class.getCanonicalName());
-        vns.deleteHost(null, port);
-        setStatus(Status.SUCCESS_OK);
-        return "{\"status\":\"ok\"}";
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/IVirtualNetworkService.java b/src/main/java/net/floodlightcontroller/virtualnetwork/IVirtualNetworkService.java
deleted file mode 100644
index 4304a33..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/IVirtualNetworkService.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.util.Collection;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.util.MACAddress;
-
-public interface IVirtualNetworkService extends IFloodlightService {
-    /**
-     * Creates a new virtual network. This can also be called
-     * to modify a virtual network. To update a network you specify the GUID
-     * and the fields you want to update.
-     * @param network The network name. Must be unique.
-     * @param guid The ID of the network. Must be unique.
-     * @param gateway The IP address of the network gateway, null if none.
-     */
-    public void createNetwork(String guid, String network, Integer gateway);
-    
-    /**
-     * Deletes a virtual network.
-     * @param guid The ID (not name) of virtual network to delete.
-     */
-    public void deleteNetwork(String guid);
-    
-    /**
-     * Adds a host to a virtual network. If a mapping already exists the
-     * new one will override the old mapping.
-     * @param mac The MAC address of the host to add.
-     * @param network The network to add the host to.
-     * @param port The logical port name to attach the host to. Must be unique.
-     */
-    public void addHost(MACAddress mac, String network, String port); 
-    
-    /**
-     * Deletes a host from a virtual network. Either the MAC or Port must
-     * be specified.
-     * @param mac The MAC address to delete.
-     * @param port The logical port the host is attached to.
-     */
-    public void deleteHost(MACAddress mac, String port);
-    
-    /**
-     * Return list of all virtual networks.
-     * @return Collection <VirtualNetwork>
-     */
-    public Collection <VirtualNetwork> listNetworks();
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/NetworkResource.java b/src/main/java/net/floodlightcontroller/virtualnetwork/NetworkResource.java
deleted file mode 100644
index 2efe52a..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/NetworkResource.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.io.IOException;
-import java.util.Collection;
-
-import net.floodlightcontroller.packet.IPv4;
-
-import org.codehaus.jackson.JsonParseException;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.map.MappingJsonFactory;
-import org.restlet.data.Status;
-import org.restlet.resource.Delete;
-import org.restlet.resource.Get;
-import org.restlet.resource.Post;
-import org.restlet.resource.Put;
-import org.restlet.resource.ServerResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetworkResource extends ServerResource {
-    protected static Logger log = LoggerFactory.getLogger(NetworkResource.class);
-    
-    public class NetworkDefinition {
-        public String name = null;
-        public String guid = null;
-        public String gateway = null;
-    }
-    
-    protected void jsonToNetworkDefinition(String json, NetworkDefinition network) throws IOException {
-        MappingJsonFactory f = new MappingJsonFactory();
-        JsonParser jp;
-        
-        try {
-            jp = f.createJsonParser(json);
-        } catch (JsonParseException e) {
-            throw new IOException(e);
-        }
-        
-        jp.nextToken();
-        if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
-            throw new IOException("Expected START_OBJECT");
-        }
-        
-        while (jp.nextToken() != JsonToken.END_OBJECT) {
-            if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
-                throw new IOException("Expected FIELD_NAME");
-            }
-            
-            String n = jp.getCurrentName();
-            jp.nextToken();
-            if (jp.getText().equals("")) 
-                continue;
-            else if (n.equals("network")) {
-                while (jp.nextToken() != JsonToken.END_OBJECT) {
-                    String field = jp.getCurrentName();
-                    if (field.equals("name")) {
-                        network.name = jp.getText();
-                    } else if (field.equals("gateway")) {
-                    	String gw = jp.getText();
-                    	if ((gw != null) && (!gw.equals("null")))
-                    		network.gateway = gw;
-                    } else if (field.equals("id")) {
-                    	network.guid = jp.getText();
-                    } else {
-                        log.warn("Unrecognized field {} in " +
-                        		"parsing network definition", 
-                        		jp.getText());
-                    }
-                }
-            }
-        }
-        
-        jp.close();
-    }
-    
-    @Get("json")
-    public Collection <VirtualNetwork> retrieve() {
-        IVirtualNetworkService vns =
-                (IVirtualNetworkService)getContext().getAttributes().
-                    get(IVirtualNetworkService.class.getCanonicalName());
-        
-        return vns.listNetworks();               
-    }
-    
-    @Put
-    @Post
-    public String createNetwork(String postData) {        
-        NetworkDefinition network = new NetworkDefinition();
-        try {
-            jsonToNetworkDefinition(postData, network);
-        } catch (IOException e) {
-            log.error("Could not parse JSON {}", e.getMessage());
-        }
-        
-        // We try to get the ID from the URI only if it's not
-        // in the POST data 
-        if (network.guid == null) {
-	        String guid = (String) getRequestAttributes().get("network");
-	        if ((guid != null) && (!guid.equals("null")))
-	        	network.guid = guid;
-        }
-        
-        IVirtualNetworkService vns =
-                (IVirtualNetworkService)getContext().getAttributes().
-                    get(IVirtualNetworkService.class.getCanonicalName());
-        
-        Integer gw = null;
-        if (network.gateway != null) {
-            try {
-                gw = IPv4.toIPv4Address(network.gateway);
-            } catch (IllegalArgumentException e) {
-                log.warn("Could not parse gateway {} as IP for network {}, setting as null",
-                         network.gateway, network.name);
-                network.gateway = null;
-            }
-        }
-        vns.createNetwork(network.guid, network.name, gw);
-        setStatus(Status.SUCCESS_OK);
-        return "{\"status\":\"ok\"}";
-    }
-    
-    @Delete
-    public String deleteNetwork() {
-        IVirtualNetworkService vns =
-                (IVirtualNetworkService)getContext().getAttributes().
-                    get(IVirtualNetworkService.class.getCanonicalName());
-        String guid = (String) getRequestAttributes().get("network");
-        vns.deleteNetwork(guid);
-        setStatus(Status.SUCCESS_OK);
-        return "{\"status\":\"ok\"}";
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/NoOp.java b/src/main/java/net/floodlightcontroller/virtualnetwork/NoOp.java
deleted file mode 100644
index a184a95..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/NoOp.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import org.restlet.data.Status;
-import org.restlet.resource.Get;
-import org.restlet.resource.Post;
-import org.restlet.resource.Put;
-import org.restlet.resource.ServerResource;
-
-public class NoOp extends ServerResource {
-	/**
-	 * Does nothing and returns 200 OK with a status message
-	 * @return status: ok
-	 */
-	@Get
-	@Put
-	@Post
-	public String noOp(String postdata) {
-		setStatus(Status.SUCCESS_OK);
-        return "{\"status\":\"ok\"}";
-	}
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetwork.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetwork.java
deleted file mode 100644
index f5dfb21..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetwork.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
-
-import net.floodlightcontroller.util.MACAddress;
-
-/**
- * Data structure for storing and outputing information of a virtual network created
- * by VirtualNetworkFilter
- * 
- * @author KC Wang
- */
-
-@JsonSerialize(using=VirtualNetworkSerializer.class)
-public class VirtualNetwork{
-    protected String name; // network name
-    protected String guid; // network id
-    protected String gateway; // network gateway
-    protected Collection<MACAddress> hosts; // array of hosts explicitly added to this network
-
-    /**
-     * Constructor requires network name and id
-     * @param name: network name
-     * @param guid: network id 
-     */
-    public VirtualNetwork(String name, String guid) {
-        this.name = name;
-        this.guid = guid;
-        this.gateway = null;
-        this.hosts = new ArrayList<MACAddress>();
-        return;        
-    }
-
-    /**
-     * Sets network name
-     * @param gateway: IP address as String
-     */
-    public void setName(String name){
-        this.name = name;
-        return;                
-    }
-    
-    /**
-     * Sets network gateway IP address
-     * @param gateway: IP address as String
-     */
-    public void setGateway(String gateway){
-        this.gateway = gateway;
-        return;                
-    }
-    
-    /**
-     * Adds a host to this network record
-     * @param host: MAC address as MACAddress
-     */
-    public void addHost(MACAddress host){
-        this.hosts.add(host);
-        return;        
-    }
-    
-    /**
-     * Removes a host from this network record
-     * @param host: MAC address as MACAddress
-     * @return boolean: true: removed, false: host not found
-     */
-    public boolean removeHost(MACAddress host){
-        Iterator<MACAddress> iter = this.hosts.iterator();
-        while(iter.hasNext()){
-            MACAddress element = iter.next();
-            if(element.equals(host) ){
-                //assuming MAC address for host is unique
-                iter.remove();
-                return true;
-            }                
-        }
-        return false;
-    }
-    
-    /**
-     * Removes all hosts from this network record
-     */
-    public void clearHosts(){
-        this.hosts.clear();
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java
deleted file mode 100644
index 012dfb6..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilter.java
+++ /dev/null
@@ -1,521 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.util.HexString;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.util.AppCookie;
-import net.floodlightcontroller.devicemanager.IDevice;
-import net.floodlightcontroller.devicemanager.IDeviceListener;
-import net.floodlightcontroller.devicemanager.IDeviceService;
-import net.floodlightcontroller.packet.DHCP;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.routing.ForwardingBase;
-import net.floodlightcontroller.util.MACAddress;
-
-/**
- * A simple Layer 2 (MAC based) network virtualization module. This module allows
- * you to create simple L2 networks (host + gateway) and will drop traffic if
- * they are not on the same virtual network.
- * 
- * LIMITATIONS
- * - This module does not allow overlapping of IPs or MACs
- * - You can only have 1 gateway per virtual network (can be shared)
- * - There is filtering of multicast/broadcast traffic
- * - All DHCP traffic will be allowed, regardless of unicast/broadcast
- * 
- * @author alexreimers
- */
-public class VirtualNetworkFilter 
-    implements IFloodlightModule, IVirtualNetworkService, IOFMessageListener, IDeviceListener {
-    protected static Logger log = LoggerFactory.getLogger(VirtualNetworkFilter.class);
-    
-    private final short APP_ID = 20;
-    
-    // Our dependencies
-    IFloodlightProviderService floodlightProvider;
-    IRestApiService restApi;
-    IDeviceService deviceService;
-    
-    // Our internal state
-    protected Map<String, VirtualNetwork> vNetsByGuid; // List of all created virtual networks 
-    protected Map<String, String> nameToGuid; // Logical name -> Network ID
-    protected Map<String, Integer> guidToGateway; // Network ID -> Gateway IP
-    protected Map<Integer, Set<String>> gatewayToGuid; // Gateway IP -> Network ID
-    protected Map<MACAddress, Integer> macToGateway; // Gateway MAC -> Gateway IP
-    protected Map<MACAddress, String> macToGuid; // Host MAC -> Network ID
-    protected Map<String, MACAddress> portToMac; // Host MAC -> logical port name
-    
-    /**
-     * Adds a gateway to a virtual network.
-     * @param guid The ID (not name) of the network.
-     * @param ip The IP addresses of the gateway.
-     */
-    protected void addGateway(String guid, Integer ip) {
-        if (ip.intValue() != 0) {
-        	if (log.isDebugEnabled())
-        		log.debug("Adding {} as gateway for GUID {}",
-        				IPv4.fromIPv4Address(ip), guid);
-        	
-            guidToGateway.put(guid, ip);
-            if (vNetsByGuid.get(guid) != null)
-                vNetsByGuid.get(guid).setGateway(IPv4.fromIPv4Address(ip));
-            if (gatewayToGuid.containsKey(ip)) {
-                Set<String> gSet = gatewayToGuid.get(ip);
-                gSet.add(guid);
-            } else {
-                Set<String> gSet = Collections.synchronizedSet(new HashSet<String>());
-                gSet.add(guid);
-                gatewayToGuid.put(ip, gSet);
-            }
-        }
-    }
-    
-    /**
-     * Deletes a gateway for a virtual network.
-     * @param guid The ID (not name) of the network to delete
-     * the gateway for.
-     */
-    protected void deleteGateway(String guid) {
-        Integer gwIp = guidToGateway.remove(guid);
-        if (gwIp == null) return;
-        Set<String> gSet = gatewayToGuid.get(gwIp);
-        gSet.remove(guid);
-        if(vNetsByGuid.get(guid)!=null)
-            vNetsByGuid.get(guid).setGateway(null);
-    }
-    
-    // IVirtualNetworkService
-    
-    @Override
-    public void createNetwork(String guid, String network, Integer gateway) {
-        if (log.isDebugEnabled()) {
-            String gw = null;
-            try {
-                gw = IPv4.fromIPv4Address(gateway);
-            } catch (Exception e) {
-                // fail silently
-            }
-            log.debug("Creating network {} with ID {} and gateway {}", 
-                      new Object[] {network, guid, gw});
-        }
-        
-        if (!nameToGuid.isEmpty()) {
-            // We have to iterate all the networks to handle name/gateway changes
-            for (Entry<String, String> entry : nameToGuid.entrySet()) {
-                if (entry.getValue().equals(guid)) {
-                    nameToGuid.remove(entry.getKey());
-                    break;
-                }
-            }
-        }
-        nameToGuid.put(network, guid);
-        if (vNetsByGuid.containsKey(guid))
-            vNetsByGuid.get(guid).setName(network); //network already exists, just updating name
-        else
-            vNetsByGuid.put(guid, new VirtualNetwork(network, guid)); //new network
-        
-        // If they don't specify a new gateway the old one will be preserved
-        if ((gateway != null) && (gateway != 0)) {
-            addGateway(guid, gateway);
-            if(vNetsByGuid.get(guid)!=null)
-                vNetsByGuid.get(guid).setGateway(IPv4.fromIPv4Address(gateway));
-        }
-    }
-
-    @Override
-    public void deleteNetwork(String guid) {
-        String name = null;
-        if (nameToGuid.isEmpty()) {
-            log.warn("Could not delete network with ID {}, network doesn't exist",
-                     guid);
-            return;
-        }
-        for (Entry<String, String> entry : nameToGuid.entrySet()) {
-            if (entry.getValue().equals(guid)) {
-                name = entry.getKey();
-                break;
-            }
-            log.warn("Could not delete network with ID {}, network doesn't exist",
-                     guid);
-        }
-        
-        if (log.isDebugEnabled()) 
-            log.debug("Deleting network with name {} ID {}", name, guid);
-        
-        nameToGuid.remove(name);
-        deleteGateway(guid);
-        if(vNetsByGuid.get(guid)!=null){
-            vNetsByGuid.get(guid).clearHosts();
-            vNetsByGuid.remove(guid);
-        }
-        Collection<MACAddress> deleteList = new ArrayList<MACAddress>();
-        for (MACAddress host : macToGuid.keySet()) {
-            if (macToGuid.get(host).equals(guid)) {
-                deleteList.add(host);
-            }
-        }
-        for (MACAddress mac : deleteList) {
-            if (log.isDebugEnabled()) {
-                log.debug("Removing host {} from network {}", 
-                          HexString.toHexString(mac.toBytes()), guid);
-            }
-            macToGuid.remove(mac);
-            for (Entry<String, MACAddress> entry : portToMac.entrySet()) {
-                if (entry.getValue().equals(mac)) {
-                    portToMac.remove(entry.getKey());
-                    break;
-                }
-            }
-        }
-    }
-
-    @Override
-    public void addHost(MACAddress mac, String guid, String port) {
-        if (guid != null) {
-            if (log.isDebugEnabled()) {
-                log.debug("Adding {} to network ID {} on port {}",
-                          new Object[] {mac, guid, port});
-            }
-            // We ignore old mappings
-            macToGuid.put(mac, guid);
-            portToMac.put(port, mac);
-            if(vNetsByGuid.get(guid)!=null)
-                vNetsByGuid.get(guid).addHost(new MACAddress(mac.toBytes()));
-        } else {
-            log.warn("Could not add MAC {} to network ID {} on port {}, the network does not exist",
-                     new Object[] {mac, guid, port});
-        }
-    }
-
-    @Override
-    public void deleteHost(MACAddress mac, String port) {
-        if (log.isDebugEnabled()) {
-            log.debug("Removing host {} from port {}", mac, port);
-        }
-        if (mac == null && port == null) return;
-        if (port != null) {
-            MACAddress host = portToMac.remove(port);
-            if(vNetsByGuid.get(macToGuid.get(host)) != null)
-                vNetsByGuid.get(macToGuid.get(host)).removeHost(host);
-            macToGuid.remove(host);
-        } else if (mac != null) {
-            if (!portToMac.isEmpty()) {
-                for (Entry<String, MACAddress> entry : portToMac.entrySet()) {
-                    if (entry.getValue().equals(mac)) {
-                        if(vNetsByGuid.get(macToGuid.get(entry.getValue())) != null)
-                            vNetsByGuid.get(macToGuid.get(entry.getValue())).removeHost(entry.getValue());
-                        portToMac.remove(entry.getKey());
-                        macToGuid.remove(entry.getValue());
-                        return;
-                    }
-                }
-            }
-        }
-    }
-    
-    // IFloodlightModule
-    
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IVirtualNetworkService.class);
-        return l;
-    }
-
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService>
-            getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-            IFloodlightService> m = 
-                new HashMap<Class<? extends IFloodlightService>,
-                    IFloodlightService>();
-        m.put(IVirtualNetworkService.class, this);
-        return m;
-    }
-
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
-        Collection<Class<? extends IFloodlightService>> l = 
-                new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(IFloodlightProviderService.class);
-        l.add(IRestApiService.class);
-        l.add(IDeviceService.class);
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)  
-                                 throws FloodlightModuleException {
-        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-        restApi = context.getServiceImpl(IRestApiService.class);
-        deviceService = context.getServiceImpl(IDeviceService.class);
-        
-        vNetsByGuid = new ConcurrentHashMap<String, VirtualNetwork>();
-        nameToGuid = new ConcurrentHashMap<String, String>();
-        guidToGateway = new ConcurrentHashMap<String, Integer>();
-        gatewayToGuid = new ConcurrentHashMap<Integer, Set<String>>();
-        macToGuid = new ConcurrentHashMap<MACAddress, String>();
-        portToMac = new ConcurrentHashMap<String, MACAddress>();
-        macToGateway = new ConcurrentHashMap<MACAddress, Integer>();
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-        floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        restApi.addRestletRoutable(new VirtualNetworkWebRoutable());
-        deviceService.addListener(this);
-    }
-
-    // IOFMessageListener
-    
-    @Override
-    public String getName() {
-        return "virtualizer";
-    }
-
-    @Override
-    public boolean isCallbackOrderingPrereq(OFType type, String name) {
-        // Link discovery should go before us so we don't block LLDPs
-        return (type.equals(OFType.PACKET_IN) && 
-        		(name.equals("linkdiscovery") || (name.equals("devicemanager"))));
-    }
-
-    @Override
-    public boolean isCallbackOrderingPostreq(OFType type, String name) {
-        // We need to go before forwarding
-        return (type.equals(OFType.PACKET_IN) && name.equals("forwarding"));
-    }
-
-    @Override
-    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
-        switch (msg.getType()) {
-            case PACKET_IN:
-                return processPacketIn(sw, (OFPacketIn)msg, cntx);
-            default:
-            	break;
-        }
-        log.warn("Received unexpected message {}", msg);
-        return Command.CONTINUE;
-    }
-    
-    /**
-     * Checks whether the frame is destined to or from a gateway.
-     * @param frame The ethernet frame to check.
-     * @return True if it is to/from a gateway, false otherwise.
-     */
-    protected boolean isDefaultGateway(Ethernet frame) {
-    	if (macToGateway.containsKey(frame.getSourceMAC()))
-    		return true;
-    	
-    	Integer gwIp = macToGateway.get(frame.getDestinationMAC());
-    	if (gwIp != null) {
-    		MACAddress host = frame.getSourceMAC();
-    		String srcNet = macToGuid.get(host);
-    		if (srcNet != null) {
-	    		Integer gwIpSrcNet = guidToGateway.get(srcNet);
-	    		if ((gwIpSrcNet != null) && (gwIp.equals(gwIpSrcNet)))
-	    			return true;
-    		}
-    	}
-
-    	return false;
-    }
-    
-    /**
-     * Checks to see if two MAC Addresses are on the same network.
-     * @param m1 The first MAC.
-     * @param m2 The second MAC.
-     * @return True if they are on the same virtual network,
-     * 		   false otherwise.
-     */
-    protected boolean oneSameNetwork(MACAddress m1, MACAddress m2) {
-        String net1 = macToGuid.get(m1);
-        String net2 = macToGuid.get(m2);
-        if (net1 == null) return false;
-        if (net2 == null) return false;
-        return net1.equals(net2);
-    }
-    
-    /**
-     * Checks to see if an Ethernet frame is a DHCP packet.
-     * @param frame The Ethernet frame.
-     * @return True if it is a DHCP frame, false otherwise.
-     */
-    protected boolean isDhcpPacket(Ethernet frame) {
-        IPacket payload = frame.getPayload(); // IP
-        if (payload == null) return false;
-        IPacket p2 = payload.getPayload(); // TCP or UDP
-        if (p2 == null) return false;
-        IPacket p3 = p2.getPayload(); // Application
-        if ((p3 != null) && (p3 instanceof DHCP)) return true;
-        return false;
-    }
-    
-    /**
-     * Processes an OFPacketIn message and decides if the OFPacketIn should be dropped
-     * or the processing should continue.
-     * @param sw The switch the PacketIn came from.
-     * @param msg The OFPacketIn message from the switch.
-     * @param cntx The FloodlightContext for this message.
-     * @return Command.CONTINUE if processing should be continued, Command.STOP otherwise.
-     */
-    protected Command processPacketIn(IOFSwitch sw, OFPacketIn msg, FloodlightContext cntx) {
-        Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, 
-                                              IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
-        Command ret = Command.STOP;
-        String srcNetwork = macToGuid.get(eth.getSourceMAC());
-        // If the host is on an unknown network we deny it.
-        // We make exceptions for ARP and DHCP.
-        if (eth.isBroadcast() || eth.isMulticast() || isDefaultGateway(eth) || isDhcpPacket(eth)) {
-        	ret = Command.CONTINUE;
-        } else if (srcNetwork == null) {
-            log.trace("Blocking traffic from host {} because it is not attached to any network.",
-                      HexString.toHexString(eth.getSourceMACAddress()));
-            ret = Command.STOP;
-        } else if (oneSameNetwork(eth.getSourceMAC(), eth.getDestinationMAC())) {
-            // if they are on the same network continue
-            ret = Command.CONTINUE;
-        }
-        
-        if (log.isTraceEnabled())
-        	log.trace("Results for flow between {} and {} is {}",
-        			new Object[] {eth.getSourceMAC(), eth.getDestinationMAC(), ret});
-        /*
-         * TODO - figure out how to still detect gateways while using
-         * drop mods 
-        if (ret == Command.STOP) {
-            if (!(eth.getPayload() instanceof ARP))
-            	doDropFlow(sw, msg, cntx);
-        }
-        */
-        return ret;
-    }
-    
-    /**
-     * Writes a FlowMod to a switch that inserts a drop flow.
-     * @param sw The switch to write the FlowMod to.
-     * @param pi The corresponding OFPacketIn. Used to create the OFMatch structure.
-     * @param cntx The FloodlightContext that gets passed to the switch.
-     */
-    protected void doDropFlow(IOFSwitch sw, OFPacketIn pi, FloodlightContext cntx) {
-        if (log.isTraceEnabled()) {
-            log.trace("doDropFlow pi={} srcSwitch={}",
-                    new Object[] { pi, sw });
-        }
-
-        if (sw == null) {
-            log.warn("Switch is null, not installing drop flowmod for PacketIn {}", pi);
-            return;
-        }
-
-        // Create flow-mod based on packet-in and src-switch
-        OFFlowMod fm = 
-            (OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD);
-        OFMatch match = new OFMatch();
-        match.loadFromPacket(pi.getPacketData(), pi.getInPort());
-        List<OFAction> actions = new ArrayList<OFAction>(); // no actions = drop
-        long cookie = AppCookie.makeCookie(APP_ID, 0);
-        fm.setCookie(cookie)
-        .setIdleTimeout(ForwardingBase.FLOWMOD_DEFAULT_IDLE_TIMEOUT)
-        .setHardTimeout(ForwardingBase.FLOWMOD_DEFAULT_HARD_TIMEOUT)
-        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
-        .setMatch(match)
-        .setActions(actions)
-        .setLengthU(OFFlowMod.MINIMUM_LENGTH);
-        fm.setFlags(OFFlowMod.OFPFF_SEND_FLOW_REM);
-        try {
-            if (log.isTraceEnabled()) {
-                log.trace("write drop flow-mod srcSwitch={} match={} " + 
-                          "pi={} flow-mod={}",
-                          new Object[] {sw, match, pi, fm});
-            }
-            sw.write(fm, cntx);
-        } catch (IOException e) {
-            log.error("Failure writing drop flow mod", e);
-        }
-        return;
-    }
-
-    // IDeviceListener
-    
-	@Override
-	public void deviceAdded(IDevice device) {
-		if (device.getIPv4Addresses() == null) return;
-		for (Integer i : device.getIPv4Addresses()) {
-			if (gatewayToGuid.containsKey(i)) {
-				MACAddress mac = MACAddress.valueOf(device.getMACAddress());
-				if (log.isDebugEnabled())
-					log.debug("Adding MAC {} with IP {} a a gateway",
-							HexString.toHexString(mac.toBytes()),
-							IPv4.fromIPv4Address(i));
-				macToGateway.put(mac, i);
-			}
-		}
-	}
-
-	@Override
-	public void deviceRemoved(IDevice device) {
-		// if device is a gateway remove
-		MACAddress mac = MACAddress.valueOf(device.getMACAddress());
-		if (macToGateway.containsKey(mac)) {
-			if (log.isDebugEnabled())
-				log.debug("Removing MAC {} as a gateway",
-						HexString.toHexString(mac.toBytes()));
-			macToGateway.remove(mac);
-		}
-	}
-
-	@Override
-	public void deviceIPV4AddrChanged(IDevice device) {
-		// add or remove entry as gateway
-		deviceAdded(device);
-	}
-
-	@Override
-	public void deviceMoved(IDevice device) {
-		// ignore
-	}
-	
-	@Override
-	public void deviceVlanChanged(IDevice device) {
-		// ignore
-	}
-
-    @Override
-    public Collection <VirtualNetwork> listNetworks() {
-        return vNetsByGuid.values();
-        
-    }
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkSerializer.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkSerializer.java
deleted file mode 100644
index 6902f6c..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkSerializer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import java.io.IOException;
-import java.util.Iterator;
-
-import net.floodlightcontroller.util.MACAddress;
-
-import org.codehaus.jackson.JsonGenerator;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.map.JsonSerializer;
-import org.codehaus.jackson.map.SerializerProvider;
-
-/**
- * Serialize a VirtualNetwork object
- * @author KC Wang
- */
-public class VirtualNetworkSerializer extends JsonSerializer<VirtualNetwork> {
-
-    @Override
-    public void serialize(VirtualNetwork vNet, JsonGenerator jGen,
-            SerializerProvider serializer) throws IOException,
-            JsonProcessingException {
-        jGen.writeStartObject();
-        
-        jGen.writeStringField("name", vNet.name);
-        jGen.writeStringField("guid", vNet.guid);
-        jGen.writeStringField("gateway", vNet.gateway);
-
-        jGen.writeArrayFieldStart("mac");
-        Iterator<MACAddress> hit = vNet.hosts.iterator();
-        while (hit.hasNext())
-            jGen.writeString(hit.next().toString());
-        jGen.writeEndArray();
-        
-        jGen.writeEndObject();
-    }
-
-}
diff --git a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkWebRoutable.java b/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkWebRoutable.java
deleted file mode 100644
index 61769ec..0000000
--- a/src/main/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkWebRoutable.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import org.restlet.Context;
-import org.restlet.Restlet;
-import org.restlet.routing.Router;
-
-import net.floodlightcontroller.restserver.RestletRoutable;
-
-public class VirtualNetworkWebRoutable implements RestletRoutable {
-
-    @Override
-    public Restlet getRestlet(Context context) {
-        Router router = new Router(context);
-        router.attach("/tenants/{tenant}/networks", NetworkResource.class); // GET
-        router.attach("/tenants/{tenant}/networks/{network}", NetworkResource.class); // PUT, DELETE
-        router.attach("/tenants/{tenant}/networks", NetworkResource.class); // POST
-        router.attach("/tenants/{tenant}/networks/{network}/ports/{port}/attachment", HostResource.class);
-        router.attachDefault(NoOp.class);
-        return router;
-    }
-
-    @Override
-    public String basePath() {
-        return "/quantum/v1.0";
-    }
-}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
index b8b3303..2e2706c 100644
--- a/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
+++ b/src/main/java/net/onrc/onos/flow/FlowManagerImpl.java
@@ -17,27 +17,27 @@
 import com.tinkerpop.blueprints.Direction;
 import com.tinkerpop.blueprints.Vertex;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowEntry;
-import net.floodlightcontroller.util.FlowEntryAction;
-import net.floodlightcontroller.util.FlowEntryMatch;
-import net.floodlightcontroller.util.FlowPath;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.LocalTopologyEventListener;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.graph.LocalTopologyEventListener;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
+import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 public class FlowManagerImpl implements IFlowManager {
 	
 	protected static Logger log = LoggerFactory.getLogger(LocalTopologyEventListener.class);
-	protected static GraphDBConnection conn;
+	protected GraphDBOperation op;
 
 	@Override
 	public void createFlow(IPortObject src_port, IPortObject dest_port) {
@@ -87,8 +87,8 @@
 		Short dst_port = flow.getDstPort();
 		IPortObject src = null;
 		IPortObject dst = null;
-		src = conn.utils().searchPort(conn, src_dpid, src_port);
-		dst = conn.utils().searchPort(conn, dst_dpid, dst_port);
+		src = op.searchPort(src_dpid, src_port);
+		dst = op.searchPort(dst_dpid, dst_port);
 		if (src != null && dst != null) {
 			FlowPath newFlow = this.computeFlowPath(src,dst);
 			installFlow(newFlow);
@@ -133,16 +133,12 @@
 		    flowEntry.setOutPort(new Port(src_port.getNumber()));
 		    flowEntry.setFlowEntryMatch(new FlowEntryMatch());
 		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
-		    
+
 		    // Set the outgoing port output action
-		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
-		    if (flowEntryActions == null) {
-			flowEntryActions = new ArrayList<FlowEntryAction>();
-			flowEntry.setFlowEntryActions(flowEntryActions);
-		    }
+		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
 		    FlowEntryAction flowEntryAction = new FlowEntryAction();
 		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.add(flowEntryAction);
+		    flowEntryActions.addAction(flowEntryAction);
 		    dataPath.flowEntries().add(flowEntry);
 		    
 		    FlowPath flowPath = new FlowPath();
@@ -255,14 +251,10 @@
 		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
 		    
 		    // Set the outgoing port output action
-		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
-		    if (flowEntryActions == null) {
-			flowEntryActions = new ArrayList<FlowEntryAction>();
-			flowEntry.setFlowEntryActions(flowEntryActions);
-		    }
+		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
 		    FlowEntryAction flowEntryAction = new FlowEntryAction();
 		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.add(flowEntryAction);
+		    flowEntryActions.addAction(flowEntryAction);
 		    dataPath.flowEntries().add(flowEntry);
 			continue;
 		    }
@@ -277,14 +269,10 @@
 		    flowEntry.flowEntryMatch().enableInPort(flowEntry.inPort());
 		    
 		    // Set the outgoing port output action
-		    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
-		    if (flowEntryActions == null) {
-			flowEntryActions = new ArrayList<FlowEntryAction>();
-			flowEntry.setFlowEntryActions(flowEntryActions);
-		    }
+		    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
 		    FlowEntryAction flowEntryAction = new FlowEntryAction();
 		    flowEntryAction.setActionOutput(flowEntry.outPort());
-		    flowEntryActions.add(flowEntryAction);
+		    flowEntryActions.addAction(flowEntryAction);
 		    dataPath.flowEntries().add(flowEntry);
 		    dataPath.flowEntries().add(flowEntry);
 		}
diff --git a/src/main/java/net/onrc/onos/flow/IFlowManager.java b/src/main/java/net/onrc/onos/flow/IFlowManager.java
index 743f8fb..598da85 100644
--- a/src/main/java/net/onrc/onos/flow/IFlowManager.java
+++ b/src/main/java/net/onrc/onos/flow/IFlowManager.java
@@ -1,11 +1,9 @@
 package net.onrc.onos.flow;
 
-import java.util.Map;
-
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.util.FlowEntry;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 public interface IFlowManager {
     /**
diff --git a/src/main/java/net/onrc/onos/graph/GraphDBConnection.java b/src/main/java/net/onrc/onos/graph/GraphDBConnection.java
new file mode 100644
index 0000000..f9f3b67
--- /dev/null
+++ b/src/main/java/net/onrc/onos/graph/GraphDBConnection.java
@@ -0,0 +1,161 @@
+package net.onrc.onos.graph;
+
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.TransactionalGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.wrappers.event.EventTransactionalGraph;
+import com.tinkerpop.frames.FramedGraph;
+
+public class GraphDBConnection implements IDBConnection {
+	public enum Transaction {
+		COMMIT, ROLLBACK
+	}
+
+	public enum GenerateEvent {
+		TRUE, FALSE
+	}
+
+	class TransactionHandle {
+		protected TransactionalGraph tr;
+
+		public void create() {
+			tr = graph.newTransaction();
+		}
+	}
+
+	protected static Logger log = LoggerFactory
+			.getLogger(GraphDBConnection.class);
+	private static GraphDBConnection singleton = new GraphDBConnection();
+	private static TitanGraph graph;
+	private static EventTransactionalGraph<TitanGraph> eg;
+	private static String configFile;
+
+	/*
+	 * A private Constructor prevents any other class from instantiating.
+	 */
+	private GraphDBConnection() {
+	}
+
+	/* Static 'instance' method */
+	/**
+	 * Get the instance of GraphDBConnection class.
+	 * @param conf the path to the database configuration file.
+	 * @return GraphDBConnection instance.
+	 */
+	public static synchronized GraphDBConnection getInstance(final String conf) {
+		if (GraphDBConnection.configFile == null
+				|| GraphDBConnection.configFile.isEmpty()) {
+			GraphDBConnection.configFile = conf;
+			log.debug("GraphDBConnection::Setting Config File {}",
+					GraphDBConnection.configFile);
+		}
+		if (!GraphDBConnection.configFile.isEmpty()
+				&& (graph == null || graph.isOpen() == Boolean.FALSE)) {
+			graph = TitanFactory.open(GraphDBConnection.configFile);
+			// FIXME: Creation on Indexes should be done only once
+			Set<String> s = graph.getIndexedKeys(Vertex.class);
+			if (!s.contains("dpid")) {
+				graph.createKeyIndex("dpid", Vertex.class);
+			}
+			if (!s.contains("port_id")) {
+				graph.createKeyIndex("port_id", Vertex.class);
+			}
+			if (!s.contains("type")) {
+				graph.createKeyIndex("type", Vertex.class);
+			}
+			if (!s.contains("dl_addr")) {
+				graph.createKeyIndex("dl_addr", Vertex.class);
+			}
+			if (!s.contains("flow_id")) {
+				graph.createKeyIndex("flow_id", Vertex.class);
+			}
+			if (!s.contains("flow_entry_id")) {
+				graph.createKeyIndex("flow_entry_id", Vertex.class);
+			}
+			if (!s.contains("switch_state")) {
+				graph.createKeyIndex("switch_state", Vertex.class);
+			}
+			graph.commit();
+			eg = new EventTransactionalGraph<TitanGraph>(graph);
+		}
+		return singleton;
+	}
+
+	/** 
+	 * Get a FramedGraph instance of the graph.
+	 */
+	public FramedGraph<TitanGraph> getFramedGraph() {
+		if (isValid()) {
+			FramedGraph<TitanGraph> fg = new FramedGraph<TitanGraph>(graph);
+			return fg;
+		} else {
+			log.error("new FramedGraph failed");
+			return null;
+		}
+	}
+
+	/**
+	 * Get EventTransactionalGraph of the titan graph.
+	 * @return EventTransactionalGraph of the titan graph
+	 */
+	protected EventTransactionalGraph<TitanGraph> getEventGraph() {
+		if (isValid()) {
+			return eg;
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * Add LocalGraphChangedLister for the graph.
+	 */
+	public void addEventListener(final LocalGraphChangedListener listener) {
+		EventTransactionalGraph<TitanGraph> eg = this.getEventGraph();
+		eg.addListener(listener);
+		log.debug("Registered listener {}", listener.getClass());
+	}
+
+	/**
+	 * Return whether this connection is valid.
+	 */
+	public Boolean isValid() {
+		return (graph != null || graph.isOpen());
+	}
+
+	/**
+	 * Commit changes for the graph operations.
+	 */
+	public void commit() {
+		try {
+			graph.commit();
+		}
+		catch (Exception e) {
+			log.error("{}", e.toString());
+		}
+	}
+
+	/**
+	 * Rollback changes for the graph operations.
+	 */
+	public void rollback() {
+		try {
+			graph.rollback();
+		}
+		catch (Exception e) {
+			log.error("{}", e.toString());
+		}
+	}
+
+	/**
+	 * Close this database connection.
+	 */
+	public void close() {
+		commit();
+	}
+}
diff --git a/src/main/java/net/onrc/onos/graph/GraphDBOperation.java b/src/main/java/net/onrc/onos/graph/GraphDBOperation.java
new file mode 100644
index 0000000..acfe43b
--- /dev/null
+++ b/src/main/java/net/onrc/onos/graph/GraphDBOperation.java
@@ -0,0 +1,361 @@
+package net.onrc.onos.graph;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openflow.protocol.OFPhysicalPort;
+
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowId;
+
+import com.google.common.base.Stopwatch;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.frames.FramedGraph;
+import com.tinkerpop.frames.structures.FramedVertexIterable;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+
+public class GraphDBOperation implements IDBOperation {
+	private GraphDBConnection conn;
+
+	/**
+	 * Create a GraphDBOperation instance from specified GraphDBConnection's instance.
+	 * @param dbConnection an instance of GraphDBConnection
+	 */
+	public GraphDBOperation(GraphDBConnection dbConnection) {
+		this.conn = dbConnection;
+	}
+
+	/**
+	 * Create a GraphDBOperation instance from database configuration path.
+	 * @param dbConfPath a path for database configuration file.
+	 */
+	public GraphDBOperation(final String dbConfPath) {
+		this.conn = GraphDBConnection.getInstance(dbConfPath);
+	}
+
+	/**
+	 * Create a new switch and return the created switch object.
+	 * @param dpid DPID of the switch
+	 */
+	public ISwitchObject newSwitch(String dpid) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		ISwitchObject obj = fg.addVertex(null,ISwitchObject.class);
+		if (obj != null) {
+			obj.setType("switch");
+			obj.setDPID(dpid);
+		}
+		return obj;
+	}
+
+	/**
+	 * Search and get a switch object with DPID.
+	 * @param dpid DPID of the switch 
+	 */
+	public ISwitchObject searchSwitch(String dpid) {
+
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return (fg != null && fg.getVertices("dpid",dpid).iterator().hasNext()) ? 
+				fg.getVertices("dpid",dpid,ISwitchObject.class).iterator().next() : null;
+				
+	}
+
+	/**
+	 * Search and get an active switch object with DPID.
+	 * @param dpid DPID of the switch 
+	 */
+	public ISwitchObject searchActiveSwitch(String dpid) {
+	
+	    ISwitchObject sw = searchSwitch(dpid);
+	    if ((sw != null) &&
+	        sw.getState().equals(SwitchState.ACTIVE.toString())) {
+	        return sw;
+	    }
+	    return null;
+	}
+
+	/**
+	 * Get all switch objects.
+	 */
+	public Iterable<ISwitchObject> getAllSwitches() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
+		return switches;
+	}
+
+	/**
+	 * Get all active switch objects.
+	 */
+	public Iterable<ISwitchObject> getActiveSwitches() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
+		List<ISwitchObject> activeSwitches = new ArrayList<ISwitchObject>();
+	
+		for (ISwitchObject sw: switches) {
+			if(sw.getState().equals(SwitchState.ACTIVE.toString())) {
+				activeSwitches.add(sw);
+			}
+		}
+		return activeSwitches;
+	}
+
+	/**
+	 * Get all inactive switch objects.
+	 */
+	public Iterable<ISwitchObject> getInactiveSwitches() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
+		List<ISwitchObject> inactiveSwitches = new ArrayList<ISwitchObject>();
+	
+		for (ISwitchObject sw: switches) {
+			if(sw.getState().equals(SwitchState.INACTIVE.toString())) {
+				inactiveSwitches.add(sw);
+			}
+		}
+		return inactiveSwitches;
+	}
+
+	/**
+	 * Get all flow entries' objects where their switches are not updated.
+	 */
+	public Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		//TODO: Should use an enum for flow_switch_state
+		return fg.getVertices("switch_state", "FE_SWITCH_NOT_UPDATED", IFlowEntry.class);
+	}
+
+	/**
+	 * Remove specified switch.
+	 * @param sw switch object to remove
+	 */
+	public void removeSwitch(ISwitchObject sw) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		fg.removeVertex(sw.asVertex());		
+	}
+	
+	@Override
+	public IPortObject newPort(String dpid, Short portNumber) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IPortObject obj = fg.addVertex(null,IPortObject.class);
+		if (obj != null) {
+			obj.setType("port");
+			String id = dpid + portNumber.toString();
+			obj.setPortId(id);
+			obj.setNumber(portNumber);
+		}
+		return obj;	
+		
+	}
+
+	/**
+	 * Create a port having specified port number.
+	 * @param portNumber port number
+	 */
+	@Deprecated
+	public IPortObject newPort(Short portNumber) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IPortObject obj = fg.addVertex(null,IPortObject.class);
+		if (obj != null) {
+			obj.setType("port");
+			obj.setNumber(portNumber);
+		}
+		return obj;
+	}
+
+	/**
+	 * Search and get a port object of specified switch and port number.
+	 * @param dpid DPID of a switch
+	 * @param number port number of the switch's port
+	 */
+	public IPortObject searchPort(String dpid, Short number) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		String id = dpid + number.toString();
+		return (fg != null && fg.getVertices("port_id",id).iterator().hasNext()) ? 
+				fg.getVertices("port_id",id,IPortObject.class).iterator().next() : null;
+	}
+
+	/**
+	 * Remove the specified switch port.
+	 * @param port switch port object to remove
+	 */
+	public void removePort(IPortObject port) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+//		EventGraph<TitanGraph> eg = conn.getEventGraph();
+		if (fg != null) fg.removeVertex(port.asVertex());		
+	}
+
+	/**
+	 * Create and return a device object.
+	 */
+	public IDeviceObject newDevice() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IDeviceObject obj = fg.addVertex(null,IDeviceObject.class);
+		if (obj != null) obj.setType("device");
+		return obj;
+	}
+
+	/**
+	 * Search and get a device object having specified MAC address.
+	 * @param macAddr MAC address to search and get
+	 */
+	public IDeviceObject searchDevice(String macAddr) {
+		// TODO Auto-generated method stub
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		return (fg != null && fg.getVertices("dl_addr",macAddr).iterator().hasNext()) ?
+			fg.getVertices("dl_addr",macAddr, IDeviceObject.class).iterator().next() : null;
+	}
+
+	/**
+	 * Get all devices.
+	 */
+	public Iterable<IDeviceObject> getDevices() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		return fg != null ? fg.getVertices("type","device",IDeviceObject.class) : null;
+	}
+
+	/**
+	 * Remove the specified device.
+	 * @param dev a device object to remove
+	 */
+	public void removeDevice(IDeviceObject dev) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		if (fg != null) fg.removeVertex(dev.asVertex());		
+	}
+
+	/**
+	 * Create and return a flow path object.
+	 */
+	public IFlowPath newFlowPath() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IFlowPath flowPath = fg.addVertex(null, IFlowPath.class);
+		if (flowPath != null) flowPath.setType("flow");
+		return flowPath;
+	}
+
+	/**
+	 * Search and get a flow path object with specified flow ID.
+	 * @param flowId flow ID to search
+	 */
+	public IFlowPath searchFlowPath(FlowId flowId) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("flow_id", flowId.toString()).iterator().hasNext() ? 
+		    fg.getVertices("flow_id", flowId.toString(),
+				   IFlowPath.class).iterator().next() : null;
+	}
+
+	/**
+	 * Get a flow path object with a flow entry.
+	 * @param flowEntry flow entry object
+	 */
+	public IFlowPath getFlowPathByFlowEntry(IFlowEntry flowEntry) {
+		GremlinPipeline<Vertex, IFlowPath> pipe = new GremlinPipeline<Vertex, IFlowPath>();
+		pipe.start(flowEntry.asVertex());
+		pipe.out("flow");
+		FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), (Iterable) pipe, IFlowPath.class);
+		return r.iterator().hasNext() ? r.iterator().next() : null;
+	}
+
+	/**
+	 * Get all flow path objects.
+	 */
+    public Iterable<IFlowPath> getAllFlowPaths() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		Iterable<IFlowPath> flowPaths = fg.getVertices("type", "flow", IFlowPath.class);
+		
+		List<IFlowPath> nonNullFlows = new ArrayList<IFlowPath>();
+
+		for (IFlowPath fp: flowPaths) {
+			if (fp.getFlowId() != null) {
+				nonNullFlows.add(fp);
+			}
+		}
+		return nonNullFlows;
+	}
+
+    /**
+     * Remove the specified flow path.
+     * @param flowPath flow path object to remove
+     */
+	public void removeFlowPath(IFlowPath flowPath) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		fg.removeVertex(flowPath.asVertex());
+	}
+
+	/**
+	 * Create and return a flow entry object.
+	 */
+	public IFlowEntry newFlowEntry() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
+		IFlowEntry flowEntry = fg.addVertex(null, IFlowEntry.class);
+		if (flowEntry != null) flowEntry.setType("flow_entry");
+		return flowEntry;
+	}
+
+	/**
+	 * Search and get a flow entry object with flow entry ID.
+	 * @param flowEntryId flow entry ID to search
+	 */
+	public IFlowEntry searchFlowEntry(FlowEntryId flowEntryId) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("flow_entry_id", flowEntryId.toString()).iterator().hasNext() ? 
+		    fg.getVertices("flow_entry_id", flowEntryId.toString(),
+				   IFlowEntry.class).iterator().next() : null;
+	}
+
+	/**
+	 * Get all flow entry objects.
+	 */
+	public Iterable<IFlowEntry> getAllFlowEntries() {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		return fg.getVertices("type", "flow_entry", IFlowEntry.class);
+	}
+
+	/**
+	 * Remove the specified flow entry.
+	 * @param flowEntry flow entry object to remove
+	 */
+	public void removeFlowEntry(IFlowEntry flowEntry) {
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		fg.removeVertex(flowEntry.asVertex());
+	}
+	
+	/**
+	 * Get the instance of GraphDBConnection assigned to this class.
+	 */
+	public IDBConnection getDBConnection() {
+		return conn;
+	}
+	
+	/**
+	 * Commit changes for the graph.
+	 */
+	public void commit() {
+		conn.commit();
+	}
+
+	/**
+	 * Rollback changes for the graph.
+	 */
+	public void rollback() {
+		conn.rollback();
+	}
+
+	/**
+	 * Close the connection of the assigned GraphDBConnection.
+	 */
+	public void close() {
+		conn.close();
+	}
+
+
+}
diff --git a/src/main/java/net/onrc/onos/graph/IDBConnection.java b/src/main/java/net/onrc/onos/graph/IDBConnection.java
new file mode 100644
index 0000000..82ebba2
--- /dev/null
+++ b/src/main/java/net/onrc/onos/graph/IDBConnection.java
@@ -0,0 +1,13 @@
+package net.onrc.onos.graph;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.frames.FramedGraph;
+
+public interface IDBConnection {
+	public FramedGraph<TitanGraph> getFramedGraph();
+	public void addEventListener(final LocalGraphChangedListener listener);
+	public Boolean isValid();
+	public void commit();
+	public void rollback();
+	public void close();
+}
diff --git a/src/main/java/net/onrc/onos/graph/IDBOperation.java b/src/main/java/net/onrc/onos/graph/IDBOperation.java
new file mode 100644
index 0000000..f873f27
--- /dev/null
+++ b/src/main/java/net/onrc/onos/graph/IDBOperation.java
@@ -0,0 +1,48 @@
+package net.onrc.onos.graph;
+
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowId;
+
+public interface IDBOperation {
+	public ISwitchObject newSwitch(String dpid);
+	public ISwitchObject searchSwitch(String dpid);
+	public ISwitchObject searchActiveSwitch(String dpid);
+	public Iterable<ISwitchObject> getActiveSwitches();
+	public Iterable<ISwitchObject> getAllSwitches();
+	public Iterable<ISwitchObject> getInactiveSwitches();
+	public Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries();
+	public void removeSwitch(ISwitchObject sw);
+	
+	@Deprecated
+	public IPortObject newPort(Short portNumber);
+	public IPortObject newPort(String dpid, Short portNum);
+	public IPortObject searchPort(String dpid, Short number);
+	public void removePort(IPortObject port);
+	
+	public IDeviceObject newDevice();
+	public IDeviceObject searchDevice(String macAddr);
+	public Iterable<IDeviceObject> getDevices();
+	public void removeDevice(IDeviceObject dev);
+
+	public IFlowPath newFlowPath();
+	public IFlowPath searchFlowPath(FlowId flowId);
+	public IFlowPath getFlowPathByFlowEntry(IFlowEntry flowEntry);
+	public Iterable<IFlowPath> getAllFlowPaths();
+	public void removeFlowPath(IFlowPath flowPath);
+
+	public IFlowEntry newFlowEntry();
+	public IFlowEntry searchFlowEntry(FlowEntryId flowEntryId);
+	public Iterable<IFlowEntry> getAllFlowEntries();
+	public void removeFlowEntry(IFlowEntry flowEntry);
+	
+	public IDBConnection getDBConnection();	
+	public void commit();
+	public void rollback();
+	public void close();
+	
+}
diff --git a/src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java b/src/main/java/net/onrc/onos/graph/LocalGraphChangedListener.java
similarity index 84%
rename from src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java
rename to src/main/java/net/onrc/onos/graph/LocalGraphChangedListener.java
index ac819f9..5f3bbf1 100644
--- a/src/main/java/net/onrc/onos/util/LocalGraphChangedListener.java
+++ b/src/main/java/net/onrc/onos/graph/LocalGraphChangedListener.java
@@ -1,4 +1,4 @@
-package net.onrc.onos.util;
+package net.onrc.onos.graph;
 
 import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
 
diff --git a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java b/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
similarity index 96%
rename from src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
rename to src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
index 61f227d..f83e7c2 100644
--- a/src/main/java/net/onrc/onos/util/LocalTopologyEventListener.java
+++ b/src/main/java/net/onrc/onos/graph/LocalTopologyEventListener.java
@@ -1,8 +1,8 @@
-package net.onrc.onos.util;
+package net.onrc.onos.graph;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
 import net.onrc.onos.flow.FlowManagerImpl;
 import net.onrc.onos.flow.IFlowManager;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpPeer.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpPeer.java
new file mode 100644
index 0000000..7425a07
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpPeer.java
@@ -0,0 +1,42 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.InetAddress;
+
+import net.floodlightcontroller.util.MACAddress;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import com.google.common.net.InetAddresses;
+
+public class BgpPeer {
+	private String interfaceName;
+	private InetAddress ipAddress;
+	private MACAddress macAddress;
+	
+	public String getInterfaceName() {
+		return interfaceName;
+	}
+	
+	@JsonProperty("interface")
+	public void setInterfaceName(String interfaceName) {
+		this.interfaceName = interfaceName;
+	}
+	
+	public InetAddress getIpAddress() {
+		return ipAddress;
+	}
+	
+	@JsonProperty("ipAddress")
+	public void setIpAddress(String ipAddress) {
+		this.ipAddress = InetAddresses.forString(ipAddress);
+	}
+	
+	public MACAddress getMacAddress() {
+		return macAddress;
+	}
+	
+	@JsonProperty("macAddress")
+	public void setMacAddress(String macAddress) {
+		this.macAddress = MACAddress.valueOf(macAddress);
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
new file mode 100644
index 0000000..acdf185
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRoute.java
@@ -0,0 +1,1060 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.IOFSwitchListener;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.FloodlightModuleException;
+import net.floodlightcontroller.core.module.IFloodlightModule;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.core.util.SingletonTask;
+import net.floodlightcontroller.devicemanager.IDeviceService;
+import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.floodlightcontroller.routing.Link;
+import net.floodlightcontroller.topology.ITopologyListener;
+import net.floodlightcontroller.topology.ITopologyService;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoLinkService;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.onrc.onos.ofcontroller.core.internal.TopoLinkServiceImpl;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
+import net.onrc.onos.ofcontroller.proxyarp.ProxyArpManager;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
+import net.sf.json.JSONSerializer;
+
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFMatch;
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionDataLayerDestination;
+import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+public class BgpRoute implements IFloodlightModule, IBgpRouteService, 
+									ITopologyListener, IOFSwitchListener {
+	
+	protected static Logger log = LoggerFactory.getLogger(BgpRoute.class);
+
+	protected IFloodlightProviderService floodlightProvider;
+	protected ITopologyService topology;
+	protected ITopoRouteService topoRouteService;
+	protected IDeviceService devices;
+	protected IRestApiService restApi;
+	
+	protected ProxyArpManager proxyArp;
+	
+	protected static Ptree ptree;
+	protected BlockingQueue<RibUpdate> ribUpdates;
+	
+	protected String bgpdRestIp;
+	protected String routerId;
+	protected String configFilename = "config.json";
+	
+	//We need to identify our flows somehow. But like it says in LearningSwitch.java,
+	//the controller/OS should hand out cookie IDs to prevent conflicts.
+	protected final long APP_COOKIE = 0xa0000000000000L;
+	//Cookie for flows that do L2 forwarding within SDN domain to egress routers
+	protected final long L2_FWD_COOKIE = APP_COOKIE + 1;
+	//Cookie for flows in ingress switches that rewrite the MAC address
+	protected final long MAC_RW_COOKIE = APP_COOKIE + 2;
+	//Cookie for flows that setup BGP paths
+	protected final long BGP_COOKIE = APP_COOKIE + 3;
+	//Forwarding uses priority 0, and the mac rewrite entries in ingress switches
+	//need to be higher priority than this otherwise the rewrite may not get done
+	protected final short SDNIP_PRIORITY = 10;
+	
+	protected final short BGP_PORT = 179;
+	
+	protected final int TOPO_DETECTION_WAIT = 2; //seconds
+	
+	//Configuration stuff
+	protected List<String> switches;
+	protected Map<String, Interface> interfaces;
+	protected Map<InetAddress, BgpPeer> bgpPeers;
+	protected SwitchPort bgpdAttachmentPoint;
+	
+	//True when all switches have connected
+	protected volatile boolean switchesConnected = false;
+	//True when we have a full mesh of shortest paths between gateways
+	protected volatile boolean topologyReady = false;
+
+	protected ArrayList<LDUpdate> linkUpdates;
+	protected SingletonTask topologyChangeDetectorTask;
+	
+	protected class TopologyChangeDetector implements Runnable {
+		@Override
+		public void run() {
+			log.debug("Running topology change detection task");
+			synchronized (linkUpdates) {
+				//This is the model the REST API uses to retrieve network graph info
+				ITopoLinkService topoLinkService = new TopoLinkServiceImpl();
+				
+				List<Link> activeLinks = topoLinkService.getActiveLinks();
+				//for (Link l : activeLinks){
+					//log.debug("active link: {}", l);
+				//}
+				
+				Iterator<LDUpdate> it = linkUpdates.iterator();
+				while (it.hasNext()){
+					LDUpdate ldu = it.next();
+					Link l = new Link(ldu.getSrc(), ldu.getSrcPort(), 
+							ldu.getDst(), ldu.getDstPort());
+					
+					if (activeLinks.contains(l)){
+						log.debug("Not found: {}", l);
+						it.remove();
+					}
+				}
+			}
+			
+			if (linkUpdates.isEmpty()){
+				//All updates have been seen in network map.
+				//We can check if topology is ready
+				log.debug("No known changes outstanding. Checking topology now");
+				checkStatus();
+			}
+			else {
+				//We know of some link updates that haven't propagated to the database yet
+				log.debug("Some changes not found in network map - {} links missing", linkUpdates.size());
+				topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
+			}
+		}
+	}
+	
+	private void readGatewaysConfiguration(String gatewaysFilename){
+		File gatewaysFile = new File(gatewaysFilename);
+		ObjectMapper mapper = new ObjectMapper();
+		
+		try {
+			Configuration config = mapper.readValue(gatewaysFile, Configuration.class);
+			
+			switches = config.getSwitches();
+			interfaces = new HashMap<String, Interface>();
+			for (Interface intf : config.getInterfaces()){
+				interfaces.put(intf.getName(), intf);
+			}
+			bgpPeers = new HashMap<InetAddress, BgpPeer>();
+			for (BgpPeer peer : config.getPeers()){
+				bgpPeers.put(peer.getIpAddress(), peer);
+			}
+			
+			bgpdAttachmentPoint = new SwitchPort(
+					new Dpid(config.getBgpdAttachmentDpid()),
+					new Port(config.getBgpdAttachmentPort()));
+			
+		} catch (JsonParseException e) {
+			log.error("Error in JSON file", e);
+			System.exit(1);
+		} catch (JsonMappingException e) {
+			log.error("Error in JSON file", e);
+			System.exit(1);
+		} catch (IOException e) {
+			log.error("Error reading JSON file", e);
+			System.exit(1);
+		}
+	}
+	
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleServices() {
+		Collection<Class<? extends IFloodlightService>> l 
+			= new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IBgpRouteService.class);
+		return l;
+	}
+
+	@Override
+	public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
+		Map<Class<? extends IFloodlightService>, IFloodlightService> m 
+			= new HashMap<Class<? extends IFloodlightService>, IFloodlightService>();
+		m.put(IBgpRouteService.class, this);
+		return m;
+	}
+
+	@Override
+	public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
+		Collection<Class<? extends IFloodlightService>> l 
+			= new ArrayList<Class<? extends IFloodlightService>>();
+		l.add(IFloodlightProviderService.class);
+		l.add(ITopologyService.class);
+		l.add(IDeviceService.class);
+		l.add(IRestApiService.class);
+		return l;
+	}
+	
+	@Override
+	public void init(FloodlightModuleContext context)
+			throws FloodlightModuleException {
+	    
+	    ptree = new Ptree(32);
+	    
+	    ribUpdates = new LinkedBlockingQueue<RibUpdate>();
+	    	
+		// Register floodlight provider and REST handler.
+		floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
+		topology = context.getServiceImpl(ITopologyService.class);
+		devices = context.getServiceImpl(IDeviceService.class);
+		restApi = context.getServiceImpl(IRestApiService.class);
+		
+		//TODO We'll initialise this here for now, but it should really be done as
+		//part of the controller core
+		proxyArp = new ProxyArpManager(floodlightProvider, topology, devices);
+		
+		linkUpdates = new ArrayList<LDUpdate>();
+		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+		topologyChangeDetectorTask = new SingletonTask(executor, new TopologyChangeDetector());
+
+		topoRouteService = new TopoRouteService("");
+		
+		//Read in config values
+		bgpdRestIp = context.getConfigParams(this).get("BgpdRestIp");
+		if (bgpdRestIp == null){
+			log.error("BgpdRestIp property not found in config file");
+			System.exit(1);
+		}
+		else {
+			log.info("BgpdRestIp set to {}", bgpdRestIp);
+		}
+		
+		routerId = context.getConfigParams(this).get("RouterId");
+		if (routerId == null){
+			log.error("RouterId property not found in config file");
+			System.exit(1);
+		}
+		else {
+			log.info("RouterId set to {}", routerId);
+		}
+		
+		String configFilenameParameter = context.getConfigParams(this).get("configfile");
+		if (configFilenameParameter != null){
+			configFilename = configFilenameParameter;
+		}
+		log.debug("Config file set to {}", configFilename);
+		
+		readGatewaysConfiguration(configFilename);
+		// Test.
+		//test();
+	}
+
+	public Ptree getPtree() {
+		return ptree;
+	}
+	
+	public void clearPtree() {
+		//ptree = null;
+		ptree = new Ptree(32);	
+	}
+	
+	public String getBGPdRestIp() {
+		return bgpdRestIp;
+	}
+	
+	public String getRouterId() {
+		return routerId;
+	}
+	
+	// Return nexthop address as byte array.
+	public Rib lookupRib(byte[] dest) {
+		if (ptree == null) {
+		    log.debug("lookupRib: ptree null");
+		    return null;
+		}
+		
+		PtreeNode node = ptree.match(dest, 32);
+		if (node == null) {
+            log.debug("lookupRib: ptree node null");
+			return null;
+		}
+		
+		if (node.rib == null) {
+            log.debug("lookupRib: ptree rib null");
+			return null;
+		}
+		
+		ptree.delReference(node);
+		
+		return node.rib;
+	}
+	
+	//TODO looks like this should be a unit test
+	@SuppressWarnings("unused")
+    private void test() throws UnknownHostException {
+		System.out.println("Here it is");
+		Prefix p = new Prefix("128.0.0.0", 8);
+		Prefix q = new Prefix("8.0.0.0", 8);
+		Prefix r = new Prefix("10.0.0.0", 24);
+		Prefix a = new Prefix("10.0.0.1", 32);
+	
+		ptree.acquire(p.getAddress(), p.getPrefixLength());
+		ptree.acquire(q.getAddress(), q.getPrefixLength());
+		ptree.acquire(r.getAddress(), r.getPrefixLength());
+	
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+	
+		PtreeNode n = ptree.match(a.getAddress(), a.getPrefixLength());
+		if (n != null) {
+			System.out.println("Matched prefix for 10.0.0.1:");
+			Prefix x = new Prefix(n.key, n.keyBits);
+			ptree.delReference(n);
+		}
+		
+		n = ptree.lookup(p.getAddress(), p.getPrefixLength());
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+		
+		n = ptree.lookup(q.getAddress(), q.getPrefixLength());
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+		
+		n = ptree.lookup(r.getAddress(), r.getPrefixLength());
+		if (n != null) {
+			ptree.delReference(n);
+			ptree.delReference(n);
+		}
+		System.out.println("Traverse start");
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+			Prefix p_result = new Prefix(node.key, node.keyBits);
+		}
+
+	}
+	
+	private String getPrefixFromPtree(PtreeNode node){
+        InetAddress address = null;
+        try {
+			address = InetAddress.getByAddress(node.key);
+		} catch (UnknownHostException e1) {
+			//Should never happen is the reverse conversion has already been done
+			log.error("Malformed IP address");
+			return "";
+		}
+        return address.toString() + "/" + node.rib.masklen;
+	}
+	
+	private void retrieveRib(){
+		String url = "http://" + bgpdRestIp + "/wm/bgp/" + routerId;
+		String response = RestClient.get(url);
+		
+		if (response.equals("")){
+			return;
+		}
+		
+		response = response.replaceAll("\"", "'");
+		JSONObject jsonObj = (JSONObject) JSONSerializer.toJSON(response);  
+		JSONArray rib_json_array = jsonObj.getJSONArray("rib");
+		String router_id = jsonObj.getString("router-id");
+
+		int size = rib_json_array.size();
+
+		log.info("Retrived RIB of {} entries from BGPd", size);
+		
+		for (int j = 0; j < size; j++) {
+			JSONObject second_json_object = rib_json_array.getJSONObject(j);
+			String prefix = second_json_object.getString("prefix");
+			String nexthop = second_json_object.getString("nexthop");
+
+			//insert each rib entry into the local rib;
+			String[] substring = prefix.split("/");
+			String prefix1 = substring[0];
+			String mask1 = substring[1];
+
+			Prefix p;
+			try {
+				p = new Prefix(prefix1, Integer.valueOf(mask1));
+			} catch (NumberFormatException e) {
+				log.warn("Wrong mask format in RIB JSON: {}", mask1);
+				continue;
+			} catch (UnknownHostException e1) {
+				log.warn("Wrong prefix format in RIB JSON: {}", prefix1);
+				continue;
+			}
+			
+			PtreeNode node = ptree.acquire(p.getAddress(), p.getPrefixLength());
+			Rib rib = new Rib(router_id, nexthop, p.getPrefixLength());
+			
+			if (node.rib != null) {
+				node.rib = null;
+				ptree.delReference(node);
+			}
+			
+			node.rib = rib;
+			
+			prefixAdded(node);
+		} 
+	}
+	
+	@Override
+	public void newRibUpdate(RibUpdate update) {
+		ribUpdates.add(update);
+	}
+	
+	//TODO temporary
+	public void wrapPrefixAdded(RibUpdate update) {
+		Prefix prefix = update.getPrefix();
+		
+		PtreeNode node = ptree.acquire(prefix.getAddress(), prefix.getPrefixLength());
+		
+		if (node.rib != null) {
+			node.rib = null;
+			ptree.delReference(node);
+		}
+		node.rib = update.getRibEntry();
+
+		prefixAdded(node);
+	}
+	
+	//TODO temporary
+	public void wrapPrefixDeleted(RibUpdate update) {
+		Prefix prefix = update.getPrefix();
+		
+		PtreeNode node = ptree.lookup(prefix.getAddress(), prefix.getPrefixLength());
+		
+		/* 
+		 * Remove the flows from the switches before the rib is lost
+		 * Theory: we could get a delete for a prefix not in the Ptree.
+		 * This would result in a null node being returned. We could get a delete for
+		 * a node that's not actually there, but is a aggregate node. This would result
+		 * in a non-null node with a null rib. Only a non-null node with a non-null
+		 * rib is an actual prefix in the Ptree.
+		 */
+		if (node != null && node.rib != null){
+			prefixDeleted(node);
+		}
+
+		if (node != null && node.rib != null) {
+			if (update.getRibEntry().equals(node.rib)) {
+				node.rib = null;
+				ptree.delReference(node);					
+			}
+		}
+	}
+	
+	@Override
+	public void prefixAdded(PtreeNode node) {
+		if (!topologyReady){
+			return;
+		}
+		
+		String prefix = getPrefixFromPtree(node);
+		
+		log.debug("New prefix {} added, next hop {}, routerId {}", 
+				new Object[] {prefix, node.rib.nextHop.toString(), 
+				node.rib.routerId.getHostAddress()});
+		
+		//TODO this is wrong, we shouldn't be dealing with BGP peers here.
+		//We need to figure out where the device is attached and what its
+		//mac address is by learning. 
+		//The next hop is not necessarily the peer, and the peer's attachment
+		//point is not necessarily the next hop's attachment point.
+		BgpPeer peer = bgpPeers.get(node.rib.nextHop);
+		
+		if (peer == null){
+			//TODO local router isn't in peers list so this will get thrown
+			//Need to work out what to do about local prefixes with next hop 0.0.0.0.
+			
+			//The other scenario is this is a route server route. In that
+			//case the next hop is not in our configuration
+			log.error("Couldn't find next hop router in router {} in config"
+					, node.rib.nextHop.toString());
+			return; //just quit out here? This is probably a configuration error
+		}
+		
+		Interface peerInterface = interfaces.get(peer.getInterfaceName());
+
+		//Add a flow to rewrite mac for this prefix to all border switches
+		for (Interface srcInterface : interfaces.values()) {
+			if (srcInterface == peerInterface) {
+				//Don't push a flow for the switch where this peer is attached
+				continue;
+			}
+						
+			DataPath shortestPath = topoRouteService.getShortestPath(
+					srcInterface.getSwitchPort(),
+					peerInterface.getSwitchPort());
+			
+			if (shortestPath == null){
+				log.debug("Shortest path between {} and {} not found",
+						srcInterface.getSwitchPort(),
+						peerInterface.getSwitchPort());
+				return; // just quit here?
+			}
+			
+			//TODO check the shortest path against the cached version we
+			//calculated before. If they don't match up that's a problem
+			
+			//Set up the flow mod
+			OFFlowMod fm =
+	                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+	                                              .getMessage(OFType.FLOW_MOD);
+			
+	        fm.setIdleTimeout((short)0)
+	        .setHardTimeout((short)0)
+	        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+	        .setCookie(MAC_RW_COOKIE)
+	        .setCommand(OFFlowMod.OFPFC_ADD)
+	        .setPriority(SDNIP_PRIORITY)
+	        .setLengthU(OFFlowMod.MINIMUM_LENGTH
+	        		+ OFActionDataLayerDestination.MINIMUM_LENGTH
+	        		+ OFActionOutput.MINIMUM_LENGTH);
+	        
+	        OFMatch match = new OFMatch();
+	        match.setDataLayerType(Ethernet.TYPE_IPv4);
+	        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	        
+	        //match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
+	        //match.setDataLayerSource(peer.getMacAddress().toBytes());
+	        //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+
+	        InetAddress address = null;
+	        try {
+				address = InetAddress.getByAddress(node.key);
+			} catch (UnknownHostException e1) {
+				//Should never happen is the reverse conversion has already been done
+				log.error("Malformed IP address");
+				return;
+			}
+	        
+	        match.setFromCIDR(address.getHostAddress() + "/" + node.rib.masklen, OFMatch.STR_NW_DST);
+	        fm.setMatch(match);
+	        
+	        //Set up MAC rewrite action
+	        OFActionDataLayerDestination macRewriteAction = new OFActionDataLayerDestination();
+	        //TODO use ARP module rather than configured mac addresses
+	        //TODO the peer's mac address is not necessarily the next hop's...
+	        macRewriteAction.setDataLayerAddress(peer.getMacAddress().toBytes());
+	        
+	        //Set up output action
+	        OFActionOutput outputAction = new OFActionOutput();
+	        outputAction.setMaxLength((short)0xffff);
+	        
+	        Port outputPort = shortestPath.flowEntries().get(0).outPort();
+	        outputAction.setPort(outputPort.value());
+	        
+	        List<OFAction> actions = new ArrayList<OFAction>();
+	        actions.add(macRewriteAction);
+	        actions.add(outputAction);
+	        fm.setActions(actions);
+	        
+	        //Write to switch
+	        IOFSwitch sw = floodlightProvider.getSwitches()
+	        			.get(srcInterface.getDpid());
+	        
+            if (sw == null){
+            	log.warn("Switch not found when pushing flow mod");
+            	continue;
+            }
+            
+            List<OFMessage> msglist = new ArrayList<OFMessage>();
+            msglist.add(fm);
+            try {
+				sw.write(msglist, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing flow mod", e);
+			}
+		}
+	}
+	
+	//TODO this is largely untested
+	@Override
+	public void prefixDeleted(PtreeNode node) {
+		if (!topologyReady) {
+			return;
+		}
+		
+		String prefix = getPrefixFromPtree(node);
+		
+		log.debug("Prefix {} deleted, next hop {}", 
+				prefix, node.rib.nextHop.toString());
+		
+		//Remove MAC rewriting flows from other border switches
+		BgpPeer peer = bgpPeers.get(node.rib.nextHop);
+		if (peer == null){
+			//either a router server route or local route. Can't handle right now
+			return;
+		}
+		
+		Interface peerInterface = interfaces.get(peer.getInterfaceName());
+		
+		for (Interface srcInterface : interfaces.values()) {
+			if (srcInterface == peerInterface) {
+				continue;
+			}
+			
+			//Set up the flow mod
+			OFFlowMod fm =
+	                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+	                                              .getMessage(OFType.FLOW_MOD);
+			
+	        fm.setIdleTimeout((short)0)
+	        .setHardTimeout((short)0)
+	        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+	        .setCookie(MAC_RW_COOKIE)
+	        .setCommand(OFFlowMod.OFPFC_DELETE)
+	        .setOutPort(OFPort.OFPP_NONE)
+	        .setPriority(SDNIP_PRIORITY)
+	        .setLengthU(OFFlowMod.MINIMUM_LENGTH);
+	        		//+ OFActionDataLayerDestination.MINIMUM_LENGTH
+	        		//+ OFActionOutput.MINIMUM_LENGTH);
+	        
+	        OFMatch match = new OFMatch();
+	        match.setDataLayerType(Ethernet.TYPE_IPv4);
+	        match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	        
+	        //match.setDataLayerSource(ingressRouter.getRouterMac().toBytes());
+	        //match.setDataLayerSource(peer.getMacAddress().toBytes());
+	        //match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_SRC);
+	        
+	        InetAddress address = null;
+	        try {
+				address = InetAddress.getByAddress(node.key);
+			} catch (UnknownHostException e1) {
+				//Should never happen is the reverse conversion has already been done
+				log.error("Malformed IP address");
+				return;
+			}
+	        
+	        match.setFromCIDR(address.getHostAddress() + "/" + node.rib.masklen, OFMatch.STR_NW_DST);
+	        fm.setMatch(match);
+	        
+	        //Write to switch
+	        IOFSwitch sw = floodlightProvider.getSwitches()
+	        		.get(srcInterface.getDpid());
+	        
+            if (sw == null){
+            	log.warn("Switch not found when pushing flow mod");
+            	continue;
+            }
+            
+            List<OFMessage> msglist = new ArrayList<OFMessage>();
+            msglist.add(fm);
+            try {
+				sw.write(msglist, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing flow mod", e);
+			}
+		}
+	}
+	
+	/*
+	 * On startup we need to calculate a full mesh of paths between all gateway
+	 * switches
+	 */
+	private void setupFullMesh(){
+		//For each border router, calculate and install a path from every other
+		//border switch to said border router. However, don't install the entry
+		//in to the first hop switch, as we need to install an entry to rewrite
+		//for each prefix received. This will be done later when prefixes have 
+		//actually been received.
+		
+		for (BgpPeer peer : bgpPeers.values()) {
+			Interface peerInterface = interfaces.get(peer.getInterfaceName());
+			//for (Map.Entry<String, Interface> intfEntry : interfaces.entrySet()) {
+			for (Interface srcInterface : interfaces.values()) {
+				//Interface srcInterface = intfEntry.getValue();
+				//if (peer.getInterfaceName().equals(intfEntry.getKey())){
+				if (peer.getInterfaceName().equals(srcInterface.getName())){
+					continue;
+				}
+				
+				DataPath shortestPath = topoRouteService.getShortestPath(
+							srcInterface.getSwitchPort(), peerInterface.getSwitchPort()); 
+				
+				if (shortestPath == null){
+					log.debug("Shortest path between {} and {} not found",
+							srcInterface.getSwitchPort(), peerInterface.getSwitchPort());
+					return; // just quit here?
+				}
+				
+				//install flows
+				installPath(shortestPath.flowEntries(), peer);
+			}
+		}
+	}
+	
+	private void installPath(List<FlowEntry> flowEntries, BgpPeer peer){
+		//Set up the flow mod
+		OFFlowMod fm =
+                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+                                              .getMessage(OFType.FLOW_MOD);
+		
+        OFActionOutput action = new OFActionOutput();
+        action.setMaxLength((short)0xffff);
+        List<OFAction> actions = new ArrayList<OFAction>();
+        actions.add(action);
+        
+        fm.setIdleTimeout((short)0)
+        .setHardTimeout((short)0)
+        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+        .setCookie(L2_FWD_COOKIE)
+        .setCommand(OFFlowMod.OFPFC_ADD)
+        .setActions(actions)
+        .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+        
+        //Don't push the first flow entry. We need to push entries in the
+		//first switch based on IP prefix which we don't know yet.
+        for (int i = 1; i < flowEntries.size(); i++){        	
+        	FlowEntry flowEntry = flowEntries.get(i);
+           
+            OFMatch match = new OFMatch();
+            //TODO Again using MAC address from configuration
+            match.setDataLayerDestination(peer.getMacAddress().toBytes());
+            match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
+            ((OFActionOutput) fm.getActions().get(0)).setPort(flowEntry.outPort().value());
+            
+            fm.setMatch(match);
+            
+            IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
+            
+            if (sw == null){
+            	log.warn("Switch not found when pushing flow mod");
+            	continue;
+            }
+            
+            List<OFMessage> msglist = new ArrayList<OFMessage>();
+            msglist.add(fm);
+            try {
+				sw.write(msglist, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing flow mod", e);
+			}
+            
+            try {
+                fm = fm.clone();
+            } catch (CloneNotSupportedException e1) {
+                log.error("Failure cloning flow mod", e1);
+            }
+		}
+	}
+	
+	private void setupBgpPaths(){
+		for (BgpPeer bgpPeer : bgpPeers.values()){
+			Interface peerInterface = interfaces.get(bgpPeer.getInterfaceName());
+			
+			DataPath path = topoRouteService.getShortestPath(
+					peerInterface.getSwitchPort(), bgpdAttachmentPoint);
+			
+			if (path == null){
+				log.debug("Unable to compute path for BGP traffic for {}",
+							bgpPeer.getIpAddress());
+				continue;
+			}
+			
+			//Set up the flow mod
+			OFFlowMod fm =
+	                (OFFlowMod) floodlightProvider.getOFMessageFactory()
+	                                              .getMessage(OFType.FLOW_MOD);
+			
+	        OFActionOutput action = new OFActionOutput();
+	        action.setMaxLength((short)0xffff);
+	        List<OFAction> actions = new ArrayList<OFAction>();
+	        actions.add(action);
+	        
+	        fm.setIdleTimeout((short)0)
+	        .setHardTimeout((short)0)
+	        .setBufferId(OFPacketOut.BUFFER_ID_NONE)
+	        .setCookie(BGP_COOKIE)
+	        .setCommand(OFFlowMod.OFPFC_ADD)
+	        .setPriority(SDNIP_PRIORITY)
+	        .setActions(actions)
+	        .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+
+	        //Forward = gateway -> bgpd, reverse = bgpd -> gateway
+	        OFMatch forwardMatchSrc = new OFMatch();
+	        
+	        
+	        String interfaceCidrAddress = peerInterface.getIpAddress().getHostAddress() 
+	        					+ "/32";
+	        String peerCidrAddress = bgpPeer.getIpAddress().getHostAddress()
+	        					+ "/32";
+	        	        
+	        //Common match fields
+	        forwardMatchSrc.setDataLayerType(Ethernet.TYPE_IPv4);
+	        //forwardMatch.setWildcards(forwardMatch.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	        forwardMatchSrc.setNetworkProtocol(IPv4.PROTOCOL_TCP);
+	        forwardMatchSrc.setTransportDestination(BGP_PORT);
+	        forwardMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_IN_PORT
+	        				& ~OFMatch.OFPFW_DL_TYPE & ~OFMatch.OFPFW_NW_PROTO);
+	        
+	        
+	        OFMatch reverseMatchSrc = forwardMatchSrc.clone();
+	        
+	        forwardMatchSrc.setFromCIDR(peerCidrAddress, OFMatch.STR_NW_SRC);
+	        forwardMatchSrc.setFromCIDR(interfaceCidrAddress, OFMatch.STR_NW_DST);
+	        
+	        OFMatch forwardMatchDst = forwardMatchSrc.clone();
+	        
+	        forwardMatchSrc.setTransportSource(BGP_PORT);
+	        forwardMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+	        forwardMatchDst.setTransportDestination(BGP_PORT);
+	        forwardMatchDst.setWildcards(forwardMatchDst.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+	        
+	        reverseMatchSrc.setFromCIDR(interfaceCidrAddress, OFMatch.STR_NW_SRC);
+	        reverseMatchSrc.setFromCIDR(peerCidrAddress, OFMatch.STR_NW_DST);
+	        
+	        OFMatch reverseMatchDst = reverseMatchSrc.clone();
+	        
+	        reverseMatchSrc.setTransportSource(BGP_PORT);
+	        reverseMatchSrc.setWildcards(forwardMatchSrc.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+	        reverseMatchDst.setTransportDestination(BGP_PORT);
+	        reverseMatchDst.setWildcards(forwardMatchDst.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+	        
+	        fm.setMatch(forwardMatchSrc);
+	        
+			for (FlowEntry flowEntry : path.flowEntries()){
+				OFFlowMod forwardFlowModSrc, forwardFlowModDst;
+				OFFlowMod reverseFlowModSrc, reverseFlowModDst;
+				try {
+					forwardFlowModSrc = fm.clone();
+					forwardFlowModDst = fm.clone();
+					reverseFlowModSrc = fm.clone();
+					reverseFlowModDst = fm.clone();
+				} catch (CloneNotSupportedException e) {
+					log.warn("Clone failed", e);
+					continue;
+				}
+				
+				forwardMatchSrc.setInputPort(flowEntry.inPort().value());
+				forwardFlowModSrc.setMatch(forwardMatchSrc);
+				((OFActionOutput)forwardFlowModSrc.getActions().get(0))
+						.setPort(flowEntry.outPort().value());
+				
+				forwardMatchDst.setInputPort(flowEntry.inPort().value());
+				forwardFlowModDst.setMatch(forwardMatchDst);
+				((OFActionOutput)forwardFlowModDst.getActions().get(0))
+						.setPort(flowEntry.outPort().value());
+				
+				reverseMatchSrc.setInputPort(flowEntry.outPort().value());
+				reverseFlowModSrc.setMatch(reverseMatchSrc);
+				((OFActionOutput)reverseFlowModSrc.getActions().get(0))
+						.setPort(flowEntry.inPort().value());
+				
+				reverseMatchDst.setInputPort(flowEntry.outPort().value());
+				reverseFlowModDst.setMatch(reverseMatchDst);
+				((OFActionOutput)reverseFlowModDst.getActions().get(0))
+						.setPort(flowEntry.inPort().value());
+				
+				IOFSwitch sw = floodlightProvider.getSwitches().get(flowEntry.dpid().value());
+				
+				//Hopefully the switch is there
+				List<OFMessage> msgList = new ArrayList<OFMessage>(2);
+				msgList.add(forwardFlowModSrc);
+				msgList.add(forwardFlowModDst);
+				msgList.add(reverseFlowModSrc);
+				msgList.add(reverseFlowModDst);
+				
+				try {
+					sw.write(msgList, null);
+					sw.flush();
+				} catch (IOException e) {
+					log.error("Failure writing flow mod", e);
+				}
+			}
+		}
+	}
+	
+	private void beginRouting(){
+		log.debug("Topology is now ready, beginning routing function");
+		setupBgpPaths();
+		setupFullMesh();
+		
+		//Traverse ptree and create flows for all routes
+		for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)){
+			if (node.rib != null){
+				prefixAdded(node);
+			}
+		}
+	}
+	
+	private void checkSwitchesConnected(){
+		for (String dpid : switches){
+			if (floodlightProvider.getSwitches().get(HexString.toLong(dpid)) == null){
+				log.debug("Not all switches are here yet");
+				return;
+			}
+		}
+		switchesConnected = true;
+	}
+	
+	//Actually we only need to go half way round to verify full mesh connectivity
+	//(n^2)/2
+	private void checkTopologyReady(){
+		for (Interface dstInterface : interfaces.values()) {
+			for (Interface srcInterface : interfaces.values()) {			
+				if (dstInterface == srcInterface) {
+					continue;
+				}
+				
+				DataPath shortestPath = topoRouteService.getShortestPath(
+						srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
+				
+				if (shortestPath == null){
+					log.debug("Shortest path between {} and {} not found",
+							srcInterface.getSwitchPort(), dstInterface.getSwitchPort());
+					return;
+				}
+			}
+		}
+		topologyReady = true;
+	}
+	
+	private void checkStatus(){
+		log.debug("In checkStatus, swC {}, toRe {}", switchesConnected, topologyReady);
+		
+		if (!switchesConnected){
+			checkSwitchesConnected();
+		}
+		boolean oldTopologyReadyStatus = topologyReady;
+		if (switchesConnected && !topologyReady){
+			checkTopologyReady();
+		}
+		if (!oldTopologyReadyStatus && topologyReady){
+			beginRouting();
+		}
+	}
+	
+	@Override
+	public void startUp(FloodlightModuleContext context) {
+		restApi.addRestletRoutable(new BgpRouteWebRoutable());
+		floodlightProvider.addOFSwitchListener(this);
+		topology.addListener(this);
+		
+		floodlightProvider.addOFMessageListener(OFType.PACKET_IN, proxyArp);
+		
+		ExecutorService e = Executors.newSingleThreadExecutor(
+				new ThreadFactoryBuilder().setNameFormat("bgp-updates-%d").build());
+		
+		
+		e.execute(new Runnable() {
+			@Override
+			public void run() {
+				doUpdatesThread();
+			}
+		});
+		
+		//Retrieve the RIB from BGPd during startup
+		retrieveRib();
+	}
+	
+	private void doUpdatesThread() {
+		boolean interrupted = false;
+		try {
+			while (true) {
+				try {
+					RibUpdate update = ribUpdates.take();
+					switch (update.getOperation()){
+					case UPDATE:
+						wrapPrefixAdded(update);
+						break;
+					case DELETE:
+						wrapPrefixDeleted(update);
+						break;
+					}
+				} catch (InterruptedException e) {
+					interrupted = true;
+				}
+			}
+		} finally {
+			if (interrupted) {
+				Thread.currentThread().interrupt();
+			}
+		}
+	}
+
+	@Override
+	public void topologyChanged() {		
+		//There seems to be more topology events than there should be. Lots of link
+		//updated, port up and switch updated on what should be a fairly static topology
+		
+		boolean refreshNeeded = false;
+		for (LDUpdate ldu : topology.getLastLinkUpdates()){
+			if (!ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_UPDATED)){
+				//We don't need to recalculate anything for just link updates
+				//They happen way too frequently (may be a bug in our link discovery)
+				refreshNeeded = true;
+			}
+			
+			log.debug("Topo change {}", ldu.getOperation());
+			
+			if (ldu.getOperation().equals(ILinkDiscovery.UpdateOperation.LINK_ADDED)){
+				synchronized (linkUpdates) {
+					linkUpdates.add(ldu);
+				}
+			}
+		}
+		
+		if (refreshNeeded){
+			topologyChangeDetectorTask.reschedule(TOPO_DETECTION_WAIT, TimeUnit.SECONDS);
+		}
+	}
+
+	//TODO determine whether we need to listen for switch joins
+	@Override
+	public void addedSwitch(IOFSwitch sw) {
+		//checkStatus();
+	}
+
+	@Override
+	public void removedSwitch(IOFSwitch sw) {
+		// TODO Auto-generated method stub	
+	}
+
+	@Override
+	public void switchPortChanged(Long switchId) {}
+
+	@Override
+	public String getName() {
+		return "BgpRoute";
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
new file mode 100644
index 0000000..19b44c8
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResource.java
@@ -0,0 +1,233 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.UnknownHostException;
+
+import net.onrc.onos.ofcontroller.bgproute.RibUpdate.Operation;
+
+import org.restlet.resource.Delete;
+import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpRouteResource extends ServerResource {
+
+	protected static Logger log = LoggerFactory.getLogger(BgpRouteResource.class);
+
+	private String addrToString(byte [] addr) {
+		String str = "";
+
+		for (int i = 0; i < 4; i++) {
+			int val = (addr[i] & 0xff);
+			str += val;
+			if (i != 3)
+				str += ".";
+		}
+
+		return str;
+	}
+
+	//@SuppressWarnings("unused")
+	@Get
+	public String get(String fmJson) {
+		String dest = (String) getRequestAttributes().get("dest");
+		String output = "";
+		IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+				get(IBgpRouteService.class.getCanonicalName());
+
+		if (dest != null) {
+			//TODO Needs to be changed to use the new RestClient.get().
+			
+			
+			//Prefix p;
+			//try {
+			//	p = new Prefix(dest, 32);
+			//} catch (UnknownHostException e) {
+			//if (p == null) {
+			//	return "[GET]: dest address format is wrong";
+			//}
+
+			// the dest here refers to router-id
+			//bgpdRestIp includes port number, such as 1.1.1.1:8080
+			String BGPdRestIp = bgpRoute.getBGPdRestIp();
+			String url="http://"+BGPdRestIp+"/wm/bgp/"+dest;
+
+			RestClient.get(url);
+			
+			output="Get rib from bgpd finished!\n";
+			return output;
+		} 
+		else {
+			Ptree ptree = bgpRoute.getPtree();
+			output += "{\n  \"rib\": [\n";
+			boolean printed = false;
+			
+			for (PtreeNode node = ptree.begin(); node != null; node = ptree.next(node)) {
+				if (node.rib == null) {
+					continue;
+				}
+				if (printed == true) {
+					output += ",\n";
+				}
+				output += "    {\"prefix\": \"" + addrToString(node.key) + "/" + node.keyBits +"\", ";
+				output += "\"nexthop\": \"" + addrToString(node.rib.nextHop.getAddress()) +"\"}";
+				printed = true;
+			}
+			//output += "{\"router_id\": \"" + addrToString(node.rib.routerId.getAddress()) +"\"}\n";
+			output += "\n  ]\n}\n";
+		}
+		
+		return output;
+	}
+
+	//unused?
+	/*
+	public static ByteBuffer toByteBuffer(String value) throws UnsupportedEncodingException {
+		return ByteBuffer.wrap(value.getBytes("UTF-8"));
+	}
+	*/
+
+	//unused?
+	/*
+	public static String toString(ByteBuffer buffer) throws UnsupportedEncodingException {
+		byte[] bytes = new byte[buffer.remaining()];
+		buffer.get(bytes);
+		return new String(bytes, "UTF-8");
+	}
+	*/
+
+	@Post
+	public String store(String fmJson) {
+		IBgpRouteService bgpRoute = (IBgpRouteService) getContext().getAttributes().
+				get(IBgpRouteService.class.getCanonicalName());
+
+		//Ptree ptree = bgpRoute.getPtree();
+
+		String routerId = (String) getRequestAttributes().get("routerid");
+		String prefix = (String) getRequestAttributes().get("prefix");
+		String mask = (String) getRequestAttributes().get("mask");
+		String nexthop = (String) getRequestAttributes().get("nexthop");
+		String capability = (String) getRequestAttributes().get("capability");
+
+		String reply = "";
+
+		if (capability == null) {
+			// this is a prefix add
+			Prefix p;
+			try {
+				p = new Prefix(prefix, Integer.valueOf(mask));
+			} catch (NumberFormatException e) {
+				reply = "[POST: mask format is wrong]";
+				log.info(reply);
+				return reply + "\n";				
+			} catch (UnknownHostException e1) {
+				reply = "[POST: prefix format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			}
+			
+			Rib rib = new Rib(routerId, nexthop, p.getPrefixLength());
+
+			bgpRoute.newRibUpdate(new RibUpdate(Operation.UPDATE, p, rib));
+			
+			/*
+			PtreeNode node = ptree.acquire(p.getAddress(), p.getPrefixLength());
+			
+			if (node.rib != null) {
+				node.rib = null;
+				ptree.delReference(node);
+			}
+			node.rib = rib;
+
+			bgpRoute.prefixAdded(node);
+			*/
+			
+			reply = "[POST: " + prefix + "/" + mask + ":" + nexthop + "]";
+			log.info(reply);
+		}
+		else if(capability.equals("1")) {
+			reply = "[POST-capability: " + capability + "]\n";
+			log.info(reply);
+			// to store the number in the top node of the Ptree	
+		}
+		else {			
+			reply = "[POST-capability: " + capability + "]\n";
+			log.info(reply);
+			// to store the number in the top node of the Ptree	
+		}
+
+		return reply + "\n";
+	}
+
+	@Delete
+	public String delete(String fmJson) {
+		IBgpRouteService bgpRoute = (IBgpRouteService)getContext().getAttributes().
+				get(IBgpRouteService.class.getCanonicalName());
+
+		//Ptree ptree = bgpRoute.getPtree();
+
+		String routerId = (String) getRequestAttributes().get("routerid");
+		String prefix = (String) getRequestAttributes().get("prefix");
+		String mask = (String) getRequestAttributes().get("mask");
+		String nextHop = (String) getRequestAttributes().get("nexthop");
+		String capability = (String) getRequestAttributes().get("capability");
+
+		String reply = "";
+
+		if (capability == null) {
+			// this is a prefix delete
+			Prefix p;
+			try {
+				p = new Prefix(prefix, Integer.valueOf(mask));
+			} catch (NumberFormatException e) {
+				reply = "[DELE: mask format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			} catch (UnknownHostException e1) {
+				reply = "[DELE: prefix format is wrong]";
+				log.info(reply);
+				return reply + "\n";
+			}
+			
+			Rib r = new Rib(routerId, nextHop, p.getPrefixLength());
+			
+			bgpRoute.newRibUpdate(new RibUpdate(Operation.DELETE, p, r));
+			
+			/*
+			PtreeNode node = ptree.lookup(p.getAddress(), p.getPrefixLength());
+			
+			//Remove the flows from the switches before the rib is lost
+			//Theory: we could get a delete for a prefix not in the Ptree.
+			//This would result in a null node being returned. We could get a delete for
+			//a node that's not actually there, but is a aggregate node. This would result
+			//in a non-null node with a null rib. Only a non-null node with a non-null
+			//rib is an actual prefix in the Ptree.
+			if (node != null && node.rib != null){
+				bgpRoute.prefixDeleted(node);
+			}
+
+			
+
+			if (node != null && node.rib != null) {
+				if (r.equals(node.rib)) {
+					node.rib = null;
+					ptree.delReference(node);					
+				}
+			}
+			*/
+			
+			reply =reply + "[DELE: " + prefix + "/" + mask + ":" + nextHop + "]";
+		}
+		else {
+			// clear the local rib: Ptree			
+			bgpRoute.clearPtree();
+			reply = "[DELE-capability: " + capability + "; The local Rib is cleared!]\n";
+
+			// to store the number in the top node of the Ptree	
+		}
+		
+		log.info(reply);
+		return reply + "\n";
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java
similarity index 92%
rename from src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java
rename to src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java
index d0c337a..543827d 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteResourceSynch.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteResourceSynch.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.bgproute;
+package net.onrc.onos.ofcontroller.bgproute;
 
 
 import org.restlet.resource.Post;
@@ -6,7 +6,6 @@
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import net.floodlightcontroller.restclient.RestClient;
 
 
 public class BgpRouteResourceSynch extends ServerResource {
@@ -29,7 +28,7 @@
 				
 			String BGPdRestIp = bgpRoute.getBGPdRestIp();	
 				
-			//BGPdRestIp includes port number, such as 1.1.1.1:8080
+			//bgpdRestIp includes port number, such as 1.1.1.1:8080
 			RestClient.post("http://"+BGPdRestIp+"/wm/bgp/"+router_id+"/"+prefix+"/"+mask+"/"+nexthop);
 			}catch(Exception e)
 			{e.printStackTrace();}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
similarity index 94%
rename from src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java
rename to src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
index a18c550..669c385 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/BgpRouteWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/BgpRouteWebRoutable.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.bgproute;
+package net.onrc.onos.ofcontroller.bgproute;
 
 import org.restlet.Context;
 import org.restlet.Restlet;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Configuration.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Configuration.java
new file mode 100644
index 0000000..c3c8cbb
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Configuration.java
@@ -0,0 +1,75 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.openflow.util.HexString;
+
+public class Configuration {
+	private long bgpdAttachmentDpid;
+	private short bgpdAttachmentPort;
+	private List<String> switches;
+	private List<Interface> interfaces;
+	private List<BgpPeer> peers;
+	//private Map<String, GatewayRouter> gateways;
+	
+	public Configuration() {
+		// TODO Auto-generated constructor stub
+	}
+
+	public long getBgpdAttachmentDpid() {
+		return bgpdAttachmentDpid;
+	}
+
+	@JsonProperty("bgpdAttachmentDpid")
+	public void setBgpdAttachmentDpid(String bgpdAttachmentDpid) {
+		this.bgpdAttachmentDpid = HexString.toLong(bgpdAttachmentDpid);
+	}
+
+	public short getBgpdAttachmentPort() {
+		return bgpdAttachmentPort;
+	}
+
+	@JsonProperty("bgpdAttachmentPort")
+	public void setBgpdAttachmentPort(short bgpdAttachmentPort) {
+		this.bgpdAttachmentPort = bgpdAttachmentPort;
+	}
+
+	public List<String> getSwitches() {
+		return switches;
+	}
+
+	@JsonProperty("switches")
+	public void setSwitches(List<String> switches) {
+		this.switches = switches;
+	}
+
+	public List<Interface> getInterfaces() {
+		return interfaces;
+	}
+
+	@JsonProperty("interfaces")
+	public void setInterfaces(List<Interface> interfaces) {
+		this.interfaces = interfaces;
+	}
+	
+	public List<BgpPeer> getPeers() {
+		return peers;
+	}
+
+	@JsonProperty("bgpPeers")
+	public void setPeers(List<BgpPeer> peers) {
+		this.peers = peers;
+	}
+
+	/*
+	public Map<String, GatewayRouter> getGateways() {
+		return gateways;
+	}
+
+	@JsonProperty("gateways")
+	public void setGateways(Map<String, GatewayRouter> gateways) {
+		this.gateways = gateways;
+	}*/
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java
new file mode 100644
index 0000000..e893acf
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/GatewayRouter.java
@@ -0,0 +1,72 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.IPv4;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.openflow.util.HexString;
+
+public class GatewayRouter {
+	private SwitchPort attachmentPoint = null;
+	private long dpid;
+	private short port;
+	private MACAddress routerMac;
+	private IPv4 routerIp;
+	private IPv4 myIpAddress;
+	
+	
+	public SwitchPort getAttachmentPoint() {
+		if (attachmentPoint == null){
+			attachmentPoint = new SwitchPort(new Dpid(dpid), new Port(port));
+		}
+		return attachmentPoint;
+	}
+	
+	public long getDpid() {
+		return dpid;
+	}
+
+	@JsonProperty("attachmentDpid")
+	public void setDpid(String dpid) {
+		this.dpid = HexString.toLong(dpid);
+	}
+
+	public short getPort() {
+		return port;
+	}
+
+	@JsonProperty("attachmentPort")
+	public void setPort(short port) {
+		this.port = port;
+	}
+
+	public MACAddress getRouterMac() {
+		return routerMac;
+	}
+	
+	@JsonProperty("macAddress")
+	public void setRouterMac(String routerMac) {
+		this.routerMac = MACAddress.valueOf(routerMac);;
+	}
+
+	public IPv4 getRouterIp() {
+		return routerIp;
+	}
+	
+	@JsonProperty("ipAddress")
+	public void setRouterIp(String routerIp) {
+		this.routerIp = new IPv4(routerIp);
+	}
+	
+	public IPv4 getMyIpAddress() {
+		return myIpAddress;
+	}
+	
+	@JsonProperty("myIpAddress")
+	public void setMyIpAddress(String myIpAddress) {
+		this.myIpAddress = new IPv4(myIpAddress);
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
new file mode 100644
index 0000000..3dbc940
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/IBgpRouteService.java
@@ -0,0 +1,26 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import net.floodlightcontroller.core.module.IFloodlightService;
+
+public interface IBgpRouteService extends IFloodlightService {
+
+	public Rib lookupRib(byte[] dest);
+
+	public Ptree getPtree();
+
+	public String getBGPdRestIp();
+
+	public String getRouterId();
+
+	public void clearPtree();
+	
+	/**
+	 * Pass a RIB update to the {@link IBgpRouteService}
+	 * @param update
+	 */
+	public void newRibUpdate(RibUpdate update);
+	
+	//TODO This functionality should be provided by some sort of Ptree listener framework
+	public void prefixAdded(PtreeNode node);
+	public void prefixDeleted(PtreeNode node);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Interface.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Interface.java
new file mode 100644
index 0000000..088c18e
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Interface.java
@@ -0,0 +1,73 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.InetAddress;
+
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.openflow.util.HexString;
+
+import com.google.common.net.InetAddresses;
+
+public class Interface {
+	private String name;
+	private SwitchPort switchPort = null;
+	private long dpid;
+	private short port;
+	private InetAddress ipAddress;
+	private int prefixLength;
+	
+	public String getName() {
+		return name;
+	}
+
+	@JsonProperty("name")
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public synchronized SwitchPort getSwitchPort() {
+		if (switchPort == null){
+			switchPort = new SwitchPort(new Dpid(dpid), new Port(port));
+		}
+		return switchPort;
+	}
+	
+	public long getDpid() {
+		return dpid;
+	}
+
+	@JsonProperty("dpid")
+	public void setDpid(String dpid) {
+		this.dpid = HexString.toLong(dpid);
+	}
+
+	public short getPort() {
+		return port;
+	}
+
+	@JsonProperty("port")
+	public void setPort(short port) {
+		this.port = port;
+	}
+
+	public InetAddress getIpAddress() {
+		return ipAddress;
+	}
+
+	@JsonProperty("ipAddress")
+	public void setIpAddress(String ipAddress) {
+		this.ipAddress = InetAddresses.forString(ipAddress);
+	}
+
+	public int getPrefixLength() {
+		return prefixLength;
+	}
+
+	@JsonProperty("prefixLength")
+	public void setPrefixLength(int prefixLength) {
+		this.prefixLength = prefixLength;
+	}
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
new file mode 100644
index 0000000..4d7c53a
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Prefix.java
@@ -0,0 +1,43 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+public class Prefix {
+	private int prefixLength;
+	private InetAddress address;
+
+	public Prefix(byte[] addr, int prefixLength) throws UnknownHostException {
+		//try {
+		address = InetAddress.getByAddress(addr);
+		//} catch (UnknownHostException e) {
+		//	System.out.println("InetAddress exception");
+		//	return;
+		//}
+		this.prefixLength = prefixLength;
+		//System.out.println(address.toString() + "/" + prefixLength);
+	}
+
+	public Prefix(String str, int prefixLength) throws UnknownHostException {
+		//try {
+		address = InetAddress.getByName(str);
+		//} catch (UnknownHostException e) {
+		//	System.out.println("InetAddress exception");
+		//	return;
+		//}
+		this.prefixLength = prefixLength;
+	}
+
+	public int getPrefixLength() {
+		return prefixLength;
+	}
+	
+	public byte[] getAddress() {
+		return address.getAddress();
+	}
+	
+	@Override
+	public String toString() {
+		return address.getHostAddress() + "/" + prefixLength;
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/Ptree.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
similarity index 80%
rename from src/main/java/net/floodlightcontroller/bgproute/Ptree.java
rename to src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
index dcb6e83..041061c 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/Ptree.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Ptree.java
@@ -1,24 +1,33 @@
-package net.floodlightcontroller.bgproute;
+package net.onrc.onos.ofcontroller.bgproute;
 
+/*
+ * TODO This Ptree needs to be refactored if we're going to use it permenantly.
+ *
+ * The biggest problem is it leaks PTreeNode references - these need to stay within
+ * the Ptree as they contain data fundamental to the structure of the tree.
+ * You should put RIB entries in and get RIB entries out.
+ * Also we need to get rid of the referencing scheme to determine when to delete nodes.
+ * Deletes should be explicit, and there's no need to keep track of references if 
+ * we don't leak them out the the Ptree.
+ */
 public class Ptree {
-	int maxKeyBits;
-	int maxKeyOctets;
-	int refCount;
-	PtreeNode top;
-	byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
+	private int maxKeyBits;
+	private int maxKeyOctets;
+	//private int refCount;
+	private PtreeNode top;
+	private byte maskBits[] = { (byte)0x00, (byte)0x80, (byte)0xc0, (byte)0xe0, (byte)0xf0, (byte)0xf8, (byte)0xfc, (byte)0xfe, (byte)0xff };
 	
-	// Constructor.
-	Ptree(int max_key_bits) {
+	public Ptree(int max_key_bits) {
 		maxKeyBits = max_key_bits;
 		maxKeyOctets = bit_to_octet(max_key_bits); 
-		refCount = 0;
+		//refCount = 0;
 	}
 	
-	public PtreeNode acquire(byte [] key) {
+	public synchronized PtreeNode acquire(byte [] key) {
 		return acquire(key, maxKeyBits);
 	}
 	
-	public PtreeNode acquire(byte [] key, int key_bits) {
+	public synchronized PtreeNode acquire(byte [] key, int key_bits) {
 		if (key_bits > maxKeyBits) {
 			return null;
 		}
@@ -76,7 +85,7 @@
 		return addReference(add);
 	}
 
-	public PtreeNode lookup(byte [] key, int key_bits) {
+	public synchronized PtreeNode lookup(byte [] key, int key_bits) {
 		if (key_bits > maxKeyBits) {
 			return null;
 		}
@@ -99,7 +108,7 @@
 		return null;
 	}
 	
-	public PtreeNode match(byte [] key, int key_bits) {
+	public synchronized PtreeNode match(byte [] key, int key_bits) {
 		if (key_bits > maxKeyBits) {
 			return null;
 		}
@@ -127,14 +136,14 @@
 		return null;
 	}
 	
-	public PtreeNode begin() {
+	public synchronized PtreeNode begin() {
 		if (top == null) {
 			return null;
 		}
 		return addReference(top);
 	}
 	
-	public PtreeNode next(PtreeNode node) {
+	public synchronized PtreeNode next(PtreeNode node) {
 		PtreeNode next;
 		
 		if (node.left != null) {
@@ -175,7 +184,7 @@
 		return node;
 	}
 	
-	public void delReference(PtreeNode node) {
+	public synchronized void delReference(PtreeNode node) {
 		if (node.refCount > 0) {
 			node.refCount--;
 		}
@@ -278,10 +287,6 @@
 		
 		return add;
 	}
-	//add by linpp
-	private void clear() {
-	
-	}
 	
 	private void node_remove(PtreeNode node) {
 		PtreeNode child;
diff --git a/src/main/java/net/floodlightcontroller/bgproute/PtreeNode.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/bgproute/PtreeNode.java
rename to src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java
index 4d2c265..a4d6996 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/PtreeNode.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/PtreeNode.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.bgproute;
+package net.onrc.onos.ofcontroller.bgproute;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java
new file mode 100644
index 0000000..f6f1a03
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RestClient.java
@@ -0,0 +1,104 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.httpclient.ConnectTimeoutException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class RestClient {
+	protected static Logger log = LoggerFactory.getLogger(RestClient.class);
+
+	public static String get(String str) {
+		StringBuilder response = new StringBuilder();
+
+		try {
+
+			URL url = new URL(str);
+			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+			conn.setConnectTimeout(2 * 1000); //2 seconds
+			conn.setRequestMethod("GET");
+			conn.setRequestProperty("Accept", "application/json");
+
+			if (conn.getResponseCode() != 200) {
+				throw new RuntimeException("Failed : HTTP error code : "
+						+ conn.getResponseCode());
+			}
+
+			if (!conn.getContentType().equals("application/json")){	
+				log.warn("The content received from {} is not json", str);
+			}		
+
+			BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 
+			String line;
+			while ((line = br.readLine()) != null) {
+				response.append(line);
+			}
+			
+			br.close();
+			conn.disconnect();
+			
+		} catch (MalformedURLException e) {
+			log.error("Malformed URL for GET request", e);
+		} catch (ConnectTimeoutException e) {
+			log.warn("Couldn't connect remote REST server");
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+		
+		return response.toString();
+	}
+
+	public static void post (String str) {
+
+		try {
+			URL url = new URL(str);
+			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+			conn.setDoOutput(true);
+			conn.setRequestMethod("POST");
+			conn.setRequestProperty("Content-Type", "application/json");		
+
+			if (conn.getResponseCode() != 200) {
+				throw new RuntimeException("Failed : HTTP error code : "
+						+ conn.getResponseCode());
+			}
+
+			conn.disconnect();
+
+		} catch (MalformedURLException e) {
+			log.error("Malformed URL for GET request", e);
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+	}
+
+
+	public static void delete (String str) {
+
+		try {
+			URL url = new URL(str);
+			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+			conn.setRequestMethod("DELETE");
+			conn.setRequestProperty("Accept", "application/json");
+
+
+			if (conn.getResponseCode() != 200) {
+				throw new RuntimeException("Failed : HTTP error code : "
+						+ conn.getResponseCode());
+			}
+
+			conn.disconnect();
+
+		} catch (MalformedURLException e) {
+			log.error("Malformed URL for GET request", e);
+		} catch (IOException e) {
+			log.warn("Couldn't connect remote REST server");
+		}
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/bgproute/Rib.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/bgproute/Rib.java
rename to src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java
index 574e820..dc5f71d 100644
--- a/src/main/java/net/floodlightcontroller/bgproute/Rib.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/Rib.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.bgproute;
+package net.onrc.onos.ofcontroller.bgproute;
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java
new file mode 100644
index 0000000..c7272bd
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/bgproute/RibUpdate.java
@@ -0,0 +1,27 @@
+package net.onrc.onos.ofcontroller.bgproute;
+
+public class RibUpdate {
+	public enum Operation {UPDATE, DELETE}; 
+	
+	private Operation operation;
+	private Prefix prefix;
+	private Rib ribEntry;
+	
+	public RibUpdate(Operation operation, Prefix prefix, Rib ribEntry) {
+		this.operation = operation;
+		this.prefix = prefix;
+		this.ribEntry = ribEntry;
+	}
+
+	public Operation getOperation() {
+		return operation;
+	}
+
+	public Prefix getPrefix() {
+		return prefix;
+	}
+
+	public Rib getRibEntry() {
+		return ribEntry;
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
similarity index 70%
rename from src/main/java/net/floodlightcontroller/devicemanager/IDeviceStorage.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
index f41e32c..7310d8c 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/IDeviceStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IDeviceStorage.java
@@ -1,7 +1,7 @@
-package net.floodlightcontroller.devicemanager;
+package net.onrc.onos.ofcontroller.core;
 
-import net.floodlightcontroller.core.INetMapStorage;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.floodlightcontroller.devicemanager.IDevice;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
 
 public interface IDeviceStorage extends INetMapStorage {
 	
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
similarity index 86%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/ILinkStorage.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
index eb2fac9..b56cfef 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/ILinkStorage.java
@@ -1,9 +1,9 @@
-package net.floodlightcontroller.linkdiscovery;
+package net.onrc.onos.ofcontroller.core;
 
 import java.util.List;
 
-import net.floodlightcontroller.core.INetMapStorage;
 import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
 
 public interface ILinkStorage extends INetMapStorage {
 	
@@ -17,7 +17,7 @@
 	/*
 	 *  Add Linkinfo
 	 */
-	public void addOrUpdateLink (Link link, LinkInfo linkinfo, DM_OPERATION op);
+	public void updateLink (Link link, LinkInfo linkinfo, DM_OPERATION op);
 	
 	/*
 	 * Delete a single link
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/INetMapService.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapService.java
new file mode 100644
index 0000000..8392a32
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapService.java
@@ -0,0 +1,5 @@
+package net.onrc.onos.ofcontroller.core;
+
+public interface INetMapService {
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapStorage.java
similarity index 90%
rename from src/main/java/net/floodlightcontroller/core/INetMapStorage.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/INetMapStorage.java
index 67c6631..b052540 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapStorage.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapStorage.java
@@ -1,7 +1,7 @@
 /**
  * 
  */
-package net.floodlightcontroller.core;
+package net.onrc.onos.ofcontroller.core;
 
 /**
  * @author pankaj
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
similarity index 68%
rename from src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
index 4a03327..9a96638 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyObjects.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjects.java
@@ -1,6 +1,6 @@
-package net.floodlightcontroller.core;
+package net.onrc.onos.ofcontroller.core;
 
-import net.floodlightcontroller.flowcache.web.DatapathSummarySerializer;
+import net.onrc.onos.ofcontroller.flowmanager.web.DatapathSummarySerializer;
 
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
@@ -11,8 +11,15 @@
 import com.tinkerpop.frames.Incidence;
 import com.tinkerpop.frames.Property;
 import com.tinkerpop.frames.annotations.gremlin.GremlinGroovy;
+import com.tinkerpop.frames.annotations.gremlin.GremlinParam;
 import com.tinkerpop.frames.VertexFrame;
 
+/*
+ * This is the interfaces to make the objects for Cassandra DB.
+ * They are interfaces, but it is also implementation,
+ * so this handles various control to the objects.  
+ * Please take a look at tinkerpop/frames annotation doc to understand more.
+ */
 public interface INetMapTopologyObjects {
 	
 public interface IBaseObject extends VertexFrame {
@@ -46,9 +53,9 @@
 		public Iterable<IPortObject> getPorts();
 
 // Requires Frames 2.3.0		
-//		@JsonIgnore
-//		@GremlinGroovy("_().out('on').has('number',port_num)")
-//		public IPortObject getPort(@GremlinParam("port_num") final short port_num);
+		@JsonIgnore
+		@GremlinGroovy("it.out('on').has('number',port_num)")
+		public IPortObject getPort(@GremlinParam("port_num") final short port_num);
 		
 		@Adjacency(label="on")
 		public void addPort(final IPortObject port);
@@ -57,12 +64,13 @@
 		public void removePort(final IPortObject port);
 		
 		@JsonIgnore
-		@GremlinGroovy("_().out('on').out('host')")
+		@GremlinGroovy("it.out('on').out('host')")
 		public Iterable<IDeviceObject> getDevices();
 		
 		@JsonIgnore
-		@Incidence(label="switch",direction = Direction.IN)
+		@Adjacency(label="switch",direction = Direction.IN)
 		public Iterable<IFlowEntry> getFlowEntries();
+
 	}
 	
 	public interface IPortObject extends IBaseObject{
@@ -71,6 +79,14 @@
 		@Property("number")
 		public Short getNumber();
 		
+		@JsonIgnore
+		@Property("port_id")
+		public void setPortId(String id);
+		
+		@JsonIgnore
+		@Property("port_id")
+		public String getPortId();
+		
 		@Property("number")
 		public void setNumber(Short n);
 		
@@ -89,7 +105,8 @@
 		public void setPortState(Integer s);
 		
 		@JsonIgnore
-		@Incidence(label="on",direction = Direction.IN)
+//		@GremlinGroovy("it.in('on')")
+		@Adjacency(label="on",direction = Direction.IN)
 		public ISwitchObject getSwitch();
 				
 		@JsonProperty("devices")
@@ -103,11 +120,11 @@
 		public void removeDevice(final IDeviceObject device);
 		
 		@JsonIgnore
-		@Incidence(label="inport",direction = Direction.IN)
+		@Adjacency(label="inport",direction = Direction.IN)
 		public Iterable<IFlowEntry> getInFlowEntries();
 		
 		@JsonIgnore
-		@Incidence(label="outport",direction = Direction.IN)
+		@Adjacency(label="outport",direction = Direction.IN)
 		public Iterable<IFlowEntry> getOutFlowEntries();
 		
 		@JsonIgnore
@@ -136,23 +153,23 @@
 		@JsonProperty("ipv4")
 		@Property("nw_addr")
 		public String getIPAddress();
-		@Property("dl_addr")
+		@Property("nw_addr")
 		public void setIPAddress(String ipaddr);
 		
 		@JsonIgnore
-		@Incidence(label="host",direction = Direction.IN)
+		@Adjacency(label="host",direction = Direction.IN)
 		public Iterable<IPortObject> getAttachedPorts();
 			
 		@JsonIgnore
-		@Incidence(label="host",direction=Direction.IN)
+		@Adjacency(label="host",direction=Direction.IN)
 		public void setHostPort(final IPortObject port);
 		
 		@JsonIgnore
-		@Incidence(label="host",direction=Direction.IN)
+		@Adjacency(label="host",direction=Direction.IN)
 		public void removeHostPort(final IPortObject port);
 		
 		@JsonIgnore
-		@GremlinGroovy("_().in('host').in('on')")
+		@GremlinGroovy("it.in('host').in('on')")
 		public Iterable<ISwitchObject> getSwitch();
 		
 /*		@JsonProperty("dpid")
@@ -183,6 +200,13 @@
 		@Property("installer_id")
 		public void setInstallerId(String installerId);
 
+		@JsonProperty("flowPathFlags")
+		@Property("flow_path_flags")
+		public Long getFlowPathFlags();
+
+		@Property("flow_path_flags")
+		public void setFlowPathFlags(Long flowPathFlags);
+
 		@JsonProperty("srcDpid")
 		@Property("src_switch")
 		public String getSrcSwitch();
@@ -229,13 +253,9 @@
 		@Adjacency(label="flow", direction=Direction.IN)
 		public void removeFlowEntry(final IFlowEntry flowEntry);
 
-		@JsonIgnore
-		@Property("matchEthernetFrameType")
-		public Short getMatchEthernetFrameType();
-
-		@Property("matchEthernetFrameType")
-		public void setMatchEthernetFrameType(Short matchEthernetFrameType);
-
+		//
+		// Matching fields
+		//
 		@JsonIgnore
 		@Property("matchSrcMac")
 		public String getMatchSrcMac();
@@ -251,6 +271,27 @@
 		public void setMatchDstMac(String matchDstMac);
 
 		@JsonIgnore
+		@Property("matchEthernetFrameType")
+		public Short getMatchEthernetFrameType();
+
+		@Property("matchEthernetFrameType")
+		public void setMatchEthernetFrameType(Short matchEthernetFrameType);
+
+		@JsonIgnore
+		@Property("matchVlanId")
+		public Short getMatchVlanId();
+
+		@Property("matchVlanId")
+		public void setMatchVlanId(Short matchVlanId);
+
+		@JsonIgnore
+		@Property("matchVlanPriority")
+		public Byte getMatchVlanPriority();
+
+		@Property("matchVlanPriority")
+		public void setMatchVlanPriority(Byte matchVlanPriority);
+
+		@JsonIgnore
 		@Property("matchSrcIPv4Net")
 		public String getMatchSrcIPv4Net();
 
@@ -263,9 +304,49 @@
 
 		@Property("matchDstIPv4Net")
 		public void setMatchDstIPv4Net(String matchDstIPv4Net);
-		
+
 		@JsonIgnore
-		@GremlinGroovy("_().in('flow').out('switch')")
+		@Property("matchIpProto")
+		public Byte getMatchIpProto();
+
+		@Property("matchIpProto")
+		public void setMatchIpProto(Byte matchIpProto);
+
+		@JsonIgnore
+		@Property("matchIpToS")
+		public Byte getMatchIpToS();
+
+		@Property("matchIpToS")
+		public void setMatchIpToS(Byte matchIpToS);
+
+		@JsonIgnore
+		@Property("matchSrcTcpUdpPort")
+		public Short getMatchSrcTcpUdpPort();
+
+		@Property("matchSrcTcpUdpPort")
+		public void setMatchSrcTcpUdpPort(Short matchSrcTcpUdpPort);
+
+		@JsonIgnore
+		@Property("matchDstTcpUdpPort")
+		public Short getMatchDstTcpUdpPort();
+
+		@Property("matchDstTcpUdpPort")
+		public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort);
+
+		//
+		// Action-related fields
+		//
+		@Property("actions")
+		public String getActions();
+
+		@Property("actions")
+		public void setActions(String actionsStr);
+
+		//
+		// Other fields
+		//
+		@JsonIgnore
+		@GremlinGroovy("it.in('flow').out('switch')")
 		public Iterable<ISwitchObject> getSwitches();
 		
 		@JsonIgnore
@@ -317,18 +398,15 @@
 		@Property("error_state_code")
 		public void setErrorStateCode(String errorStateCode);
 
+		//
+		// Matching fields
+		//
 		@Property("matchInPort")
 		public Short getMatchInPort();
 
 		@Property("matchInPort")
 		public void setMatchInPort(Short matchInPort);
 
-		@Property("matchEthernetFrameType")
-		public Short getMatchEthernetFrameType();
-
-		@Property("matchEthernetFrameType")
-		public void setMatchEthernetFrameType(Short matchEthernetFrameType);
-
 		@Property("matchSrcMac")
 		public String getMatchSrcMac();
 
@@ -341,6 +419,24 @@
 		@Property("matchDstMac")
 		public void setMatchDstMac(String matchDstMac);
 
+		@Property("matchEthernetFrameType")
+		public Short getMatchEthernetFrameType();
+
+		@Property("matchEthernetFrameType")
+		public void setMatchEthernetFrameType(Short matchEthernetFrameType);
+
+		@Property("matchVlanId")
+		public Short getMatchVlanId();
+
+		@Property("matchVlanId")
+		public void setMatchVlanId(Short matchVlanId);
+
+		@Property("matchVlanPriority")
+		public Byte getMatchVlanPriority();
+
+		@Property("matchVlanPriority")
+		public void setMatchVlanPriority(Byte matchVlanPriority);
+
 		@Property("matchSrcIPv4Net")
 		public String getMatchSrcIPv4Net();
 
@@ -353,12 +449,48 @@
 		@Property("matchDstIPv4Net")
 		public void setMatchDstIPv4Net(String matchDstIPv4Net);
 
-		@Property("actionOutput")
-		public Short getActionOutput();
+		@Property("matchIpProto")
+		public Byte getMatchIpProto();
 
-		@Property("actionOutput")
-		public void setActionOutput(Short actionOutput);
+		@Property("matchIpProto")
+		public void setMatchIpProto(Byte matchIpProto);
 
+		@Property("matchIpToS")
+		public Byte getMatchIpToS();
+
+		@Property("matchIpToS")
+		public void setMatchIpToS(Byte matchIpToS);
+
+		@Property("matchSrcTcpUdpPort")
+		public Short getMatchSrcTcpUdpPort();
+
+		@Property("matchSrcTcpUdpPort")
+		public void setMatchSrcTcpUdpPort(Short matchSrcTcpUdpPort);
+
+		@Property("matchDstTcpUdpPort")
+		public Short getMatchDstTcpUdpPort();
+
+		@Property("matchDstTcpUdpPort")
+		public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort);
+
+		//
+		// Action-related fields
+		//
+		@Property("actionOutputPort")
+		public Short getActionOutputPort();
+
+		@Property("actionOutputPort")
+		public void setActionOutputPort(Short actionOutputPort);
+
+		@Property("actions")
+		public String getActions();
+
+		@Property("actions")
+		public void setActions(String actionsStr);
+
+		//
+		// Other fields
+		//
 		@Adjacency(label="flow")
 		public IFlowPath getFlow();
 
diff --git a/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyService.java
similarity index 75%
rename from src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyService.java
index ecf217e..1992624 100644
--- a/src/main/java/net/floodlightcontroller/core/INetMapTopologyService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/INetMapTopologyService.java
@@ -1,15 +1,16 @@
-package net.floodlightcontroller.core;
+package net.onrc.onos.ofcontroller.core;
 
 import java.util.List;
+import java.util.Map;
 
 import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
 import net.floodlightcontroller.routing.Link;
 import net.floodlightcontroller.topology.NodePortTuple;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.SwitchPort;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 public interface INetMapTopologyService extends INetMapService {
 
@@ -47,7 +48,7 @@
 
 	    /**
 	     * Fetch the Switch and Ports info from the Titan Graph
-	     * and store it locally for fast access during the shortest path
+	     * and return it for fast access during the shortest path
 	     * computation.
 	     *
 	     * After fetching the state, method @ref getTopoShortestPath()
@@ -63,14 +64,17 @@
 	     * method @ref dropShortestPathTopo() should be used to release
 	     * the internal state that is not needed anymore:
 	     *
-	     *       prepareShortestPathTopo();
+	     *       Map<Long, ?> shortestPathTopo;
+	     *       shortestPathTopo = prepareShortestPathTopo();
 	     *       for (int i = 0; i < 10000; i++) {
-	     *           dataPath = getTopoShortestPath(...);
+	     *           dataPath = getTopoShortestPath(shortestPathTopo, ...);
 	     *           ...
 	     *        }
-	     *        dropShortestPathTopo();
+	     *        dropShortestPathTopo(shortestPathTopo);
+	     *
+	     * @return the Shortest Path info handler stored in a map.
 	     */
-	    void prepareShortestPathTopo();
+	    Map<Long, ?> prepareShortestPathTopo();
 
 	    /**
 	     * Release the state that was populated by
@@ -78,8 +82,10 @@
 	     *
 	     * See the documentation for method @ref prepareShortestPathTopo()
 	     * for additional information and usage.
+	     *
+	     * @shortestPathTopo the Shortest Path info handler to release.
 	     */
-	    void dropShortestPathTopo();
+	    void dropShortestPathTopo(Map<Long, ?> shortestPathTopo);
 
 	    /**
 	     * Get the shortest path from a source to a destination by
@@ -89,12 +95,15 @@
 	     * See the documentation for method @ref prepareShortestPathTopo()
 	     * for additional information and usage.
 	     *
+	     * @paran shortestPathTopoHandler the Shortest Path info handler
+	     * to use.
 	     * @param src the source in the shortest path computation.
 	     * @param dest the destination in the shortest path computation.
 	     * @return the data path with the computed shortest path if
 	     * found, otherwise null.
 	     */
-	    DataPath getTopoShortestPath(SwitchPort src, SwitchPort dest);
+	    DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopo,
+					 SwitchPort src, SwitchPort dest);
 
 	    /**
 	     * Test whether a route exists from a source to a destination.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/IOFSwitchPortListener.java b/src/main/java/net/onrc/onos/ofcontroller/core/IOFSwitchPortListener.java
new file mode 100644
index 0000000..5deae69
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IOFSwitchPortListener.java
@@ -0,0 +1,26 @@
+/**
+ * 
+ */
+package net.onrc.onos.ofcontroller.core;
+
+import org.openflow.protocol.OFPhysicalPort;
+
+import net.floodlightcontroller.core.IOFSwitchListener;
+
+/**
+ * @author y-higuchi
+ *
+ */
+public interface IOFSwitchPortListener extends IOFSwitchListener {
+
+	/**
+	 * Fired when ports on a switch area added
+	 */
+	public void switchPortAdded(Long switchId, OFPhysicalPort port);
+
+	/**
+	 * Fired when ports on a switch area removed
+	 */
+	public void switchPortRemoved(Long switchId, OFPhysicalPort port);
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/IOnosRemoteSwitch.java b/src/main/java/net/onrc/onos/ofcontroller/core/IOnosRemoteSwitch.java
new file mode 100644
index 0000000..c9b0e2f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/IOnosRemoteSwitch.java
@@ -0,0 +1,20 @@
+/**
+ * 
+ */
+package net.onrc.onos.ofcontroller.core;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+/**
+ * @author y-higuchi
+ *
+ */
+public interface IOnosRemoteSwitch extends IOFSwitch {
+
+	/**
+	 * Setup an unconnected switch with the info required.
+	 * @param dpid of the switch
+	 */
+	public void setupRemoteSwitch(Long dpid);
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/ISwitchStorage.java b/src/main/java/net/onrc/onos/ofcontroller/core/ISwitchStorage.java
new file mode 100644
index 0000000..a4dd528
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/ISwitchStorage.java
@@ -0,0 +1,47 @@
+package net.onrc.onos.ofcontroller.core;
+
+import java.util.Collection;
+
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.protocol.OFPhysicalPort;
+
+public interface ISwitchStorage extends INetMapStorage {
+	
+	public enum SwitchState {
+		INACTIVE,
+		ACTIVE
+	}
+	
+	/*
+	 * Update the switch details
+	 */
+	public void update(String dpid,SwitchState state, DM_OPERATION op);
+	/*
+	 * Associate a port on switch
+	 */
+	public void addPort(String dpid, OFPhysicalPort port);
+	/*
+	 * Add a switch and all its associated ports
+	 */
+	public void addSwitch(IOFSwitch sw);
+	/*
+	 * Add a switch
+	 */
+	public void addSwitch(String dpid);
+	/*
+	 * Delete switch and associated ports
+	 */
+	public void deleteSwitch(String dpid);
+	/*
+	 * Delete a port on a switch by num
+	 */
+	public void deletePort(String dpid, short port);
+	/*
+	 * Initialize
+	 */
+	public void init(String conf);
+	
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/Main.java b/src/main/java/net/onrc/onos/ofcontroller/core/Main.java
similarity index 92%
rename from src/main/java/net/floodlightcontroller/core/Main.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/Main.java
index 91b317a..a80ac36 100644
--- a/src/main/java/net/floodlightcontroller/core/Main.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/Main.java
@@ -1,8 +1,9 @@
-package net.floodlightcontroller.core;
+package net.onrc.onos.ofcontroller.core;
 
 import org.kohsuke.args4j.CmdLineException;
 import org.kohsuke.args4j.CmdLineParser;
 
+import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.internal.CmdLineSettings;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.FloodlightModuleLoader;
@@ -10,7 +11,7 @@
 import net.floodlightcontroller.restserver.IRestApiService;
 
 /**
- * Host for the Floodlight main method
+ * Host for the ONOS main method
  * @author alexreimers
  */
 public class Main {
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
new file mode 100644
index 0000000..386c1bd
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/DeviceStorageImpl.java
@@ -0,0 +1,264 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.thinkaurelius.titan.core.TitanException;
+import net.floodlightcontroller.devicemanager.IDevice;
+import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.packet.IPv4;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.IDeviceStorage;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+
+/**
+ * This is the class for storing the information of devices into CassandraDB
+ * @author Pankaj
+ */
+public class DeviceStorageImpl implements IDeviceStorage {
+	
+	private GraphDBOperation ope;
+	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	/***
+	 * Initialize function. Before you use this class, please call this method
+	 * @param conf configuration file for Cassandra DB
+	 */
+	@Override
+	public void init(String conf) {
+		try{
+			ope = new GraphDBOperation(conf);
+		} catch(Exception e) {
+			log.error(e.getMessage());
+		}
+	}	
+	
+	/***
+	 * Finalize/close function. After you use this class, please call this method.
+	 * It will close the DB connection.
+	 */
+	@Override
+	public void close() {
+		ope.close();
+	}
+	
+	/***
+	 * Finalize/close function. After you use this class, please call this method.
+	 * It will close the DB connection. This is for Java garbage collection.
+	 */
+	@Override
+	public void finalize() {
+		close();
+	}
+
+	/***
+	 * This function is for adding the device into the DB.
+	 * @param device The device you want to add into the DB.
+	 * @return IDeviceObject which was added in the DB. 
+	 */
+	@Override
+	public IDeviceObject addDevice(IDevice device) {
+		IDeviceObject obj = null;
+ 		try {
+ 			if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
+ 				log.debug("Adding device {}: found existing device",device.getMACAddressString());
+            } else {
+            	obj = ope.newDevice();
+                log.debug("Adding device {}: creating new device",device.getMACAddressString());
+            }
+	            changeDeviceAttachments(device, obj);
+	
+				String multiIntString = "";
+				for(Integer intValue : device.getIPv4Addresses()) {
+				   if (multiIntString == null || multiIntString.isEmpty()){
+				     multiIntString = IPv4.fromIPv4Address(intValue);
+				     multiIntString = "[" + IPv4.fromIPv4Address(intValue);
+				   }else{
+				        multiIntString += "," + IPv4.fromIPv4Address(intValue);
+				   }
+				}
+	 	            
+	            if(multiIntString.toString() != null && !multiIntString.toString().isEmpty()){
+	            	obj.setIPAddress(multiIntString + "]");
+	            }
+	            
+	 			obj.setMACAddress(device.getMACAddressString());
+	 			obj.setType("device");
+	 			obj.setState("ACTIVE");
+	 			ope.commit();
+ 			
+	 			log.debug("Adding device {}",device.getMACAddressString());
+		} catch (Exception e) {
+			ope.rollback();
+			log.error(":addDevice mac:{} failed", device.getMACAddressString());
+			obj = null;
+		}	
+ 			return obj;		
+	}
+
+	/***
+	 * This function is for updating the Device properties.
+	 * @param device The device you want to add into the DB.
+	 * @return IDeviceObject which was added in the DB. 
+	 */
+	@Override
+	public IDeviceObject updateDevice(IDevice device) {
+		return addDevice(device);
+	}
+
+	/***
+	 * This function is for removing the Device from the DB.
+	 * @param device The device you want to delete from the DB.
+	 */
+	@Override
+	public void removeDevice(IDevice device) {
+		IDeviceObject dev;
+		try {
+			if ((dev = ope.searchDevice(device.getMACAddressString())) != null) {
+             	ope.removeDevice(dev);
+             	ope.commit();
+            	log.error("DeviceStorage:removeDevice mac:{} done", device.getMACAddressString());
+            }
+		} catch (Exception e) {
+			ope.rollback();
+			log.error("DeviceStorage:removeDevice mac:{} failed", device.getMACAddressString());
+		}
+	}
+
+	/***
+	 * This function is for getting the Device from the DB by Mac address of the device.
+	 * @param mac The device mac address you want to get from the DB.
+	 * @return IDeviceObject you want to get.
+	 */
+	@Override
+	public IDeviceObject getDeviceByMac(String mac) {
+		return ope.searchDevice(mac);
+	}
+
+	/***
+	 * This function is for getting the Device from the DB by IP address of the device.
+	 * @param ip The device ip address you want to get from the DB.
+	 * @return IDeviceObject you want to get.
+	 */
+	@Override
+	public IDeviceObject getDeviceByIP(String ip) {
+		try
+		{
+			for(IDeviceObject dev : ope.getDevices()){
+				String ips;
+				if((ips = dev.getIPAddress()) != null){
+					String nw_addr_wob = ips.replace("[", "").replace("]", "");
+					ArrayList<String> iplists = Lists.newArrayList(nw_addr_wob.split(","));	
+					if(iplists.contains(ip)){
+						return dev;
+					}
+				}
+			}
+			return null;
+		}
+		catch (Exception e)
+		{
+			log.error("DeviceStorage:getDeviceByIP:{} failed");
+			return null;
+		}
+	}
+
+	/***
+	 * This function is for changing the Device attachment point.
+	 * @param device The device you want change the attachment point
+	 */
+	@Override
+	public void changeDeviceAttachments(IDevice device) {
+		IDeviceObject obj = null;
+ 		try {
+            if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
+                log.debug("Changing device ports {}: found existing device",device.getMACAddressString());
+                changeDeviceAttachments(device, obj);
+                ope.commit();
+            } else {
+   				log.debug("failed to search device...now adding {}",device.getMACAddressString());
+   				addDevice(device);
+            }            			
+		} catch (Exception e) {
+			ope.rollback();
+			log.error(":addDevice mac:{} failed", device.getMACAddressString());
+		}	
+	}
+	
+	/***
+	 * This function is for changing the Device attachment point.
+	 * @param device The new device you want change the attachment point
+	 * @param obj The old device IDeviceObject that is going to change the attachment point.
+	 */
+	public void changeDeviceAttachments(IDevice device, IDeviceObject obj) {
+		SwitchPort[] attachmentPoints = device.getAttachmentPoints();
+		List<IPortObject> attachedPorts = Lists.newArrayList(obj.getAttachedPorts());
+		
+        for (SwitchPort ap : attachmentPoints) {
+        	//Check weather there is the port
+          	 IPortObject port = ope.searchPort( HexString.toHexString(ap.getSwitchDPID()),
+												(short) ap.getPort());
+          	 log.debug("New Switch Port is {},{}", HexString.toHexString(ap.getSwitchDPID()),(short) ap.getPort());
+	       	 
+	       	 if(port != null){
+	   			if(attachedPorts.contains(port))
+	       		{
+		       		log.debug("This is the port you already attached {}: do nothing",device.getMACAddressString());
+		       		//This port will be remained, so remove from the removed port lists.
+		       		attachedPorts.remove(port);
+		       	} else {
+	     		   log.debug("Adding device {}: attaching to port",device.getMACAddressString());
+		       		port.setDevice(obj);  
+		        }
+	    	
+		       	log.debug("port number is {}", port.getNumber().toString());
+		        log.debug("port desc is {}", port.getDesc());  
+	       	 }
+        }      		 
+	            
+	    for (IPortObject port: attachedPorts) {
+            log.debug("Detouching the device {}: detouching from port",device.getMACAddressString());
+       		port.removeDevice(obj);
+        }
+	}
+
+	/***
+	 * This function is for changing the Device IPv4 address.
+	 * @param device The new device you want change the ipaddress
+	 */
+	@Override
+	public void changeDeviceIPv4Address(IDevice device) {
+		IDeviceObject obj;
+  		try {
+  			if ((obj = ope.searchDevice(device.getMACAddressString())) != null) {
+
+  				String multiIntString = "";
+  				for(Integer intValue : device.getIPv4Addresses()){
+  				   if (multiIntString == null || multiIntString.isEmpty()){
+  				     multiIntString = "[" + IPv4.fromIPv4Address(intValue);
+  				   } else {
+  				        multiIntString += "," + IPv4.fromIPv4Address(intValue);
+  				   }
+  				}
+  				
+  	            if(multiIntString != null && !multiIntString.isEmpty()){
+  	            	obj.setIPAddress(multiIntString + "]");
+  	            }
+  	            
+              	ope.commit();
+  			} else {
+            	log.error(":changeDeviceIPv4Address mac:{} failed", device.getMACAddressString());
+            }		
+  		} catch (TitanException e) {
+  			ope.rollback();
+			log.error(":changeDeviceIPv4Address mac:{} failed due to exception {}", device.getMACAddressString(),e);
+		}
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java
new file mode 100644
index 0000000..6e42771
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImpl.java
@@ -0,0 +1,350 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.ILinkStorage;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
+
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanException;
+import com.tinkerpop.blueprints.Direction;
+import com.tinkerpop.blueprints.Edge;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.PipeFunction;
+import com.tinkerpop.pipes.transform.PathPipe;
+
+/**
+ * This is the class for storing the information of links into CassandraDB
+ */
+public class LinkStorageImpl implements ILinkStorage {
+	
+	protected static Logger log = LoggerFactory.getLogger(LinkStorageImpl.class);
+	protected GraphDBOperation dbop;
+
+	/**
+	 * Update a record in the LinkStorage in a way provided by op.
+	 * @param link Record of a link to be updated.
+	 * @param op Operation to be done.
+	 */
+	@Override
+	public void update(Link link, DM_OPERATION op) {
+		update(link, (LinkInfo)null, op);
+	}
+
+	/**
+	 * Update multiple records in the LinkStorage in a way provided by op.
+	 * @param links List of records to be updated.
+	 * @param op Operation to be done.
+	 */
+	@Override
+	public void update(List<Link> links, DM_OPERATION op) {
+		for (Link lt: links) {
+			update(lt, (LinkInfo)null, op);
+		}
+	}
+
+	/**
+	 * Update a record of link with meta-information in the LinkStorage in a way provided by op.
+	 * @param link Record of a link to update.
+	 * @param linkinfo Meta-information of a link to be updated.
+	 * @param op Operation to be done.
+	 */
+	@Override
+	public void update(Link link, LinkInfo linkinfo, DM_OPERATION op) {
+		switch (op) {
+		case UPDATE:
+		case CREATE:
+		case INSERT:
+			updateLink(link, linkinfo, op);
+			break;
+		case DELETE:
+			deleteLink(link);
+			break;
+		}
+	}
+	
+	/**
+	 * Perform INSERT/CREATE/UPDATE operation to update the LinkStorage.
+	 * @param lt Record of a link to be updated.
+	 * @param linkinfo Meta-information of a link to be updated.
+	 * @param op Operation to be done. (only INSERT/CREATE/UPDATE is acceptable)
+	 */
+	public void updateLink(Link lt, LinkInfo linkinfo, DM_OPERATION op) {
+		IPortObject vportSrc = null, vportDst = null;
+	
+		log.trace("updateLink(): op {} {} {}", new Object[]{op, lt, linkinfo});
+		
+        try {
+            // get source port vertex
+        	String dpid = HexString.toHexString(lt.getSrc());
+        	short port = lt.getSrcPort();
+        	vportSrc = dbop.searchPort(dpid, port);
+            
+            // get dest port vertex
+            dpid = HexString.toHexString(lt.getDst());
+            port = lt.getDstPort();
+            vportDst = dbop.searchPort(dpid, port);
+                        
+            if (vportSrc != null && vportDst != null) {
+            	// check if the link exists
+            	
+            	Iterable<IPortObject> currPorts = vportSrc.getLinkedPorts();
+            	List<IPortObject> currLinks = new ArrayList<IPortObject>();
+            	for (IPortObject V : currPorts) {
+            		currLinks.add(V);
+            	}
+
+            	if (currLinks.contains(vportDst)) {
+            		// TODO: update linkinfo
+            		if (op.equals(DM_OPERATION.INSERT) || op.equals(DM_OPERATION.CREATE)) {
+            			log.debug("addOrUpdateLink(): failed link exists {} {} src {} dst {}", 
+            					new Object[]{op, lt, vportSrc, vportDst});
+            		}
+            	} else {
+            		vportSrc.setLinkPort(vportDst);
+
+            		dbop.commit();
+            		log.debug("updateLink(): link added {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
+            	}
+            } else {
+            	log.error("updateLink(): failed invalid vertices {} {} src {} dst {}", new Object[]{op, lt, vportSrc, vportDst});
+            	dbop.rollback();
+            }
+        } catch (TitanException e) {
+            /*
+             * retry till we succeed?
+             */
+        	e.printStackTrace();
+        	log.error("updateLink(): titan exception {} {} {}", new Object[]{op, lt, e.toString()});
+        }
+	}
+	
+	/**
+	 * Delete multiple records in LinkStorage.
+	 * @param links List of records to be deleted.
+	 */
+	@Override
+	public void deleteLinks(List<Link> links) {
+
+		for (Link lt : links) {
+			deleteLink(lt);
+		}
+	}
+	
+	/**
+	 * Delete a record in the LinkStorage.
+	 * @param link Record to be deleted.
+	 */
+	@Override
+	public void deleteLink(Link lt) {
+		IPortObject vportSrc = null, vportDst = null;
+		int count = 0;
+		
+		log.debug("deleteLink(): {}", lt);
+		
+        try {
+            // get source port vertex
+         	String dpid = HexString.toHexString(lt.getSrc());
+         	short port = lt.getSrcPort();
+         	vportSrc = dbop.searchPort(dpid, port);
+            
+            // get dst port vertex
+         	dpid = HexString.toHexString(lt.getDst());
+         	port = lt.getDstPort();
+         	vportDst = dbop.searchPort(dpid, port);
+     		// FIXME: This needs to remove all edges
+         	
+         	if (vportSrc != null && vportDst != null) {
+
+   /*      		for (Edge e : vportSrc.asVertex().getEdges(Direction.OUT)) {
+         			log.debug("deleteLink(): {} in {} out {}", 
+         					new Object[]{e.getLabel(), e.getVertex(Direction.IN), e.getVertex(Direction.OUT)});
+         			if (e.getLabel().equals("link") && e.getVertex(Direction.IN).equals(vportDst)) {
+         				graph.removeEdge(e);
+         				count++;
+         			}
+         		}*/
+         		vportSrc.removeLink(vportDst);
+        		dbop.commit();
+            	log.debug("deleteLink(): deleted edges src {} dst {}", new Object[]{
+            			lt, vportSrc, vportDst});
+            	
+            } else {
+            	log.error("deleteLink(): failed invalid vertices {} src {} dst {}", new Object[]{lt, vportSrc, vportDst});
+            	dbop.rollback();
+            }
+         	
+        } catch (TitanException e) {
+            /*
+             * retry till we succeed?
+             */
+        	log.error("deleteLink(): titan exception {} {}", new Object[]{lt, e.toString()});
+        	dbop.rollback();
+        	e.printStackTrace();
+        }
+	}
+
+	/**
+	 * Get list of all links connected to the port specified by given DPID and port number.
+	 * @param dpid DPID of desired port.
+	 * @param port Port number of desired port.
+	 * @return List of links. Empty list if no port was found.
+	 */
+	// TODO: Fix me
+	@Override
+	public List<Link> getLinks(Long dpid, short port) {
+    	List<Link> links = new ArrayList<Link>();
+    	
+    	IPortObject srcPort = dbop.searchPort(HexString.toHexString(dpid), port);
+    	ISwitchObject srcSw = srcPort.getSwitch();
+    	
+    	if(srcSw != null) {
+        	for(IPortObject dstPort : srcPort.getLinkedPorts()) {
+        		ISwitchObject dstSw = dstPort.getSwitch();
+        		Link link = new Link(HexString.toLong(srcSw.getDPID()),
+        				srcPort.getNumber(),
+        				HexString.toLong(dstSw.getDPID()),
+        				dstPort.getNumber());
+    		
+        		links.add(link);
+        	}
+    	}
+    	
+     	return links;
+	}
+	
+	/**
+	 * Initialize the object. Open LinkStorage using given configuration file.
+	 * @param conf Path (absolute path for now) to configuration file.
+	 */
+	@Override
+	public void init(String conf) {
+		//TODO extract the DB location from properties
+		this.dbop = new GraphDBOperation(conf);
+	}
+
+	/**
+	 * Delete records of the links connected to the port specified by given DPID and port number.
+	 * @param dpid DPID of desired port.
+	 * @param port Port number of desired port.
+	 */
+	// TODO: Fix me
+	@Override
+	public void deleteLinksOnPort(Long dpid, short port) {
+		List<Link> linksToDelete = getLinks(dpid,port);
+		
+		for(Link l : linksToDelete) {
+			deleteLink(l);
+		}
+	}
+
+	/**
+	 * Get list of all links connected to the switch specified by given DPID.
+	 * @param dpid DPID of desired switch.
+	 * @return List of links. Empty list if no port was found.
+	 */
+	// TODO: Fix me
+	@Override
+	public List<Link> getLinks(String dpid) {
+		List<Link> links = new ArrayList<Link>();
+
+		ISwitchObject srcSw = dbop.searchSwitch(dpid);
+		
+		if(srcSw != null) {
+			for(IPortObject srcPort : srcSw.getPorts()) {
+				for(IPortObject dstPort : srcPort.getLinkedPorts()) {
+					ISwitchObject dstSw = dstPort.getSwitch();
+					if(dstSw != null) {
+		        		Link link = new Link(HexString.toLong(srcSw.getDPID()),
+		        				srcPort.getNumber(),
+		        				HexString.toLong(dstSw.getDPID()),
+		        				dstPort.getNumber());
+		        		links.add(link);
+					}
+				}
+			}
+		}
+		
+		return links;
+	}
+
+	/**
+	 * Get list of all links whose state is ACTIVE.
+	 * @return List of active links. Empty list if no port was found.
+	 */
+	public List<Link> getActiveLinks() {
+		Iterable<ISwitchObject> switches = dbop.getActiveSwitches();
+
+		List<Link> links = new ArrayList<Link>(); 
+		
+		for (ISwitchObject srcSw : switches) {
+			for(IPortObject srcPort : srcSw.getPorts()) {
+				for(IPortObject dstPort : srcPort.getLinkedPorts()) {
+					ISwitchObject dstSw = dstPort.getSwitch();
+					
+					if(dstSw != null && dstSw.getState().equals("ACTIVE")) {
+						links.add(new Link(HexString.toLong(srcSw.getDPID()),
+								srcPort.getNumber(),
+								HexString.toLong(dstSw.getDPID()),
+								dstPort.getNumber()));
+					}
+				}
+			}
+		}
+		
+		return links;
+	}
+	
+	static class ExtractLink implements PipeFunction<PathPipe<Vertex>, Link> {
+	
+		@Override
+		public Link compute(PathPipe<Vertex> pipe ) {
+			// TODO Auto-generated method stub
+			long s_dpid = 0;
+			long d_dpid = 0;
+			short s_port = 0;
+			short d_port = 0;
+			List<Vertex> V = new ArrayList<Vertex>();
+			V = pipe.next();
+			Vertex src_sw = V.get(0);
+			Vertex dest_sw = V.get(3);
+			Vertex src_port = V.get(1);
+			Vertex dest_port = V.get(2);
+			s_dpid = HexString.toLong((String) src_sw.getProperty("dpid"));
+			d_dpid = HexString.toLong((String) dest_sw.getProperty("dpid"));
+			s_port = (Short) src_port.getProperty("number");
+			d_port = (Short) dest_port.getProperty("number");
+			
+			Link l = new Link(s_dpid,s_port,d_dpid,d_port);
+			
+			return l;
+		}
+	}
+	
+	/**
+	 * Finalize the object.
+	 */
+	public void finalize() {
+		close();
+	}
+
+	/**
+	 * Close LinkStorage.
+	 */
+	@Override
+	public void close() {
+		// TODO Auto-generated method stub
+//		graph.shutdown();		
+	}
+
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java
new file mode 100644
index 0000000..126efb3
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImpl.java
@@ -0,0 +1,243 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import net.floodlightcontroller.core.IOFSwitch;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the class for storing the information of switches into CassandraDB
+ */
+public class SwitchStorageImpl implements ISwitchStorage {
+	protected GraphDBOperation op;
+	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+	
+	/***
+	 * Initialize function. Before you use this class, please call this method
+	 * @param conf configuration file for Cassandra DB
+	 */
+	@Override
+	public void init(String conf) {
+		GraphDBConnection conn = GraphDBConnection.getInstance(conf);
+		op = new GraphDBOperation(conn);
+	}
+
+	/***
+	 * Finalize/close function. After you use this class, please call this method.
+	 * It will close the DB connection.
+	 */
+	public void finalize() {
+		close();
+	}
+	
+	/***
+	 * Finalize/close function. After you use this class, please call this method.
+	 * It will close the DB connection. This is for Java garbage collection.
+	 */
+	@Override
+	public void close() {
+		op.close();		
+	}
+	
+	private void setStatus(String dpid, SwitchState state) {
+		ISwitchObject sw = op.searchSwitch(dpid);
+		
+		try {
+			if (sw != null) {
+				sw.setState(state.toString());
+				op.commit();
+				log.info("SwitchStorage:setStatus dpid:{} state: {} done", dpid, state);
+			}
+		} catch(Exception e) {
+			e.printStackTrace();
+			op.rollback();
+			log.info("SwitchStorage:setStatus dpid:{} state: {} failed: switch not found", dpid, state);	
+		}
+	}
+
+	/***
+	 * This function is for adding the switch into the DB.
+	 * @param dpid The switch dpid you want to add into the DB.
+	 */
+	@Override
+	public void addSwitch(String dpid) {
+		
+		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
+		try {
+			ISwitchObject sw = newSwitch(dpid);
+			if ( sw == null ) throw new RuntimeException();
+            op.commit();
+		} catch (Exception e) {
+			e.printStackTrace();
+			op.rollback();
+			log.info("SwitchStorage:addSwitch dpid:{} failed", dpid);
+		}
+	}
+	
+	private ISwitchObject newSwitch(String dpid) {
+		ISwitchObject sw = op.searchSwitch(dpid);
+		if (sw != null) {
+			//If existing the switch. set The SW state ACTIVE. 
+			log.info("SwitchStorage:newSwitch dpid:{} already exists", dpid);
+			sw.setState(SwitchState.ACTIVE.toString());
+		} else {
+			sw = op.newSwitch(dpid);
+			if (sw != null) {
+				sw.setState(SwitchState.ACTIVE.toString());
+				log.info("SwitchStorage:newSwitch dpid:{} added", dpid);
+			} else {
+				log.error("switchStorage:newSwitch dpid:{} failed -> newSwitch failed", dpid);
+			}
+		}
+		return sw;
+	}
+	
+	/***
+	 * This function is for updating the switch into the DB.
+	 * @param dpid The switch dpid you want to update from the DB
+	 * @param state The state of the switch like ACTIVE, INACTIVE
+	 * @param dmope	The DM_OPERATION of the switch
+	 */
+	@Override
+	public void update(String dpid, SwitchState state, DM_OPERATION dmope) {
+		log.info("SwitchStorage:update dpid:{} state: {} ", dpid, state);
+        switch(dmope) {
+        	case UPDATE:
+        	case INSERT:
+        	case CREATE:
+                addSwitch(dpid);
+                if (state != SwitchState.ACTIVE) {
+                	setStatus(dpid, state);
+                }
+                break;
+        	case DELETE:
+                deleteSwitch(dpid);
+                break;
+        	default:
+        }
+	}
+
+	/***
+	 * This function is for deleting the switch into the DB.
+	 * @param dpid The switch dpid you want to delete from the DB.
+	 */
+	@Override
+	public void deleteSwitch(String dpid) {
+		try {
+			ISwitchObject sw = op.searchSwitch(dpid);
+            if (sw  != null) {
+            	op.removeSwitch(sw);
+            	op.commit();
+            	log.info("SwitchStorage:DeleteSwitch dpid:{} done", dpid);
+            }
+		} catch (Exception e) {
+			e.printStackTrace();
+			op.rollback();			
+			log.error("SwitchStorage:deleteSwitch {} failed", dpid);
+		}
+
+	}
+
+	/***
+	 * This function is for adding the switch port into the DB.
+	 * @param dpid The switch dpid that has the port.
+	 * @param port The port you want to add the switch.
+	 */
+	@Override
+	public void addPort(String dpid, OFPhysicalPort port) {
+		
+       if(((OFPortConfig.OFPPC_PORT_DOWN.getValue() & port.getConfig()) > 0) ||
+        					((OFPortState.OFPPS_LINK_DOWN.getValue() & port.getState()) > 0)) {
+    	     deletePort(dpid, port.getPortNumber());
+             return;  
+       }
+
+		try {
+			ISwitchObject sw = op.searchSwitch(dpid);
+
+            if (sw != null) {
+            	IPortObject p = op.searchPort(dpid, port.getPortNumber());
+            	log.info("SwitchStorage:addPort dpid:{} port:{}", dpid, port.getPortNumber());
+            	if (p != null) {
+            		log.error("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
+            	} else {
+            		p = op.newPort(dpid, port.getPortNumber());
+            		p.setState("ACTIVE");
+            		p.setPortState(port.getState());
+            		p.setDesc(port.getName());
+            		sw.addPort(p);
+            		op.commit();
+            	}
+            } else {
+        		log.error("SwitchStorage:addPort dpid:{} port:{} : failed switch does not exist", dpid, port.getPortNumber());
+            }
+		} catch (Exception e) {
+			e.printStackTrace();
+			op.rollback();
+			log.error("SwitchStorage:addPort dpid:{} port:{} failed", dpid, port.getPortNumber());
+		}	
+
+	}
+	
+	/***
+	 * This function is for deleting the switch port from the DB.
+	 * @param dpid The switch dpid that has the port.
+	 * @param port The port you want to delete the switch.
+	 */
+	@Override
+	public void deletePort(String dpid, short port) {
+		try {
+			ISwitchObject sw = op.searchSwitch(dpid);
+
+            if (sw != null) {
+            	IPortObject p = op.searchPort(dpid, port);
+                if (p != null) {
+            		log.info("SwitchStorage:deletePort dpid:{} port:{} found and deleted", dpid, port);
+            		sw.removePort(p);
+            		op.removePort(p);
+            		op.commit();
+            	}
+            }
+		} catch (Exception e) {
+			e.printStackTrace();
+			op.rollback();
+			log.info("SwitchStorage:deletePort dpid:{} port:{} failed", dpid, port);
+		}	
+	}
+
+	@Override
+	public void addSwitch(IOFSwitch sw) {
+		// TODO Auto-generated method stub
+		String dpid = sw.getStringId();
+		log.info("SwitchStorage:addSwitch(): dpid {} ", dpid);
+		try {
+			ISwitchObject switchObject = newSwitch(dpid);
+        	for (OFPhysicalPort port: sw.getPorts()) {
+        		IPortObject p = op.searchPort(dpid, port.getPortNumber());
+        		if (p != null) {
+            		log.error("SwitchStorage:addPort dpid:{} port:{} exists", dpid, port.getPortNumber());
+            	} else {
+            		p = op.newPort(dpid, port.getPortNumber());
+            		p.setState("ACTIVE");
+            		p.setPortState(port.getState());
+            		p.setDesc(port.getName());           		
+            		switchObject.addPort(p);
+            	}         		
+        	}
+            op.commit();
+		} catch (Exception e) {
+			e.printStackTrace();
+			op.rollback();
+			log.info("SwitchStorage:addSwitch dpid:{} failed", dpid);
+		}		
+		
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/TopoLinkServiceImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoLinkServiceImpl.java
similarity index 70%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/internal/TopoLinkServiceImpl.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoLinkServiceImpl.java
index 1bd6421..e810646 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/TopoLinkServiceImpl.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoLinkServiceImpl.java
@@ -1,13 +1,13 @@
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.core.internal;
 
 import java.util.ArrayList;
 import java.util.List;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoLinkService;
-import net.floodlightcontroller.linkdiscovery.internal.LinkStorageImpl.ExtractLink;
 import net.floodlightcontroller.routing.Link;
-import net.onrc.onos.util.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoLinkService;
+import net.onrc.onos.ofcontroller.core.internal.LinkStorageImpl.ExtractLink;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -17,25 +17,24 @@
 
 public class TopoLinkServiceImpl implements ITopoLinkService {
 	
-	public GraphDBConnection conn;
+	protected GraphDBOperation op;
 	protected static Logger log = LoggerFactory.getLogger(TopoLinkServiceImpl.class);
 
-
 	public void finalize() {
 		close();
 	}
 	
 	@Override
 	public void close() {
-		conn.close();
+		op.close();
 	}
  
 	@Override
 	public List<Link> getActiveLinks() {
 		// TODO Auto-generated method stub
-		conn = GraphDBConnection.getInstance("");
-		conn.close(); //Commit to ensure we see latest data
-		Iterable<ISwitchObject> switches = conn.utils().getActiveSwitches(conn);
+		op = new GraphDBOperation("");
+		op.commit(); //Commit to ensure we see latest data
+		Iterable<ISwitchObject> switches = op.getActiveSwitches();
 		List<Link> links = new ArrayList<Link>(); 
 		for (ISwitchObject sw : switches) {
 			GremlinPipeline<Vertex, Link> pipe = new GremlinPipeline<Vertex, Link>();
@@ -51,6 +50,7 @@
 			}
 						
 		}
+		op.commit();
 		return links;
 	}
 
@@ -58,7 +58,7 @@
 	public List<Link> getLinksOnSwitch(String dpid) {
 		// TODO Auto-generated method stub
 		List<Link> links = new ArrayList<Link>(); 
-		ISwitchObject sw = conn.utils().searchSwitch(conn, dpid);
+		ISwitchObject sw = op.searchSwitch(dpid);
 		GremlinPipeline<Vertex, Link> pipe = new GremlinPipeline<Vertex, Link>();
 		ExtractLink extractor = new ExtractLink();
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
new file mode 100644
index 0000000..978fcde
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/internal/TopoSwitchServiceImpl.java
@@ -0,0 +1,65 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoSwitchService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TopoSwitchServiceImpl implements ITopoSwitchService {
+	
+	private GraphDBOperation op;
+	protected static Logger log = LoggerFactory.getLogger(TopoSwitchServiceImpl.class);
+
+	public TopoSwitchServiceImpl(String conf) {
+		op = new GraphDBOperation(conf);
+	}
+
+	public TopoSwitchServiceImpl() {
+		this("/tmp/cassandra.titan");
+	}
+	
+	public void finalize() {
+		close();
+	}
+	
+	@Override
+	public void close() {
+		op.close();
+	}
+	
+	@Override
+	public Iterable<ISwitchObject> getActiveSwitches() {
+		// TODO Auto-generated method stub
+		op.close(); //Commit to ensure we see latest data
+		return op.getActiveSwitches();
+	}
+
+	@Override
+	public Iterable<ISwitchObject> getAllSwitches() {
+		// TODO Auto-generated method stub
+		op.close(); //Commit to ensure we see latest data
+		return op.getAllSwitches();
+	}
+
+	@Override
+	public Iterable<ISwitchObject> getInactiveSwitches() {
+		// TODO Auto-generated method stub
+		op.close(); //Commit to ensure we see latest data
+		return op.getInactiveSwitches();
+	}
+
+	@Override
+	public Iterable<IPortObject> getPortsOnSwitch(String dpid) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public IPortObject getPortOnSwitch(String dpid, short port_num) {
+		// TODO Auto-generated method stub
+		return null;
+	}	
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/ClearFlowTableResource.java b/src/main/java/net/onrc/onos/ofcontroller/core/web/ClearFlowTableResource.java
similarity index 96%
rename from src/main/java/net/floodlightcontroller/core/web/ClearFlowTableResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/web/ClearFlowTableResource.java
index c2d2eb4..7b1acfe 100644
--- a/src/main/java/net/floodlightcontroller/core/web/ClearFlowTableResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/web/ClearFlowTableResource.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.core.web;
+package net.onrc.onos.ofcontroller.core.web;
 
 import java.io.IOException;
 import java.util.ArrayList;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/web/TopoLinksResource.java b/src/main/java/net/onrc/onos/ofcontroller/core/web/TopoLinksResource.java
similarity index 74%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/web/TopoLinksResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/web/TopoLinksResource.java
index 25b68fb..327c110 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/web/TopoLinksResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/web/TopoLinksResource.java
@@ -1,8 +1,8 @@
-package net.floodlightcontroller.linkdiscovery.web;
+package net.onrc.onos.ofcontroller.core.web;
 
 import java.util.List;
-import net.floodlightcontroller.linkdiscovery.internal.TopoLinkServiceImpl;
 import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.ofcontroller.core.internal.TopoLinkServiceImpl;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java b/src/main/java/net/onrc/onos/ofcontroller/core/web/TopoSwitchesResource.java
similarity index 77%
rename from src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/core/web/TopoSwitchesResource.java
index 7a8511b..a173a70 100644
--- a/src/main/java/net/floodlightcontroller/core/web/TopoSwitchesResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/core/web/TopoSwitchesResource.java
@@ -1,9 +1,9 @@
-package net.floodlightcontroller.core.web;
+package net.onrc.onos.ofcontroller.core.web;
 
 import java.util.Iterator;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.TopoSwitchServiceImpl;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/devicemanager/web/TopoDevicesResource.java b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/web/TopoDevicesResource.java
new file mode 100644
index 0000000..ac9409f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/devicemanager/web/TopoDevicesResource.java
@@ -0,0 +1,19 @@
+package net.onrc.onos.ofcontroller.devicemanager.web;
+
+import java.util.Iterator;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+public class TopoDevicesResource extends ServerResource {
+	
+	@Get("json")
+	public Iterator<IDeviceObject> retrieve() {
+		GraphDBOperation op = new GraphDBOperation("");
+		
+		return op.getDevices().iterator();
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
similarity index 65%
rename from src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java
rename to src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
index 723fe1c..e0ac4e1 100644
--- a/src/main/java/net/floodlightcontroller/onoslistener/OnosPublisher.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/floodlightlistener/NetworkGraphPublisher.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.onoslistener;
+package net.onrc.onos.ofcontroller.floodlightlistener;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -6,19 +6,14 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import org.openflow.protocol.OFPhysicalPort;
 import org.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.INetMapStorage.DM_OPERATION;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchListener;
-import net.floodlightcontroller.core.ISwitchStorage;
-import net.floodlightcontroller.core.internal.SwitchStorageImpl;
-import net.floodlightcontroller.core.internal.TopoSwitchServiceImpl;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -27,32 +22,47 @@
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.IDeviceListener;
 import net.floodlightcontroller.devicemanager.IDeviceService;
-import net.floodlightcontroller.devicemanager.IDeviceStorage;
-import net.floodlightcontroller.devicemanager.internal.DeviceStorageImpl;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
+import net.floodlightcontroller.routing.Link;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.graph.IDBConnection;
+import net.onrc.onos.graph.LocalTopologyEventListener;
+import net.onrc.onos.ofcontroller.core.IDeviceStorage;
+import net.onrc.onos.ofcontroller.core.ILinkStorage;
+import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage;
+import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.LinkStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
 import net.onrc.onos.registry.controller.RegistryException;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.LocalTopologyEventListener;
 
-public class OnosPublisher implements IDeviceListener, IOFSwitchListener,
+public class NetworkGraphPublisher implements IDeviceListener, IOFSwitchListener, IOFSwitchPortListener,
 		ILinkDiscoveryListener, IFloodlightModule {
 	
 	protected IDeviceStorage devStore;
 	protected ISwitchStorage swStore;
+	protected ILinkStorage linkStore;
 	protected static Logger log;
 	protected IDeviceService deviceService;
 	protected IControllerRegistryService registryService;
-	protected GraphDBConnection conn;
+	protected GraphDBOperation op;
 	
 	protected static final String DBConfigFile = "dbconf";
 	protected static final String CleanupEnabled = "EnableCleanup";
 	protected IThreadPoolService threadPool;
+	protected IFloodlightProviderService floodlightProvider;
 	
 	protected final int CLEANUP_TASK_INTERVAL = 60; // 1 min
 	protected SingletonTask cleanupTask;
+	protected ILinkDiscoveryService linkDiscovery;
 	
 	/**
      *  Cleanup and synch switch state from registry
@@ -67,7 +77,7 @@
             catch (Exception e) {
                 log.error("Error in cleanup thread", e);
             } finally {
-            	conn.close();
+            	op.close();
                     cleanupTask.reschedule(CLEANUP_TASK_INTERVAL,
                                               TimeUnit.SECONDS);
             }
@@ -86,8 +96,8 @@
     }
 
     protected void switchCleanup() {
-    	conn.close();
-    	Iterable<ISwitchObject> switches = conn.utils().getActiveSwitches(conn);
+    	op.close();
+    	Iterable<ISwitchObject> switches = op.getActiveSwitches();
     	
     	log.debug("Checking for inactive switches");
     	// For each switch check if a controller exists in controller registry
@@ -110,18 +120,44 @@
 				e.printStackTrace();
 			}			
 		}
-    	conn.close();
+    	op.close();
     }
 
 	@Override
 	public void linkDiscoveryUpdate(LDUpdate update) {
 		// TODO Auto-generated method stub
+		Link lt = new Link(update.getSrc(),update.getSrcPort(),update.getDst(),update.getDstPort());
+		//log.debug("{}:LinkDicoveryUpdate(): Updating Link {}",this.getClass(), lt);
+		
+		switch (update.getOperation()) {
+			case LINK_REMOVED:
+				log.debug("LinkDiscoveryUpdate(): Removing link {}", lt);
+				linkStore.update(lt, DM_OPERATION.DELETE);
+				// TODO: Move network map link removal here
+				// reconcile paths here
+//				IPortObject srcPort = conn.utils().searchPort(conn, HexString.toHexString(update.getSrc()), update.getSrcPort());
+				break;
+			case LINK_UPDATED:
+				log.debug("LinkDiscoveryUpdate(): Updating link {}", lt);
+				linkStore.update(lt, DM_OPERATION.UPDATE);
+				break;
+			case LINK_ADDED:
+				log.debug("LinkDiscoveryUpdate(): Adding link {}", lt);
+				linkStore.update(lt, DM_OPERATION.INSERT);
+				break;
+					
+			default:
+				break;
+		}
 
 	}
 
 	@Override
 	public void addedSwitch(IOFSwitch sw) {
-		// TODO Auto-generated method stub
+
+		if (registryService.hasControl(sw.getId())) {
+	        	swStore.addSwitch(sw);
+		}
 
 	}
 
@@ -137,9 +173,22 @@
 
 	}
 
+
+	@Override
+	public void switchPortAdded(Long switchId, OFPhysicalPort port) {
+		// TODO Auto-generated method stub
+		swStore.addPort(HexString.toHexString(switchId), port);
+	}
+
+	@Override
+	public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
+		// TODO Auto-generated method stub
+		swStore.deletePort(HexString.toHexString(switchId), port.getPortNumber());		
+	}
+
 	@Override
 	public String getName() {
-		return "OnosPublisher";
+		return "NetworkGraphPublisher";
 	}
 
 	@Override
@@ -203,10 +252,13 @@
 		// TODO Auto-generated method stub
 		Map<String, String> configMap = context.getConfigParams(this);
 		String conf = configMap.get(DBConfigFile);
-		conn = GraphDBConnection.getInstance(conf);
+		op = new GraphDBOperation(conf);
 		
-		log = LoggerFactory.getLogger(OnosPublisher.class);
+		log = LoggerFactory.getLogger(NetworkGraphPublisher.class);
+		floodlightProvider =
+	            context.getServiceImpl(IFloodlightProviderService.class);
 		deviceService = context.getServiceImpl(IDeviceService.class);
+		linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
 		threadPool = context.getServiceImpl(IThreadPoolService.class);
 		registryService = context.getServiceImpl(IControllerRegistryService.class);
 		
@@ -215,8 +267,11 @@
 		
 		swStore = new SwitchStorageImpl();
 		swStore.init(conf);
+		
+		linkStore = new LinkStorageImpl();
+		linkStore.init(conf);
 				
-		log.debug("Initializing OnosPublisher module with {}", conf);
+		log.debug("Initializing NetworkGraphPublisher module with {}", conf);
 		
 	}
 
@@ -227,9 +282,12 @@
 		String cleanupNeeded = configMap.get(CleanupEnabled);
 
 		deviceService.addListener(this);
+		floodlightProvider.addOFSwitchListener(this);
+		linkDiscovery.addListener(this);
 		
 		log.debug("Adding EventListener");
-		conn.addEventListener(new LocalTopologyEventListener(conn));
+		IDBConnection conn = op.getDBConnection();
+		conn.addEventListener(new LocalTopologyEventListener((GraphDBConnection) conn));
 	       // Setup the Cleanup task. 
 		if (cleanupNeeded == null || !cleanupNeeded.equals("False")) {
 				ScheduledExecutorService ses = threadPool.getScheduledExecutor();
diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
similarity index 67%
rename from src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
index 251620c..a072882 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/FlowManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/FlowManager.java
@@ -1,6 +1,8 @@
-package net.floodlightcontroller.flowcache;
+package net.onrc.onos.ofcontroller.flowmanager;
 
 import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -11,58 +13,61 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.INetMapStorage;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.flowcache.web.FlowWebRoutable;
 import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.util.CallerId;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.DataPathEndpoints;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowEntry;
-import net.floodlightcontroller.util.FlowEntryAction;
-import net.floodlightcontroller.util.FlowEntryId;
-import net.floodlightcontroller.util.FlowEntryMatch;
-import net.floodlightcontroller.util.FlowEntrySwitchState;
-import net.floodlightcontroller.util.FlowEntryUserState;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
-import net.floodlightcontroller.util.IPv4Net;
 import net.floodlightcontroller.util.MACAddress;
 import net.floodlightcontroller.util.OFMessageDamper;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapStorage;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.ofcontroller.util.CallerId;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction;
+import net.onrc.onos.ofcontroller.util.FlowEntryAction.*;
+import net.onrc.onos.ofcontroller.util.FlowEntryActions;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowEntryMatch;
+import net.onrc.onos.ofcontroller.util.FlowEntrySwitchState;
+import net.onrc.onos.ofcontroller.util.FlowEntryUserState;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.FlowPathFlags;
+import net.onrc.onos.ofcontroller.util.IPv4Net;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 import org.openflow.protocol.OFFlowMod;
 import org.openflow.protocol.OFMatch;
 import org.openflow.protocol.OFPacketOut;
 import org.openflow.protocol.OFPort;
 import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.protocol.action.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 
 public class FlowManager implements IFloodlightModule, IFlowService, INetMapStorage {
 
-    public GraphDBConnection conn;
+    protected GraphDBOperation op;
 
     protected IRestApiService restApi;
     protected volatile IFloodlightProviderService floodlightProvider;
@@ -93,9 +98,10 @@
     private long modifiedMeasurementFlowTime = 0;
     //
     private LinkedList<FlowPath> measurementStoredPaths = new LinkedList<FlowPath>();
-    private LinkedList<FlowPath> measurementProcessingPaths = null;
     private long measurementStartTimeProcessingPaths = 0;
     private long measurementEndTimeProcessingPaths = 0;
+    Map<Long, ?> measurementShortestPathTopo = null;
+    private String measurementPerFlowStr = new String();
 
     /** The logger. */
     private static Logger log = LoggerFactory.getLogger(FlowManager.class);
@@ -110,7 +116,7 @@
 		    runImpl();
 		} catch (Exception e) {
 		    log.debug("Exception processing All Flow Entries from the Network MAP: ", e);
-		    conn.endTx(Transaction.ROLLBACK);
+		    op.rollback();
 		    return;
 		}
 	    }
@@ -137,7 +143,7 @@
 		//
 		boolean processed_measurement_flow = false;
 		Iterable<IFlowEntry> allFlowEntries =
-		    conn.utils().getAllSwitchNotUpdatedFlowEntries(conn);
+		    op.getAllSwitchNotUpdatedFlowEntries();
 		for (IFlowEntry flowEntryObj : allFlowEntries) {
 		    counterAllFlowEntries++;
 
@@ -150,7 +156,7 @@
 			continue;	// Ignore the entry: not my switch
 
 		    IFlowPath flowObj =
-			conn.utils().getFlowPathByFlowEntry(conn, flowEntryObj);
+			op.getFlowPathByFlowEntry(flowEntryObj);
 		    if (flowObj == null)
 			continue;		// Should NOT happen
 		    if (flowObj.getFlowId() == null)
@@ -188,8 +194,7 @@
 		//
 		for (IFlowEntry flowEntryObj : addFlowEntries) {
 		    IFlowPath flowObj =
-			conn.utils().getFlowPathByFlowEntry(conn,
-							    flowEntryObj);
+			op.getFlowPathByFlowEntry(flowEntryObj);
 		    if (flowObj == null)
 			continue;		// Should NOT happen
 		    if (flowObj.getFlowId() == null)
@@ -213,16 +218,16 @@
 		while (! deleteFlowEntries.isEmpty()) {
 		    IFlowEntry flowEntryObj = deleteFlowEntries.poll();
 		    IFlowPath flowObj =
-			conn.utils().getFlowPathByFlowEntry(conn, flowEntryObj);
+			op.getFlowPathByFlowEntry(flowEntryObj);
 		    if (flowObj == null) {
 			log.debug("Did not find FlowPath to be deleted");
 			continue;
 		    }
 		    flowObj.removeFlowEntry(flowEntryObj);
-		    conn.utils().removeFlowEntry(conn, flowEntryObj);
+		    op.removeFlowEntry(flowEntryObj);
 		}
 
-		conn.endTx(Transaction.COMMIT);
+		op.commit();
 
 		if (processed_measurement_flow) {
 		    long estimatedTime =
@@ -251,7 +256,7 @@
 		    runImpl();
 		} catch (Exception e) {
 		    log.debug("Exception processing All Flows from the Network MAP: ", e);
-		    conn.endTx(Transaction.ROLLBACK);
+		    op.rollback();
 		    return;
 		}
 	    }
@@ -275,8 +280,9 @@
 		// Fetch and recompute the Shortest Path for those
 		// Flow Paths this controller is responsible for.
 		//
-		topoRouteService.prepareShortestPathTopo();
-		Iterable<IFlowPath> allFlowPaths = conn.utils().getAllFlowPaths(conn);
+		Map<Long, ?> shortestPathTopo =
+		    topoRouteService.prepareShortestPathTopo();
+		Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
 		for (IFlowPath flowPathObj : allFlowPaths) {
 		    counterAllFlowPaths++;
 		    if (flowPathObj == null)
@@ -326,9 +332,11 @@
 		    Short srcPortShort = flowPathObj.getSrcPort();
 		    String dstDpidStr = flowPathObj.getDstSwitch();
 		    Short dstPortShort = flowPathObj.getDstPort();
+		    Long flowPathFlagsLong = flowPathObj.getFlowPathFlags();
 		    if ((srcPortShort == null) ||
 			(dstDpidStr == null) ||
-			(dstPortShort == null)) {
+			(dstPortShort == null) ||
+			(flowPathFlagsLong == null)) {
 			continue;
 		    }
 
@@ -337,6 +345,7 @@
 		    Port dstPort = new Port(dstPortShort);
 		    SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
 		    SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
+		    FlowPathFlags flowPathFlags = new FlowPathFlags(flowPathFlagsLong);
 
 		    counterMyFlowPaths++;
 
@@ -350,7 +359,8 @@
 		    // to avoid closing the transaction.
 		    //
 		    DataPath dataPath =
-			topoRouteService.getTopoShortestPath(srcSwitchPort,
+			topoRouteService.getTopoShortestPath(shortestPathTopo,
+							     srcSwitchPort,
 							     dstSwitchPort);
 		    if (dataPath == null) {
 			// We need the DataPath to compare the paths
@@ -358,6 +368,7 @@
 			dataPath.setSrcPort(srcSwitchPort);
 			dataPath.setDstPort(dstSwitchPort);
 		    }
+		    dataPath.applyFlowPathFlags(flowPathFlags);
 
 		    String newDataPathSummaryStr = dataPath.dataPathSummary();
 		    if (dataPathSummaryStr.equals(newDataPathSummaryStr))
@@ -372,12 +383,12 @@
 		//
 		while (! deleteFlows.isEmpty()) {
 		    IFlowPath flowPathObj = deleteFlows.poll();
-		    conn.utils().removeFlowPath(conn, flowPathObj);
+		    op.removeFlowPath(flowPathObj);
 		}
 
-		topoRouteService.dropShortestPathTopo();
+		topoRouteService.dropShortestPathTopo(shortestPathTopo);
 
-		conn.endTx(Transaction.COMMIT);
+		op.commit();
 
 		if (processed_measurement_flow) {
 		    long estimatedTime =
@@ -408,16 +419,17 @@
 
     @Override
     public void init(String conf) {
-    	conn = GraphDBConnection.getInstance(conf);
+    	op = new GraphDBOperation(conf);
+	topoRouteService = new TopoRouteService(conf);
     }
 
     public void finalize() {
-	close();
+    	close();
     }
 
     @Override
     public void close() {
-	conn.close();
+    	op.close();
     }
 
     @Override
@@ -445,7 +457,6 @@
 	Collection<Class<? extends IFloodlightService>> l =
 	    new ArrayList<Class<? extends IFloodlightService>>();
 	l.add(IFloodlightProviderService.class);
-	l.add(ITopoRouteService.class);
 	l.add(IRestApiService.class);
         return l;
     }
@@ -455,11 +466,11 @@
 	throws FloodlightModuleException {
 	this.context = context;
 	floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
-	topoRouteService = context.getServiceImpl(ITopoRouteService.class);
 	restApi = context.getServiceImpl(IRestApiService.class);
 	messageDamper = new OFMessageDamper(OFMESSAGE_DAMPER_CAPACITY,
 					    EnumSet.of(OFType.FLOW_MOD),
 					    OFMESSAGE_DAMPER_TIMEOUT);
+
 	// TODO: An ugly hack!
 	String conf = "/tmp/cassandra.titan";
 	this.init(conf);
@@ -494,9 +505,9 @@
 		nextFlowEntryIdPrefix = randomGenerator.nextInt();
 		
 		mapReaderScheduler.scheduleAtFixedRate(
-				mapReader, 1, 1, TimeUnit.SECONDS);
+				mapReader, 3, 3, TimeUnit.SECONDS);
 		shortestPathReconcileScheduler.scheduleAtFixedRate(
-				shortestPathReconcile, 100, 100, TimeUnit.MILLISECONDS);
+				shortestPathReconcile, 3, 3, TimeUnit.SECONDS);
     }
 
     /**
@@ -524,26 +535,32 @@
 	IFlowPath flowObj = null;
 	boolean found = false;
 	try {
-	    if ((flowObj = conn.utils().searchFlowPath(conn, flowPath.flowId()))
+	    if ((flowObj = op.searchFlowPath(flowPath.flowId()))
 		!= null) {
 		log.debug("Adding FlowPath with FlowId {}: found existing FlowPath",
 			  flowPath.flowId().toString());
 		found = true;
 	    } else {
-		flowObj = conn.utils().newFlowPath(conn);
+		flowObj = op.newFlowPath();
 		log.debug("Adding FlowPath with FlowId {}: creating new FlowPath",
 			  flowPath.flowId().toString());
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
-	    conn.endTx(Transaction.ROLLBACK);
-	    log.error(":addFlow FlowId:{} failed",
-		      flowPath.flowId().toString());
+	    op.rollback();
+
+	    StringWriter sw = new StringWriter();
+	    e.printStackTrace(new PrintWriter(sw));
+	    String stacktrace = sw.toString();
+
+	    log.error(":addFlow FlowId:{} failed: {}",
+		      flowPath.flowId().toString(),
+		      stacktrace);
 	}
 	if (flowObj == null) {
 	    log.error(":addFlow FlowId:{} failed: Flow object not created",
 		      flowPath.flowId().toString());
-	    conn.endTx(Transaction.ROLLBACK);
+	    op.rollback();
 	    return false;
 	}
 
@@ -557,33 +574,63 @@
 	//
 	// Set the Flow attributes:
 	// - flowPath.installerId()
+	// - flowPath.flowPathFlags()
 	// - flowPath.dataPath().srcPort()
 	// - flowPath.dataPath().dstPort()
-	// - flowPath.matchEthernetFrameType()
-	// - flowPath.matchSrcIPv4Net()
-	// - flowPath.matchDstIPv4Net()
 	// - flowPath.matchSrcMac()
 	// - flowPath.matchDstMac()
+	// - flowPath.matchEthernetFrameType()
+	// - flowPath.matchVlanId()
+	// - flowPath.matchVlanPriority()
+	// - flowPath.matchSrcIPv4Net()
+	// - flowPath.matchDstIPv4Net()
+	// - flowPath.matchIpProto()
+	// - flowPath.matchIpToS()
+	// - flowPath.matchSrcTcpUdpPort()
+	// - flowPath.matchDstTcpUdpPort()
+	// - flowPath.flowEntryActions()
 	//
 	flowObj.setInstallerId(flowPath.installerId().toString());
+	flowObj.setFlowPathFlags(flowPath.flowPathFlags().flags());
 	flowObj.setSrcSwitch(flowPath.dataPath().srcPort().dpid().toString());
 	flowObj.setSrcPort(flowPath.dataPath().srcPort().port().value());
 	flowObj.setDstSwitch(flowPath.dataPath().dstPort().dpid().toString());
 	flowObj.setDstPort(flowPath.dataPath().dstPort().port().value());
+	if (flowPath.flowEntryMatch().matchSrcMac()) {
+	    flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
+	}
+	if (flowPath.flowEntryMatch().matchDstMac()) {
+	    flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
+	}
 	if (flowPath.flowEntryMatch().matchEthernetFrameType()) {
 	    flowObj.setMatchEthernetFrameType(flowPath.flowEntryMatch().ethernetFrameType());
 	}
+	if (flowPath.flowEntryMatch().matchVlanId()) {
+	    flowObj.setMatchVlanId(flowPath.flowEntryMatch().vlanId());
+	}
+	if (flowPath.flowEntryMatch().matchVlanPriority()) {
+	    flowObj.setMatchVlanPriority(flowPath.flowEntryMatch().vlanPriority());
+	}
 	if (flowPath.flowEntryMatch().matchSrcIPv4Net()) {
 	    flowObj.setMatchSrcIPv4Net(flowPath.flowEntryMatch().srcIPv4Net().toString());
 	}
 	if (flowPath.flowEntryMatch().matchDstIPv4Net()) {
 	    flowObj.setMatchDstIPv4Net(flowPath.flowEntryMatch().dstIPv4Net().toString());
 	}
-	if (flowPath.flowEntryMatch().matchSrcMac()) {
-	    flowObj.setMatchSrcMac(flowPath.flowEntryMatch().srcMac().toString());
+	if (flowPath.flowEntryMatch().matchIpProto()) {
+	    flowObj.setMatchIpProto(flowPath.flowEntryMatch().ipProto());
 	}
-	if (flowPath.flowEntryMatch().matchDstMac()) {
-	    flowObj.setMatchDstMac(flowPath.flowEntryMatch().dstMac().toString());
+	if (flowPath.flowEntryMatch().matchIpToS()) {
+	    flowObj.setMatchIpToS(flowPath.flowEntryMatch().ipToS());
+	}
+	if (flowPath.flowEntryMatch().matchSrcTcpUdpPort()) {
+	    flowObj.setMatchSrcTcpUdpPort(flowPath.flowEntryMatch().srcTcpUdpPort());
+	}
+	if (flowPath.flowEntryMatch().matchDstTcpUdpPort()) {
+	    flowObj.setMatchDstTcpUdpPort(flowPath.flowEntryMatch().dstTcpUdpPort());
+	}
+	if (! flowPath.flowEntryActions().actions().isEmpty()) {
+	    flowObj.setActions(flowPath.flowEntryActions().toString());
 	}
 
 	if (dataPathSummaryStr != null) {
@@ -607,11 +654,11 @@
 	//
 	for (FlowEntry flowEntry : flowPath.dataPath().flowEntries()) {
 	    if (addFlowEntry(flowObj, flowEntry) == null) {
-		conn.endTx(Transaction.ROLLBACK);
+		op.rollback();
 		return false;
 	    }
 	}
-	conn.endTx(Transaction.COMMIT);
+	op.commit();
 
 	//
 	// TODO: We need a proper Flow ID allocation mechanism.
@@ -645,12 +692,12 @@
 	boolean found = false;
 	try {
 	    if ((flowEntryObj =
-		 conn.utils().searchFlowEntry(conn, flowEntry.flowEntryId())) != null) {
+		 op.searchFlowEntry(flowEntry.flowEntryId())) != null) {
 		log.debug("Adding FlowEntry with FlowEntryId {}: found existing FlowEntry",
 			  flowEntry.flowEntryId().toString());
 		found = true;
 	    } else {
-		flowEntryObj = conn.utils().newFlowEntry(conn);
+		flowEntryObj = op.newFlowEntry();
 		log.debug("Adding FlowEntry with FlowEntryId {}: creating new FlowEntry",
 			  flowEntry.flowEntryId().toString());
 	    }
@@ -678,57 +725,83 @@
 	// - InPort edge
 	// - OutPort edge
 	//
-	// - flowEntry.flowEntryMatch()
-	// - flowEntry.flowEntryActions()
 	// - flowEntry.dpid()
 	// - flowEntry.flowEntryUserState()
 	// - flowEntry.flowEntrySwitchState()
 	// - flowEntry.flowEntryErrorState()
 	// - flowEntry.matchInPort()
-	// - flowEntry.matchEthernetFrameType()
-	// - flowEntry.matchSrcIPv4Net()
-	// - flowEntry.matchDstIPv4Net()
 	// - flowEntry.matchSrcMac()
 	// - flowEntry.matchDstMac()
-	// - flowEntry.actionOutput()
+	// - flowEntry.matchEthernetFrameType()
+	// - flowEntry.matchVlanId()
+	// - flowEntry.matchVlanPriority()
+	// - flowEntry.matchSrcIPv4Net()
+	// - flowEntry.matchDstIPv4Net()
+	// - flowEntry.matchIpProto()
+	// - flowEntry.matchIpToS()
+	// - flowEntry.matchSrcTcpUdpPort()
+	// - flowEntry.matchDstTcpUdpPort()
+	// - flowEntry.actionOutputPort()
+	// - flowEntry.actions()
 	//
 	ISwitchObject sw =
-	    conn.utils().searchSwitch(conn, flowEntry.dpid().toString());
+	    op.searchSwitch(flowEntry.dpid().toString());
 	flowEntryObj.setSwitchDpid(flowEntry.dpid().toString());
 	flowEntryObj.setSwitch(sw);
 	if (flowEntry.flowEntryMatch().matchInPort()) {
 	    IPortObject inport =
-		conn.utils().searchPort(conn, flowEntry.dpid().toString(),
+		op.searchPort(flowEntry.dpid().toString(),
 					flowEntry.flowEntryMatch().inPort().value());
 	    flowEntryObj.setMatchInPort(flowEntry.flowEntryMatch().inPort().value());
 	    flowEntryObj.setInPort(inport);
 	}
-	if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
-	    flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
-	}
-	if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
-	    flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
-	}
-	if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
-	    flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
-	}
 	if (flowEntry.flowEntryMatch().matchSrcMac()) {
 	    flowEntryObj.setMatchSrcMac(flowEntry.flowEntryMatch().srcMac().toString());
 	}
 	if (flowEntry.flowEntryMatch().matchDstMac()) {
 	    flowEntryObj.setMatchDstMac(flowEntry.flowEntryMatch().dstMac().toString());
 	}
+	if (flowEntry.flowEntryMatch().matchEthernetFrameType()) {
+	    flowEntryObj.setMatchEthernetFrameType(flowEntry.flowEntryMatch().ethernetFrameType());
+	}
+	if (flowEntry.flowEntryMatch().matchVlanId()) {
+	    flowEntryObj.setMatchVlanId(flowEntry.flowEntryMatch().vlanId());
+	}
+	if (flowEntry.flowEntryMatch().matchVlanPriority()) {
+	    flowEntryObj.setMatchVlanPriority(flowEntry.flowEntryMatch().vlanPriority());
+	}
+	if (flowEntry.flowEntryMatch().matchSrcIPv4Net()) {
+	    flowEntryObj.setMatchSrcIPv4Net(flowEntry.flowEntryMatch().srcIPv4Net().toString());
+	}
+	if (flowEntry.flowEntryMatch().matchDstIPv4Net()) {
+	    flowEntryObj.setMatchDstIPv4Net(flowEntry.flowEntryMatch().dstIPv4Net().toString());
+	}
+	if (flowEntry.flowEntryMatch().matchIpProto()) {
+	    flowEntryObj.setMatchIpProto(flowEntry.flowEntryMatch().ipProto());
+	}
+	if (flowEntry.flowEntryMatch().matchIpToS()) {
+	    flowEntryObj.setMatchIpToS(flowEntry.flowEntryMatch().ipToS());
+	}
+	if (flowEntry.flowEntryMatch().matchSrcTcpUdpPort()) {
+	    flowEntryObj.setMatchSrcTcpUdpPort(flowEntry.flowEntryMatch().srcTcpUdpPort());
+	}
+	if (flowEntry.flowEntryMatch().matchDstTcpUdpPort()) {
+	    flowEntryObj.setMatchDstTcpUdpPort(flowEntry.flowEntryMatch().dstTcpUdpPort());
+	}
 
-	for (FlowEntryAction fa : flowEntry.flowEntryActions()) {
+	for (FlowEntryAction fa : flowEntry.flowEntryActions().actions()) {
 	    if (fa.actionOutput() != null) {
 		IPortObject outport =
-		    conn.utils().searchPort(conn,
-					    flowEntry.dpid().toString(),
-					    fa.actionOutput().port().value());
-		flowEntryObj.setActionOutput(fa.actionOutput().port().value());
+		    op.searchPort(flowEntry.dpid().toString(),
+					      fa.actionOutput().port().value());
+		flowEntryObj.setActionOutputPort(fa.actionOutput().port().value());
 		flowEntryObj.setOutPort(outport);
 	    }
 	}
+	if (! flowEntry.flowEntryActions().isEmpty()) {
+	    flowEntryObj.setActions(flowEntry.flowEntryActions().toString());
+	}
+
 	// TODO: Hacks with hard-coded state names!
 	if (found)
 	    flowEntryObj.setUserState("FE_USER_MODIFY");
@@ -757,13 +830,63 @@
      */
     @Override
     public boolean deleteAllFlows() {
+	List<Thread> threads = new LinkedList<Thread>();
+	final ConcurrentLinkedQueue<FlowId> concurrentAllFlowIds =
+	    new ConcurrentLinkedQueue<FlowId>();
 
-	// Get all flows and delete them one-by-one
-    	ArrayList<FlowPath> allFlows = getAllFlows();
-	for (FlowPath flowPath : allFlows) {
-	    deleteFlow(flowPath.flowId());
+	// Get all Flow IDs
+	Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
+	for (IFlowPath flowPathObj : allFlowPaths) {
+	    if (flowPathObj == null)
+		continue;
+	    String flowIdStr = flowPathObj.getFlowId();
+	    if (flowIdStr == null)
+		continue;
+	    FlowId flowId = new FlowId(flowIdStr);
+	    concurrentAllFlowIds.add(flowId);
 	}
 
+	// Delete all flows one-by-one
+	for (FlowId flowId : concurrentAllFlowIds)
+	    deleteFlow(flowId);
+
+	/*
+	 * TODO: A faster mechanism to delete the Flow Paths by using
+	 * a number of threads. Commented-out for now.
+	 */
+	/*
+	//
+	// Create the threads to delete the Flow Paths
+	//
+	for (int i = 0; i < 10; i++) {
+	    Thread thread = new Thread(new Runnable() {
+		@Override
+		public void run() {
+		    while (true) {
+			FlowId flowId = concurrentAllFlowIds.poll();
+			if (flowId == null)
+			    return;
+			deleteFlow(flowId);
+		    }
+		}}, "Delete All Flow Paths");
+	    threads.add(thread);
+	}
+
+	// Start processing
+	for (Thread thread : threads) {
+	    thread.start();
+	}
+
+	// Wait for all threads to complete
+	for (Thread thread : threads) {
+	    try {
+		thread.join();
+	    } catch (InterruptedException e) {
+		log.debug("Exception waiting for a thread to delete a Flow Path: ", e);
+	    }
+	}
+	*/
+
 	return true;
     }
 
@@ -789,7 +912,7 @@
 	// it has been removed from the switches.
 	//
 	try {
-	    if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
+	    if ((flowObj = op.searchFlowPath(flowId))
 		!= null) {
 		log.debug("Deleting FlowPath with FlowId {}: found existing FlowPath",
 			  flowId.toString());
@@ -799,11 +922,11 @@
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
-	    conn.endTx(Transaction.ROLLBACK);
+	    op.rollback();
 	    log.error(":deleteFlow FlowId:{} failed", flowId.toString());
 	}
 	if (flowObj == null) {
-	    conn.endTx(Transaction.COMMIT);
+	    op.commit();
 	    return true;		// OK: No such flow
 	}
 
@@ -823,8 +946,8 @@
 	}
 	// Remove from the database empty flows
 	if (empty)
-	    conn.utils().removeFlowPath(conn, flowObj);
-	conn.endTx(Transaction.COMMIT);
+	    op.removeFlowPath(flowObj);
+	op.commit();
 
 	return true;
     }
@@ -836,11 +959,23 @@
      */
     @Override
     public boolean clearAllFlows() {
+	List<FlowId> allFlowIds = new LinkedList<FlowId>();
 
-	// Get all flows and clear them one-by-one
-    	ArrayList<FlowPath> allFlows = getAllFlows();
-	for (FlowPath flowPath : allFlows) {
-	    clearFlow(flowPath.flowId());
+	// Get all Flow IDs
+	Iterable<IFlowPath> allFlowPaths = op.getAllFlowPaths();
+	for (IFlowPath flowPathObj : allFlowPaths) {
+	    if (flowPathObj == null)
+		continue;
+	    String flowIdStr = flowPathObj.getFlowId();
+	    if (flowIdStr == null)
+		continue;
+	    FlowId flowId = new FlowId(flowIdStr);
+	    allFlowIds.add(flowId);
+	}
+
+	// Clear all flows one-by-one
+	for (FlowId flowId : allFlowIds) {
+	    clearFlow(flowId);
 	}
 
 	return true;
@@ -856,7 +991,7 @@
     public boolean clearFlow(FlowId flowId) {
 	IFlowPath flowObj = null;
 	try {
-	    if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
+	    if ((flowObj = op.searchFlowPath(flowId))
 		!= null) {
 		log.debug("Clearing FlowPath with FlowId {}: found existing FlowPath",
 			  flowId.toString());
@@ -866,11 +1001,11 @@
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
-	    conn.endTx(Transaction.ROLLBACK);
+	    op.rollback();
 	    log.error(":clearFlow FlowId:{} failed", flowId.toString());
 	}
 	if (flowObj == null) {
-	    conn.endTx(Transaction.COMMIT);
+	    op.commit();
 	    return true;		// OK: No such flow
 	}
 
@@ -880,11 +1015,11 @@
 	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
 	for (IFlowEntry flowEntryObj : flowEntries) {
 	    flowObj.removeFlowEntry(flowEntryObj);
-	    conn.utils().removeFlowEntry(conn, flowEntryObj);
+	    op.removeFlowEntry(flowEntryObj);
 	}
 	// Remove the Flow itself
-	conn.utils().removeFlowPath(conn, flowObj);
-	conn.endTx(Transaction.COMMIT);
+	op.removeFlowPath(flowObj);
+	op.commit();
 
 	return true;
     }
@@ -899,7 +1034,7 @@
     public FlowPath getFlow(FlowId flowId) {
 	IFlowPath flowObj = null;
 	try {
-	    if ((flowObj = conn.utils().searchFlowPath(conn, flowId))
+	    if ((flowObj = op.searchFlowPath(flowId))
 		!= null) {
 		log.debug("Get FlowPath with FlowId {}: found existing FlowPath",
 			  flowId.toString());
@@ -909,11 +1044,11 @@
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
-	    conn.endTx(Transaction.ROLLBACK);
+	    op.rollback();
 	    log.error(":getFlow FlowId:{} failed", flowId.toString());
 	}
 	if (flowObj == null) {
-	    conn.endTx(Transaction.COMMIT);
+	    op.commit();
 	    return null;		// Flow not found
 	}
 
@@ -921,7 +1056,7 @@
 	// Extract the Flow state
 	//
 	FlowPath flowPath = extractFlowPath(flowObj);
-	conn.endTx(Transaction.COMMIT);
+	op.commit();
 
 	return flowPath;
     }
@@ -1112,18 +1247,18 @@
 	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
 
 	try {
-	    if ((flowPathsObj = conn.utils().getAllFlowPaths(conn)) != null) {
+	    if ((flowPathsObj = op.getAllFlowPaths()) != null) {
 		log.debug("Get all FlowPaths: found FlowPaths");
 	    } else {
 		log.debug("Get all FlowPaths: no FlowPaths found");
 	    }
 	} catch (Exception e) {
 	    // TODO: handle exceptions
-	    conn.endTx(Transaction.ROLLBACK);
+	    op.rollback();
 	    log.error(":getAllFlowPaths failed");
 	}
 	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
-	    conn.endTx(Transaction.COMMIT);
+	    op.commit();
 	    return flowPaths;	// No Flows found
 	}
 
@@ -1136,7 +1271,7 @@
 		flowPaths.add(flowPath);
 	}
 
-	conn.endTx(Transaction.COMMIT);
+	op.commit();
 
 	return flowPaths;
     }
@@ -1146,17 +1281,17 @@
     	ArrayList<IFlowPath> flowPathsObjArray = new ArrayList<IFlowPath>();
     	ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
 
-    	conn.endTx(Transaction.COMMIT);
+    	op.commit();
     	
     	try {
-    	    if ((flowPathsObj = conn.utils().getAllFlowPaths(conn)) != null) {
+    	    if ((flowPathsObj = op.getAllFlowPaths()) != null) {
     		log.debug("Get all FlowPaths: found FlowPaths");
     	    } else {
     		log.debug("Get all FlowPaths: no FlowPaths found");
     	    }
     	} catch (Exception e) {
     	    // TODO: handle exceptions
-    	    conn.endTx(Transaction.ROLLBACK);
+    	    op.rollback();
     	    log.error(":getAllFlowPaths failed");
     	}
     	if ((flowPathsObj == null) || (flowPathsObj.iterator().hasNext() == false)) {
@@ -1194,6 +1329,7 @@
 	//
 	String flowIdStr = flowObj.getFlowId();
 	String installerIdStr = flowObj.getInstallerId();
+	Long flowPathFlags = flowObj.getFlowPathFlags();
 	String srcSwitchStr = flowObj.getSrcSwitch();
 	Short srcPortShort = flowObj.getSrcPort();
 	String dstSwitchStr = flowObj.getDstSwitch();
@@ -1201,6 +1337,7 @@
 
 	if ((flowIdStr == null) ||
 	    (installerIdStr == null) ||
+	    (flowPathFlags == null) ||
 	    (srcSwitchStr == null) ||
 	    (srcPortShort == null) ||
 	    (dstSwitchStr == null) ||
@@ -1212,6 +1349,7 @@
 	FlowPath flowPath = new FlowPath();
 	flowPath.setFlowId(new FlowId(flowIdStr));
 	flowPath.setInstallerId(new CallerId(installerIdStr));
+	flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
 	flowPath.dataPath().srcPort().setDpid(new Dpid(srcSwitchStr));
 	flowPath.dataPath().srcPort().setPort(new Port(srcPortShort));
 	flowPath.dataPath().dstPort().setDpid(new Dpid(dstSwitchStr));
@@ -1221,23 +1359,52 @@
 	//
 	{
 	    FlowEntryMatch match = new FlowEntryMatch();
-	    Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
-	    if (matchEthernetFrameType != null)
-		match.enableEthernetFrameType(matchEthernetFrameType);
-	    String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
-	    if (matchSrcIPv4Net != null)
-		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
-	    String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
-	    if (matchDstIPv4Net != null)
-		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
 	    String matchSrcMac = flowObj.getMatchSrcMac();
 	    if (matchSrcMac != null)
 		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
 	    String matchDstMac = flowObj.getMatchDstMac();
 	    if (matchDstMac != null)
 		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+	    Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
+	    if (matchEthernetFrameType != null)
+		match.enableEthernetFrameType(matchEthernetFrameType);
+	    Short matchVlanId = flowObj.getMatchVlanId();
+	    if (matchVlanId != null)
+		match.enableVlanId(matchVlanId);
+	    Byte matchVlanPriority = flowObj.getMatchVlanPriority();
+	    if (matchVlanPriority != null)
+		match.enableVlanPriority(matchVlanPriority);
+	    String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
+	    if (matchSrcIPv4Net != null)
+		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+	    String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
+	    if (matchDstIPv4Net != null)
+		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+	    Byte matchIpProto = flowObj.getMatchIpProto();
+	    if (matchIpProto != null)
+		match.enableIpProto(matchIpProto);
+	    Byte matchIpToS = flowObj.getMatchIpToS();
+	    if (matchIpToS != null)
+		match.enableIpToS(matchIpToS);
+	    Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
+	    if (matchSrcTcpUdpPort != null)
+		match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+	    Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
+	    if (matchDstTcpUdpPort != null)
+		match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+
 	    flowPath.setFlowEntryMatch(match);
 	}
+	//
+	// Extract the actions for the first Flow Entry
+	//
+	{
+	    String actionsStr = flowObj.getActions();
+	    if (actionsStr != null) {
+		FlowEntryActions flowEntryActions = new FlowEntryActions(actionsStr);
+		flowPath.setFlowEntryActions(flowEntryActions);
+	    }
+	}
 
 	//
 	// Extract all Flow Entries
@@ -1284,39 +1451,53 @@
 	Short matchInPort = flowEntryObj.getMatchInPort();
 	if (matchInPort != null)
 	    match.enableInPort(new Port(matchInPort));
-	Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
-	if (matchEthernetFrameType != null)
-	    match.enableEthernetFrameType(matchEthernetFrameType);
-	String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
-	if (matchSrcIPv4Net != null)
-	    match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
-	String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
-	if (matchDstIPv4Net != null)
-	    match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
 	String matchSrcMac = flowEntryObj.getMatchSrcMac();
 	if (matchSrcMac != null)
 	    match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
 	String matchDstMac = flowEntryObj.getMatchDstMac();
 	if (matchDstMac != null)
 	    match.enableDstMac(MACAddress.valueOf(matchDstMac));
+	Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+	if (matchEthernetFrameType != null)
+	    match.enableEthernetFrameType(matchEthernetFrameType);
+	Short matchVlanId = flowEntryObj.getMatchVlanId();
+	if (matchVlanId != null)
+	    match.enableVlanId(matchVlanId);
+	Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
+	if (matchVlanPriority != null)
+	    match.enableVlanPriority(matchVlanPriority);
+	String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+	if (matchSrcIPv4Net != null)
+	    match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+	String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+	if (matchDstIPv4Net != null)
+	    match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+	Byte matchIpProto = flowEntryObj.getMatchIpProto();
+	if (matchIpProto != null)
+	    match.enableIpProto(matchIpProto);
+	Byte matchIpToS = flowEntryObj.getMatchIpToS();
+	if (matchIpToS != null)
+	    match.enableIpToS(matchIpToS);
+	Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
+	if (matchSrcTcpUdpPort != null)
+	    match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+	Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
+	if (matchDstTcpUdpPort != null)
+	    match.enableDstTcpUdpPort(matchDstTcpUdpPort);
 	flowEntry.setFlowEntryMatch(match);
 
 	//
 	// Extract the actions
 	//
-	ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
-	Short actionOutputPort = flowEntryObj.getActionOutput();
-	if (actionOutputPort != null) {
-	    FlowEntryAction action = new FlowEntryAction();
-	    action.setActionOutput(new Port(actionOutputPort));
-	    actions.add(action);
-	}
+	FlowEntryActions actions = new FlowEntryActions();
+	String actionsStr = flowEntryObj.getActions();
+	if (actionsStr != null)
+	    actions = new FlowEntryActions(actionsStr);
 	flowEntry.setFlowEntryActions(actions);
 	flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
 	flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
 	//
-	// TODO: Take care of the FlowEntryMatch, FlowEntryAction set,
-	// and FlowEntryErrorState.
+	// TODO: Take care of FlowEntryErrorState.
 	//
 	return flowEntry;
     }
@@ -1348,8 +1529,10 @@
 	FlowPath computedFlowPath = new FlowPath();
 	computedFlowPath.setFlowId(new FlowId(flowPath.flowId().value()));
 	computedFlowPath.setInstallerId(new CallerId(flowPath.installerId().value()));
+	computedFlowPath.setFlowPathFlags(new FlowPathFlags(flowPath.flowPathFlags().flags()));
 	computedFlowPath.setDataPath(dataPath);
 	computedFlowPath.setFlowEntryMatch(new FlowEntryMatch(flowPath.flowEntryMatch()));
+	computedFlowPath.setFlowEntryActions(new FlowEntryActions(flowPath.flowEntryActions()));
 
 	FlowId flowId = new FlowId();
 	String dataPathSummaryStr = dataPath.dataPathSummary();
@@ -1375,21 +1558,35 @@
 	// Set the incoming port matching and the outgoing port output
 	// actions for each flow entry.
 	//
+	int idx = 0;
 	for (FlowEntry flowEntry : newDataPath.flowEntries()) {
 	    // Set the incoming port matching
 	    FlowEntryMatch flowEntryMatch = new FlowEntryMatch();
 	    flowEntry.setFlowEntryMatch(flowEntryMatch);
 	    flowEntryMatch.enableInPort(flowEntry.inPort());
 
-	    // Set the outgoing port output action
-	    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
-	    if (flowEntryActions == null) {
-		flowEntryActions = new ArrayList<FlowEntryAction>();
-		flowEntry.setFlowEntryActions(flowEntryActions);
+	    //
+	    // Set the actions
+	    //
+	    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
+	    //
+	    // If the first Flow Entry, copy the Flow Path actions to it
+	    //
+	    if (idx == 0) {
+		String actionsStr = flowObj.getActions();
+		if (actionsStr != null) {
+		    FlowEntryActions flowActions = new FlowEntryActions(actionsStr);
+		    for (FlowEntryAction action : flowActions.actions())
+			flowEntryActions.addAction(action);
+		}
 	    }
+	    idx++;
+	    //
+	    // Add the outgoing port output action
+	    //
 	    FlowEntryAction flowEntryAction = new FlowEntryAction();
 	    flowEntryAction.setActionOutput(flowEntry.outPort());
-	    flowEntryActions.add(flowEntryAction);
+	    flowEntryActions.addAction(flowEntryAction);
 	}
 
 	//
@@ -1481,31 +1678,6 @@
 	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
 	}
 
-	// Match the Ethernet Frame Type
-	Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
-	if (matchEthernetFrameType == null)
-	    matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
-	if (matchEthernetFrameType != null) {
-	    match.setDataLayerType(matchEthernetFrameType);
-	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
-	}
-
-	// Match the Source IPv4 Network prefix
-	String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
-	if (matchSrcIPv4Net == null)
-	    matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
-	if (matchSrcIPv4Net != null) {
-	    match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
-	}
-
-	// Natch the Destination IPv4 Network prefix
-	String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
-	if (matchDstIPv4Net == null)
-	    matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
-	if (matchDstIPv4Net != null) {
-	    match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
-	}
-
 	// Match the Source MAC address
 	String matchSrcMac = flowEntryObj.getMatchSrcMac();
 	if (matchSrcMac == null)
@@ -1524,19 +1696,197 @@
 	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
 	}
 
+	// Match the Ethernet Frame Type
+	Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+	if (matchEthernetFrameType == null)
+	    matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
+	if (matchEthernetFrameType != null) {
+	    match.setDataLayerType(matchEthernetFrameType);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	}
+
+	// Match the VLAN ID
+	Short matchVlanId = flowEntryObj.getMatchVlanId();
+	if (matchVlanId == null)
+	    matchVlanId = flowObj.getMatchVlanId();
+	if (matchVlanId != null) {
+	    match.setDataLayerVirtualLan(matchVlanId);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
+	}
+
+	// Match the VLAN priority
+	Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
+	if (matchVlanPriority == null)
+	    matchVlanPriority = flowObj.getMatchVlanPriority();
+	if (matchVlanPriority != null) {
+	    match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
+	}
+
+	// Match the Source IPv4 Network prefix
+	String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+	if (matchSrcIPv4Net == null)
+	    matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
+	if (matchSrcIPv4Net != null) {
+	    match.setFromCIDR(matchSrcIPv4Net, OFMatch.STR_NW_SRC);
+	}
+
+	// Natch the Destination IPv4 Network prefix
+	String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+	if (matchDstIPv4Net == null)
+	    matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
+	if (matchDstIPv4Net != null) {
+	    match.setFromCIDR(matchDstIPv4Net, OFMatch.STR_NW_DST);
+	}
+
+	// Match the IP protocol
+	Byte matchIpProto = flowEntryObj.getMatchIpProto();
+	if (matchIpProto == null)
+	    matchIpProto = flowObj.getMatchIpProto();
+	if (matchIpProto != null) {
+	    match.setNetworkProtocol(matchIpProto);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
+	}
+
+	// Match the IP ToS (DSCP field, 6 bits)
+	Byte matchIpToS = flowEntryObj.getMatchIpToS();
+	if (matchIpToS == null)
+	    matchIpToS = flowObj.getMatchIpToS();
+	if (matchIpToS != null) {
+	    match.setNetworkTypeOfService(matchIpToS);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
+	}
+
+	// Match the Source TCP/UDP port
+	Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
+	if (matchSrcTcpUdpPort == null)
+	    matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
+	if (matchSrcTcpUdpPort != null) {
+	    match.setTransportSource(matchSrcTcpUdpPort);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+	}
+
+	// Match the Destination TCP/UDP port
+	Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
+	if (matchDstTcpUdpPort == null)
+	    matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
+	if (matchDstTcpUdpPort != null) {
+	    match.setTransportDestination(matchDstTcpUdpPort);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+	}
+
 	//
 	// Fetch the actions
 	//
-	// TODO: For now we support only the "OUTPUT" actions.
-	//
-	List<OFAction> actions = new ArrayList<OFAction>();
-	Short actionOutputPort = flowEntryObj.getActionOutput();
-	if (actionOutputPort != null) {
-	    OFActionOutput action = new OFActionOutput();
-	    // XXX: The max length is hard-coded for now
-	    action.setMaxLength((short)0xffff);
-	    action.setPort(actionOutputPort);
-	    actions.add(action);
+	Short actionOutputPort = null;
+	List<OFAction> openFlowActions = new ArrayList<OFAction>();
+	int actionsLen = 0;
+	FlowEntryActions flowEntryActions = null;
+	String actionsStr = flowEntryObj.getActions();
+	if (actionsStr != null)
+	    flowEntryActions = new FlowEntryActions(actionsStr);
+	for (FlowEntryAction action : flowEntryActions.actions()) {
+	    ActionOutput actionOutput = action.actionOutput();
+	    ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+	    ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+	    ActionStripVlan actionStripVlan = action.actionStripVlan();
+	    ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+	    ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+	    ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+	    ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+	    ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+	    ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+	    ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+	    ActionEnqueue actionEnqueue = action.actionEnqueue();
+
+	    if (actionOutput != null) {
+		actionOutputPort = actionOutput.port().value();
+		// XXX: The max length is hard-coded for now
+		OFActionOutput ofa =
+		    new OFActionOutput(actionOutput.port().value(),
+				       (short)0xffff);
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetVlanId != null) {
+		OFActionVirtualLanIdentifier ofa =
+		    new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetVlanPriority != null) {
+		OFActionVirtualLanPriorityCodePoint ofa =
+		    new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionStripVlan != null) {
+		if (actionStripVlan.stripVlan() == true) {
+		    OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+		    openFlowActions.add(ofa);
+		    actionsLen += ofa.getLength();
+		}
+	    }
+
+	    if (actionSetEthernetSrcAddr != null) {
+		OFActionDataLayerSource ofa = 
+		    new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetEthernetDstAddr != null) {
+		OFActionDataLayerDestination ofa =
+		    new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIPv4SrcAddr != null) {
+		OFActionNetworkLayerSource ofa =
+		    new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIPv4DstAddr != null) {
+		OFActionNetworkLayerDestination ofa =
+		    new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIpToS != null) {
+		OFActionNetworkTypeOfService ofa =
+		    new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetTcpUdpSrcPort != null) {
+		OFActionTransportLayerSource ofa =
+		    new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetTcpUdpDstPort != null) {
+		OFActionTransportLayerDestination ofa =
+		    new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionEnqueue != null) {
+		OFActionEnqueue ofa =
+		    new OFActionEnqueue(actionEnqueue.port().value(),
+					actionEnqueue.queueId());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
 	}
 
 	fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
@@ -1546,8 +1896,8 @@
 	    .setCookie(cookie)
 	    .setCommand(flowModCommand)
 	    .setMatch(match)
-	    .setActions(actions)
-	    .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+	    .setActions(openFlowActions)
+	    .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
 	fm.setOutPort(OFPort.OFPP_NONE.getValue());
 	if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
 	    (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
@@ -1640,34 +1990,6 @@
 	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_IN_PORT);
 	}
 
-	// Match the Ethernet Frame Type
-	Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
-	if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
-	    matchEthernetFrameType = flowPathMatch.ethernetFrameType();
-	}
-	if (matchEthernetFrameType != null) {
-	    match.setDataLayerType(matchEthernetFrameType);
-	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
-	}
-
-	// Match the Source IPv4 Network prefix
-	IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
-	if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
-	    matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
-	}
-	if (matchSrcIPv4Net != null) {
-	    match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
-	}
-
-	// Natch the Destination IPv4 Network prefix
-	IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
-	if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
-	    matchDstIPv4Net = flowPathMatch.dstIPv4Net();
-	}
-	if (matchDstIPv4Net != null) {
-	    match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
-	}
-
 	// Match the Source MAC address
 	MACAddress matchSrcMac = flowEntryMatch.srcMac();
 	if ((matchSrcMac == null) && (flowPathMatch != null)) {
@@ -1688,30 +2010,204 @@
 	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_DST);
 	}
 
+	// Match the Ethernet Frame Type
+	Short matchEthernetFrameType = flowEntryMatch.ethernetFrameType();
+	if ((matchEthernetFrameType == null) && (flowPathMatch != null)) {
+	    matchEthernetFrameType = flowPathMatch.ethernetFrameType();
+	}
+	if (matchEthernetFrameType != null) {
+	    match.setDataLayerType(matchEthernetFrameType);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_TYPE);
+	}
+
+	// Match the VLAN ID
+	Short matchVlanId = flowEntryMatch.vlanId();
+	if ((matchVlanId == null) && (flowPathMatch != null)) {
+	    matchVlanId = flowPathMatch.vlanId();
+	}
+	if (matchVlanId != null) {
+	    match.setDataLayerVirtualLan(matchVlanId);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN);
+	}
+
+	// Match the VLAN priority
+	Byte matchVlanPriority = flowEntryMatch.vlanPriority();
+	if ((matchVlanPriority == null) && (flowPathMatch != null)) {
+	    matchVlanPriority = flowPathMatch.vlanPriority();
+	}
+	if (matchVlanPriority != null) {
+	    match.setDataLayerVirtualLanPriorityCodePoint(matchVlanPriority);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_DL_VLAN_PCP);
+	}
+
+	// Match the Source IPv4 Network prefix
+	IPv4Net matchSrcIPv4Net = flowEntryMatch.srcIPv4Net();
+	if ((matchSrcIPv4Net == null) && (flowPathMatch != null)) {
+	    matchSrcIPv4Net = flowPathMatch.srcIPv4Net();
+	}
+	if (matchSrcIPv4Net != null) {
+	    match.setFromCIDR(matchSrcIPv4Net.toString(), OFMatch.STR_NW_SRC);
+	}
+
+	// Natch the Destination IPv4 Network prefix
+	IPv4Net matchDstIPv4Net = flowEntryMatch.dstIPv4Net();
+	if ((matchDstIPv4Net == null) && (flowPathMatch != null)) {
+	    matchDstIPv4Net = flowPathMatch.dstIPv4Net();
+	}
+	if (matchDstIPv4Net != null) {
+	    match.setFromCIDR(matchDstIPv4Net.toString(), OFMatch.STR_NW_DST);
+	}
+
+	// Match the IP protocol
+	Byte matchIpProto = flowEntryMatch.ipProto();
+	if ((matchIpProto == null) && (flowPathMatch != null)) {
+	    matchIpProto = flowPathMatch.ipProto();
+	}
+	if (matchIpProto != null) {
+	    match.setNetworkProtocol(matchIpProto);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_PROTO);
+	}
+
+	// Match the IP ToS (DSCP field, 6 bits)
+	Byte matchIpToS = flowEntryMatch.ipToS();
+	if ((matchIpToS == null) && (flowPathMatch != null)) {
+	    matchIpToS = flowPathMatch.ipToS();
+	}
+	if (matchIpToS != null) {
+	    match.setNetworkTypeOfService(matchIpToS);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_NW_TOS);
+	}
+
+	// Match the Source TCP/UDP port
+	Short matchSrcTcpUdpPort = flowEntryMatch.srcTcpUdpPort();
+	if ((matchSrcTcpUdpPort == null) && (flowPathMatch != null)) {
+	    matchSrcTcpUdpPort = flowPathMatch.srcTcpUdpPort();
+	}
+	if (matchSrcTcpUdpPort != null) {
+	    match.setTransportSource(matchSrcTcpUdpPort);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_SRC);
+	}
+
+	// Match the Destination TCP/UDP port
+	Short matchDstTcpUdpPort = flowEntryMatch.dstTcpUdpPort();
+	if ((matchDstTcpUdpPort == null) && (flowPathMatch != null)) {
+	    matchDstTcpUdpPort = flowPathMatch.dstTcpUdpPort();
+	}
+	if (matchDstTcpUdpPort != null) {
+	    match.setTransportDestination(matchDstTcpUdpPort);
+	    match.setWildcards(match.getWildcards() & ~OFMatch.OFPFW_TP_DST);
+	}
+
 	//
 	// Fetch the actions
 	//
-	// TODO: For now we support only the "OUTPUT" actions.
+	Short actionOutputPort = null;
+	List<OFAction> openFlowActions = new ArrayList<OFAction>();
+	int actionsLen = 0;
+	FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
 	//
-	fm.setOutPort(OFPort.OFPP_NONE.getValue());
-	List<OFAction> actions = new ArrayList<OFAction>();
-	ArrayList<FlowEntryAction> flowEntryActions =
-	    flowEntry.flowEntryActions();
-	for (FlowEntryAction flowEntryAction : flowEntryActions) {
-	    FlowEntryAction.ActionOutput actionOutput =
-		flowEntryAction.actionOutput();
+	for (FlowEntryAction action : flowEntryActions.actions()) {
+	    ActionOutput actionOutput = action.actionOutput();
+	    ActionSetVlanId actionSetVlanId = action.actionSetVlanId();
+	    ActionSetVlanPriority actionSetVlanPriority = action.actionSetVlanPriority();
+	    ActionStripVlan actionStripVlan = action.actionStripVlan();
+	    ActionSetEthernetAddr actionSetEthernetSrcAddr = action.actionSetEthernetSrcAddr();
+	    ActionSetEthernetAddr actionSetEthernetDstAddr = action.actionSetEthernetDstAddr();
+	    ActionSetIPv4Addr actionSetIPv4SrcAddr = action.actionSetIPv4SrcAddr();
+	    ActionSetIPv4Addr actionSetIPv4DstAddr = action.actionSetIPv4DstAddr();
+	    ActionSetIpToS actionSetIpToS = action.actionSetIpToS();
+	    ActionSetTcpUdpPort actionSetTcpUdpSrcPort = action.actionSetTcpUdpSrcPort();
+	    ActionSetTcpUdpPort actionSetTcpUdpDstPort = action.actionSetTcpUdpDstPort();
+	    ActionEnqueue actionEnqueue = action.actionEnqueue();
+
 	    if (actionOutput != null) {
-		short actionOutputPort = actionOutput.port().value();
-		OFActionOutput action = new OFActionOutput();
+		actionOutputPort = actionOutput.port().value();
 		// XXX: The max length is hard-coded for now
-		action.setMaxLength((short)0xffff);
-		action.setPort(actionOutputPort);
-		actions.add(action);
-		if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
-		    (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
-		    fm.setOutPort(actionOutputPort);
+		OFActionOutput ofa =
+		    new OFActionOutput(actionOutput.port().value(),
+				       (short)0xffff);
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetVlanId != null) {
+		OFActionVirtualLanIdentifier ofa =
+		    new OFActionVirtualLanIdentifier(actionSetVlanId.vlanId());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetVlanPriority != null) {
+		OFActionVirtualLanPriorityCodePoint ofa =
+		    new OFActionVirtualLanPriorityCodePoint(actionSetVlanPriority.vlanPriority());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionStripVlan != null) {
+		if (actionStripVlan.stripVlan() == true) {
+		    OFActionStripVirtualLan ofa = new OFActionStripVirtualLan();
+		    openFlowActions.add(ofa);
+		    actionsLen += ofa.getLength();
 		}
 	    }
+
+	    if (actionSetEthernetSrcAddr != null) {
+		OFActionDataLayerSource ofa = 
+		    new OFActionDataLayerSource(actionSetEthernetSrcAddr.addr().toBytes());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetEthernetDstAddr != null) {
+		OFActionDataLayerDestination ofa =
+		    new OFActionDataLayerDestination(actionSetEthernetDstAddr.addr().toBytes());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIPv4SrcAddr != null) {
+		OFActionNetworkLayerSource ofa =
+		    new OFActionNetworkLayerSource(actionSetIPv4SrcAddr.addr().value());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIPv4DstAddr != null) {
+		OFActionNetworkLayerDestination ofa =
+		    new OFActionNetworkLayerDestination(actionSetIPv4DstAddr.addr().value());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetIpToS != null) {
+		OFActionNetworkTypeOfService ofa =
+		    new OFActionNetworkTypeOfService(actionSetIpToS.ipToS());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetTcpUdpSrcPort != null) {
+		OFActionTransportLayerSource ofa =
+		    new OFActionTransportLayerSource(actionSetTcpUdpSrcPort.port());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionSetTcpUdpDstPort != null) {
+		OFActionTransportLayerDestination ofa =
+		    new OFActionTransportLayerDestination(actionSetTcpUdpDstPort.port());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
+
+	    if (actionEnqueue != null) {
+		OFActionEnqueue ofa =
+		    new OFActionEnqueue(actionEnqueue.port().value(),
+					actionEnqueue.queueId());
+		openFlowActions.add(ofa);
+		actionsLen += ofa.getLength();
+	    }
 	}
 
 	fm.setIdleTimeout(FLOWMOD_DEFAULT_IDLE_TIMEOUT)
@@ -1721,8 +2217,14 @@
 	    .setCookie(cookie)
 	    .setCommand(flowModCommand)
 	    .setMatch(match)
-	    .setActions(actions)
-	    .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
+	    .setActions(openFlowActions)
+	    .setLengthU(OFFlowMod.MINIMUM_LENGTH + actionsLen);
+	fm.setOutPort(OFPort.OFPP_NONE.getValue());
+	if ((flowModCommand == OFFlowMod.OFPFC_DELETE) ||
+	    (flowModCommand == OFFlowMod.OFPFC_DELETE_STRICT)) {
+	    if (actionOutputPort != null)
+		fm.setOutPort(actionOutputPort);
+	}
 
 	//
 	// TODO: Set the following flag
@@ -1816,18 +2318,19 @@
      * @return the stored shortest-path flow on success, otherwise null.
      */
     @Override
-    public FlowPath measurementStorePathFlow(FlowPath flowPath) {
+    public synchronized FlowPath measurementStorePathFlow(FlowPath flowPath) {
 	//
 	// Prepare the Shortest Path computation if the first Flow Path
 	//
 	if (measurementStoredPaths.isEmpty())
-	    topoRouteService.prepareShortestPathTopo();
+	    measurementShortestPathTopo = topoRouteService.prepareShortestPathTopo();
 
 	//
 	// Compute the Shortest Path
 	//
 	DataPath dataPath =
-	    topoRouteService.getTopoShortestPath(flowPath.dataPath().srcPort(),
+	    topoRouteService.getTopoShortestPath(measurementShortestPathTopo,
+						 flowPath.dataPath().srcPort(),
 						 flowPath.dataPath().dstPort());
 	if (dataPath == null) {
 	    // We need the DataPath to populate the Network MAP
@@ -1835,6 +2338,7 @@
 	    dataPath.setSrcPort(flowPath.dataPath().srcPort());
 	    dataPath.setDstPort(flowPath.dataPath().dstPort());
 	}
+	dataPath.applyFlowPathFlags(flowPath.flowPathFlags());
 
 	//
 	// Set the incoming port matching and the outgoing port output
@@ -1847,14 +2351,10 @@
 	    flowEntryMatch.enableInPort(flowEntry.inPort());
 
 	    // Set the outgoing port output action
-	    ArrayList<FlowEntryAction> flowEntryActions = flowEntry.flowEntryActions();
-	    if (flowEntryActions == null) {
-		flowEntryActions = new ArrayList<FlowEntryAction>();
-		flowEntry.setFlowEntryActions(flowEntryActions);
-	    }
+	    FlowEntryActions flowEntryActions = flowEntry.flowEntryActions();
 	    FlowEntryAction flowEntryAction = new FlowEntryAction();
 	    flowEntryAction.setActionOutput(flowEntry.outPort());
-	    flowEntryActions.add(flowEntryAction);
+	    flowEntryActions.addAction(flowEntryAction);
 	}
 
 	//
@@ -1863,14 +2363,18 @@
 	FlowPath computedFlowPath = new FlowPath();
 	computedFlowPath.setFlowId(new FlowId(flowPath.flowId().value()));
 	computedFlowPath.setInstallerId(new CallerId(flowPath.installerId().value()));
+	computedFlowPath.setFlowPathFlags(new FlowPathFlags(flowPath.flowPathFlags().flags()));
 	computedFlowPath.setDataPath(dataPath);
 	computedFlowPath.setFlowEntryMatch(new FlowEntryMatch(flowPath.flowEntryMatch()));
 
 	//
-	// Add the computed Flow Path the the internal storage
+	// Add the computed Flow Path to the internal storage
 	//
 	measurementStoredPaths.add(computedFlowPath);
 
+	log.debug("Measurement storing path {}",
+		  computedFlowPath.flowId().toString());
+
 	return (computedFlowPath);
     }
 
@@ -1883,29 +2387,48 @@
      */
     @Override
     public boolean measurementInstallPaths(Integer numThreads) {
-	List<Thread> threads = new LinkedList<Thread>();
+	// Create a copy of the Flow Paths to install
+	final ConcurrentLinkedQueue<FlowPath> measurementProcessingPaths =
+	    new ConcurrentLinkedQueue<FlowPath>(measurementStoredPaths);
 
-	// Create a copy of the paths to install
-	measurementProcessingPaths = new LinkedList<FlowPath>(measurementStoredPaths);
+	/**
+	 * A Thread-wrapper class for executing the threads and collecting
+	 * the measurement data.
+	 */
+	class MyThread extends Thread {
+	    public long[] execTime = new long[2000];
+	    public int samples = 0;
+	    public int threadId = -1;
+	    @Override
+	    public void run() {
+		while (true) {
+		    FlowPath flowPath = measurementProcessingPaths.poll();
+		    if (flowPath == null)
+			return;
+		    // Install the Flow Path
+		    FlowId flowId = new FlowId();
+		    String dataPathSummaryStr =
+			flowPath.dataPath().dataPathSummary();
+		    long startTime = System.nanoTime();
+		    addFlow(flowPath, flowId, dataPathSummaryStr);
+		    long endTime = System.nanoTime();
+		    execTime[samples] = endTime - startTime;
+		    samples++;
+		}
+	    }
+	};
+
+	List<MyThread> threads = new LinkedList<MyThread>();
+
+	log.debug("Measurement Installing {} flows",
+		  measurementProcessingPaths.size());
 
 	//
 	// Create the threads to install the Flow Paths
 	//
 	for (int i = 0; i < numThreads; i++) {
-	    Thread thread = new Thread(new Runnable() {
-		@Override
-		public void run() {
-		    while (true) {
-			FlowPath flowPath = measurementPollFirstFlowPath();
-			if (flowPath == null)
-			    return;
-			// Install the Flow Path
-			FlowId flowId = new FlowId();
-			String dataPathSummaryStr =
-			    flowPath.dataPath().dataPathSummary();
-			addFlow(flowPath, flowId, dataPathSummaryStr);
-		    }
-		}}, "Measurement Add Flow Path");
+	    MyThread thread = new MyThread();
+	    thread.threadId = i;
 	    threads.add(thread);
 	}
 
@@ -1918,14 +2441,29 @@
 	    thread.start();
 	}
 
-	//
-	// Wait until the end of processing time
-	//
-	while (measurementEndTimeProcessingPaths == 0) {
+	// Wait for all threads to complete
+	for (Thread thread : threads) {
 	    try {
-		Thread.sleep(100);
+		thread.join();
 	    } catch (InterruptedException e) {
-		// Continue waiting
+		log.debug("Exception waiting for a thread to install a Flow Path: ", e);
+	    }
+	}
+
+	// Record the end of processing
+	measurementEndTimeProcessingPaths = System.nanoTime();
+
+	//
+	// Prepare the string with measurement data per each Flow Path
+	// installation.
+	// The string is multiple lines: one line per Flow Path installation:
+	//    ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+	//
+	measurementPerFlowStr = new String();
+	String eol = System.getProperty("line.separator");
+	for (MyThread thread : threads) {
+	    for (int i = 0; i < thread.samples; i++) {
+		measurementPerFlowStr += "ThreadAndTimePerFlow " + thread.threadId + " " + numThreads + " " + thread.execTime[i] + eol;
 	    }
 	}
 
@@ -1945,21 +2483,14 @@
     }
 
     /**
-     * Get a Flow Path that needs to be installed for measurement purpose.
+     * Get the measurement install time per Flow.
      *
-     * If there is no next Flow Path to install, the end time measurement
-     * is recorded.
-     *
-     * @return the next Flow Path to install if exists, otherwise null.
+     * @return a multi-line string with the following format per line:
+     * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
      */
-    private synchronized FlowPath measurementPollFirstFlowPath() {
-	FlowPath flowPath = measurementProcessingPaths.pollFirst();
-
-	// Record the end of processing, if the first call
-	if ((flowPath == null) && (measurementEndTimeProcessingPaths == 0))
-	    measurementEndTimeProcessingPaths = System.nanoTime();
-
-	return flowPath;
+    @Override
+    public String measurementGetPerFlowInstallTime() {
+	return new String(measurementPerFlowStr);
     }
 
     /**
@@ -1970,11 +2501,11 @@
     @Override
     public boolean measurementClearAllPaths() {
 	measurementStoredPaths.clear();
-	topoRouteService.dropShortestPathTopo();
+	topoRouteService.dropShortestPathTopo(measurementShortestPathTopo);
 	measurementStartTimeProcessingPaths = 0;
 	measurementEndTimeProcessingPaths = 0;
+	measurementPerFlowStr = new String();
 
 	return true;
     }
-
 }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
similarity index 88%
rename from src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
index 5e0db35..ba9cd1b 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/IFlowService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/IFlowService.java
@@ -1,13 +1,13 @@
-package net.floodlightcontroller.flowcache;
+package net.onrc.onos.ofcontroller.flowmanager;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
 import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.util.CallerId;
-import net.floodlightcontroller.util.DataPathEndpoints;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.util.CallerId;
+import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 /**
  * @short Interface for providing Flow Service to other modules.
@@ -145,6 +145,14 @@
     public Long measurementGetInstallPathsTimeNsec();
 
     /**
+     * Get the measurement install time per Flow.
+     *
+     * @return a multi-line string with the following format per line:
+     * ThreadAndTimePerFlow <ThreadId> <TotalThreads> <Time(ns)>
+     */
+    public String measurementGetPerFlowInstallTime();
+
+    /**
      * Clear the path flows stored for measurement purpose.
      *
      * @return true on success, otherwise false.
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
index e266e2e..2800305 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/AddFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddFlowResource.java
@@ -1,15 +1,14 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.io.IOException;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 import org.codehaus.jackson.JsonGenerationException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.JsonMappingException;
-import org.codehaus.jackson.map.ObjectMapper;
 import org.restlet.resource.Post;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/AddShortestPathFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
similarity index 84%
rename from src/main/java/net/floodlightcontroller/flowcache/web/AddShortestPathFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
index 3c5bcd8..2a75c6a 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/AddShortestPathFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/AddShortestPathFlowResource.java
@@ -1,13 +1,12 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.io.IOException;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.restlet.resource.Post;
@@ -54,10 +53,11 @@
 	if (flowPath != null) {
 	    FlowPath addedFlowPath =
 		flowService.addAndMaintainShortestPathFlow(flowPath);
-	    if (addedFlowPath == null)
+	    if (addedFlowPath == null) {
 		result = new FlowId();		// Error: Return empty Flow Id
-	    else
+	    } else {
 		result = addedFlowPath.flowId();
+	    }
 	}
 
         return result;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/ClearFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/ClearFlowResource.java
similarity index 84%
rename from src/main/java/net/floodlightcontroller/flowcache/web/ClearFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/ClearFlowResource.java
index 7f3b589..1daa2ab 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/ClearFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/ClearFlowResource.java
@@ -1,9 +1,8 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
 
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/DatapathSummarySerializer.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DatapathSummarySerializer.java
similarity index 97%
rename from src/main/java/net/floodlightcontroller/flowcache/web/DatapathSummarySerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DatapathSummarySerializer.java
index b780e5c..9133077 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/DatapathSummarySerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DatapathSummarySerializer.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.io.IOException;
 
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java
similarity index 84%
rename from src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java
index ed6f0f7..393ff44 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/DeleteFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/DeleteFlowResource.java
@@ -1,9 +1,8 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
 
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
similarity index 90%
rename from src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
index 9fa5e63..954c84d 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/FlowWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/FlowWebRoutable.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import net.floodlightcontroller.restserver.RestletRoutable;
 
@@ -25,6 +25,7 @@
         router.attach("/measurement-store-path/json", MeasurementStorePathFlowResource.class);
         router.attach("/measurement-install-paths/{num-threads}/json", MeasurementInstallPathsFlowResource.class);
         router.attach("/measurement-get-install-paths-time-nsec/json", MeasurementGetInstallPathsTimeNsecFlowResource.class);
+        router.attach("/measurement-get-per-flow-install-time/json", MeasurementGetPerFlowInstallTimeFlowResource.class);
         router.attach("/measurement-clear-all-paths/json", MeasurementClearAllPathsFlowResource.class);
         return router;
     }
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java
similarity index 81%
rename from src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java
index 34d79c8..6142096 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByEndpointsResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByEndpointsResource.java
@@ -1,13 +1,13 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.DataPathEndpoints;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowPath;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByInstallerIdResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java
similarity index 81%
rename from src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByInstallerIdResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java
index e3043dc..498108f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsByInstallerIdResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsByInstallerIdResource.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.CallerId;
-import net.floodlightcontroller.util.DataPathEndpoints;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowPath;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.CallerId;
+import net.onrc.onos.ofcontroller.util.DataPathEndpoints;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java
similarity index 83%
rename from src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java
index 92317cf..61eaf27 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetAllFlowsResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetAllFlowsResource.java
@@ -1,9 +1,9 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java
similarity index 80%
rename from src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java
index 85d5b7e..48e7369 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetFlowByIdResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetFlowByIdResource.java
@@ -1,8 +1,8 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/GetSummaryFlowsResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java
similarity index 81%
rename from src/main/java/net/floodlightcontroller/flowcache/web/GetSummaryFlowsResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java
index 5f63222..4b3c00f 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/GetSummaryFlowsResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/GetSummaryFlowsResource.java
@@ -1,11 +1,10 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementClearAllPathsFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementClearAllPathsFlowResource.java
similarity index 81%
rename from src/main/java/net/floodlightcontroller/flowcache/web/MeasurementClearAllPathsFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementClearAllPathsFlowResource.java
index f69180d..07d9fb2 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementClearAllPathsFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementClearAllPathsFlowResource.java
@@ -1,9 +1,7 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetInstallPathsTimeNsecFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetInstallPathsTimeNsecFlowResource.java
similarity index 82%
rename from src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetInstallPathsTimeNsecFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetInstallPathsTimeNsecFlowResource.java
index 3dc1d08..467afca 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementGetInstallPathsTimeNsecFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetInstallPathsTimeNsecFlowResource.java
@@ -1,9 +1,7 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetPerFlowInstallTimeFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetPerFlowInstallTimeFlowResource.java
new file mode 100644
index 0000000..92d84ab
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementGetPerFlowInstallTimeFlowResource.java
@@ -0,0 +1,35 @@
+package net.onrc.onos.ofcontroller.flowmanager.web;
+
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MeasurementGetPerFlowInstallTimeFlowResource extends ServerResource {
+    protected static Logger log = LoggerFactory.getLogger(MeasurementGetPerFlowInstallTimeFlowResource.class);
+
+    @Get("json")
+    public String retrieve() {
+	String result = null;
+
+        IFlowService flowService =
+                (IFlowService)getContext().getAttributes().
+                get(IFlowService.class.getCanonicalName());
+
+        if (flowService == null) {
+	    log.debug("ONOS Flow Service not found");
+	    return result;
+	}
+
+	// Extract the arguments
+
+	// Process the request
+	result = flowService.measurementGetPerFlowInstallTime();
+
+	log.debug("Measurement Get Install Paths Time (nsec): " + result);
+
+	return result;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementInstallPathsFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementInstallPathsFlowResource.java
similarity index 83%
rename from src/main/java/net/floodlightcontroller/flowcache/web/MeasurementInstallPathsFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementInstallPathsFlowResource.java
index 1bba4b1..074dfb4 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementInstallPathsFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementInstallPathsFlowResource.java
@@ -1,9 +1,7 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
 
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
diff --git a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementStorePathFlowResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementStorePathFlowResource.java
similarity index 86%
rename from src/main/java/net/floodlightcontroller/flowcache/web/MeasurementStorePathFlowResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementStorePathFlowResource.java
index e68ceb7..0f23663 100644
--- a/src/main/java/net/floodlightcontroller/flowcache/web/MeasurementStorePathFlowResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowmanager/web/MeasurementStorePathFlowResource.java
@@ -1,13 +1,12 @@
-package net.floodlightcontroller.flowcache.web;
+package net.onrc.onos.ofcontroller.flowmanager.web;
 
 import java.io.IOException;
 
-import net.floodlightcontroller.flowcache.IFlowService;
-import net.floodlightcontroller.util.FlowId;
-import net.floodlightcontroller.util.FlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
 
 import org.codehaus.jackson.JsonGenerationException;
-import org.codehaus.jackson.map.ObjectMapper;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.restlet.resource.Post;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscovery.java
similarity index 96%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscovery.java
index 1efe015..6113ea8 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscovery.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscovery.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery;
+package net.onrc.onos.ofcontroller.linkdiscovery;
 
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.codehaus.jackson.map.ser.std.ToStringSerializer;
@@ -8,6 +8,7 @@
 
     @JsonSerialize(using=ToStringSerializer.class)
     public enum UpdateOperation {
+    	LINK_ADDED("Link Added"), // Operation Added by ONOS
         LINK_UPDATED("Link Updated"),
         LINK_REMOVED("Link Removed"),
         SWITCH_UPDATED("Switch Updated"),
@@ -106,6 +107,7 @@
         @Override
         public String toString() {
             switch (operation) {
+            case LINK_ADDED:
             case LINK_REMOVED:
             case LINK_UPDATED:
                 return "LDUpdate [operation=" + operation +
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryListener.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryListener.java
similarity index 94%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryListener.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryListener.java
index 35779a2..9ca114f 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryListener.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryListener.java
@@ -15,7 +15,7 @@
  *    under the License.
  **/
 
-package net.floodlightcontroller.linkdiscovery;
+package net.onrc.onos.ofcontroller.linkdiscovery;
 
 public interface ILinkDiscoveryListener extends ILinkDiscovery{
 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryService.java
similarity index 97%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryService.java
index 4145592..99438ab 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/ILinkDiscoveryService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/ILinkDiscoveryService.java
@@ -15,7 +15,7 @@
 *    under the License.
 **/
 
-package net.floodlightcontroller.linkdiscovery;
+package net.onrc.onos.ofcontroller.linkdiscovery;
 
 import java.util.Map;
 import java.util.Set;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/LinkInfo.java
similarity index 97%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/LinkInfo.java
index 9c0dd1a..825b0a2 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/LinkInfo.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/LinkInfo.java
@@ -13,9 +13,9 @@
 *    under the License.
 **/
 
-package net.floodlightcontroller.linkdiscovery;
+package net.onrc.onos.ofcontroller.linkdiscovery;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LinkType;
 
 import org.openflow.protocol.OFPhysicalPort.OFPortState;
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/README b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/README
new file mode 100644
index 0000000..3cec58d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/README
@@ -0,0 +1,8 @@
+Note about this directory
+=========================
+
+This directory contains link discovery manager and it's related module derived from Flood Light v0.9.0.
+Many of the code is unmodified from it's original state, but they had to be moved due to package visibility etc.
+
+Compare with floodlight's linkdiscovery directory to see what was modified from it's original code.
+
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java
index d57e987..696c63e 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyCluster.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.linkdiscovery.internal;
 
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java
similarity index 96%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java
index 98796ed..5d2e955 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologyLink.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.linkdiscovery.internal;
 
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java
similarity index 94%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java
index 001942b..d6afd7a 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/EventHistoryTopologySwitch.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.linkdiscovery.internal;
 
 import net.floodlightcontroller.core.web.serializers.DPIDSerializer;
 import net.floodlightcontroller.core.web.serializers.IPv4Serializer;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index 634f7eb..f4e4223 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -15,7 +15,7 @@
  *    under the License.
  **/
 
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.linkdiscovery.internal;
 
 import java.io.IOException;
 import java.net.InetAddress;
@@ -44,7 +44,6 @@
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IInfoProvider;
-import net.floodlightcontroller.core.INetMapStorage.DM_OPERATION;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchListener;
@@ -57,15 +56,6 @@
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.SwitchType;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.UpdateOperation;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.LinkInfo;
-import net.floodlightcontroller.linkdiscovery.web.LinkDiscoveryWebRoutable;
 import net.floodlightcontroller.packet.BSN;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
@@ -82,6 +72,16 @@
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.util.EventHistory;
 import net.floodlightcontroller.util.EventHistory.EvAction;
+import net.onrc.onos.ofcontroller.core.IOnosRemoteSwitch;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LDUpdate;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LinkType;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.SwitchType;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.UpdateOperation;
+import net.onrc.onos.ofcontroller.linkdiscovery.web.LinkDiscoveryWebRoutable;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
 
 import org.openflow.protocol.OFMessage;
@@ -127,12 +127,6 @@
 IStorageSourceListener, ILinkDiscoveryService,
 IFloodlightModule, IInfoProvider, IHAListener {
     protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManager.class);
-    
-    protected enum NetworkMapOperation {
-    	NONE,
-    	INSERT,
-    	UPDATE
-    }
 
     // Names of table/fields for links in the storage API
     private static final String LINK_TABLE_NAME = "controller_link";
@@ -152,8 +146,10 @@
     protected IStorageSourceService storageSource;
     protected IThreadPoolService threadPool;
     protected IRestApiService restApi;
+    // Registry Service for ONOS
     protected IControllerRegistryService registryService;
 
+
     // LLDP and BDDP fields
     private static final byte[] LLDP_STANDARD_DST_MAC_STRING = 
             HexString.fromHexString("01:80:c2:00:00:0e");
@@ -161,8 +157,8 @@
     private static final long LINK_LOCAL_VALUE = 0x0180c2000000L;
 
     // BigSwitch OUI is 5C:16:C7, so 5D:16:C7 is the multicast version
-    private static final String LLDP_BSN_DST_MAC_STRING = "5d:16:c7:00:00:01";
-    //private static final String LLDP_BSN_DST_MAC_STRING = "ff:ff:ff:ff:ff:ff";
+    // private static final String LLDP_BSN_DST_MAC_STRING = "5d:16:c7:00:00:01";
+    private static final String LLDP_BSN_DST_MAC_STRING = "ff:ff:ff:ff:ff:ff";
 
 
     // Direction TLVs are used to indicate if the LLDPs were sent 
@@ -198,20 +194,6 @@
     protected ReentrantReadWriteLock lock;
     int lldpTimeCount = 0;
 
-    // Storage
-
-    ThreadLocal<LinkStorageImpl> store = new ThreadLocal<LinkStorageImpl>() {
-		@Override
-		protected LinkStorageImpl initialValue() {
-			LinkStorageImpl swStore = new LinkStorageImpl();
-			//TODO: Get the file path from global properties
-			swStore.init("/tmp/cassandra.titan");
-			return swStore;
-		}
-	};
-    protected LinkStorageImpl linkStore = store.get();
-   // protected SwitchStorageImpl swStore;
-    
     /**
      * Flag to indicate if automatic port fast is enabled or not.
      * Default is set to false -- Initialized in the init method as well.
@@ -220,10 +202,10 @@
 
     /**
      * Map of remote switches that are not connected to this controller. This
-     * is used to learn remote switches in a distributed controller.
+     * is used to learn remote switches in a distributed controller ONOS.
      */
-    protected Map<Long, IOFSwitch> remoteSwitches;
-    
+    protected Map<Long, IOnosRemoteSwitch> remoteSwitches;
+
     /**
      * Map from link to the most recent time it was verified functioning
      */
@@ -534,10 +516,10 @@
     }
 
     /**
-     * Learn remote switches when running as a distributed controller
+     * Learn remote switches when running as a distributed controller ONOS
      */
     protected IOFSwitch addRemoteSwitch(long sw, short port) {
-    	IOFSwitch remotesw = null;
+    	IOnosRemoteSwitch remotesw = null;
     	
     	// add a switch if we have not seen it before
     	remotesw = remoteSwitches.get(sw);
@@ -825,6 +807,7 @@
                 ByteBuffer dpidBB = ByteBuffer.wrap(lldptlv.getValue());
                 remoteSwitch = floodlightProvider.getSwitches().get(dpidBB.getLong(4));
                 if (remoteSwitch == null) {
+                	// Added by ONOS
                 	// floodlight LLDP coming from a remote switch connected to a different controller
                 	// add it to our cache of unconnected remote switches
                 	remoteSwitch = addRemoteSwitch(dpidBB.getLong(4), remotePort);
@@ -857,7 +840,7 @@
                     log.trace("Getting BDDP packets from a different controller" +
                             "and letting it go through normal processing chain.");
                 }
-                //XXX Fix the BDDP broadcast issue
+                //XXX ONOS: Fix the BDDP broadcast issue
                 //return Command.CONTINUE;
                 return Command.STOP;
             }
@@ -978,7 +961,6 @@
             if (bsn.getPayload() instanceof LLDP == false)
                 return Command.CONTINUE;
             return handleLldp((LLDP) bsn.getPayload(), sw, pi, false, cntx);
-            //return Command.STOP;
         } else if (eth.getEtherType() == Ethernet.TYPE_LLDP)  {
             return handleLldp((LLDP) eth.getPayload(), sw, pi, true, cntx);
         } else if (eth.getEtherType() < 1500) {
@@ -1028,7 +1010,6 @@
 
         NodePortTuple srcNpt, dstNpt;
         boolean linkChanged = false;
-        NetworkMapOperation operation = NetworkMapOperation.NONE;
 
         lock.writeLock().lock();
         try {
@@ -1076,11 +1057,8 @@
 
                 writeLinkToStorage(lt, newInfo);
                 
-                // Write link to network map
-                operation = NetworkMapOperation.INSERT;
-                //linkStore.update(lt, newInfo, DM_OPERATION.INSERT);
-                
-                updateOperation = UpdateOperation.LINK_UPDATED;
+                // ONOS: Distinguish added event separately from updated event
+                updateOperation = UpdateOperation.LINK_ADDED;
                 linkChanged = true;
 
                 // Add to event history
@@ -1136,10 +1114,6 @@
                 // they weren't set to null in the previous block of code.
                 writeLinkToStorage(lt, newInfo);
 
-                // Write link to network map
-                operation = NetworkMapOperation.UPDATE;
-                //linkStore.update(lt, newInfo, DM_OPERATION.UPDATE);
-                
                 if (linkChanged) {
                     updateOperation = getUpdateOperation(newInfo.getSrcPortState(),
                                                          newInfo.getDstPortState());
@@ -1168,18 +1142,6 @@
         } finally {
             lock.writeLock().unlock();
         }
-        
-        switch (operation){
-        case INSERT:
-        	linkStore.update(lt, newInfo, DM_OPERATION.INSERT);
-        	break;
-        case UPDATE:
-        	linkStore.update(lt, newInfo, DM_OPERATION.UPDATE);
-        	break;
-        case NONE:
-        default:
-        	break;
-        }
 
         return linkChanged;
     }
@@ -1193,14 +1155,6 @@
      * @param links The List of @LinkTuple to delete.
      */
     protected void deleteLinks(List<Link> links, String reason) {
-    	deleteLinks(links, reason, Boolean.TRUE);
-    }
-    
-    /**
-     * Removes links from memory and storage.
-     * @param links The List of @LinkTuple to delete.
-     */
-    protected void deleteLinks(List<Link> links, String reason, Boolean hasControl) {
         NodePortTuple srcNpt, dstNpt;
 
         lock.writeLock().lock();
@@ -1247,10 +1201,6 @@
                 // remove link from storage.
                 removeLinkFromStorage(lt);
 
-                // remote link from network map
-                linkStore.update(lt, DM_OPERATION.DELETE);
-
-                
                 // TODO  Whenever link is removed, it has to checked if
                 // the switchports must be added to quarantine.
 
@@ -1274,8 +1224,8 @@
 
         IOFSwitch iofSwitch = floodlightProvider.getSwitches().get(sw);
         if (iofSwitch == null) return Command.CONTINUE;
-        
-        // If we do not control this switch, then we should not process its port status messages
+
+        // ONOS: If we do not control this switch, then we should not process its port status messages
         if (!registryService.hasControl(iofSwitch.getId())) return Command.CONTINUE;
         
         if (log.isTraceEnabled()) {
@@ -1301,7 +1251,6 @@
                     ((byte)OFPortReason.OFPPR_MODIFY.ordinal() ==
                     ps.getReason() && !portEnabled(ps.getDesc()))) {
                 deleteLinksOnPort(npt, "Port Status Changed");
-                //swStore.deletePort(HexString.toHexString(npt.getNodeId()), npt.getPortId());
                 LDUpdate update = new LDUpdate(sw, port, UpdateOperation.PORT_DOWN);
                 updates.add(update);
                 linkDeleted = true;
@@ -1344,10 +1293,6 @@
                                                      getLinkType(lt, linkInfo),
                                                      operation));
                             writeLinkToStorage(lt, linkInfo);
-                            
-                            // Write the changed link to the network map
-                            linkStore.update(lt,  linkInfo, DM_OPERATION.UPDATE);
-                            
                             linkInfoChanged = true;
                         }
                     }
@@ -1451,11 +1396,7 @@
                 }
                 // add all tuples with an endpoint on this switch to erase list
                 eraseList.addAll(switchLinks.get(sw));
-                
-                // We can get called to delete links when we lose mastership. To avoid clearing the network map in that case,
-                // figure out if we have control of the switch
-                boolean hasControl = registryService.hasControl(sw);
-                deleteLinks(eraseList, "Switch Removed", hasControl);
+                deleteLinks(eraseList, "Switch Removed");
 
                 // Send a switch removed update
                 LDUpdate update = new LDUpdate(sw, null, UpdateOperation.SWITCH_REMOVED);
@@ -1885,6 +1826,7 @@
         l.add(IStorageSourceService.class);
         l.add(IThreadPoolService.class);
         l.add(IRestApiService.class);
+        // Added by ONOS
         l.add(IControllerRegistryService.class);
         return l;
     }
@@ -1896,6 +1838,7 @@
         storageSource = context.getServiceImpl(IStorageSourceService.class);
         threadPool = context.getServiceImpl(IThreadPoolService.class);
         restApi = context.getServiceImpl(IRestApiService.class);
+        // Added by ONOS
         registryService = context.getServiceImpl(IControllerRegistryService.class);
 
         // Set the autoportfast feature to false.
@@ -1913,7 +1856,8 @@
         this.switchLinks = new HashMap<Long, Set<Link>>();
         this.quarantineQueue = new LinkedBlockingQueue<NodePortTuple>();
         this.maintenanceQueue = new LinkedBlockingQueue<NodePortTuple>();
-        this.remoteSwitches = new HashMap<Long, IOFSwitch>();
+        // Added by ONOS
+        this.remoteSwitches = new HashMap<Long, IOnosRemoteSwitch>();
 
         this.evHistTopologySwitch =
                 new EventHistory<EventHistoryTopologySwitch>("Topology: Switch");
@@ -1964,7 +1908,7 @@
             log.error("Error in installing listener for " +
             		  "switch table {}", SWITCH_CONFIG_TABLE_NAME);
         }
-                
+
         ScheduledExecutorService ses = threadPool.getScheduledExecutor();
 
         // To be started by the first switch connection
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/web/AutoPortFast.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/AutoPortFast.java
similarity index 89%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/web/AutoPortFast.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/AutoPortFast.java
index 8f4f4ad..29dc890 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/web/AutoPortFast.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/AutoPortFast.java
@@ -1,6 +1,6 @@
-package net.floodlightcontroller.linkdiscovery.web;
+package net.onrc.onos.ofcontroller.linkdiscovery.web;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
 
 import org.restlet.data.Status;
 import org.restlet.resource.Get;
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java
similarity index 92%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java
index 3990fba..8eae558 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkDiscoveryWebRoutable.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery.web;
+package net.onrc.onos.ofcontroller.linkdiscovery.web;
 
 import net.floodlightcontroller.restserver.RestletRoutable;
 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkWithType.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkWithType.java
similarity index 94%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkWithType.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkWithType.java
index 893e4ad..3e5a5e7 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinkWithType.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinkWithType.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.linkdiscovery.web;
+package net.onrc.onos.ofcontroller.linkdiscovery.web;
 
 import java.io.IOException;
 
@@ -9,8 +9,8 @@
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.openflow.util.HexString;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery.LinkType;
 import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery.LinkType;
 
 /**
  * This class is both the datastructure and the serializer
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinksResource.java b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinksResource.java
similarity index 86%
rename from src/main/java/net/floodlightcontroller/linkdiscovery/web/LinksResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinksResource.java
index 4cad18e..c522a05 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/web/LinksResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/linkdiscovery/web/LinksResource.java
@@ -1,13 +1,13 @@
-package net.floodlightcontroller.linkdiscovery.web;
+package net.onrc.onos.ofcontroller.linkdiscovery.web;
 
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.LinkInfo;
 import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
 
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java
new file mode 100644
index 0000000..5830cfd
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ArpTableEntry.java
@@ -0,0 +1,27 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+
+public class ArpTableEntry {
+	
+	private byte[] macAddress;
+	private long timeLastSeen;	
+
+	public ArpTableEntry(byte[] macAddress, long timeLastSeen) {
+		this.macAddress = macAddress;
+		this.timeLastSeen = timeLastSeen;
+	}
+
+	public byte[] getMacAddress() {
+		return macAddress;
+	}
+
+	public long getTimeLastSeen() {
+		return timeLastSeen;
+	}
+	
+	public void setTimeLastSeen(long time){
+		//TODO thread safety issues?
+		timeLastSeen = time;
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
new file mode 100644
index 0000000..20c6a28
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/HostArpRequester.java
@@ -0,0 +1,28 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import net.floodlightcontroller.packet.ARP;
+
+public class HostArpRequester implements IArpRequester {
+
+	private IProxyArpService arpService;
+	private ARP arpRequest;
+	private long dpid;
+	private short port;
+	//private long requestTime; //in ms
+	
+	public HostArpRequester(IProxyArpService arpService, ARP arpRequest, 
+			long dpid, short port) {
+		
+		this.arpService = arpService;
+		this.arpRequest = arpRequest;
+		this.dpid = dpid;
+		this.port = port;
+		//this.requestTime = System.currentTimeMillis();
+	}
+
+	@Override
+	public void arpResponse(byte[] mac) {
+		arpService.sendArpReply(arpRequest, dpid, port, mac);
+	}
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
new file mode 100644
index 0000000..2a74944
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IArpRequester.java
@@ -0,0 +1,5 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+public interface IArpRequester {
+	public void arpResponse(byte[] mac);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
new file mode 100644
index 0000000..4632aba
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/IProxyArpService.java
@@ -0,0 +1,41 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import java.net.InetAddress;
+
+import net.floodlightcontroller.packet.ARP;
+
+public interface IProxyArpService {
+	
+	public final int ARP_REQUEST_TIMEOUT = 2000; //ms
+	
+	/**
+	 * Tell the IProxyArpService to send an ARP reply with the targetMac to 
+	 * the host on the specified switchport.
+	 * @param arpRequest
+	 * @param dpid
+	 * @param port
+	 * @param targetMac
+	 */
+	public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac);
+	
+	/**
+	 * Returns the mac address if there is a valid entry in the cache.
+	 * Otherwise returns null.
+	 * @param ipAddress
+	 * @return
+	 */
+	public byte[] getMacAddress(InetAddress ipAddress);
+	
+	/**
+	 * Tell the IProxyArpService to send an ARP request for the IP address.
+	 * The request will be broadcast out all edge ports in the network.
+	 * As an optimization, the IProxyArpService will first check its cache and
+	 * return the MAC address if it is already known. If not, the request will be
+	 * sent and the callback will be called when the MAC address is known
+	 * (or if the request times out). 
+	 * @param ipAddress
+	 * @param requester
+	 * @return
+	 */
+	public byte[] sendArpRequest(InetAddress ipAddress, IArpRequester requester);
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
new file mode 100644
index 0000000..5c2a2b9
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/proxyarp/ProxyArpManager.java
@@ -0,0 +1,453 @@
+package net.onrc.onos.ofcontroller.proxyarp;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
+
+import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.devicemanager.IDeviceService;
+import net.floodlightcontroller.packet.ARP;
+import net.floodlightcontroller.packet.Ethernet;
+import net.floodlightcontroller.topology.ITopologyService;
+import net.floodlightcontroller.util.MACAddress;
+
+import org.openflow.protocol.OFMessage;
+import org.openflow.protocol.OFPacketIn;
+import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.action.OFAction;
+import org.openflow.protocol.action.OFActionOutput;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProxyArpManager implements IProxyArpService, IOFMessageListener {
+	private static Logger log = LoggerFactory.getLogger(ProxyArpManager.class);
+	
+	private final long ARP_ENTRY_TIMEOUT = 600000; //ms (== 10 mins)
+	
+	private final long ARP_REQUEST_TIMEOUT_THREAD_PERIOD = 60000; //ms (== 1 min) 
+			
+	protected IFloodlightProviderService floodlightProvider;
+	protected ITopologyService topology;
+	protected IDeviceService devices;
+	
+	protected Map<InetAddress, ArpTableEntry> arpTable;
+	
+	//protected ConcurrentHashMap<InetAddress, Set<ArpRequest>> arpRequests;
+	protected ConcurrentHashMap<InetAddress, ArpRequest> arpRequests;
+	
+	private class ArpRequest {
+		private Set<IArpRequester> requesters;
+		private long requestTime;
+		
+		public ArpRequest(){
+			this.requesters = new HashSet<IArpRequester>();
+			this.requestTime = System.currentTimeMillis();
+		}
+		
+		public synchronized void addRequester(IArpRequester requester){
+			requestTime = System.currentTimeMillis();
+			requesters.add(requester);
+		}
+		
+		public boolean isExpired(){
+			return (System.currentTimeMillis() - requestTime) 
+					> IProxyArpService.ARP_REQUEST_TIMEOUT;
+		}
+		
+		public synchronized void dispatchReply(byte[] replyMacAddress){
+			for (IArpRequester requester : requesters){
+				requester.arpResponse(replyMacAddress);
+			}
+		}
+	}
+	
+	public ProxyArpManager(IFloodlightProviderService floodlightProvider,
+				ITopologyService topology, IDeviceService devices){
+		this.floodlightProvider = floodlightProvider;
+		this.topology = topology;
+		this.devices = devices;
+		
+		arpTable = new HashMap<InetAddress, ArpTableEntry>();
+		//arpRequests = new ConcurrentHashMap<InetAddress, Set<ArpRequest>>();
+		arpRequests = new ConcurrentHashMap<InetAddress, ArpRequest>();
+		
+		Timer arpRequestTimeoutTimer = new Timer();
+		arpRequestTimeoutTimer.scheduleAtFixedRate(new TimerTask() {
+			@Override
+			public void run() {
+				synchronized (arpRequests) {
+					log.debug("Current have {} outstanding requests", 
+							arpRequests.size());
+					
+					Iterator<Map.Entry<InetAddress, ArpRequest>> it 
+							= arpRequests.entrySet().iterator();
+					
+					while (it.hasNext()){
+						Map.Entry<InetAddress, ArpRequest> entry
+								= it.next();
+						
+						if (entry.getValue().isExpired()){
+							log.debug("Cleaning expired ARP request for {}", 
+									entry.getKey().getHostAddress());
+							it.remove();
+						}
+					}
+				}
+			}
+		}, 0, ARP_REQUEST_TIMEOUT_THREAD_PERIOD);
+	}
+	
+	private void storeRequester(InetAddress address, IArpRequester requester) {
+		synchronized (arpRequests) {
+			if (arpRequests.get(address) == null) {
+				arpRequests.put(address, new ArpRequest());
+			}
+			ArpRequest request = arpRequests.get(address);
+							
+			request.addRequester(requester);
+		}
+	}
+	
+	@Override
+	public String getName() {
+		return "ProxyArpManager";
+	}
+
+	@Override
+	public boolean isCallbackOrderingPrereq(OFType type, String name) {
+		return false;
+	}
+
+	@Override
+	public boolean isCallbackOrderingPostreq(OFType type, String name) {
+		return false;
+	}
+
+	@Override
+	public Command receive(
+			IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
+		
+		if (msg.getType() != OFType.PACKET_IN){
+			return Command.CONTINUE;
+		}
+		
+		OFPacketIn pi = (OFPacketIn) msg;
+		
+		Ethernet eth = IFloodlightProviderService.bcStore.get(cntx, 
+                IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+		
+		if (eth.getEtherType() == Ethernet.TYPE_ARP){
+			ARP arp = (ARP) eth.getPayload();
+			
+			if (arp.getOpCode() == ARP.OP_REQUEST) {
+				handleArpRequest(sw, pi, arp);
+			}
+			else if (arp.getOpCode() == ARP.OP_REPLY) {
+				handleArpReply(sw, pi, arp);
+			}
+		}
+		
+		//TODO should we propagate ARP or swallow it?
+		//Always propagate for now so DeviceManager can learn the host location
+		return Command.CONTINUE;
+	}
+	
+	protected void handleArpRequest(IOFSwitch sw, OFPacketIn pi, ARP arp) {
+		log.debug("ARP request received for {}", 
+				bytesToStringAddr(arp.getTargetProtocolAddress()));
+		
+		byte[] mac = lookupArpTable(arp.getTargetProtocolAddress());
+		
+		if (mac == null){
+			//Mac address is not in our arp table.
+			
+			//TODO check what the DeviceManager thinks
+			
+			//Record where the request came from so we know where to send the reply
+			InetAddress target;
+			try {
+				 target = InetAddress.getByAddress(arp.getTargetProtocolAddress());
+			} catch (UnknownHostException e) {
+				log.debug("Invalid address in ARP request", e);
+				//return Command.CONTINUE; //Continue or stop?
+				return;
+			}
+			
+			storeRequester(target, new HostArpRequester(this, arp, sw.getId(), 
+					pi.getInPort()));
+			
+			//Flood the request out edge ports
+			broadcastArpRequestOutEdge(pi.getPacketData(), sw.getId(), pi.getInPort());
+		}
+		else {
+			//We know the address, so send a reply
+			log.debug("Sending reply of {}", MACAddress.valueOf(mac).toString());
+			//sendArpReply(arp, pi, mac, sw);
+			sendArpReply(arp, sw.getId(), pi.getInPort(), mac);
+		}
+	}
+	
+	protected void handleArpReply(IOFSwitch sw, OFPacketIn pi, ARP arp){
+		log.debug("ARP reply recieved for {}", 
+				bytesToStringAddr(arp.getSenderProtocolAddress()));
+		
+		updateArpTable(arp);
+		
+		//See if anyone's waiting for this ARP reply
+		InetAddress addr;
+		try {
+			addr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
+		} catch (UnknownHostException e) {
+			return;
+		}
+		
+		ArpRequest request = null;
+		synchronized (arpRequests) {
+			request = arpRequests.get(addr);
+			if (request != null) {
+				arpRequests.remove(addr);
+			}
+		}
+		if (request != null && !request.isExpired()) {
+			request.dispatchReply(arp.getSenderHardwareAddress());
+		}
+		
+		/*
+		Set<ArpRequest> requests = arpRequests.get(addr);
+		if (requests != null){
+			
+			synchronized (requests) {
+				for (ArpRequest request : requests) {
+					if (!request.isExpired()){
+						request.getRequester().arpResponse(
+								arp.getSenderHardwareAddress());
+					}
+				}
+			}
+		}*/
+	}
+
+	private synchronized byte[] lookupArpTable(byte[] ipAddress){
+		InetAddress addr;
+		try {
+			addr = InetAddress.getByAddress(ipAddress);
+		} catch (UnknownHostException e) {
+			log.warn("Unable to create InetAddress", e);
+			return null;
+		}
+		
+		ArpTableEntry arpEntry = arpTable.get(addr);
+		
+		if (arpEntry == null){
+			return null;
+		}
+		
+		if (System.currentTimeMillis() - arpEntry.getTimeLastSeen() 
+				> ARP_ENTRY_TIMEOUT){
+			//Entry has timed out so we'll remove it and return null
+			arpTable.remove(addr);
+			return null;
+		}
+		
+		return arpEntry.getMacAddress();
+	}
+	
+	private synchronized void updateArpTable(ARP arp){
+		InetAddress addr;
+		try {
+			addr = InetAddress.getByAddress(arp.getSenderProtocolAddress());
+		} catch (UnknownHostException e) {
+			log.warn("Unable to create InetAddress", e);
+			return;
+		}
+		
+		ArpTableEntry arpEntry = arpTable.get(addr);
+		
+		if (arpEntry != null 
+				&& arpEntry.getMacAddress() == arp.getSenderHardwareAddress()){
+			arpEntry.setTimeLastSeen(System.currentTimeMillis());
+		}
+		else {
+			arpTable.put(addr, 
+					new ArpTableEntry(arp.getSenderHardwareAddress(), 
+										System.currentTimeMillis()));
+		}
+	}
+	
+	private void sendArpRequestForAddress(InetAddress ipAddress) {
+		byte[] zeroIpv4 = {0x0, 0x0, 0x0, 0x0};
+		byte[] zeroMac = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+		byte[] broadcastMac = {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, 
+				(byte)0xff, (byte)0xff, (byte)0xff};
+		
+		ARP arpRequest = new ARP();
+		
+		arpRequest.setHardwareType(ARP.HW_TYPE_ETHERNET)
+			.setProtocolType(ARP.PROTO_TYPE_IP)
+			.setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
+			.setProtocolAddressLength((byte)4) //can't find the constant anywhere
+			.setOpCode(ARP.OP_REQUEST)
+			.setSenderHardwareAddress(zeroMac)
+			.setSenderProtocolAddress(zeroIpv4)
+			.setTargetHardwareAddress(zeroMac)
+			.setTargetProtocolAddress(ipAddress.getAddress());
+	
+		Ethernet eth = new Ethernet();
+		eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
+			.setSourceMACAddress(broadcastMac)
+			.setEtherType(Ethernet.TYPE_ARP)
+			.setPayload(arpRequest);
+		
+		broadcastArpRequestOutEdge(eth.serialize(), 0, OFPort.OFPP_NONE.getValue());
+	}
+	
+	//private void broadcastArpRequestOutEdge(OFPacketIn pi, long inSwitch, short inPort){
+	private void broadcastArpRequestOutEdge(byte[] arpRequest, long inSwitch, short inPort) {
+		for (IOFSwitch sw : floodlightProvider.getSwitches().values()){
+			Collection<Short> enabledPorts = sw.getEnabledPortNumbers();
+			Set<Short> linkPorts = topology.getPortsWithLinks(sw.getId());
+			
+			if (linkPorts == null){
+				//I think this means the switch isn't known to topology yet.
+				//Maybe it only just joined.
+				continue;
+			}
+			
+			OFPacketOut po = new OFPacketOut();
+			po.setInPort(OFPort.OFPP_NONE)
+				.setBufferId(-1)
+				.setPacketData(arpRequest);
+				
+			List<OFAction> actions = new ArrayList<OFAction>();
+			
+			for (short portNum : enabledPorts){
+				if (linkPorts.contains(portNum) || 
+						(sw.getId() == inSwitch && portNum == inPort)){
+					//If this port isn't an edge port or is the ingress port
+					//for the ARP, don't broadcast out it
+					continue;
+				}
+				
+				actions.add(new OFActionOutput(portNum));
+				log.debug("Broadcasting out {}/{}", HexString.toHexString(sw.getId()), portNum);
+			}
+			
+			po.setActions(actions);
+			short actionsLength = (short) (actions.size() * OFActionOutput.MINIMUM_LENGTH);
+			po.setActionsLength(actionsLength);
+			po.setLengthU(OFPacketOut.MINIMUM_LENGTH + actionsLength 
+					+ arpRequest.length);
+			
+			List<OFMessage> msgList = new ArrayList<OFMessage>();
+			msgList.add(po);
+			
+			try {
+				sw.write(msgList, null);
+				sw.flush();
+			} catch (IOException e) {
+				log.error("Failure writing packet out to switch", e);
+			}
+		}
+	}
+	
+	public void sendArpReply(ARP arpRequest, long dpid, short port, byte[] targetMac) {
+	//private void sendArpReply(ARP arpRequest, OFPacketIn pi, byte[] macRequested, IOFSwitch sw){
+		ARP arpReply = new ARP();
+		arpReply.setHardwareType(ARP.HW_TYPE_ETHERNET)
+			.setProtocolType(ARP.PROTO_TYPE_IP)
+			.setHardwareAddressLength((byte)Ethernet.DATALAYER_ADDRESS_LENGTH)
+			.setProtocolAddressLength((byte)4) //can't find the constant anywhere
+			.setOpCode(ARP.OP_REPLY)
+			//.setSenderHardwareAddress(macRequested)
+			.setSenderHardwareAddress(targetMac)
+			.setSenderProtocolAddress(arpRequest.getTargetProtocolAddress())
+			.setTargetHardwareAddress(arpRequest.getSenderHardwareAddress())
+			.setTargetProtocolAddress(arpRequest.getSenderProtocolAddress());
+		
+		Ethernet eth = new Ethernet();
+		eth.setDestinationMACAddress(arpRequest.getSenderHardwareAddress())
+			//.setSourceMACAddress(macRequested)
+			.setSourceMACAddress(targetMac)
+			.setEtherType(Ethernet.TYPE_ARP)
+			.setPayload(arpReply);
+		
+		List<OFAction> actions = new ArrayList<OFAction>();
+		//actions.add(new OFActionOutput(pi.getInPort()));
+		actions.add(new OFActionOutput(port));
+		
+		OFPacketOut po = new OFPacketOut();
+		po.setInPort(OFPort.OFPP_NONE)
+			.setBufferId(-1)
+			.setPacketData(eth.serialize())
+			.setActions(actions)
+			.setActionsLength((short)OFActionOutput.MINIMUM_LENGTH)
+			.setLengthU(OFPacketOut.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH
+					+ po.getPacketData().length);
+		
+		List<OFMessage> msgList = new ArrayList<OFMessage>();
+		msgList.add(po);
+
+		IOFSwitch sw = floodlightProvider.getSwitches().get(dpid);
+		
+		if (sw == null) {
+			return;
+		}
+		
+		try {
+			log.debug("Sending ARP reply to {}/{}", HexString.toHexString(sw.getId()), port);
+			sw.write(msgList, null);
+			sw.flush();
+		} catch (IOException e) {
+			log.warn("Failure writing packet out to switch", e);
+		}
+	}
+
+	//TODO this should be put somewhere more central. I use it in BgpRoute as well.
+	//We need a HexString.toHexString() equivalent.
+	private String bytesToStringAddr(byte[] bytes) {
+		InetAddress addr;
+		try {
+			addr = InetAddress.getByAddress(bytes);
+		} catch (UnknownHostException e) {
+			log.warn(" ", e);
+			return "";
+		}
+		if (addr == null) return "";
+		else return addr.getHostAddress();
+	}
+	
+	
+	public byte[] getMacAddress(InetAddress ipAddress) {
+		return lookupArpTable(ipAddress.getAddress());
+	}
+	
+	public byte[] sendArpRequest(InetAddress ipAddress, IArpRequester requester) {
+		byte[] lookupMac;
+		if ((lookupMac = lookupArpTable(ipAddress.getAddress())) == null) {
+			return lookupMac;
+		}
+		
+		sendArpRequestForAddress(ipAddress);
+		
+		storeRequester(ipAddress, requester);
+		
+		return null;
+	}
+}
diff --git a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java b/src/main/java/net/onrc/onos/ofcontroller/routing/TopoRouteService.java
similarity index 78%
rename from src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
rename to src/main/java/net/onrc/onos/ofcontroller/routing/TopoRouteService.java
index 95a3b19..59e76ca 100644
--- a/src/main/java/net/floodlightcontroller/routing/TopoRouteService.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/routing/TopoRouteService.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.routing;
+package net.onrc.onos.ofcontroller.routing;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -11,27 +11,21 @@
 import java.util.Queue;
 import java.util.Set;
 
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.module.IFloodlightService;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowEntry;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
-import net.onrc.onos.util.GraphDBConnection;
-import net.onrc.onos.util.GraphDBConnection.Transaction;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowEntry;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
 import org.openflow.util.HexString;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.tinkerpop.blueprints.Direction;
-import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
 import com.tinkerpop.blueprints.Vertex;
 import com.tinkerpop.pipes.PipeFunction;
 import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
@@ -42,6 +36,10 @@
  * of shortest paths.
  */
 class Node {
+    /**
+     * A class for storing Link information for fast computation of shortest
+     * paths.
+     */
     class Link {
 	public Node me;			// The node this link originates from
 	public Node neighbor;		// The neighbor node on the other side
@@ -92,83 +90,68 @@
     }
 };
 
-
-public class TopoRouteService implements IFloodlightModule, ITopoRouteService {
+/**
+ * A class for implementing Topology Route Service.
+ */
+public class TopoRouteService implements ITopoRouteService {
 
     /** The logger. */
     private static Logger log =
 	LoggerFactory.getLogger(TopoRouteService.class);
     
-    GraphDBConnection conn;
+    protected GraphDBOperation op;
 
-    //
-    // Topology state for storing (on demand) Switch and Ports info for
-    // fast access during the shortest path computation.
-    // It is explicitly populated by method @ref prepareShortestPathTopo().
-    // See the documentation for that method for details.
-    //
-    HashMap<Long, Node> shortestPathTopo;
 
-    @Override
-    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
-        Collection<Class<? extends IFloodlightService>> l = 
-            new ArrayList<Class<? extends IFloodlightService>>();
-        l.add(ITopoRouteService.class);
-        return l;
+    /**
+     * Default constructor.
+     */
+    public TopoRouteService() {
     }
 
-    @Override
-    public Map<Class<? extends IFloodlightService>, IFloodlightService> 
-			       getServiceImpls() {
-        Map<Class<? extends IFloodlightService>,
-        IFloodlightService> m = 
-            new HashMap<Class<? extends IFloodlightService>,
-                IFloodlightService>();
-        m.put(ITopoRouteService.class, this);
-        return m;
+    /**
+     * Constructor for given database configuration file.
+     *
+     * @param config the database configuration file to use for
+     * the initialization.
+     */
+    public TopoRouteService(String config) {
+	this.init(config);
     }
 
-    @Override
-    public Collection<Class<? extends IFloodlightService>> 
-                                                    getModuleDependencies() {
-	Collection<Class<? extends IFloodlightService>> l =
-	    new ArrayList<Class<? extends IFloodlightService>>();
-	// TODO: Add the appropriate dependencies
-	// l.add(IRestApiService.class);
-        return l;
-    }
-
-    @Override
-    public void init(FloodlightModuleContext context)
-	throws FloodlightModuleException {
-	// TODO: Add the appropriate initialization
-    	conn = GraphDBConnection.getInstance("");
-    }
-
-    @Override
-    public void startUp(FloodlightModuleContext context) {
-	// TODO: Add the approprate setup
-    }
-
-
-    static class ShortestPathLoopFunction implements PipeFunction<LoopBundle<Vertex>, Boolean> {
-	String dpid;
-	public ShortestPathLoopFunction(String dpid) {
-	    super();
-	    this.dpid = dpid;
-	}
-	public Boolean compute(LoopBundle<Vertex> bundle) {
-	    Boolean output = false;
-	    if (! bundle.getObject().getProperty("dpid").equals(dpid)) {
-		output = true;
-	    }
-	    return output;
+    /**
+     * Init the module.
+     *
+     * @param config the database configuration file to use for
+     * the initialization.
+     */
+    public void init(String config) {
+	try {
+	    op = new GraphDBOperation(config);
+	} catch (Exception e) {
+	    log.error(e.getMessage());
 	}
     }
 
     /**
+     * Close the service. It will close the corresponding database connection.
+     */
+    public void close() {
+	op.close();
+    }
+
+    /**
+     * Set the database operation handler.
+     *
+     * @param init_op the database operation handler to use for the
+     * initialization.
+     */
+    public void setDbOperationHandler(GraphDBOperation init_op) {
+    	op = init_op;
+    }
+
+    /**
      * Fetch the Switch and Ports info from the Titan Graph
-     * and store it locally for fast access during the shortest path
+     * and return it for fast access during the shortest path
      * computation.
      *
      * After fetching the state, method @ref getTopoShortestPath()
@@ -184,22 +167,24 @@
      * method @ref dropShortestPathTopo() should be used to release
      * the internal state that is not needed anymore:
      *
-     *       prepareShortestPathTopo();
+     *       Map<Long, ?> shortestPathTopo;
+     *       shortestPathTopo = prepareShortestPathTopo();
      *       for (int i = 0; i < 10000; i++) {
-     *           dataPath = getTopoShortestPath(...);
+     *           dataPath = getTopoShortestPath(shortestPathTopo, ...);
      *           ...
      *        }
-     *        dropShortestPathTopo();
+     *        dropShortestPathTopo(shortestPathTopo);
+     *
+     * @return the Shortest Path info handler stored in a map.
      */
-    
-    public void prepareShortestPathTopo() {
-	shortestPathTopo = new HashMap<Long, Node>();
+    public Map<Long, ?> prepareShortestPathTopo() {
+	Map<Long, Node> shortestPathTopo = new HashMap<Long, Node>();
 
 	//
 	// Fetch the relevant info from the Switch and Port vertices
 	// from the Titan Graph.
 	//
-	Iterable<ISwitchObject> nodes = conn.utils().getActiveSwitches(conn);
+	Iterable<ISwitchObject> nodes = op.getActiveSwitches();
 	for (ISwitchObject switchObj : nodes) {
 	    Vertex nodeVertex = switchObj.asVertex();
 	    //
@@ -259,7 +244,9 @@
 		}
 	    }
 	}
-	conn.endTx(Transaction.COMMIT);
+	op.commit();
+
+	return shortestPathTopo;
     }
 
     /**
@@ -268,9 +255,10 @@
      *
      * See the documentation for method @ref prepareShortestPathTopo()
      * for additional information and usage.
+     *
+     * @param shortestPathTopo the Shortest Path info handler to release.
      */
-  
-    public void dropShortestPathTopo() {
+    public void dropShortestPathTopo(Map<Long, ?> shortestPathTopo) {
 	shortestPathTopo = null;
     }
 
@@ -282,13 +270,17 @@
      * See the documentation for method @ref prepareShortestPathTopo()
      * for additional information and usage.
      *
+     * @param shortestPathTopoHandler the Shortest Path info handler
+     * to use.
      * @param src the source in the shortest path computation.
      * @param dest the destination in the shortest path computation.
      * @return the data path with the computed shortest path if
      * found, otherwise null.
      */
-  
-    public DataPath getTopoShortestPath(SwitchPort src, SwitchPort dest) {
+    public DataPath getTopoShortestPath(Map<Long, ?> shortestPathTopoHandler,
+					SwitchPort src, SwitchPort dest) {
+	@SuppressWarnings("unchecked")
+	Map<Long, Node> shortestPathTopo = (Map)shortestPathTopoHandler;
 	DataPath result_data_path = new DataPath();
 
 	// Initialize the source and destination in the data path to return
@@ -415,9 +407,9 @@
 
 	// Get the source and destination switches
 	ISwitchObject srcSwitch =
-	    conn.utils().searchActiveSwitch(conn, dpid_src);
+	    op.searchActiveSwitch(dpid_src);
 	ISwitchObject destSwitch =
-	    conn.utils().searchActiveSwitch(conn, dpid_dest);
+	    op.searchActiveSwitch(dpid_dest);
 	if (srcSwitch == null || destSwitch == null) {
 	    return null;
 	}
@@ -432,7 +424,7 @@
 	    flowEntry.setInPort(src.port());
 	    flowEntry.setOutPort(dest.port());
 	    result_data_path.flowEntries().add(flowEntry);
-	    conn.endTx(Transaction.COMMIT);
+	    op.commit();
 	    return result_data_path;
 	}
 
@@ -551,7 +543,7 @@
 	    result_data_path.flowEntries().add(flowEntry);
 	}
 
-	conn.endTx(Transaction.COMMIT);
+	op.commit();
 	if (result_data_path.flowEntries().size() > 0)
 	    return result_data_path;
 
diff --git a/src/main/java/net/floodlightcontroller/topology/web/RouteResource.java b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
similarity index 65%
rename from src/main/java/net/floodlightcontroller/topology/web/RouteResource.java
rename to src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
index 20f39d4..659609d 100644
--- a/src/main/java/net/floodlightcontroller/topology/web/RouteResource.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/topology/web/RouteResource.java
@@ -1,17 +1,12 @@
-package net.floodlightcontroller.topology.web;
+package net.onrc.onos.ofcontroller.topology.web;
 
-import java.util.List;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
 
-import net.floodlightcontroller.core.INetMapTopologyService.ITopoRouteService;
-import net.floodlightcontroller.routing.IRoutingService;
-import net.floodlightcontroller.routing.Route;
-import net.floodlightcontroller.topology.NodePortTuple;
-import net.floodlightcontroller.util.DataPath;
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.Port;
-import net.floodlightcontroller.util.SwitchPort;
-
-import org.openflow.util.HexString;
 import org.restlet.resource.Get;
 import org.restlet.resource.ServerResource;
 import org.slf4j.Logger;
@@ -23,9 +18,7 @@
 
     @Get("json")
     public DataPath retrieve() {
-        ITopoRouteService topoRouteService = 
-                (ITopoRouteService)getContext().getAttributes().
-                    get(ITopoRouteService.class.getCanonicalName());
+        ITopoRouteService topoRouteService = new TopoRouteService("");
 	if (topoRouteService == null) {
 	    log.debug("Topology Route Service not found");
 	    return null;
diff --git a/src/main/java/net/floodlightcontroller/util/CallerId.java b/src/main/java/net/onrc/onos/ofcontroller/util/CallerId.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/util/CallerId.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/CallerId.java
index ade0f0d..0607533 100644
--- a/src/main/java/net/floodlightcontroller/util/CallerId.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/CallerId.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
diff --git a/src/main/java/net/floodlightcontroller/util/DataPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
similarity index 81%
rename from src/main/java/net/floodlightcontroller/util/DataPath.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
index 0ca0d13..dec70e3 100644
--- a/src/main/java/net/floodlightcontroller/util/DataPath.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/DataPath.java
@@ -1,14 +1,11 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.util.SwitchPort;
-import net.floodlightcontroller.util.FlowEntry;
-
 import org.codehaus.jackson.annotate.JsonProperty;
 
 /**
- * The class representing the Data Path.
+ * The data forwarding path state from a source to a destination.
  */
 public class DataPath {
     private SwitchPort srcPort;		// The source port
@@ -79,6 +76,31 @@
     }
 
     /**
+     * Apply Flow Path Flags to the pre-computed Data Path.
+     *
+     * @param flowPathFlags the Flow Path Flags to apply.
+     */
+    public void applyFlowPathFlags(FlowPathFlags flowPathFlags) {
+	if (flowPathFlags == null)
+	    return;		// Nothing to do
+
+	// Discard the first Flow Entry
+	if (flowPathFlags.isDiscardFirstHopEntry()) {
+	    if (flowEntries.size() > 0)
+		flowEntries.remove(0);
+	}
+
+	// Keep only the first Flow Entry
+	if (flowPathFlags.isKeepOnlyFirstHopEntry()) {
+	    if (flowEntries.size() > 1) {
+		FlowEntry flowEntry = flowEntries.get(0);
+		flowEntries.clear();
+		flowEntries.add(flowEntry);
+	    }
+	}
+    }
+
+    /**
      * Get a string with the summary of the shortest-path data path
      * computation.
      *
diff --git a/src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java b/src/main/java/net/onrc/onos/ofcontroller/util/DataPathEndpoints.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/DataPathEndpoints.java
index 3ee88d1..9cdd4fb 100644
--- a/src/main/java/net/floodlightcontroller/util/DataPathEndpoints.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/DataPathEndpoints.java
@@ -1,6 +1,5 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import net.floodlightcontroller.util.SwitchPort;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
diff --git a/src/main/java/net/floodlightcontroller/util/Dpid.java b/src/main/java/net/onrc/onos/ofcontroller/util/Dpid.java
similarity index 86%
rename from src/main/java/net/floodlightcontroller/util/Dpid.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/Dpid.java
index 5af6bea..c3cf3aa 100644
--- a/src/main/java/net/floodlightcontroller/util/Dpid.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/Dpid.java
@@ -1,12 +1,11 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import org.openflow.util.HexString;
-import net.floodlightcontroller.util.serializers.DpidDeserializer;
-import net.floodlightcontroller.util.serializers.DpidSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.DpidDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.DpidSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.openflow.util.HexString;
 
 /**
  * The class representing a network switch DPID.
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntry.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
similarity index 86%
rename from src/main/java/net/floodlightcontroller/util/FlowEntry.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
index 3e29c78..049e783 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntry.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntry.java
@@ -1,18 +1,7 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import java.util.ArrayList;
 
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.FlowEntryAction;
-import net.floodlightcontroller.util.FlowEntryId;
-import net.floodlightcontroller.util.FlowEntryMatch;
-import net.floodlightcontroller.util.FlowEntrySwitchState;
-import net.floodlightcontroller.util.FlowEntryUserState;
-import net.floodlightcontroller.util.Port;
-
-import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.util.IPv4;
-
 import org.codehaus.jackson.annotate.JsonIgnore;
 import org.codehaus.jackson.annotate.JsonProperty;
 
@@ -23,10 +12,10 @@
  * support multiple in-ports and multiple out-ports.
  */
 public class FlowEntry {
-    private FlowId flowId;			// FlowID of flowEntry
+    private FlowId flowId;			// FlowID of the Flow Entry
     private FlowEntryId flowEntryId;		// The Flow Entry ID
     private FlowEntryMatch flowEntryMatch;	// The Flow Entry Match
-    private ArrayList<FlowEntryAction> flowEntryActions; // The Flow Entry Actions
+    private FlowEntryActions flowEntryActions;	// The Flow Entry Actions
     private Dpid dpid;				// The Switch DPID
     private Port inPort;		// The Switch incoming port. Used only
 					// when the entry is used to return
@@ -64,64 +53,64 @@
 	flowEntryMatch.enableDstTcpUdpPort((short)80);
 
 	FlowEntryAction action = null;
-	ArrayList<FlowEntryAction> actions = new ArrayList<FlowEntryAction>();
+	FlowEntryActions actions = new FlowEntryActions();
 
 	action = new FlowEntryAction();
 	action.setActionOutput(new Port((short)12));
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionOutputToController((short)13);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetVlanId((short)14);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetVlanPriority((byte)15);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionStripVlan(true);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetEthernetSrcAddr(mac);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetEthernetDstAddr(mac);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetIPv4SrcAddr(ipv4);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetIPv4DstAddr(ipv4);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetIpToS((byte)16);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetTcpUdpSrcPort((short)17);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionSetTcpUdpDstPort((short)18);
-	actions.add(action);
+	actions.addAction(action);
 
 	action = new FlowEntryAction();
 	action.setActionEnqueue(new Port((short)19), 20);
-	actions.add(action);
+	actions.addAction(action);
 
 	setFlowEntryActions(actions);
 	*/
 
-
+	flowEntryActions = new FlowEntryActions();
 	flowEntryUserState = FlowEntryUserState.FE_USER_UNKNOWN;
 	flowEntrySwitchState = FlowEntrySwitchState.FE_SWITCH_UNKNOWN;
     }
@@ -184,7 +173,7 @@
      * @return the Flow Entry Actions.
      */
     @JsonProperty("flowEntryActions")
-    public ArrayList<FlowEntryAction> flowEntryActions() {
+    public FlowEntryActions flowEntryActions() {
 	return flowEntryActions;
     }
 
@@ -194,7 +183,7 @@
      * @param flowEntryActions the Flow Entry Actions to set.
      */
     @JsonProperty("flowEntryActions")
-    public void setFlowEntryActions(ArrayList<FlowEntryAction> flowEntryActions) {
+    public void setFlowEntryActions(FlowEntryActions flowEntryActions) {
 	this.flowEntryActions = flowEntryActions;
     }
 
@@ -330,8 +319,7 @@
      * Convert the flow entry to a string.
      *
      * The string has the following form:
-     *  [flowEntryId=XXX flowEntryMatch=XXX flowEntryAction=XXX
-     *   flowEntryAction=XXX flowEntryAction=XXX dpid=XXX
+     *  [flowEntryId=XXX flowEntryMatch=XXX flowEntryActions=XXX dpid=XXX
      *   inPort=XXX outPort=XXX flowEntryUserState=XXX flowEntrySwitchState=XXX
      *   flowEntryErrorState=XXX]
      * @return the flow entry as a string.
@@ -340,9 +328,7 @@
     public String toString() {
 	String ret = "[flowEntryId=" + this.flowEntryId.toString();
 	ret += " flowEntryMatch=" + this.flowEntryMatch.toString();
-	for (FlowEntryAction fa : flowEntryActions) {
-	    ret += " flowEntryAction=" + fa.toString();
-	}
+	ret += " flowEntryActions=" + this.flowEntryActions.toString();
 	ret += " dpid=" + this.dpid.toString();
 	ret += " inPort=" + this.inPort.toString();
 	ret += " outPort=" + this.outPort.toString();
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java
new file mode 100644
index 0000000..f150983
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryAction.java
@@ -0,0 +1,1664 @@
+package net.onrc.onos.ofcontroller.util;
+
+import net.floodlightcontroller.util.MACAddress;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * The class representing a single Flow Entry action.
+ *
+ * A Flow Entry action that needs to be applied to each packet.
+ * Note that it contains only a single action. Multiple actions are
+ * listed in a list inside @ref FlowEntryActions.
+ */
+public class FlowEntryAction {
+    /**
+     * Special action values.
+     *
+     * Those values are taken as-is from the OpenFlow-v1.0.0 specification
+     * (pp 21-22).
+     */
+    public enum ActionValues {
+	ACTION_OUTPUT		((short)0x0),	// Output to switch port
+	ACTION_SET_VLAN_VID	((short)0x1),	// Set the 802.1q VLAN id
+	ACTION_SET_VLAN_PCP	((short)0x2),	// Set the 802.1q priority
+	ACTION_STRIP_VLAN	((short)0x3),	// Strip the 802.1q header
+	ACTION_SET_DL_SRC	((short)0x4),	// Ethernet source address
+	ACTION_SET_DL_DST	((short)0x5),	// Ethernet destination address
+	ACTION_SET_NW_SRC	((short)0x6),	// IP source address
+	ACTION_SET_NW_DST	((short)0x7),	// IP destination address
+	ACTION_SET_NW_TOS	((short)0x8),	// IP ToS (DSCP field, 6 bits)
+	ACTION_SET_TP_SRC	((short)0x9),	// TCP/UDP source port
+	ACTION_SET_TP_DST	((short)0xa),	// TCP/UDP destination port
+	ACTION_ENQUEUE		((short)0xb),	// Output to queue on port
+	ACTION_VENDOR		((short)0xffff); // Vendor-specific
+
+	private final short value;	// The value
+
+	/**
+	 * Constructor for a given value.
+	 *
+	 * @param value the value to use for the initialization.
+	 */
+	private ActionValues(short value) {
+	    this.value = value;
+	}
+    }
+
+    /**
+     * Action structure for ACTION_OUTPUT: Output to switch port.
+     */
+    public class ActionOutput {
+	private Port port;	// Output port
+	private short maxLen;	// Max. length (in bytes) to send to controller
+				// if the port is set to PORT_CONTROLLER
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionOutput() {
+	    this.port = null;
+	    this.maxLen = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionOutput(ActionOutput other) {
+	    if (other.port != null)
+		this.port = new Port(other.port);
+	    this.maxLen = other.maxLen;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX maxLen=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionOutput(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given output port and maximum length.
+	 *
+	 * @param port the output port to set.
+	 * @param maxLen the maximum length (in bytes) to send to controller
+	 * if the port is set to PORT_CONTROLLER.
+	 */
+	public ActionOutput(Port port, short maxLen) {
+	    this.port = port;
+	    this.maxLen = maxLen;
+	}
+
+	/**
+	 * Constructor for a given output port.
+	 *
+	 * @param port the output port to set.
+	 */
+	public ActionOutput(Port port) {
+	    this.port = port;
+	    this.maxLen = 0;
+	}
+
+	/**
+	 * Get the output port.
+	 *
+	 * @return the output port.
+	 */
+	@JsonProperty("port")
+	public Port port() {
+	    return this.port;
+	}
+
+	/**
+	 * Get the maximum length (in bytes) to send to controller if the
+	 * port is set to PORT_CONTROLLER.
+	 *
+	 * @return the maximum length (in bytes) to send to controller if the
+	 * port is set to PORT_CONTROLLER.
+	 */
+	@JsonProperty("maxLen")
+	public short maxLen() {
+	    return this.maxLen;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX maxLen=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "port=" + port.toString();
+	    ret += " maxLen=" + maxLen;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX maxLen=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split(" ");
+	    String decode = null;
+
+	    // Decode the "port=XXX" part
+	    if (parts.length > 0)
+		decode = parts[0];
+	    if (decode != null) {
+		String[] tokens = decode.split("port=");
+		if (tokens.length > 1 && tokens[1] != null) {
+		    try {
+			Short valueShort = Short.valueOf(tokens[1]);
+			port = new Port(valueShort);
+		    } catch (NumberFormatException e) {
+			throw new IllegalArgumentException("Invalid action string");
+		    }
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+
+	    // Decode the "maxLen=XXX" part
+	    decode = null;
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		String[] tokens = decode.split("maxLen=");
+		if (tokens.length > 1 && tokens[1] != null) {
+		    try {
+			maxLen = Short.valueOf(tokens[1]);
+		    } catch (NumberFormatException e) {
+			throw new IllegalArgumentException("Invalid action string");
+		    }
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_VLAN_VID: Set the 802.1q VLAN id
+     */
+    public class ActionSetVlanId {
+	private short vlanId;		// The VLAN ID to set
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetVlanId() {
+	    this.vlanId = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetVlanId(ActionSetVlanId other) {
+	    this.vlanId = other.vlanId;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [vlanId=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetVlanId(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given VLAN ID.
+	 *
+	 * @param vlanId the VLAN ID to set.
+	 */
+	public ActionSetVlanId(short vlanId) {
+	    this.vlanId = vlanId;
+	}
+
+	/**
+	 * Get the VLAN ID.
+	 *
+	 * @return the VLAN ID.
+	 */
+	@JsonProperty("vlanId")
+	public short vlanId() {
+	    return this.vlanId;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [vlanId=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "vlanId=" + this.vlanId;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [vlanId=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("vlanId=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    vlanId = Short.valueOf(decode);
+		} catch (NumberFormatException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_VLAN_PCP: Set the 802.1q priority
+     */
+    public class ActionSetVlanPriority {
+	private byte vlanPriority;	// The VLAN priority to set
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetVlanPriority() {
+	    this.vlanPriority = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetVlanPriority(ActionSetVlanPriority other) {
+	    this.vlanPriority = other.vlanPriority;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [vlanPriority=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetVlanPriority(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given VLAN priority.
+	 *
+	 * @param vlanPriority the VLAN priority to set.
+	 */
+	public ActionSetVlanPriority(byte vlanPriority) {
+	    this.vlanPriority = vlanPriority;
+	}
+
+	/**
+	 * Get the VLAN priority.
+	 *
+	 * @return the VLAN priority.
+	 */
+	@JsonProperty("vlanPriority")
+	public byte vlanPriority() {
+	    return this.vlanPriority;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [vlanPriority=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "vlanPriority=" + this.vlanPriority;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [vlanPriority=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("vlanPriority=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    vlanPriority = Byte.valueOf(decode);
+		} catch (NumberFormatException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_STRIP_VLAN: Strip the 802.1q header
+     */
+    public class ActionStripVlan {
+	private boolean stripVlan;	// If true, strip the VLAN header
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionStripVlan() {
+	    this.stripVlan = false;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionStripVlan(ActionStripVlan other) {
+	    this.stripVlan = other.stripVlan;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [stripVlan=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionStripVlan(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given boolean flag.
+	 *
+	 * @param stripVlan if true, strip the VLAN header.
+	 */
+	public ActionStripVlan(boolean stripVlan) {
+	    this.stripVlan = stripVlan;
+	}
+
+	/**
+	 * Get the boolean flag whether the VLAN header should be stripped.
+	 *
+	 * @return the boolean flag whether the VLAN header should be stripped.
+	 */
+	@JsonProperty("stripVlan")
+	public boolean stripVlan() {
+	    return this.stripVlan;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [stripVlan=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "stripVlan=" + this.stripVlan;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [stripVlan=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("stripVlan=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		stripVlan = Boolean.valueOf(decode);
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_DL_SRC and ACTION_SET_DL_DST:
+     * Set the Ethernet source/destination address.
+     */
+    public class ActionSetEthernetAddr {
+	private MACAddress addr;	// The MAC address to set
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetEthernetAddr() {
+	    this.addr = null;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetEthernetAddr(ActionSetEthernetAddr other) {
+	    if (other.addr != null)
+		this.addr = MACAddress.valueOf(other.addr.toLong());
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetEthernetAddr(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given MAC address.
+	 *
+	 * @param addr the MAC address to set.
+	 */
+	public ActionSetEthernetAddr(MACAddress addr) {
+	    this.addr = addr;
+	}
+
+	/**
+	 * Get the MAC address.
+	 *
+	 * @return the MAC address.
+	 */
+	@JsonProperty("addr")
+	public MACAddress addr() {
+	    return this.addr;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "addr=" + addr.toString();
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("addr=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    addr = MACAddress.valueOf(decode);
+		} catch (IllegalArgumentException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_NW_SRC and ACTION_SET_NW_DST:
+     * Set the IPv4 source/destination address.
+     */
+    public class ActionSetIPv4Addr {
+	private IPv4 addr;		// The IPv4 address to set
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetIPv4Addr() {
+	    this.addr = null;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetIPv4Addr(ActionSetIPv4Addr other) {
+	    if (other.addr != null)
+		this.addr = new IPv4(other.addr);
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetIPv4Addr(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given IPv4 address.
+	 *
+	 * @param addr the IPv4 address to set.
+	 */
+	public ActionSetIPv4Addr(IPv4 addr) {
+	    this.addr = addr;
+	}
+
+	/**
+	 * Get the IPv4 address.
+	 *
+	 * @return the IPv4 address.
+	 */
+	@JsonProperty("addr")
+	public IPv4 addr() {
+	    return this.addr;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "addr=" + addr.toString();
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [addr=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("addr=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    addr = new IPv4(decode);
+		} catch (IllegalArgumentException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_NW_TOS:
+     * Set the IP ToS (DSCP field, 6 bits).
+     */
+    public class ActionSetIpToS {
+	private byte ipToS;	// The IP ToS to set DSCP field, 6 bits)
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetIpToS() {
+	    this.ipToS = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetIpToS(ActionSetIpToS other) {
+	    this.ipToS = other.ipToS;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [ipToS=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetIpToS(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given IP ToS (DSCP field, 6 bits).
+	 *
+	 * @param ipToS the IP ToS (DSCP field, 6 bits) to set.
+	 */
+	public ActionSetIpToS(byte ipToS) {
+	    this.ipToS = ipToS;
+	}
+
+	/**
+	 * Get the IP ToS (DSCP field, 6 bits).
+	 *
+	 * @return the IP ToS (DSCP field, 6 bits).
+	 */
+	@JsonProperty("ipToS")
+	public byte ipToS() {
+	    return this.ipToS;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [ipToS=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "ipToS=" + ipToS;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [ipToS=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("ipToS=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    ipToS = Byte.valueOf(decode);
+		} catch (NumberFormatException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_SET_TP_SRC and ACTION_SET_TP_DST:
+     * Set the TCP/UDP source/destination port.
+     */
+    public class ActionSetTcpUdpPort {
+	private short port;		// The TCP/UDP port to set
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionSetTcpUdpPort() {
+	    this.port = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionSetTcpUdpPort(ActionSetTcpUdpPort other) {
+	    this.port = other.port;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionSetTcpUdpPort(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given TCP/UDP port.
+	 *
+	 * @param port the TCP/UDP port to set.
+	 */
+	public ActionSetTcpUdpPort(short port) {
+	    this.port = port;
+	}
+
+	/**
+	 * Get the TCP/UDP port.
+	 *
+	 * @return the TCP/UDP port.
+	 */
+	@JsonProperty("port")
+	public short port() {
+	    return this.port;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "port=" + port;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split("port=");
+	    String decode = null;
+
+	    // Decode the value
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		try {
+		    port = Short.valueOf(decode);
+		} catch (NumberFormatException e) {
+		    throw new IllegalArgumentException("Invalid action string");
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    /**
+     * Action structure for ACTION_ENQUEUE: Output to queue on port.
+     */
+    public class ActionEnqueue {
+	private Port port;	// Port that queue belongs. Should
+				// refer to a valid physical port
+				// (i.e. < PORT_MAX) or PORT_IN_PORT
+	private int queueId;	// Where to enqueue the packets
+
+	/**
+	 * Default constructor.
+	 */
+	public ActionEnqueue() {
+	    this.port = null;
+	    this.queueId = 0;
+	}
+
+	/**
+	 * Copy constructor.
+	 *
+	 * @param other the object to copy from.
+	 */
+	public ActionEnqueue(ActionEnqueue other) {
+	    if (other.port != null)
+		this.port = new Port(other.port);
+	    this.queueId = other.queueId;
+	}
+
+	/**
+	 * Constructor from a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX queueId=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public ActionEnqueue(String actionStr) {
+	    this.fromString(actionStr);
+	}
+
+	/**
+	 * Constructor for a given port and queue ID.
+	 *
+	 * @param port the port to set.
+	 * @param queueId the queue ID on the port.
+	 */
+	public ActionEnqueue(Port port, int queueId) {
+	    this.port = port;
+	    this.queueId = queueId;
+	}
+
+	/**
+	 * Get the port.
+	 *
+	 * @return the port.
+	 */
+	@JsonProperty("port")
+	public Port port() {
+	    return this.port;
+	}
+
+	/**
+	 * Get the queue ID.
+	 *
+	 * @return the queue ID.
+	 */
+	@JsonProperty("queueId")
+	public int queueId() {
+	    return this.queueId;
+	}
+
+	/**
+	 * Convert the action to a string.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX queueId=XXX]
+	 *
+	 * @return the action as a string.
+	 */
+	@Override
+	public String toString() {
+	    String ret = "[";
+	    ret += "port=" + port.toString();
+	    ret += " queueId=" + queueId;
+	    ret += "]";
+
+	    return ret;
+	}
+
+	/**
+	 * Convert a string to an action.
+	 *
+	 * The string has the following form:
+	 *  [port=XXX queueId=XXX]
+	 *
+	 * @param actionStr the action as a string.
+	 */
+	public void fromString(String actionStr) {
+	    String[] parts = actionStr.split(" ");
+	    String decode = null;
+
+	    // Decode the "port=XXX" part
+	    if (parts.length > 0)
+		decode = parts[0];
+	    if (decode != null) {
+		String[] tokens = decode.split("port=");
+		if (tokens.length > 1 && tokens[1] != null) {
+		    try {
+			Short valueShort = Short.valueOf(tokens[1]);
+			port = new Port(valueShort);
+		    } catch (NumberFormatException e) {
+			throw new IllegalArgumentException("Invalid action string");
+		    }
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+
+	    // Decode the "queueId=XXX" part
+	    decode = null;
+	    if (parts.length > 1)
+		decode = parts[1];
+	    if (decode != null) {
+		decode = decode.replace("]", "");
+		String[] tokens = decode.split("queueId=");
+		if (tokens.length > 1 && tokens[1] != null) {
+		    try {
+			queueId = Short.valueOf(tokens[1]);
+		    } catch (NumberFormatException e) {
+			throw new IllegalArgumentException("Invalid action string");
+		    }
+		}
+	    } else {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	}
+    }
+
+    private ActionValues actionType;	// The action type
+
+    //
+    // The actions.
+    // NOTE: Only one action should be set.
+    //
+    private ActionOutput actionOutput;
+    private ActionSetVlanId actionSetVlanId;
+    private ActionSetVlanPriority actionSetVlanPriority;
+    private ActionStripVlan actionStripVlan;
+    private ActionSetEthernetAddr actionSetEthernetSrcAddr;
+    private ActionSetEthernetAddr actionSetEthernetDstAddr;
+    private ActionSetIPv4Addr actionSetIPv4SrcAddr;
+    private ActionSetIPv4Addr actionSetIPv4DstAddr;
+    private ActionSetIpToS actionSetIpToS;
+    private ActionSetTcpUdpPort actionSetTcpUdpSrcPort;
+    private ActionSetTcpUdpPort actionSetTcpUdpDstPort;
+    private ActionEnqueue actionEnqueue;
+
+    /**
+     * Default constructor.
+     */
+    public FlowEntryAction() {
+	actionType = ActionValues.ACTION_VENDOR;	// XXX: Initial value
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public FlowEntryAction(FlowEntryAction other) {
+	this.actionType = other.actionType;
+
+	//
+	if (other.actionOutput != null)
+	    this.actionOutput = new ActionOutput(other.actionOutput);
+	else
+	    this.actionOutput = null;
+	//
+	if (other.actionSetVlanId != null)
+	    this.actionSetVlanId = new ActionSetVlanId(other.actionSetVlanId);
+	else
+	    this.actionSetVlanId = null;
+	//
+	if (other.actionSetVlanPriority != null)
+	    this.actionSetVlanPriority = new ActionSetVlanPriority(other.actionSetVlanPriority);
+	else
+	    this.actionSetVlanPriority = null;
+	//
+	if (other.actionStripVlan != null)
+	    this.actionStripVlan = new ActionStripVlan(other.actionStripVlan);
+	else
+	    this.actionStripVlan = null;
+	//
+	if (other.actionSetEthernetSrcAddr != null)
+	    this.actionSetEthernetSrcAddr = new ActionSetEthernetAddr(other.actionSetEthernetSrcAddr);
+	else
+	    this.actionSetEthernetSrcAddr = null;
+	//
+	if (other.actionSetEthernetDstAddr != null)
+	    this.actionSetEthernetDstAddr = new ActionSetEthernetAddr(other.actionSetEthernetDstAddr);
+	else
+	    this.actionSetEthernetDstAddr = null;
+	//
+	if (other.actionSetIPv4SrcAddr != null)
+	    this.actionSetIPv4SrcAddr = new ActionSetIPv4Addr(other.actionSetIPv4SrcAddr);
+	else
+	    this.actionSetIPv4SrcAddr = null;
+	//
+	if (other.actionSetIPv4DstAddr != null)
+	    this.actionSetIPv4DstAddr = new ActionSetIPv4Addr(other.actionSetIPv4DstAddr);
+	else
+	    this.actionSetIPv4DstAddr = null;
+	//
+	if (other.actionSetIpToS != null)
+	    this.actionSetIpToS = new ActionSetIpToS(other.actionSetIpToS);
+	else
+	    this.actionSetIpToS = null;
+	//
+	if (other.actionSetTcpUdpSrcPort != null)
+	    this.actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(other.actionSetTcpUdpSrcPort);
+	else
+	    this.actionSetTcpUdpSrcPort = null;
+	//
+	if (other.actionSetTcpUdpDstPort != null)
+	    this.actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(other.actionSetTcpUdpDstPort);
+	else
+	    this.actionSetTcpUdpDstPort = null;
+	//
+	if (other.actionEnqueue != null)
+	    this.actionEnqueue = new ActionEnqueue(other.actionEnqueue);
+	else
+	    this.actionEnqueue = null;
+    }
+
+    /**
+     * Constructor from a string.
+     *
+     * The string has the following form:
+     *  [type=XXX action=XXX]
+     *
+     * @param actionStr the action as a string.
+     */
+    public FlowEntryAction(String actionStr) {
+	this.fromString(actionStr);
+    }
+
+    /**
+     * Get the action type.
+     *
+     * @return the action type.
+     */
+    @JsonProperty("actionType")
+    public ActionValues actionType() { return actionType; }
+
+    /**
+     * Get the output action.
+     *
+     * @return the output action.
+     */
+    @JsonProperty("actionOutput")
+    public ActionOutput actionOutput() { return actionOutput; }
+
+    /**
+     * Set the output action on a port.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionOutput")
+    public void setActionOutput(ActionOutput action) {
+	actionOutput = action;
+	actionType = ActionValues.ACTION_OUTPUT;
+    }
+
+    /**
+     * Set the output action on a port.
+     *
+     * @param port the output port to set.
+     */
+    public void setActionOutput(Port port) {
+	actionOutput = new ActionOutput(port);
+	actionType = ActionValues.ACTION_OUTPUT;
+    }
+
+    /**
+     * Set the output action to controller.
+     *
+     * @param maxLen the maximum length (in bytes) to send to controller.
+     */
+    public void setActionOutputToController(short maxLen) {
+	Port port = new Port(Port.PortValues.PORT_CONTROLLER);
+	actionOutput = new ActionOutput(port, maxLen);
+	actionType = ActionValues.ACTION_OUTPUT;
+    }
+
+    /**
+     * Get the action to set the VLAN ID.
+     *
+     * @return the action to set the VLAN ID.
+     */
+    @JsonProperty("actionSetVlanId")
+    public ActionSetVlanId actionSetVlanId() { return actionSetVlanId; }
+
+    /**
+     * Set the action to set the VLAN ID.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetVlanId")
+    public void setActionSetVlanId(ActionSetVlanId action) {
+	actionSetVlanId = action;
+	actionType = ActionValues.ACTION_SET_VLAN_VID;
+    }
+
+    /**
+     * Set the action to set the VLAN ID.
+     *
+     * @param vlanId the VLAN ID to set.
+     */
+    public void setActionSetVlanId(short vlanId) {
+	actionSetVlanId = new ActionSetVlanId(vlanId);
+	actionType = ActionValues.ACTION_SET_VLAN_VID;
+    }
+
+    /**
+     * Get the action to set the VLAN priority.
+     *
+     * @return the action to set the VLAN priority.
+     */
+    @JsonProperty("actionSetVlanPriority")
+    public ActionSetVlanPriority actionSetVlanPriority() {
+	return actionSetVlanPriority;
+    }
+
+    /**
+     * Set the action to set the VLAN priority.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetVlanPriority")
+    public void setActionSetVlanPriority(ActionSetVlanPriority action) {
+	actionSetVlanPriority = action;
+	actionType = ActionValues.ACTION_SET_VLAN_PCP;
+    }
+
+    /**
+     * Set the action to set the VLAN priority.
+     *
+     * @param vlanPriority the VLAN priority to set.
+     */
+    public void setActionSetVlanPriority(byte vlanPriority) {
+	actionSetVlanPriority = new ActionSetVlanPriority(vlanPriority);
+	actionType = ActionValues.ACTION_SET_VLAN_PCP;
+    }
+
+    /**
+     * Get the action to strip the VLAN header.
+     *
+     * @return the action to strip the VLAN header.
+     */
+    @JsonProperty("actionStripVlan")
+    public ActionStripVlan actionStripVlan() {
+	return actionStripVlan;
+    }
+
+    /**
+     * Set the action to strip the VLAN header.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionStripVlan")
+    public void setActionStripVlan(ActionStripVlan action) {
+	actionStripVlan = action;
+	actionType = ActionValues.ACTION_STRIP_VLAN;
+    }
+
+    /**
+     * Set the action to strip the VLAN header.
+     *
+     * @param stripVlan if true, strip the VLAN header.
+     */
+    public void setActionStripVlan(boolean stripVlan) {
+	actionStripVlan = new ActionStripVlan(stripVlan);
+	actionType = ActionValues.ACTION_STRIP_VLAN;
+    }
+
+    /**
+     * Get the action to set the Ethernet source address.
+     *
+     * @return the action to set the Ethernet source address.
+     */
+    @JsonProperty("actionSetEthernetSrcAddr")
+    public ActionSetEthernetAddr actionSetEthernetSrcAddr() {
+	return actionSetEthernetSrcAddr;
+    }
+
+    /**
+     * Set the action to set the Ethernet source address.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetEthernetSrcAddr")
+    public void setActionSetEthernetSrcAddr(ActionSetEthernetAddr action) {
+	actionSetEthernetSrcAddr = action;
+	actionType = ActionValues.ACTION_SET_DL_SRC;
+    }
+
+    /**
+     * Set the action to set the Ethernet source address.
+     *
+     * @param addr the MAC address to set as the Ethernet source address.
+     */
+    public void setActionSetEthernetSrcAddr(MACAddress addr) {
+	actionSetEthernetSrcAddr = new ActionSetEthernetAddr(addr);
+	actionType = ActionValues.ACTION_SET_DL_SRC;
+    }
+
+    /**
+     * Get the action to set the Ethernet destination address.
+     *
+     * @return the action to set the Ethernet destination address.
+     */
+    @JsonProperty("actionSetEthernetDstAddr")
+    public ActionSetEthernetAddr actionSetEthernetDstAddr() {
+	return actionSetEthernetDstAddr;
+    }
+
+    /**
+     * Set the action to set the Ethernet destination address.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetEthernetDstAddr")
+    public void setActionSetEthernetDstAddr(ActionSetEthernetAddr action) {
+	actionSetEthernetDstAddr = action;
+	actionType = ActionValues.ACTION_SET_DL_DST;
+    }
+
+    /**
+     * Set the action to set the Ethernet destination address.
+     *
+     * @param addr the MAC address to set as the Ethernet destination address.
+     */
+    public void setActionSetEthernetDstAddr(MACAddress addr) {
+	actionSetEthernetDstAddr = new ActionSetEthernetAddr(addr);
+	actionType = ActionValues.ACTION_SET_DL_DST;
+    }
+
+    /**
+     * Get the action to set the IPv4 source address.
+     *
+     * @return the action to set the IPv4 source address.
+     */
+    @JsonProperty("actionSetIPv4SrcAddr")
+    public ActionSetIPv4Addr actionSetIPv4SrcAddr() {
+	return actionSetIPv4SrcAddr;
+    }
+
+    /**
+     * Set the action to set the IPv4 source address.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetIPv4SrcAddr")
+    public void setActionSetIPv4SrcAddr(ActionSetIPv4Addr action) {
+	actionSetIPv4SrcAddr = action;
+	actionType = ActionValues.ACTION_SET_NW_SRC;
+    }
+
+    /**
+     * Set the action to set the IPv4 source address.
+     *
+     * @param addr the IPv4 address to set as the IPv4 source address.
+     */
+    public void setActionSetIPv4SrcAddr(IPv4 addr) {
+	actionSetIPv4SrcAddr = new ActionSetIPv4Addr(addr);
+	actionType = ActionValues.ACTION_SET_NW_SRC;
+    }
+
+    /**
+     * Get the action to set the IPv4 destination address.
+     *
+     * @return the action to set the IPv4 destination address.
+     */
+    @JsonProperty("actionSetIPv4DstAddr")
+    public ActionSetIPv4Addr actionSetIPv4DstAddr() {
+	return actionSetIPv4DstAddr;
+    }
+
+    /**
+     * Set the action to set the IPv4 destination address.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetIPv4DstAddr")
+    public void setActionSetIPv4DstAddr(ActionSetIPv4Addr action) {
+	actionSetIPv4DstAddr = action;
+	actionType = ActionValues.ACTION_SET_NW_DST;
+    }
+
+    /**
+     * Set the action to set the IPv4 destination address.
+     *
+     * @param addr the IPv4 address to set as the IPv4 destination address.
+     */
+    public void setActionSetIPv4DstAddr(IPv4 addr) {
+	actionSetIPv4DstAddr = new ActionSetIPv4Addr(addr);
+	actionType = ActionValues.ACTION_SET_NW_DST;
+    }
+
+    /**
+     * Get the action to set the IP ToS (DSCP field, 6 bits).
+     *
+     * @return the action to set the IP ToS (DSCP field, 6 bits).
+     */
+    @JsonProperty("actionSetIpToS")
+    public ActionSetIpToS actionSetIpToS() {
+	return actionSetIpToS;
+    }
+
+    /**
+     * Set the action to set the IP ToS (DSCP field, 6 bits).
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetIpToS")
+    public void setActionSetIpToS(ActionSetIpToS action) {
+	actionSetIpToS = action;
+	actionType = ActionValues.ACTION_SET_NW_TOS;
+    }
+
+    /**
+     * Set the action to set the IP ToS (DSCP field, 6 bits).
+     *
+     * @param ipToS the IP ToS (DSCP field, 6 bits) to set.
+     */
+    public void setActionSetIpToS(byte ipToS) {
+	actionSetIpToS = new ActionSetIpToS(ipToS);
+	actionType = ActionValues.ACTION_SET_NW_TOS;
+    }
+
+    /**
+     * Get the action to set the TCP/UDP source port.
+     *
+     * @return the action to set the TCP/UDP source port.
+     */
+    @JsonProperty("actionSetTcpUdpSrcPort")
+    public ActionSetTcpUdpPort actionSetTcpUdpSrcPort() {
+	return actionSetTcpUdpSrcPort;
+    }
+
+    /**
+     * Set the action to set the TCP/UDP source port.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetTcpUdpSrcPort")
+    public void setActionSetTcpUdpSrcPort(ActionSetTcpUdpPort action) {
+	actionSetTcpUdpSrcPort = action;
+	actionType = ActionValues.ACTION_SET_TP_SRC;
+    }
+
+    /**
+     * Set the action to set the TCP/UDP source port.
+     *
+     * @param port the TCP/UDP port to set as the TCP/UDP source port.
+     */
+    public void setActionSetTcpUdpSrcPort(short port) {
+	actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(port);
+	actionType = ActionValues.ACTION_SET_TP_SRC;
+    }
+
+    /**
+     * Get the action to set the TCP/UDP destination port.
+     *
+     * @return the action to set the TCP/UDP destination port.
+     */
+    @JsonProperty("actionSetTcpUdpDstPort")
+    public ActionSetTcpUdpPort actionSetTcpUdpDstPort() {
+	return actionSetTcpUdpDstPort;
+    }
+
+    /**
+     * Set the action to set the TCP/UDP destination port.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionSetTcpUdpDstPort")
+    public void setActionSetTcpUdpDstPort(ActionSetTcpUdpPort action) {
+	actionSetTcpUdpDstPort = action;
+	actionType = ActionValues.ACTION_SET_TP_DST;
+    }
+
+    /**
+     * Set the action to set the TCP/UDP destination port.
+     *
+     * @param port the TCP/UDP port to set as the TCP/UDP destination port.
+     */
+    public void setActionSetTcpUdpDstPort(short port) {
+	actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(port);
+	actionType = ActionValues.ACTION_SET_TP_DST;
+    }
+
+    /**
+     * Get the action to output to queue on a port.
+     *
+     * @return the action to output to queue on a port.
+     */
+    @JsonProperty("actionEnqueue")
+    public ActionEnqueue actionEnqueue() { return actionEnqueue; }
+
+    /**
+     * Set the action to output to queue on a port.
+     *
+     * @param action the action to set.
+     */
+    @JsonProperty("actionEnqueue")
+    public void setActionEnqueue(ActionEnqueue action) {
+	actionEnqueue = action;
+	actionType = ActionValues.ACTION_ENQUEUE;
+    }
+
+    /**
+     * Set the action to output to queue on a port.
+     *
+     * @param port the port to set.
+     * @param int queueId the queue ID to set.
+     */
+    public void setActionEnqueue(Port port, int queueId) {
+	actionEnqueue = new ActionEnqueue(port, queueId);
+	actionType = ActionValues.ACTION_ENQUEUE;
+    }
+
+    /**
+     * Convert the action to a string.
+     *
+     * The string has the following form:
+     *  [type=XXX action=XXX]
+     *
+     * @return the action as a string.
+     */
+    @Override
+    public String toString() {
+	String ret = "[";
+	ret += "type=" + actionType;
+	switch (actionType) {
+	case ACTION_OUTPUT:
+	    ret += " action=" + actionOutput.toString();
+	    break;
+	case ACTION_SET_VLAN_VID:
+	    ret += " action=" + actionSetVlanId.toString();
+	    break;
+	case ACTION_SET_VLAN_PCP:
+	    ret += " action=" + actionSetVlanPriority.toString();
+	    break;
+	case ACTION_STRIP_VLAN:
+	    ret += " action=" + actionStripVlan.toString();
+	    break;
+	case ACTION_SET_DL_SRC:
+	    ret += " action=" + actionSetEthernetSrcAddr.toString();
+	    break;
+	case ACTION_SET_DL_DST:
+	    ret += " action=" + actionSetEthernetDstAddr.toString();
+	    break;
+	case ACTION_SET_NW_SRC:
+	    ret += " action=" + actionSetIPv4SrcAddr.toString();
+	    break;
+	case ACTION_SET_NW_DST:
+	    ret += " action=" + actionSetIPv4DstAddr.toString();
+	    break;
+	case ACTION_SET_NW_TOS:
+	    ret += " action=" + actionSetIpToS.toString();
+	    break;
+	case ACTION_SET_TP_SRC:
+	    ret += " action=" + actionSetTcpUdpSrcPort.toString();
+	    break;
+	case ACTION_SET_TP_DST:
+	    ret += " action=" + actionSetTcpUdpDstPort.toString();
+	    break;
+	case ACTION_ENQUEUE:
+	    ret += " action=" + actionEnqueue.toString();
+	    break;
+	}
+	ret += "]";
+
+	return ret;
+    }
+
+    /**
+     * Convert a string to an action.
+     *
+     * The string has the following form:
+     *  [type=XXX action=XXX]
+     *
+     * @param actionStr the action as a string.
+     */
+    public void fromString(String actionStr) {
+	String[] parts = actionStr.split("type=");
+	String decode = null;
+
+	// Extract the string after the "type="
+	if (parts.length > 1)
+	    decode = parts[1];
+	if (decode == null)
+	    throw new IllegalArgumentException("Invalid action string");
+
+	// Remove the trailing ']'
+	if ((decode.length() > 0) && (decode.charAt(decode.length() - 1) == ']')) {
+	    decode = decode.substring(0, decode.length() - 1);
+	} else {
+	    throw new IllegalArgumentException("Invalid action string");
+	}
+
+	// Extract the type value and the action value
+	parts = decode.split(" action=");
+
+	// Decode the "type=XXX" payload
+	if (parts.length > 0)
+	    decode = parts[0];
+	if (decode != null) {
+	    try {
+		actionType = Enum.valueOf(ActionValues.class, decode);
+	    } catch (IllegalArgumentException e) {
+		throw new IllegalArgumentException("Invalid action string");
+	    }
+	} else {
+	    throw new IllegalArgumentException("Invalid action string");
+	}
+
+	// Decode the "action=XXX" payload
+	decode = null;
+	if (parts.length > 1)
+	    decode = parts[1];
+	if (decode == null)
+	    throw new IllegalArgumentException("Invalid action string");
+	//
+	try {
+	    switch (actionType) {
+	    case ACTION_OUTPUT:
+		actionOutput = new ActionOutput(decode);
+		break;
+	    case ACTION_SET_VLAN_VID:
+		actionSetVlanId = new ActionSetVlanId(decode);
+		break;
+	    case ACTION_SET_VLAN_PCP:
+		actionSetVlanPriority = new ActionSetVlanPriority(decode);
+		break;
+	    case ACTION_STRIP_VLAN:
+		actionStripVlan = new ActionStripVlan(decode);
+		break;
+	    case ACTION_SET_DL_SRC:
+		actionSetEthernetSrcAddr = new ActionSetEthernetAddr(decode);
+		break;
+	    case ACTION_SET_DL_DST:
+		actionSetEthernetDstAddr = new ActionSetEthernetAddr(decode);
+		break;
+	    case ACTION_SET_NW_SRC:
+		actionSetIPv4SrcAddr = new ActionSetIPv4Addr(decode);
+		break;
+	    case ACTION_SET_NW_DST:
+		actionSetIPv4DstAddr = new ActionSetIPv4Addr(decode);
+		break;
+	    case ACTION_SET_NW_TOS:
+		actionSetIpToS = new ActionSetIpToS(decode);
+		break;
+	    case ACTION_SET_TP_SRC:
+		actionSetTcpUdpSrcPort = new ActionSetTcpUdpPort(decode);
+		break;
+	    case ACTION_SET_TP_DST:
+		actionSetTcpUdpDstPort = new ActionSetTcpUdpPort(decode);
+		break;
+	    case ACTION_ENQUEUE:
+		actionEnqueue = new ActionEnqueue(decode);
+		break;
+	    }
+	} catch (IllegalArgumentException e) {
+	    throw new IllegalArgumentException("Invalid action string");
+	}
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java
new file mode 100644
index 0000000..46f638d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryActions.java
@@ -0,0 +1,146 @@
+package net.onrc.onos.ofcontroller.util;
+
+import java.util.ArrayList;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * The class representing multiple Flow Entry actions.
+ *
+ * A set of Flow Entry actions need to be applied to each packet.
+ */
+public class FlowEntryActions {
+    private ArrayList<FlowEntryAction> actions;	// The Flow Entry Actions
+
+    /**
+     * Default constructor.
+     */
+    public FlowEntryActions() {
+	actions = new ArrayList<FlowEntryAction>();
+    }
+
+    /**
+     * Constructor from a string.
+     *
+     * The string has the following form:
+     *  [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+     *
+     * @param actionsStr the set of actions as a string.
+     */
+    public FlowEntryActions(String actionsStr) {
+	this.fromString(actionsStr);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public FlowEntryActions(FlowEntryActions other) {
+	actions = new ArrayList<FlowEntryAction>();
+
+	for (FlowEntryAction action : other.actions) {
+	    FlowEntryAction newAction = new FlowEntryAction(action);
+	    actions.add(newAction);
+	}
+    }
+
+    /**
+     * Get the Flow Entry Actions.
+     *
+     * @return the Flow Entry Actions.
+     */
+    @JsonProperty("actions")
+    public ArrayList<FlowEntryAction> actions() {
+	return actions;
+    }
+
+    /**
+     * Set the Flow Entry Actions.
+     *
+     * @param actions the Flow Entry Actions to set.
+     */
+    @JsonProperty("actions")
+    public void setActions(ArrayList<FlowEntryAction> actions) {
+	this.actions = actions;
+    }
+
+    /**
+     * Add a Flow Entry Action.
+     *
+     * @param FlowEntryAction the Flow Entry Action to add.
+     */
+    public void addAction(FlowEntryAction flowEntryAction) {
+	actions.add(flowEntryAction);
+    }
+
+    /**
+     * Test whether the set of actions is empty.
+     *
+     * @return true if the set of actions is empty, otherwise false.
+     */
+    public Boolean isEmpty() {
+	return actions.isEmpty();
+    }
+
+    /**
+     * Convert the set of actions to a string.
+     *
+     * The string has the following form:
+     *  [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+     *
+     * @return the set of actions as a string.
+     */
+    @Override
+    public String toString() {
+	String ret = "[";
+	for (FlowEntryAction action : actions) {
+	    ret += action.toString() + ";";
+	}
+	ret += "]";
+
+	return ret;
+    }
+
+    /**
+     * Convert a string to a set of actions.
+     *
+     * The string has the following form:
+     *  [[type=XXX action=XXX];[type=XXX action=XXX];...;]
+     *
+     * @param actionsStr the set of actions as a string.
+     */
+    public void fromString(String actionsStr) {
+	String decode = actionsStr;
+
+	actions = new ArrayList<FlowEntryAction>();
+
+	if (decode.isEmpty())
+	    return;		// Nothing to do
+
+	// Remove the '[' and ']' in the beginning and the end of the string
+	if ((decode.length() > 1) && (decode.charAt(0) == '[') &&
+	    (decode.charAt(decode.length() - 1) == ']')) {
+	    decode = decode.substring(1, decode.length() - 1);
+	} else {
+	    throw new IllegalArgumentException("Invalid action string");
+	}
+
+	// Split the string, and decode each action
+	String[] parts = decode.split(";");
+	for (int i = 0; i < parts.length; i++) {
+	    decode = parts[i];
+	    if ((decode == null) || decode.isEmpty())
+		continue;
+	    FlowEntryAction flowEntryAction = null;
+	    try {
+		flowEntryAction = new FlowEntryAction(decode);
+	    } catch (IllegalArgumentException e) {
+		// TODO: Ignore invalid actions for now
+		continue;
+	    }
+	    if (flowEntryAction != null)
+		actions.add(flowEntryAction);
+	}
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryErrorState.java
similarity index 97%
rename from src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryErrorState.java
index bf1708d..2e8c448 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryErrorState.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryErrorState.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryId.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryId.java
similarity index 87%
rename from src/main/java/net/floodlightcontroller/util/FlowEntryId.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryId.java
index e146a3d..c4e75a5 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryId.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryId.java
@@ -1,11 +1,10 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import java.math.BigInteger;
 
-import net.floodlightcontroller.util.serializers.FlowEntryIdDeserializer;
-import net.floodlightcontroller.util.serializers.FlowEntryIdSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.FlowEntryIdDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.FlowEntryIdSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryMatch.java
similarity index 99%
rename from src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryMatch.java
index 6c8e71e..a721ff2 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryMatch.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryMatch.java
@@ -1,7 +1,6 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.util.IPv4Net;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
@@ -73,13 +72,13 @@
     private Field<Port> inPort;		// Matching input switch port
     private Field<MACAddress> srcMac;	// Matching source MAC address
     private Field<MACAddress> dstMac;	// Matching destination MAC address
+    private Field<Short> ethernetFrameType; // Matching Ethernet frame type
     private Field<Short> vlanId;	// Matching VLAN ID
     private Field<Byte> vlanPriority;	// Matching VLAN priority
-    private Field<Short> ethernetFrameType; // Matching Ethernet frame type
-    private Field<Byte> ipToS;		// Matching IP ToS (DSCP field, 6 bits)
-    private Field<Byte> ipProto;	// Matching IP protocol
     private Field<IPv4Net> srcIPv4Net;	// Matching source IPv4 prefix
     private Field<IPv4Net> dstIPv4Net;	// Matching destination IPv4 prefix
+    private Field<Byte> ipProto;	// Matching IP protocol
+    private Field<Byte> ipToS;		// Matching IP ToS (DSCP field, 6 bits)
     private Field<Short> srcTcpUdpPort;	// Matching source TCP/UDP port
     private Field<Short> dstTcpUdpPort;	// Matching destination TCP/UDP port
 
@@ -101,20 +100,20 @@
 	    this.enableSrcMac(other.srcMac.value());
 	if ((other.dstMac != null) && other.dstMac.enabled())
 	    this.enableDstMac(other.dstMac.value());
+	if ((other.ethernetFrameType != null) && other.ethernetFrameType.enabled())
+	    this.enableEthernetFrameType(other.ethernetFrameType.value());
 	if ((other.vlanId != null) && other.vlanId.enabled())
 	    this.enableVlanId(other.vlanId.value());
 	if ((other.vlanPriority != null) && other.vlanPriority.enabled())
 	    this.enableVlanPriority(other.vlanPriority.value());
-	if ((other.ethernetFrameType != null) && other.ethernetFrameType.enabled())
-	    this.enableEthernetFrameType(other.ethernetFrameType.value());
-	if ((other.ipToS != null) && other.ipToS.enabled())
-	    this.enableIpToS(other.ipToS.value());
-	if ((other.ipProto != null) && other.ipProto.enabled())
-	    this.enableIpProto(other.ipProto.value());
 	if ((other.srcIPv4Net != null) && other.srcIPv4Net.enabled())
 	    this.enableSrcIPv4Net(other.srcIPv4Net.value());
 	if ((other.dstIPv4Net != null) && other.dstIPv4Net.enabled())
 	    this.enableDstIPv4Net(other.dstIPv4Net.value());
+	if ((other.ipProto != null) && other.ipProto.enabled())
+	    this.enableIpProto(other.ipProto.value());
+	if ((other.ipToS != null) && other.ipToS.enabled())
+	    this.enableIpToS(other.ipToS.value());
 	if ((other.srcTcpUdpPort != null) && other.srcTcpUdpPort.enabled())
 	    this.enableSrcTcpUdpPort(other.srcTcpUdpPort.value());
 	if ((other.dstTcpUdpPort != null) && other.dstTcpUdpPort.enabled())
@@ -245,6 +244,48 @@
     }
 
     /**
+     * Get the matching Ethernet frame type.
+     *
+     * @return the matching Ethernet frame type.
+     */
+    @JsonProperty("ethernetFrameType")
+    public Short ethernetFrameType() {
+	if (ethernetFrameType != null)
+	    return ethernetFrameType.value();
+	return null;
+    }
+
+    /**
+     * Enable the matching on Ethernet frame type.
+     *
+     * @param ethernetFrameType the Ethernet frame type value to enable for
+     * matching.
+     */
+    @JsonProperty("ethernetFrameType")
+    public void enableEthernetFrameType(Short ethernetFrameType) {
+	this.ethernetFrameType = new Field<Short>(ethernetFrameType);
+    }
+
+    /**
+     * Disable the matching on Ethernet frame type.
+     */
+    public void disableEthernetFrameType() {
+	this.ethernetFrameType = null;
+    }
+
+    /**
+     * Test if matching on Ethernet frame type is enabled.
+     *
+     * @return true if matching on Ethernet frame type is enabled.
+     */
+    @JsonProperty("matchEthernetFrameType")
+    public boolean matchEthernetFrameType() {
+	if (ethernetFrameType != null)
+	    return ethernetFrameType.enabled();
+	return false;
+    }
+
+    /**
      * Get the matching VLAN ID.
      *
      * @return the matching VLAN ID.
@@ -327,130 +368,6 @@
     }
 
     /**
-     * Get the matching Ethernet frame type.
-     *
-     * @return the matching Ethernet frame type.
-     */
-    @JsonProperty("ethernetFrameType")
-    public Short ethernetFrameType() {
-	if (ethernetFrameType != null)
-	    return ethernetFrameType.value();
-	return null;
-    }
-
-    /**
-     * Enable the matching on Ethernet frame type.
-     *
-     * @param ethernetFrameType the Ethernet frame type value to enable for
-     * matching.
-     */
-    @JsonProperty("ethernetFrameType")
-    public void enableEthernetFrameType(Short ethernetFrameType) {
-	this.ethernetFrameType = new Field<Short>(ethernetFrameType);
-    }
-
-    /**
-     * Disable the matching on Ethernet frame type.
-     */
-    public void disableEthernetFrameType() {
-	this.ethernetFrameType = null;
-    }
-
-    /**
-     * Test if matching on Ethernet frame type is enabled.
-     *
-     * @return true if matching on Ethernet frame type is enabled.
-     */
-    @JsonProperty("matchEthernetFrameType")
-    public boolean matchEthernetFrameType() {
-	if (ethernetFrameType != null)
-	    return ethernetFrameType.enabled();
-	return false;
-    }
-
-    /**
-     * Get the matching IP ToS (DSCP field, 6 bits)
-     *
-     * @return the matching IP ToS.
-     */
-    @JsonProperty("ipToS")
-    public Byte ipToS() {
-	if (ipToS != null)
-	    return ipToS.value();
-	return null;
-    }
-
-    /**
-     * Enable the matching on IP ToS (DSCP field, 6 bits).
-     *
-     * @param ipToS the IP ToS value to enable for matching.
-     */
-    @JsonProperty("ipToS")
-    public void enableIpToS(Byte ipToS) {
-	this.ipToS = new Field<Byte>(ipToS);
-    }
-
-    /**
-     * Disable the matching on IP ToS (DSCP field, 6 bits).
-     */
-    public void disableIpToS() {
-	this.ipToS = null;
-    }
-
-    /**
-     * Test if matching on IP ToS (DSCP field, 6 bits) is enabled.
-     *
-     * @return true if matching on IP ToS is enabled.
-     */
-    @JsonProperty("matchIpToS")
-    public boolean matchIpToS() {
-	if (ipToS != null)
-	    return ipToS.enabled();
-	return false;
-    }
-
-    /**
-     * Get the matching IP protocol.
-     *
-     * @return the matching IP protocol.
-     */
-    @JsonProperty("ipProto")
-    public Byte ipProto() {
-	if (ipProto != null)
-	    return ipProto.value();
-	return null;
-    }
-
-    /**
-     * Enable the matching on IP protocol.
-     *
-     * @param ipProto the IP protocol value to enable for matching.
-     */
-    @JsonProperty("ipProto")
-    public void enableIpProto(Byte ipProto) {
-	this.ipProto = new Field<Byte>(ipProto);
-    }
-
-    /**
-     * Disable the matching on IP protocol.
-     */
-    public void disableIpProto() {
-	this.ipProto = null;
-    }
-
-    /**
-     * Test if matching on IP protocol is enabled.
-     *
-     * @return true if matching on IP protocol is enabled.
-     */
-    @JsonProperty("matchIpProto")
-    public boolean matchIpProto() {
-	if (ipProto != null)
-	    return ipProto.enabled();
-	return false;
-    }
-
-    /**
      * Get the matching source IPv4 prefix.
      *
      * @return the matching source IPv4 prefix.
@@ -534,6 +451,88 @@
     }
 
     /**
+     * Get the matching IP protocol.
+     *
+     * @return the matching IP protocol.
+     */
+    @JsonProperty("ipProto")
+    public Byte ipProto() {
+	if (ipProto != null)
+	    return ipProto.value();
+	return null;
+    }
+
+    /**
+     * Enable the matching on IP protocol.
+     *
+     * @param ipProto the IP protocol value to enable for matching.
+     */
+    @JsonProperty("ipProto")
+    public void enableIpProto(Byte ipProto) {
+	this.ipProto = new Field<Byte>(ipProto);
+    }
+
+    /**
+     * Disable the matching on IP protocol.
+     */
+    public void disableIpProto() {
+	this.ipProto = null;
+    }
+
+    /**
+     * Test if matching on IP protocol is enabled.
+     *
+     * @return true if matching on IP protocol is enabled.
+     */
+    @JsonProperty("matchIpProto")
+    public boolean matchIpProto() {
+	if (ipProto != null)
+	    return ipProto.enabled();
+	return false;
+    }
+
+    /**
+     * Get the matching IP ToS (DSCP field, 6 bits)
+     *
+     * @return the matching IP ToS.
+     */
+    @JsonProperty("ipToS")
+    public Byte ipToS() {
+	if (ipToS != null)
+	    return ipToS.value();
+	return null;
+    }
+
+    /**
+     * Enable the matching on IP ToS (DSCP field, 6 bits).
+     *
+     * @param ipToS the IP ToS value to enable for matching.
+     */
+    @JsonProperty("ipToS")
+    public void enableIpToS(Byte ipToS) {
+	this.ipToS = new Field<Byte>(ipToS);
+    }
+
+    /**
+     * Disable the matching on IP ToS (DSCP field, 6 bits).
+     */
+    public void disableIpToS() {
+	this.ipToS = null;
+    }
+
+    /**
+     * Test if matching on IP ToS (DSCP field, 6 bits) is enabled.
+     *
+     * @return true if matching on IP ToS is enabled.
+     */
+    @JsonProperty("matchIpToS")
+    public boolean matchIpToS() {
+	if (ipToS != null)
+	    return ipToS.enabled();
+	return false;
+    }
+
+    /**
      * Get the matching source TCP/UDP port.
      *
      * @return the matching source TCP/UDP port.
@@ -650,6 +649,12 @@
 	    addSpace = true;
 	    ret += "dstMac=" + this.dstMac().toString();
 	}
+	if (matchEthernetFrameType()) {
+	    if (addSpace)
+		ret += " ";
+	    addSpace = true;
+	    ret += "ethernetFrameType=" + this.ethernetFrameType().toString();
+	}
 	if (matchVlanId()) {
 	    if (addSpace)
 		ret += " ";
@@ -662,24 +667,6 @@
 	    addSpace = true;
 	    ret += "vlanPriority=" + this.vlanPriority().toString();
 	}
-	if (matchEthernetFrameType()) {
-	    if (addSpace)
-		ret += " ";
-	    addSpace = true;
-	    ret += "ethernetFrameType=" + this.ethernetFrameType().toString();
-	}
-	if (matchIpToS()) {
-	    if (addSpace)
-		ret += " ";
-	    addSpace = true;
-	    ret += "ipToS=" + this.ipToS().toString();
-	}
-	if (matchIpProto()) {
-	    if (addSpace)
-		ret += " ";
-	    addSpace = true;
-	    ret += "ipProto=" + this.ipProto().toString();
-	}
 	if (matchSrcIPv4Net()) {
 	    if (addSpace)
 		ret += " ";
@@ -692,6 +679,18 @@
 	    addSpace = true;
 	    ret += "dstIPv4Net=" + this.dstIPv4Net().toString();
 	}
+	if (matchIpProto()) {
+	    if (addSpace)
+		ret += " ";
+	    addSpace = true;
+	    ret += "ipProto=" + this.ipProto().toString();
+	}
+	if (matchIpToS()) {
+	    if (addSpace)
+		ret += " ";
+	    addSpace = true;
+	    ret += "ipToS=" + this.ipToS().toString();
+	}
 	if (matchSrcTcpUdpPort()) {
 	    if (addSpace)
 		ret += " ";
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntrySwitchState.java
similarity index 90%
rename from src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntrySwitchState.java
index 4f9882a..a69fdac 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntrySwitchState.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntrySwitchState.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 /**
  * The Flow Entry state as set by the controller.
diff --git a/src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryUserState.java
similarity index 88%
rename from src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryUserState.java
index 8637b4f..e3b64f0 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowEntryUserState.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowEntryUserState.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 /**
  * The Flow Entry state as set by the user (via the ONOS API).
diff --git a/src/main/java/net/floodlightcontroller/util/FlowId.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowId.java
similarity index 68%
rename from src/main/java/net/floodlightcontroller/util/FlowId.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/FlowId.java
index 0297e2a..de955ba 100644
--- a/src/main/java/net/floodlightcontroller/util/FlowId.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowId.java
@@ -1,11 +1,10 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import java.math.BigInteger;
 
-import net.floodlightcontroller.util.serializers.FlowIdDeserializer;
-import net.floodlightcontroller.util.serializers.FlowIdSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.FlowIdDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.FlowIdSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -14,7 +13,7 @@
  */
 @JsonDeserialize(using=FlowIdDeserializer.class)
 @JsonSerialize(using=FlowIdSerializer.class)
-public class FlowId {
+public class FlowId implements Comparable<FlowId> {
     private long value;
 
     /**
@@ -77,4 +76,16 @@
     public String toString() {
 	return "0x" + Long.toHexString(this.value);
     }
+
+    /**
+     * Compare two FlowId objects numerically using their Flow IDs.
+     *
+     * @return the value 0 if the Flow ID is equal to the argument's Flow ID;
+     *         a value less than 0 if the Flow ID is numerically less than the argument's Flow ID;
+     *         and a value greater than 0 if the Flow ID is numerically greater than the argument's Flow ID.
+     */
+ 	@Override
+	public int compareTo(FlowId o) {
+		return Long.valueOf(this.value).compareTo(o.value());
+	}
 }
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java
new file mode 100644
index 0000000..153e184
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPath.java
@@ -0,0 +1,332 @@
+package net.onrc.onos.ofcontroller.util;
+
+import java.util.ArrayList;
+
+import net.floodlightcontroller.util.MACAddress;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.util.FlowPathFlags;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * The class representing the Flow Path.
+ */
+public class FlowPath implements Comparable<FlowPath> {
+    private FlowId flowId;		// The Flow ID
+    private CallerId installerId;	// The Caller ID of the path installer
+    private FlowPathFlags flowPathFlags; // The Flow Path flags
+    private DataPath dataPath;		// The data path
+    private FlowEntryMatch flowEntryMatch; // Common Flow Entry Match for all
+					// Flow Entries
+    private FlowEntryActions flowEntryActions; // The Flow Entry Actions for
+					// the first Flow Entry
+
+    /**
+     * Default constructor.
+     */
+    public FlowPath() {
+	flowPathFlags = new FlowPathFlags();
+	dataPath = new DataPath();
+	flowEntryActions = new FlowEntryActions();
+    }
+
+    /**
+     * Constructor to instantiate from object in Network Map
+     */
+    public FlowPath(IFlowPath flowObj) {
+    	dataPath = new DataPath();
+    	this.setFlowId(new FlowId(flowObj.getFlowId()));
+    	this.setInstallerId(new CallerId(flowObj.getInstallerId()));
+	this.setFlowPathFlags(new FlowPathFlags(flowObj.getFlowPathFlags()));
+    	this.dataPath().srcPort().setDpid(new Dpid(flowObj.getSrcSwitch()));
+    	this.dataPath().srcPort().setPort(new Port(flowObj.getSrcPort()));
+    	this.dataPath().dstPort().setDpid(new Dpid(flowObj.getDstSwitch()));
+    	this.dataPath().dstPort().setPort(new Port(flowObj.getDstPort()));
+	//
+	// Extract the match conditions that are common for all Flow Entries
+	//
+	{
+    	    FlowEntryMatch match = new FlowEntryMatch();
+    	    String matchSrcMac = flowObj.getMatchSrcMac();
+    	    if (matchSrcMac != null)
+    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+    	    String matchDstMac = flowObj.getMatchDstMac();
+    	    if (matchDstMac != null)
+    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+    	    Short matchEthernetFrameType = flowObj.getMatchEthernetFrameType();
+    	    if (matchEthernetFrameType != null)
+    		match.enableEthernetFrameType(matchEthernetFrameType);
+    	    Short matchVlanId = flowObj.getMatchVlanId();
+    	    if (matchVlanId != null)
+    		match.enableVlanId(matchVlanId);
+    	    Byte matchVlanPriority = flowObj.getMatchVlanPriority();
+    	    if (matchVlanPriority != null)
+    		match.enableVlanPriority(matchVlanPriority);
+    	    String matchSrcIPv4Net = flowObj.getMatchSrcIPv4Net();
+    	    if (matchSrcIPv4Net != null)
+    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+    	    String matchDstIPv4Net = flowObj.getMatchDstIPv4Net();
+    	    if (matchDstIPv4Net != null)
+    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+    	    Byte matchIpProto = flowObj.getMatchIpProto();
+    	    if (matchIpProto != null)
+    		match.enableIpProto(matchIpProto);
+    	    Byte matchIpToS = flowObj.getMatchIpToS();
+    	    if (matchIpToS != null)
+    		match.enableIpToS(matchIpToS);
+    	    Short matchSrcTcpUdpPort = flowObj.getMatchSrcTcpUdpPort();
+    	    if (matchSrcTcpUdpPort != null)
+    		match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+    	    Short matchDstTcpUdpPort = flowObj.getMatchDstTcpUdpPort();
+    	    if (matchDstTcpUdpPort != null)
+    		match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+
+    	    this.setFlowEntryMatch(match);
+	}
+
+	//
+	// Extract the actions for the first Flow Entry
+	//
+	{
+	    FlowEntryActions actions = new FlowEntryActions();
+
+	    String actionsStr = flowObj.getActions();
+	    if (actions != null)
+		actions = new FlowEntryActions(actionsStr);
+
+	    this.setFlowEntryActions(actions);
+	}
+
+    	//
+    	// Extract all Flow Entries
+    	//
+    	Iterable<IFlowEntry> flowEntries = flowObj.getFlowEntries();
+    	for (IFlowEntry flowEntryObj : flowEntries) {
+    	    FlowEntry flowEntry = new FlowEntry();
+    	    flowEntry.setFlowEntryId(new FlowEntryId(flowEntryObj.getFlowEntryId()));
+    	    flowEntry.setDpid(new Dpid(flowEntryObj.getSwitchDpid()));
+
+    	    //
+    	    // Extract the match conditions
+    	    //
+    	    FlowEntryMatch match = new FlowEntryMatch();
+	    //
+    	    Short matchInPort = flowEntryObj.getMatchInPort();
+    	    if (matchInPort != null)
+    		match.enableInPort(new Port(matchInPort));
+	    //
+    	    String matchSrcMac = flowEntryObj.getMatchSrcMac();
+    	    if (matchSrcMac != null)
+    		match.enableSrcMac(MACAddress.valueOf(matchSrcMac));
+	    //
+    	    String matchDstMac = flowEntryObj.getMatchDstMac();
+    	    if (matchDstMac != null)
+    		match.enableDstMac(MACAddress.valueOf(matchDstMac));
+	    //
+    	    Short matchEthernetFrameType = flowEntryObj.getMatchEthernetFrameType();
+    	    if (matchEthernetFrameType != null)
+    		match.enableEthernetFrameType(matchEthernetFrameType);
+	    //
+    	    Short matchVlanId = flowEntryObj.getMatchVlanId();
+    	    if (matchVlanId != null)
+    		match.enableVlanId(matchVlanId);
+	    //
+    	    Byte matchVlanPriority = flowEntryObj.getMatchVlanPriority();
+    	    if (matchVlanPriority != null)
+    		match.enableVlanPriority(matchVlanPriority);
+	    //
+    	    String matchSrcIPv4Net = flowEntryObj.getMatchSrcIPv4Net();
+    	    if (matchSrcIPv4Net != null)
+    		match.enableSrcIPv4Net(new IPv4Net(matchSrcIPv4Net));
+	    //
+    	    String matchDstIPv4Net = flowEntryObj.getMatchDstIPv4Net();
+    	    if (matchDstIPv4Net != null)
+    		match.enableDstIPv4Net(new IPv4Net(matchDstIPv4Net));
+	    //
+    	    Byte matchIpProto = flowEntryObj.getMatchIpProto();
+    	    if (matchIpProto != null)
+    		match.enableIpProto(matchIpProto);
+	    //
+    	    Byte matchIpToS = flowEntryObj.getMatchIpToS();
+    	    if (matchIpToS != null)
+    		match.enableIpToS(matchIpToS);
+	    //
+    	    Short matchSrcTcpUdpPort = flowEntryObj.getMatchSrcTcpUdpPort();
+    	    if (matchSrcTcpUdpPort != null)
+    		match.enableSrcTcpUdpPort(matchSrcTcpUdpPort);
+	    //
+    	    Short matchDstTcpUdpPort = flowEntryObj.getMatchDstTcpUdpPort();
+    	    if (matchDstTcpUdpPort != null)
+    		match.enableDstTcpUdpPort(matchDstTcpUdpPort);
+	    //
+    	    flowEntry.setFlowEntryMatch(match);
+
+	    //
+	    // Extract the actions
+	    //
+	    {
+		FlowEntryActions actions = new FlowEntryActions();
+
+		String actionsStr = flowObj.getActions();
+		if (actions != null)
+		    actions = new FlowEntryActions(actionsStr);
+
+		flowEntry.setFlowEntryActions(actions);
+	    }
+
+    	    String userState = flowEntryObj.getUserState();
+    	    flowEntry.setFlowEntryUserState(FlowEntryUserState.valueOf(userState));
+    	    String switchState = flowEntryObj.getSwitchState();
+    	    flowEntry.setFlowEntrySwitchState(FlowEntrySwitchState.valueOf(switchState));
+	    //
+	    // TODO: Take care of the FlowEntryErrorState.
+	    //
+    	    this.dataPath().flowEntries().add(flowEntry);
+    	}
+    }
+
+    /**
+     * Get the flow path Flow ID.
+     *
+     * @return the flow path Flow ID.
+     */
+    @JsonProperty("flowId")
+    public FlowId flowId() { return flowId; }
+
+    /**
+     * Set the flow path Flow ID.
+     *
+     * @param flowId the flow path Flow ID to set.
+     */
+    @JsonProperty("flowId")
+    public void setFlowId(FlowId flowId) {
+	this.flowId = flowId;
+    }
+
+    /**
+     * Get the Caller ID of the flow path installer.
+     *
+     * @return the Caller ID of the flow path installer.
+     */
+    @JsonProperty("installerId")
+    public CallerId installerId() { return installerId; }
+
+    /**
+     * Set the Caller ID of the flow path installer.
+     *
+     * @param installerId the Caller ID of the flow path installer.
+     */
+    @JsonProperty("installerId")
+    public void setInstallerId(CallerId installerId) {
+	this.installerId = installerId;
+    }
+
+    /**
+     * Get the flow path flags.
+     *
+     * @return the flow path flags.
+     */
+    @JsonProperty("flowPathFlags")
+    public FlowPathFlags flowPathFlags() { return flowPathFlags; }
+
+    /**
+     * Set the flow path flags.
+     *
+     * @param flowPathFlags the flow path flags to set.
+     */
+    @JsonProperty("flowPathFlags")
+    public void setFlowPathFlags(FlowPathFlags flowPathFlags) {
+	this.flowPathFlags = flowPathFlags;
+    }
+
+    /**
+     * Get the flow path's data path.
+     *
+     * @return the flow path's data path.
+     */
+    @JsonProperty("dataPath")
+    public DataPath dataPath() { return dataPath; }
+
+    /**
+     * Set the flow path's data path.
+     *
+     * @param dataPath the flow path's data path to set.
+     */
+    @JsonProperty("dataPath")
+    public void setDataPath(DataPath dataPath) {
+	this.dataPath = dataPath;
+    }
+
+    /**
+     * Get the flow path's match conditions common for all Flow Entries.
+     *
+     * @return the flow path's match conditions common for all Flow Entries.
+     */
+    @JsonProperty("flowEntryMatch")
+    public FlowEntryMatch flowEntryMatch() { return flowEntryMatch; }
+
+    /**
+     * Set the flow path's match conditions common for all Flow Entries.
+     *
+     * @param flowEntryMatch the flow path's match conditions common for all
+     * Flow Entries.
+     */
+    @JsonProperty("flowEntryMatch")
+    public void setFlowEntryMatch(FlowEntryMatch flowEntryMatch) {
+	this.flowEntryMatch = flowEntryMatch;
+    }
+
+    /**
+     * Get the flow path's flow entry actions for the first Flow Entry.
+     *
+     * @return the flow path's flow entry actions for the first Flow Entry.
+     */
+    @JsonProperty("flowEntryActions")
+    public FlowEntryActions flowEntryActions() {
+	return flowEntryActions;
+    }
+
+    /**
+     * Set the flow path's flow entry actions for the first Flow Entry.
+     *
+     * @param flowEntryActions the flow path's flow entry actions for the first
+     * Flow Entry.
+     */
+    @JsonProperty("flowEntryActions")
+    public void setFlowEntryActions(FlowEntryActions flowEntryActions) {
+	this.flowEntryActions = flowEntryActions;
+    }
+
+    /**
+     * Convert the flow path to a string.
+     *
+     * The string has the following form:
+     *  [flowId=XXX installerId=XXX flowPathFlags=XXX dataPath=XXX
+     *   flowEntryMatch=XXX flowEntryActions=XXX]
+     *
+     * @return the flow path as a string.
+     */
+    @Override
+    public String toString() {
+	String ret = "[flowId=" + this.flowId.toString();
+	ret += " installerId=" + this.installerId.toString();
+	ret += " flowPathFlags=" + this.flowPathFlags.toString();
+	if (dataPath != null)
+	    ret += " dataPath=" + this.dataPath.toString();
+	if (flowEntryMatch != null)
+	    ret += " flowEntryMatch=" + this.flowEntryMatch.toString();
+	if (flowEntryActions != null)
+	    ret += " flowEntryActions=" + this.flowEntryActions.toString();
+	ret += "]";
+	return ret;
+    }
+    
+    /**
+     * CompareTo method to order flowPath by Id
+     */
+    @Override
+    public int compareTo(FlowPath f) {
+    	return (int) (this.flowId.value() - f.flowId.value());
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/util/FlowPathFlags.java b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPathFlags.java
new file mode 100644
index 0000000..63241f0
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/FlowPathFlags.java
@@ -0,0 +1,128 @@
+package net.onrc.onos.ofcontroller.util;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * The class representing the Flow Path flags.
+ */
+public class FlowPathFlags {
+    private long flags;
+
+    // Discard the first-hop Flow Entry
+    private final long DISCARD_FIRST_HOP_ENTRY		= (1 << 0);
+
+    // Keep only the first-hop Flow Entry
+    private final long KEEP_ONLY_FIRST_HOP_ENTRY	= (1 << 1);
+
+    /**
+     * Default constructor.
+     */
+    public FlowPathFlags() {
+	this.flags = 0;
+    }
+
+    /**
+     * Constructor for given flags.
+     *
+     * @param flags the flags value to set.
+     */
+    public FlowPathFlags(long flags) {
+	this.flags = flags;
+    }
+
+    /**
+     * Constructor for given flags as a string.
+     *
+     * The string value should contain the name of each flags to set. E.g.:
+     *  "DISCARD_FIRST_HOP_ENTRY,KEEP_ONLY_FIRST_HOP_ENTRY"
+     * @param flagsStr the string value of the flags to set.
+     */
+    public FlowPathFlags(String flagsStr) {
+	this.setFlagsStr(flagsStr);
+    }
+
+    /**
+     * Get the flags.
+     *
+     * @return the flags.
+     */
+    @JsonProperty("flags")
+    public long flags() { return flags; }
+
+    /**
+     * Set the flags.
+     *
+     * @param flags the flags value to set.
+     */
+    @JsonProperty("flags")
+    public void setFlags(long flags) {
+	this.flags = flags;
+    }
+
+    /**
+     * Set the flags as a string.
+     *
+     * The string value should contain the name of each flags to set. E.g.:
+     *  "DISCARD_FIRST_HOP_ENTRY,KEEP_ONLY_FIRST_HOP_ENTRY"
+     * @param flagsStr the string value of the flags to set.
+     */
+    @JsonProperty("flagsStr")
+    public void setFlagsStr(String flagsStr) {
+	this.flags = 0L;
+
+	// Test all flags
+	if (flagsStr.contains("DISCARD_FIRST_HOP_ENTRY"))
+	    this.flags |= DISCARD_FIRST_HOP_ENTRY;
+	if (flagsStr.contains("KEEP_ONLY_FIRST_HOP_ENTRY"))
+	    this.flags |= KEEP_ONLY_FIRST_HOP_ENTRY;
+    }
+
+    /**
+     * Test whether the DISCARD_FIRST_HOP_ENTRY flag is set.
+     *
+     * @return true if the DISCARD_FIRST_HOP_ENTRY flag is set,
+     * otherwise false.
+     */
+    public boolean isDiscardFirstHopEntry() {
+	return ((flags & DISCARD_FIRST_HOP_ENTRY) != 0);
+    }
+
+    /**
+     * Test whether the KEEP_ONLY_FIRST_HOP_ENTRY flag is set.
+     *
+     * @return true if the KEEP_ONLY_FIRST_HOP_ENTRY flag is set,
+     * otherwise false.
+     */
+    public boolean isKeepOnlyFirstHopEntry() {
+	return ((flags & KEEP_ONLY_FIRST_HOP_ENTRY) != 0);
+    }
+
+    /**
+     * Convert the Flow Path Flags to a string.
+     *
+     * The string has the following form:
+     *  [flags=DISCARD_FIRST_HOP_ENTRY,KEEP_ONLY_FIRST_HOP_ENTRY]
+     *
+     * @return the Flow Path flags as a string.
+     */
+    @Override
+    public String toString() {
+	String flagsStr = null;
+	String ret = "[flags=";
+
+	// Test all flags
+	if ((this.flags & DISCARD_FIRST_HOP_ENTRY) != 0) {
+	    if (flagsStr != null)
+		flagsStr += ",";
+	    flagsStr += "DISCARD_FIRST_HOP_ENTRY";
+	}
+	if ((this.flags & KEEP_ONLY_FIRST_HOP_ENTRY) != 0) {
+	    if (flagsStr != null)
+		flagsStr += ",";
+	    flagsStr += "KEEP_ONLY_FIRST_HOP_ENTRY";
+	}
+	ret += "]";
+
+	return ret;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/util/IPv4.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
similarity index 83%
rename from src/main/java/net/floodlightcontroller/util/IPv4.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
index ef3a1e5..119165c 100644
--- a/src/main/java/net/floodlightcontroller/util/IPv4.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4.java
@@ -1,9 +1,8 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import net.floodlightcontroller.util.serializers.IPv4Deserializer;
-import net.floodlightcontroller.util.serializers.IPv4Serializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv4Deserializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv4Serializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -23,6 +22,15 @@
     }
 
     /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public IPv4(IPv4 other) {
+	this.value = other.value;
+    }
+
+    /**
      * Constructor from an integer value.
      *
      * @param value the value to use.
diff --git a/src/main/java/net/floodlightcontroller/util/IPv4Net.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/IPv4Net.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
index 824e3e2..9ce247c 100644
--- a/src/main/java/net/floodlightcontroller/util/IPv4Net.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv4Net.java
@@ -1,10 +1,8 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import net.floodlightcontroller.util.IPv4;
-import net.floodlightcontroller.util.serializers.IPv4NetDeserializer;
-import net.floodlightcontroller.util.serializers.IPv4NetSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv4NetDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv4NetSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -25,6 +23,17 @@
     }
 
     /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public IPv4Net(IPv4Net other) {
+	if (other.address != null)
+	    this.address = new IPv4(other.address);
+	this.prefixLen = other.prefixLen;
+    }
+
+    /**
      * Constructor for a given address and prefix length.
      *
      * @param address the address to use.
diff --git a/src/main/java/net/floodlightcontroller/util/IPv6.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
similarity index 87%
rename from src/main/java/net/floodlightcontroller/util/IPv6.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
index eda4502..f5dae11 100644
--- a/src/main/java/net/floodlightcontroller/util/IPv6.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6.java
@@ -1,12 +1,11 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import org.openflow.util.HexString;
-import net.floodlightcontroller.util.serializers.IPv6Deserializer;
-import net.floodlightcontroller.util.serializers.IPv6Serializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv6Deserializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv6Serializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
+import org.openflow.util.HexString;
 
 /**
  * The class representing an IPv6 address.
@@ -26,6 +25,16 @@
     }
 
     /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public IPv6(IPv6 other) {
+	this.valueHigh = other.valueHigh;
+	this.valueLow = other.valueLow;
+    }
+
+    /**
      * Constructor from integer values.
      *
      * @param valueHigh the higher (more significant) 64 bits of the address.
diff --git a/src/main/java/net/floodlightcontroller/util/IPv6Net.java b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/IPv6Net.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
index b6f7d67..65ffe54 100644
--- a/src/main/java/net/floodlightcontroller/util/IPv6Net.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/IPv6Net.java
@@ -1,10 +1,8 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
-import net.floodlightcontroller.util.IPv6;
-import net.floodlightcontroller.util.serializers.IPv6NetDeserializer;
-import net.floodlightcontroller.util.serializers.IPv6NetSerializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv6NetDeserializer;
+import net.onrc.onos.ofcontroller.util.serializers.IPv6NetSerializer;
 
-import org.codehaus.jackson.annotate.JsonProperty;
 import org.codehaus.jackson.map.annotate.JsonDeserialize;
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 
@@ -25,6 +23,17 @@
     }
 
     /**
+     * Copy constructor.
+     *
+     * @param other the object to copy from.
+     */
+    public IPv6Net(IPv6Net other) {
+	if (other.address != null)
+	    this.address = new IPv6(other.address);
+	this.prefixLen = other.prefixLen;
+    }
+
+    /**
      * Constructor for a given address and prefix length.
      *
      * @param address the address to use.
diff --git a/src/main/java/net/floodlightcontroller/util/Port.java b/src/main/java/net/onrc/onos/ofcontroller/util/Port.java
similarity index 95%
rename from src/main/java/net/floodlightcontroller/util/Port.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/Port.java
index 41f0d55..bb4851c 100644
--- a/src/main/java/net/floodlightcontroller/util/Port.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/Port.java
@@ -1,4 +1,4 @@
-package net.floodlightcontroller.util;
+package net.onrc.onos.ofcontroller.util;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
@@ -78,9 +78,9 @@
     }
 
     /**
-     * Constructor from another entry.
+     * Copy constructor.
      *
-     * @param other the other entry to use.
+     * @param other the object to copy from.
      */
     public Port(Port other) {
 	this.value = other.value();
diff --git a/src/main/java/net/floodlightcontroller/util/SwitchPort.java b/src/main/java/net/onrc/onos/ofcontroller/util/SwitchPort.java
similarity index 93%
rename from src/main/java/net/floodlightcontroller/util/SwitchPort.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/SwitchPort.java
index 027b681..95a934f 100644
--- a/src/main/java/net/floodlightcontroller/util/SwitchPort.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/SwitchPort.java
@@ -1,7 +1,4 @@
-package net.floodlightcontroller.util;
-
-import net.floodlightcontroller.util.Dpid;
-import net.floodlightcontroller.util.Port;
+package net.onrc.onos.ofcontroller.util;
 
 import org.codehaus.jackson.annotate.JsonProperty;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/DpidDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidDeserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/DpidDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidDeserializer.java
index 9297f56..9075f96 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/DpidDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.Dpid;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.Dpid;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/DpidSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidSerializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/DpidSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidSerializer.java
index 06fab62..7ece4d3 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/DpidSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/DpidSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.Dpid;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.Dpid;
-
 /**
  * Serialize a DPID as a string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdDeserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdDeserializer.java
index e6481d5..72ddfea 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.FlowEntryId;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdSerializer.java
similarity index 84%
rename from src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdSerializer.java
index 4b6583c..bf73265 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/FlowEntryIdSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowEntryIdSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.FlowEntryId;
-
 /**
  * Serialize a Flow Entry ID as a hexadecimal string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/FlowIdDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdDeserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/FlowIdDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdDeserializer.java
index a7f53d4..eb93a23 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/FlowIdDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.FlowId;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.FlowId;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/FlowIdSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdSerializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/FlowIdSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdSerializer.java
index 6f1a6f6..34f6e05 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/FlowIdSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/FlowIdSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.FlowId;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.FlowId;
-
 /**
  * Serialize a Flow ID as a hexadecimal string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv4Deserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Deserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv4Deserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Deserializer.java
index 275f9f0..daf90af 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv4Deserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Deserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.IPv4;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.IPv4;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv4NetDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetDeserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv4NetDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetDeserializer.java
index 3c36870..f67ab38 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv4NetDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.IPv4Net;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.IPv4Net;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv4NetSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetSerializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv4NetSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetSerializer.java
index 5c5e1d0..0454a58 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv4NetSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4NetSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.IPv4Net;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.IPv4Net;
-
 /**
  * Serialize an IPv4Net address as a string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv4Serializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Serializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv4Serializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Serializer.java
index ba7d825..aefc8a0 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv4Serializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv4Serializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.IPv4;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.IPv4;
-
 /**
  * Serialize an IPv4 address as a string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv6Deserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Deserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv6Deserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Deserializer.java
index 818de30..7e3e5f6 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv6Deserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Deserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.IPv6;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.IPv6;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv6NetDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetDeserializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv6NetDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetDeserializer.java
index 375dc26..d7631b3 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv6NetDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
+import net.onrc.onos.ofcontroller.util.IPv6Net;
+
 import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
+import org.codehaus.jackson.JsonToken;
 import org.codehaus.jackson.map.DeserializationContext;
-
-import net.floodlightcontroller.util.IPv6Net;
-
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv6NetSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetSerializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv6NetSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetSerializer.java
index fc5d262..06dc6cf 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv6NetSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6NetSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.IPv6Net;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.IPv6Net;
-
 /**
  * Serialize an IPv6Net address as a string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/IPv6Serializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Serializer.java
similarity index 85%
rename from src/main/java/net/floodlightcontroller/util/serializers/IPv6Serializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Serializer.java
index 0b08a63..b6709b8 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/IPv6Serializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/IPv6Serializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.onrc.onos.ofcontroller.util.IPv6;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.IPv6;
-
 /**
  * Serialize an IPv6 address as a string.
  */
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/MACAddressDeserializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressDeserializer.java
similarity index 89%
rename from src/main/java/net/floodlightcontroller/util/serializers/MACAddressDeserializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressDeserializer.java
index 35b384d..dc4a0e2 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/MACAddressDeserializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressDeserializer.java
@@ -1,17 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.JsonProcessingException;
-import org.codehaus.jackson.ObjectCodec;
-import org.codehaus.jackson.map.JsonDeserializer;
-import org.codehaus.jackson.map.DeserializationContext;
-
 import net.floodlightcontroller.util.MACAddress;
 
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.JsonToken;
+import org.codehaus.jackson.map.DeserializationContext;
+import org.codehaus.jackson.map.JsonDeserializer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/src/main/java/net/floodlightcontroller/util/serializers/MACAddressSerializer.java b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressSerializer.java
similarity index 92%
rename from src/main/java/net/floodlightcontroller/util/serializers/MACAddressSerializer.java
rename to src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressSerializer.java
index dec2596..9c0e225 100644
--- a/src/main/java/net/floodlightcontroller/util/serializers/MACAddressSerializer.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/util/serializers/MACAddressSerializer.java
@@ -1,14 +1,14 @@
-package net.floodlightcontroller.util.serializers;
+package net.onrc.onos.ofcontroller.util.serializers;
 
 import java.io.IOException;
 
+import net.floodlightcontroller.util.MACAddress;
+
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
-import net.floodlightcontroller.util.MACAddress;
-
 /**
  * Serialize a MAC address as a string.
  */
diff --git a/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java b/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java
index e48c519..640a49d 100644
--- a/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java
+++ b/src/main/java/net/onrc/onos/registry/controller/StandaloneRegistry.java
@@ -116,10 +116,22 @@
 		throw new RuntimeException("Not yet implemented");
 	}
 	
+	private long blockTop = 0L;
+	private static final long BLOCK_SIZE = 0x1000000L;
+	
+	/**
+	 * Returns a block of IDs which are unique and unused.
+	 * Range of IDs is fixed size and is assigned incrementally as this method called.
+	 */
 	@Override
-	public IdBlock allocateUniqueIdBlock(){
-		//XXX Not exactly unique...
-		return new IdBlock(0L, 0x10000000L, 0x10000000L);
+	public synchronized IdBlock allocateUniqueIdBlock(){
+		long blockHead = blockTop;
+		long blockTail = blockTop + BLOCK_SIZE;
+		
+		IdBlock block = new IdBlock(blockHead, blockTail - 1, BLOCK_SIZE);
+		blockTop = blockTail;
+		
+		return block;
 	}
 
 	@Override
diff --git a/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
index 82259a9..2d2083f 100644
--- a/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
+++ b/src/main/java/net/onrc/onos/registry/controller/ZookeeperRegistry.java
@@ -109,13 +109,7 @@
 		}
 	}
 	
-	
-	/**
-	 * Listens for changes to the switch znodes in Zookeeper. This maintains
-	 * the second level of PathChildrenCaches that hold the controllers 
-	 * contending for each switch - there's one for each switch.
-	 */
-	PathChildrenCacheListener switchPathCacheListener = new PathChildrenCacheListener() {
+	protected class SwitchPathCacheListener implements PathChildrenCacheListener {
 		@Override
 		public void childEvent(CuratorFramework client,
 				PathChildrenCacheEvent event) throws Exception {
@@ -158,6 +152,12 @@
 			
 		}
 	};
+	/**
+	 * Listens for changes to the switch znodes in Zookeeper. This maintains
+	 * the second level of PathChildrenCaches that hold the controllers 
+	 * contending for each switch - there's one for each switch.
+	 */
+	PathChildrenCacheListener switchPathCacheListener = new SwitchPathCacheListener();
 	protected ServiceDiscovery<ControllerService> serviceDiscovery;
 	protected ServiceCache<ControllerService> serviceCache;
 
@@ -379,6 +379,12 @@
 		return data;
 	}
 	
+	/**
+	 * Returns a block of IDs which are unique and unused.
+	 * Range of IDs is fixed size and is assigned incrementally as this method called.
+	 * Since the range of IDs is managed by Zookeeper in distributed way, this method may block when
+	 * requests come up simultaneously.
+	 */
 	public IdBlock allocateUniqueIdBlock(){
 		try {
 			AtomicValue<Long> result = null;
diff --git a/src/main/java/net/onrc/onos/util/GraphDBConnection.java b/src/main/java/net/onrc/onos/util/GraphDBConnection.java
deleted file mode 100644
index 7ea0ab8..0000000
--- a/src/main/java/net/onrc/onos/util/GraphDBConnection.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package net.onrc.onos.util;
-
-import java.util.Set;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.thinkaurelius.titan.core.TitanFactory;
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.TransactionalGraph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.blueprints.util.wrappers.event.EventTransactionalGraph;
-import com.tinkerpop.frames.FramedGraph;
-
-public class GraphDBConnection {
-	public enum Transaction {
-		COMMIT,
-		ROLLBACK
-	}
-	public enum GenerateEvent {
-		TRUE,
-		FALSE
-	}
-	class TransactionHandle {
-		protected TransactionalGraph tr;
-		public void create() {
-			tr = graph.newTransaction();			
-		}
-	}
-	protected static Logger log = LoggerFactory.getLogger(GraphDBConnection.class);
-	private static GraphDBConnection singleton = new GraphDBConnection( );
-	private static TitanGraph graph;
-	private static EventTransactionalGraph<TitanGraph> eg;
-	private static GraphDBUtils utils;
-	private static String configFile;
-
-	   
-	   /* A private Constructor prevents any other 
-	    * class from instantiating.
-	    */
-	   private GraphDBConnection(){ }
-	   
-	   /* Static 'instance' method */
-	   public static synchronized GraphDBConnection getInstance(final String conf) {
-		   if (GraphDBConnection.configFile == null || GraphDBConnection.configFile.isEmpty()) {
-			   GraphDBConnection.configFile = conf;
-			   log.debug("GraphDBConnection::Setting Config File {}", GraphDBConnection.configFile);
-		   }
-		   if (!GraphDBConnection.configFile.isEmpty() && 
-				   (graph == null||graph.isOpen() == Boolean.FALSE)) {
-		        graph = TitanFactory.open(GraphDBConnection.configFile);		        
-		        // FIXME: Creation on Indexes should be done only once
-		        Set<String> s = graph.getIndexedKeys(Vertex.class);
-		        if (!s.contains("dpid")) {
-		           graph.createKeyIndex("dpid", Vertex.class);
-		        }
-		        if (!s.contains("type")) {
-		        	graph.createKeyIndex("type", Vertex.class);
-		        }
-		        if (!s.contains("dl_address")) {
-		        	graph.createKeyIndex("dl_address", Vertex.class);
-		        }
-		        if (!s.contains("flow_id")) {
-		        	graph.createKeyIndex("flow_id", Vertex.class);
-		        }
-		        if (!s.contains("flow_entry_id")) {
-		        	graph.createKeyIndex("flow_entry_id",
-						     Vertex.class);
-		        }
-		        if (!s.contains("switch_state")) {
-		        	graph.createKeyIndex("switch_state",
-						     Vertex.class);
-		        }
-		        graph.commit();
-		        eg = new EventTransactionalGraph<TitanGraph>(graph);
-		   }		   
-		   if (utils == null) {
-			   utils = new GraphDBUtils();
-		   }
-	      return singleton;
-	   }
-	   
-	   public IDBUtils utils() {
-		   return utils;
-	   }
-	   
-	   public FramedGraph<TitanGraph> getFramedGraph() {
-	   
-		   	if (isValid()) {
-		   		FramedGraph<TitanGraph> fg = new FramedGraph<TitanGraph>(graph);
-		   		return fg;
-		   	} else {
-		   		log.error("new FramedGraph failed");
-		   		return null;
-		   	}
-	   }
-	   
-	   protected EventTransactionalGraph<TitanGraph> getEventGraph() {
-		   
-		   	if (isValid()) {		   		
-		   		return eg;
-		   	} else {
-		   		return null;
-		   	}
-	   }
-	   
-	   public void addEventListener(final LocalGraphChangedListener listener) {		   
-		   EventTransactionalGraph<TitanGraph> eg = this.getEventGraph();
-		   eg.addListener(listener);
-		   log.debug("Registered listener {}",listener.getClass());
-	   }
-	   
-	   public Boolean isValid() {
-		   
-		   return (graph != null||graph.isOpen());
-	   }
-	   
-	   public void startTx() {
-		   
-		   
-	   }
-	   
-	   public void endTx(Transaction tx) {
-		   try {
-			   switch (tx) {
-			   case COMMIT:
-				   graph.commit();
-			   case ROLLBACK:
-				   graph.rollback();
-			   }
-		   } catch (Exception e) {
-			   // TODO Auto-generated catch block
-			   log.error("{}",e.toString());
-		   }
-	   }
-	   
-	   public void endTx(TransactionHandle tr, Transaction tx) {
-		   switch (tx) {
-		   case COMMIT:
-			   if (tr != null && tr.tr != null) {
-				   tr.tr.commit();
-			   } else {
-				   graph.commit();
-			   }
-		   case ROLLBACK:
-			   if (tr != null && tr.tr != null) {
-				   tr.tr.rollback();
-			   } else {
-				   graph.rollback();
-			   }
-		   }
-	   }   
-	   
-	   public void endTx(Transaction tx, GenerateEvent fire) {
-
-		   try {
-			if (fire.equals(GenerateEvent.TRUE)) {
-				   switch (tx) {
-				   case COMMIT:
-					   eg.commit();
-				   case ROLLBACK:
-					   eg.rollback();
-				   }
-			   } else {
-					endTx(tx);   			   
-			   }
-		} catch (Exception e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
-		}
-	   }
-	   
-	   public void close() {
-		   endTx(Transaction.COMMIT);
-	   }	   
-}
diff --git a/src/main/java/net/onrc/onos/util/GraphDBUtils.java b/src/main/java/net/onrc/onos/util/GraphDBUtils.java
deleted file mode 100644
index 6601bf9..0000000
--- a/src/main/java/net/onrc/onos/util/GraphDBUtils.java
+++ /dev/null
@@ -1,250 +0,0 @@
-package net.onrc.onos.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
-import net.floodlightcontroller.util.FlowEntryId;
-import net.floodlightcontroller.util.FlowId;
-
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.frames.FramedGraph;
-import com.tinkerpop.frames.structures.FramedVertexIterable;
-import com.tinkerpop.gremlin.java.GremlinPipeline;
-
-public class GraphDBUtils implements IDBUtils {
-	
-	@Override
-	public ISwitchObject newSwitch(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		ISwitchObject obj = fg.addVertex(null,ISwitchObject.class);
-		return obj;
-	}
-
-	@Override
-	public void removeSwitch(GraphDBConnection conn, ISwitchObject sw) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		fg.removeVertex(sw.asVertex());		
-	}
-	
-	@Override
-	public ISwitchObject searchSwitch(GraphDBConnection conn, String dpid) {
-		// TODO Auto-generated method stub
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		
-		return (fg != null && fg.getVertices("dpid",dpid).iterator().hasNext()) ? 
-				fg.getVertices("dpid",dpid,ISwitchObject.class).iterator().next() : null;
-    			
-	}
-
-	@Override
-	public IDeviceObject searchDevice(GraphDBConnection conn, String macAddr) {
-		// TODO Auto-generated method stub
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		return (fg != null && fg.getVertices("dl_address",macAddr).iterator().hasNext()) ? fg.getVertices("dl_address",macAddr,
-    			IDeviceObject.class).iterator().next() : null;
-    			
-	}
-
-	@Override
-	public IPortObject searchPort(GraphDBConnection conn, String dpid, short number) {
-		ISwitchObject sw = searchSwitch(conn, dpid);
-//		if (sw != null) {
-//			
-//			IPortObject port = null;
-//			
-			// Requires Frames 2.3.0
-//			
-//			try {
-//				port = sw.getPort(number);
-//			} catch (Exception e) {
-//				// TODO Auto-generated catch block
-//				e.printStackTrace();
-//			}
-//			
-//			return port;
-//		}
-		
-		if (sw != null) {
-			GremlinPipeline<Vertex, IPortObject> pipe = new GremlinPipeline<Vertex, IPortObject>();
-			pipe.start(sw.asVertex());
-			pipe.out("on").has("number", number);
-			FramedVertexIterable<IPortObject> r = new FramedVertexIterable<IPortObject>(conn.getFramedGraph(), (Iterable) pipe, IPortObject.class);
-			return r != null && r.iterator().hasNext() ? r.iterator().next() : null;
-		}
-		return null;
-	}
-
-	@Override
-	public IPortObject newPort(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		IPortObject obj = fg.addVertex(null,IPortObject.class);
-		return obj;
-	}
-	
-	@Override
-	public IDeviceObject newDevice(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		IDeviceObject obj = fg.addVertex(null,IDeviceObject.class);
-		return obj;
-	}
-	
-	@Override
-	public void removePort(GraphDBConnection conn, IPortObject port) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-//		EventGraph<TitanGraph> eg = conn.getEventGraph();
-		if (fg != null) fg.removeVertex(port.asVertex());		
-	}
-
-	@Override
-	public void removeDevice(GraphDBConnection conn, IDeviceObject dev) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		if (fg != null) fg.removeVertex(dev.asVertex());		
-	}
-
-	@Override
-	public Iterable<IDeviceObject> getDevices(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		return fg != null ? fg.getVertices("type","device",IDeviceObject.class) : null;
-	}
-
-	@Override
-	public IFlowPath searchFlowPath(GraphDBConnection conn,
-					FlowId flowId) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		
-		return fg.getVertices("flow_id", flowId.toString()).iterator().hasNext() ? 
-		    fg.getVertices("flow_id", flowId.toString(),
-				   IFlowPath.class).iterator().next() : null;
-	}
-
-	@Override
-	public IFlowPath newFlowPath(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		IFlowPath flowPath = fg.addVertex(null, IFlowPath.class);
-		return flowPath;
-	}
-
-	@Override
-	public void removeFlowPath(GraphDBConnection conn,
-				   IFlowPath flowPath) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		fg.removeVertex(flowPath.asVertex());
-	}
-
-	@Override
-	public IFlowPath getFlowPathByFlowEntry(GraphDBConnection conn,
-						IFlowEntry flowEntry) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		GremlinPipeline<Vertex, IFlowPath> pipe = new GremlinPipeline<Vertex, IFlowPath>();
-		pipe.start(flowEntry.asVertex());
-		pipe.out("flow");
-		FramedVertexIterable<IFlowPath> r = new FramedVertexIterable(conn.getFramedGraph(), (Iterable) pipe, IFlowPath.class);
-		return r.iterator().hasNext() ? r.iterator().next() : null;
-	}
-
-	@Override
-    public Iterable<IFlowPath> getAllFlowPaths(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		Iterable<IFlowPath> flowPaths = fg.getVertices("type", "flow", IFlowPath.class);
-		
-		List<IFlowPath> nonNullFlows = new ArrayList<IFlowPath>();
-
-		for (IFlowPath fp: flowPaths) {
-			if (fp.getFlowId() != null) {
-				nonNullFlows.add(fp);
-			}
-		}
-		return nonNullFlows;
-	}
-
-	@Override
-	public IFlowEntry searchFlowEntry(GraphDBConnection conn,
-					  FlowEntryId flowEntryId) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		
-		return fg.getVertices("flow_entry_id", flowEntryId.toString()).iterator().hasNext() ? 
-		    fg.getVertices("flow_entry_id", flowEntryId.toString(),
-				   IFlowEntry.class).iterator().next() : null;
-	}
-
-	@Override
-	public IFlowEntry newFlowEntry(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();	
-		IFlowEntry flowEntry = fg.addVertex(null, IFlowEntry.class);
-		return flowEntry;
-	}
-
-	@Override
-	public void removeFlowEntry(GraphDBConnection conn,
-				    IFlowEntry flowEntry) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		fg.removeVertex(flowEntry.asVertex());
-	}
-
-	@Override
-        public Iterable<IFlowEntry> getAllFlowEntries(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		
-		return fg.getVertices("type", "flow_entry", IFlowEntry.class);
-	}
-	
-	@Override
-	public Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		//TODO: Should use an enum for flow_switch_state
-		return fg.getVertices("switch_state", "FE_SWITCH_NOT_UPDATED", IFlowEntry.class);
-	}
-
-	@Override
-	public Iterable<ISwitchObject> getActiveSwitches(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
-		List<ISwitchObject> activeSwitches = new ArrayList<ISwitchObject>();
-
-		for (ISwitchObject sw: switches) {
-			if(sw.getState().equals(SwitchState.ACTIVE.toString())) {
-				activeSwitches.add(sw);
-			}
-		}
-		return activeSwitches;
-	}
-
-	@Override
-	public Iterable<ISwitchObject> getAllSwitches(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
-		return switches;
-	}
-
-	@Override
-	public Iterable<ISwitchObject> getInactiveSwitches(GraphDBConnection conn) {
-		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
-		Iterable<ISwitchObject> switches =  fg.getVertices("type","switch",ISwitchObject.class);
-		List<ISwitchObject> inactiveSwitches = new ArrayList<ISwitchObject>();
-
-		for (ISwitchObject sw: switches) {
-			if(sw.getState().equals(SwitchState.INACTIVE.toString())) {
-				inactiveSwitches.add(sw);
-			}
-		}
-		return inactiveSwitches;
-	}
-
-	@Override
-	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid) {
-
-        ISwitchObject sw = searchSwitch(conn, dpid);
-        if ((sw != null) &&
-            sw.getState().equals(SwitchState.ACTIVE.toString())) {
-            return sw;
-        }
-        return null;
-	}
-}
diff --git a/src/main/java/net/onrc/onos/util/IDBUtils.java b/src/main/java/net/onrc/onos/util/IDBUtils.java
deleted file mode 100644
index 35803d2..0000000
--- a/src/main/java/net/onrc/onos/util/IDBUtils.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package net.onrc.onos.util;
-
-import net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath;
-import net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject;
-import net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject;
-import net.floodlightcontroller.util.FlowEntryId;
-import net.floodlightcontroller.util.FlowId;
-
-public interface IDBUtils {	
-	public ISwitchObject searchSwitch(GraphDBConnection conn, String dpid);
-	public ISwitchObject searchActiveSwitch(GraphDBConnection conn, String dpid);
-	public Iterable<ISwitchObject> getActiveSwitches(GraphDBConnection conn);
-	public Iterable<ISwitchObject> getAllSwitches(GraphDBConnection conn);
-	public Iterable<ISwitchObject> getInactiveSwitches(GraphDBConnection conn);
-	
-
-	public IDeviceObject searchDevice(GraphDBConnection conn, String macAddr);
-	public IDeviceObject newDevice(GraphDBConnection conn);
-	public void removeDevice(GraphDBConnection conn, IDeviceObject dev);
-	public IPortObject searchPort(GraphDBConnection conn, String dpid, short number);
-	public Iterable<IDeviceObject> getDevices(GraphDBConnection conn);
-	public IFlowPath searchFlowPath(GraphDBConnection conn, FlowId flowId);
-	public IFlowPath newFlowPath(GraphDBConnection conn);
-	public void removeFlowPath(GraphDBConnection conn, IFlowPath flowPath);
-        public IFlowPath getFlowPathByFlowEntry(GraphDBConnection conn,
-						IFlowEntry flowEntry);
-	public Iterable<IFlowPath> getAllFlowPaths(GraphDBConnection conn);
-	public IFlowEntry searchFlowEntry(GraphDBConnection conn,
-					  FlowEntryId flowEntryId);
-	public IFlowEntry newFlowEntry(GraphDBConnection conn);
-	public void removeFlowEntry(GraphDBConnection conn,
-				    IFlowEntry flowEntry);
-	public Iterable<IFlowEntry> getAllFlowEntries(GraphDBConnection conn);
-	public IPortObject newPort(GraphDBConnection conn);
-	ISwitchObject newSwitch(GraphDBConnection conn);
-	void removePort(GraphDBConnection conn, IPortObject port);
-	void removeSwitch(GraphDBConnection conn, ISwitchObject sw);
-	Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries(GraphDBConnection conn);
-}
diff --git a/src/main/python/PythonClient.py b/src/main/python/PythonClient.py
deleted file mode 100644
index 5c9890e..0000000
--- a/src/main/python/PythonClient.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-sys.path.append('../../../target/gen-py')
-
-from packetstreamer import PacketStreamer
-from packetstreamer.ttypes import *
-
-from thrift import Thrift
-from thrift.transport import TSocket
-from thrift.transport import TTransport
-from thrift.protocol import TBinaryProtocol
-
-try:
-
-    # Make socket
-    transport = TSocket.TSocket('localhost', 9090)
-
-    # Buffering is critical. Raw sockets are very slow
-    transport = TTransport.TFramedTransport(transport)
-
-    # Wrap in a protocol
-    protocol = TBinaryProtocol.TBinaryProtocol(transport)
-
-    # Create a client to use the protocol encoder
-    client = PacketStreamer.Client(protocol)
-
-    # Connect!
-    transport.open()
-
-    while 1:
-        packets = client.getPackets("session1")
-        print 'session1 packets num: %d' % (len(packets))
-        count = 1
-        for packet in packets:
-            print "Packet %d: %s"% (count, packet)
-            if "FilterTimeout" in packet:
-                sys.exit()
-            count += 1 
-
-    # Close!
-    transport.close()
-
-except Thrift.TException, tx:
-    print '%s' % (tx.message)
-
-except KeyboardInterrupt, e:
-    print 'Bye-bye'
diff --git a/src/main/python/PythonServer.py b/src/main/python/PythonServer.py
deleted file mode 100644
index c3c844e..0000000
--- a/src/main/python/PythonServer.py
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import logging
-sys.path.append('../../../target/gen-py')
-
-from packetstreamer import PacketStreamer
-from packetstreamer.ttypes import *
-
-from thrift.transport import TSocket
-from thrift.transport import TTransport
-from thrift.protocol import TBinaryProtocol
-from thrift.server import TServer
-
-class PacketStreamerHandler:
-  def __init__(self):
-    logging.handlers.codecs = None
-    self.log = logging.getLogger("packetstreamer")
-    self.log.setLevel(logging.DEBUG)
-    handler = logging.handlers.SysLogHandler("/dev/log")
-    handler.setFormatter(logging.Formatter("%(name)s: %(levelname)s %(message)s"))
-    self.log.addHandler(handler)
-
-  def ping(self):
-    self.log.debug('ping()')
-    return true
-
-  def pushPacketSync(self, packet):
-    self.log.debug('receive a packet synchronously: %s' %(packet))
-    return 0
-
-  def pushPacketAsync(self, packet):
-    self.log.debug('receive a packet Asynchronously: %s' %(packet))
-
-handler = PacketStreamerHandler()
-processor = PacketStreamer.Processor(handler)
-transport = TSocket.TServerSocket(9090)
-tfactory = TTransport.TBufferedTransportFactory()
-pfactory = TBinaryProtocol.TBinaryProtocolFactory()
-
-server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)
-
-# You could do one of these for a multithreaded server
-#server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
-#server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory)
-
-print 'Starting the server...'
-server.serve()
-print 'done.'
diff --git a/src/main/python/compileall.py b/src/main/python/compileall.py
deleted file mode 100644
index b21d95f..0000000
--- a/src/main/python/compileall.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""Module/script to "compile" all .py files to .pyc (or .pyo) file.
-
-When called as a script with arguments, this compiles the directories
-given as arguments recursively; the -l option prevents it from
-recursing into directories.
-
-Without arguments, if compiles all modules on sys.path, without
-recursing into subdirectories.  (Even though it should do so for
-packages -- for now, you'll have to deal with packages separately.)
-
-See module py_compile for details of the actual byte-compilation.
-
-"""
-
-import os
-import sys
-import py_compile
-
-__all__ = ["compile_dir","compile_path"]
-
-def compile_dir(dir, maxlevels=10, ddir=None,
-                force=0, rx=None, quiet=0):
-    """Byte-compile all modules in the given directory tree.
-
-    Arguments (only dir is required):
-
-    dir:       the directory to byte-compile
-    maxlevels: maximum recursion level (default 10)
-    ddir:      if given, purported directory name (this is the
-               directory name that will show up in error messages)
-    force:     if 1, force compilation, even if timestamps are up-to-date
-    quiet:     if 1, be quiet during compilation
-
-    """
-    if not quiet:
-        print 'Listing', dir, '...'
-    try:
-        names = os.listdir(dir)
-    except os.error:
-        print "Can't list", dir
-        names = []
-    names.sort()
-    success = 1
-    for name in names:
-        fullname = os.path.join(dir, name)
-        if ddir is not None:
-            dfile = os.path.join(ddir, name)
-        else:
-            dfile = None
-        if rx is not None:
-            mo = rx.search(fullname)
-            if mo:
-                continue
-        if os.path.isfile(fullname):
-            head, tail = name[:-3], name[-3:]
-            if tail == '.py':
-                cfile = fullname + (__debug__ and 'c' or 'o')
-                ftime = os.stat(fullname).st_mtime
-                try: ctime = os.stat(cfile).st_mtime
-                except os.error: ctime = 0
-                if (ctime > ftime) and not force: continue
-                if not quiet:
-                    print 'Compiling', fullname, '...'
-                try:
-                    ok = py_compile.compile(fullname, None, dfile, True)
-                except KeyboardInterrupt:
-                    raise KeyboardInterrupt
-                except py_compile.PyCompileError,err:
-                    if quiet:
-                        print 'Compiling', fullname, '...'
-                    print err.msg
-                    success = 0
-                except IOError, e:
-                    print "Sorry", e
-                    success = 0
-                else:
-                    if ok == 0:
-                        success = 0
-        elif maxlevels > 0 and \
-             name != os.curdir and name != os.pardir and \
-             os.path.isdir(fullname) and \
-             not os.path.islink(fullname):
-            if not compile_dir(fullname, maxlevels - 1, dfile, force, rx, quiet):
-                success = 0
-    return success
-
-def compile_path(skip_curdir=1, maxlevels=0, force=0, quiet=0):
-    """Byte-compile all module on sys.path.
-
-    Arguments (all optional):
-
-    skip_curdir: if true, skip current directory (default true)
-    maxlevels:   max recursion level (default 0)
-    force: as for compile_dir() (default 0)
-    quiet: as for compile_dir() (default 0)
-
-    """
-    success = 1
-    for dir in sys.path:
-        if (not dir or dir == os.curdir) and skip_curdir:
-            print 'Skipping current directory'
-        else:
-            success = success and compile_dir(dir, maxlevels, None,
-                                              force, quiet=quiet)
-    return success
-
-def main():
-    """Script main program."""
-    import getopt
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], 'lfqd:x:')
-    except getopt.error, msg:
-        print msg
-        print "usage: python compileall.py [-l] [-f] [-q] [-d destdir] " \
-              "[-x regexp] [directory ...]"
-        print "-l: don't recurse down"
-        print "-f: force rebuild even if timestamps are up-to-date"
-        print "-q: quiet operation"
-        print "-d destdir: purported directory name for error messages"
-        print "   if no directory arguments, -l sys.path is assumed"
-        print "-x regexp: skip files matching the regular expression regexp"
-        print "   the regexp is search for in the full path of the file"
-        sys.exit(2)
-    maxlevels = 10
-    ddir = None
-    force = 0
-    quiet = 0
-    rx = None
-    for o, a in opts:
-        if o == '-l': maxlevels = 0
-        if o == '-d': ddir = a
-        if o == '-f': force = 1
-        if o == '-q': quiet = 1
-        if o == '-x':
-            import re
-            rx = re.compile(a)
-    if ddir:
-        if len(args) != 1:
-            print "-d destdir require exactly one directory argument"
-            sys.exit(2)
-    success = 1
-    try:
-        if args:
-            for dir in args:
-                if not compile_dir(dir, maxlevels, ddir,
-                                   force, rx, quiet):
-                    success = 0
-        else:
-            success = compile_path()
-    except KeyboardInterrupt:
-        print "\n[interrupt]"
-        success = 0
-    return success
-
-if __name__ == '__main__':
-    exit_status = int(not main())
-    sys.exit(exit_status)
diff --git a/src/main/python/debugserver.py b/src/main/python/debugserver.py
deleted file mode 100644
index d8c81f9..0000000
--- a/src/main/python/debugserver.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-from threading import currentThread
-from SocketServer import BaseRequestHandler, TCPServer
-from code import InteractiveConsole
-
-_locals = None
-
-class DebugLogger(object):
-    def do_print(self, *args):
-        for i in args:
-            print i,
-        print
-    info = do_print
-    warn = do_print
-    debug = do_print
-_log = DebugLogger()
-
-
-class DebugConsole(InteractiveConsole):
-    def __init__(self, request):
-        self.request = request
-        InteractiveConsole.__init__(self, _locals)
-
-    def raw_input(self, prompt):
-        self.request.send(prompt)
-        data = self.request.recv(10000).rstrip()
-        if len(data) == 1 and ord(data[0]) == 4:
-            sys.exit()
-        return data
-
-    def write(self, data):
-        self.request.send(str(data))
-
-    def write_nl(self, data):
-        self.write(str(data)+"\r\n")
-
-class DebugServerHandler(BaseRequestHandler):
-    def __init__(self, request, client_address, server):
-        currentThread()._thread.setName("debugserver-%s:%d" % client_address)
-        _log.debug('Open connection to DebugServer from %s:%d' % client_address)
-        BaseRequestHandler.__init__(self, request, client_address, server)
-
-    def handle(self):
-        console = DebugConsole(self.request)
-        sys.displayhook = console.write_nl
-        console.interact('DebugServer')
-        self.request.close()
-
-class DebugServer(TCPServer):
-    daemon_threads = True
-    allow_reuse_address = True
-
-    def handle_error(self, request, client_address):
-        _log.debug('Closing connection to DebugServer from %s:%d' % client_address)
-        request.close()
-
-def run_server(port=6655, host='0.0.0.0', locals=locals()):
-    currentThread()._thread.setName("debugserver-main")
-
-    global _locals
-    _locals = locals
-    if "log" in locals.keys():
-        global _log
-        _log = locals["log"]
-
-    _log.info("Starting DebugServer on port %d" % port)
-    server = DebugServer(('', port), DebugServerHandler)
-    try:
-        server.serve_forever()
-    except KeyboardInterrupt:
-        pass
-
-if __name__ == "__main__":
-    run_server()
diff --git a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
index b4b4f27..a9ff0b8 100644
--- a/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
+++ b/src/main/resources/META-INF/services/net.floodlightcontroller.core.module.IFloodlightModule
@@ -1,31 +1,25 @@
 net.floodlightcontroller.core.FloodlightProvider
 net.floodlightcontroller.storage.memory.MemoryStorageSource
 net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl
-net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager
+net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager
 net.floodlightcontroller.topology.TopologyManager
 net.floodlightcontroller.forwarding.Forwarding
 net.floodlightcontroller.flowcache.FlowReconcileManager
-net.floodlightcontroller.core.OFMessageFilterManager
 net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher
 net.floodlightcontroller.perfmon.PktInProcessingTime
 net.floodlightcontroller.perfmon.NullPktInProcessingTime
 net.floodlightcontroller.restserver.RestApiServer
-net.floodlightcontroller.learningswitch.LearningSwitch
-net.floodlightcontroller.hub.Hub
-net.floodlightcontroller.jython.JythonDebugInterface
 net.floodlightcontroller.counter.CounterStore
 net.floodlightcontroller.counter.NullCounterStore
 net.floodlightcontroller.threadpool.ThreadPool
 net.floodlightcontroller.ui.web.StaticWebRoutable
-net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter
 net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier
 net.floodlightcontroller.devicemanager.test.MockDeviceManager
 net.floodlightcontroller.core.test.MockFloodlightProvider
 net.floodlightcontroller.core.test.MockThreadPoolService
-net.floodlightcontroller.firewall.Firewall
-net.floodlightcontroller.onoslistener.OnosPublisher
-net.floodlightcontroller.flowcache.FlowManager
-net.floodlightcontroller.routing.TopoRouteService
-net.floodlightcontroller.bgproute.BgpRoute
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher
+net.onrc.onos.ofcontroller.flowmanager.FlowManager
+net.onrc.onos.ofcontroller.routing.TopoRouteService
+net.onrc.onos.ofcontroller.bgproute.BgpRoute
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.onrc.onos.registry.controller.StandaloneRegistry
diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties
index 9e4fc02..8decafb 100644
--- a/src/main/resources/floodlightdefault.properties
+++ b/src/main/resources/floodlightdefault.properties
@@ -6,12 +6,12 @@
 net.floodlightcontroller.counter.CounterStore,\
 net.floodlightcontroller.perfmon.PktInProcessingTime,\
 net.floodlightcontroller.ui.web.StaticWebRoutable,\
-net.floodlightcontroller.onoslistener.OnosPublisher, \
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher, \
 net.onrc.onos.registry.controller.ZookeeperRegistry
 net.floodlightcontroller.restserver.RestApiServer.port = 8080
 net.floodlightcontroller.core.FloodlightProvider.openflowport = 6633
 net.floodlightcontroller.jython.JythonDebugInterface.port = 6655
 net.floodlightcontroller.forwarding.Forwarding.idletimeout = 5
 net.floodlightcontroller.forwarding.Forwarding.hardtimeout = 0
-net.floodlightcontroller.onoslistener.OnosPublisher.dbconf = /tmp/cassandra.titan
-net.floodlightcontroller.onoslistener.OnosPublisher.EnableCleanup = True
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.dbconf = /tmp/cassandra.titan
+net.onrc.onos.ofcontroller.floodlightlistener.NetworkGraphPublisher.EnableCleanup = True
diff --git a/src/main/thrift/packetstreamer.thrift b/src/main/thrift/packetstreamer.thrift
deleted file mode 100644
index 827dd85..0000000
--- a/src/main/thrift/packetstreamer.thrift
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-# Interface definition for packetstreamer service
-#
-
-namespace java net.floodlightcontroller.packetstreamer.thrift 
-namespace cpp net.floodlightcontroller.packetstreamer
-namespace py packetstreamer
-namespace php packetstreamer
-namespace perl packetstreamer
-
-const string VERSION = "0.1.0"
-
-#
-# data structures
-#
-
-/**
- * OFMessage type
- **/
-enum OFMessageType {
-  HELLO = 0,
-  ERROR = 1,
-  ECHO_REQUEST = 2,
-  ECHO_REPLY = 3,
-  VENDOR = 4,
-  FEATURES_REQUEST = 5,
-  FEATURES_REPLY = 6,
-  GET_CONFIG_REQUEST = 7,
-  GET_CONFIG_REPLY = 8,
-  SET_CONFIG = 9,
-  PACKET_IN = 10,
-  FLOW_REMOVED = 11,
-  PORT_STATUS = 12,
-  PACKET_OUT = 13,
-  FLOW_MOD = 14,
-  PORT_MOD = 15,
-  STATS_REQUEST = 16,
-  STATS_REPLY = 17,
-  BARRIER_REQUEST = 18,
-  BARRIER_REPLY = 19,
-}
-
-/**
- * A struct that defines switch port tuple
- */
-struct SwitchPortTuple {
-  1: i64 dpid,
-  2: i16 port,
-}
-
-struct Packet {
-  1: OFMessageType messageType,
-  2: SwitchPortTuple swPortTuple,
-  3: binary data,
-}
-
-struct Message {
-  1: list<string> sessionIDs,
-  2: Packet packet,
-}
-
-/**
- * Packetstreamer API
- */
-service PacketStreamer {
-
-   /**
-    * Synchronous method to get packets for a given sessionid
-    */
-   list<binary> getPackets(1:string sessionid),
-
-   /**
-    * Synchronous method to publish a packet.
-    * It ensure the order that the packets are pushed
-    */
-   i32 pushMessageSync(1:Message packet),
-
-   /** 
-    * Asynchronous method to publish a packet.
-    * Order is not guaranteed.
-    */
-   oneway void pushMessageAsync(1:Message packet)
-
-   /** 
-    * Terminate a session
-    */
-   void terminateSession(1:string sessionid)
-}
diff --git a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
index a6948c0..ecdc2d7 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/ControllerTest.java
@@ -17,36 +17,43 @@
 
 package net.floodlightcontroller.core.internal;
 
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.same;
+import static org.easymock.EasyMock.verify;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
-import net.floodlightcontroller.core.FloodlightProvider;
 import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.FloodlightProvider;
 import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
-import net.floodlightcontroller.core.IOFMessageFilterManagerService;
-import net.floodlightcontroller.core.IOFMessageListener;
+import net.floodlightcontroller.core.IHAListener;
 import net.floodlightcontroller.core.IListener.Command;
+import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchListener;
-import net.floodlightcontroller.core.OFMessageFilterManager;
 import net.floodlightcontroller.core.internal.Controller.IUpdate;
 import net.floodlightcontroller.core.internal.Controller.SwitchUpdate;
 import net.floodlightcontroller.core.internal.Controller.SwitchUpdateType;
 import net.floodlightcontroller.core.internal.OFChannelState.HandshakeState;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
 import net.floodlightcontroller.counter.CounterStore;
 import net.floodlightcontroller.counter.ICounterStoreService;
@@ -62,6 +69,13 @@
 import net.floodlightcontroller.storage.memory.MemoryStorageSource;
 import net.floodlightcontroller.test.FloodlightTestCase;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
+import net.onrc.onos.ofcontroller.core.IOFSwitchPortListener;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyService.ITopoRouteService;
+import net.onrc.onos.ofcontroller.flowmanager.FlowManager;
+import net.onrc.onos.ofcontroller.flowmanager.IFlowService;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.registry.controller.IControllerRegistryService;
+import net.onrc.onos.registry.controller.StandaloneRegistry;
 
 import org.easymock.Capture;
 import org.easymock.EasyMock;
@@ -72,17 +86,15 @@
 import org.openflow.protocol.OFError.OFErrorType;
 import org.openflow.protocol.OFFeaturesReply;
 import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketOut;
+import org.openflow.protocol.OFPacketIn.OFPacketInReason;
 import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.protocol.OFPort;
+import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
 import org.openflow.protocol.OFPortStatus;
+import org.openflow.protocol.OFPortStatus.OFPortReason;
 import org.openflow.protocol.OFStatisticsReply;
 import org.openflow.protocol.OFType;
-import org.openflow.protocol.OFPacketIn.OFPacketInReason;
-import org.openflow.protocol.OFPortStatus.OFPortReason;
 import org.openflow.protocol.OFVendor;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
 import org.openflow.protocol.factory.BasicFactory;
 import org.openflow.protocol.statistics.OFFlowStatisticsReply;
 import org.openflow.protocol.statistics.OFStatistics;
@@ -124,16 +136,26 @@
         tp = new MockThreadPoolService();
         fmc.addService(IThreadPoolService.class, tp);
         
+        // Following added by ONOS
+        // TODO replace with mock if further testing is needed.
+        fmc.addService(IFlowService.class, new FlowManager() );
+        fmc.addService(ITopoRouteService.class, new TopoRouteService() );
+        StandaloneRegistry sr = new StandaloneRegistry();
+        fmc.addService(IControllerRegistryService.class, sr );
+
+        
         ppt.init(fmc);
         restApi.init(fmc);
         memstorage.init(fmc);
         cm.init(fmc);
         tp.init(fmc);
+        sr.init(fmc);
         ppt.startUp(fmc);
         restApi.startUp(fmc);
         memstorage.startUp(fmc);
         cm.startUp(fmc);
         tp.startUp(fmc);
+        sr.startUp(fmc);
     }
 
     public Controller getController() {
@@ -359,125 +381,6 @@
     }
 
     @Test
-    public void testMessageFilterManager() throws Exception {
-        class MyOFMessageFilterManager extends OFMessageFilterManager {
-            public MyOFMessageFilterManager(int timer_interval) {
-                super();
-                TIMER_INTERVAL = timer_interval;
-            }
-        }
-        FloodlightModuleContext fmCntx = new FloodlightModuleContext();
-        MockFloodlightProvider mfp = new MockFloodlightProvider();
-        OFMessageFilterManager mfm = new MyOFMessageFilterManager(100);
-        MockThreadPoolService mtp = new MockThreadPoolService();
-        fmCntx.addService(IOFMessageFilterManagerService.class, mfm);
-        fmCntx.addService(IFloodlightProviderService.class, mfp);
-        fmCntx.addService(IThreadPoolService.class, mtp);
-        String sid = null;
-        
-        mfm.init(fmCntx);
-        mfm.startUp(fmCntx);
-
-        ConcurrentHashMap <String, String> filter;
-        int i;
-
-        //Adding the filter works -- adds up to the maximum filter size.
-        for(i=mfm.getMaxFilterSize(); i > 0; --i) {
-            filter = new ConcurrentHashMap<String,String>();
-            filter.put("mac", String.format("00:11:22:33:44:%d%d", i,i));
-            sid = mfm.setupFilter(null, filter, 60);
-            assertTrue(mfm.getNumberOfFilters() == mfm.getMaxFilterSize() - i +1);
-        }
-
-        // Add one more to see if you can't
-        filter = new ConcurrentHashMap<String,String>();
-        filter.put("mac", "mac2");
-        mfm.setupFilter(null, filter, 10*1000);
-
-        assertTrue(mfm.getNumberOfFilters() == mfm.getMaxFilterSize());
-
-        // Deleting the filter works.
-        mfm.setupFilter(sid, null, -1);        
-        assertTrue(mfm.getNumberOfFilters() == mfm.getMaxFilterSize()-1);
-
-        // Creating mock switch to which we will send packet out and 
-        IOFSwitch sw = createMock(IOFSwitch.class);
-        expect(sw.getId()).andReturn(new Long(0));
-
-        // Mock Packet-in   
-        IPacket testPacket = new Ethernet()
-        .setSourceMACAddress("00:44:33:22:11:00")
-        .setDestinationMACAddress("00:11:22:33:44:55")
-        .setEtherType(Ethernet.TYPE_ARP)
-        .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setHardwareAddressLength((byte) 6)
-                .setProtocolAddressLength((byte) 4)
-                .setOpCode(ARP.OP_REPLY)
-                .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
-                .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
-                .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
-                .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
-        byte[] testPacketSerialized = testPacket.serialize();
-
-        // Build the PacketIn        
-        OFPacketIn pi = ((OFPacketIn) new BasicFactory().getMessage(OFType.PACKET_IN))
-                .setBufferId(-1)
-                .setInPort((short) 1)
-                .setPacketData(testPacketSerialized)
-                .setReason(OFPacketInReason.NO_MATCH)
-                .setTotalLength((short) testPacketSerialized.length);
-
-        // Mock Packet-out
-        OFPacketOut packetOut =
-                (OFPacketOut) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT);
-        packetOut.setBufferId(pi.getBufferId())
-        .setInPort(pi.getInPort());
-        List<OFAction> poactions = new ArrayList<OFAction>();
-        poactions.add(new OFActionOutput(OFPort.OFPP_TABLE.getValue(), (short) 0));
-        packetOut.setActions(poactions)
-        .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
-        .setPacketData(testPacketSerialized)
-        .setLengthU(OFPacketOut.MINIMUM_LENGTH+packetOut.getActionsLength()+testPacketSerialized.length);
-
-        FloodlightContext cntx = new FloodlightContext();
-        IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, (Ethernet) testPacket);
-
-
-        // Let's check the listeners.
-        List <IOFMessageListener> lm; 
-
-        // Check to see if all the listeners are active.
-        lm = mfp.getListeners().get(OFType.PACKET_OUT);
-        assertTrue(lm.size() == 1);
-        assertTrue(lm.get(0).equals(mfm));
-
-        lm = mfp.getListeners().get(OFType.FLOW_MOD);
-        assertTrue(lm.size() == 1);
-        assertTrue(lm.get(0).equals(mfm));
-
-        lm = mfp.getListeners().get(OFType.PACKET_IN);
-        assertTrue(lm.size() == 1);
-        assertTrue(lm.get(0).equals(mfm));
-
-        HashSet<String> matchedFilters;        
-
-        // Send a packet in and check if it matches a filter.
-        matchedFilters = mfm.getMatchedFilters(pi, cntx);
-        assertTrue(matchedFilters.size() == 1);
-
-        // Send a packet out and check if it matches a filter
-        matchedFilters = mfm.getMatchedFilters(packetOut, cntx);
-        assertTrue(matchedFilters.size() == 1);
-
-        // Wait for all filters to be timed out.
-        Thread.sleep(150);
-        assertEquals(0, mfm.getNumberOfFilters());
-    }
-
-    @Test
     public void testAddSwitch() throws Exception {
         controller.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
 
@@ -509,7 +412,6 @@
         expect(newsw.getBuffers()).andReturn(0).anyTimes();
         expect(newsw.getTables()).andReturn((byte)0).anyTimes();
         expect(newsw.getActions()).andReturn(0).anyTimes();
-        expect(newsw.getPorts()).andReturn(new ArrayList<OFPhysicalPort>());
         controller.activeSwitches.put(0L, oldsw);
         replay(newsw, channel, channel2);
 
@@ -520,7 +422,7 @@
     
     @Test
     public void testUpdateQueue() throws Exception {
-        class DummySwitchListener implements IOFSwitchListener {
+        class DummySwitchListener implements IOFSwitchListener, IOFSwitchPortListener {
             public int nAdded;
             public int nRemoved;
             public int nPortChanged;
@@ -545,6 +447,16 @@
                 nPortChanged++;
                 notifyAll();
             }
+			@Override
+			public void switchPortAdded(Long switchId, OFPhysicalPort port) {
+				// TODO Auto-generated method stub
+				
+			}
+			@Override
+			public void switchPortRemoved(Long switchId, OFPhysicalPort port) {
+				// TODO Auto-generated method stub
+				
+			}
         }
         DummySwitchListener switchListener = new DummySwitchListener();
         IOFSwitch sw = createMock(IOFSwitch.class);
@@ -752,7 +664,7 @@
         assertTrue("Check that update is HARoleUpdate", 
                    upd instanceof Controller.HARoleUpdate);
         Controller.HARoleUpdate roleUpd = (Controller.HARoleUpdate)upd;
-        assertSame(null, roleUpd.oldRole);
+        assertSame(Role.MASTER, roleUpd.oldRole);
         assertSame(Role.SLAVE, roleUpd.newRole);
     }
     
@@ -806,15 +718,16 @@
         state.hasGetConfigReply = true;
         // Role support disabled. Switch should be promoted to active switch
         // list. 
-        setupSwitchForAddSwitch(chdlr.sw, 0L);
-        chdlr.sw.clearAllFlowMods();
-        replay(controller.roleChanger, chdlr.sw);
-        chdlr.checkSwitchReady();
-        verify(controller.roleChanger, chdlr.sw);
-        assertSame(OFChannelState.HandshakeState.READY, state.hsState);
-        assertSame(chdlr.sw, controller.activeSwitches.get(0L));
-        assertTrue(controller.connectedSwitches.contains(chdlr.sw));
-        assertTrue(state.firstRoleReplyReceived);
+// FIXME: ONOS modified the behavior to always submit Role Request to trigger OFS error.
+//        setupSwitchForAddSwitch(chdlr.sw, 0L);
+//        chdlr.sw.clearAllFlowMods();
+//        replay(controller.roleChanger, chdlr.sw);
+//        chdlr.checkSwitchReady();
+//        verify(controller.roleChanger, chdlr.sw);
+//        assertSame(OFChannelState.HandshakeState.READY, state.hsState);
+//        assertSame(chdlr.sw, controller.activeSwitches.get(0L));
+//        assertTrue(controller.connectedSwitches.contains(chdlr.sw));
+//        assertTrue(state.firstRoleReplyReceived);
         reset(chdlr.sw);
         reset(controller.roleChanger);
         controller.connectedSwitches.clear();
@@ -824,9 +737,15 @@
         // Role support enabled. 
         state.hsState = OFChannelState.HandshakeState.FEATURES_REPLY;
         controller.role = Role.MASTER;
+        expect(chdlr.sw.getStringId()).andReturn("SomeID").anyTimes();
+        expect(chdlr.sw.getId()).andReturn(42L).anyTimes();
         Capture<Collection<OFSwitchImpl>> swListCapture = 
                     new Capture<Collection<OFSwitchImpl>>();
         controller.roleChanger.submitRequest(capture(swListCapture), 
+                    same(Role.SLAVE));
+        Capture<Collection<OFSwitchImpl>> swListCapture2 = 
+                new Capture<Collection<OFSwitchImpl>>();
+        controller.roleChanger.submitRequest(capture(swListCapture2), 
                     same(Role.MASTER));
         replay(controller.roleChanger, chdlr.sw);
         chdlr.checkSwitchReady();
@@ -834,7 +753,7 @@
         assertSame(OFChannelState.HandshakeState.READY, state.hsState);
         assertTrue(controller.activeSwitches.isEmpty());
         assertTrue(controller.connectedSwitches.contains(chdlr.sw));
-        assertTrue(state.firstRoleReplyReceived);
+//        assertTrue(state.firstRoleReplyReceived);
         Collection<OFSwitchImpl> swList = swListCapture.getValue();
         assertEquals(1, swList.size());
         assertTrue("swList must contain this switch", swList.contains(chdlr.sw));
@@ -930,7 +849,7 @@
         state.firstRoleReplyReceived = false;
         controller.role = Role.SLAVE;
         expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
-        chdlr.sw.deliverRoleRequestNotSupported(xid);
+        expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
         expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
         expect(ch.close()).andReturn(null);
         
@@ -950,7 +869,7 @@
         state.firstRoleReplyReceived = false;
         controller.role = Role.SLAVE;
         expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
-        chdlr.sw.deliverRoleRequestNotSupported(xid);
+        expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.SLAVE);
         expect(chdlr.sw.getChannel()).andReturn(ch).anyTimes();
         expect(ch.close()).andReturn(null);
         replay(ch, chdlr.sw);
@@ -969,7 +888,7 @@
         state.firstRoleReplyReceived = false;
         controller.role = Role.MASTER;
         expect(chdlr.sw.checkFirstPendingRoleRequestXid(xid)).andReturn(true);
-        chdlr.sw.deliverRoleRequestNotSupported(xid);
+        expect(chdlr.sw.deliverRoleRequestNotSupportedEx(xid)).andReturn(Role.MASTER);
         setupSwitchForAddSwitch(chdlr.sw, 0L);
         chdlr.sw.clearAllFlowMods();
         replay(ch, chdlr.sw);
@@ -1207,6 +1126,26 @@
         assertEquals(SwitchUpdateType.PORTCHANGED, swUpdate.switchUpdateType);
     }
     
+    public void verifyPortAddedUpdateInQueue(IOFSwitch sw) throws Exception {
+        assertEquals(2, controller.updates.size());
+        IUpdate update = controller.updates.take();
+        assertEquals(true, update instanceof SwitchUpdate);
+        SwitchUpdate swUpdate = (SwitchUpdate)update;
+        assertEquals(sw, swUpdate.sw);
+        assertEquals(SwitchUpdateType.PORTADDED, swUpdate.switchUpdateType);
+        verifyPortChangedUpdateInQueue(sw);
+    }
+    
+    public void verifyPortRemovedUpdateInQueue(IOFSwitch sw) throws Exception {
+        assertEquals(2, controller.updates.size());
+        IUpdate update = controller.updates.take();
+        assertEquals(true, update instanceof SwitchUpdate);
+        SwitchUpdate swUpdate = (SwitchUpdate)update;
+        assertEquals(sw, swUpdate.sw);
+        assertEquals(SwitchUpdateType.PORTREMOVED, swUpdate.switchUpdateType);
+        verifyPortChangedUpdateInQueue(sw);
+    }
+    
     /*
      * Test handlePortStatus()
      * TODO: test correct updateStorage behavior!
@@ -1227,25 +1166,51 @@
         replay(sw);
         controller.handlePortStatusMessage(sw, ofps, false);
         verify(sw);
-        verifyPortChangedUpdateInQueue(sw);
+        verifyPortAddedUpdateInQueue(sw);
         reset(sw);
         
+        // ONOS:Port is considered added if Link state is not down and not configured to be down
         ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
         sw.setPort(port);
         expectLastCall().once();
         replay(sw);
         controller.handlePortStatusMessage(sw, ofps, false);
         verify(sw);
-        verifyPortChangedUpdateInQueue(sw);
+        verifyPortAddedUpdateInQueue(sw);
         reset(sw);
         
+        // ONOS:Port is considered removed if Link state is down
+        ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
+        port.setState(OFPortState.OFPPS_LINK_DOWN.getValue());
+        sw.setPort(port);
+        expectLastCall().once();
+        replay(sw);
+        controller.handlePortStatusMessage(sw, ofps, false);
+        verify(sw);
+        verifyPortRemovedUpdateInQueue(sw);
+        reset(sw);
+        port.setState(0);// reset
+        
+        // ONOS: .. or is configured to be down
+        ofps.setReason((byte)OFPortReason.OFPPR_MODIFY.ordinal());
+        port.setConfig(OFPortConfig.OFPPC_PORT_DOWN.getValue());
+        sw.setPort(port);
+        expectLastCall().once();
+        replay(sw);
+        controller.handlePortStatusMessage(sw, ofps, false);
+        verify(sw);
+        verifyPortRemovedUpdateInQueue(sw);
+        reset(sw);
+        port.setConfig(0);// reset
+        
+        
         ofps.setReason((byte)OFPortReason.OFPPR_DELETE.ordinal());
         sw.deletePort(port.getPortNumber());
         expectLastCall().once();
         replay(sw);
         controller.handlePortStatusMessage(sw, ofps, false);
         verify(sw);
-        verifyPortChangedUpdateInQueue(sw);
+        verifyPortRemovedUpdateInQueue(sw);
         reset(sw);
     }
 }
diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchImplTest.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchImplTest.java
index 758cd05..128c09f 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchImplTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchImplTest.java
@@ -197,7 +197,7 @@
         sw.role = Role.SLAVE;
         sw.pendingRoleRequests.add(pending);
         replay(sw.channel);
-        sw.deliverRoleRequestNotSupported(pending.xid);
+        sw.deliverRoleRequestNotSupportedEx(pending.xid);
         verify(sw.channel);
         assertEquals(false, sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE));
         assertEquals(null, sw.role);
@@ -210,7 +210,7 @@
         sw.role = Role.SLAVE;
         expect(sw.channel.close()).andReturn(null);
         replay(sw.channel);
-        sw.deliverRoleRequestNotSupported(1);
+        sw.deliverRoleRequestNotSupportedEx(1);
         verify(sw.channel);
         assertEquals(null, sw.role);
         assertEquals(0, sw.pendingRoleRequests.size());
@@ -228,7 +228,7 @@
         sw.pendingRoleRequests.add(pending);
         expect(sw.channel.close()).andReturn(null);
         replay(sw.channel);
-        sw.deliverRoleRequestNotSupported(pending.xid+1);
+        sw.deliverRoleRequestNotSupportedEx(pending.xid+1);
         verify(sw.channel);
         assertEquals(null, sw.role);
         assertEquals(0, sw.pendingRoleRequests.size());
diff --git a/src/test/java/net/floodlightcontroller/core/internal/RoleChangeCallbackTest.java b/src/test/java/net/floodlightcontroller/core/internal/RoleChangeCallbackTest.java
new file mode 100644
index 0000000..2aeb60e
--- /dev/null
+++ b/src/test/java/net/floodlightcontroller/core/internal/RoleChangeCallbackTest.java
@@ -0,0 +1,143 @@
+package net.floodlightcontroller.core.internal;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+// Extends Controller class to access protected inner class
+public class RoleChangeCallbackTest extends Controller {
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	/**
+	 * Test if {@link RoleChangeCallback#controlChanged(long, boolean)} correctly calls {@link RoleChanger#submitRequest(Collection, net.floodlightcontroller.core.IFloodlightProviderService.Role)}
+	 * when connectedSwitch is not empty.
+	 * @throws Exception
+	 */
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testNormalSwitches() throws Exception {
+		Long [] dpids = new Long [] { 1000L, 1001L, 1002L, 1003L };
+		final long dpidExist = 1000L;
+		final long dpidNotExist = 2000L;
+		
+		roleChanger = EasyMock.createMock(RoleChanger.class);
+		
+		// First call will be called with (dpidExist,true)
+		roleChanger.submitRequest(EasyMock.anyObject(Collection.class), EasyMock.anyObject(Role.class));
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+			@Override
+			public Object answer() throws Throwable {
+				Collection<OFSwitchImpl> switches = (Collection<OFSwitchImpl>)EasyMock.getCurrentArguments()[0];
+				Role role = (Role)EasyMock.getCurrentArguments()[1];
+
+				List<Long> dpids = new ArrayList<Long>();
+				
+				for(OFSwitchImpl sw : switches) {
+					dpids.add(sw.getId());
+				}
+				assertTrue(dpids.contains(dpidExist));
+				assertEquals(role, Role.MASTER);
+				
+				return null;
+			}
+		}).once();
+
+		// Second call will be called with (dpidExist,false)
+		roleChanger.submitRequest(EasyMock.anyObject(Collection.class), EasyMock.anyObject(Role.class));
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+			@Override
+			public Object answer() throws Throwable {
+				Collection<OFSwitchImpl> switches = (Collection<OFSwitchImpl>)EasyMock.getCurrentArguments()[0];
+				Role role = (Role)EasyMock.getCurrentArguments()[1];
+
+				List<Long> dpids = new ArrayList<Long>();
+				
+				for(OFSwitchImpl sw : switches) {
+					dpids.add(sw.getId());
+				}
+				assertTrue(dpids.contains(dpidExist));
+				assertEquals(role, Role.SLAVE);
+				
+				return null;
+			}
+		}).once();
+
+		EasyMock.replay(roleChanger);
+		
+		initNetwork(roleChanger, dpids);
+		
+		RoleChangeCallback callback = new RoleChangeCallback();
+		callback.controlChanged(dpidExist, true);
+		callback.controlChanged(dpidExist, false);
+		callback.controlChanged(dpidNotExist, true);
+		callback.controlChanged(dpidNotExist, false);
+		
+		EasyMock.verify(roleChanger);
+	}
+
+	/**
+	 * Test if {@link RoleChangeCallback#controlChanged(long, boolean)} doesn't call RoleChanger methods
+	 * when connectedSwitch is empty.
+	 * @throws Exception
+	 */
+	@Test
+	public void testEmptySwitches() throws Exception {
+		Long [] dpids = new Long [] {};
+		final long dpidToTest = 1000L;
+		
+		roleChanger = EasyMock.createMock(RoleChanger.class);
+		// roleChanger methods must not be used
+		EasyMock.replay(roleChanger);
+		
+		initNetwork(roleChanger, dpids);
+		
+		RoleChangeCallback callback = new RoleChangeCallback();
+		callback.controlChanged(dpidToTest, true);
+		callback.controlChanged(dpidToTest, false);
+		
+		EasyMock.verify(roleChanger);
+	}
+	
+	/**
+	 * Create mock OFSwitchImpl object.
+	 * @param id
+	 * @return
+	 */
+	private OFSwitchImpl createOFSwitchImplMock(Long id) {
+		OFSwitchImpl sw = EasyMock.createMock(OFSwitchImpl.class);
+
+		EasyMock.expect(sw.getId()).andReturn(id).anyTimes();
+		EasyMock.replay(sw);
+		
+		return sw;
+	}
+	
+	/**
+	 * Setup connectedSwitches
+	 * @param changer
+	 * @param ids
+	 * @throws Exception
+	 */
+	private void initNetwork(RoleChanger changer, Long [] ids) throws Exception {
+		connectedSwitches = new HashSet<OFSwitchImpl>();
+		
+		for(Long id : ids) {
+			connectedSwitches.add(createOFSwitchImplMock(id));
+		}
+	}
+}
diff --git a/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java b/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java
index 991afff..a6a6d85 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/RoleChangerTest.java
@@ -16,6 +16,7 @@
 import org.easymock.EasyMock;
 import org.jboss.netty.channel.Channel;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 public class RoleChangerTest {
@@ -58,6 +59,7 @@
      * The connection should be closed.
      */
     @Test
+    @Ignore // FIXME: ONOS modified the behavior here to intentionally trigger OFS error.
     public void testSendRoleRequestMasterNotSupported() {
         LinkedList<OFSwitchImpl> switches = new LinkedList<OFSwitchImpl>();
         
diff --git a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java b/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
deleted file mode 100644
index a187d4c..0000000
--- a/src/test/java/net/floodlightcontroller/core/internal/SwitchStorageImplTest.java
+++ /dev/null
@@ -1,278 +0,0 @@
-package net.floodlightcontroller.core.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-import net.floodlightcontroller.core.ISwitchStorage;
-import net.floodlightcontroller.core.ISwitchStorage.SwitchState;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.openflow.protocol.OFPhysicalPort;
-
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.gremlin.java.GremlinPipeline;
-import com.tinkerpop.pipes.PipeFunction;
-import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
-
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptException;
-import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
-
-
-public class SwitchStorageImplTest {
-
-	private ISwitchStorage switchStorage;
-	private TitanGraph titanGraph;
-	
-	@Before
-	public void setUp() throws Exception {
-		titanGraph = TestDatabaseManager.getTestDatabase();
-		TestDatabaseManager.populateTestData(titanGraph);
-		
-		switchStorage = new TestableSwitchStorageImpl();
-	}
-
-	@After
-	public void tearDown() throws Exception {
-		titanGraph.shutdown();
-	}
-
-	@Ignore @Test
-	public void testUpdate() {
-		fail("Not yet implemented");
-	}
-
-	@Test
-	public void testAddPort() {
-		
-		String dpid = "00:00:00:00:00:00:0a:01";
-		short portNumber = 5;
-		
-		OFPhysicalPort portToAdd = new OFPhysicalPort();
-		portToAdd.setName("port 5 at SEA switch");
-		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
-		portToAdd.setPortNumber(portNumber);
-		
-		switchStorage.addPort(dpid, portToAdd);
-		
-		Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
-		
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		pipe.start(sw).out("on").has("number", portNumber);
-		
-		assertTrue(pipe.hasNext());
-		Vertex addedPort = pipe.next();
-		assertFalse(pipe.hasNext());
-		
-		assertEquals(addedPort.getProperty("number"), portNumber);
-	}
-
-	@Ignore @Test
-	public void testGetPorts() {
-		fail("Not yet implemented");
-	}
-
-	@Ignore @Test
-	public void testGetPortStringShort() {
-		fail("Not yet implemented");
-	}
-
-	@Ignore @Test
-	public void testGetPortStringString() {
-		fail("Not yet implemented");
-	}
-
-	@Test
-	public void testAddSwitch() {
-		String dpid = "00:00:00:00:00:00:0a:07";
-		
-		switchStorage.addSwitch(dpid);
-		
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
-		assertTrue(it.hasNext());
-		Vertex addedSwitch = it.next();
-		assertFalse(it.hasNext());
-		
-		assertEquals(addedSwitch.getProperty("type"), "switch");
-		assertEquals(addedSwitch.getProperty("dpid"), dpid);
-		assertEquals(addedSwitch.getProperty("state"), SwitchState.ACTIVE.toString());
-	}
-
-	
-	@Test
-	public void testDeleteSwitch() {
-		String dpid = "00:00:00:00:00:00:0a:01";
-		
-		switchStorage.deleteSwitch(dpid);
-		
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
-		assertFalse(it.hasNext());
-	}
-
-	@Test
-	public void testDeletePortByPortNum() {
-		//FIXME fails because query for the port is wrong in SwitchStorageImpl
-		
-		String dpid = "00:00:00:00:00:00:0a:01";
-		short portNum = 3;
-		
-		switchStorage.deletePort(dpid, portNum);
-		
-		Vertex sw = titanGraph.getVertices("dpid", dpid).iterator().next();
-		
-		/*
-		Iterator<Vertex> it = sw.getVertices(Direction.OUT, "on").iterator();
-		
-		while (it.hasNext()){
-			System.out.println(it.next());
-		}
-		*/
-		
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		pipe.start(sw).out("on").has("number", portNum);
-		assertFalse(pipe.hasNext());
-	}
-
-	@Ignore @Test
-	public void testDeletePortStringString() {
-		fail("Not yet implemented");
-	}
-
-	@Ignore @Test
-	public void testGetActiveSwitches() {
-		fail("Not yet implemented");
-	}
-
-	static class MyLoopFunction implements PipeFunction<LoopBundle<Vertex>, Boolean> {
-	    String dpid;
-	    public MyLoopFunction(String dpid) {
-		super();
-		this.dpid = dpid;
-	    }
-	    public Boolean compute(LoopBundle<Vertex> bundle) {
-		Boolean output = false;
-		if (! bundle.getObject().getProperty("dpid").equals(dpid)) {
-		    output = true;
-		}
-		return output;
-	    }
-	}
-
-	@Test
-	public void testShortestPath() {
-	    String dpid_src = "00:00:00:00:00:00:0a:01";
-	    String dpid_dest = "00:00:00:00:00:00:0a:06";
-
-	    //
-	    // Implement the Shortest Path between two vertices by using
-	    // the following Gremlin CLI code:
-	    //   v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path(){it.dpid}{it.number}{it.number}
-	    // The equivalent code used here is:
-	    //   results = []; v_src.as("x").out("on").out("link").in("on").dedup().loop("x"){it.object.dpid != v_dest.dpid}.path().fill(results)
-	    //
-
-	    // Get the source vertex
-	    Iterator<Vertex> iter = titanGraph.getVertices("dpid", dpid_src).iterator();
-	    if (! iter.hasNext())
-		return;			// Source vertex not found
-	    Vertex v_src = iter.next();
-
-	    // Get the destination vertex
-	    iter = titanGraph.getVertices("dpid", dpid_dest).iterator();
-	    if (! iter.hasNext())
-		return;			// Destination vertex not found
-	    Vertex v_dest = iter.next();
-
-	    //
-	    // Implement the Gremlin script and run it
-	    //
-	    // NOTE: This mechanism is slower. The code is kept here
-	    // for future reference.
-	    //
-	    /*
-	    String gremlin = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != v_dest.dpid}.path().fill(results)";
-
-	    String gremlin_nopath = "v_src.as(\"x\").out(\"on\").out(\"link\").in(\"on\").dedup().loop(\"x\"){it.object.dpid != \"NO-SUCH-DPID\"}.path().fill(results)";
-
-	    ScriptEngine engine = new GremlinGroovyScriptEngine();
-	    ArrayList<ArrayList<Vertex>> results = new ArrayList<ArrayList<Vertex>>();
-	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("g", titanGraph);
-	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_src", v_src);
-	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("v_dest", v_dest);
-	    engine.getBindings(ScriptContext.ENGINE_SCOPE).put("results", results);
-
-	    try {
-		engine.eval(gremlin);
-	    } catch (ScriptException e) {
-		System.err.println("Caught ScriptException running Gremlin script: " + e.getMessage());
-		return;
-	    }
-
-	    for (ArrayList<Vertex> lv : results) {
-		...
-	    }
-	    */
-
-	    MyLoopFunction whileFunction = new MyLoopFunction(dpid_dest);
-	    GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-	    Collection<List> results = new ArrayList<List>();
-	    GremlinPipeline<Vertex, List> path;
-	    path = pipe.start(v_src).as("x").out("on").out("link").in("on").dedup().loop("x", whileFunction).path();
-	    path.fill(results);
-
-	    //
-	    // Extract the result and compose it into a string
-	    //
-	    String results_str = "";
-	    // System.out.println("BEGIN " + results.size());
-	    for (List l : results) {
-		for (Object o: l) {
-		    Vertex v = (Vertex)(o);
-		    // System.out.println(v);
-		    String type = v.getProperty("type").toString();
-		    results_str += "[type: " + type;
-		    // System.out.println("type: " + type);
-		    if (type.equals("port")) {
-			String number = v.getProperty("number").toString();
-			// System.out.println("number: " + number);
-			results_str += " number: " + number + "]";
-		    }
-		    if (type.equals("switch")) {
-			String dpid = v.getProperty("dpid").toString();
-			// System.out.println("dpid: " + dpid);
-			results_str += " dpid: " + dpid + "]";
-		    }
-		}
-	    }
-	    // System.out.println("END\n");
-	    System.out.println(results_str);
-
-	    //
-	    // Check the result
-	    //
-	    String expected_result = "[type: switch dpid: 00:00:00:00:00:00:0a:01][type: port number: 2][type: port number: 1][type: switch dpid: 00:00:00:00:00:00:0a:03][type: port number: 2][type: port number: 2][type: switch dpid: 00:00:00:00:00:00:0a:04][type: port number: 3][type: port number: 1][type: switch dpid: 00:00:00:00:00:00:0a:06]";
-
-	    assertEquals(results_str, expected_result);
-
-	    //
-	    // Test Shortest-Path computation to non-existing destination
-	    //
-	    results.clear();
-	    MyLoopFunction noDestWhileFunction = new MyLoopFunction("NO-SUCH-DPID");
-	    path = pipe.start(v_src).as("x").out("on").out("link").in("on").dedup().loop("x", noDestWhileFunction).path();
-	    path.fill(results);
-	    assertTrue(results.size() == 0);
-	}
-}
diff --git a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
index 3d5e03b..f811c9d 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
+++ b/src/test/java/net/floodlightcontroller/core/internal/TestDatabaseManager.java
@@ -58,8 +58,17 @@
         Iterator<Vertex> it = titanGraph.getVertices("type", "port").iterator();
         while (it.hasNext()){
         	Vertex port = it.next();
-        	Integer portNum = (Integer) port.getProperty("number");
-        	port.setProperty("number", portNum.shortValue());
+
+        	if(port.getProperty("number") instanceof Short)
+        	{
+        		Short portNum = (Short) port.getProperty("number");
+        		port.setProperty("number", portNum.shortValue());
+        	}
+        	else{
+        		Integer portNum = (Integer) port.getProperty("number");	
+        		port.setProperty("number", portNum.shortValue());
+        	}
+
         }
         titanGraph.stopTransaction(Conclusion.SUCCESS);
 	}
diff --git a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java
deleted file mode 100644
index 959bb49..0000000
--- a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java
+++ /dev/null
@@ -1,513 +0,0 @@
-package net.floodlightcontroller.firewall;
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.module.FloodlightModuleException;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
-import net.floodlightcontroller.packet.ARP;
-import net.floodlightcontroller.packet.Data;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.packet.TCP;
-import net.floodlightcontroller.packet.UDP;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.restserver.RestApiServer;
-import net.floodlightcontroller.routing.IRoutingDecision;
-import net.floodlightcontroller.storage.IStorageSourceService;
-import net.floodlightcontroller.storage.memory.MemoryStorageSource;
-import net.floodlightcontroller.test.FloodlightTestCase;
-import net.floodlightcontroller.util.MACAddress;
-
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketIn.OFPacketInReason;
-import org.openflow.protocol.OFType;
-import org.openflow.util.HexString;
-
-/**
- * Unit test for stateless firewall implemented as a Google Summer of Code project.
- * 
- * @author Amer Tahir
- */
-public class FirewallTest extends FloodlightTestCase {
-    protected MockFloodlightProvider mockFloodlightProvider;
-    protected FloodlightContext cntx;
-    protected OFPacketIn packetIn;
-    protected IOFSwitch sw;
-    protected IPacket tcpPacket;
-    protected IPacket broadcastARPPacket;
-    protected IPacket ARPReplyPacket;
-    protected IPacket broadcastIPPacket;
-    protected IPacket tcpPacketReply;
-    protected IPacket broadcastMalformedPacket;
-    private Firewall firewall;
-    public static String TestSwitch1DPID = "00:00:00:00:00:00:00:01";
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        cntx = new FloodlightContext();
-        mockFloodlightProvider = getMockFloodlightProvider();
-        firewall = new Firewall();
-        IStorageSourceService storageService = new MemoryStorageSource();
-        RestApiServer restApi = new RestApiServer();
-
-        // Mock switches
-        long dpid = HexString.toLong(TestSwitch1DPID);
-        sw = EasyMock.createNiceMock(IOFSwitch.class);
-        expect(sw.getId()).andReturn(dpid).anyTimes();
-        expect(sw.getStringId()).andReturn(TestSwitch1DPID).anyTimes();
-        replay(sw);
-        // Load the switch map
-        Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>();
-        switches.put(dpid, sw);
-        mockFloodlightProvider.setSwitches(switches);
-
-        FloodlightModuleContext fmc = new FloodlightModuleContext();
-        fmc.addService(IFloodlightProviderService.class, 
-                mockFloodlightProvider);
-        fmc.addService(IFirewallService.class, firewall);
-        fmc.addService(IStorageSourceService.class, storageService);
-        fmc.addService(IRestApiService.class, restApi);
-
-        try {
-            restApi.init(fmc);
-        } catch (FloodlightModuleException e) {
-            e.printStackTrace();
-        }
-
-        firewall.init(fmc);
-        firewall.startUp(fmc);
-
-        // Build our test packet
-        this.tcpPacket = new Ethernet()
-        .setDestinationMACAddress("00:11:22:33:44:55")
-        .setSourceMACAddress("00:44:33:22:11:00")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.2")
-                .setPayload(new TCP()
-                .setSourcePort((short) 81)
-                .setDestinationPort((short) 80)
-                .setPayload(new Data(new byte[] {0x01}))));
-        
-        // Build a broadcast ARP packet
-        this.broadcastARPPacket = new Ethernet()
-        .setDestinationMACAddress("FF:FF:FF:FF:FF:FF")
-        .setSourceMACAddress("00:44:33:22:11:00")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_ARP)
-        .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setOpCode(ARP.OP_REQUEST)
-                .setHardwareAddressLength((byte)6)
-                .setProtocolAddressLength((byte)4)
-                .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
-                .setSenderProtocolAddress(IPv4.toIPv4Address("192.168.1.1"))
-                .setTargetHardwareAddress(Ethernet.toMACAddress("00:00:00:00:00:00"))
-                .setTargetProtocolAddress(IPv4.toIPv4Address("192.168.1.2"))
-                .setPayload(new Data(new byte[] {0x01})));
-        
-        // Build a ARP packet
-        this.ARPReplyPacket = new Ethernet()
-        .setDestinationMACAddress("00:44:33:22:11:00")
-        .setSourceMACAddress("00:11:22:33:44:55")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_ARP)
-        .setPayload(
-                new ARP()
-                .setHardwareType(ARP.HW_TYPE_ETHERNET)
-                .setProtocolType(ARP.PROTO_TYPE_IP)
-                .setOpCode(ARP.OP_REQUEST)
-                .setHardwareAddressLength((byte)6)
-                .setProtocolAddressLength((byte)4)
-                .setSenderHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
-                .setSenderProtocolAddress(IPv4.toIPv4Address("192.168.1.2"))
-                .setTargetHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
-                .setTargetProtocolAddress(IPv4.toIPv4Address("192.168.1.1"))
-                .setPayload(new Data(new byte[] {0x01})));
-        
-        // Build a broadcast IP packet
-        this.broadcastIPPacket = new Ethernet()
-        .setDestinationMACAddress("FF:FF:FF:FF:FF:FF")
-        .setSourceMACAddress("00:44:33:22:11:00")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.255")
-                .setPayload(new UDP()
-                .setSourcePort((short) 5000)
-                .setDestinationPort((short) 5001)
-                .setPayload(new Data(new byte[] {0x01}))));
-
-        // Build a malformed broadcast packet
-        this.broadcastMalformedPacket = new Ethernet()
-        .setDestinationMACAddress("FF:FF:FF:FF:FF:FF")
-        .setSourceMACAddress("00:44:33:22:11:00")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.2")
-                .setPayload(new UDP()
-                .setSourcePort((short) 5000)
-                .setDestinationPort((short) 5001)
-                .setPayload(new Data(new byte[] {0x01}))));
-
-        this.tcpPacketReply = new Ethernet()
-        .setDestinationMACAddress("00:44:33:22:11:00")
-        .setSourceMACAddress("00:11:22:33:44:55")
-        .setVlanID((short) 42)
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.2")
-                .setDestinationAddress("192.168.1.1")
-                .setPayload(new TCP()
-                .setSourcePort((short) 80)
-                .setDestinationPort((short) 81)
-                .setPayload(new Data(new byte[] {0x02}))));
-    }
-
-    protected void setPacketIn(IPacket packet) {
-        byte[] serializedPacket = packet.serialize();
-        // Build the PacketIn
-        this.packetIn = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
-                .setBufferId(-1)
-                .setInPort((short) 1)
-                .setPacketData(serializedPacket)
-                .setReason(OFPacketInReason.NO_MATCH)
-                .setTotalLength((short) serializedPacket.length);
-
-        // Add the packet to the context store
-        IFloodlightProviderService.bcStore.
-        put(cntx, 
-                IFloodlightProviderService.CONTEXT_PI_PAYLOAD, 
-                (Ethernet)packet);
-    }
-
-    @Test
-    public void testNoRules() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-        // simulate a packet-in event
-        this.setPacketIn(tcpPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        assertEquals(0, firewall.rules.size());
-
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        // no rules to match, so firewall should deny
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP);
-    }
-    
-    @Test
-    public void testReadRulesFromStorage() throws Exception {
-        // add 2 rules first
-        FirewallRule rule = new FirewallRule();
-        rule.in_port = 2;
-        rule.dl_src = MACAddress.valueOf("00:00:00:00:00:01").toLong();
-        rule.dl_dst = MACAddress.valueOf("00:00:00:00:00:02").toLong();
-        rule.priority = 1;
-        rule.action = FirewallRule.FirewallAction.DENY;
-        firewall.addRule(rule);
-        rule = new FirewallRule();
-        rule.in_port = 3;
-        rule.dl_src = MACAddress.valueOf("00:00:00:00:00:02").toLong();
-        rule.dl_dst = MACAddress.valueOf("00:00:00:00:00:01").toLong();
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.tp_dst = 80;
-        rule.priority = 2;
-        rule.action = FirewallRule.FirewallAction.ALLOW;
-        firewall.addRule(rule);
-
-        List<FirewallRule> rules = firewall.readRulesFromStorage();
-        // verify rule 1
-        FirewallRule r = rules.get(0);
-        assertEquals(r.in_port, 2);
-        assertEquals(r.priority, 1);
-        assertEquals(r.dl_src, MACAddress.valueOf("00:00:00:00:00:01").toLong());
-        assertEquals(r.dl_dst, MACAddress.valueOf("00:00:00:00:00:02").toLong());
-        assertEquals(r.action, FirewallRule.FirewallAction.DENY);
-        // verify rule 2
-        r = rules.get(1);
-        assertEquals(r.in_port, 3);
-        assertEquals(r.priority, 2);
-        assertEquals(r.dl_src, MACAddress.valueOf("00:00:00:00:00:02").toLong());
-        assertEquals(r.dl_dst, MACAddress.valueOf("00:00:00:00:00:01").toLong());
-        assertEquals(r.nw_proto, IPv4.PROTOCOL_TCP);
-        assertEquals(r.tp_dst, 80);
-        assertEquals(r.wildcard_nw_proto, false);
-        assertEquals(r.action, FirewallRule.FirewallAction.ALLOW);
-    }
-
-    @Test
-    public void testRuleInsertionIntoStorage() throws Exception {
-        // add TCP rule
-        FirewallRule rule = new FirewallRule();
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.priority = 1;
-        firewall.addRule(rule);
-
-        List<Map<String, Object>> rulesFromStorage = firewall.getStorageRules();
-        assertEquals(1, rulesFromStorage.size());
-        assertEquals(Integer.parseInt((String)rulesFromStorage.get(0).get("ruleid")), rule.ruleid);
-    }
-
-    @Test
-    public void testRuleDeletion() throws Exception {
-        // add TCP rule
-        FirewallRule rule = new FirewallRule();
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.priority = 1;
-        firewall.addRule(rule);
-        int rid = rule.ruleid;
-
-        List<Map<String, Object>> rulesFromStorage = firewall.getStorageRules();
-        assertEquals(1, rulesFromStorage.size());
-        assertEquals(Integer.parseInt((String)rulesFromStorage.get(0).get("ruleid")), rid);
-
-        // delete rule
-        firewall.deleteRule(rid);
-        rulesFromStorage = firewall.getStorageRules();
-        assertEquals(0, rulesFromStorage.size());
-    }
-
-    @Test
-    public void testFirewallDisabled() throws Exception {
-        // firewall isn't enabled by default
-        // so, it shouldn't make any decision
-
-        // add TCP rule
-        FirewallRule rule = new FirewallRule();
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.priority = 1;
-        firewall.addRule(rule);
-
-        this.setPacketIn(tcpPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        assertEquals(1, firewall.rules.size());
-
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertNull(decision);
-    }
-
-    @Test
-    public void testSimpleAllowRule() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-
-        // add TCP rule
-        FirewallRule rule = new FirewallRule();
-        rule.dl_type = Ethernet.TYPE_IPv4;
-        rule.wildcard_dl_type = false;
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        // source is IP 192.168.1.2
-        rule.nw_src_prefix = IPv4.toIPv4Address("192.168.1.2");
-        rule.wildcard_nw_src = false;
-        // dest is network 192.168.1.0/24
-        rule.nw_dst_prefix = IPv4.toIPv4Address("192.168.1.0");
-        rule.nw_dst_maskbits = 24;
-        rule.wildcard_nw_dst = false;
-        rule.priority = 1;
-        firewall.addRule(rule);
-
-        // simulate a packet-in events
-
-        this.setPacketIn(tcpPacketReply);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
-
-        // clear decision
-        IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION);
-
-        this.setPacketIn(tcpPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP);
-    }
-
-    @Test
-    public void testOverlappingRules() throws Exception {
-        firewall.enableFirewall(true);
-
-        // add TCP port 80 (destination only) allow rule
-        FirewallRule rule = new FirewallRule();
-        rule.dl_type = Ethernet.TYPE_IPv4;
-        rule.wildcard_dl_type = false;
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.tp_dst = 80;
-        rule.priority = 1;
-        firewall.addRule(rule);
-
-        // add block all rule
-        rule = new FirewallRule();
-        rule.action = FirewallRule.FirewallAction.DENY;
-        rule.priority = 2;
-        firewall.addRule(rule);
-
-        assertEquals(2, firewall.rules.size());
-
-        // packet destined to TCP port 80 - should be allowed
-
-        this.setPacketIn(tcpPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
-
-        // clear decision
-        IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION);
-
-        // packet destined for port 81 - should be denied
-
-        this.setPacketIn(tcpPacketReply);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP);
-    }
-
-    @Test
-    public void testARP() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-
-        // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked
-
-        // simulate an ARP broadcast packet-in event
-
-        this.setPacketIn(broadcastARPPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        // broadcast-ARP traffic should be allowed
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction());
-        
-        // clear decision
-        IRoutingDecision.rtStore.remove(cntx, IRoutingDecision.CONTEXT_DECISION);
-        
-        // simulate an ARP reply packet-in event
-
-        this.setPacketIn(ARPReplyPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        // ARP reply traffic should be denied
-        decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP);
-    }
-    
-    @Test
-    public void testIPBroadcast() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-        
-        // set subnet mask for IP broadcast
-        firewall.setSubnetMask("255.255.255.0");
-
-        // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked
-
-        // simulate a packet-in event
-
-        this.setPacketIn(broadcastIPPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        // broadcast traffic should be allowed
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(IRoutingDecision.RoutingAction.MULTICAST, decision.getRoutingAction());
-    }
-
-    @Test
-    public void testMalformedIPBroadcast() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-
-        // no rules inserted so all traffic other than broadcast and ARP-request-broadcast should be blocked
-
-        // simulate a packet-in event
-
-        this.setPacketIn(broadcastMalformedPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        // malformed broadcast traffic should NOT be allowed
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.DROP);
-    }
-
-    @Test
-    public void testLayer2Rule() throws Exception {
-        // enable firewall first
-        firewall.enableFirewall(true);
-
-        // add L2 rule
-        FirewallRule rule = new FirewallRule();
-        rule.dl_src = MACAddress.valueOf("00:44:33:22:11:00").toLong();
-        rule.wildcard_dl_src = false;
-        rule.dl_dst = MACAddress.valueOf("00:11:22:33:44:55").toLong();
-        rule.wildcard_dl_dst = false;
-        rule.priority = 1;
-        firewall.addRule(rule);
-
-        // add TCP deny all rule
-        rule = new FirewallRule();
-        rule.nw_proto = IPv4.PROTOCOL_TCP;
-        rule.wildcard_nw_proto = false;
-        rule.priority = 2;
-        rule.action = FirewallRule.FirewallAction.DENY;
-        firewall.addRule(rule);
-
-        // simulate a packet-in event
-
-        this.setPacketIn(tcpPacket);
-        firewall.receive(sw, this.packetIn, cntx);
-        verify(sw);
-
-        IRoutingDecision decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION);
-        assertEquals(decision.getRoutingAction(), IRoutingDecision.RoutingAction.FORWARD_OR_FLOOD);
-    }
-}
diff --git a/src/test/java/net/floodlightcontroller/hub/HubTest.java b/src/test/java/net/floodlightcontroller/hub/HubTest.java
deleted file mode 100644
index b4a215c..0000000
--- a/src/test/java/net/floodlightcontroller/hub/HubTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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.
-**/
-
-package net.floodlightcontroller.hub;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.easymock.EasyMock.capture;
-
-import java.util.Arrays;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
-import net.floodlightcontroller.packet.Data;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.packet.UDP;
-import net.floodlightcontroller.test.FloodlightTestCase;
-
-import org.easymock.Capture;
-import org.easymock.CaptureType;
-import org.junit.Before;
-import org.junit.Test;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketIn.OFPacketInReason;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class HubTest extends FloodlightTestCase {
-    protected OFPacketIn packetIn;
-    protected IPacket testPacket;
-    protected byte[] testPacketSerialized;
-    private   MockFloodlightProvider mockFloodlightProvider;
-    private Hub hub;
-    
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        mockFloodlightProvider = getMockFloodlightProvider();
-        hub = new Hub();
-        mockFloodlightProvider.addOFMessageListener(OFType.PACKET_IN, hub);
-        hub.setFloodlightProvider(mockFloodlightProvider);
-        
-        // Build our test packet
-        this.testPacket = new Ethernet()
-            .setDestinationMACAddress("00:11:22:33:44:55")
-            .setSourceMACAddress("00:44:33:22:11:00")
-            .setEtherType(Ethernet.TYPE_IPv4)
-            .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.2")
-                .setPayload(new UDP()
-                            .setSourcePort((short) 5000)
-                            .setDestinationPort((short) 5001)
-                            .setPayload(new Data(new byte[] {0x01}))));
-        this.testPacketSerialized = testPacket.serialize();
-
-        // Build the PacketIn
-        this.packetIn = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
-            .setBufferId(-1)
-            .setInPort((short) 1)
-            .setPacketData(this.testPacketSerialized)
-            .setReason(OFPacketInReason.NO_MATCH)
-            .setTotalLength((short) this.testPacketSerialized.length);
-    }
-
-    @Test
-    public void testFloodNoBufferId() throws Exception {
-        // build our expected flooded packetOut
-        OFPacketOut po = ((OFPacketOut) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT))
-            .setActions(Arrays.asList(new OFAction[] {new OFActionOutput().setPort(OFPort.OFPP_FLOOD.getValue())}))
-            .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
-            .setBufferId(-1)
-            .setInPort((short) 1)
-            .setPacketData(this.testPacketSerialized);
-        po.setLengthU(OFPacketOut.MINIMUM_LENGTH + po.getActionsLengthU()
-                + this.testPacketSerialized.length);
-
-        // Mock up our expected behavior
-        IOFSwitch mockSwitch = createMock(IOFSwitch.class);
-        
-        Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL);
-        Capture<FloodlightContext> bc1 = new Capture<FloodlightContext>(CaptureType.ALL);
-        
-        mockSwitch.write(capture(wc1), capture(bc1));
-
-        // Start recording the replay on the mocks
-        replay(mockSwitch);
-        // Get the listener and trigger the packet in
-        IOFMessageListener listener = mockFloodlightProvider.getListeners().get(
-                OFType.PACKET_IN).get(0);
-        listener.receive(mockSwitch, this.packetIn,
-                         parseAndAnnotate(this.packetIn));
-
-        // Verify the replay matched our expectations
-        verify(mockSwitch);
-        
-        assertTrue(wc1.hasCaptured());
-        OFMessage m = wc1.getValue();
-        assert(m.equals(po));
-    }
-
-    @Test
-    public void testFloodBufferId() throws Exception {
-        MockFloodlightProvider mockFloodlightProvider = getMockFloodlightProvider();
-        this.packetIn.setBufferId(10);
-
-        // build our expected flooded packetOut
-        OFPacketOut po = ((OFPacketOut) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_OUT))
-            .setActions(Arrays.asList(new OFAction[] {new OFActionOutput().setPort(OFPort.OFPP_FLOOD.getValue())}))
-            .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
-            .setBufferId(10)
-            .setInPort((short) 1);
-        po.setLengthU(OFPacketOut.MINIMUM_LENGTH + po.getActionsLengthU());
-
-        // Mock up our expected behavior
-        IOFSwitch mockSwitch = createMock(IOFSwitch.class);
-        Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL);
-        Capture<FloodlightContext> bc1 = new Capture<FloodlightContext>(CaptureType.ALL);
-        
-        mockSwitch.write(capture(wc1), capture(bc1));
-
-        // Start recording the replay on the mocks
-        replay(mockSwitch);
-        // Get the listener and trigger the packet in
-        IOFMessageListener listener = mockFloodlightProvider.getListeners().get(
-                OFType.PACKET_IN).get(0);
-        listener.receive(mockSwitch, this.packetIn,
-                         parseAndAnnotate(this.packetIn));
-
-        // Verify the replay matched our expectations
-        verify(mockSwitch);
-        
-        assertTrue(wc1.hasCaptured());
-        OFMessage m = wc1.getValue();
-        assert(m.equals(po));
-    }
-}
diff --git a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java b/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java
deleted file mode 100644
index a68a1b8..0000000
--- a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
-*    Copyright 2011, Big Switch Networks, Inc. 
-*    Originally created by David Erickson, Stanford University
-* 
-*    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.
-**/
-
-package net.floodlightcontroller.learningswitch;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightTestModuleLoader;
-import net.floodlightcontroller.core.module.IFloodlightModule;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
-import net.floodlightcontroller.packet.Data;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.packet.UDP;
-import net.floodlightcontroller.test.FloodlightTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.openflow.protocol.OFFlowMod;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFMessage;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFPacketIn.OFPacketInReason;
-import org.openflow.protocol.OFPacketOut;
-import org.openflow.protocol.OFPort;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.action.OFAction;
-import org.openflow.protocol.action.OFActionOutput;
-
-/**
- *
- * @author David Erickson (daviderickson@cs.stanford.edu)
- */
-public class LearningSwitchTest extends FloodlightTestCase {
-    protected OFPacketIn packetIn;
-    protected IPacket testPacket;
-    protected byte[] testPacketSerialized;
-    protected IPacket broadcastPacket;
-    protected byte[] broadcastPacketSerialized;
-    protected IPacket testPacketReply;
-    protected byte[] testPacketReplySerialized;
-    private LearningSwitch learningSwitch;
-    
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        FloodlightTestModuleLoader fml = new FloodlightTestModuleLoader();
-        Collection<Class<? extends IFloodlightModule>> mods 
-        	= new ArrayList<Class<? extends IFloodlightModule>>();
-        mods.add(LearningSwitch.class);
-        fml.setupModules(mods, null);
-        learningSwitch = (LearningSwitch) fml.getModuleByName(LearningSwitch.class);
-        mockFloodlightProvider = 
-        		(MockFloodlightProvider) fml.getModuleByName(MockFloodlightProvider.class);
-       
-        // Build our test packet
-        this.testPacket = new Ethernet()
-            .setDestinationMACAddress("00:11:22:33:44:55")
-            .setSourceMACAddress("00:44:33:22:11:00")
-            .setVlanID((short) 42)
-            .setEtherType(Ethernet.TYPE_IPv4)
-            .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.2")
-                .setPayload(new UDP()
-                            .setSourcePort((short) 5000)
-                            .setDestinationPort((short) 5001)
-                            .setPayload(new Data(new byte[] {0x01}))));
-        this.testPacketSerialized = testPacket.serialize();
-        // Build a broadcast packet
-        this.broadcastPacket = new Ethernet()
-            .setDestinationMACAddress("FF:FF:FF:FF:FF:FF")
-            .setSourceMACAddress("00:44:33:22:11:00")
-            .setVlanID((short) 42)
-            .setEtherType(Ethernet.TYPE_IPv4)
-            .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.255.255")
-                .setPayload(new UDP()
-                        .setSourcePort((short) 5000)
-                        .setDestinationPort((short) 5001)
-                        .setPayload(new Data(new byte[] {0x01}))));
-
-        this.broadcastPacketSerialized = broadcastPacket.serialize();
-        this.testPacketReply = new Ethernet()
-            .setDestinationMACAddress("00:44:33:22:11:00")
-            .setSourceMACAddress("00:11:22:33:44:55")
-            .setVlanID((short) 42)
-            .setEtherType(Ethernet.TYPE_IPv4)
-            .setPayload(
-                    new IPv4()
-                    .setTtl((byte) 128)
-                    .setSourceAddress("192.168.1.2")
-                    .setDestinationAddress("192.168.1.1")
-                    .setPayload(new UDP()
-                    .setSourcePort((short) 5001)
-                    .setDestinationPort((short) 5000)
-                    .setPayload(new Data(new byte[] {0x02}))));
-        this.testPacketReplySerialized = testPacketReply.serialize();
-
-        // Build the PacketIn
-        this.packetIn = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN))
-            .setBufferId(-1)
-            .setInPort((short) 1)
-            .setPacketData(this.testPacketSerialized)
-            .setReason(OFPacketInReason.NO_MATCH)
-            .setTotalLength((short) this.testPacketSerialized.length);
-    }
-
-    @Test
-    public void testFlood() throws Exception {
-        // build our expected flooded packetOut
-        OFPacketOut po = new OFPacketOut()
-            .setActions(Arrays.asList(new OFAction[] {new OFActionOutput().setPort(OFPort.OFPP_FLOOD.getValue())}))
-            .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH)
-            .setBufferId(-1)
-            .setInPort((short)1)
-            .setPacketData(this.testPacketSerialized);
-        po.setLengthU(OFPacketOut.MINIMUM_LENGTH + po.getActionsLengthU()
-                + this.testPacketSerialized.length);
-
-        // Mock up our expected behavior
-        IOFSwitch mockSwitch = createMock(IOFSwitch.class);
-        expect(mockSwitch.getStringId()).andReturn("00:11:22:33:44:55:66:77").anyTimes();
-        mockSwitch.write(po, null);
-
-        // Start recording the replay on the mocks
-        replay(mockSwitch);
-        // Get the listener and trigger the packet in
-        IOFMessageListener listener = mockFloodlightProvider.getListeners().get(
-                OFType.PACKET_IN).get(0);
-        // Make sure it's the right listener
-        listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn));
-
-        // Verify the replay matched our expectations      
-        short result = learningSwitch.getFromPortMap(mockSwitch, Ethernet.toLong(Ethernet.toMACAddress("00:44:33:22:11:00")), (short) 42).shortValue();
-        verify(mockSwitch);
-
-        // Verify the MAC table inside the switch
-        assertEquals(1, result);
-    }
-    
-    @Test
-    public void testFlowMod() throws Exception {
-        // tweak the test packet in since we need a bufferId
-        this.packetIn.setBufferId(50);
-
-        // build expected flow mods
-        OFMessage fm1 = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD))
-            .setActions(Arrays.asList(new OFAction[] {
-                    new OFActionOutput().setPort((short) 2).setMaxLength((short) -1)}))
-            .setBufferId(50)
-            .setCommand(OFFlowMod.OFPFC_ADD)
-            .setIdleTimeout((short) 5)
-            .setMatch(new OFMatch()
-                .loadFromPacket(testPacketSerialized, (short) 1)
-                .setWildcards(OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST
-                        | OFMatch.OFPFW_NW_TOS))
-            .setOutPort(OFPort.OFPP_NONE.getValue())
-            .setCookie(1L << 52)
-            .setPriority((short) 100)
-            .setFlags((short)(1 << 0))
-            .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
-        OFMessage fm2 = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD))
-            .setActions(Arrays.asList(new OFAction[] {
-                    new OFActionOutput().setPort((short) 1).setMaxLength((short) -1)}))
-            .setBufferId(-1)
-            .setCommand(OFFlowMod.OFPFC_ADD)
-            .setIdleTimeout((short) 5)
-            .setMatch(new OFMatch()
-                .loadFromPacket(testPacketReplySerialized, (short) 2)
-                .setWildcards(OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST
-                        | OFMatch.OFPFW_NW_TOS))
-            .setOutPort(OFPort.OFPP_NONE.getValue())
-            .setCookie(1L << 52)
-            .setPriority((short) 100)
-            .setFlags((short)(1 << 0))
-            .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH);
-
-        // Mock up our expected behavior
-        IOFSwitch mockSwitch = createMock(IOFSwitch.class);
-        expect(mockSwitch.getId()).andReturn(1L).anyTimes();
-        expect(mockSwitch.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn((Integer) (OFMatch.OFPFW_IN_PORT | OFMatch.OFPFW_NW_PROTO
-                | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST | OFMatch.OFPFW_NW_SRC_ALL
-                | OFMatch.OFPFW_NW_DST_ALL | OFMatch.OFPFW_NW_TOS));
-        mockSwitch.write(fm1, null);
-        mockSwitch.write(fm2, null);
-
-        // Start recording the replay on the mocks
-        replay(mockSwitch);
-
-        // Populate the MAC table
-        learningSwitch.addToPortMap(mockSwitch,
-                Ethernet.toLong(Ethernet.toMACAddress("00:11:22:33:44:55")), (short) 42, (short) 2);
-        
-        // Get the listener and trigger the packet in
-        IOFMessageListener listener = mockFloodlightProvider.getListeners().get(
-                OFType.PACKET_IN).get(0);
-        listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn));
-        
-        // Verify the replay matched our expectations
-        short result = learningSwitch.getFromPortMap(mockSwitch, Ethernet.toLong(Ethernet.toMACAddress("00:44:33:22:11:00")), (short) 42).shortValue();
-        verify(mockSwitch);
-
-        // Verify the MAC table inside the switch
-        assertEquals(1, result);
-    }
-}
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
deleted file mode 100644
index 1e71138..0000000
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkStorageImplTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-package net.floodlightcontroller.linkdiscovery.internal;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Iterator;
-import java.util.List;
-
-import net.floodlightcontroller.core.INetMapStorage.DM_OPERATION;
-import net.floodlightcontroller.core.internal.TestDatabaseManager;
-import net.floodlightcontroller.linkdiscovery.ILinkStorage;
-import net.floodlightcontroller.routing.Link;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import com.thinkaurelius.titan.core.TitanGraph;
-import com.tinkerpop.blueprints.Vertex;
-import com.tinkerpop.gremlin.java.GremlinPipeline;
-
-public class LinkStorageImplTest {
-	private static ILinkStorage linkStorage;
-	private static TitanGraph titanGraph;
-	
-	//TODO Future ideas:
-	//Test add links with CREATE and UPDATE
-	//Test adding existing link again
-	
-	@Before
-	public void setUp() throws Exception{
-		titanGraph = TestDatabaseManager.getTestDatabase();
-		TestDatabaseManager.populateTestData(titanGraph);
-		
-		linkStorage = new TestableLinkStorageImpl(titanGraph);
-	}
-	
-	@After
-	public void tearDown() throws Exception {		
-		titanGraph.shutdown();
-	}
-	
-	/*
-	 * Add a link between port 1.102 and 2.104
-	 * i.e SEA switch port 3 to LAX switch port 1
-	 */
-	@Test
-	public void testAddSingleLink(){
-		Link linkToAdd = new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a02"), 1);
-		
-		//Use the link storage API to add the link
-		linkStorage.update(linkToAdd, ILinkStorage.DM_OPERATION.INSERT);
-		
-		//Test if it was added correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
-		
-		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
-		assertFalse(it.hasNext());
-		
-		pipe.start(sw1).out("on").has("number", (short)3).out("link").in("on");
-		
-		assertTrue(pipe.hasNext());
-		Vertex sw2 = pipe.next();
-		assertFalse(pipe.hasNext());
-		
-		//Check we ended up at the right vertex
-		assertEquals((String)sw2.getProperty("dpid"), "00:00:00:00:00:00:0a:02");
-	}
-	
-	//TODO enable once method is written
-	@Ignore @Test
-	public void testGetLinks(){
-		//TODO Make sure this works when the implementation is written
-		List<Link> list = linkStorage.getLinks(Long.decode("0x0000000000000a01"), (short)2);
-		
-		assertEquals(list.size(), 1);
-		
-		Link l = list.get(0);
-		assertEquals(l.getSrc(), 2561L);
-		assertEquals(l.getSrcPort(), (short)2);
-		assertEquals(l.getDst(), 2563L);
-		assertEquals(l.getDstPort(), (short)1);
-	}
-	
-	//TODO enable once method is written
-	@Ignore @Test
-	public void testUpdateDelete(){
-		Link linkToDelete = new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a03"), 1);
-		
-		linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
-		
-		//Test if it was deleted correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
-		
-		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
-		assertFalse(it.hasNext());
-		
-		pipe.start(sw1).out("on").has("number", 2).out("link");
-		
-		assertFalse(pipe.hasNext());
-	}
-	
-	//TODO enable once method is written
-	@Ignore @Test
-	public void testDeleteLinks(){
-		//TODO Make sure this works when the implementation is written
-		
-		linkStorage.deleteLinksOnPort(Long.decode("0x0000000000000a01"), (short)2);
-		
-		//Test if it was deleted correctly with the Gremlin API
-		GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>();
-		Iterator<Vertex> it = titanGraph.getVertices("dpid", "00:00:00:00:00:00:0a:01").iterator();
-		
-		assertTrue(it.hasNext());
-		Vertex sw1 = it.next();
-		assertFalse(it.hasNext());
-		
-		pipe.start(sw1).out("on").has("number", 2).out("link");
-		
-		assertFalse(pipe.hasNext());
-	}
-	
-}
diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
index e72179d..9232bb5 100644
--- a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
+++ b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java
@@ -11,11 +11,11 @@
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.test.MockFloodlightProvider;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.topology.TopologyInstance;
 import net.floodlightcontroller.topology.TopologyManager;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
index 113cecb..1cf344d 100644
--- a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
+++ b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
@@ -4,10 +4,10 @@
 import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
 import net.floodlightcontroller.test.FloodlightTestCase;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.topology.TopologyManager;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscovery;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
index ffabf6f..59e0a51 100644
--- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
+++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java
@@ -346,10 +346,4 @@
         return 0;
     }
 
-	@Override
-	public void setupRemoteSwitch(Long dpid) {
-		// TODO Auto-generated method stub
-		
-	}
-
 }
\ No newline at end of file
diff --git a/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java b/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java
deleted file mode 100644
index 32afe4e..0000000
--- a/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java
+++ /dev/null
@@ -1,375 +0,0 @@
-package net.floodlightcontroller.virtualnetwork;
-
-import static org.easymock.EasyMock.*;
-
-import java.util.List;
-
-import org.easymock.EasyMock;
-import org.junit.Before;
-import org.junit.Test;
-import org.openflow.protocol.OFMatch;
-import org.openflow.protocol.OFPacketIn;
-import org.openflow.protocol.OFType;
-import org.openflow.protocol.OFPacketIn.OFPacketInReason;
-
-import net.floodlightcontroller.core.FloodlightContext;
-import net.floodlightcontroller.core.IFloodlightProviderService;
-import net.floodlightcontroller.core.IOFMessageListener;
-import net.floodlightcontroller.core.IListener.Command;
-import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.test.MockThreadPoolService;
-import net.floodlightcontroller.core.test.PacketFactory;
-import net.floodlightcontroller.devicemanager.IDeviceService;
-import net.floodlightcontroller.devicemanager.IEntityClassifierService;
-import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
-import net.floodlightcontroller.devicemanager.test.MockDeviceManager;
-import net.floodlightcontroller.flowcache.FlowReconcileManager;
-import net.floodlightcontroller.flowcache.IFlowReconcileService;
-import net.floodlightcontroller.packet.Data;
-import net.floodlightcontroller.packet.Ethernet;
-import net.floodlightcontroller.packet.IPacket;
-import net.floodlightcontroller.packet.IPv4;
-import net.floodlightcontroller.packet.UDP;
-import net.floodlightcontroller.restserver.IRestApiService;
-import net.floodlightcontroller.restserver.RestApiServer;
-import net.floodlightcontroller.test.FloodlightTestCase;
-import net.floodlightcontroller.threadpool.IThreadPoolService;
-import net.floodlightcontroller.topology.ITopologyService;
-import net.floodlightcontroller.util.MACAddress;
-import net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter;
-
-public class VirtualNetworkFilterTest extends FloodlightTestCase {
-    protected VirtualNetworkFilter vns;
-    protected MockDeviceManager deviceService;
-    
-    protected static String guid1 = "guid1";
-    protected static String net1 = "net1";
-    protected static String gw1 = "1.1.1.1";
-    protected static String guid2 = "guid2";
-    protected static String net2 = "net2";
-    protected static String guid3 = "guid3";
-    protected static String net3 = "net3";
-    protected static String gw2 = "2.2.2.2";
-    
-    protected static MACAddress mac1 = 
-            new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:55"));
-    protected static MACAddress mac2 = 
-            new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:66"));
-    protected static MACAddress mac3 = 
-            new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:77"));
-    protected static MACAddress mac4 = 
-            new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:88"));
-    protected static String hostPort1 = "port1";
-    protected static String hostPort2 = "port2";
-    protected static String hostPort3 = "port3";
-    protected static String hostPort4 = "port4";
-    
-    // For testing forwarding behavior
-    protected IOFSwitch sw1;
-    protected FloodlightContext cntx;
-    protected OFPacketIn mac1ToMac2PacketIn;
-    protected IPacket mac1ToMac2PacketIntestPacket;
-    protected byte[] mac1ToMac2PacketIntestPacketSerialized;
-    protected OFPacketIn mac1ToMac4PacketIn;
-    protected IPacket mac1ToMac4PacketIntestPacket;
-    protected byte[] mac1ToMac4PacketIntestPacketSerialized;
-    protected OFPacketIn mac1ToGwPacketIn;
-    protected IPacket mac1ToGwPacketIntestPacket;
-    protected byte[] mac1ToGwPacketIntestPacketSerialized;
-    protected OFPacketIn packetInDHCPDiscoveryRequest;
-    
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-
-        // Module loading stuff
-        FloodlightModuleContext fmc = new FloodlightModuleContext();
-        RestApiServer restApi = new RestApiServer();
-        deviceService = new MockDeviceManager();
-        FlowReconcileManager frm = new FlowReconcileManager();
-        MockThreadPoolService tps = new MockThreadPoolService();
-        ITopologyService topology = createMock(ITopologyService.class);
-        vns = new VirtualNetworkFilter();
-        DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier();
-        fmc.addService(IRestApiService.class, restApi);
-        fmc.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
-        fmc.addService(IDeviceService.class, deviceService);
-        fmc.addService(IFlowReconcileService.class, frm);
-        fmc.addService(IThreadPoolService.class, tps);
-        fmc.addService(IEntityClassifierService.class, entityClassifier);
-        fmc.addService(ITopologyService.class, topology);
-        tps.init(fmc);
-        frm.init(fmc);
-        deviceService.init(fmc);
-        restApi.init(fmc);
-        getMockFloodlightProvider().init(fmc);
-        entityClassifier.init(fmc);
-        tps.startUp(fmc);
-        vns.init(fmc);
-        frm.startUp(fmc);
-        deviceService.startUp(fmc);
-        restApi.startUp(fmc);
-        getMockFloodlightProvider().startUp(fmc);
-        vns.startUp(fmc);
-        entityClassifier.startUp(fmc);
-
-        topology.addListener(deviceService);
-        expectLastCall().times(1);
-        replay(topology);
-        // Mock switches
-        //fastWilcards mocked as this constant
-        int fastWildcards = 
-                OFMatch.OFPFW_IN_PORT | 
-                OFMatch.OFPFW_NW_PROTO | 
-                OFMatch.OFPFW_TP_SRC | 
-                OFMatch.OFPFW_TP_DST | 
-                OFMatch.OFPFW_NW_SRC_ALL | 
-                OFMatch.OFPFW_NW_DST_ALL |
-                OFMatch.OFPFW_NW_TOS;
-        sw1 = EasyMock.createNiceMock(IOFSwitch.class);
-        expect(sw1.getId()).andReturn(1L).anyTimes();
-        expect(sw1.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn((Integer)fastWildcards).anyTimes();
-        expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes();
-        replay(sw1);
-        
-        // Mock packets
-        // Mock from MAC1 -> MAC2
-        mac1ToMac2PacketIntestPacket = new Ethernet()
-            .setDestinationMACAddress(mac2.toBytes())
-            .setSourceMACAddress(mac1.toBytes())
-            .setEtherType(Ethernet.TYPE_IPv4)
-            .setPayload(
-                new IPv4()
-                .setTtl((byte) 128)
-                .setSourceAddress("192.168.1.1")
-                .setDestinationAddress("192.168.1.2")
-                .setPayload(new UDP()
-                            .setSourcePort((short) 5000)
-                            .setDestinationPort((short) 5001)
-                            .setPayload(new Data(new byte[] {0x01}))));
-        mac1ToMac2PacketIntestPacketSerialized = mac1ToMac2PacketIntestPacket.serialize();
-        mac1ToMac2PacketIn = 
-                ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
-                        getMessage(OFType.PACKET_IN))
-                        .setBufferId(-1)
-                        .setInPort((short) 1)
-                        .setPacketData(mac1ToMac2PacketIntestPacketSerialized)
-                        .setReason(OFPacketInReason.NO_MATCH)
-                        .setTotalLength((short) mac1ToMac2PacketIntestPacketSerialized.length);
-        
-        // Mock from MAC1 -> MAC4
-        mac1ToMac4PacketIntestPacket = new Ethernet()
-        .setDestinationMACAddress(mac4.toBytes())
-        .setSourceMACAddress(mac1.toBytes())
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-            new IPv4()
-            .setTtl((byte) 128)
-            .setSourceAddress("192.168.1.1")
-            .setDestinationAddress("192.168.1.2")
-            .setPayload(new UDP()
-                        .setSourcePort((short) 5000)
-                        .setDestinationPort((short) 5001)
-                        .setPayload(new Data(new byte[] {0x01}))));
-        mac1ToMac4PacketIntestPacketSerialized = mac1ToMac4PacketIntestPacket.serialize();
-        mac1ToMac4PacketIn = 
-            ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
-                    getMessage(OFType.PACKET_IN))
-                    .setBufferId(-1)
-                    .setInPort((short) 1)
-                    .setPacketData(mac1ToMac4PacketIntestPacketSerialized)
-                    .setReason(OFPacketInReason.NO_MATCH)
-                    .setTotalLength((short) mac1ToMac4PacketIntestPacketSerialized.length);
-        
-        // Mock from MAC1 to gateway1
-        mac1ToGwPacketIntestPacket = new Ethernet()
-        .setDestinationMACAddress("00:11:33:33:44:55") // mac shouldn't matter, can't be other host
-        .setSourceMACAddress(mac1.toBytes())
-        .setEtherType(Ethernet.TYPE_IPv4)
-        .setPayload(
-            new IPv4()
-            .setTtl((byte) 128)
-            .setSourceAddress("192.168.1.1")
-            .setDestinationAddress(gw1)
-            .setPayload(new UDP()
-                        .setSourcePort((short) 5000)
-                        .setDestinationPort((short) 5001)
-                        .setPayload(new Data(new byte[] {0x01}))));
-        mac1ToGwPacketIntestPacketSerialized = mac1ToGwPacketIntestPacket.serialize();
-        mac1ToGwPacketIn = 
-            ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
-                    getMessage(OFType.PACKET_IN))
-                    .setBufferId(-1)
-                    .setInPort((short) 1)
-                    .setPacketData(mac1ToGwPacketIntestPacketSerialized)
-                    .setReason(OFPacketInReason.NO_MATCH)
-                    .setTotalLength((short) mac1ToGwPacketIntestPacketSerialized.length);
-    }
-    
-    @Test
-    public void testCreateNetwork() {
-        // Test creating a network with all parameters
-        vns.createNetwork(guid1, net1, IPv4.toIPv4Address(gw1));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
-        assertTrue(vns.nameToGuid.get(net1).equals(guid1));
-        assertTrue(vns.guidToGateway.get(guid1).equals(IPv4.toIPv4Address(gw1)));
-        assertTrue(vns.vNetsByGuid.get(guid1).name.equals(net1));
-        assertTrue(vns.vNetsByGuid.get(guid1).guid.equals(guid1));
-        assertTrue(vns.vNetsByGuid.get(guid1).gateway.equals(gw1));
-        assertTrue(vns.vNetsByGuid.get(guid1).hosts.size()==0);
-
-        // Test creating network without a gateway
-        vns.createNetwork(guid2, net2, null);
-        assertTrue(vns.nameToGuid.get(net2).equals(guid2));
-        assertTrue(vns.guidToGateway.get(guid2) == null);
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 1);
-        assertTrue(vns.vNetsByGuid.get(guid2).name.equals(net2));
-        assertTrue(vns.vNetsByGuid.get(guid2).guid.equals(guid2));
-        assertTrue(vns.vNetsByGuid.get(guid2).gateway == null);
-        assertTrue(vns.vNetsByGuid.get(guid2).hosts.size()==0);
-        
-        // Test creating a network that shares the gateway with net1
-        vns.createNetwork(guid3, net3, IPv4.toIPv4Address(gw1));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2);
-        assertTrue(vns.nameToGuid.get(net3).equals(guid3));
-        assertTrue(vns.guidToGateway.get(guid3).equals(IPv4.toIPv4Address(gw1)));
-        assertTrue(vns.vNetsByGuid.get(guid3).name.equals(net3));
-        assertTrue(vns.vNetsByGuid.get(guid3).guid.equals(guid3));
-        assertTrue(vns.vNetsByGuid.get(guid3).gateway.equals(gw1));
-        assertTrue(vns.vNetsByGuid.get(guid3).hosts.size()==0);
-
-    }
-    
-    @Test
-    public void testModifyNetwork() {
-        // Create some networks
-        
-        testCreateNetwork();
-        // Modify net2 to add a gateway
-        vns.createNetwork(guid2, net2, IPv4.toIPv4Address(gw1));
-        assertTrue(vns.nameToGuid.get(net2).equals(guid2));
-        assertTrue(vns.guidToGateway.get(guid2).equals(IPv4.toIPv4Address(gw1)));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 3);
-        // Modify net2 to change it's name
-        vns.createNetwork(guid2, "newnet2", null);
-        // Make sure the gateway is still there
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2));
-        assertTrue(vns.vNetsByGuid.get(guid2).gateway.equals(gw1));
-        // make sure the new name mapping was learned
-        assertTrue(vns.nameToGuid.get("newnet2").equals(guid2));
-        assertTrue(vns.vNetsByGuid.get(guid2).name.equals("newnet2"));
-        // and the old one was deleted
-        assertFalse(vns.nameToGuid.containsKey(net2));
-    }
-    
-    @Test
-    public void testDeleteNetwork() {
-        testModifyNetwork();
-        // Delete newnet2
-        vns.deleteNetwork(guid2);
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
-        assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2);
-        assertFalse(vns.nameToGuid.containsKey(net2));
-        assertFalse(vns.guidToGateway.containsKey(net2));
-        assertTrue(vns.vNetsByGuid.get(guid2)==null);
-    }
-    
-    @Test
-    public void testAddHost() {
-        testModifyNetwork();
-        vns.addHost(mac1, guid1, hostPort1);
-        assertTrue(vns.macToGuid.get(mac1).equals(guid1));
-        assertTrue(vns.portToMac.get(hostPort1).equals(mac1));
-        assertTrue(vns.vNetsByGuid.get(guid1).hosts.contains(mac1));
-        vns.addHost(mac2, guid1, hostPort2);
-        assertTrue(vns.macToGuid.get(mac2).equals(guid1));
-        assertTrue(vns.portToMac.get(hostPort2).equals(mac2));
-        assertTrue(vns.vNetsByGuid.get(guid1).hosts.contains(mac2));
-        vns.addHost(mac3, guid3, hostPort3);
-        vns.addHost(mac4, guid3, hostPort4);
-        assertTrue(vns.vNetsByGuid.get(guid3).hosts.contains(mac4));
-    }
-    
-    @Test
-    public void testDeleteHost() {
-        testAddHost();
-
-        String host1Guid = vns.macToGuid.get(mac1);
-        vns.deleteHost(mac1, null);
-        assertFalse(vns.macToGuid.containsKey(mac1));
-        assertFalse(vns.portToMac.containsKey(hostPort1));
-        assertFalse(vns.vNetsByGuid.get(host1Guid).hosts.contains(mac1));
-        
-        String host2Guid = vns.macToGuid.get(vns.portToMac.get(hostPort2));
-        vns.deleteHost(null, hostPort2);
-        assertFalse(vns.macToGuid.containsKey(mac2));
-        assertFalse(vns.portToMac.containsKey(hostPort2));
-        assertFalse(vns.vNetsByGuid.get(host2Guid).hosts.contains(mac2));
-
-        String host3Guid = vns.macToGuid.get(mac3);        
-        vns.deleteHost(mac3, hostPort3);
-        assertFalse(vns.macToGuid.containsKey(mac3));
-        assertFalse(vns.portToMac.containsKey(hostPort3));
-        assertFalse(vns.vNetsByGuid.get(host3Guid).hosts.contains(mac3));
-        
-    }
-    
-    @Test
-    public void testForwarding() {
-        testAddHost();
-        // make sure mac1 can communicate with mac2
-        IOFMessageListener listener = getVirtualNetworkListener();
-        cntx = new FloodlightContext();
-        IFloodlightProviderService.bcStore.put(cntx, 
-                           IFloodlightProviderService.CONTEXT_PI_PAYLOAD, 
-                               (Ethernet)mac1ToMac2PacketIntestPacket);
-        Command ret = listener.receive(sw1, mac1ToMac2PacketIn, cntx);
-        assertTrue(ret == Command.CONTINUE);
-        // make sure mac1 can't communicate with mac4
-        cntx = new FloodlightContext();
-        IFloodlightProviderService.bcStore.put(cntx,
-                           IFloodlightProviderService.CONTEXT_PI_PAYLOAD, 
-                               (Ethernet)mac1ToMac4PacketIntestPacket);
-        ret = listener.receive(sw1, mac1ToMac4PacketIn, cntx);
-        assertTrue(ret == Command.STOP);
-    }
-
-    @Test
-    public void testDefaultGateway() {
-        testAddHost();
-        IOFMessageListener listener = getVirtualNetworkListener();
-        cntx = new FloodlightContext();
-        IFloodlightProviderService.bcStore.put(cntx, 
-                           IFloodlightProviderService.CONTEXT_PI_PAYLOAD, 
-                               (Ethernet)mac1ToGwPacketIntestPacket);
-        deviceService.learnEntity(((Ethernet)mac1ToGwPacketIntestPacket).getDestinationMAC().toLong(), 
-        		null, IPv4.toIPv4Address(gw1), null, null);
-        Command ret = listener.receive(sw1, mac1ToGwPacketIn, cntx);
-        assertTrue(ret == Command.CONTINUE);
-    }
-    
-    @Test
-    public void testDhcp() {
-        IOFMessageListener listener = getVirtualNetworkListener();
-        Ethernet dhcpPacket = PacketFactory.DhcpDiscoveryRequestEthernet(mac1);
-        OFPacketIn dhcpPacketOf = PacketFactory.DhcpDiscoveryRequestOFPacketIn(mac1);
-        cntx = new FloodlightContext();
-        IFloodlightProviderService.bcStore.put(cntx, 
-                           IFloodlightProviderService.CONTEXT_PI_PAYLOAD, 
-                           dhcpPacket);
-        Command ret = listener.receive(sw1, dhcpPacketOf, cntx);
-        assertTrue(ret == Command.CONTINUE);
-    }
-    
-    protected IOFMessageListener getVirtualNetworkListener() {
-    	List<IOFMessageListener> listeners = mockFloodlightProvider.getListeners().get(OFType.PACKET_IN);
-    	return listeners.get(listeners.indexOf(vns));
-    }
-}
diff --git a/src/test/java/net/onrc/onos/graph/GraphDBConnectionTest.java b/src/test/java/net/onrc/onos/graph/GraphDBConnectionTest.java
new file mode 100644
index 0000000..bee936d
--- /dev/null
+++ b/src/test/java/net/onrc/onos/graph/GraphDBConnectionTest.java
@@ -0,0 +1,229 @@
+/**
+ * 
+ */
+package net.onrc.onos.graph;
+
+import static org.junit.Assert.*;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+import java.util.*;
+
+import net.onrc.onos.graph.GraphDBOperation;
+
+import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.wrappers.event.EventTransactionalGraph;
+import com.tinkerpop.frames.FramedGraph;
+
+/**
+ * @author Toshio Koide
+ *
+ */
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({
+	GraphDBConnection.class,
+	GraphDBOperation.class,
+	TitanFactory.class,
+	EventTransactionalGraph.class})
+public class GraphDBConnectionTest {
+	private static TitanGraph graph = null;
+	private static EventTransactionalGraph<TitanGraph> eg = null;
+	private static Boolean isGraphOpen = false;
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+	}
+
+	
+	private void expectDBConnectionAvailable() throws Exception {
+		isGraphOpen = false;
+		
+		// create mock objects
+		mockStatic(TitanFactory.class);
+		mockStatic(EventTransactionalGraph.class);
+		graph = createMock(TitanGraph.class);
+		eg = createMock(EventTransactionalGraph.class);
+		
+		// setup expectations
+		expect(graph.isOpen()).andAnswer(new IAnswer<Boolean>() {
+			@Override
+			public Boolean answer() throws Throwable {
+				return isGraphOpen;
+			}
+		}).anyTimes();
+		expect(TitanFactory.open("/path/to/dummy")).andAnswer(new IAnswer<TitanGraph>() {
+			@Override
+			public TitanGraph answer() throws Throwable {
+				isGraphOpen = true;
+				return graph;
+			}
+		}).anyTimes();
+		expect(graph.getIndexedKeys(Vertex.class)).andReturn(new TreeSet<String>());
+		graph.createKeyIndex("dpid", Vertex.class);
+		graph.createKeyIndex("port_id", Vertex.class);
+		graph.createKeyIndex("type", Vertex.class);
+		graph.createKeyIndex("dl_addr", Vertex.class);
+		graph.createKeyIndex("flow_id", Vertex.class);
+		graph.createKeyIndex("flow_entry_id", Vertex.class);
+		graph.createKeyIndex("switch_state", Vertex.class);
+		graph.commit();
+		expectNew(EventTransactionalGraph.class, graph).andReturn(eg);
+	}
+	
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#getInstance(java.lang.String)}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testGetInstance() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+
+		// verify the test
+		verifyAll();
+		assertNotNull(conn);
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#getFramedGraph()}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testGetFramedGraph() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		FramedGraph<TitanGraph> fg = conn.getFramedGraph();
+		
+		// verify the test
+		verifyAll();
+		assertNotNull(fg);
+		assertEquals(graph, fg.getBaseGraph());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#addEventListener(net.onrc.onos.graph.LocalGraphChangedListener)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testAddEventListener() throws Exception {
+		// instantiate required objects
+		LocalGraphChangedListener listener = new LocalTopologyEventListener(null);
+
+		// setup expectations
+		expectDBConnectionAvailable();
+		eg.addListener(listener);
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		conn.addEventListener(listener);
+		
+		// verify the test
+		verifyAll();
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#isValid()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testIsValid() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		Boolean result = conn.isValid();
+		
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#commit()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testCommit() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+		graph.commit();
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		conn.commit();
+
+		// verify the test
+		verifyAll();
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#rollback()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testRollback() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+		graph.rollback();
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		conn.rollback();
+
+		// verify the test
+		verifyAll();
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBConnection#close()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testClose() throws Exception {
+		// setup expectations
+		expectDBConnectionAvailable();
+		graph.commit();
+		
+		// start the test
+		replayAll();
+		GraphDBConnection conn = GraphDBConnection.getInstance("/path/to/dummy");
+		conn.close();
+
+		// verify the test
+		verifyAll();
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/graph/GraphDBOperationTest.java b/src/test/java/net/onrc/onos/graph/GraphDBOperationTest.java
new file mode 100644
index 0000000..e99ca81
--- /dev/null
+++ b/src/test/java/net/onrc/onos/graph/GraphDBOperationTest.java
@@ -0,0 +1,596 @@
+/**
+ * 
+ */
+package net.onrc.onos.graph;
+
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import junit.framework.TestCase;
+
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowId;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.Vertex;
+
+/**
+ * @author Toshio Koide
+ *
+ */
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class})
+public class GraphDBOperationTest extends TestCase {
+	private static TitanGraph testdb;
+	private static GraphDBOperation op;
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@BeforeClass
+	public static void setUpBeforeClass() throws Exception {
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp() throws Exception {
+		TestDatabaseManager.deleteTestDatabase();
+		testdb = TestDatabaseManager.getTestDatabase();
+//		TestDatabaseManager.populateTestData(titanGraph);
+
+		String dummyPath = "/dummy/to/conf";
+		// replace return value of TitanFactory.open() to dummy DB created above
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open(dummyPath)).andReturn(testdb);
+		PowerMock.replay(TitanFactory.class);
+		
+		op = new GraphDBOperation(dummyPath);
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+		op.close();
+		testdb.shutdown();
+		PowerMock.verifyAll();
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#newSwitch(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testNewSwitch() {
+		assertNull(op.searchSwitch("123"));
+
+		ISwitchObject sw = op.newSwitch("123");
+		assertEquals(sw.getDPID(), "123");
+		op.commit();
+
+		sw = op.searchSwitch("123");
+		assertNotNull(sw);
+		assertEquals("123", sw.getDPID());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchSwitch(net.onrc.onos.graph.GraphDBConnection, java.lang.String)}.
+	 */
+	@Test
+	public final void testSearchSwitch() {
+		op.newSwitch("123");
+		op.newSwitch("456");
+		op.commit();
+
+		ISwitchObject sw = op.searchSwitch("123");
+		assertNotNull(sw);
+		assertEquals("123", sw.getDPID());
+
+		sw = op.searchSwitch("789");
+		assertNull(sw);
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchActiveSwitch(net.onrc.onos.graph.GraphDBConnection, java.lang.String)}.
+	 */
+	@Test
+	public final void testSearchActiveSwitch() {
+		op.newSwitch("111").setState(SwitchState.ACTIVE.toString());
+		op.newSwitch("222").setState(SwitchState.INACTIVE.toString());
+		op.commit();
+		
+		ISwitchObject sw = op.searchActiveSwitch("111");
+		assertNotNull(sw);
+		assertEquals("111", sw.getDPID());
+		
+		sw = op.searchActiveSwitch("222");
+		assertNull(sw);	
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getActiveSwitches(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetActiveSwitches() {
+		op.newSwitch("111").setState(SwitchState.ACTIVE.toString());
+		op.newSwitch("222").setState(SwitchState.INACTIVE.toString());
+		op.commit();
+		
+		Iterator<ISwitchObject> i = op.getActiveSwitches().iterator();
+		
+		assertTrue(i.hasNext());
+		assertEquals("111", i.next().getDPID());
+		assertFalse(i.hasNext());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getAllSwitches(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetAllSwitches() {
+		List<String> dpids = Arrays.asList("111", "222", "333");
+		Collections.sort(dpids);
+		
+		for (String dpid: dpids) op.newSwitch(dpid);
+		op.commit();
+
+		List<String> actual_ids = new ArrayList<String>();
+		for (ISwitchObject switchObj: op.getAllSwitches()) actual_ids.add(switchObj.getDPID());
+		Collections.sort(actual_ids);
+
+		assertArrayEquals(dpids.toArray(), actual_ids.toArray());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getInactiveSwitches(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetInactiveSwitches() {
+		op.newSwitch("111").setState(SwitchState.ACTIVE.toString());
+		op.newSwitch("222").setState(SwitchState.INACTIVE.toString());
+		op.commit();
+		
+		Iterator<ISwitchObject> i = op.getInactiveSwitches().iterator();
+		
+		assertTrue(i.hasNext());
+		assertEquals("222", i.next().getDPID());
+		assertFalse(i.hasNext());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getAllSwitchNotUpdatedFlowEntries(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetAllSwitchNotUpdatedFlowEntries() {
+		FlowEntryId flowEntryId10 = new FlowEntryId(10);
+		FlowEntryId flowEntryId20 = new FlowEntryId(20);
+		IFlowEntry flowEntry10 = op.newFlowEntry();
+		IFlowEntry flowEntry20 = op.newFlowEntry();
+		flowEntry10.setFlowEntryId(flowEntryId10.toString());
+		flowEntry20.setFlowEntryId(flowEntryId20.toString());
+		flowEntry10.setSwitchState("FE_SWITCH_NOT_UPDATED");
+		flowEntry20.setSwitchState("FE_SWITCH_UPDATED");
+ 		op.commit();
+		
+		Iterator<IFlowEntry> flowEntries = op.getAllSwitchNotUpdatedFlowEntries().iterator();
+		assertNotNull(flowEntries);
+		assertTrue(flowEntries.hasNext());
+		assertEquals(flowEntryId10.toString(), flowEntries.next().getFlowEntryId());
+		assertFalse(flowEntries.hasNext());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#removeSwitch(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.ISwitchObject)}.
+	 */
+	@Test
+	public final void testRemoveSwitch() {
+		ISwitchObject sw = op.newSwitch("123");
+		op.commit();	
+		sw = op.searchSwitch("123");
+		assertNotNull(sw);
+
+		op.removeSwitch(sw);
+		op.commit();
+		
+		assertNull(op.searchSwitch("123"));
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#newPort(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testNewPort() {
+		assertFalse(testdb.getVertices("type", "port").iterator().hasNext());
+		
+		IPortObject port = op.newPort("1", (short) 10);
+		assertTrue(port.getNumber() == 10);
+		op.commit();
+		
+		Iterator<Vertex> vertices = testdb.getVertices("type", "port").iterator();
+		assertTrue(vertices.hasNext());
+		assertEquals(vertices.next().getProperty("number").toString(), "10");		
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchPort(net.onrc.onos.graph.GraphDBConnection, java.lang.String, short)}.
+	 */
+	@Test
+	public final void testSearchPort() {
+		ISwitchObject sw;
+		IPortObject port;
+		
+		sw = op.newSwitch("1");
+		sw.addPort(op.newPort("1", (short) 1));
+		sw.addPort(op.newPort("1", (short) 2));
+		
+		sw = op.newSwitch("2");
+		sw.addPort(op.newPort("2", (short) 1));
+		sw.addPort(op.newPort("2", (short) 2));
+
+		op.commit();
+
+		assertNull(op.searchPort("3", (short) 1));
+		assertNull(op.searchPort("1", (short) 3));
+
+		port = op.searchPort("1", (short) 1);
+		assertNotNull(port);
+		assertTrue(port.getNumber() == 1);
+		sw = port.getSwitch();
+		assertNotNull(sw);
+		assertEquals("1", sw.getDPID());
+
+		port = op.searchPort("1", (short) 2);
+		assertNotNull(port);
+		assertTrue(port.getNumber() == 2);
+		sw = port.getSwitch();
+		assertNotNull(sw);
+		assertEquals("1", sw.getDPID());
+
+		port = op.searchPort("2", (short) 1);
+		assertNotNull(port);
+		assertTrue(port.getNumber() == 1);
+		sw = port.getSwitch();
+		assertNotNull(sw);
+		assertEquals("2", sw.getDPID());
+
+		port = op.searchPort("2", (short) 2);
+		assertNotNull(port);
+		assertTrue(port.getNumber() == 2);
+		sw = port.getSwitch();
+		assertNotNull(sw);
+		assertEquals("2", sw.getDPID());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#removePort(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.IPortObject)}.
+	 */
+	@Test
+	public final void testRemovePort() {
+		ISwitchObject sw;
+		IPortObject port;
+		
+		sw = op.newSwitch("1");
+		sw.addPort(op.newPort("1", (short) 1));
+		sw.addPort(op.newPort("1", (short) 2));
+		
+		op.commit();
+
+		port = op.searchPort("1", (short) 1);
+		assertNotNull(port);
+		assertNotNull(op.searchPort("1", (short) 2));
+		assertNull(op.searchPort("1", (short) 3));
+
+		op.removePort(port);
+		op.commit();
+		
+		assertNull(op.searchPort("1", (short) 1));
+		port = op.searchPort("1", (short) 2);
+		assertNotNull(port);
+		
+		op.removePort(port);
+		op.commit();
+
+		assertNull(op.searchPort("1", (short) 1));
+		assertNull(op.searchPort("1", (short) 2));
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#newDevice(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testNewDevice() {
+		assertFalse(testdb.getVertices("type", "device").iterator().hasNext());
+		
+		IDeviceObject device = op.newDevice();
+		device.setMACAddress("11:22:33:44:55:66");
+		device.setIPAddress("192.168.1.1");
+		op.commit();
+		
+		Iterator<Vertex> vertices = testdb.getVertices("type", "device").iterator();
+		assertTrue(vertices.hasNext());
+		Vertex v = vertices.next();
+		assertEquals("11:22:33:44:55:66", v.getProperty("dl_addr").toString());
+		assertEquals("192.168.1.1", v.getProperty("nw_addr").toString());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchDevice(net.onrc.onos.graph.GraphDBConnection, java.lang.String)}.
+	 */
+	@Test
+	public final void testSearchDevice() {
+		assertNull(op.searchDevice("11:22:33:44:55:66"));
+		assertNull(op.searchDevice("66:55:44:33:22:11"));
+
+		op.newDevice().setMACAddress("11:22:33:44:55:66");
+		op.commit();
+		
+		IDeviceObject device = op.searchDevice("11:22:33:44:55:66");
+		assertNotNull(device);
+		assertEquals("11:22:33:44:55:66", device.getMACAddress());
+		
+		assertNull(op.searchDevice("66:55:44:33:22:11"));
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getDevices(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetDevices() {
+		List<String> original_macs = Arrays.asList(
+				"11:11:11:11:11:11",
+				"22:22:22:22:22:22",
+				"33:33:33:33:33:33"
+				);
+		
+		for (String mac: original_macs) op.newDevice().setMACAddress(mac);
+		op.commit();
+		
+		Iterable<IDeviceObject> devices = op.getDevices();
+		List<String> macs = new ArrayList<String>();
+		for (IDeviceObject device: devices) macs.add(device.getMACAddress());
+		Collections.sort(macs);
+		assertArrayEquals(original_macs.toArray(), macs.toArray());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#removeDevice(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.IDeviceObject)}.
+	 */
+	@Test
+	public final void testRemoveDevice() {
+		op.newDevice().setMACAddress("11:22:33:44:55:66");
+		op.commit();
+		
+		op.removeDevice(op.searchDevice("11:22:33:44:55:66"));
+		op.commit();
+		assertNull(op.searchDevice("11:22:33:44:55:66"));
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#newFlowPath(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testNewFlowPath() {
+		FlowId flowId = new FlowId(10);
+		IFlowPath flowPath = op.newFlowPath();
+		flowPath.setFlowId(flowId.toString());
+		op.commit();
+
+		Iterator<IFlowPath> flows = op.getAllFlowPaths().iterator();
+		assertTrue(flows.hasNext());
+		assertEquals(flowId.toString(), flows.next().getFlowId());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchFlowPath(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.util.FlowId)}.
+	 */
+	@Test
+	public final void testSearchFlowPath() {
+		FlowId flowId = new FlowId(20);
+		assertNull(op.searchFlowPath(flowId));
+
+		op.newFlowPath().setFlowId(flowId.toString());
+		op.commit();
+		
+		IFlowPath flowPath = op.searchFlowPath(flowId);
+		assertNotNull(flowPath);
+		assertEquals(flowId.toString(), flowPath.getFlowId());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getFlowPathByFlowEntry(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry)}.
+	 */
+	@Test
+	public final void testGetFlowPathByFlowEntry() {
+		FlowId flowId10 = new FlowId(10);
+		FlowId flowId20 = new FlowId(20);
+		IFlowPath flowPath10 = op.newFlowPath();
+		IFlowPath flowPath20 = op.newFlowPath();
+		IFlowEntry flowEntry10 = op.newFlowEntry();
+		IFlowEntry flowEntry20 = op.newFlowEntry();
+		IFlowEntry flowEntry30 = op.newFlowEntry();
+		FlowEntryId flowEntryId10 = new FlowEntryId(10); 
+		FlowEntryId flowEntryId20 = new FlowEntryId(20); 
+		FlowEntryId flowEntryId30 = new FlowEntryId(30); 
+		flowEntry10.setFlowEntryId(flowEntryId10.toString());
+		flowEntry20.setFlowEntryId(flowEntryId20.toString());
+		flowEntry30.setFlowEntryId(flowEntryId30.toString());
+		flowPath10.setFlowId(flowId10.toString());
+		flowPath10.addFlowEntry(flowEntry10);
+		flowPath20.setFlowId(flowId20.toString());
+		flowPath20.addFlowEntry(flowEntry20);
+		op.commit();
+
+		flowEntry10 = op.searchFlowEntry(flowEntryId10);
+		IFlowPath obtainedFlowPath = op.getFlowPathByFlowEntry(flowEntry10);
+		assertNotNull(obtainedFlowPath);
+		assertEquals(flowId10.toString(), obtainedFlowPath.getFlowId());
+		
+		flowEntry20 = op.searchFlowEntry(flowEntryId20);
+		obtainedFlowPath = op.getFlowPathByFlowEntry(flowEntry20);
+		assertNotNull(obtainedFlowPath);
+		assertEquals(flowId20.toString(), obtainedFlowPath.getFlowId());
+		
+		flowEntry30 = op.searchFlowEntry(flowEntryId30);
+		obtainedFlowPath = op.getFlowPathByFlowEntry(flowEntry30);
+		assertNull(obtainedFlowPath);
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getAllFlowPaths(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetAllFlowPaths() {
+		List<FlowId> flowids = Arrays.asList(
+				new FlowId(10), new FlowId(20), new FlowId(30)
+				);
+		
+		for (FlowId flowId: flowids)
+			op.newFlowPath().setFlowId(flowId.toString());
+		op.commit();
+
+		List<String> actual_ids = new ArrayList<String>();
+		for (IFlowPath flowPath: op.getAllFlowPaths()) actual_ids.add(flowPath.getFlowId());
+		Collections.sort(actual_ids);
+
+		List<String> expected_ids = new ArrayList<String>();
+		for (FlowId flowid: flowids) expected_ids.add(flowid.toString());
+		Collections.sort(expected_ids);
+		
+		assertArrayEquals(expected_ids.toArray(), actual_ids.toArray());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#removeFlowPath(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.IFlowPath)}.
+	 */
+	@Test
+	public final void testRemoveFlowPath() {
+		FlowId flowId10 = new FlowId(10);
+		FlowId flowId20 = new FlowId(20);
+		op.newFlowPath().setFlowId(flowId10.toString());
+		op.newFlowPath().setFlowId(flowId20.toString());
+		op.commit();
+		
+		IFlowPath flowPath = op.searchFlowPath(flowId10);
+		assertNotNull(flowPath);
+		op.removeFlowPath(flowPath);
+		op.commit();
+		
+		assertNull(op.searchFlowPath(flowId10));
+		assertNotNull(op.searchFlowPath(flowId20));
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#newFlowEntry(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testNewFlowEntry() {
+		IFlowEntry flowEntry = op.newFlowEntry();
+		FlowEntryId flowEntryId = new FlowEntryId();
+		flowEntryId.setValue(12345);
+		flowEntry.setFlowEntryId(flowEntryId.toString());
+		op.commit();
+		
+		flowEntry = op.searchFlowEntry(flowEntryId);
+		assertNotNull(flowEntry);
+		assertEquals(flowEntry.getFlowEntryId(), flowEntryId.toString());		
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#searchFlowEntry(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.util.FlowEntryId)}.
+	 */
+	@Test
+	public final void testSearchFlowEntry() {
+		FlowEntryId flowEntryId10 = new FlowEntryId();
+		flowEntryId10.setValue(10);
+		FlowEntryId flowEntryId20 = new FlowEntryId();
+		flowEntryId20.setValue(20);
+		FlowEntryId flowEntryId30 = new FlowEntryId();
+		flowEntryId30.setValue(30);
+		
+		op.newFlowEntry().setFlowEntryId(flowEntryId10.toString());
+		op.newFlowEntry().setFlowEntryId(flowEntryId20.toString());
+		op.commit();
+		
+		assertNull(op.searchFlowEntry(flowEntryId30));
+		IFlowEntry flowEntry = op.searchFlowEntry(flowEntryId10);
+		assertEquals(flowEntry.getFlowEntryId(), flowEntryId10.toString());
+		flowEntry = op.searchFlowEntry(flowEntryId20);
+		assertEquals(flowEntry.getFlowEntryId(), flowEntryId20.toString());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#getAllFlowEntries(net.onrc.onos.graph.GraphDBConnection)}.
+	 */
+	@Test
+	public final void testGetAllFlowEntries() {
+		List<FlowEntryId> flowEntryIds = Arrays.asList(
+				new FlowEntryId(10), new FlowEntryId(20), new FlowEntryId(30)
+				);
+		
+		for (FlowEntryId flowEntryId: flowEntryIds)
+			op.newFlowEntry().setFlowEntryId(flowEntryId.toString());
+		op.commit();
+
+		List<String> actual_ids = new ArrayList<String>();
+		for (IFlowEntry flowEntry: op.getAllFlowEntries()) actual_ids.add(flowEntry.getFlowEntryId());
+		Collections.sort(actual_ids);
+
+		List<String> expected_ids = new ArrayList<String>();
+		for (FlowEntryId flowEntryId: flowEntryIds) expected_ids.add(flowEntryId.toString());
+		Collections.sort(expected_ids);
+		
+		assertArrayEquals(expected_ids.toArray(), actual_ids.toArray());
+	}
+
+	/**
+	 * Test method for {@link net.onrc.onos.graph.GraphDBOperation#removeFlowEntry(net.onrc.onos.graph.GraphDBConnection, net.floodlightcontroller.core.INetMapTopologyObjects.IFlowEntry)}.
+	 */
+	@Test
+	public final void testRemoveFlowEntry() {
+		FlowEntryId flowEntryId10 = new FlowEntryId(10);
+		FlowEntryId flowEntryId20 = new FlowEntryId(20);
+		op.newFlowEntry().setFlowEntryId(flowEntryId10.toString());
+		op.newFlowEntry().setFlowEntryId(flowEntryId20.toString());
+		op.commit();
+		
+		IFlowEntry flowEntry = op.searchFlowEntry(flowEntryId10);
+		assertNotNull(flowEntry);
+		op.removeFlowEntry(flowEntry);
+		op.commit();
+		
+		assertNull(op.searchFlowEntry(flowEntryId10));
+		assertNotNull(op.searchFlowEntry(flowEntryId20));
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIDeviceObjectTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIDeviceObjectTest.java
new file mode 100644
index 0000000..3ea90ba
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIDeviceObjectTest.java
@@ -0,0 +1,206 @@
+package net.onrc.onos.ofcontroller.core;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class INetMapTopologyObjectsIDeviceObjectTest {
+	
+	//The test network is ./titan/schema/test-network.xml
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+	
+	@Before
+	public void setUp() throws Exception {
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		TestDatabaseManager.deleteTestDatabase();
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		//TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set MacAddress method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the mac address.
+	 * 2. Should get the mac address.
+	 */
+	@Test
+	public void testSetGetMacAddress() {
+		String macaddr = "00:00:00:00:00:00:0a:07";
+		IDeviceObject devObj = ope.newDevice();
+		devObj.setMACAddress(macaddr);
+		assertEquals(devObj.getMACAddress(), macaddr);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set IPAddress method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the ip address.
+	 * 2. Should get the ip address.
+	 */
+	@Test
+	public void testSetGetIPAddress() {
+		String ipaddr = "192.168.0.1";
+		IDeviceObject devObj = ope.newDevice();
+		devObj.setIPAddress(ipaddr);
+		assertEquals(devObj.getIPAddress(), ipaddr);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get attached port.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the attached ports.
+	 */
+	@Test
+	public void testGetAttachedPort() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short number = 1;	
+		Short number2 = 2;
+		IPortObject portObj = ope.newPort(dpid, number);
+		IPortObject portObj2 = ope.newPort(dpid, number2);
+		
+		String ipaddr = "192.168.0.1";
+		IDeviceObject devObj = ope.newDevice();
+		
+		portObj.setDevice(devObj);
+		portObj2.setDevice(devObj);
+		
+		HashMap<Short, IPortObject> portObjectList = new HashMap<Short, IPortObject>();
+		for(IPortObject port : devObj.getAttachedPorts())
+		{
+			portObjectList.put(port.getNumber(), port);
+		}
+		
+		assertTrue(portObjectList.containsValue(portObj));
+		assertTrue(portObjectList.containsValue(portObj2));
+		
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and remove host port method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set host port from the device.
+	 * 2. Should remove host port from the device.
+	 */
+	@Test
+	public void testSetRemoveHostPort() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short number = 1;	
+		Short number2 = 2;
+		IPortObject portObj = ope.newPort(dpid, number);
+		IPortObject portObj2 = ope.newPort(dpid, number2);
+		
+		String ipaddr = "192.168.0.1";
+		IDeviceObject devObj = ope.newDevice();
+		
+		devObj.setHostPort(portObj);
+		
+		HashMap<String, IDeviceObject> portObjectList = new HashMap<String, IDeviceObject>();
+		for(IDeviceObject dev : portObj.getDevices())
+		{
+			portObjectList.put(dev.getMACAddress(), dev);
+		}
+		assertTrue(portObjectList.containsValue(devObj));
+		
+		devObj.removeHostPort(portObj);
+		
+		HashMap<String, IDeviceObject> portObjectList2 = new HashMap<String, IDeviceObject>();
+		for(IDeviceObject dev : portObj.getDevices())
+		{
+			portObjectList2.put(dev.getMACAddress(), dev);
+		}
+		assertTrue(!portObjectList2.containsValue(devObj));
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for getSwitch method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the switch connected to the device.
+	 */
+	@Test
+	public void testGetSwitches() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String dpid2 = "00:00:00:00:00:00:0a:08";
+		Short number = 1;	
+		Short number2 = 2;	
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		ISwitchObject swObj2 = ope.newSwitch(dpid2);
+		IPortObject portObj = ope.newPort(dpid, number);
+		IPortObject portObj2 = ope.newPort(dpid2, number2);
+		swObj.addPort(portObj);
+		swObj2.addPort(portObj2);
+		IDeviceObject devObj = ope.newDevice();
+		portObj.setDevice(devObj);
+		portObj2.setDevice(devObj);
+		
+		HashMap<String, ISwitchObject> switchObjectList = new HashMap<String, ISwitchObject>();
+		for(ISwitchObject sw : devObj.getSwitch())
+		{
+			switchObjectList.put(sw.getDPID(), sw);
+		}
+		assertTrue(switchObjectList.containsValue(swObj));
+		assertTrue(switchObjectList.containsValue(swObj2));
+	}
+	
+	
+}
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
new file mode 100644
index 0000000..06d8522
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowEntryTest.java
@@ -0,0 +1,444 @@
+package net.onrc.onos.ofcontroller.core;
+
+import static org.junit.Assert.*;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class INetMapTopologyObjectsIFlowEntryTest {
+	
+	//The test network is ./titan/schema/test-network.xml
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+	private IFlowEntry flowEntry = null;
+	
+	@Before
+	public void setUp() throws Exception {
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		TestDatabaseManager.deleteTestDatabase();
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		//TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+		
+		flowEntry = ope.newFlowEntry();
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get FlowEntryId.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set FlowEntryId.
+	 * 2. Should get FlowEntryId.
+	 */
+	@Test
+	public void testSetGetFlowEntryId() {
+		String flowEntryId = "xx";
+		flowEntry.setFlowEntryId(flowEntryId);
+		assertEquals(flowEntry.getFlowEntryId(), flowEntryId);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get SwitchDpid.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set SwitchDpid.
+	 * 2. Should get SwitchDpid.
+	 */
+	@Test
+	public void testSetGetSwitchDpid() {
+		String switchDpid = "00:00:00:00:00:11";
+		flowEntry.setSwitchDpid(switchDpid);
+		assertEquals(flowEntry.getSwitchDpid(), switchDpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get UserState.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set UserState.
+	 * 2. Should get UserState.
+	 */
+	@Test
+	public void testSetGetUserState() {
+		String userStete = "good";
+		flowEntry.setUserState(userStete);
+		assertEquals(flowEntry.getUserState(), userStete);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get SwitchState.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set SwitchState.
+	 * 2. Should get SwitchState.
+	 */
+	@Test
+	public void testSetGetSwitchState() {
+		String switchStete = "ACTIVE";
+		flowEntry.setSwitchState(switchStete);
+		assertEquals(flowEntry.getSwitchState(), switchStete);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get ErrorStateType.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set ErrorStateType.
+	 * 2. Should get ErrorStateType.
+	 */
+	@Test
+	public void testSetGetErrorStateType() {
+		String errorSteteType = "error";
+		flowEntry.setErrorStateType(errorSteteType);
+		assertEquals(flowEntry.getErrorStateType(), errorSteteType);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get ErrorStateCode.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set ErrorStateCode.
+	 * 2. Should get ErrorStateCode.
+	 */
+	@Test
+	public void testSetGetErrorStateCode() {
+		String errorSteteCode = "error";
+		flowEntry.setErrorStateCode(errorSteteCode);
+		assertEquals(flowEntry.getErrorStateCode(), errorSteteCode);
+	}	
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchInPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchInPort.
+	 * 2. Should get MatchInPort.
+	 */
+	@Test
+	public void testSetGetMatchInPort() {
+		Short inPort = 1;
+		flowEntry.setMatchInPort(inPort);
+		assertEquals(flowEntry.getMatchInPort(), inPort);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchSrcMac.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchSrcMac.
+	 * 2. Should get MatchSrcMac.
+	 */
+	@Test
+	public void testSetGetMatchSrcMac() {
+		String matchSrcMac = "00:00:00:00:00:11";
+		flowEntry.setMatchSrcMac(matchSrcMac);
+		assertEquals(flowEntry.getMatchSrcMac(), matchSrcMac);
+	}	
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstMac.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstMac.
+	 * 2. Should get MatchDstMac.
+	 */
+	@Test
+	public void testSetGetMatchDstMac() {
+		String matchDstMac = "00:00:00:00:00:11";
+		flowEntry.setMatchDstMac(matchDstMac);
+		assertEquals(flowEntry.getMatchDstMac(), matchDstMac);
+	}	
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchEthernetFrameType.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchEthernetFrameType.
+	 * 2. Should get MatchEthernetFrameType.
+	 */
+	@Test
+	public void testSetGetMatchEthernetFrameType() {
+		Short matchEthernetFrameType = 1;
+		flowEntry.setMatchEthernetFrameType(matchEthernetFrameType);
+		assertEquals(flowEntry.getMatchEthernetFrameType(), matchEthernetFrameType);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchVlanId.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchVlanId.
+	 * 2. Should get MatchVlanId.
+	 */
+	@Test
+	public void testSetGetMatchVlanId() {
+		Short matchVlanId = 10;
+		flowEntry.setMatchVlanId(matchVlanId);
+		assertEquals(flowEntry.getMatchVlanId(), matchVlanId);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchVlanPriority.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchVlanPriority.
+	 * 2. Should get MatchVlanPriority.
+	 */
+	@Test
+	public void testSetGetMatchVlanPriority() {
+		Byte matchVlanPriority = 10;
+		flowEntry.setMatchVlanPriority(matchVlanPriority);
+		assertEquals(flowEntry.getMatchVlanPriority(), matchVlanPriority);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get SrcIPv4Net.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set SrcIPv4Net.
+	 * 2. Should get SrcIPv4Net.
+	 */
+	@Test
+	public void testSetGetMatchSrcIPv4Net() {
+		String srcIPv4Net = "192.168.0.1";
+		flowEntry.setMatchSrcIPv4Net(srcIPv4Net);
+		assertEquals(flowEntry.getMatchSrcIPv4Net(), srcIPv4Net);
+	}	
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstIPv4Net.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstIPv4Net.
+	 * 2. Should get MatchDstIPv4Net.
+	 */
+	@Test
+	public void testSetGetMatchDstIPv4Net() {
+		String dstIPv4Net = "192.168.0.1";
+		flowEntry.setMatchDstIPv4Net(dstIPv4Net);
+		assertEquals(flowEntry.getMatchDstIPv4Net(), dstIPv4Net);
+	}	
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchIpProto.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchIpProto.
+	 * 2. Should get MatchIpProto.
+	 */
+	@Test
+	public void testSetGetMatchIpProto() {
+		Byte matchIpProto = 20;
+		flowEntry.setMatchIpProto(matchIpProto);
+		assertEquals(flowEntry.getMatchIpProto(), matchIpProto);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchIpToS.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchIpToS.
+	 * 2. Should get MatchIpToS.
+	 */
+	@Test
+	public void testSetGetMatchIpToS() {
+		Byte matchIpToS = 20;
+		flowEntry.setMatchIpToS(matchIpToS);
+		assertEquals(flowEntry.getMatchIpToS(), matchIpToS);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchSrcTcpUdpPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchSrcTcpUdpPort.
+	 * 2. Should get MatchSrcTcpUdpPort.
+	 */
+	@Test
+	public void testSetGetMatchSrcTcpUdpPort() {
+		Short srcTcpUdpPort = (short)65535;
+		flowEntry.setMatchSrcTcpUdpPort(srcTcpUdpPort);
+		assertEquals(flowEntry.getMatchSrcTcpUdpPort(), srcTcpUdpPort);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstTcpUdpPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstTcpUdpPort.
+	 * 2. Should get MatchDstTcpUdpPort.
+	 */
+	@Test
+	public void testSetGetMatchDstTcpUdpPort() {
+		Short dstTcpUdpPort = (short)65535;
+		flowEntry.setMatchDstTcpUdpPort(dstTcpUdpPort);
+		assertEquals(flowEntry.getMatchDstTcpUdpPort(), dstTcpUdpPort);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get ActionOutputPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set ActionOutputPort.
+	 * 2. Should get ActionOutputPort.
+	 */
+	@Test
+	public void testSetGetActionOutputPort() {
+		Short actionOutputPort = 1;
+		flowEntry.setActionOutputPort(actionOutputPort);
+		assertEquals(flowEntry.getActionOutputPort(), actionOutputPort);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get FlowPath.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set FlowPath.
+	 * 2. Should get FlowPath.
+	 */
+	@Test
+	public void testSetGetFlowPath() {
+		IFlowPath fp = ope.newFlowPath();
+		String flowId = "xx";
+		fp.setFlowId(flowId);
+		flowEntry.setFlow(fp);
+		IFlowPath fp2 = flowEntry.getFlow();
+		assertEquals(fp2.getFlowId(), flowId);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get Switch.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set Switch.
+	 * 2. Should get Switch.
+	 */
+	@Test
+	public void testSetGetSwitch() {
+		String dpid = "00:00:00:00:00:22";
+		ISwitchObject sw1 = ope.newSwitch(dpid);
+		flowEntry.setSwitch(sw1);
+		ISwitchObject sw2 = flowEntry.getSwitch();
+		assertEquals(sw2, sw1);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get InPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set InPort.
+	 * 2. Should get InPort.
+	 */
+	@Test
+	public void testSetGetInPort() {
+		String dpid = "00:00:00:00:00:22";
+		Short portNum = 4;
+		IPortObject port1 = ope.newPort(dpid, portNum);
+		flowEntry.setInPort(port1);
+		IPortObject port2 = flowEntry.getInPort();
+		assertEquals(port2, port1);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get OutPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set OutPort.
+	 * 2. Should get OutPort.
+	 */
+	@Test
+	public void testSetGetOutPort() {
+		String dpid = "00:00:00:00:00:22";
+		Short portNum = 4;
+		IPortObject port1 = ope.newPort(dpid, portNum);
+		flowEntry.setOutPort(port1);
+		IPortObject port2 = flowEntry.getOutPort();
+		assertEquals(port2, port1);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java
new file mode 100644
index 0000000..bb0dbbf
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIFlowPathTest.java
@@ -0,0 +1,509 @@
+package net.onrc.onos.ofcontroller.core;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class INetMapTopologyObjectsIFlowPathTest {
+	
+	//The test network is ./titan/schema/test-network.xml
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+	private IFlowPath flowPath = null;
+	private IFlowEntry flowEntry = null;
+	
+	@Before
+	public void setUp() throws Exception {
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		TestDatabaseManager.deleteTestDatabase();
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		//TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+		
+		flowPath = ope.newFlowPath();
+		flowEntry = ope.newFlowEntry();
+		flowEntry.setState("zz");
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set FlowId method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the flow id.
+	 * 2. Should get the flow id.
+	 */
+	@Test
+	public void testSetGetFlowId() {
+		String flowId = "xx";
+		flowPath.setFlowId(flowId);
+		assertEquals(flowPath.getFlowId(), flowId);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set InstallerId method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the installer id.
+	 * 2. Should get the installer id.
+	 */
+	@Test
+	public void testSetGetInstallerId() {
+		String flowId = "xx";
+		String installerId = "yy";
+		flowPath.setFlowId(flowId);
+		flowPath.setInstallerId(installerId);
+		assertEquals(flowPath.getInstallerId(), installerId);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for get and set FlowPathFlags method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the Flow Path Flags.
+	 * 2. Should get the Flow Path Flags.
+	 */
+	@Test
+	public void testSetGetFlowPathFlags() {
+		String flowId = "xx";
+		Long flowPathFlags = new Long(0x3);
+		flowPath.setFlowId(flowId);
+		flowPath.setFlowPathFlags(flowPathFlags);
+		assertEquals(flowPath.getFlowPathFlags(), flowPathFlags);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for get and set SourceSwitch method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the source switch.
+	 * 2. Should get the source switch.
+	 */
+	@Test
+	public void testSetGetSourceSwitch() {
+		String flowId = "xx";
+		String sourceSwitch = "aa";
+		flowPath.setFlowId(flowId);
+		flowPath.setSrcSwitch(sourceSwitch);
+		assertEquals(flowPath.getSrcSwitch(), sourceSwitch);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set SourcePort method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the source port.
+	 * 2. Should get the source port.
+	 */
+	@Test
+	public void testSetGetSourcePort() {
+		String flowId = "xx";
+		Short sourcePort = 1;
+		flowPath.setFlowId(flowId);
+		flowPath.setSrcPort(sourcePort);
+		assertEquals(flowPath.getSrcPort(), sourcePort);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set DestSwitch method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the dest switch.
+	 * 2. Should get the dest switch.
+	 */
+	@Test
+	public void testSetGetDestSwitch() {
+		String flowId = "xx";
+		String destSwitch = "bb";
+		flowPath.setFlowId(flowId);
+		flowPath.setDstSwitch(destSwitch);
+		assertEquals(flowPath.getDstSwitch(), destSwitch);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set DestPort method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the source dest port.
+	 * 2. Should get the source dest port.
+	 */
+	@Test
+	public void testSetGetDstPort() {
+		String flowId = "xx";
+		Short dstPort = 2;
+		flowPath.setFlowId(flowId);
+		flowPath.setDstPort(dstPort);
+		assertEquals(flowPath.getDstPort(), dstPort);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set DataPathSummary method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the data path summary.
+	 * 2. Should get the data path summary.
+	 */
+	@Test
+	public void testSetGetDataPathSummary() {
+		String flowId = "xx";
+		String dataPathSummary = "yy";
+		flowPath.setFlowId(flowId);
+		flowPath.setInstallerId(dataPathSummary);
+		assertEquals(flowPath.getInstallerId(), dataPathSummary);
+	}
+	
+	public boolean testIFlowEntry(IFlowPath fp, IFlowEntry fe)
+	{
+		ArrayList<IFlowEntry> flowEntryList = new ArrayList<IFlowEntry>();
+		for(IFlowEntry inFlowEntry : fp.getFlowEntries())
+		{
+			flowEntryList.add(inFlowEntry);
+		}
+		return flowEntryList.contains(fe);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addFlowEntry and getFlorEntries method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should add the FlowEntry.
+	 * 2. Should get the FlowEntries. It is tested in the testIFlowEntry method.
+	 */
+	@Test
+	public void testAddFlowEntryAndGetFlowEntries() {
+		String flowId = "xx";
+		flowPath.setFlowId(flowId);
+		flowPath.addFlowEntry(flowEntry);
+		IFlowEntry flowEntry2 = ope.newFlowEntry();
+		flowPath.addFlowEntry(flowEntry2);
+		assertTrue(testIFlowEntry(flowPath, flowEntry));
+		assertTrue(testIFlowEntry(flowPath, flowEntry2));
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for remove FlowEntry.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should remove FlowEntry.
+	 */
+	@Test
+	public void testRemoveFlowEntry() {
+		String flowId = "xx";
+		flowPath.setFlowId(flowId);
+		flowPath.addFlowEntry(flowEntry);
+		flowPath.removeFlowEntry(flowEntry);
+		assertTrue(!testIFlowEntry(flowPath, flowEntry));
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchSrcMac
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchSrcMac.
+	 * 2. Should get MatchSrcMac.
+	 */
+	@Test
+	public void testSetGetMatchSrcMac() {
+		String flowId = "xx";
+		String matchSrcMac = "00:00:00:00:00:11";
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchSrcMac(matchSrcMac);
+		assertEquals(flowPath.getMatchSrcMac(), matchSrcMac);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstMac.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstMac.
+	 * 2. Should get MatchDstMac.
+	 */
+	@Test
+	public void testSetGetMatchDstMac() {
+		String flowId = "xx";
+		String matchDstMac = "00:00:00:00:00:11";
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchDstMac(matchDstMac);
+		assertEquals(flowPath.getMatchDstMac(), matchDstMac);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchEthernetFrameType
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchEthernetFrameType.
+	 * 2. Should get MatchEthernetFrameType.
+	 */
+	@Test
+	public void testSetGetMatchEthernetFrameType() {
+		String flowId = "xx";
+		Short matchEthernetFrameType = 1;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchEthernetFrameType(matchEthernetFrameType);
+		assertEquals(flowPath.getMatchEthernetFrameType(), matchEthernetFrameType);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchVlanId
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchVlanId.
+	 * 2. Should get MatchVlanId.
+	 */
+	@Test
+	public void testSetGetMatchVlanId() {
+		String flowId = "xx";
+		Short matchVlanId = 10;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchVlanId(matchVlanId);
+		assertEquals(flowPath.getMatchVlanId(), matchVlanId);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchVlanPriority
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchVlanPriority.
+	 * 2. Should get MatchVlanPriority.
+	 */
+	@Test
+	public void testSetGetMatchVlanPriority() {
+		String flowId = "xx";
+		Byte matchVlanPriority = 20;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchVlanPriority(matchVlanPriority);
+		assertEquals(flowPath.getMatchVlanPriority(), matchVlanPriority);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchSrcIPv4Net.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchSrcIPv4Net.
+	 * 2. Should get MatchSrcIPv4Net.
+	 */
+	@Test
+	public void testSetGetMatchSrcIPv4Net() {
+		String flowId = "xx";
+		String ip = "192.168.0.1";
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchSrcIPv4Net(ip);
+		assertEquals(flowPath.getMatchSrcIPv4Net(), ip);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstIPv4Net.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstIPv4Net.
+	 * 2. Should get MatchDstIPv4Net.
+	 */
+	@Test
+	public void testSetGetMatchDstIPv4Net() {
+		String flowId = "xx";
+		String ip = "192.168.0.1";
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchDstIPv4Net(ip);
+		assertEquals(flowPath.getMatchDstIPv4Net(), ip);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchIpProto
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchIpProto.
+	 * 2. Should get MatchIpProto.
+	 */
+	@Test
+	public void testSetGetMatchIpProto() {
+		String flowId = "xx";
+		Byte matchIpProto = 20;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchIpProto(matchIpProto);
+		assertEquals(flowPath.getMatchIpProto(), matchIpProto);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchIpToS
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchIpToS.
+	 * 2. Should get MatchIpToS.
+	 */
+	@Test
+	public void testSetGetMatchIpToS() {
+		String flowId = "xx";
+		Byte matchIpToS = 20;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchIpToS(matchIpToS);
+		assertEquals(flowPath.getMatchIpToS(), matchIpToS);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchSrcTcpUdpPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchSrcTcpUdpPort.
+	 * 2. Should get MatchSrcTcpUdpPort.
+	 */
+	@Test
+	public void testSetGetMatchSrcTcpUdpPort() {
+		String flowId = "xx";
+		Short srcTcpUdpPort = (short)65535;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchSrcTcpUdpPort(srcTcpUdpPort);
+		assertEquals(flowPath.getMatchSrcTcpUdpPort(), srcTcpUdpPort);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get MatchDstTcpUdpPort.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set MatchDstTcpUdpPort.
+	 * 2. Should get MatchDstTcpUdpPort.
+	 */
+	@Test
+	public void testSetGetMatchDstTcpUdpPort() {
+		String flowId = "xx";
+		Short dstTcpUdpPort = (short)65535;
+		flowPath.setFlowId(flowId);
+		flowPath.setMatchDstTcpUdpPort(dstTcpUdpPort);
+		assertEquals(flowPath.getMatchDstTcpUdpPort(), dstTcpUdpPort);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for set and get UserState.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set UserState.
+	 * 2. Should get UserState.
+	 */
+	@Test
+	public void testSetGetUserState() {
+		String flowId = "xx";
+		String userStatus = "Good";
+		flowPath.setFlowId(flowId);
+		flowPath.setUserState(userStatus);
+		assertEquals(flowPath.getUserState(), userStatus);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get Switches.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get switches.
+	 */
+	@Test
+	public void testGetSwitches() {
+		String flowId = "xx";
+		String dpid = "1";
+		flowPath.setFlowId(flowId);
+		ISwitchObject sw = ope.newSwitch(dpid);
+		flowEntry.setSwitch(sw);
+		flowPath.addFlowEntry(flowEntry);
+		
+		HashMap<String, ISwitchObject> swList = new HashMap<String, ISwitchObject>();
+		for(ISwitchObject insw : flowPath.getSwitches()){
+			swList.put(sw.getDPID(), insw);
+		}
+		
+		assertTrue(swList.containsKey(dpid));
+	}
+	
+	//TODO Dont know how to set the state property.
+	@Test
+	public void testGetState() {
+		String status = null;
+		assertEquals(flowPath.getState(), status);
+	}
+	
+	
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIPortObjectTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIPortObjectTest.java
new file mode 100644
index 0000000..2ddab3d
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsIPortObjectTest.java
@@ -0,0 +1,359 @@
+package net.onrc.onos.ofcontroller.core;
+
+import static org.junit.Assert.*;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import net.onrc.onos.ofcontroller.flowmanager.FlowManager;
+import net.onrc.onos.ofcontroller.util.FlowId;
+import net.onrc.onos.ofcontroller.util.FlowPath;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class INetMapTopologyObjectsIPortObjectTest {
+	
+	//The test network is ./titan/schema/test-network.xml
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+    
+    private ISwitchObject swObj;
+    private IPortObject portObj;
+    private IPortObject portObj2;
+    String dpid;
+    Short number;
+    Short number2;
+    
+    private ISwitchObject swObjParty;
+    private IPortObject portObjParty1;
+    private IPortObject portObjParty2;  
+    String dpidParty;
+    Short numberParty1;
+    Short numberParty2;
+    
+    
+	@Before
+	public void setUp() throws Exception {
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		TestDatabaseManager.deleteTestDatabase();
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		//TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+		
+		dpid = "00:00:00:00:00:00:0a:07";
+		number = 1;	
+		number2 = 2;
+		swObj = ope.newSwitch(dpid);
+		portObj = ope.newPort(dpid, number);
+		portObj2 = ope.newPort(dpid, number2);
+
+		swObj.addPort(portObj);	
+		swObj.addPort(portObj2);
+		
+		dpidParty = "00:00:00:00:00:00:0a:08";
+		numberParty1 = 1;
+		numberParty2 = 2;
+		swObjParty = ope.newSwitch(dpidParty);
+		portObjParty1 = ope.newPort(dpidParty, numberParty1);
+		portObjParty2 = ope.newPort(dpidParty, numberParty2);
+		swObjParty.addPort(portObjParty1);	
+		swObjParty.addPort(portObjParty2);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get port number property.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the port number.
+	 * 2. Should get the port number.
+	 */
+	@Test
+	public void testSetGetNumber() {
+		assertEquals(portObj.getNumber(), number);
+		Short testedNumber = 4;
+		portObj.setNumber(testedNumber);
+		assertEquals(portObj.getNumber(), testedNumber);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get port id property.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the port id.
+	 * 2. Should get the port id.
+	 */
+	@Test
+	public void testSetGetPortId() {
+		String portId = "test1";
+		portObj.setPortId(portId);
+		assertEquals(portObj.getPortId(), portId);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get port desc property.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the port desc.
+	 * 2. Should get the port desc.
+	 */
+	@Test
+	public void testSetGetDesc() {
+		String testedDesc = "port 4 at ATL Switch";
+		portObj.setDesc(testedDesc);
+		assertEquals(portObj.getDesc(), testedDesc);
+	}
+	
+	
+	/**
+	 * Desc:
+	 *  Test method for set and get port status property.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the port status.
+	 * 2. Should get the port status.
+	 */
+	@Test
+	public void testSetGetPortState() {
+		Integer portState = OFPortState.OFPPS_STP_FORWARD.getValue();
+		portObj.setPortState(portState);
+		assertEquals(portObj.getPortState(), portState);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get switch object.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the switch status.
+	 */
+	@Test
+	public void testGetSwitch() {
+		ISwitchObject sw = portObj.getSwitch();
+		assertEquals(sw.getDPID(), dpid);
+	}
+	
+	private boolean checkIDeviceObject(IPortObject IportObj, String mac)
+	{
+		HashMap<String, IDeviceObject> devList = new HashMap<String, IDeviceObject>();
+		for(IDeviceObject IdevObj : IportObj.getDevices())
+		{
+			devList.put(IdevObj.getMACAddress(), IdevObj);
+		}
+		return devList.containsKey(mac);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set and remove device object.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the device object.
+	 * 2. SHould remove the device object.
+	 */
+	@Test
+	public void testSetAndRemoveDevice() {
+		IDeviceObject devObj = ope.newDevice();
+		String devMac = "00:00:00:00:00:11";
+		devObj.setMACAddress(devMac);
+		
+		boolean b = checkIDeviceObject(portObj, devMac);
+		assertTrue(!b);
+		portObj.setDevice(devObj);
+		boolean b2 = checkIDeviceObject(portObj, devMac);
+		assertTrue(b2);
+		
+		portObj.removeDevice(devObj);
+		boolean b3 = checkIDeviceObject(portObj, devMac);
+		assertTrue(!b3);
+		
+	}	
+	
+	/**
+	 * Desc:
+	 *  Test method for get devices object.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the device objects.
+	 */
+	@Test
+	public void testGetDevices() {
+		IDeviceObject devObj = ope.newDevice();
+		String devMac = "58:55:ca:c4:1b:a0";
+		devObj.setMACAddress(devMac);
+		
+		portObj.setDevice(devObj);
+		boolean b = checkIDeviceObject(portObj, devMac);
+		assertTrue(b);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for set, get and remove linked port.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the linked objects.
+	 * 2. Should get the linked objects.
+	 * 3. SHould remove the liked objects.
+	 */
+	@Test
+	public void testSetGetRemoveLinkedPorts() {
+		String dpidParty = "00:00:00:00:00:00:00:08";
+		ISwitchObject swParty = ope.newSwitch(dpidParty);
+		Short poShort = 1;
+		IPortObject poParty = ope.newPort(dpidParty, poShort);
+		swParty.addPort(poParty);
+		
+		portObj.setLinkPort(poParty);
+		
+		ArrayList<IPortObject> iPortList = new ArrayList<IPortObject>();
+		for(IPortObject port : portObj.getLinkedPorts()) {
+			iPortList.add(port);
+		}	
+		assertTrue(iPortList.contains(poParty));	
+		
+		portObj.removeLink(poParty);
+		
+		ArrayList<IPortObject> iPortList2 = new ArrayList<IPortObject>();
+		for(IPortObject port : portObj.getLinkedPorts()) {
+			iPortList2.add(port);
+		}	
+		
+		assertTrue(!iPortList2.contains(poParty));
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get inbound flowEntry
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the inbound flowEntry.
+	 */
+	@Test
+	public void testGetInFlowEntries() {
+
+		portObj.setLinkPort(portObj2);
+		
+		IFlowPath flowPathObj = ope.newFlowPath();
+		
+		String flowEId = "1";
+		IFlowEntry flowEntryObj = ope.newFlowEntry();		
+		flowEntryObj.setFlowEntryId(flowEId);
+		flowEntryObj.setInPort(portObj);
+		flowEntryObj.setOutPort(portObj2);
+		flowEntryObj.setSwitch(swObj);
+		flowEntryObj.setFlow(flowPathObj);
+		
+		String flowEId2 = "2";
+		IFlowEntry flowEntryObj2 = ope.newFlowEntry();		
+		flowEntryObj2.setFlowEntryId(flowEId2);
+		flowEntryObj2.setInPort(portObjParty1);
+		flowEntryObj2.setOutPort(portObjParty2);
+		flowEntryObj.setSwitch(swObjParty);
+		flowEntryObj2.setFlow(flowPathObj);
+		
+		HashMap<String, IFlowEntry> flowEntryList = new HashMap<String, IFlowEntry>();
+		for(IFlowEntry flowEnt : portObj.getInFlowEntries())
+		{				
+			flowEntryList.put(flowEnt.getFlowEntryId(), flowEnt);
+		}
+		
+		assertTrue(flowEntryList.containsValue(flowEntryObj));
+		
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get outbound flowEntry
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the outbound flowEntry.
+	 */
+	@Test
+	public void testGetOutFlowEntries() {
+		
+		portObj.setLinkPort(portObj2);
+		
+		IFlowPath flowPathObj = ope.newFlowPath();
+		
+		String flowEId = "1";
+		IFlowEntry flowEntryObj = ope.newFlowEntry();		
+		flowEntryObj.setFlowEntryId(flowEId);
+		flowEntryObj.setInPort(portObj);
+		flowEntryObj.setOutPort(portObj2);
+		flowEntryObj.setSwitch(swObj);
+		flowEntryObj.setFlow(flowPathObj);
+		
+		String flowEId2 = "2";
+		IFlowEntry flowEntryObj2 = ope.newFlowEntry();		
+		flowEntryObj2.setFlowEntryId(flowEId2);
+		flowEntryObj2.setInPort(portObjParty1);
+		flowEntryObj2.setOutPort(portObjParty2);
+		flowEntryObj.setSwitch(swObjParty);
+		flowEntryObj2.setFlow(flowPathObj);
+		
+		HashMap<String, IFlowEntry> flowEntryList = new HashMap<String, IFlowEntry>();
+		for(IFlowEntry flowEnt : portObj2.getOutFlowEntries())
+		{				
+			flowEntryList.put(flowEnt.getFlowEntryId(), flowEnt);
+		}
+		
+		assertTrue(flowEntryList.containsValue(flowEntryObj));
+		
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsISwitchObjectTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsISwitchObjectTest.java
new file mode 100644
index 0000000..c4dca4b
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/INetMapTopologyObjectsISwitchObjectTest.java
@@ -0,0 +1,285 @@
+package net.onrc.onos.ofcontroller.core;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class INetMapTopologyObjectsISwitchObjectTest {
+	
+	//The test network is ./titan/schema/test-network.xml
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+	
+	@Before
+	public void setUp() throws Exception {
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		TestDatabaseManager.deleteTestDatabase();
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		//TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set state method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the status of the switch.
+	 * 2. Should get the status of the switch.
+	 */
+	@Test
+	public void testSetGetState() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		swObj.setState(state);
+		assertEquals(swObj.getState(), state);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for get and set Type method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the Type of the switch.
+	 * 2. Should get the Type of the switch.
+	 */
+	@Test
+	public void testSetGetType() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String type = "Switch";
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		swObj.setType("Switch");
+		assertEquals(swObj.getType(), type);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for getDPID method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get the dpid of the switch.
+	 */
+	@Test
+	public void testGetDPID() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		
+		assertEquals(swObj.getDPID(), dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for setDPID method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should set the dpid of the switch.
+	 */
+	@Test
+	public void testSetDPID() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String dpid2 = "00:00:00:00:00:00:0a:08";
+		ISwitchObject obj = ope.newSwitch(dpid);
+		assertEquals(obj.getDPID(), dpid);
+		
+		obj.setDPID(dpid2);
+		assertEquals(obj.getDPID(), dpid2);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for getPorts method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get all of ports taken by the switch.
+	 */
+	@Test
+	public void testGetPorts() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short portNumber = 1;
+		int testSwitchPortNumber = 1;
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		IPortObject portObj = ope.newPort(dpid, portNumber);
+
+		swObj.addPort(portObj);
+		int i = 0;
+		for(IPortObject port : swObj.getPorts()){
+			i++;
+		}
+		assertEquals(testSwitchPortNumber, 1);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for add and getPort method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should add the port.
+	 * 1. Should get the port.
+	 */
+	@Test
+	public void testGetPort() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short portNumber = 1;
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		IPortObject portObj = ope.newPort(dpid, portNumber);
+		
+		swObj.addPort(portObj);
+		IPortObject portObj2 = swObj.getPort(portNumber);
+		assertEquals(portObj, portObj2);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for add and removePort method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should add a port to the switch.
+	 * 1. Should remove a port from the switch.
+	 */
+	@Test
+	public void testAddRemovePorts() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short portNum = 1;
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		IPortObject portObj = ope.newPort(dpid, portNum);
+		swObj.addPort(portObj);
+		
+		IPortObject portObj2 = swObj.getPort(portNum);
+		assertEquals(portObj2, portObj);
+		swObj.removePort(portObj);
+		assertNull(swObj.getPort(portNum));
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for getDevices method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get all devices attached to the switch.
+	 */
+	@Test
+	public void testGetDevices() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short portNum = 1;
+		String devMac = "00:00:00:00:00:11";
+		int numOfDev = 1;
+		
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		IPortObject portObj = ope.newPort(dpid, portNum);
+		IDeviceObject devObj = ope.newDevice();
+		devObj.setMACAddress(devMac);
+		swObj.addPort(portObj);
+		portObj.setDevice(devObj);
+		
+		int i = 0;
+		for(IDeviceObject dev : swObj.getDevices()){
+			i++;
+		}
+		assertEquals(i, numOfDev);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for getFlowEntries method.
+	 * Condition:
+	 *  N/A
+	 * Expect:
+	 * 1. Should get all flowEntries attached to the switch.
+	 */
+	@Test
+	public void testGetFlowEntries() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		Short number = 1;	
+		Short number2 = 2;
+		Short number3 = 3;
+		ISwitchObject swObj = ope.newSwitch(dpid);
+		IPortObject portObj = ope.newPort(dpid, number);
+		IPortObject portObj2 = ope.newPort(dpid, number2);
+		IPortObject portObj3 = ope.newPort(dpid, number3);
+
+		swObj.addPort(portObj);	
+		swObj.addPort(portObj2);
+		swObj.addPort(portObj3);
+		
+		IFlowPath flowPathObj = ope.newFlowPath();
+		
+		String flowEId = "1";
+		IFlowEntry flowEntryObj = ope.newFlowEntry();		
+		flowEntryObj.setFlowEntryId(flowEId);
+		flowEntryObj.setInPort(portObj);
+		flowEntryObj.setOutPort(portObj2);
+		flowEntryObj.setSwitch(swObj);
+		flowEntryObj.setFlow(flowPathObj);
+		
+		String flowEId2 = "2";
+		IFlowEntry flowEntryObj2 = ope.newFlowEntry();		
+		flowEntryObj2.setFlowEntryId(flowEId2);
+		flowEntryObj2.setInPort(portObj);
+		flowEntryObj2.setOutPort(portObj3);
+		flowEntryObj2.setSwitch(swObj);
+		flowEntryObj2.setFlow(flowPathObj);
+		
+		HashMap<String, IFlowEntry> flowEntryList = new HashMap<String, IFlowEntry>();
+		for(IFlowEntry flowEnt : swObj.getFlowEntries())
+		{				
+			flowEntryList.put(flowEnt.getFlowEntryId(), flowEnt);
+		}
+		
+		assertTrue(flowEntryList.containsValue(flowEntryObj));
+		assertTrue(flowEntryList.containsValue(flowEntryObj2));
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
new file mode 100644
index 0000000..9b1c4d6
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/LinkStorageImplTest.java
@@ -0,0 +1,802 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.routing.Link;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.ILinkStorage;
+import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
+
+import org.easymock.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.util.HexString;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Unit test for {@link LinkStorageImpl}.
+ * @author Naoki Shiota
+ *
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({LinkStorageImpl.class, GraphDBConnection.class, GraphDBOperation.class})
+public class LinkStorageImplTest {
+	protected static Logger log = LoggerFactory.getLogger(LinkStorageImplTest.class);
+
+	private static ILinkStorage linkStorage;
+	
+	// Mock GraphDBConnection (do nothing)
+	private static GraphDBConnection conn;
+	
+	// Mock GraphDBOperation (mocks port-related methods only)
+	private static GraphDBOperation ope;
+	
+	// Uncommitted actions executed in LinkStorageImpl
+	private static ArrayList<LinkEvent> actions;
+	
+	// Dictionary of mock IPortObject to information of port
+	// -> Used to refer DPID from IPortObject
+	private static Map<IPortObject,PortInfo> mockToPortInfoMap;
+	
+	
+	// Links existing in virtual graph
+	private List<Link> links;
+	
+	//================ Utility classes for logging actions in LinkStorageImpl ===========
+	private enum LinkEventType {
+		ADD, DELETE
+	}
+	
+	private class LinkEvent {
+		private Long src_dpid = null;
+		private Long dst_dpid = null;
+		private Short src_port = null;
+		private Short dst_port = null;
+		
+		public LinkEventType type;
+		
+		public LinkEvent(Link link, LinkEventType type) {
+			this.src_dpid = link.getSrc();
+			this.src_port = link.getSrcPort();
+			this.dst_dpid = link.getDst();
+			this.dst_port = link.getDstPort();
+			
+			this.type = type;
+		}
+
+		public Long getSrcDpid() { return src_dpid; }
+		public Short getSrcPort() { return src_port; }
+		public Long getDstDpid() { return dst_dpid; }
+		public Short getDstPort() { return dst_port; }
+		public LinkEventType getType() { return type; }
+	}
+	
+	private class PortInfo {
+		public Long dpid = null;
+		public Short port = null;
+		
+		public PortInfo(Long dpid, Short port) { this.dpid = dpid; this.port = port; }
+	}
+
+	/**
+	 * Setup code called before each tests.
+	 * Read test graph data and replace DB access by test graph data.
+	 * @throws Exception
+	 */
+	@Before
+	public void setUp() throws Exception{
+		// Create mock GraphDBConnection (replace Singleton object to mock one)
+		PowerMock.mockStatic(GraphDBConnection.class);
+		PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
+		conn = PowerMock.createMock(GraphDBConnection.class);
+		EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(conn).anyTimes();
+		PowerMock.replay(GraphDBConnection.class);
+		
+		// Create mock GraphDBOperation
+		ope = createMockGraphDBOperation();
+		PowerMock.expectNew(GraphDBOperation.class, new Class<?>[] {GraphDBConnection.class}, EasyMock.anyObject(GraphDBConnection.class)).andReturn(ope).anyTimes();
+		PowerMock.replay(GraphDBOperation.class);
+		
+		actions = new ArrayList<LinkEvent>();
+		mockToPortInfoMap = new HashMap<IPortObject,PortInfo>();
+		
+		linkStorage = new LinkStorageImpl();
+		linkStorage.init("/dummy/path/to/conf");
+		
+		initLinks();
+	}
+	
+	/**
+	 * Closing code called after each tests.
+	 * @throws Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+		linkStorage.close();
+	}
+	
+	// TODO: remove @Ignore after UPDATE method is implemented
+	/**
+	 * Test if {@link LinkStorageImpl#update(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
+	 */
+	@Ignore @Test
+	public void testUpdate_UpdateSingleLink() {
+		Link linkToUpdate= createExistingLink();
+		long currentTime = System.currentTimeMillis();
+		LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
+		LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
+
+		linkStorage.update(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
+		
+		doTestLinkHasStateOf(linkToUpdate, infoToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly creates a Link.
+	 */
+	@Test
+	public void testUpdate_CreateSingleLink() {
+		Link linkToCreate = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.update(linkToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		doTestLinkExist(linkToVerify);
+	}
+
+	/**
+	 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)}can correctly inserts a Link.
+	 */
+	@Test
+	public void testUpdate_InsertSingleLink(){
+		Link linkToInsert = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.update(linkToInsert, ILinkStorage.DM_OPERATION.INSERT);
+		doTestLinkExist(linkToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#update(Link, DM_OPERATION)} can correctly deletes a Link.
+	 */
+	@Test
+	public void testUpdate_DeleteSingleLink(){
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+
+		// Test deletion of existing link
+		linkStorage.update(linkToDelete, DM_OPERATION.DELETE);
+		doTestLinkNotExist(linkToVerify);
+	}
+
+	/**
+	 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly creates multiple Links.
+	 */
+	@Test
+	public void testUpdate_CreateLinks(){
+		List<Link> linksToCreate = createFeasibleLinks();
+		List<Link> linksToVerify = createFeasibleLinks();
+
+		// Test creation of new links
+		linkStorage.update(linksToCreate, ILinkStorage.DM_OPERATION.CREATE);
+		for(Link l : linksToVerify) {
+			doTestLinkExist(l);
+		}
+	}
+
+	/**
+	 * Test if {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly inserts multiple Links.
+	 */
+	@Test
+	public void testUpdate_InsertLinks(){
+		List<Link> linksToInsert = createFeasibleLinks();
+		List<Link> linksToVerify = createFeasibleLinks();
+		
+		// Test insertion of new links
+		linkStorage.update(linksToInsert, ILinkStorage.DM_OPERATION.INSERT);
+		for(Link l : linksToVerify) {
+			doTestLinkExist(l);
+		}
+	}
+	
+	/**
+	 * Test if  {@link LinkStorageImpl#update(List, DM_OPERATION)} can correctly deletes multiple Links.
+	 */
+	@Test
+	public void testUpdate_DeleteLinks(){
+		List<Link> linksToDelete = createExistingLinks();
+		List<Link> linksToVerify = createExistingLinks();
+		
+		// Test deletion of existing links
+		linkStorage.update(linksToDelete, ILinkStorage.DM_OPERATION.DELETE);
+		for(Link l : linksToVerify) {
+			doTestLinkNotExist(l);
+		}
+	}
+	
+	// TODO: remove @Ignore after UPDATE method is implemented
+	/**
+	 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly updates LinkInfo for a Link.
+	 */
+	@Ignore @Test
+	public void testUpdateLink_Update() {
+		Link linkToUpdate= createExistingLink();
+		long currentTime = System.currentTimeMillis();
+		LinkInfo infoToUpdate = createFeasibleLinkInfo(currentTime);
+		LinkInfo infoToVerify = createFeasibleLinkInfo(currentTime);
+
+		linkStorage.updateLink(linkToUpdate, infoToUpdate, ILinkStorage.DM_OPERATION.UPDATE);
+		
+		doTestLinkHasStateOf(linkToUpdate, infoToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly creates a Link.
+	 */
+	@Test
+	public void testUpdateLink_Create() {
+		Link linkToCreate = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.updateLink(linkToCreate, null, ILinkStorage.DM_OPERATION.CREATE);
+		doTestLinkExist(linkToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly inserts a Link.
+	 */
+	@Test
+	public void testUpdateLink_Insert() {
+		Link linkToInsert = createFeasibleLink();
+		Link linkToVerify = createFeasibleLink();
+		
+		//Use the link storage API to add the link
+		linkStorage.updateLink(linkToInsert, null, ILinkStorage.DM_OPERATION.INSERT);
+
+		doTestLinkExist(linkToVerify);
+	}
+	
+	// TODO: Check if addOrUpdateLink() should accept DELETE operation. If not, remove this test.
+	/**
+	 * Test if {@link LinkStorageImpl#updateLink(Link, LinkInfo, DM_OPERATION)} can correctly deletes a Link.
+	 */
+	@Ignore @Test
+	public void testUpdateLink_Delete() {
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+
+		// Test deletion of existing link
+		linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
+		doTestLinkNotExist(linkToVerify);
+		
+		linkToDelete = createFeasibleLink();
+		linkToVerify = createFeasibleLink();
+
+		// Test deletion of not-existing link
+		linkStorage.updateLink(linkToDelete, null, DM_OPERATION.DELETE);
+		doTestLinkNotExist(linkToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#getLinks(Long, short)} can correctly return Links connected to specific DPID and port.
+	 */
+	@Test
+	public void testGetLinks_ByDpidPort(){
+		Link linkToVerify = createExistingLink();
+		Long dpid = linkToVerify.getSrc();
+		short port = (short)linkToVerify.getSrcPort();
+		
+		List<Link> list = linkStorage.getLinks(dpid, port);
+		
+		assertEquals(1, list.size());
+		
+		Link l = list.get(0);
+		assertEquals(l.getSrc(), linkToVerify.getSrc());
+		assertEquals(l.getSrcPort(), linkToVerify.getSrcPort());
+		assertEquals(l.getDst(), linkToVerify.getDst());
+		assertEquals(l.getDstPort(), linkToVerify.getDstPort());
+		
+		Link linkToVerifyNot = createFeasibleLink();
+		
+		List<Link> list2 = linkStorage.getLinks(linkToVerifyNot.getSrc(), (short)linkToVerifyNot.getSrcPort());
+		
+		assertEquals(0, list2.size());
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#getLinks(String)} can correctly return Links connected to specific MAC address.
+	 */
+	@Test
+	public void testGetLinks_ByString() {
+		Link linkToVeryfy = createExistingLink();
+		String dpid = HexString.toHexString(linkToVeryfy.getSrc());
+		
+		List<Link> links = linkStorage.getLinks(dpid);
+		assertTrue(links.contains(linkToVeryfy));
+
+		Link linkToVerifyNot = createFeasibleLink();
+		assertFalse(links.contains(linkToVerifyNot));
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#deleteLink(Link)} can correctly delete a Link.
+	 */
+	@Test
+	public void testDeleteLink() {
+		// Deletion of existing link
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+		
+		linkStorage.deleteLink(linkToDelete);
+		doTestLinkNotExist(linkToVerify);
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#deleteLinks(List)} can correctly delete Links.
+	 */
+	@Test
+	public void testDeleteLinks(){
+		List<Link> linksToDelete = createExistingLinks();
+		List<Link> linksToVerify = createExistingLinks();
+		
+		linkStorage.deleteLinks(linksToDelete);
+		for(Link l : linksToVerify) {
+			doTestLinkNotExist(l);
+		}
+	}
+
+	/**
+	 * Test if {@link LinkStorageImpl#getActiveLinks()} can correctly return active Links.
+	 */
+	@Test
+	public void testGetActiveLinks() {
+		Link existingLink = createExistingLink();
+		Link notExistingLink = createFeasibleLink();
+
+		List<Link> links = linkStorage.getActiveLinks();
+		
+		assertTrue(links.contains(existingLink));
+		assertFalse(links.contains(notExistingLink));
+	}
+	
+	/**
+	 * Test if {@link LinkStorageImpl#deleteLinksOnPort(Long, short)} can delete Links.
+	 */
+	@Test
+	public void testDeleteLinksOnPort() {
+		Link linkToDelete = createExistingLink();
+		Link linkToVerify = createExistingLink();
+		
+		linkStorage.deleteLinksOnPort(linkToDelete.getSrc(), linkToDelete.getSrcPort());
+		
+		doTestLinkNotExist(linkToVerify);
+	}
+
+	/**
+	 * Test if specific link exists
+	 * @param link 
+	 */
+	private void doTestLinkExist(Link link) {
+		int count = 0;
+		for(Link lt : links) {
+			if(lt.equals(link)) {
+				++count;
+			}
+		}
+		
+		assertTrue(count == 1);
+	}
+	
+	/**
+	 * Test if specific link doesn't exist
+	 * @param link
+	 */
+	private void doTestLinkNotExist(Link link) {
+		assertFalse(links.contains(link));
+	}
+	
+	/**
+	 * Test if titanGraph has specific Link with specific LinkInfo
+	 * @param link 
+	 */
+	// TODO: Fix me
+	private void doTestLinkHasStateOf(Link link, LinkInfo info) {
+	}
+	
+	/**
+	 * Class defines a function called back when {@link IPortObject#removeLink(IPortObject)} is called.
+	 * @author Naoki Shiota
+	 *
+	 */
+	private class RemoveLinkCallback implements IAnswer<Object> {
+		private long dpid;
+		private short port;
+		public RemoveLinkCallback(long dpid, short port) {
+			this.dpid = dpid; this.port = port;
+		}
+		
+		@Override
+		public Object answer() throws Throwable {
+			IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
+			PortInfo dst = mockToPortInfoMap.get(dstPort);
+
+			Link linkToRemove = new Link(this.dpid,this.port,dst.dpid,dst.port);
+			actions.add(new LinkEvent(linkToRemove,LinkEventType.DELETE));
+			
+			return null;
+		}
+	}
+	
+	/**
+	 * Class defines a function called back when {@link IPortObject#setLinkPort(IPortObject)} is called.
+	 * @author Naoki Shiota
+	 */
+	private class SetLinkPortCallback implements IAnswer<Object> {
+		private long dpid;
+		private short port;
+		public SetLinkPortCallback(long dpid, short port) {
+			this.dpid = dpid; this.port = port;
+		}
+
+		@Override
+		public Object answer() throws Throwable {
+			IPortObject dstPort = (IPortObject) EasyMock.getCurrentArguments()[0];
+			PortInfo dst = mockToPortInfoMap.get(dstPort);
+
+			Link linkToAdd = new Link(this.dpid,this.port,dst.dpid,dst.port);
+			actions.add(new LinkEvent(linkToAdd,LinkEventType.ADD));
+
+			return null;
+		}
+		
+	}
+	
+	/**
+	 * Class defines a function called back when {@link IPortObject#getSwitch()} is called.
+	 * @author Naoki Shiota
+	 *
+	 */
+	private class GetSwitchCallback implements IAnswer<ISwitchObject> {
+		private long dpid;
+		
+		public GetSwitchCallback(long dpid) {
+			this.dpid = dpid;
+		}
+
+		@Override
+		public ISwitchObject answer() throws Throwable {
+			ISwitchObject sw = createMockSwitch(dpid);
+			return sw;
+		}
+	}
+	
+	/**
+	 * Class defines a function called back when {@link IPortObject#getLinkedPorts()} is called.
+	 * @author Naoki Shiota
+	 *
+	 */
+	private class GetLinkedPortsCallback implements IAnswer< Iterable<IPortObject> > {
+		private long dpid;
+		private short port;
+		
+		public GetLinkedPortsCallback(long dpid, short port) {
+			this.dpid = dpid;
+			this.port = port;
+		}
+
+		@Override
+		public Iterable<IPortObject> answer() throws Throwable {
+			List<IPortObject> ports = new ArrayList<IPortObject>();
+
+			for(Link lk : links) {
+				if(lk.getSrc() == dpid && lk.getSrcPort() == port) {
+					ports.add(createMockPort(lk.getDst(), lk.getDstPort()));
+				}
+			}
+
+			return ports;
+		}
+		
+	}
+
+	/**
+	 * Class defines a function called back when {@link LinkStorageImplTest} is called.
+	 * @author Naoki Shiota
+	 *
+	 */
+	private class GetPortsCallback implements IAnswer< Iterable <IPortObject> > {
+		private long dpid;
+		
+		public GetPortsCallback(long dpid) {
+			this.dpid = dpid;
+		}
+		
+		@Override
+		public Iterable<IPortObject> answer() throws Throwable {
+			List<IPortObject> ports = new ArrayList<IPortObject>();
+			
+			for(Short number : getPorts(dpid)) {
+				ports.add(createMockPort(dpid, number));
+			}
+
+			return ports;
+		}
+	}
+
+	// ------------------------Creation of Mock-----------------------------
+	/**
+	 * Create a mock {@link GraphDBOperation} which hooks port-related methods.
+	 * @return EasyMock-wrapped GraphDBOperation object.
+	 */
+	@SuppressWarnings("serial")
+	private GraphDBOperation createMockGraphDBOperation() {
+		GraphDBOperation mockDBOpe = EasyMock.createNiceMock(GraphDBOperation.class);
+		
+		// Mock searchPort() method to create new mock IPortObject.
+		EasyMock.expect(mockDBOpe.searchPort((String)EasyMock.anyObject(), EasyMock.anyShort())).
+			andAnswer(new IAnswer<IPortObject>() {
+			@Override
+			public IPortObject answer() throws Throwable {
+				long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
+				short port = (Short) EasyMock.getCurrentArguments()[1];
+				IPortObject ret = createMockPort(dpid,port);
+				
+				return ret;
+			}
+		}).anyTimes();
+		
+		// Mock searchSwitch() method to create new mock ISwitchObject.
+		EasyMock.expect(mockDBOpe.searchSwitch((String)EasyMock.anyObject())).
+			andAnswer(new IAnswer<ISwitchObject>() {
+			@Override
+			public ISwitchObject answer() throws Throwable {
+				long dpid = HexString.toLong((String)EasyMock.getCurrentArguments()[0]);
+				ISwitchObject ret = createMockSwitch(dpid);
+				
+				return ret;
+			}
+		}).anyTimes();
+		
+		// Mock getActiveSwitches() method to create list of mock ISwitchObject.
+		EasyMock.expect(mockDBOpe.getActiveSwitches()).andReturn(new ArrayList<ISwitchObject> () {{
+			for(Long dpid : getDpids()) {
+				add(createMockSwitch(dpid));
+			}
+		}}).anyTimes();
+
+		// Mock commit() method to commit change of link information
+		mockDBOpe.commit();
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+			@Override
+			public Object answer() throws Throwable {
+				for(LinkEvent action : actions) {
+					if(action.getType().equals(LinkEventType.ADD)) {
+						Link linkToAdd = new Link(
+								action.getSrcDpid(),
+								action.getSrcPort(),
+								action.getDstDpid(),
+								action.getDstPort());
+						links.add(linkToAdd);
+					} else if(action.getType().equals(LinkEventType.DELETE)) {
+						Link linkToRemove = new Link(
+								action.getSrcDpid(),
+								action.getSrcPort(),
+								action.getDstDpid(),
+								action.getDstPort());
+						links.remove(linkToRemove);
+					} else {
+						log.error("mock commit(): unexpected action {}", new Object[]{action.getType()});
+					}
+				}
+				actions.clear();
+				return null;
+			}
+		}).atLeastOnce();
+		
+		EasyMock.replay(mockDBOpe);
+		return mockDBOpe;
+	}
+	
+	/**
+	 * Create a mock {@link IPortObject} using given DPID and port number.
+	 * {@link IPortObject} can't store DPID, so DPID is stored to mockToPortInfoMap for later use.
+	 * Duplication is not checked.
+	 * @param dpid DPID of a port
+	 * @param number Port Number
+	 * @return EasyMock-wrapped IPortObject
+	 */
+	private IPortObject createMockPort(long dpid, short number) {
+		IPortObject mockPort = EasyMock.createNiceMock(IPortObject.class);
+		
+		EasyMock.expect(mockPort.getNumber()).andReturn(number);
+		
+		// Mock removeLink() method
+		mockPort.removeLink((IPortObject) EasyMock.anyObject());
+		EasyMock.expectLastCall().andAnswer(new RemoveLinkCallback(dpid, number)).anyTimes();
+		
+		// Mock setLinkPort() method
+		mockPort.setLinkPort((IPortObject) EasyMock.anyObject());
+		EasyMock.expectLastCall().andAnswer(new SetLinkPortCallback(dpid, number)).anyTimes();
+		
+		// Mock getLinkPorts() method
+		EasyMock.expect(mockPort.getLinkedPorts()).andAnswer(new GetLinkedPortsCallback(dpid, number)).anyTimes();
+		
+		// Mock getSwitch() method
+		EasyMock.expect(mockPort.getSwitch()).andAnswer(new GetSwitchCallback(dpid)).anyTimes();
+		
+		mockToPortInfoMap.put(mockPort, new PortInfo(dpid,number));
+		EasyMock.replay(mockPort);
+		
+		return mockPort;
+	}
+	
+	/**
+	 * Create a mock {@link ISwitchObject} using given DPID number.
+	 * Duplication is not checked.
+	 * @param dpid DPID of a switch
+	 * @return EasyMock-wrapped ISwitchObject
+	 */
+	private ISwitchObject createMockSwitch(long dpid) {
+		ISwitchObject mockSw = EasyMock.createNiceMock(ISwitchObject.class);
+		
+		EasyMock.expect(mockSw.getPorts()).andAnswer(new GetPortsCallback(dpid)).anyTimes();
+		EasyMock.expect(mockSw.getDPID()).andReturn(HexString.toHexString(dpid)).anyTimes();
+		EasyMock.expect(mockSw.getState()).andReturn("ACTIVE").anyTimes();
+		
+		EasyMock.replay(mockSw);
+		return mockSw;
+	}
+
+
+	//----------------- Creation of test data -----------------------
+	// Assume a network shown below.
+	//
+	// [dpid1]--+--[port:1]----[port:1]--+--[dpid2]
+	//          |                        |
+	//          +--[port:2]    [port:2]--+
+	//          |
+	//          +--[port:3]    [port:1]--+--[dpid3]
+	//          |                        |
+	//          +--[port:4]----[port:2]--+
+	//
+	// dpid1 : 00:00:00:00:0a:01
+	// dpid2 : 00:00:00:00:0a:02
+	// dpid3 : 00:00:00:00:0a:03
+	
+	/**
+	 * Initialize links member to represent test topology above.
+	 */
+	private void initLinks() {
+		links = new ArrayList<Link>();
+		
+		links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
+		links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
+	}
+	
+	/**
+	 * Returns list of port number attached to the switch specified by given DPID.
+	 * @param dpid DPID of the switch
+	 * @return List of port number
+	 */
+	@SuppressWarnings("serial")
+	private List<Short> getPorts(long dpid) {
+		List<Short> ports;
+		
+		if(dpid == Long.decode("0x0000000000000a01")) {
+			ports = new ArrayList<Short>() {{
+				add((short)1);
+				add((short)2);
+				add((short)3);
+				add((short)4);
+			}};
+		} else if(dpid == Long.decode("0x0000000000000a02") || dpid == Long.decode("0x0000000000000a03")) {
+			ports = new ArrayList<Short>() {{
+				add((short)1);
+				add((short)2);
+			}};
+		} else {
+			ports = new ArrayList<Short>();
+		}
+		
+		return ports;
+	}
+	
+	/**
+	 * Returns list of DPIDs in test topology.
+	 * @return List of DPIDs
+	 */
+	@SuppressWarnings("serial")
+	private List<Long> getDpids() {
+		List<Long> dpids = new ArrayList<Long>() {{
+			add(Long.decode("0x0000000000000a01"));
+			add(Long.decode("0x0000000000000a02"));
+			add(Long.decode("0x0000000000000a03"));
+		}};
+		
+		return dpids;
+	}
+	
+	/**
+	 * Returns new {@link Link} object of an existing link
+	 * @return new Link object
+	 */
+	private Link createExistingLink() {
+		return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1);
+	}
+	
+	/**
+	 * Returns new {@link Link} object of a not-existing but feasible link
+	 * @return new Link object
+	 */
+	private Link createFeasibleLink() {
+		return new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1);
+	}
+	
+	// make NO sense while test-network data doesn't define physical network (i.e. any link is feasible)
+	@SuppressWarnings("unused")
+	private Link createInfeasibleLink() {
+		return new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a03"), 3);
+	}
+
+	/**
+	 * Returns list of existing {@link Link} objects
+	 * @return ArrayList of new Link objects
+	 */
+	private List<Link> createExistingLinks() {
+		List<Link> links = new ArrayList<Link>();
+		links.add(new Link(Long.decode("0x0000000000000a01"), 1, Long.decode("0x0000000000000a02"), 1));
+		links.add(new Link(Long.decode("0x0000000000000a01"), 4, Long.decode("0x0000000000000a03"), 2));
+		return links;
+	}
+	
+	/**
+	 * Returns list of {@link Link} objects that are all not-existing but feasible
+	 * @return ArrayList of new Link objects
+	 */
+	private List<Link> createFeasibleLinks() {
+		List<Link> links = new ArrayList<Link>();
+		links.add(new Link(Long.decode("0x0000000000000a01"), 2, Long.decode("0x0000000000000a02"), 2));
+		links.add(new Link(Long.decode("0x0000000000000a01"), 3, Long.decode("0x0000000000000a03"), 1));
+		return links;
+	}
+	
+	/**
+	 * Returns new {@link LinkInfo} object with convenient values.
+	 * @return LinkInfo object
+	 */
+	private LinkInfo createFeasibleLinkInfo(long time) {
+		long time_first = time;
+		long time_last_lldp = time + 50;
+		long time_last_bddp = time + 100;
+		int state_src = OFPhysicalPort.OFPortState.OFPPS_STP_FORWARD.getValue();
+		int state_dst = OFPhysicalPort.OFPortState.OFPPS_STP_LISTEN.getValue();
+
+		return new LinkInfo(time_first,
+				time_last_lldp,
+				time_last_bddp,
+				state_src,
+				state_dst);
+	}
+	//---------------------------------------------------------------
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTest.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTest.java
new file mode 100644
index 0000000..4956136
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTest.java
@@ -0,0 +1,767 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import static org.easymock.EasyMock.*;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class SwitchStorageImplTest {
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection mockConn = null;
+    private GraphDBOperation mockOpe = null;
+    private GraphDBOperation realOpe = null;
+    private TitanGraph titanGraph = null;
+    ISwitchStorage swSt = null;
+    
+	@Before
+	public void setUp() throws Exception {
+		
+		swSt = new SwitchStorageImpl();
+		conf = "/dummy/path/to/db";
+		
+        // Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+
+		PowerMock.mockStatic(GraphDBConnection.class);
+		mockConn = createMock(GraphDBConnection.class);
+		PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
+		EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(mockConn);
+		PowerMock.replay(GraphDBConnection.class);
+		
+		PowerMock.mockStatic(GraphDBOperation.class);
+		mockOpe = PowerMock.createStrictMock(GraphDBOperation.class);
+		PowerMock.expectNew(GraphDBOperation.class, mockConn).andReturn(mockOpe);
+		PowerMock.replay(GraphDBOperation.class);
+        // Replace the conf to dummy conf
+		// String conf = "/tmp/cassandra.titan";
+		
+
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		swSt.close();
+		swSt = null;
+		
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  Normal
+	 * Expect:
+	 * 	Call SwitchStorageImpl.addSwitch func with proper properties.
+	 */
+	@Test
+	public void testAddSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  The switch is already existing.
+	 * Expect:
+	 * 	Call SwitchStorageImpl.addSwitch func with proper properties.
+	 */
+	//@Ignore 
+	@Test
+	public void testAddSwitchExisting() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.setState(state);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addSwitch(dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  The switch construction is fail and return null
+	 * Expect:
+	 * 	Write the status as info log.
+	 */
+	@Test
+	public void testAddSwitchAbnormal() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(null);
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  Throw runtimeException. 
+	 * Expect:
+	 * 	The rollback method is called.
+	 */
+	//@Ignore 
+	@Test
+	public void testAddSwitchException() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expectLastCall().andThrow(new RuntimeException());
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for updateSwitch method.
+	 * Condition:
+	 *  SwitchState : INACTIVE
+	 *  DMOPERATION : UPDATE
+	 * Expect:
+	 * 	Should call addSwitch function and commit.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdateUPDATE() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		SwitchState stateINACTIVE = SwitchState.INACTIVE;
+		DM_OPERATION opUPDATE = DM_OPERATION.UPDATE;
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState("ACTIVE");
+		mockISw.setState(stateINACTIVE.toString());
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);	
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.update(dpid, stateINACTIVE, opUPDATE);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for updateSwitch method.
+	 * Condition:
+	 *  SwitchState : INACTIVE
+	 *  DMOPERATION : CREATE
+	 * Expect:
+	 * 	Should call addSwitch function and commit.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdateCREATE() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		SwitchState stateINACTIVE = SwitchState.INACTIVE;
+		DM_OPERATION opCREATE = DM_OPERATION.CREATE;
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState("ACTIVE");
+		mockISw.setState(stateINACTIVE.toString());
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);	
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.update(dpid, stateINACTIVE, opCREATE);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for updateSwitch method.
+	 * Condition:
+	 *  SwitchState : INACTIVE
+	 *  DMOPERATION : INSERT
+	 * Expect:
+	 * 	Should call addSwitch function and commit.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdateINSERT() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		SwitchState stateINACTIVE = SwitchState.INACTIVE;
+		DM_OPERATION opINSERT = DM_OPERATION.INSERT;
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState("ACTIVE");
+		mockISw.setState(stateINACTIVE.toString());
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.update(dpid, stateINACTIVE, opINSERT);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for updateSwitch method.
+	 * Condition:
+	 *  SwitchState : ACTIVE
+	 *  DMOPERATION : DELETE
+	 * Expect:
+	 * 	Should call removeSwitch function and commit.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdateDELETE() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		SwitchState stateACTIVE = SwitchState.ACTIVE;
+		DM_OPERATION opDELETE = DM_OPERATION.DELETE;
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(stateACTIVE.toString());
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		mockOpe.removeSwitch(mockISw);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.update(dpid, stateACTIVE, opDELETE);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for deleteSwitch method.
+	 * Condition:
+	 *  The switch is existing.
+	 * Expect:
+	 * 	Should call removeSwitch function and commit.
+	 */
+	//@Ignore
+	@Test
+	public void testDeleteSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+	
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+    	mockOpe.removeSwitch(mockISw);
+    	mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.deleteSwitch(dpid);
+		
+		//Iterator<Vertex> it = titanGraph.getVertices("dpid", dpid).iterator();
+		//assertFalse(it.hasNext());
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for deleteSwitch method.
+	 * Condition:
+	 *  The commit func throw exception.
+	 * Expect:
+	 * 	Should call rollback.
+	 */
+	//@Ignore
+	@Test
+	public void testDeleteSwitchException() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		String state = "ACTIVE";
+		String type = "";
+		
+		//Mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+    	mockOpe.removeSwitch(mockISw);
+    	mockOpe.commit();
+		expectLastCall().andThrow(new RuntimeException());
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+		
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.deleteSwitch(dpid);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  port is existing.
+	 * Expect:
+	 * 	Should call addPort and commit.
+	 */
+	//@Ignore
+	@Test
+	public void testAddPort() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.addPort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(null);
+		expect(mockOpe.newPort(dpid, portNumber)).andReturn(mockIPort);	
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  Port status is down.
+	 * Expect:
+	 * 	Should call removePort and commit.
+	 */
+	//@Ignore
+	@Test
+	public void testAddPortWithPortLinkDown() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_LINK_DOWN.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.removePort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);	
+		mockOpe.commit();	
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(mockIPort);
+		mockOpe.removePort(mockIPort);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  The switch is not existing.
+	 * Expect:
+	 * 	Nothing happens.
+	 */
+	//@Ignore
+	@Test
+	public void testAddPortAbnormalNoSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createStrictMock(IPortObject.class);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createStrictMock(ISwitchObject.class);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addPort(dpid, portToAdd);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  port is not existing.
+	 * Expect:
+	 * 	Should call addPort and commit.
+	 */
+	//@Ignore
+	@Test
+	public void testAddPortAbnormalNoPort() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.addPort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(null);
+		expect(mockOpe.newPort(dpid, portNumber)).andReturn(null);	
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  commit throw the exception.
+	 * Expect:
+	 * 	Should call rollback.
+	 */
+	//@Ignore
+	@Test
+	public void testAddPortWithException() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.addPort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(null);
+		expect(mockOpe.newPort(dpid, portNumber)).andReturn(mockIPort);	
+		mockOpe.commit();
+		expectLastCall().andThrow(new RuntimeException());
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for deletePort method.
+	 * Condition:
+	 *  port is existing.
+	 * Expect:
+	 * 	Should call removePort and commit.
+	 */
+	//@Ignore
+	@Test
+	public void testDeletePort() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.addPort(mockIPort);
+		mockISw.removePort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(null);
+		expect(mockOpe.newPort(dpid, portNumber)).andReturn(mockIPort);	
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(mockIPort);
+		mockOpe.removePort(mockIPort);
+		mockOpe.commit();
+		mockOpe.close();
+		replay(mockOpe);
+
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+		swSt.deletePort(dpid, portNumber);
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for addPort method.
+	 * Condition:
+	 *  commit throws the exception.
+	 * Expect:
+	 * 	Should call rollback.
+	 */
+	//@Ignore
+	@Test
+	public void testDeletePortException() {
+		String dpid = "00:00:00:00:00:00:0a:01";
+		short portNumber = 5;
+		String state = "ACTIVE";
+		String name = "port 5 at SEA switch";
+		
+		OFPhysicalPort portToAdd = new OFPhysicalPort();
+		portToAdd.setName(name);
+		portToAdd.setCurrentFeatures(OFPhysicalPort.OFPortFeatures.OFPPF_100MB_FD.getValue());
+		portToAdd.setPortNumber(portNumber);
+		portToAdd.setState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		
+		//Expectation of  mock Port
+		IPortObject mockIPort = createMock(IPortObject.class);
+		mockIPort.setState(state);
+		mockIPort.setPortState(OFPortState.OFPPS_STP_FORWARD.getValue());
+		mockIPort.setDesc(name);
+		replay(mockIPort);
+		
+		//Expectation of mock Switch
+		ISwitchObject mockISw = createMock(ISwitchObject.class);
+		mockISw.setState(state);
+		mockISw.addPort(mockIPort);
+		mockISw.removePort(mockIPort);
+		replay(mockISw);
+		
+		//Expectation of mock operation.
+		expect(mockOpe.searchSwitch(dpid)).andReturn(null);
+		expect(mockOpe.newSwitch(dpid)).andReturn(mockISw);
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(null);
+		expect(mockOpe.newPort(dpid, portNumber)).andReturn(mockIPort);	
+		mockOpe.commit();
+		expect(mockOpe.searchSwitch(dpid)).andReturn(mockISw);
+		expect(mockOpe.searchPort(dpid, portNumber)).andReturn(mockIPort);
+		mockOpe.removePort(mockIPort);
+		expectLastCall().andThrow(new RuntimeException());
+		mockOpe.rollback();
+		mockOpe.close();
+		replay(mockOpe);
+	
+		swSt.init(conf);
+		swSt.addSwitch(dpid);
+		swSt.addPort(dpid, portToAdd);
+		swSt.deletePort(dpid, portNumber);
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTestBB.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTestBB.java
new file mode 100644
index 0000000..57aefd3
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/SwitchStorageImplTestBB.java
@@ -0,0 +1,334 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import static org.junit.Assert.*;
+
+import net.floodlightcontroller.core.internal.TestDatabaseManager;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage;
+import net.onrc.onos.ofcontroller.core.ISwitchStorage.SwitchState;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.onrc.onos.ofcontroller.core.INetMapStorage;
+import net.onrc.onos.ofcontroller.core.INetMapStorage.DM_OPERATION;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFPhysicalPort;
+import org.openflow.protocol.OFPhysicalPort.OFPortState;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.slf4j.LoggerFactory;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class SwitchStorageImplTestBB {
+
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+    ISwitchStorage swSt = null;
+    
+	@Before
+	public void setUp() throws Exception {
+		
+		swSt = new SwitchStorageImpl();
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+		
+		swSt.init(conf);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+
+		swSt.close();
+		swSt = null;
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  Normal
+	 * Expect:
+	 * 1. Switch should be generated.
+	 * 2. The status of switch should be ACTIVE
+	 */
+	//@Ignore 
+	@Test
+	public void testAddSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw == null);
+		swSt.addSwitch(dpid);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 != null);
+		assertEquals(sw2.getState(), "ACTIVE");
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for addSwitch method.
+	 * Condition:
+	 *  The existing switch status is INACTIVE.
+	 *  The switch is already existing.
+	 * Expect:
+	 * 1. After add the same switch, the status of switch should be ACTIVE
+	 */
+	//@Ignore 
+	@Test
+	public void testAddSwitchExisting() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		
+		swSt.update(dpid, SwitchState.INACTIVE, DM_OPERATION.UPDATE);
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		assertEquals(sw.getState(), SwitchState.INACTIVE.toString());
+		swSt.addSwitch(dpid);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 != null);
+		assertEquals(sw2.getState(), SwitchState.ACTIVE.toString());
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for testUpdate method.
+	 * Condition:
+	 *  The switch is not existing.
+	 *  The status of added switch is INACTIVE.
+	 *  DM_OPERATION is CREATE.
+	 * Expect:
+	 * 1. Switch should be created.
+	 * 2. The status of switch should be INACTIVE.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdate() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		SwitchState state = ISwitchStorage.SwitchState.INACTIVE;
+		DM_OPERATION dmope = INetMapStorage.DM_OPERATION.CREATE;
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw == null);
+		swSt.update(dpid, state, dmope);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 != null);
+		assertEquals(sw2.getState(), state.toString());
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for testUpdate method.
+	 * Condition:
+	 *  The switch is existing.
+	 *  The status of added switch is ACTIVE.
+	 *  DM_OPERATION is DELETE.
+	 * Expect:
+	 * 1. Switch should be deleted.
+	 */
+	//@Ignore 
+	@Test
+	public void testUpdateWithDELETE() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		SwitchState state = ISwitchStorage.SwitchState.ACTIVE;
+		DM_OPERATION dmope = INetMapStorage.DM_OPERATION.DELETE;
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		swSt.update(dpid, state, dmope);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 == null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for delete switch method.
+	 * Condition:
+	 *  The switch is existing.
+	 * Expect:
+	 * 1. Switch should be deleted.
+	 */
+	//@Ignore 
+	@Test
+	public void testDeleteSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		swSt.deleteSwitch(dpid);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 == null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for delete switch method.
+	 * Condition:
+	 *  The switch is not existing.
+	 * Expect:
+	 * Nothing happens.
+	 */
+	//@Ignore 
+	@Test
+	public void testDeleteNonExistingSwitch() {
+		String dpid = "00:00:00:00:00:00:0a:07";
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw == null);
+		swSt.deleteSwitch(dpid);
+		ISwitchObject sw2 = ope.searchSwitch(dpid);
+		assertTrue(sw2 == null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for delete port method.
+	 * Condition:
+	 *  The port is existing.
+	 * Expect:
+	 *  Deleted the port.
+	 */
+	//@Ignore 
+	@Test
+	public void testDeletePort() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		short portNumber = 3;
+		
+		IPortObject portObj1 = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj1 != null);
+		swSt.deletePort(dpid, portNumber);
+		IPortObject portObj2 = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj2 == null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for delete port method.
+	 * Condition:
+	 *  The port is not existing.
+	 * Expect:
+	 *  Nothing happens.
+	 */
+	//@Ignore 
+	@Test
+	public void testDeleteNonExistingPort() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		short portNumber = 4;
+		
+		IPortObject portObj1 = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj1 == null);
+		swSt.deletePort(dpid, portNumber);
+		IPortObject portObj2 = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj2 == null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for add port method.
+	 * Condition:
+	 *  The port is not existing.
+	 * Expect:
+	 *  The port should be added.
+	 *  The desc of IPortObject is the same as the name of OFPhysicalPort.
+	 */
+	//@Ignore 
+	@Test
+	public void testAddPort() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		short portNumber = 4;
+		String name = "port 4 at ATL Switch";
+		int state = OFPortState.OFPPS_STP_FORWARD.getValue();
+		OFPhysicalPort port = new OFPhysicalPort(); 
+		port.setPortNumber(portNumber);
+		port.setName(name);
+		port.setState(state);
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		swSt.addPort(dpid, port);
+		IPortObject portObj = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj != null);
+		assertEquals(portObj.getDesc(), name);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for add method.
+	 * Condition:
+	 *  The port is existing.
+	 * Expect:
+	 *  Nothing happens.
+	 */
+	//@Ignore 
+	@Test
+	public void testAddExistingPort() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		short portNumber = 3;
+		String name = "xxx";
+		int state = OFPortState.OFPPS_STP_FORWARD.getValue();
+		OFPhysicalPort port = new OFPhysicalPort(); 
+		port.setPortNumber(portNumber);
+		port.setName(name);
+		port.setState(state);
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		swSt.addPort(dpid, port);
+		IPortObject portObj = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj != null);
+	}
+	
+	/**
+	 * Desc:
+	 *  Test method for add method.
+	 * Condition:
+	 *  The port status is down.
+	 * Expect:
+	 *  Delete the port.
+	 */
+	//@Ignore 
+	@Test
+	public void testAddDownPort() {
+		String dpid = "00:00:00:00:00:00:0a:06";
+		short portNumber = 3;
+		String name = "port 3 at ATL Switch";
+		int state = OFPortState.OFPPS_LINK_DOWN.getValue();
+		OFPhysicalPort port = new OFPhysicalPort(); 
+		port.setPortNumber(portNumber);
+		port.setName(name);
+		port.setState(state);
+		
+		ISwitchObject sw = ope.searchSwitch(dpid);
+		assertTrue(sw != null);
+		swSt.addPort(dpid, port);
+		IPortObject portObj = ope.searchPort(dpid, portNumber);
+		assertTrue(portObj == null);
+	}
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestDatabaseManager.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestDatabaseManager.java
new file mode 100644
index 0000000..5b0a5b1
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestDatabaseManager.java
@@ -0,0 +1,87 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.commons.io.FileUtils;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.blueprints.util.io.graphml.GraphMLReader;
+
+public class TestDatabaseManager {
+	private static final String testDbLocation = "/tmp/onos-testdb";
+	
+	//private static final String testDbGraphML = "<?xml version=\"1.0\" ?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\">    <key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"type\" for=\"node\" attr.name=\"type\" attr.type=\"string\"></key>    <key id=\"dpid\" for=\"node\" attr.name=\"dpid\" attr.type=\"string\"></key>    <key id=\"desc\" for=\"node\" attr.name=\"desc\" attr.type=\"string\"></key>    <key id=\"number\" for=\"node\" attr.name=\"number\" attr.type=\"int\"></key>    <key id=\"dl_addr\" for=\"node\" attr.name=\"dl_addr\" attr.type=\"string\"></key>    <key id=\"nw_addr\" for=\"node\" attr.name=\"nw_addr\" attr.type=\"string\"></key>    <key id=\"id\" for=\"edge\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"source\" for=\"edge\" attr.name=\"source\" attr.type=\"string\"></key>    <key id=\"target\" for=\"edge\" attr.name=\"target\" attr.type=\"string\"></key>    <key id=\"label\" for=\"edge\" attr.name=\"label\" attr.type=\"string\"></key>    <graph id=\"G\" edgedefault=\"directed\">        <node id=\"1\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:01</data>            <data key=\"desc\">OpenFlow Switch at SEA</data>        </node>        <node id=\"2\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:02</data>            <data key=\"desc\">OpenFlow Switch at LAX</data>        </node>        <node id=\"3\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:03</data>            <data key=\"desc\">OpenFlow Switch at CHI</data>        </node>        <node id=\"4\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:04</data>            <data key=\"desc\">OpenFlow Switch at IAH</data>        </node>        <node id=\"5\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:05</data>            <data key=\"desc\">OpenFlow Switch at NYC</data>        </node>        <node id=\"6\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:06</data>            <data key=\"desc\">OpenFlow Switch at ATL</data>        </node>        <node id=\"100\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at SEA Switch</data>        </node>        <node id=\"101\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at SEA Switch</data>        </node>        <node id=\"102\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at SEA Switch</data>        </node>        <node id=\"103\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at SEA Switch</data>        </node>        <node id=\"104\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at LAX Switch</data>        </node>        <node id=\"105\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at LAX Switch</data>        </node>        <node id=\"106\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at LAX Switch</data>        </node>        <node id=\"107\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at CHI Switch</data>        </node>        <node id=\"108\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at CHI Switch</data>        </node>        <node id=\"109\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at CHI Switch</data>        </node>        <node id=\"110\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at CHI Switch</data>        </node>        <node id=\"111\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at IAH Switch</data>        </node>        <node id=\"112\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at IAH Switch</data>        </node>        <node id=\"113\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at IAH Switch</data>        </node>        <node id=\"114\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at NYC Switch</data>        </node>        <node id=\"115\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at NYC Switch</data>        </node>        <node id=\"116\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at NYC Switch</data>        </node>        <node id=\"117\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at ATL Switch</data>        </node>        <node id=\"118\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at ATL Switch</data>        </node>        <node id=\"119\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at ATL Switch</data>        </node>        <node id=\"1000\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:73</data>            <data key=\"nw_addr\">192.168.10.101</data>        </node>        <node id=\"1001\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:62</data>            <data key=\"nw_addr\">192.168.20.101</data>        </node>        <node id=\"1002\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">10:40:f3:e6:8d:55</data>            <data key=\"nw_addr\">192.168.10.1</data>        </node>        <node id=\"1003\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">a0:b3:cc:9c:c6:88</data>            <data key=\"nw_addr\">192.168.20.1</data>        </node>        <node id=\"1004\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">00:04:20:e2:50:a2</data>            <data key=\"nw_addr\">192.168.30.1</data>        </node>        <node id=\"1005\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">58:55:ca:c4:1b:a0</data>            <data key=\"nw_addr\">192.168.40.1</data>        </node>        <edge id=\"10000\" source=\"1\" target=\"101\" label=\"on\"></edge>        <edge id=\"10001\" source=\"1\" target=\"102\" label=\"on\"></edge>        <edge id=\"10002\" source=\"1\" target=\"103\" label=\"on\"></edge>        <edge id=\"10003\" source=\"2\" target=\"104\" label=\"on\"></edge>        <edge id=\"10004\" source=\"2\" target=\"105\" label=\"on\"></edge>        <edge id=\"10005\" source=\"2\" target=\"106\" label=\"on\"></edge>        <edge id=\"10006\" source=\"3\" target=\"107\" label=\"on\"></edge>        <edge id=\"10007\" source=\"3\" target=\"108\" label=\"on\"></edge>        <edge id=\"10008\" source=\"3\" target=\"109\" label=\"on\"></edge>        <edge id=\"10009\" source=\"3\" target=\"110\" label=\"on\"></edge>        <edge id=\"10010\" source=\"4\" target=\"111\" label=\"on\"></edge>        <edge id=\"10011\" source=\"4\" target=\"112\" label=\"on\"></edge>        <edge id=\"10012\" source=\"4\" target=\"113\" label=\"on\"></edge>        <edge id=\"10013\" source=\"5\" target=\"114\" label=\"on\"></edge>        <edge id=\"10014\" source=\"5\" target=\"115\" label=\"on\"></edge>        <edge id=\"10015\" source=\"5\" target=\"116\" label=\"on\"></edge>        <edge id=\"10016\" source=\"6\" target=\"117\" label=\"on\"></edge>        <edge id=\"10017\" source=\"6\" target=\"118\" label=\"on\"></edge>        <edge id=\"10018\" source=\"6\" target=\"119\" label=\"on\"></edge>        <edge id=\"11000\" source=\"101\" target=\"107\" label=\"link\"></edge>         <edge id=\"11003\" source=\"105\" target=\"111\" label=\"link\"></edge>        <edge id=\"11004\" source=\"107\" target=\"101\" label=\"link\"></edge>        <edge id=\"11005\" source=\"108\" target=\"112\" label=\"link\"></edge>        <edge id=\"11006\" source=\"109\" target=\"114\" label=\"link\"></edge>        <edge id=\"11007\" source=\"111\" target=\"105\" label=\"link\"></edge>        <edge id=\"11008\" source=\"112\" target=\"108\" label=\"link\"></edge>        <edge id=\"11009\" source=\"113\" target=\"117\" label=\"link\"></edge>        <edge id=\"11010\" source=\"114\" target=\"109\" label=\"link\"></edge>        <edge id=\"11011\" source=\"115\" target=\"118\" label=\"link\"></edge>        <edge id=\"11012\" source=\"117\" target=\"113\" label=\"link\"></edge>        <edge id=\"11013\" source=\"118\" target=\"115\" label=\"link\"></edge>        <edge id=\"12000\" source=\"103\" target=\"1000\" label=\"host\"></edge>        <edge id=\"12001\" source=\"103\" target=\"1001\" label=\"host\"></edge>        <edge id=\"12002\" source=\"110\" target=\"1002\" label=\"host\"></edge>        <edge id=\"12003\" source=\"116\" target=\"1003\" label=\"host\"></edge>        <edge id=\"12004\" source=\"106\" target=\"1004\" label=\"host\"></edge>        <edge id=\"12005\" source=\"119\" target=\"1005\" label=\"host\"></edge>      </graph>    </graphml>";
+	
+	private static final String testDataLocation = "titan/schema/test-network.xml";
+	
+	public static TitanGraph getTestDatabase(){
+		//return TitanFactory.open(testDbLocation);
+//		return TitanFactory.openInMemoryGraph();
+		return TitanFactory.open(testDbLocation);
+	}
+	
+	public static void populateTestData(TitanGraph titanGraph){
+		Set<String> s = titanGraph.getIndexedKeys(Vertex.class);
+        if (!s.contains("dpid")) {
+           titanGraph.createKeyIndex("dpid", Vertex.class);
+           titanGraph.stopTransaction(Conclusion.SUCCESS);
+        }
+        if (!s.contains("type")) {
+        	titanGraph.createKeyIndex("type", Vertex.class);
+        	titanGraph.stopTransaction(Conclusion.SUCCESS);
+        }
+        
+        //InputStream graphMLStream = new ByteArrayInputStream(testDbGraphML.getBytes());
+        
+        try {
+        	InputStream graphMLStream = new FileInputStream(testDataLocation);
+			GraphMLReader.inputGraph(titanGraph, graphMLStream);
+		} catch (FileNotFoundException e) {
+			Assert.fail("Test data file not found: " + testDataLocation);
+		} catch (IOException e) {
+			e.printStackTrace();
+			Assert.fail("IOException thrown");
+		}
+        
+        //Change the type of all port numbers to short in the database
+        Iterator<Vertex> it = titanGraph.getVertices("type", "port").iterator();
+
+        while (it.hasNext()){
+        	Vertex port = it.next();
+
+        	if(port.getProperty("number") instanceof Short)
+        	{
+        		Short portNum = (Short) port.getProperty("number");
+        		port.setProperty("number", portNum.shortValue());
+        	}
+        	else{
+        		Integer portNum = (Integer) port.getProperty("number");	
+        		port.setProperty("number", portNum.shortValue());
+        	}
+
+        }
+        
+        titanGraph.stopTransaction(Conclusion.SUCCESS);
+	}
+	
+	public static void deleteTestDatabase(){
+		try {
+			FileUtils.deleteDirectory(new File(testDbLocation));
+		} catch (IOException e) {
+			System.out.println("delete failed");
+			e.printStackTrace();
+		}
+	}
+	
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
new file mode 100644
index 0000000..bcff36a
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableGraphDBOperation.java
@@ -0,0 +1,1523 @@
+package net.onrc.onos.ofcontroller.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.easymock.EasyMock;
+import org.openflow.util.HexString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.frames.Property;
+import com.tinkerpop.frames.annotations.gremlin.GremlinParam;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.graph.IDBConnection;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.util.FlowEntryId;
+import net.onrc.onos.ofcontroller.util.FlowId;
+
+/**
+ * Mock class of GraphDBOperation which provides additional setter to construct a graph for test.
+ * This object simply caches parameters set up by override interfaces and reflect them when commit().
+ * *ForTest() methods are exempt from cache, parameters through those methods are reflected soon.
+ * @author Naoki Shiota
+ *
+ */
+public class TestableGraphDBOperation extends GraphDBOperation {
+	protected static Logger log = LoggerFactory.getLogger(TestableGraphDBOperation.class);
+
+	protected List<TestSwitchObject> switches;
+	protected List<TestPortObject> ports;
+	protected List<TestDeviceObject> devices;
+	protected List<TestFlowPath> paths;
+	protected List<TestFlowEntry> entries;
+
+	protected List<TestSwitchObject> switchesToAdd;
+	protected List<TestPortObject> portsToAdd;
+	protected List<TestDeviceObject> devicesToAdd;
+	protected List<TestFlowPath> pathsToAdd;
+	protected List<TestFlowEntry> entriesToAdd;
+
+	protected List<TestSwitchObject> switchesToRemove;
+	protected List<TestPortObject> portsToRemove;
+	protected List<TestDeviceObject> devicesToRemove;
+	protected List<TestFlowPath> pathsToRemove;
+	protected List<TestFlowEntry> entriesToRemove;
+
+	// Testable implementations of INetMapTopologyObject interfaces
+
+	public static class TestSwitchObject implements ISwitchObject {
+		private String state,type,dpid;
+		private List<IPortObject> ports;
+		private List<IDeviceObject> devices;
+		private List<IFlowEntry> entries;
+
+		private String stateToUpdate, typeToUpdate, dpidToUpdate;
+		private List<IPortObject> portsToAdd;
+		private List<IPortObject> portsToRemove;
+
+		public TestSwitchObject() {
+			type = "switch";
+			
+			ports = new ArrayList<IPortObject>();
+			portsToAdd = new ArrayList<IPortObject>();
+			portsToRemove = new ArrayList<IPortObject>();
+			devices = new ArrayList<IDeviceObject>();
+			entries = new ArrayList<IFlowEntry>();
+			
+			clearUncommitedData();
+		}
+		
+		public void commit() {
+			for(IPortObject port : portsToAdd) {
+				ports.add(port);
+			}
+			for(IPortObject port : portsToRemove) {
+				ports.remove(port);
+			}
+			if(stateToUpdate != null) { state = stateToUpdate; }
+			if(typeToUpdate != null) { type = typeToUpdate; }
+			if(dpidToUpdate != null) { dpid = dpidToUpdate; }
+
+			clearUncommitedData();
+		}
+		
+		public void rollback() {
+			clearUncommitedData();
+		}
+		
+		public void clearUncommitedData() {
+			portsToAdd.clear();
+			portsToRemove.clear();
+			stateToUpdate = typeToUpdate = dpidToUpdate = null;
+		}
+		
+		public void setStateForTest(String state) { this.state = state; }
+		public void setTypeForTest(String type) { this.type = type; }
+		public void setDpidForTest(String dpid) { this.dpid = dpid; }
+		public void addPortForTest(TestPortObject port) { ports.add(port);  }
+		public void addDeviceForTest(TestDeviceObject dev) { devices.add(dev); }
+		public void addEntryForTest(TestFlowEntry entry) { entries.add(entry); }
+		
+		@Override
+		public String getState() { return state; }
+	
+		@Override
+		public void setState(String state) { this.stateToUpdate = state; }
+	
+		@Override
+		public String getType() { return type ; }
+	
+		@Override
+		public void setType(String type) { this.typeToUpdate = type; }
+	
+		// Not support for test
+		@Override
+		public Vertex asVertex() { return null; }
+	
+		@Override
+		public String getDPID() { return dpid; }
+	
+		@Override
+		public void setDPID(String dpid) { this.dpidToUpdate = dpid; }
+	
+		@Override
+		public Iterable<IPortObject> getPorts() { return ports; }
+	
+		@Override
+		public IPortObject getPort(@GremlinParam("port_num") short port_num) {
+			for(IPortObject port : ports) {
+				if(port.getNumber() == port_num) {
+					return port;
+				}
+			}
+			return null;
+		}
+	
+		@Override
+		public void addPort(IPortObject port) { portsToAdd.add(port); }
+	
+		@Override
+		public void removePort(IPortObject port) { portsToRemove.add(port); }
+	
+		@Override
+		public Iterable<IDeviceObject> getDevices() { return devices; }
+	
+		@Override
+		public Iterable<IFlowEntry> getFlowEntries() { return entries; }
+	}
+	
+	public static class TestPortObject implements IPortObject {
+		private String state,type,desc;
+		private Short number;
+		private Integer port_state;
+		private ISwitchObject sw;
+		
+		private List<IPortObject> linkedPorts;
+		private List<IDeviceObject> devices;
+		private List<IFlowEntry> inflows,outflows;
+		
+		private String stateToUpdate,typeToUpdate,descToUpdate;
+		private Short numberToUpdate;
+		private Integer port_stateToUpdate;
+		
+		private List<IPortObject> linkedPortsToAdd;
+		private List<IPortObject> linkedPortsToRemove;
+		private List<IDeviceObject> devicesToAdd;
+		private List<IDeviceObject> devicesToRemove;
+		
+
+		public TestPortObject() {
+			type = "port";
+
+			linkedPorts = new ArrayList<IPortObject>();
+			linkedPortsToAdd = new ArrayList<IPortObject>();
+			linkedPortsToRemove = new ArrayList<IPortObject>();
+			devices = new ArrayList<IDeviceObject>();
+			devicesToAdd = new ArrayList<IDeviceObject>();
+			devicesToRemove = new ArrayList<IDeviceObject>();
+			inflows = new ArrayList<IFlowEntry>();
+			outflows = new ArrayList<IFlowEntry>();
+			
+			clearUncommitedData();
+		}
+		
+		public void commit() {
+			for(IPortObject port : linkedPortsToAdd) { linkedPorts.add(port); }
+			for(IPortObject port : linkedPortsToRemove) { linkedPorts.remove(port); }
+			for(IDeviceObject dev : devicesToAdd) { devices.add(dev); }
+			for(IDeviceObject dev : devicesToRemove) { devices.remove(dev); }
+			
+			if(stateToUpdate != null) { state = stateToUpdate; }
+			if(typeToUpdate != null) { type = typeToUpdate; }
+			if(descToUpdate != null) { desc = descToUpdate; }
+			if(numberToUpdate != null) { number = numberToUpdate; }
+			if(port_stateToUpdate != null) { port_state = port_stateToUpdate; }
+			
+			clearUncommitedData();
+		}
+		
+		public void rollback() {
+			clearUncommitedData();
+		}
+		
+		public void clearUncommitedData() {
+			linkedPortsToAdd.clear();
+			linkedPortsToRemove.clear();
+			devicesToAdd.clear();
+			devicesToRemove.clear();
+			stateToUpdate = typeToUpdate = descToUpdate = null;
+			port_stateToUpdate = null;
+			numberToUpdate = null;
+		}
+		
+		// Setter methods for test
+		public void setStateForTest(String state) { this.state = state; }
+		public void setTypeForTest(String type) { this.type = type; }
+		public void setDescForTest(String desc) { this.desc = desc; }
+		public void setNumberForTest(Short number) { this.number = number; }
+		public void setPortStateForTest(Integer state) { this.port_state = state; }
+		public void setSwitchForTest(ISwitchObject sw) { this.sw = sw; }
+		public void addLinkedPortForTest(TestPortObject port) { this.linkedPorts.add(port); }
+		public void addInflowForTest(TestFlowEntry entry) { inflows.add(entry); }
+		public void addOutflowForTest(TestFlowEntry entry) { outflows.add(entry); }
+		
+		// Override methods for mock IPortObject
+		@Override
+		public String getState() { return state; }
+
+		@Override
+		public void setState(String state) { this.stateToUpdate = state; }
+
+		@Override
+		public String getType() { return type; }
+
+		@Override
+		public void setType(String type) { this.typeToUpdate = type; }
+
+		// not support for test
+		@Override
+		public Vertex asVertex() {
+			return null;
+		}
+
+		@Override
+		public Short getNumber() { return number; }
+
+		@Override
+		public void setNumber(Short n) { this.numberToUpdate = n; }
+
+		@Override
+		public String getDesc() { return desc; }
+
+		@Override
+		public void setDesc(String s) { this.descToUpdate = s; }
+
+		@Override
+		public Integer getPortState() { return port_state; }
+
+		@Override
+		public void setPortState(Integer s) { this.port_stateToUpdate = s; }
+
+		@Override
+		public ISwitchObject getSwitch() { return sw; }
+
+		@Override
+		public Iterable<IDeviceObject> getDevices() { return devices; }
+
+		@Override
+		public void setDevice(IDeviceObject device) { devicesToAdd.add(device); }
+
+		@Override
+		public void removeDevice(IDeviceObject device) { devicesToRemove.add(device); }
+
+		@Override
+		public Iterable<IFlowEntry> getInFlowEntries() { return inflows; }
+
+		@Override
+		public Iterable<IFlowEntry> getOutFlowEntries() { return outflows; }
+
+		@Override
+		public Iterable<IPortObject> getLinkedPorts() { return linkedPorts; }
+
+		@Override
+		public void removeLink(IPortObject dest_port) { linkedPortsToRemove.add(dest_port); }
+
+		@Override
+		public void setLinkPort(IPortObject dest_port) { linkedPortsToAdd.add(dest_port); }
+
+		@Override
+		@JsonIgnore
+		@Property("port_id")
+		public void setPortId(String id) {
+			// TODO Auto-generated method stub
+			
+		}
+
+		@Override
+		@JsonIgnore
+		@Property("port_id")
+		public String getPortId() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+	}
+		
+	public static class TestDeviceObject implements IDeviceObject {
+		private String state,type,mac,ipaddr;
+		private List<IPortObject> ports;
+		private List<ISwitchObject> switches;
+		
+		private String stateToUpdate,typeToUpdate,macToUpdate,ipaddrToUpdate;
+		private List<IPortObject> portsToAdd;
+		private List<IPortObject> portsToRemove;
+	
+		public TestDeviceObject() {
+			type = "device";
+			
+			ports = new ArrayList<IPortObject>();
+			portsToAdd = new ArrayList<IPortObject>();
+			portsToRemove = new ArrayList<IPortObject>();
+			switches = new ArrayList<ISwitchObject>();
+			
+			clearUncommitedData();
+		}
+		
+		public void commit() {
+			for(IPortObject port : portsToAdd) {
+				ports.add(port);
+			}
+			for(IPortObject port : portsToRemove) {
+				ports.remove(port);
+			}
+			
+			if(stateToUpdate != null) { state = stateToUpdate; }
+			if(typeToUpdate != null) { type = typeToUpdate; }
+			if(macToUpdate != null) { mac = macToUpdate; }
+			if(ipaddrToUpdate != null) { ipaddr = ipaddrToUpdate; }
+			
+			clearUncommitedData();
+		}
+		
+		public void rollback() {
+			clearUncommitedData();
+		}
+		
+		public void clearUncommitedData() {
+			ports.clear();
+			portsToAdd.clear();
+			portsToRemove.clear();
+			
+			stateToUpdate = typeToUpdate = macToUpdate = ipaddrToUpdate = null;
+		}
+		
+		// Setter methods for test
+		public void setStateForTest(String state) { this.state = state; }
+		public void setTypeForTest(String type) { this.type = type; }
+		public void setMacForTest(String mac) { this.mac = mac; }
+		public void setIpaddrForTest(String ipaddr) { this.ipaddr = ipaddr; }
+		public void addSwitchForTest(ISwitchObject sw) { switches.add(sw); }
+		public void addPortForTest(IPortObject port) { ports.add(port); }
+		
+		
+		// Override methods
+		@Override
+		public String getState() { return state; }
+	
+		@Override
+		public void setState(String state) { stateToUpdate = state; }
+	
+		@Override
+		public String getType() { return type; }
+	
+		@Override
+		public void setType(String type) { typeToUpdate = type; }
+	
+		@Override
+		public Vertex asVertex() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+	
+		@Override
+		public String getMACAddress() { return mac; }
+	
+		@Override
+		public void setMACAddress(String macaddr) { macToUpdate = macaddr; }
+	
+		@Override
+		public String getIPAddress() { return ipaddr; }
+	
+		@Override
+		public void setIPAddress(String ipaddr) { ipaddrToUpdate = ipaddr; }
+	
+		@Override
+		public Iterable<IPortObject> getAttachedPorts() {
+			return ports; }
+	
+		@Override
+		public void setHostPort(IPortObject port) { portsToAdd.add(port); }
+	
+		@Override
+		public void removeHostPort(IPortObject port) { portsToRemove.add(port); }
+	
+		@Override
+		public Iterable<ISwitchObject> getSwitch() { return switches; }
+	}
+	
+	public static class TestFlowPath implements IFlowPath {
+		private String state,type,flowId,installerId,srcSw,dstSw;
+		private Long flowPathFlags;
+		private String dataPathSummary,userState;
+		private Short srcPort,dstPort;
+		private String matchSrcMac,matchDstMac;
+		private Short matchEthernetFrameType;
+		private Short matchVlanId;
+		private Byte matchVlanPriority;
+		private String matchSrcIpaddr,matchDstIpaddr;
+		private Byte matchIpProto, matchIpToS;
+		private Short matchSrcTcpUdpPort, matchDstTcpUdpPort;
+		private String actions;
+		
+		private List<IFlowEntry> entries;
+		private List<ISwitchObject> switches;
+
+		private String stateToUpdate,typeToUpdate,flowIdToUpdate,installerIdToUpdate,srcSwToUpdate,dstSwToUpdate;
+		private Long flowPathFlagsToUpdate;
+		private String dataPathSummaryToUpdate,userStateToUpdate;
+		private Short srcPortToUpdate,dstPortToUpdate;
+		private String matchSrcMacToUpdate,matchDstMacToUpdate;
+		private Short matchEthernetFrameTypeToUpdate;
+		private Short matchVlanIdToUpdate;
+		private Byte matchVlanPriorityToUpdate;
+		private String matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
+		private Byte matchIpProtoToUpdate, matchIpToSToUpdate;
+		private Short matchSrcTcpUdpPortToUpdate, matchDstTcpUdpPortToUpdate;
+		private String actionsToUpdate;
+
+		private List<IFlowEntry> flowsToAdd;
+		private List<IFlowEntry> flowsToRemove;
+
+		public TestFlowPath() {
+			type = "flow";
+			
+			entries = new ArrayList<IFlowEntry>();
+			flowsToAdd = new ArrayList<IFlowEntry>();
+			flowsToRemove = new ArrayList<IFlowEntry>();
+			
+			switches = new ArrayList<ISwitchObject>();
+			
+			clear();
+		}
+		
+		public void commit() {
+			for(IFlowEntry flow : flowsToAdd) {
+				entries.add(flow);
+			}
+			for(IFlowEntry flow : flowsToRemove) {
+				entries.remove(flow);
+			}
+			if(stateToUpdate != null) { state = stateToUpdate; }
+			if(typeToUpdate != null) { type = typeToUpdate; }
+			if(flowIdToUpdate != null) { flowId = flowIdToUpdate; }
+			if(installerIdToUpdate != null) { installerId = installerIdToUpdate; }
+			if(flowPathFlagsToUpdate != null) { flowPathFlags = flowPathFlagsToUpdate; }
+			if(srcSwToUpdate != null) { srcSw = srcSwToUpdate; }
+			if(dstSwToUpdate != null) { dstSw = dstSwToUpdate; }
+			if(dataPathSummaryToUpdate != null) { dataPathSummary = dataPathSummaryToUpdate; }
+			if(userStateToUpdate != null) { userState = userStateToUpdate; }
+			if(srcPortToUpdate != null) { srcPort = srcPortToUpdate; }
+			if(dstPortToUpdate != null) { dstPort = dstPortToUpdate; }
+			if(matchSrcMacToUpdate != null) { matchSrcMac = matchSrcMacToUpdate; }
+			if(matchDstMacToUpdate != null) { matchDstMac = matchDstMacToUpdate; }
+			if(matchEthernetFrameTypeToUpdate != null) { matchEthernetFrameType = matchEthernetFrameTypeToUpdate; }
+			if(matchVlanIdToUpdate != null) { matchVlanId = matchVlanIdToUpdate; }
+			if(matchVlanPriorityToUpdate != null) { matchVlanPriority = matchVlanPriorityToUpdate; }
+			if(matchSrcIpaddrToUpdate != null) { matchSrcIpaddr = matchSrcIpaddrToUpdate; }
+			if(matchDstIpaddrToUpdate != null) { matchDstIpaddr = matchDstIpaddrToUpdate; }
+			if(matchIpProtoToUpdate != null) { matchIpProto = matchIpProtoToUpdate; }
+			if(matchIpToSToUpdate != null) { matchIpToS = matchIpToSToUpdate; }
+			if(matchSrcTcpUdpPortToUpdate != null) { matchSrcTcpUdpPort = matchSrcTcpUdpPortToUpdate; }
+			if(matchDstTcpUdpPortToUpdate != null) { matchDstTcpUdpPort = matchDstTcpUdpPortToUpdate; }
+			if(actionsToUpdate != null) { actions = actionsToUpdate; }
+		}
+		
+		public void rollback() {
+			clear();
+		}
+		
+		public void clear() {
+			flowsToAdd.clear();
+			flowsToRemove.clear();
+			
+			stateToUpdate = typeToUpdate = flowIdToUpdate = installerIdToUpdate = null;
+			flowPathFlagsToUpdate = null;
+			srcSwToUpdate = dstSwToUpdate = dataPathSummaryToUpdate = userStateToUpdate = null;
+			srcPortToUpdate = dstPortToUpdate = null;
+			matchSrcMacToUpdate = matchDstMacToUpdate = null;
+			matchEthernetFrameTypeToUpdate = null;
+			matchVlanIdToUpdate = null;
+			matchVlanPriorityToUpdate = null;
+			matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
+			matchIpProtoToUpdate = matchIpToSToUpdate = null;
+			matchSrcTcpUdpPortToUpdate = matchDstTcpUdpPortToUpdate = null;
+			actionsToUpdate = null;
+		}
+		
+		// Setter methods for test
+		public void setStateForTest(String state) { this.state = state; }
+		public void setTypeForTest(String type) { this.type = type; }
+		public void setFlowIdForTest(String flowId) { this.flowId = flowId; }
+		public void setInstallerIdForTest(String installerId) { this.installerId = installerId; }
+		public void setFlowPathFlagsForTest(Long flowPathFlags) { this.flowPathFlags = flowPathFlags; }
+		public void setSrcSwForTest(String srcSw) { this.srcSw = srcSw; }
+		public void setDstSwForTest(String dstSw) { this.dstSw = dstSw; }
+		public void setDataPathSummaryForTest(String dataPathSummary) { this.dataPathSummary = dataPathSummary; }
+		public void setUserStateForTest(String userState) { this.userState = userState; }
+		public void setSrcPortForTest(Short srcPort) { this.srcPort = srcPort; }
+		public void setDstPortForTest(Short dstPort) { this.dstPort = dstPort; }
+		public void setMatchSrcMacForTest(String matchSrcMac) { this.matchSrcMac = matchSrcMac; }
+		public void setMatchDstMacForTest(String matchDstMac) { this.matchDstMac = matchDstMac; }
+		public void setMatchEthernetFrameTypeForTest(Short matchEthernetFrameType) { this.matchEthernetFrameType = matchEthernetFrameType; }
+		public void setMatchVlanIdForTest(Short matchVlanId) { this.matchVlanId = matchVlanId; }
+		public void setMatchVlanPriorityForTest(Byte matchVlanPriority) { this.matchVlanPriority = matchVlanPriority; }
+		public void setMatchSrcIpaddrForTest(String matchSrcIpaddr) { this.matchSrcIpaddr = matchSrcIpaddr; }
+		public void setMatchDstIpaddrForTest(String matchDstIpaddr) { this.matchDstIpaddr = matchDstIpaddr; }
+		public void setMatchIpProtoForTest(Byte matchIpProto) { this.matchIpProto = matchIpProto; }
+		public void setMatchIpToSForTest(Byte matchIpToS) { this.matchIpToS = matchIpToS; }
+		public void setMatchSrcTcpUdpPortForTest(Short matchSrcTcpUdpPort) { this.matchSrcTcpUdpPort = matchSrcTcpUdpPort; }
+		public void setMatchDstTcpUdpPortForTest(Short matchDstTcpUdpPort) { this.matchDstTcpUdpPort = matchDstTcpUdpPort; }
+		public void setActionsForTest(String actions) { this.actions = actions; }
+		public void addFlowEntryForTest(IFlowEntry entry) { entries.add(entry); }
+		public void addSwitchForTest(ISwitchObject sw) { switches.add(sw); }
+
+		@Override
+		public String getState() { return state; }
+
+		@Override
+		public void setState(String state) { stateToUpdate = state; }
+
+		@Override
+		public String getType() { return type; }
+
+		@Override
+		public void setType(String type) { typeToUpdate = type; }
+
+		@Override
+		public Vertex asVertex() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+
+		@Override
+		public String getFlowId() { return flowId; }
+
+		@Override
+		public void setFlowId(String flowId) { flowIdToUpdate = flowId; }
+
+		@Override
+		public String getInstallerId() { return installerId; }
+
+		@Override
+		public void setInstallerId(String installerId) { installerIdToUpdate = installerId; }
+
+		@Override
+		public Long getFlowPathFlags() { return flowPathFlags; }
+
+		@Override
+		public void setFlowPathFlags(Long flowPathFlags) { flowPathFlagsToUpdate = flowPathFlags; }
+
+		@Override
+		public String getSrcSwitch() { return srcSw; }
+
+		@Override
+		public void setSrcSwitch(String srcSwitch) { srcSwToUpdate = srcSwitch; }
+
+		@Override
+		public Short getSrcPort() { return srcPort; }
+
+		@Override
+		public void setSrcPort(Short srcPort) { srcPortToUpdate = srcPort; }
+
+		@Override
+		public String getDstSwitch() { return dstSw; }
+
+		@Override
+		public void setDstSwitch(String dstSwitch) { dstSwToUpdate = dstSwitch; }
+
+		@Override
+		public Short getDstPort() { return dstPort; }
+
+		@Override
+		public void setDstPort(Short dstPort) { dstPortToUpdate = dstPort; }
+
+		@Override
+		public String getDataPathSummary() { return dataPathSummary; }
+
+		@Override
+		public void setDataPathSummary(String dataPathSummary) { dataPathSummaryToUpdate = dataPathSummary; }
+
+		@Override
+		public Iterable<IFlowEntry> getFlowEntries() { return entries; }
+
+		@Override
+		public void addFlowEntry(IFlowEntry flowEntry) {
+			if(! entries.contains(flowEntry)) {
+				flowsToAdd.add(flowEntry);
+			}
+		}
+
+		@Override
+		public void removeFlowEntry(IFlowEntry flowEntry) {
+			if(entries.contains(flowEntry)) {
+				flowsToAdd.add(flowEntry);
+			}
+		}
+
+		@Override
+		public String getMatchSrcMac() { return matchSrcMac; }
+
+		@Override
+		public void setMatchSrcMac(String matchSrcMac) { matchSrcMacToUpdate = matchSrcMac; }
+
+		@Override
+		public String getMatchDstMac() { return matchDstMac; }
+
+		@Override
+		public void setMatchDstMac(String matchDstMac) { matchDstMacToUpdate = matchDstMac; }
+
+		@Override
+		public Short getMatchEthernetFrameType() { return matchEthernetFrameType; }
+
+		@Override
+		public void setMatchEthernetFrameType(Short matchEthernetFrameType) {
+			matchEthernetFrameTypeToUpdate = matchEthernetFrameType; }
+
+		@Override
+		public Short getMatchVlanId() { return matchVlanId; }
+
+		@Override
+		public void setMatchVlanId(Short matchVlanId) {
+			matchVlanIdToUpdate = matchVlanId; }
+
+		@Override
+		public Byte getMatchVlanPriority() { return matchVlanPriority; }
+
+		@Override
+		public void setMatchVlanPriority(Byte matchVlanPriority) {
+			matchVlanPriorityToUpdate = matchVlanPriority; }
+
+		@Override
+		public String getMatchSrcIPv4Net() { return matchSrcIpaddr; }
+
+		@Override
+		public void setMatchSrcIPv4Net(String matchSrcIPv4Net) {
+			matchSrcIpaddrToUpdate = matchSrcIPv4Net; }
+
+		@Override
+		public String getMatchDstIPv4Net() { return matchDstIpaddr; }
+
+		@Override
+		public void setMatchDstIPv4Net(String matchDstIPv4Net) {
+			matchDstIpaddrToUpdate = matchDstIPv4Net; }
+
+		@Override
+		public Byte getMatchIpProto() { return matchIpProto; }
+
+		@Override
+		public void setMatchIpProto(Byte matchIpProto) {
+			matchIpProtoToUpdate = matchIpProto; }
+
+		@Override
+		public Byte getMatchIpToS() { return matchIpToS; }
+
+		@Override
+		public void setMatchIpToS(Byte matchIpToS) {
+			matchIpToSToUpdate = matchIpToS; }
+
+		@Override
+		public Short getMatchSrcTcpUdpPort() { return matchSrcTcpUdpPort; }
+
+		@Override
+		public void setMatchSrcTcpUdpPort(Short matchSrcTcpUdpPort) {
+			matchSrcTcpUdpPortToUpdate = matchSrcTcpUdpPort; }
+
+		@Override
+		public Short getMatchDstTcpUdpPort() { return matchDstTcpUdpPort; }
+
+		@Override
+		public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort) {
+			matchDstTcpUdpPortToUpdate = matchDstTcpUdpPort; }
+
+		@Override
+		public String getActions() { return actions; }
+
+		@Override
+		public void setActions(String actions) {
+			actionsToUpdate = actions; }
+
+		@Override
+		public Iterable<ISwitchObject> getSwitches() { return switches; }
+
+		@Override
+		public String getUserState() { return userState; }
+
+		@Override
+		public void setUserState(String userState) { userStateToUpdate = userState; }
+	}
+
+	public static class TestFlowEntry implements IFlowEntry {
+		private String state,type,entryId,dpid,userState,switchState,errorStateType,errorStateCode;
+		private Short matchInPort;
+		private String matchSrcMac,matchDstMac;
+		private Short matchEtherFrameType;
+		private Short matchVlanId;
+		private Byte matchVlanPriority;
+		private String matchSrcIpaddr,matchDstIpaddr;
+		private Byte matchIpProto, matchIpToS;
+		private Short matchSrcTcpUdpPort, matchDstTcpUdpPort;
+		private Short actionOutputPort;
+		private String actions;
+		
+		private IFlowPath flowPath;
+		private ISwitchObject sw;
+		private IPortObject inport,outport;
+	
+		private String stateToUpdate,typeToUpdate,entryIdToUpdate,dpidToUpdate,
+			userStateToUpdate,switchStateToUpdate,errorStateTypeToUpdate,errorStateCodeToUpdate;
+		private Short matchInPortToUpdate;
+		private String matchSrcMacToUpdate,matchDstMacToUpdate;
+		private Short matchEtherFrameTypeToUpdate;
+		private Short matchVlanIdToUpdate;
+		private Byte matchVlanPriorityToUpdate;
+		private String matchSrcIpaddrToUpdate,matchDstIpaddrToUpdate;
+		private Byte matchIpProtoToUpdate, matchIpToSToUpdate;
+		private Short matchSrcTcpUdpPortToUpdate, matchDstTcpUdpPortToUpdate;
+		private Short actionOutputPortToUpdate;
+		private String actionsToUpdate;
+	
+		private IFlowPath flowPathToUpdate;
+		private ISwitchObject swToUpdate;
+		private IPortObject inportToUpdate,outportToUpdate;
+	
+		public TestFlowEntry() {
+			type = "flow_entry";
+			
+			clearUncommitedData();
+		}
+		
+		public void commit() {
+			if(stateToUpdate != null) { state = stateToUpdate; }
+			if(typeToUpdate != null) { type = typeToUpdate; }
+			if(entryIdToUpdate != null) { entryId = entryIdToUpdate; }
+			if(dpidToUpdate != null) { dpid = dpidToUpdate; }
+			if(userStateToUpdate != null) { userState = userStateToUpdate; }
+			if(switchStateToUpdate != null) { switchState = switchStateToUpdate; }
+			if(errorStateTypeToUpdate != null) { errorStateType = errorStateTypeToUpdate; }
+			if(errorStateCodeToUpdate != null) { errorStateCode = errorStateCodeToUpdate; }
+			if(matchInPortToUpdate != null) { matchInPort = matchInPortToUpdate; }
+			if(matchSrcMacToUpdate != null) { matchSrcMac = matchSrcMacToUpdate; }
+			if(matchDstMacToUpdate != null) { matchDstMac = matchDstMacToUpdate; }
+			if(matchEtherFrameTypeToUpdate != null) { matchEtherFrameType = matchEtherFrameTypeToUpdate; }
+			if(matchVlanIdToUpdate != null) { matchVlanId = matchVlanIdToUpdate; }
+			if(matchVlanPriorityToUpdate != null) { matchVlanPriority = matchVlanPriorityToUpdate; }
+			if(matchSrcIpaddrToUpdate != null) { matchSrcIpaddr = matchSrcIpaddrToUpdate; }
+			if(matchDstIpaddrToUpdate != null) { matchDstIpaddr = matchDstIpaddrToUpdate; }
+			if(matchIpProtoToUpdate != null) { matchIpProto = matchIpProtoToUpdate; }
+			if(matchIpToSToUpdate != null) { matchIpToS = matchIpToSToUpdate; }
+			if(matchSrcTcpUdpPortToUpdate != null) { matchSrcTcpUdpPort = matchSrcTcpUdpPortToUpdate; }
+			if(matchDstTcpUdpPortToUpdate != null) { matchDstTcpUdpPort = matchDstTcpUdpPortToUpdate; }
+			if(actionOutputPortToUpdate != null) { actionOutputPort = actionOutputPortToUpdate; }
+			if(actionsToUpdate != null) { actions = actionsToUpdate; }
+			
+			if(flowPathToUpdate != null) { flowPath = flowPathToUpdate; }
+			if(swToUpdate != null) { sw = swToUpdate; }
+			if(inportToUpdate != null) { inport = inportToUpdate; }
+			if(outportToUpdate != null) { outport = outportToUpdate; }
+	
+			clearUncommitedData();
+		}
+		
+		public void rollback() {
+			clearUncommitedData();
+		}
+		
+		public void clearUncommitedData() {
+			stateToUpdate = typeToUpdate = entryIdToUpdate = dpidToUpdate = null;
+			userStateToUpdate = switchStateToUpdate = errorStateTypeToUpdate = errorStateCodeToUpdate = null;
+			matchInPortToUpdate = null;
+			matchSrcMacToUpdate = matchDstMacToUpdate = null;
+			matchEtherFrameTypeToUpdate = null;
+			matchVlanIdToUpdate = null;
+			matchVlanPriorityToUpdate = null;
+			matchSrcIpaddrToUpdate = matchDstIpaddrToUpdate = null;
+			matchIpProtoToUpdate = matchIpToSToUpdate = null;
+			matchSrcTcpUdpPortToUpdate = matchDstTcpUdpPortToUpdate = null;
+			actionOutputPortToUpdate = null;
+			actionsToUpdate = null;
+			flowPathToUpdate = null;
+			swToUpdate = null;
+			inportToUpdate = outportToUpdate = null;
+		}
+		
+		// Setter methods for test
+		public void setStateForTest(String state) { this.state = state; }
+		public void setTypeForTest(String type) { this.type = type; }
+		public void setEntryIdForTest(String entryId) { this.entryId = entryId; }
+		public void setDpidForTest(String dpid) { this.dpid = dpid; }
+		public void setUserStateForTest(String userState) { this.userState = userState; }
+		public void setSwitchStateForTest(String switchState) { this.switchState = switchState; }
+		public void setErrorStateTypeForTest(String errorStateType) { this.errorStateType = errorStateType; }
+		public void setErrorStateCodeForTest(String errorStateCode) { this.errorStateCode = errorStateCode; }
+		public void setMatchInPortForTest(Short matchInPort) { this.matchInPort = matchInPort; }
+		public void setMatchSrcMacForTest(String matchSrcMac) { this.matchSrcMac = matchSrcMac; }
+		public void setMatchDstMacForTest(String matchDstMac) { this.matchDstMac = matchDstMac; }
+		public void setMatchEtherFrameTypeForTest(Short matchEtherFrameType) { this.matchEtherFrameType = matchEtherFrameType; }
+		public void setMatchVlanIdForTest(Short matchVlanId) { this.matchVlanId = matchVlanId; }
+		public void setMatchVlanPriorityForTest(Byte matchVlanPriority) { this.matchVlanPriority = matchVlanPriority; }
+		public void setMatchSrcIpaddrForTest(String matchSrcIpaddr) { this.matchSrcIpaddr = matchSrcIpaddr; }
+		public void setMatchDstIpaddrForTest(String matchDstIpaddr) { this.matchDstIpaddr = matchDstIpaddr; }
+		public void setMatchIpProtoForTest(Byte matchIpProto) { this.matchIpProto = matchIpProto; }
+		public void setMatchIpToSForTest(Byte matchIpToS) { this.matchIpToS = matchIpToS; }
+		public void setMatchSrcTcpUdpPortForTest(Short matchSrcTcpUdpPort) { this.matchSrcTcpUdpPort = matchSrcTcpUdpPort; }
+		public void setMatchDstTcpUdpPortForTest(Short matchDstTcpUdpPort) { this.matchDstTcpUdpPort = matchDstTcpUdpPort; }
+		public void setActionOutputPortForTest(Short actionOutputPort) { this.actionOutputPort = actionOutputPort; }
+		public void setActionsForTest(String actions) { this.actions = actions; }
+		public void setFlowPathForTest(IFlowPath flowPath) { this.flowPath = flowPath; }
+		public void setSwitchForTest(ISwitchObject sw) { this.sw = sw; }
+		public void setInportForTest(IPortObject inport) { this.inport = inport; }
+		public void setOutportForTest(IPortObject outport) { this.outport = outport; }
+		
+		@Override
+		public String getState() { return state; }
+	
+		@Override
+		public void setState(String state) { stateToUpdate = state; }
+	
+		@Override
+		public String getType() { return type; }
+	
+		@Override
+		public void setType(String type) { typeToUpdate = type; }
+	
+		@Override
+		public Vertex asVertex() {
+			// TODO Auto-generated method stub
+			return null;
+		}
+	
+		@Override
+		public String getFlowEntryId() { return entryId; }
+	
+		@Override
+		public void setFlowEntryId(String flowEntryId) { entryIdToUpdate = flowEntryId; }
+	
+		@Override
+		public String getSwitchDpid() { return dpid; }
+	
+		@Override
+		public void setSwitchDpid(String switchDpid) { dpidToUpdate = switchDpid; }
+	
+		@Override
+		public String getUserState() { return userState; }
+	
+		@Override
+		public void setUserState(String userState) { userStateToUpdate = userState; }
+	
+		@Override
+		public String getSwitchState() { return switchState; }
+	
+		@Override
+		public void setSwitchState(String switchState) { switchStateToUpdate = switchState; }
+	
+		@Override
+		public String getErrorStateType() { return errorStateType; }
+	
+		@Override
+		public void setErrorStateType(String errorStateType) { errorStateTypeToUpdate = errorStateType; }
+	
+		@Override
+		public String getErrorStateCode() { return errorStateCode; }
+	
+		@Override
+		public void setErrorStateCode(String errorStateCode) { errorStateCodeToUpdate = errorStateCode; }
+	
+		@Override
+		public Short getMatchInPort() { return matchInPort; }
+	
+		@Override
+		public void setMatchInPort(Short matchInPort) { matchInPortToUpdate = matchInPort; }
+	
+		@Override
+		public String getMatchSrcMac() { return matchSrcMac; }
+	
+		@Override
+		public void setMatchSrcMac(String matchSrcMac) { matchSrcMacToUpdate = matchSrcMac; }
+	
+		@Override
+		public String getMatchDstMac() { return matchDstMac; }
+	
+		@Override
+		public void setMatchDstMac(String matchDstMac) { matchDstMacToUpdate = matchDstMac; }
+
+		@Override
+		public Short getMatchEthernetFrameType() {return matchEtherFrameType; }
+	
+		@Override
+		public void setMatchEthernetFrameType(Short matchEthernetFrameType) { matchEtherFrameTypeToUpdate = matchEthernetFrameType; }
+
+		@Override
+		public Short getMatchVlanId() {return matchVlanId; }
+	
+		@Override
+		public void setMatchVlanId(Short matchVlanId) { matchVlanId = matchVlanId; }
+
+		@Override
+		public Byte getMatchVlanPriority() {return matchVlanPriority; }
+	
+		@Override
+		public void setMatchVlanPriority(Byte matchVlanPriority) { matchVlanPriority = matchVlanPriority; }
+		
+		@Override
+		public String getMatchSrcIPv4Net() { return matchSrcIpaddr; }
+	
+		@Override
+		public void setMatchSrcIPv4Net(String matchSrcIPv4Net) { matchSrcIpaddrToUpdate = matchSrcIPv4Net; }
+	
+		@Override
+		public String getMatchDstIPv4Net() { return matchDstIpaddr; }
+	
+		@Override
+		public void setMatchDstIPv4Net(String matchDstIPv4Net) { matchDstIpaddrToUpdate = matchDstIPv4Net; }
+
+		@Override
+		public Byte getMatchIpProto() {return matchIpProto; }
+	
+		@Override
+		public void setMatchIpProto(Byte matchIpProto) { matchIpProto = matchIpProto; }
+
+		@Override
+		public Byte getMatchIpToS() {return matchIpToS; }
+	
+		@Override
+		public void setMatchIpToS(Byte matchIpToS) { matchIpToS = matchIpToS; }
+
+		@Override
+		public Short getMatchSrcTcpUdpPort() {return matchSrcTcpUdpPort; }
+	
+		@Override
+		public void setMatchSrcTcpUdpPort(Short matchSrcTcpUdpPort) { matchSrcTcpUdpPortToUpdate = matchSrcTcpUdpPort; }
+
+		@Override
+		public Short getMatchDstTcpUdpPort() {return matchDstTcpUdpPort; }
+	
+		@Override
+		public void setMatchDstTcpUdpPort(Short matchDstTcpUdpPort) { matchDstTcpUdpPortToUpdate = matchDstTcpUdpPort; }
+	
+		@Override
+		public Short getActionOutputPort() { return actionOutputPort; }
+	
+		@Override
+		public void setActionOutputPort(Short actionOutputPort) { actionOutputPortToUpdate = actionOutputPort; }
+
+		@Override
+		public String getActions() { return actions; }
+	
+		@Override
+		public void setActions(String actions) { actionsToUpdate = actions; }
+	
+		@Override
+		public IFlowPath getFlow() { return flowPath; }
+	
+		@Override
+		public void setFlow(IFlowPath flow) { flowPathToUpdate = flow; }
+	
+		@Override
+		public ISwitchObject getSwitch() { return sw; }
+	
+		@Override
+		public void setSwitch(ISwitchObject sw) { swToUpdate = sw; }
+	
+		@Override
+		public IPortObject getInPort() { return inport; }
+	
+		@Override
+		public void setInPort(IPortObject port) { inportToUpdate = port; }
+	
+		@Override
+		public IPortObject getOutPort() { return outport; }
+	
+		@Override
+		public void setOutPort(IPortObject port) { outportToUpdate = port; }
+	}
+
+
+	public TestableGraphDBOperation() {
+		super(EasyMock.createNiceMock(GraphDBConnection.class));
+		
+		switches = new ArrayList<TestSwitchObject>();
+		ports = new ArrayList<TestPortObject>();
+		devices = new ArrayList<TestDeviceObject>();
+		paths = new ArrayList<TestFlowPath>();
+		entries = new ArrayList<TestFlowEntry>();
+		
+		switchesToAdd = new ArrayList<TestSwitchObject>();
+		portsToAdd = new ArrayList<TestPortObject>();
+		devicesToAdd = new ArrayList<TestDeviceObject>();
+		pathsToAdd = new ArrayList<TestFlowPath>();
+		entriesToAdd = new ArrayList<TestFlowEntry>();
+
+		switchesToRemove = new ArrayList<TestSwitchObject>();
+		portsToRemove = new ArrayList<TestPortObject>();
+		devicesToRemove = new ArrayList<TestDeviceObject>();
+		pathsToRemove = new ArrayList<TestFlowPath>();
+		entriesToRemove = new ArrayList<TestFlowEntry>();
+		
+		clearUncommitedData();
+	}
+	
+	private void clearUncommitedData() {
+		for(TestFlowEntry flow : entries) {
+			flow.clearUncommitedData();
+		}
+		for(TestFlowEntry flow : entriesToAdd) {
+			flow.clearUncommitedData();
+		}
+		
+		for(TestDeviceObject dev : devices) {
+			dev.clearUncommitedData();
+		}
+		for(TestDeviceObject dev : devicesToAdd) {
+			dev.clearUncommitedData();
+		}
+		
+		for(TestSwitchObject sw : switches) {
+			sw.clearUncommitedData();
+		}
+		for(TestSwitchObject sw : switchesToAdd) {
+			sw.clearUncommitedData();
+		}
+		
+		for(TestPortObject port : ports) {
+			port.clearUncommitedData();
+		}
+		for(TestPortObject port : portsToAdd) {
+			port.clearUncommitedData();
+		}
+		
+		entriesToAdd.clear();
+		entriesToRemove.clear();
+		devicesToAdd.clear();
+		devicesToRemove.clear();
+		switchesToAdd.clear();
+		switchesToRemove.clear();
+		portsToAdd.clear();
+		portsToRemove.clear();
+	}
+	
+	
+	// this.*ForTest() methods below are supposed to be used for creation of test topology.
+	/**
+	 * Create new empty TestSwitchObject.
+	 * @return New TestSwitchObject
+	 */
+	public TestSwitchObject createNewSwitchForTest() {
+		TestSwitchObject sw = new TestSwitchObject();
+		switches.add(sw);
+		return sw;
+	}
+	
+	/**
+	 * Create new TestSwitchObject with specific DPID.
+	 * @param dpid DPID to be set
+	 * @return New TestSwitchObject
+	 */
+	public TestSwitchObject createNewSwitchForTest(String dpid) {
+		for(TestSwitchObject sw_loop : switches) {
+			if(sw_loop.getDPID().equals(dpid)) {
+				// Already created
+				log.error("switch already exists : " + dpid);
+				return sw_loop;
+			}
+		}
+
+		TestSwitchObject sw = new TestSwitchObject();
+		
+		sw.setDpidForTest(dpid);
+		switches.add(sw);
+		
+		return sw;
+	}
+	
+	/**
+	 * Create new empty TestPortObject.
+	 * @return New TestPortObject
+	 */
+	public TestPortObject createNewPortForTest() {
+		TestPortObject port = new TestPortObject();
+		ports.add(port);
+		return port;
+	}
+	
+	/**
+	 * Create new TestPortObject with specific DPID and port number.
+	 * @param dpid DPID to be set
+	 * @param number Port number to be set
+	 * @return New TestPortObject
+	 */
+	public TestPortObject createNewPortForTest(String dpid, Short number) {
+		TestSwitchObject sw = null;
+		
+		for(TestSwitchObject sw_loop : switches) {
+			if(sw_loop.getDPID().equals(dpid)) {
+				sw = sw_loop;
+			}
+		}
+		
+		if(sw != null) {
+			TestPortObject port = new TestPortObject();
+			port.setNumberForTest(number);
+			port.setSwitchForTest(sw);
+			sw.addPortForTest(port);
+			
+			ports.add(port);
+
+			return port;
+		} else {
+			return  null;
+		}
+	}
+	
+	/**
+	 * Link a TestPortObject to other TestPortObject.
+	 * @param src TestPortObjecgt of source port.
+	 * @param dst TestPortObjecgt of destination port.
+	 */
+	public void setLinkBetweenPortsForTest(TestPortObject src, TestPortObject dst) {
+		src.addLinkedPortForTest(dst);
+	}
+	
+	/**
+	 * Create new empty TestDeviceObject.
+	 * @return New TestDeviceObject
+	 */
+	public TestDeviceObject createNewDeviceForTest() {
+		TestDeviceObject dev = new TestDeviceObject();
+		
+		return dev;
+	}
+	
+	/**
+	 * Create new empty TestFlowPathObject.
+	 * @return New TestFlowPathObject
+	 */
+	public TestFlowPath createNewFlowPathForTest() {
+		TestFlowPath path = new TestFlowPath();
+		paths.add(path);
+		return path;
+	}
+
+	/**
+	 * Create new empty TestFlowEntryObject.
+	 * @return New TestFlowEntryObject
+	 */
+	public TestFlowEntry createNewFlowEntryForTest() {
+		TestFlowEntry entry = new TestFlowEntry();
+		entries.add(entry);
+		return entry;
+	}
+
+	
+	public boolean hasLinkBetween(String srcSw_str, Short srcNumber, String dstSw_str, Short dstNumber) {
+		IPortObject srcPort = null, dstPort = null;
+		long srcSw = HexString.toLong(srcSw_str);
+		long dstSw = HexString.toLong(dstSw_str);
+		
+		for(TestSwitchObject sw : switches) {
+			long swLong = HexString.toLong(sw.getDPID());
+			if(swLong == srcSw) {
+				for(IPortObject port : sw.getPorts()) {
+					if(port.getNumber().equals(srcNumber)) {
+						srcPort = port;
+					}
+				}
+			} else if(swLong == dstSw) {
+				for(IPortObject port : sw.getPorts()) {
+					if(port.getNumber().equals(dstNumber)) {
+						dstPort = port;
+					}
+				}
+			}
+		}
+		
+		if(srcPort != null && dstPort != null) {
+			for(IPortObject port : srcPort.getLinkedPorts()) {
+				if(port.equals(dstPort)) {
+					return true;
+				}
+			}
+		}
+		
+		return false;
+	}
+
+	// Overriding methods below are to mock GraphDBOperation class.
+	@Override
+	public ISwitchObject newSwitch(String dpid) {
+		TestSwitchObject sw = new TestSwitchObject();
+		sw.setDPID(dpid);
+		switchesToAdd.add(sw);
+		
+		return sw;
+	}
+
+	@Override
+	public ISwitchObject searchSwitch(String dpid_str) {
+		Long dpid = HexString.toLong(dpid_str);
+		
+		for(ISwitchObject sw : switches) {
+			if(HexString.toLong(sw.getDPID()) == dpid) {
+				return sw;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public ISwitchObject searchActiveSwitch(String dpid_str) {
+		Long dpid = HexString.toLong(dpid_str);
+
+		for(ISwitchObject sw : switches) {
+			if(HexString.toLong(sw.getDPID()) == dpid && sw.getState().equals("ACTIVE")) {
+				return sw;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public Iterable<ISwitchObject> getActiveSwitches() {
+		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
+		
+		for(ISwitchObject sw : switches) {
+			if(sw.getState() != null && sw.getState().equals("ACTIVE")) {
+				list.add(sw);
+			}
+		}
+		return list.isEmpty() ? null : list;
+	}
+
+	@Override
+	public Iterable<ISwitchObject> getAllSwitches() {
+		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
+		
+		for(ISwitchObject sw : switches) {
+			list.add(sw);
+		}
+		
+		return list.isEmpty() ? null : list;
+	}
+
+	@Override
+	public Iterable<ISwitchObject> getInactiveSwitches() {
+		List<ISwitchObject> list = new ArrayList<ISwitchObject>();
+		
+		for(ISwitchObject sw : switches) {
+			if(! sw.getState().equals("ACTIVE")) {
+				list.add(sw);
+			}
+		}
+		return list.isEmpty() ? null : list;
+	}
+
+	@Override
+	public Iterable<IFlowEntry> getAllSwitchNotUpdatedFlowEntries() {
+		List<IFlowEntry> list = new ArrayList<IFlowEntry>();
+		
+		for(TestFlowEntry entry : entries) {
+			if(entry.getSwitchState().equals("FE_SWITCH_NOT_UPDATED")) {
+				list.add(entry);
+			}
+		}
+		return list;
+	}
+
+	@Override
+	public void removeSwitch(ISwitchObject sw) {
+		if(switches.contains(sw)) {
+			switchesToRemove.add((TestSwitchObject)sw);
+		}
+	}
+
+	@Override
+	public IPortObject newPort(Short portNumber) {
+		TestPortObject port = new TestPortObject();
+		port.setNumber(portNumber);
+		
+		return port;
+	}
+
+	public IPortObject newPort(Long dpid, Short portNumber) {
+		TestPortObject port = null;
+		TestSwitchObject sw = (TestSwitchObject)searchSwitch(HexString.toHexString(dpid));
+		
+		if(sw != null) {
+			port = (TestPortObject)newPort(portNumber);
+			portsToAdd.add(port);
+			sw.addPort(port);
+		}
+		
+		return port;
+	}
+	
+	@Override
+	public IPortObject searchPort(String dpid_str, Short number) {
+		long dpid = HexString.toLong(dpid_str);
+		
+		for(TestSwitchObject sw : switches) {
+			if(HexString.toLong(sw.getDPID()) == dpid) {
+				for(IPortObject port : sw.getPorts()) {
+					if(port.getNumber().equals(number)) {
+						return port;
+					}
+				}
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public void removePort(IPortObject port) {
+		for(TestSwitchObject sw : switches) {
+			for(IPortObject pt : sw.getPorts()) {
+				if(pt.equals(port)) {
+					sw.removePort(port);
+				}
+			}
+		}
+		portsToRemove.add((TestPortObject)port);
+	}
+
+	@Override
+	public IDeviceObject newDevice() {
+		TestDeviceObject dev = new TestDeviceObject();
+		devicesToAdd.add(dev);
+		
+		return dev;
+	}
+
+	@Override
+	public IDeviceObject searchDevice(String macAddr) {
+		for(IDeviceObject dev : devices) {
+			if(dev.getMACAddress().equals(macAddr)) {
+				return dev;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public Iterable<IDeviceObject> getDevices() {
+		List<IDeviceObject> list = new ArrayList<IDeviceObject>();
+		
+		for(TestDeviceObject dev : devices) {
+			list.add(dev);
+		}
+		
+		return list;
+	}
+
+	@Override
+	public void removeDevice(IDeviceObject dev) {
+		if(devices.contains((TestDeviceObject)dev)) {
+			devicesToRemove.add((TestDeviceObject)dev);
+		}
+	}
+
+	@Override
+	public IFlowPath newFlowPath() {
+		TestFlowPath path = new TestFlowPath();
+		pathsToAdd.add(path);
+		
+		return path;
+	}
+
+	@Override
+	public IFlowPath searchFlowPath(FlowId flowId) {
+		for(IFlowPath path : paths) {
+			if(path.getFlowId().equals(flowId)) {
+				return path;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public IFlowPath getFlowPathByFlowEntry(IFlowEntry flowEntry) {
+		for(IFlowPath path : paths) {
+			for(IFlowEntry entry : path.getFlowEntries()) {
+				if(entry.equals(flowEntry)) {
+					return path;
+				}
+			}
+
+		}
+		return null;
+	}
+
+	@Override
+	public Iterable<IFlowPath> getAllFlowPaths() {
+		List<IFlowPath> list = new ArrayList<IFlowPath>();
+		
+		for(IFlowPath path : paths) {
+			list.add(path);
+		}
+		
+		return list;
+	}
+
+	@Override
+	public void removeFlowPath(IFlowPath flowPath) {
+		if(paths.contains((TestFlowPath)flowPath)) {
+			pathsToRemove.add((TestFlowPath)flowPath);
+		}
+	}
+
+	@Override
+	public IFlowEntry newFlowEntry() {
+		TestFlowEntry entry = new TestFlowEntry();
+		entriesToAdd.add(entry);
+		return entry;
+	}
+
+	@Override
+	public IFlowEntry searchFlowEntry(FlowEntryId flowEntryId) {
+		for(TestFlowEntry entry : entries) {
+			// TODO check if this matching works
+			if(entry.getFlowEntryId().equals(flowEntryId)) {
+				return entry;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public Iterable<IFlowEntry> getAllFlowEntries() {
+		List<IFlowEntry> list = new ArrayList<IFlowEntry>();
+		
+		for(TestFlowEntry entry : entries) {
+			list.add(entry);
+		}
+		
+		return list;
+	}
+
+	@Override
+	public void removeFlowEntry(IFlowEntry flowEntry) {
+		if(entries.contains((TestFlowEntry)flowEntry)) {
+			entriesToRemove.add((TestFlowEntry)flowEntry);
+		}
+	}
+
+	@Override
+	public IDBConnection getDBConnection() {
+		return super.getDBConnection();
+	}
+
+	@Override
+	public void commit() {
+		for(TestSwitchObject sw : switchesToAdd) {
+			switches.add(sw);
+		}
+		for(TestSwitchObject sw : switchesToRemove) {
+			sw.commit();
+			switches.remove(sw);
+		}
+		for(TestSwitchObject sw : switches) {
+			sw.commit();
+		}
+		
+		for(TestPortObject port : portsToAdd) {
+			ports.add(port);
+		}
+		for(TestPortObject port : portsToRemove) {
+			port.commit();
+			ports.remove(port);
+		}
+		for(TestPortObject port : ports) {
+			port.commit();
+		}
+		
+		for(TestDeviceObject dev : devicesToAdd) {
+			devices.add(dev);
+		}
+		for(TestDeviceObject dev : devicesToRemove) {
+			dev.commit();
+			devices.remove(dev);
+		}
+		for(TestDeviceObject dev : devices) {
+			dev.commit();
+		}
+		
+		clearUncommitedData();
+	}
+
+	@Override
+	public void rollback() {
+		clearUncommitedData();
+	}
+
+	@Override
+	public void close() {
+		// TODO Auto-generated method stub
+
+	}
+}
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/TestableLinkStorageImpl.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableLinkStorageImpl.java
similarity index 87%
rename from src/test/java/net/floodlightcontroller/linkdiscovery/internal/TestableLinkStorageImpl.java
rename to src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableLinkStorageImpl.java
index 223b8a1..2f90d48 100644
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/TestableLinkStorageImpl.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableLinkStorageImpl.java
@@ -1,7 +1,9 @@
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.core.internal;
 
 import java.util.Set;
 
+import net.onrc.onos.ofcontroller.core.internal.LinkStorageImpl;
+
 import com.thinkaurelius.titan.core.TitanGraph;
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
 import com.tinkerpop.blueprints.Vertex;
@@ -17,6 +19,7 @@
  */
 
 public class TestableLinkStorageImpl extends LinkStorageImpl {
+	protected TitanGraph graph;
 
 	public TestableLinkStorageImpl(TitanGraph graph){
 		this.graph = graph;
diff --git a/src/test/java/net/floodlightcontroller/core/internal/TestableSwitchStorageImpl.java b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableSwitchStorageImpl.java
similarity index 84%
rename from src/test/java/net/floodlightcontroller/core/internal/TestableSwitchStorageImpl.java
rename to src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableSwitchStorageImpl.java
index 73d517f..e78a1b6 100644
--- a/src/test/java/net/floodlightcontroller/core/internal/TestableSwitchStorageImpl.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/core/internal/TestableSwitchStorageImpl.java
@@ -1,7 +1,9 @@
-package net.floodlightcontroller.core.internal;
+package net.onrc.onos.ofcontroller.core.internal;
 
 import java.util.Set;
 
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+
 import com.thinkaurelius.titan.core.TitanGraph;
 import com.tinkerpop.blueprints.Vertex;
 import com.tinkerpop.blueprints.TransactionalGraph.Conclusion;
diff --git a/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTest.java b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTest.java
new file mode 100644
index 0000000..de8be4e
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTest.java
@@ -0,0 +1,837 @@
+package net.onrc.onos.ofcontroller.devicemanager.internal;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.floodlightcontroller.devicemanager.IDevice;
+import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.packet.IPv4;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+import net.floodlightcontroller.devicemanager.internal.Device;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.util.HexString;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.thinkaurelius.titan.core.TitanFactory;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, DeviceStorageImpl.class})
+public class DeviceStorageImplTest{ //extends FloodlightTestCase{
+	
+	protected static Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+	
+	String conf;
+	DeviceStorageImpl deviceImpl;
+    private GraphDBConnection mockConn;
+    private GraphDBOperation mockOpe;
+    
+	@Before
+	public void setUp() throws Exception {
+	    deviceImpl = new DeviceStorageImpl();	
+		conf = "/dummy/path/to/db";
+				
+		PowerMock.mockStatic(GraphDBConnection.class);
+		mockConn = createMock(GraphDBConnection.class);
+		PowerMock.suppress(PowerMock.constructor(GraphDBConnection.class));
+		EasyMock.expect(GraphDBConnection.getInstance((String)EasyMock.anyObject())).andReturn(mockConn);
+		PowerMock.replay(GraphDBConnection.class);
+			
+		//PowerMock.mockStatic(GraphDBOperation.class);
+		mockOpe = PowerMock.createMock(GraphDBOperation.class);
+		PowerMock.expectNew(GraphDBOperation.class, new Class<?>[]{String.class}, conf).andReturn(mockOpe);
+		mockOpe.close();
+		PowerMock.replay(GraphDBOperation.class);
+        // Replace the conf to dummy conf
+		// String conf = "/tmp/cassandra.titan";
+
+		
+
+	}
+
+	@After
+	public void tearDown() throws Exception {	
+		deviceImpl.close();
+		deviceImpl = null;
+		
+		verify(mockOpe);
+	}
+	
+	private String makeIPStringFromArray(Integer[] ipaddresses){
+        String multiIntString = "";
+        for(Integer intValue : ipaddresses)
+        {
+        	if (multiIntString == null || multiIntString.isEmpty()){
+        		multiIntString = "[" + IPv4.fromIPv4Address(intValue);
+        	}
+        	else{
+           		multiIntString += "," + IPv4.fromIPv4Address(intValue);
+        	}
+        }
+        return multiIntString + "]";
+	}
+	
+
+	/**
+	 * Desc:
+	 *  Test method for addDevice method.
+	 * Codition:
+	 *  N/A
+	 * Expect:
+	 * 	Get proper IDeviceObject
+	 */
+	//@Ignore
+	@Test
+	public void testAddNewDevice() {
+		try 
+		{	   
+			//Make mockDevice
+			IDevice mockDev = createMock(Device.class);
+			// Mac addr for test device.
+			String macAddr = "99:99:99:99:99:99";
+			// IP addr for test device
+			String ip = "192.168.100.1";
+			Integer[] ipaddrs = {IPv4.toIPv4Address(ip)};
+			// Mac addr for attached switch
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			// Port number for attached switch
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+		
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs).anyTimes();
+			expect(mockDev.getAttachmentPoints()).andReturn(sps).anyTimes();
+			replay(mockDev);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList);
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+			//Add the device
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+			verify(mockIDev);
+			
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+	
+	/**
+	 * Desc:
+	 * 	Test method for addDevice method.
+	 * Condition:
+	 * 	Already added device is existed.
+	 * Expect:
+	 * 	Get proper IDeviceObject still.
+	 *  Check the IDeviceObject properties set expectedly. 
+	 */
+	//@Ignore
+	@Test
+	public void testAddDeviceExisting() {
+		try 
+		{	   
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer[] ipaddrs = {IPv4.toIPv4Address(ip)};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+		
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs).times(2);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps).times(2);
+			replay(mockDev);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList).anyTimes();
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+			//Add the device
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+			//Add the same device
+	        IDeviceObject obj2 = deviceImpl.addDevice(mockDev);
+			assertNotNull(obj2);
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+	
+	/**
+	 * Desc:
+	 * 	Test method for updateDevice method.
+	 * Condition:
+	 * 	The mac address and attachment point are the same. 
+	 *  All of the other parameter are different.
+	 * Expect:
+	 * 	Changed parameters are set expectedly.
+	 */
+	//@Ignore
+	@Test
+	public void testUpdateDevice() {
+		try
+		{
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev);
+			
+			//Dev2 (attached port is the same)
+			IDevice mockDev2 = createMock(Device.class);
+			String ip2 = "192.168.100.2";
+			Integer ipInt2 = IPv4.toIPv4Address(ip2);
+			Integer[] ipaddrs2 = {ipInt2};
+			
+			expect(mockDev2.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs2);
+			expect(mockDev2.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev2);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList).anyTimes();
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs2));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+			//update theDevice
+			IDeviceObject obj2 = deviceImpl.updateDevice(mockDev2);
+			assertNotNull(obj2);
+			
+			verify(mockIDev);
+			
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testRemoveDevice method.
+	 * Condition:
+	 * 	1. Unregistered IDeviceObject argument is put. 
+	 * Expect:
+	 *  1. Nothing happen when unregistered IDeviceObject is put
+	 * 	2. IDeviceObject will be removed.
+	 */
+	//@Ignore
+	@Test
+	public void testRemoveDevice() {
+		try
+		{
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			replay(mockDev);
+			
+			//Dev2 (attached port is the same)
+			IDevice mockDev2 = createMock(Device.class);
+			String macAddr2 = "33:33:33:33:33:33";
+			expect(mockDev2.getMACAddressString()).andReturn(macAddr2).anyTimes();
+			expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev2.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev2);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList);
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr2)).andReturn(null);
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			mockOpe.removeDevice(mockIDev);	
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			deviceImpl.removeDevice(mockDev2);
+		    IDeviceObject dev = deviceImpl.getDeviceByMac(macAddr);
+		    assertNotNull(dev);
+			
+			deviceImpl.removeDevice(mockDev);		
+		    IDeviceObject dev2 = deviceImpl.getDeviceByMac(macAddr);
+		    assertNull(dev2);
+		    
+			verify(mockIDev);
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for getDeviceByMac
+	 * Condition:
+	 * 	1. Unregistered mac address argument is set
+	 * Expect:
+	 * 	1.Nothing happen when you put unregistered mac address
+	 *  2.Get the proper IDeviceObject.
+	 *  3.Check the IDeviceObject properties set expectedly.
+	 */
+	//@Ignore
+	@Test
+	public void testGetDeviceByMac() {
+		try
+		{
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			String dummyMac = "33:33:33:33:33:33";
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList);
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(dummyMac)).andReturn(null);
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+		    IDeviceObject dummyDev = deviceImpl.getDeviceByMac(dummyMac);
+		    assertNull(dummyDev);	
+			
+		    IDeviceObject dev = deviceImpl.getDeviceByMac(macAddr);
+		    assertNotNull(dev);
+		    
+			verify(mockIDev);
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for getDeviceByIP method.
+	 * Condition:
+	 * 	1. Unregistered ip address argument is set
+	 * Expect:
+	 * 	1. Nothing happen when you put unregistered mac address
+	 * 	2. Get the proper IDeviceObject.
+	 *  3. Check the IDeviceObject properties set expectedly.
+	 */
+	//@Ignore
+	@Test
+	public void testGetDeviceByIP() {
+		try
+		{
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			String ip2 = "192.168.100.2";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer ipInt2 = IPv4.toIPv4Address(ip2);
+			Integer[] ipaddrs = {ipInt, ipInt2};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			String dummyIP = "222.222.222.222";
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList);
+			expect(mockIDev.getIPAddress()).andReturn(makeIPStringFromArray(ipaddrs)).times(2);
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			
+			//Make mock Iterator for IDeviceObject
+			List<IDeviceObject> deviceList = new ArrayList<IDeviceObject>();
+			deviceList.add(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.getDevices()).andReturn(deviceList).times(2);
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+	
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+		    IDeviceObject dummyDev = deviceImpl.getDeviceByIP(dummyIP);
+		    assertNull(dummyDev);
+			
+		    IDeviceObject dev = deviceImpl.getDeviceByIP(ip);
+		    assertNotNull(dev);
+		    
+			verify(mockIDev);
+
+			
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testChangeDeviceAttachmentsIDevice
+	 * Condition:
+	 * 	1. Unexisting attachment point argument is set
+	 * Expect:
+	 * 	1. Nothing happen when you put unexisting attachment point.
+	 * 	2. Set the attachment point expectedly;
+	 */
+	//@Ignore
+	@Test
+	public void testChangeDeviceAttachmentsIDevice() {
+		try
+		{
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev);
+			
+			//Dev2
+			IDevice mockDev2 = createMock(Device.class);
+			String switchMacAddr2 = "00:00:00:00:00:00:0a:02";
+			long lSwitchMacAddr2 = HexString.toLong(switchMacAddr2);
+			short portNum2 = 2; 
+			SwitchPort sp2 = new SwitchPort(lSwitchMacAddr2, portNum2);
+			SwitchPort sps2[] = {sp2};
+			
+			expect(mockDev2.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev2.getAttachmentPoints()).andReturn(sps2);
+			replay(mockDev2);
+			
+			//Dev3
+			IDevice mockDev3 = createMock(Device.class);
+			String switchMacAddr3 = "00:00:00:00:00:00:00:00";
+			long lSwitchMacAddr3 = HexString.toLong(switchMacAddr3);
+			short portNum3 = 1; 
+			SwitchPort sp3 = new SwitchPort(lSwitchMacAddr3, portNum3);
+			SwitchPort sps3[] = {sp3};
+			
+			expect(mockDev3.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev3.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev3.getAttachmentPoints()).andReturn(sps3);
+			replay(mockDev3);
+			
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			mockIPort.removeDevice(mockIDev);
+			mockIPort.removeDevice(mockIDev);
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			expect(mockIDev.getAttachedPorts()).andReturn(portList).anyTimes();
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			replay(mockIDev);	
+			
+			//Mock IPortObject 2 with dpid "00:00:00:00:00:00:0a:02" and port "2"
+			IPortObject mockIPort2 = createMock(IPortObject.class);
+			mockIPort2.setNumber(portNum2);
+			mockIPort2.setType("port");
+			String iPortDesc2 = "port 2 at LAX Switch";
+			expect(mockIPort2.getNumber()).andReturn(portNum2).anyTimes();
+			expect(mockIPort2.getDesc()).andReturn(iPortDesc2).anyTimes();
+			mockIPort2.setDevice(mockIDev);
+			replay(mockIPort2);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList2 = new ArrayList<IPortObject>();
+			portList2.add(mockIPort2);
+			
+			//Mock IPortObject 3 with dpid "00:00:00:00:00:00:00:00" and port "1"
+			IPortObject mockIPort3 = createMock(IPortObject.class);
+			mockIPort3.setNumber(portNum3);
+			mockIPort3.setType("port");
+			String iPortDesc3 = "n/a";
+			expect(mockIPort3.getNumber()).andReturn(portNum3).anyTimes();
+			expect(mockIPort3.getDesc()).andReturn(iPortDesc3).anyTimes();
+			mockIPort3.setDevice(mockIDev);
+			replay(mockIPort3);
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr2, portNum2)).andReturn(mockIPort2);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr3, portNum3)).andReturn(null);
+			mockOpe.commit();
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+	
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+			
+		    deviceImpl.changeDeviceAttachments(mockDev2);
+			
+		    deviceImpl.changeDeviceAttachments(mockDev3);
+		    
+			verify(mockIDev);
+
+			
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	@Ignore
+	@Test
+	public void testChangeDeviceAttachmentsIDeviceIDeviceObject() {
+		//It is tested by the testChangeDeviceAttachmentsIDevice
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testChangeDeviceIPv4Address
+	 * Condition:
+	 * 	N/A
+	 * Expect:
+	 *  1. Set the ipadress expectedly.
+	 */
+	//@Ignore
+	@Test
+	public void testChangeDeviceIPv4Address() {
+		try
+		{
+			//Dev1
+			IDevice mockDev = createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+			
+			expect(mockDev.getMACAddressString()).andReturn(macAddr).anyTimes();
+			expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			replay(mockDev);
+			
+			//Dev2
+			IDevice mockDev2 = createMock(Device.class);
+			String ip2 = "192.168.100.2";
+			Integer ipInt2 = IPv4.toIPv4Address(ip2);
+			Integer[] ipaddrs2 = {ipInt2};
+			expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs2);
+			replay(mockDev2);
+			
+			//Mock IPortObject 1 with dpid "00:00:00:00:00:00:0a:01" and port "1"
+			IPortObject mockIPort = createMock(IPortObject.class);
+			mockIPort.setNumber(portNum);
+			mockIPort.setType("port");
+			String iPortDesc = "port 1 at SEA Switch";
+			expect(mockIPort.getNumber()).andReturn(portNum).anyTimes();
+			expect(mockIPort.getDesc()).andReturn(iPortDesc).anyTimes();
+			replay(mockIPort);
+			
+			//Make Iterator for mockIport
+			List<IPortObject> portList = new ArrayList<IPortObject>();
+			portList.add(mockIPort);
+			
+			//Expectation for mockIDeviceObject
+			IDeviceObject mockIDev = createMock(IDeviceObject.class);	
+			expect(mockIDev.getAttachedPorts()).andReturn(portList);
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs));
+			mockIDev.setMACAddress(macAddr);
+			mockIDev.setType("device");
+			mockIDev.setState("ACTIVE");
+			mockIDev.setIPAddress(makeIPStringFromArray(ipaddrs2));
+			replay(mockIDev);	
+			
+			//Expectation for mockOpe
+			expect(mockOpe.searchDevice(macAddr)).andReturn(null);
+			expect(mockOpe.newDevice()).andReturn(mockIDev);
+			expect(mockOpe.searchPort(switchMacAddr, portNum)).andReturn(mockIPort);
+			mockOpe.commit();
+			expect(mockOpe.searchDevice(macAddr)).andReturn(mockIDev);
+			mockOpe.commit();
+			replay(mockOpe);				
+			
+			deviceImpl.init(conf);
+			
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+	        deviceImpl.changeDeviceIPv4Address(mockDev2);	
+	        
+			verify(mockIDev);
+
+					
+		} 
+		catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java
new file mode 100644
index 0000000..e4053f4
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/devicemanager/internal/DeviceStorageImplTestBB.java
@@ -0,0 +1,626 @@
+package net.onrc.onos.ofcontroller.devicemanager.internal;
+
+import static org.junit.Assert.*;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.floodlightcontroller.core.internal.TestDatabaseManager;
+import net.floodlightcontroller.devicemanager.IDevice;
+import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.devicemanager.internal.Device;
+import net.floodlightcontroller.packet.IPv4;
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.IDeviceStorage;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IDeviceObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IPortObject;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.ISwitchObject;
+import net.onrc.onos.ofcontroller.core.internal.DeviceStorageImpl;
+import net.onrc.onos.ofcontroller.core.internal.SwitchStorageImpl;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.util.HexString;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.slf4j.LoggerFactory;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.thinkaurelius.titan.core.TitanGraph;
+
+//Add Powermock preparation
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, SwitchStorageImpl.class})
+public class DeviceStorageImplTestBB {
+	protected static org.slf4j.Logger log = LoggerFactory.getLogger(SwitchStorageImpl.class);
+
+	String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation ope = null;
+    private TitanGraph titanGraph = null;
+    IDeviceStorage deviceImpl = null;
+    
+	@Before
+	public void setUp() throws Exception {
+		
+		deviceImpl = new DeviceStorageImpl();
+		conf = "/dummy/path/to/db";
+		
+		// Make mock cassandra DB
+		// Replace TitanFactory.open() to return mock DB
+		titanGraph = TestDatabaseManager.getTestDatabase();
+		TestDatabaseManager.populateTestData(titanGraph);
+		PowerMock.mockStatic(TitanFactory.class);
+		EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+		PowerMock.replay(TitanFactory.class);
+		
+		conn = GraphDBConnection.getInstance(conf);
+		ope = new GraphDBOperation(conn);
+		
+		deviceImpl.init(conf);
+	}
+
+	@After
+	public void tearDown() throws Exception {
+		titanGraph.shutdown();
+		TestDatabaseManager.deleteTestDatabase();
+
+		deviceImpl.close();
+		deviceImpl = null;
+	}
+
+	/**
+	 * Desc:
+	 *  Test method for addDevice method.
+	 * Codition:
+	 *  N/A
+	 * Expect:
+	 * 	Get proper IDeviceObject
+	 *  Check the IDeviceObject properties set
+	 */
+	@Test
+	public void testAddDevice() {
+		try 
+		{	   
+			//Make mockDevice
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			// Mac addr for test device.
+			String macAddr = "99:99:99:99:99:99";
+			// IP addr for test device
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			// Mac addr for attached switch
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			// Port number for attached switch
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+
+			EasyMock.replay(mockDev);
+
+			//Add the device
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			//Test to take a Device from DB correctly
+			IDeviceObject devObj1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, devObj1.getMACAddress());
+
+			//Test to take a attached sw  from DB correctly
+			for(ISwitchObject sw1: devObj1.getSwitch())
+			{
+				String swMacFromDB = sw1.getDPID();
+				assertEquals(switchMacAddr, swMacFromDB);
+			}
+
+			//Test to take a IP addr from DB
+			//TodoForGettingIPaddr. There may be bug in the test class.
+			String ipFromDB = devObj1.getIPAddress();
+			String[] ipsFromDB = ipFromDB.replace("[", "").replace("]", "").split(",");
+			List<String> ipsList = Arrays.asList(ipsFromDB);
+			assertTrue(ipsList.contains(ip));
+
+			//Test to take a attached port from DB
+			for(IPortObject port : devObj1.getAttachedPorts())
+			{
+
+				//In this implementing, the object was not set the port. So it must be null.
+				if(port.getNumber() != null)
+				{
+					String portNumFromDB = port.getNumber().toString();
+					assertEquals(String.valueOf(portNum), portNumFromDB);				
+				}
+			}	
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+	
+	/**
+	 * Desc:
+	 * 	Test method for addDevice method.
+	 * Condition:
+	 * 	Already added device is existed.
+	 * Expect:
+	 * 	Get proper IDeviceObject still.
+	 *  Check the IDeviceObject properties set.
+	 */
+	@Test
+	public void testAddDeviceExisting() {
+		try 
+		{	   
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+			//Add the device
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			//Test to take a Device from DB correctly
+			IDeviceObject devObj1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, devObj1.getMACAddress());
+
+			//Add the same device
+	        IDeviceObject obj2 = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj2);
+
+			IDeviceObject devObj2 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, devObj2.getMACAddress());	
+
+			//Test to take a attached port from DB
+			for(IPortObject port : devObj2.getAttachedPorts())
+			{
+				//In this implementing, the object was not set the port. So it must be null.
+				if(port.getNumber() != null)
+				{
+
+					String portNumFromDB = port.getNumber().toString();
+					assertEquals(String.valueOf(portNum), portNumFromDB);						
+
+					ISwitchObject sw = port.getSwitch();
+					String str = sw.getDPID();
+					log.debug("");
+				}
+			}	
+
+			String ipFromDB = devObj2.getIPAddress();
+			String[] ipsFromDB = ipFromDB.replace("[", "").replace("]", "").split(",");
+			List<String> ipsList = Arrays.asList(ipsFromDB);
+			assertTrue(ipsList.contains(ip));
+
+			//Test to take a attached port from DB
+			for(IPortObject port : devObj2.getAttachedPorts())
+			{
+
+				//In this implementing, the object was not set the port. So it must be null.
+				if(port.getNumber() != null)
+				{
+					String portNumFromDB = port.getNumber().toString();
+					assertEquals(String.valueOf(portNum), portNumFromDB);				
+				}
+			}	
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+	/**
+	 * Desc:
+	 * 	Test method for updateDevice method.
+	 * Condition:
+	 * 	The mac address and attachment point are the same. 
+	 *  All of the other parameter are different.
+	 * Expect:
+	 * 	Changed parameters are set properly.
+	 */
+	//@Ignore
+	@Test
+	public void testUpdateDevice() {
+		try
+		{
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+			//Dev2 (attached port is the same)
+			IDevice mockDev2 = EasyMock.createMock(Device.class);
+			String macAddr2 = "99:aa:aa:aa:aa:aa";
+			Integer ip2 = IPv4.toIPv4Address("192.168.100.2");
+			Integer[] ipaddrs2 = {ip2};
+
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs2);
+			EasyMock.expect(mockDev2.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr2);
+			EasyMock.replay(mockDev2);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			IDeviceObject dev1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev1.getMACAddress());
+
+			//update theDevice
+			deviceImpl.updateDevice(mockDev2);
+			IDeviceObject dev2 = ope.searchDevice(macAddr2);
+			assertEquals(macAddr2, dev2.getMACAddress());
+			IPortObject iport = ope.searchPort(switchMacAddr, portNum);
+
+			//Test to take a attached port from DB
+			for(IDeviceObject dev : iport.getDevices())
+			{
+				String macAddrFromDB = dev.getMACAddress();	
+				if(macAddr2.equals(macAddrFromDB)){
+					//Nothing to do
+				}
+				else{
+					fail("notFoundTheDeviceOnThePort");			
+				}
+			}
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testRemoveDevice method.
+	 * Condition:
+	 * 	1. Unregistered IDeviceObject argument is put. 
+	 * Expect:
+	 *  1. Nothing happen when unregistered IDeviceObject is put
+	 * 	2. IDeviceObject will be removed.
+	 */
+	//@Ignore
+	@Test
+	public void testRemoveDevice() {
+		try
+		{
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			IDeviceObject dev1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev1.getMACAddress());
+
+			deviceImpl.removeDevice(mockDev);		
+		    IDeviceObject dev = deviceImpl.getDeviceByMac(macAddr);
+		    assertNull(dev);
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for getDeviceByMac
+	 * Condition:
+	 * 	1. Unregistered mac address argument is set
+	 * Expect:
+	 * 	1.Nothing happen when you put unregistered mac address
+	 *  2.Get the proper IDeviceObject.
+	 *  3.Check the IDeviceObject properties set.
+	 */
+	//@Ignore
+	@Test
+	public void testGetDeviceByMac() {
+		try
+		{
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			IDeviceObject dev1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev1.getMACAddress());
+
+		    IDeviceObject dev = deviceImpl.getDeviceByMac(macAddr);
+		    assertNotNull(dev);
+			assertEquals(macAddr, dev.getMACAddress());
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for getDeviceByIP method.
+	 * Condition:
+	 * 	1. Unregistered ip address argument is set
+	 * Expect:
+	 * 	1. Nothing happen when you put unregistered mac address
+	 * 	2. Get the proper IDeviceObject.
+	 *  3. Check the IDeviceObject properties set.
+	 */
+	//@Ignore
+	@Test
+	public void testGetDeviceByIP() {
+		try
+		{
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			IDeviceObject dev1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev1.getMACAddress());
+
+		    IDeviceObject dev = deviceImpl.getDeviceByIP(ip);
+		    assertNotNull(dev);
+			String ipFromDB = dev.getIPAddress();
+			String[] ipsFromDB = ipFromDB.replace("[", "").replace("]", "").split(",");
+			List<String> ipsList = Arrays.asList(ipsFromDB);
+			assertTrue(ipsList.contains(ip));
+
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testChangeDeviceAttachmentsIDevice
+	 * Condition:
+	 * 	1. Unexisting attachment point argument is set
+	 * Expect:
+	 * 	1. Unexisting attachment point is ignored, so nothing happen.
+	 * 	2. Change the attachment point.
+	 */
+	//@Ignore
+	@Test
+	public void testChangeDeviceAttachmentsIDevice() {
+		try
+		{
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+			//Dev2
+			IDevice mockDev2 = EasyMock.createMock(Device.class);
+			String switchMacAddr2 = "00:00:00:00:00:00:0a:02";
+			long lSwitchMacAddr2 = HexString.toLong(switchMacAddr2);
+			short portNum2 = 2; 
+			SwitchPort sp2 = new SwitchPort(lSwitchMacAddr2, portNum2);
+			SwitchPort sps2[] = {sp2};
+
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev2.getAttachmentPoints()).andReturn(sps2);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev2);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+		    deviceImpl.changeDeviceAttachments(mockDev2);
+
+		    IDeviceObject dev = deviceImpl.getDeviceByMac(macAddr);
+		    assertNotNull(dev);
+
+			for(ISwitchObject sw1: dev.getSwitch())
+			{
+				String swMacFromDB = sw1.getDPID();
+				assertEquals(switchMacAddr2, swMacFromDB);
+			}
+		} catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+	//@Ignore
+	@Test
+	public void testChangeDeviceAttachmentsIDeviceIDeviceObject() {
+		//It is tested by the testChangeDeviceAttachmentsIDevice
+	}
+
+	/**
+	 * Desc:
+	 * 	Test method for testChangeDeviceIPv4Address
+	 * Condition:
+	 * 	N/A
+	 * Expect:
+	 *  1. Check correctly changed the ipadress
+	 */
+	//@Ignore
+	@Test
+	public void testChangeDeviceIPv4Address() {
+		try
+		{
+			//Dev1
+			IDevice mockDev = EasyMock.createMock(Device.class);
+			String macAddr = "99:99:99:99:99:99";
+			String ip = "192.168.100.1";
+			Integer ipInt = IPv4.toIPv4Address(ip);
+			Integer[] ipaddrs = {ipInt};
+			String switchMacAddr = "00:00:00:00:00:00:0a:01";		
+			long switchMacAddrL = HexString.toLong(switchMacAddr);
+			short portNum = 2; 
+			SwitchPort sp1 = new SwitchPort(switchMacAddrL, portNum);
+			SwitchPort[] sps = {sp1};
+
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getIPv4Addresses()).andReturn(ipaddrs);
+			EasyMock.expect(mockDev.getAttachmentPoints()).andReturn(sps);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev.getMACAddressString()).andReturn(macAddr);
+			EasyMock.replay(mockDev);
+
+	        IDeviceObject obj = deviceImpl.addDevice(mockDev);	
+			assertNotNull(obj);
+
+			IDevice mockDev2 = EasyMock.createMock(Device.class);
+			String ip2 = "192.168.100.2";
+			Integer ipInt2 = IPv4.toIPv4Address(ip2);
+			Integer[] ipaddrs2 = {ipInt2};
+			EasyMock.expect(mockDev2.getMACAddressString()).andReturn(macAddr);
+			EasyMock.expect(mockDev2.getIPv4Addresses()).andReturn(ipaddrs2);
+			EasyMock.replay(mockDev2);
+
+			IDeviceObject dev1 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev1.getMACAddress());
+			String ipFromDB = dev1.getIPAddress();
+			String[] ipsFromDB = ipFromDB.replace("[", "").replace("]", "").split(",");
+			List<String> ipsList = Arrays.asList(ipsFromDB);
+			assertTrue(ipsList.contains(ip));
+
+	        deviceImpl.changeDeviceIPv4Address(mockDev2);	
+
+			IDeviceObject dev2 = ope.searchDevice(macAddr);
+			assertEquals(macAddr, dev2.getMACAddress());
+			String ipFromDB2 = dev2.getIPAddress();
+			String[] ipsFromDB2 = ipFromDB2.replace("[", "").replace("]", "").split(",");
+			List<String> ipsList2 = Arrays.asList(ipsFromDB2);
+			assertTrue(ipsList2.contains(ip2));
+		} 
+		catch(Exception e) {
+			fail(e.getMessage());
+		}
+	}
+
+}
diff --git a/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
new file mode 100644
index 0000000..7bc0aac
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/flowmanager/FlowManagerTest.java
@@ -0,0 +1,1224 @@
+package net.onrc.onos.ofcontroller.flowmanager;
+
+import static org.junit.Assert.*;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.cmpEq;
+import static org.powermock.api.easymock.PowerMock.*;
+
+import java.util.*;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IOFSwitch;
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.core.module.IFloodlightService;
+import net.floodlightcontroller.restserver.IRestApiService;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowEntry;
+import net.onrc.onos.ofcontroller.core.INetMapTopologyObjects.IFlowPath;
+import net.onrc.onos.ofcontroller.flowmanager.web.FlowWebRoutable;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.ofcontroller.util.*;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.protocol.OFFlowMod;
+import org.openflow.protocol.OFType;
+import org.openflow.protocol.factory.BasicFactory;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * @author Toshio Koide
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FlowManager.class, GraphDBOperation.class, System.class, Executors.class})
+public class FlowManagerTest {
+	private static FloodlightModuleContext context;
+	private static IFloodlightProviderService floodlightProvider;
+	private static TopoRouteService topoRouteService;
+	private static IRestApiService restApi;
+	private static GraphDBOperation op;
+	
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@Before
+	public void setUp() throws Exception {
+	}
+
+	/**
+	 * @throws java.lang.Exception
+	 */
+	@After
+	public void tearDown() throws Exception {
+	}
+	
+	/**
+	 * @throws java.lang.Exception
+	 */
+	private void expectInitWithContext() throws Exception {
+		// create mock objects
+		context = createMock(FloodlightModuleContext.class);
+		floodlightProvider = createMock(IFloodlightProviderService.class);
+		topoRouteService = createMock(TopoRouteService.class);
+		restApi = createMock(IRestApiService.class);
+		op = createMock(GraphDBOperation.class);
+
+		// setup expectations
+		expect(context.getServiceImpl(IFloodlightProviderService.class)).andReturn(floodlightProvider);
+		expect(context.getServiceImpl(IRestApiService.class)).andReturn(restApi);
+		expectNew(GraphDBOperation.class, new Class<?>[] {String.class}, EasyMock.isA(String.class)).andReturn(op);
+		expectNew(TopoRouteService.class, new Class<?>[] {String.class}, EasyMock.isA(String.class)).andReturn(topoRouteService);
+	}
+	
+	private IFlowPath createIFlowPathMock(long flowId, String installerID,
+			long flowPathFlags,
+			long srcDpid, int srcPort, long dstDpid, int dstPort) {
+		IFlowPath iFlowPath = createNiceMock(IFlowPath.class);
+		expect(iFlowPath.getFlowId()).andReturn(new FlowId(flowId).toString()).anyTimes();
+		expect(iFlowPath.getInstallerId()).andReturn(installerID).anyTimes();
+		expect(iFlowPath.getFlowPathFlags()).andReturn(new Long(flowPathFlags)).anyTimes();
+		expect(iFlowPath.getSrcSwitch()).andReturn(new Dpid(srcDpid).toString()).anyTimes();
+		expect(iFlowPath.getSrcPort()).andReturn(new Short((short)srcPort)).anyTimes();
+		expect(iFlowPath.getDstSwitch()).andReturn(new Dpid(dstDpid).toString()).anyTimes();
+		expect(iFlowPath.getDstPort()).andReturn(new Short((short)dstPort)).anyTimes();
+		return iFlowPath;
+	}
+	
+	private FlowPath createTestFlowPath(long flowId, String installerId,
+			final long flowPathFlags,
+			final long srcDpid, final int srcPort,
+			final long dstDpid, final int dstPort			
+			) {
+		FlowPath flowPath = new FlowPath();
+		flowPath.setFlowId(new FlowId(flowId));
+		flowPath.setInstallerId(new CallerId(installerId));
+		flowPath.setFlowPathFlags(new FlowPathFlags(flowPathFlags));
+		flowPath.setDataPath(new DataPath() {{
+			setSrcPort(new SwitchPort(new Dpid(srcDpid), new Port((short)srcPort)));
+			setDstPort(new SwitchPort(new Dpid(dstDpid), new Port((short)dstPort)));
+		}});
+		flowPath.setFlowEntryMatch(new FlowEntryMatch());
+		return flowPath;
+	}
+	
+	private ArrayList<FlowPath> createTestFlowPaths() {
+		FlowPath flowPath1 = createTestFlowPath(1, "foo caller id", 0, 1, 1, 2, 2); 
+		FlowPath flowPath2 = createTestFlowPath(2, "caller id", 0, 1, 1, 2, 2); 
+		FlowPath flowPath3 = createTestFlowPath(3, "caller id", 0, 1, 5, 2, 2); 
+
+		ArrayList<FlowPath> flowPaths = new ArrayList<FlowPath>();
+		flowPaths.add(flowPath1);
+		flowPaths.add(flowPath2);
+		flowPaths.add(flowPath3);
+		
+		return flowPaths;
+	}
+	
+
+	// IFlowService methods
+
+
+	/**
+	 * Test method for {@link FlowManager#addFlow(FlowPath, FlowId, String)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testAddFlowFailGraphCreatesNoFlow() throws Exception {
+		// instantiate required objects
+		FlowId flowId = new FlowId(123);
+		FlowPath flowPath = new FlowPath();
+		flowPath.setFlowId(flowId);
+		FlowManager fm = new FlowManager();
+		
+		// setup expectations
+		expectInitWithContext();
+		expect(op.searchFlowPath(flowId)).andReturn(null);
+		expect(op.newFlowPath()).andReturn(null);
+		op.rollback();
+
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		Boolean result = fm.addFlow(flowPath, flowId, "");
+
+		// verify the test
+		verifyAll();
+		assertFalse(result);
+	}
+
+	/**
+	 * Test method for {@link FlowManager#addFlow(FlowPath, FlowId, String)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testAddFlowSuccessNormally() throws Exception {
+		final String addFlowEntry = "addFlowEntry";
+		// create mock objects
+		IFlowPath createdFlowPath = createNiceMock(IFlowPath.class);
+		IFlowEntry createdFlowEntry1 = createNiceMock(IFlowEntry.class);
+		IFlowEntry createdFlowEntry2 = createNiceMock(IFlowEntry.class);
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlowEntry);
+
+		// instantiate required objects
+		final FlowEntry flowEntry1 = new FlowEntry();
+		final FlowEntry flowEntry2 = new FlowEntry();
+		ArrayList<FlowEntry> flowEntries = new ArrayList<FlowEntry>();
+		flowEntries.add(flowEntry1);
+		flowEntries.add(flowEntry2);
+		
+		DataPath dataPath = new DataPath();
+		dataPath.setSrcPort(new SwitchPort(new Dpid(0x1234), new Port((short)1)));
+		dataPath.setDstPort(new SwitchPort(new Dpid(0x5678), new Port((short)2)));
+		dataPath.setFlowEntries(flowEntries);
+
+		FlowEntryMatch match = new FlowEntryMatch();
+		
+		FlowPath flowPath = new FlowPath();
+		flowPath.setFlowId(new FlowId(0x100));
+		flowPath.setInstallerId(new CallerId("installer id"));
+		flowPath.setFlowPathFlags(new FlowPathFlags(0));
+		flowPath.setDataPath(dataPath);
+		flowPath.setFlowEntryMatch(match);
+		
+		// setup expectations
+		expectInitWithContext();
+		expect(op.searchFlowPath(cmpEq(new FlowId(0x100)))).andReturn(null);
+		expect(op.newFlowPath()).andReturn(createdFlowPath);
+		createdFlowPath.setFlowId("0x100");
+		createdFlowPath.setType("flow");
+		createdFlowPath.setInstallerId("installer id");
+		createdFlowPath.setFlowPathFlags(new Long((long)0));
+		createdFlowPath.setSrcSwitch("00:00:00:00:00:00:12:34");
+		createdFlowPath.setSrcPort(new Short((short)1));
+		createdFlowPath.setDstSwitch("00:00:00:00:00:00:56:78");
+		createdFlowPath.setDstPort(new Short((short)2));
+		createdFlowPath.setDataPathSummary("data path summary");
+		createdFlowPath.setUserState("FE_USER_ADD");
+		
+		expectPrivate(fm, addFlowEntry, createdFlowPath, flowEntry1)
+			.andReturn(createdFlowEntry1);
+		expectPrivate(fm, addFlowEntry, createdFlowPath, flowEntry2)
+			.andReturn(createdFlowEntry2);
+		
+		op.commit();
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Boolean result = fm.addFlow(flowPath, new FlowId(0x100), "data path summary");
+
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#deleteAllFlows()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testDeleteAllFlowsSuccessNormally() throws Exception {
+		// create mock objects
+		IFlowPath flowPath1 = createNiceMock(IFlowPath.class);
+		IFlowPath flowPath2 = createNiceMock(IFlowPath.class);
+		
+		// instantiate required objects
+		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
+		flowPaths.add(flowPath1);
+		flowPaths.add(flowPath2);
+		FlowManager fm = new FlowManager();
+		
+		// setup expectations
+		expectInitWithContext();
+		expect(op.getAllFlowPaths()).andReturn(flowPaths);
+
+		expect(flowPath1.getFlowId()).andReturn("1").anyTimes();
+		expect(op.searchFlowPath(cmpEq(new FlowId(1)))).andReturn(flowPath1);
+		expect(flowPath1.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>());
+		op.removeFlowPath(flowPath1);
+		
+		expect(flowPath2.getFlowId()).andReturn("2").anyTimes();
+		expect(op.searchFlowPath(cmpEq(new FlowId(2)))).andReturn(flowPath2);
+		expect(flowPath2.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>());
+		op.removeFlowPath(flowPath2);
+
+		op.commit();
+		expectLastCall().anyTimes();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Boolean result = fm.deleteAllFlows();
+
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#deleteFlow(FlowId)}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testDeleteFlowSuccessEmptyFlowPath() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		
+		// create mock objects
+		IFlowPath flowObj = createNiceMock(IFlowPath.class);
+
+		// setup expectations
+		expectInitWithContext();
+		expect(op.searchFlowPath(cmpEq(new FlowId(1)))).andReturn(flowObj);
+		expect(flowObj.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>());
+		op.removeFlowPath(flowObj);
+		op.commit();
+		expectLastCall().anyTimes();
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Boolean result = fm.deleteFlow(new FlowId(1));
+		
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#clearAllFlows()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testClearAllFlowsSuccessNormally() throws Exception {
+		// create mock objects
+		IFlowPath flowPath1 = createNiceMock(IFlowPath.class);
+		IFlowPath flowPath2 = createNiceMock(IFlowPath.class);
+		IFlowPath flowPath3 = createNiceMock(IFlowPath.class);
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, "clearFlow");
+		
+		// instantiate required objects
+		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
+		flowPaths.add(flowPath1);
+		flowPaths.add(flowPath2);
+		flowPaths.add(null);
+		flowPaths.add(flowPath3);
+		
+		// setup expectations
+		expectInitWithContext();
+		expect(op.getAllFlowPaths()).andReturn(flowPaths);
+		expect(flowPath1.getFlowId()).andReturn(new FlowId(1).toString());
+		expect(flowPath2.getFlowId()).andReturn(null);
+		expect(flowPath3.getFlowId()).andReturn(new FlowId(3).toString());
+		expect(fm.clearFlow(cmpEq(new FlowId(1)))).andReturn(true);
+		expect(fm.clearFlow(cmpEq(new FlowId(3)))).andReturn(true);
+		
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		Boolean result = fm.clearAllFlows();
+		
+		//verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#getFlow()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetFlowSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		IFlowPath iFlowPath = createIFlowPathMock(1, "caller id", 0, 1, 1, 2, 2); 
+
+		// setup expectations
+		expectInitWithContext();
+		expect(op.searchFlowPath(cmpEq(new FlowId(1)))).andReturn(iFlowPath);
+		expect(iFlowPath.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>()).anyTimes();
+		op.commit();
+		
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		FlowPath flowPath = fm.getFlow(new FlowId(1));
+		String installerId = flowPath.installerId().toString();
+		long flowPathFlags = flowPath.flowPathFlags().flags();
+		
+		//verify the test
+		verifyAll();
+		assertEquals("caller id", installerId);
+		assertEquals(0L, flowPathFlags);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#getAllFlows(CallerId, DataPathEndpoints)}.
+	 * @throws Exception 
+	 */ 
+	@Test
+	public final void testGetAllFlowsWithCallerIdAndDataPathEndpointsSuccessNormally() throws Exception {
+		final String getAllFlows = "getAllFlows";
+		// create mock objects
+		FlowManager fm = createPartialMock(FlowManager.class, getAllFlows,
+				new Class<?>[]{}, new Object[]{});
+
+		// instantiate required objects
+		DataPathEndpoints dataPathEndpoints = new DataPathEndpoints(
+				new SwitchPort(new Dpid(1), new Port((short)1)),
+				new SwitchPort(new Dpid(2), new Port((short)2)));
+
+		ArrayList<FlowPath> obtainedAllFlows = createTestFlowPaths();
+			
+		//setup expectations
+		expectInitWithContext();
+		expectPrivate(fm, getAllFlows).andReturn(obtainedAllFlows);
+		
+		//start the test
+		replayAll();
+		
+		fm.init(context);
+		ArrayList<FlowPath> flows = fm.getAllFlows(new CallerId("caller id"), dataPathEndpoints);
+
+		// verify the test
+		verifyAll();
+		assertEquals(1, flows.size());
+		assertEquals(obtainedAllFlows.get(1), flows.get(0));
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#getAllFlows(DataPathEndpoints)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetAllFlowsWithDataPathEndpointsSuccessNormally() throws Exception {
+		final String getAllFlows = "getAllFlows";
+		// create mock objects
+		FlowManager fm = createPartialMock(FlowManager.class, getAllFlows,
+				new Class<?>[]{}, new Object[]{});
+
+		// instantiate required objects
+		DataPathEndpoints dataPathEndpoints = new DataPathEndpoints(
+				new SwitchPort(new Dpid(1), new Port((short)1)),
+				new SwitchPort(new Dpid(2), new Port((short)2)));
+
+		ArrayList<FlowPath> obtainedAllFlows = createTestFlowPaths();
+			
+		//setup expectations
+		expectInitWithContext();
+		expectPrivate(fm, getAllFlows).andReturn(obtainedAllFlows);
+		
+		//start the test
+		replayAll();
+		
+		fm.init(context);
+		ArrayList<FlowPath> flows = fm.getAllFlows(dataPathEndpoints);
+
+		// verify the test
+		verifyAll();
+		assertEquals(2, flows.size());
+		assertEquals(obtainedAllFlows.get(0), flows.get(0));
+		assertEquals(obtainedAllFlows.get(1), flows.get(1));
+		// TODO: ignore the order of flows in the list
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#getAllFlowsSummary(FlowId, int)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetAllFlowsSummarySuccessNormally() throws Exception {
+		final String getAllFlowsWithoutFlowEntries = "getAllFlowsWithoutFlowEntries";
+		// create mock objects
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, getAllFlowsWithoutFlowEntries);
+		IFlowPath flowPath1 = createIFlowPathMock(1, "", 0, 1, 2, 3, 4);
+		IFlowPath flowPath2 = createIFlowPathMock(5, "", 0, 2, 3, 4, 5);
+		IFlowPath flowPath3 = createIFlowPathMock(10, "", 0, 3, 4, 5, 6);
+
+		// instantiate required objects
+		ArrayList<IFlowPath> flows = new ArrayList<IFlowPath>();
+		flows.add(flowPath3);
+		flows.add(flowPath1);
+		flows.add(flowPath2);
+		
+		// setup expectations
+		expectInitWithContext();
+		expectPrivate(fm, getAllFlowsWithoutFlowEntries).andReturn(flows);
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		ArrayList<IFlowPath> returnedFlows = fm.getAllFlowsSummary(null, 0);
+		
+		// verify the test
+		verifyAll();
+		assertEquals(3, returnedFlows.size());
+		assertEquals(1, new FlowId(returnedFlows.get(0).getFlowId()).value());
+		assertEquals(5, new FlowId(returnedFlows.get(1).getFlowId()).value());
+		assertEquals(10, new FlowId(returnedFlows.get(2).getFlowId()).value());
+	}
+
+	/**
+	 * Test method for {@link FlowManager#getAllFlows()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetAllFlowsSuccessNormally() throws Exception {
+		// create mock objects
+		IFlowPath iFlowPath1 = createIFlowPathMock(1, "caller id", 0, 1, 1, 2, 2); 
+		IFlowPath iFlowPath2 = createIFlowPathMock(2, "caller id", 0, 2, 5, 3, 5);
+		
+		// instantiate required objects
+		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
+		flowPaths.add(iFlowPath1);
+		flowPaths.add(iFlowPath2);
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+		expect(op.getAllFlowPaths()).andReturn(flowPaths);
+		expect(iFlowPath1.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>()).anyTimes();
+		expect(iFlowPath2.getFlowEntries()).andReturn(new ArrayList<IFlowEntry>()).anyTimes();
+		op.commit();
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		ArrayList<FlowPath> flows = fm.getAllFlows();
+
+		// verify the test
+		verifyAll();
+		assertEquals(2, flows.size());
+		assertEquals(new SwitchPort(new Dpid(1), new Port((short)1)).toString(),
+				flows.get(0).dataPath().srcPort().toString());
+		assertEquals(new SwitchPort(new Dpid(2), new Port((short)5)).toString(),
+				flows.get(1).dataPath().srcPort().toString());
+		// TODO: more asserts
+		// TODO: ignore seq. of the list
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#addAndMaintainShortestPathFlow(FlowPath)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testAddAndMaintainShortestPathFlowSuccessNormally() throws Exception {
+		final String addFlow = "addFlow";
+
+		// create mock objects
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlow);
+
+		// instantiate required objects
+		DataPath dataPath = new DataPath();
+		dataPath.setSrcPort(new SwitchPort(new Dpid(1), new Port((short)3)));
+		dataPath.setDstPort(new SwitchPort(new Dpid(2), new Port((short)4)));
+		FlowEntryMatch match = new FlowEntryMatch();
+		FlowPath paramFlow = new FlowPath();
+		paramFlow.setFlowId(new FlowId(100));
+		paramFlow.setInstallerId(new CallerId("installer id"));
+		paramFlow.setFlowPathFlags(new FlowPathFlags(0));
+		paramFlow.setDataPath(dataPath);
+		paramFlow.setFlowEntryMatch(match);
+		
+		// setup expectations
+		expectInitWithContext();
+		expectPrivate(fm, addFlow,
+				EasyMock.anyObject(FlowPath.class),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)
+				).andAnswer(new IAnswer<Object>() {
+					public Object answer() throws Exception {
+						FlowPath flowPath = (FlowPath)EasyMock.getCurrentArguments()[0];
+						assertEquals(flowPath.flowId().value(), 100);
+						assertEquals(flowPath.installerId().toString(), "installer id");
+						assertEquals(flowPath.flowPathFlags().flags(), 0);
+						assertEquals(flowPath.dataPath().srcPort().toString(),
+								new SwitchPort(new Dpid(1), new Port((short)3)).toString());
+
+						String dataPathSummary = (String)EasyMock.getCurrentArguments()[2];
+						assertEquals(dataPathSummary, "X");
+						
+						return true;
+					}
+				});
+		
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		FlowPath resultFlow = fm.addAndMaintainShortestPathFlow(paramFlow);
+				
+		// verify the test
+		verifyAll();
+		assertEquals(paramFlow.flowId().value(), resultFlow.flowId().value());
+		assertEquals(paramFlow.installerId().toString(), resultFlow.installerId().toString());
+		assertEquals(paramFlow.flowPathFlags().flags(), resultFlow.flowPathFlags().flags());
+		assertEquals(paramFlow.dataPath().toString(), resultFlow.dataPath().toString());
+		assertEquals(paramFlow.flowEntryMatch().toString(), resultFlow.flowEntryMatch().toString());
+	}
+		
+	/**
+	 * Test method for {@link FlowManager#measurementStorePathFlow(FlowPath)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testMeasurementStorePathFlowSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowPath paramFlow = createTestFlowPath(100, "installer id", 0, 1, 3, 2, 4);
+		Map<Long, Object> shortestPathMap = new HashMap<Long, Object>();
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+		expect((Map<Long,Object>)topoRouteService.prepareShortestPathTopo()
+				).andReturn(shortestPathMap);
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				paramFlow.dataPath().srcPort(),
+				paramFlow.dataPath().dstPort())).andReturn(null);
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		FlowPath resultFlowPath = fm.measurementStorePathFlow(paramFlow);
+		
+		// verify the test
+		verifyAll();
+		assertEquals(paramFlow.flowId().value(), resultFlowPath.flowId().value());
+		assertEquals(paramFlow.installerId().toString(), resultFlowPath.installerId().toString());
+		assertEquals(paramFlow.flowPathFlags().flags(), resultFlowPath.flowPathFlags().flags());
+		assertEquals(paramFlow.dataPath().toString(), resultFlowPath.dataPath().toString());
+		assertEquals(paramFlow.flowEntryMatch().toString(), resultFlowPath.flowEntryMatch().toString());
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#measurementInstallPaths(Integer)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testMeasurementInstallPathsSuccessNormally() throws Exception {
+		final String addFlow = "addFlow";
+
+		// create mock objects
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlow);
+
+		// instantiate required objects
+		FlowPath flow1 = createTestFlowPath(1, "installer id", 0, 1, 2, 3, 4);
+		FlowPath flow2 = createTestFlowPath(2, "installer id", 0, 2, 3, 4, 5);
+		FlowPath flow3 = createTestFlowPath(3, "installer id", 0, 3, 4, 5, 6);
+		Map<Long, Object> shortestPathMap = new HashMap<Long, Object>();
+
+		// setup expectations
+		expectInitWithContext();
+		expect((Map<Long,Object>)topoRouteService.prepareShortestPathTopo()
+				).andReturn(shortestPathMap);
+
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				flow1.dataPath().srcPort(),
+				flow1.dataPath().dstPort())).andReturn(null);
+		
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				flow2.dataPath().srcPort(),
+				flow2.dataPath().dstPort())).andReturn(null);
+
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				flow3.dataPath().srcPort(),
+				flow3.dataPath().dstPort())).andReturn(null);
+
+		expectPrivate(fm, addFlow,
+				EasyMock.cmpEq(flow1),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)).andReturn(true);
+
+		expectPrivate(fm, addFlow,
+				EasyMock.cmpEq(flow2),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)).andReturn(true);
+
+		expectPrivate(fm, addFlow,
+				EasyMock.cmpEq(flow3),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)).andReturn(true);
+
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		fm.measurementStorePathFlow(flow1);
+		fm.measurementStorePathFlow(flow2);
+		fm.measurementStorePathFlow(flow3);
+		Boolean result = fm.measurementInstallPaths(3);
+		
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#measurementGetInstallPathsTimeNsec()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testMeasurementGetInstallPathsTimeNsecSuccessNormally() throws Exception {
+		final String addFlow = "addFlow";
+
+		// create mock objects
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlow);
+		mockStaticPartial(System.class, "nanoTime");
+
+		// instantiate required objects
+		FlowPath flow1 = createTestFlowPath(1, "installer id", 0, 1, 2, 3, 4);
+		Map<Long, Object> shortestPathMap = new HashMap<Long, Object>();
+
+		// setup expectations
+		expectInitWithContext();
+		expect(System.nanoTime()).andReturn(new Long(100000));
+		expect(System.nanoTime()).andReturn(new Long(110000));
+		expect((Map<Long,Object>)topoRouteService.prepareShortestPathTopo()
+				).andReturn(shortestPathMap);
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				flow1.dataPath().srcPort(),
+				flow1.dataPath().dstPort())).andReturn(null);
+		expectPrivate(fm, addFlow,
+				EasyMock.cmpEq(flow1),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)).andReturn(true);
+		
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		fm.measurementStorePathFlow(flow1).toString();
+		fm.measurementInstallPaths(1);
+		Long result = fm.measurementGetInstallPathsTimeNsec();
+		
+		// verify the test
+		verifyAll();
+		assertEquals(new Long(10000), result);
+	}
+
+	/**
+	 * Test method for {@link FlowManager#measurementGetPerFlowInstallTime()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testMeasurementGetPerFlowInstallTimeSuccessNormally() throws Exception {
+		final String addFlow = "addFlow";
+
+		// create mock objects
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlow);
+		
+		// instantiate required objects
+		FlowPath flow1 = createTestFlowPath(1, "installer id", 0, 1, 2, 3, 4);
+		Map<Long, Object> shortestPathMap = new HashMap<Long, Object>();
+
+		// setup expectations
+		expectInitWithContext();
+		expect((Map<Long,Object>)topoRouteService.prepareShortestPathTopo()
+				).andReturn(shortestPathMap);
+
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				flow1.dataPath().srcPort(),
+				flow1.dataPath().dstPort())).andReturn(null);
+
+		expectPrivate(fm, addFlow,
+				EasyMock.cmpEq(flow1),
+				EasyMock.anyObject(FlowId.class),
+				EasyMock.anyObject(String.class)).andReturn(true);
+
+
+		// start the test
+		replayAll();
+
+		fm.init(context);
+		fm.measurementStorePathFlow(flow1);
+		fm.measurementInstallPaths(10);
+		String result = fm.measurementGetPerFlowInstallTime();
+				
+		// verify the test
+		verifyAll();
+		assertTrue(result.startsWith("ThreadAndTimePerFlow"));
+	}
+
+	/**
+	 * Test method for {@link FlowManager#measurementClearAllPaths()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testMeasurementClearAllPathsSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowPath paramFlow = createTestFlowPath(100, "installer id", 0, 1, 3, 2, 4);
+		Map<Long, Object> shortestPathMap = new HashMap<Long, Object>();
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+		expect((Map<Long,Object>)topoRouteService.prepareShortestPathTopo()
+				).andReturn(shortestPathMap);
+		expect(topoRouteService.getTopoShortestPath(
+				shortestPathMap,
+				paramFlow.dataPath().srcPort(),
+				paramFlow.dataPath().dstPort())).andReturn(null);
+		topoRouteService.dropShortestPathTopo(shortestPathMap);
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		fm.measurementStorePathFlow(paramFlow);
+		Boolean result = fm.measurementClearAllPaths();
+				
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+		assertEquals(new Long(0), fm.measurementGetInstallPathsTimeNsec());
+		assertEquals("", fm.measurementGetPerFlowInstallTime());
+	}
+	
+		
+	// INetMapStorage methods
+	
+	
+	/**
+	 * Test method for {@link FlowManager#init(String)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testInitSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+
+		// create mock objects
+		op = createMock(GraphDBOperation.class);
+
+		// setup expectations
+		expectNew(GraphDBOperation.class, "/dummy/path").andReturn(op);
+		
+		// start the test
+		replayAll();
+		
+		fm.init("/dummy/path");
+		
+		// verify the test
+		verifyAll();
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#close()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testCloseSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+		op.close();
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		fm.close();
+		
+		// verify the test
+		verifyAll();
+	}
+	
+	
+	// IFloodlightModule methods
+	
+	
+	/**
+	 * Test method for {@link FlowManager#getModuleServices()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetModuleServicesSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Collection<Class<? extends IFloodlightService>> l = fm.getModuleServices();
+
+		// verify the test
+		verifyAll();
+		assertEquals(1, l.size());
+		assertEquals(IFlowService.class, l.iterator().next());
+	}
+
+	/**
+	 * Test method for {@link FlowManager#getServiceImpls()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetServiceImplsSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Map<Class<? extends IFloodlightService>, IFloodlightService> si = fm.getServiceImpls();
+
+		// verify the test
+		verifyAll();
+		assertEquals(1, si.size());
+		assertTrue(si.containsKey(IFlowService.class));
+		assertEquals(fm, si.get(IFlowService.class));	
+	}
+
+	/**
+	 * Test method for {@link FlowManager#getModuleDependencies()}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testGetModuleDependenciesSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+
+		// setup expectations
+		expectInitWithContext();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Collection<Class<? extends IFloodlightService>> md = fm.getModuleDependencies();
+
+		// verify the test
+		verifyAll();
+		assertEquals(2, md.size());
+		assertTrue(md.contains(IFloodlightProviderService.class));
+		assertTrue(md.contains(IRestApiService.class));
+	}
+
+	/**
+	 * Test method for {@link FlowManager#init(FloodlightModuleContext)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testInitWithFloodlightModuleContextSuccessNormally() throws Exception {
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		
+		// setup expectations
+		expectInitWithContext();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+
+		// verify the test
+		verifyAll();
+	}
+
+	/**
+	 * Test method for {@link FlowManager#startUp(FloodlightModuleContext)}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testStartupSuccessNormally() throws Exception {
+		// create mock objects
+		mockStaticPartial(Executors.class, "newScheduledThreadPool");
+		ScheduledExecutorService scheduler = createMock(ScheduledExecutorService.class);
+
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		
+		// setup expectations
+		expectInitWithContext();
+		expect(Executors.newScheduledThreadPool(1)).andReturn(scheduler);
+		expect(Executors.newScheduledThreadPool(1)).andReturn(scheduler);
+		expect(scheduler.scheduleAtFixedRate(
+				EasyMock.anyObject(Runnable.class),
+				EasyMock.anyLong(),
+				EasyMock.anyLong(),
+				EasyMock.anyObject(TimeUnit.class))).andReturn(null).times(2);
+		restApi.addRestletRoutable(EasyMock.anyObject(FlowWebRoutable.class));
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		fm.startUp(context);
+
+		// verify the test
+		verifyAll();
+	}
+	
+	
+	// other methods
+	
+	
+	/**
+	 * Test method for {@link FlowManager#clearFlow(FlowId)}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testClearFlowSuccessNormally() throws Exception {
+		// create mock objects
+		IFlowPath flowPath = createIFlowPathMock(123, "id", 0, 1, 2, 3, 4);
+		IFlowEntry flowEntry1 = createMock(IFlowEntry.class);
+		IFlowEntry flowEntry2 = createMock(IFlowEntry.class);
+		IFlowEntry flowEntry3 = createMock(IFlowEntry.class);
+		
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		FlowId flowId = new FlowId(123);
+		ArrayList<IFlowEntry> flowEntries = new ArrayList<IFlowEntry>();
+		flowEntries.add(flowEntry1);
+		flowEntries.add(flowEntry2);
+		flowEntries.add(flowEntry3);
+
+		// setup expectations
+		expectInitWithContext();
+		expect(op.searchFlowPath(cmpEq(flowId))).andReturn(flowPath);
+		expect(flowPath.getFlowEntries()).andReturn(flowEntries);
+		flowPath.removeFlowEntry(flowEntry1);
+		flowPath.removeFlowEntry(flowEntry2);
+		flowPath.removeFlowEntry(flowEntry3);
+		op.removeFlowEntry(flowEntry1);
+		op.removeFlowEntry(flowEntry2);
+		op.removeFlowEntry(flowEntry3);
+		op.removeFlowPath(flowPath);
+		op.commit();
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		fm.clearFlow(flowId);
+
+		// verify the test
+		verifyAll();
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#getAllFlowsWithoutFlowEntries()}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testGetAllFlowsWithoutFlowEntriesSuccessNormally() throws Exception {
+		// create mock objects
+		IFlowPath iFlowPath1 = createIFlowPathMock(1, "caller id", 0, 1, 1, 2, 2); 
+		IFlowPath iFlowPath2 = createIFlowPathMock(2, "caller id", 0, 2, 5, 3, 5);
+		
+		// instantiate required objects
+		ArrayList<IFlowPath> flowPaths = new ArrayList<IFlowPath>();
+		flowPaths.add(iFlowPath1);
+		flowPaths.add(iFlowPath2);
+		FlowManager fm = new FlowManager();
+		
+		// setup expectations
+		expectInitWithContext();
+		op.commit();
+		expect(op.getAllFlowPaths()).andReturn(flowPaths);
+		
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		ArrayList<IFlowPath> result = fm.getAllFlowsWithoutFlowEntries();
+		
+		// verify the test
+		verifyAll();
+		assertEquals(iFlowPath1, result.get(0));
+		assertEquals(iFlowPath2, result.get(1));
+		
+		// TODO: does this method just return the replica of the flow paths?
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#reconcileFlow(IFlowPath, DataPath)}.
+	 * @throws Exception
+	 */
+	@Test
+	public final void testReconcileFlowWithFlowPathAndDataPathSuccessNormally() throws Exception {
+		final String addFlowEntry = "addFlowEntry";
+		
+		// create mock objects
+		IFlowPath iFlowPath1 = createIFlowPathMock(1, "caller id", 0, 1, 1, 2, 2);
+		IFlowEntry iFlowEntry1 = createMock(IFlowEntry.class);
+		IFlowEntry iFlowEntry2 = createMock(IFlowEntry.class);
+		FlowManager fm = createPartialMockAndInvokeDefaultConstructor(FlowManager.class, addFlowEntry);
+		
+		// instantiate required objects
+		FlowEntry flowEntry1 = new FlowEntry();
+		flowEntry1.setDpid(new Dpid(1));
+		flowEntry1.setFlowId(new FlowId(1));
+		flowEntry1.setInPort(new Port((short) 1));
+		flowEntry1.setOutPort(new Port((short) 11));
+		flowEntry1.setFlowEntryId(new FlowEntryId(1));
+		flowEntry1.setFlowEntryMatch(new FlowEntryMatch());
+		flowEntry1.setFlowEntryActions(new FlowEntryActions());
+		flowEntry1.setFlowEntryErrorState(new FlowEntryErrorState());
+		
+		FlowEntry flowEntry2 = new FlowEntry();
+		flowEntry2.setDpid(new Dpid(2));
+		flowEntry2.setFlowId(new FlowId(2));
+		flowEntry2.setInPort(new Port((short) 22)); 
+		flowEntry2.setOutPort(new Port((short) 2));
+		flowEntry2.setFlowEntryId(new FlowEntryId(2));
+		flowEntry2.setFlowEntryMatch(new FlowEntryMatch());
+		flowEntry2.setFlowEntryActions(new FlowEntryActions());
+		flowEntry2.setFlowEntryErrorState(new FlowEntryErrorState());
+		
+		DataPath dataPath = new DataPath();
+		ArrayList<FlowEntry> flowEntries = new ArrayList<FlowEntry>();
+		flowEntries.add(flowEntry1);
+		flowEntries.add(flowEntry2);
+		dataPath.setFlowEntries(flowEntries);
+		
+		ArrayList<IFlowEntry> oldFlowEntries = new ArrayList<IFlowEntry>();
+		oldFlowEntries.add(iFlowEntry1);
+		oldFlowEntries.add(iFlowEntry2);
+
+		// setup expectations
+		expectInitWithContext();
+		expect(floodlightProvider.getSwitches()).andReturn(null); // TODO: why is this needed?
+		expect(iFlowPath1.getFlowEntries()).andReturn(oldFlowEntries);
+		iFlowEntry1.setUserState("FE_USER_DELETE");
+		iFlowEntry1.setSwitchState("FE_SWITCH_NOT_UPDATED");
+		iFlowEntry2.setUserState("FE_USER_DELETE");
+		iFlowEntry2.setSwitchState("FE_SWITCH_NOT_UPDATED");
+		expectPrivate(fm, addFlowEntry, iFlowPath1, flowEntry1).andReturn(null);
+		expectPrivate(fm, addFlowEntry, iFlowPath1, flowEntry2).andReturn(null);
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Boolean result = fm.reconcileFlow(iFlowPath1, dataPath);
+		
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+		// TODO: write more asserts
+	}
+	
+	/**
+	 * Test method for {@link FlowManager#installFlowEntry(net.floodlightcontroller.core.IOFSwitch, IFlowPath, IFlowEntry)}.
+	 * @throws Exception 
+	 */
+	@Test
+	public final void testInstallFlowEntryWithIFlowPathSuccessNormally() throws Exception {
+		// create mock object
+		IOFSwitch iofSwitch = createNiceMock(IOFSwitch.class);
+		IFlowPath iFlowPath = createIFlowPathMock(1, "id", 0, 1, 2, 3, 4); 
+		IFlowEntry iFlowEntry = createMock(IFlowEntry.class);
+		BasicFactory basicFactory = createMock(BasicFactory.class);
+		
+		// instantiate required objects
+		FlowManager fm = new FlowManager();
+		
+		FlowEntryAction action = new FlowEntryAction();
+		action.setActionOutput(new Port((short)2));
+		FlowEntryActions actions = new FlowEntryActions();
+		actions.addAction(action);
+
+		// setup expectations
+		expectInitWithContext();
+		expect(iFlowEntry.getFlowEntryId()).andReturn(new FlowEntryId(123).toString());
+		expect(iFlowEntry.getUserState()).andReturn("FE_USER_ADD");
+		iFlowEntry.setSwitchState("FE_SWITCH_UPDATED");
+		expect(iFlowEntry.getMatchInPort()).andReturn(new Short((short) 1));
+		expect(iFlowEntry.getMatchSrcMac()).andReturn("01:23:45:67:89:01");
+		expect(iFlowEntry.getMatchDstMac()).andReturn("01:23:45:67:89:02");
+		expect(iFlowEntry.getMatchEthernetFrameType()).andReturn(new Short((short)0x0800));
+		expect(iFlowEntry.getMatchVlanId()).andReturn(new Short((short)0x1234));
+		expect(iFlowEntry.getMatchVlanPriority()).andReturn(new Byte((byte)0x10));
+		expect(iFlowEntry.getMatchSrcIPv4Net()).andReturn("192.168.0.1");
+		expect(iFlowEntry.getMatchDstIPv4Net()).andReturn("192.168.0.2");
+		expect(iFlowEntry.getMatchIpProto()).andReturn(new Byte((byte)0x20));
+		expect(iFlowEntry.getMatchIpToS()).andReturn(new Byte((byte)0x3));
+		expect(iFlowEntry.getMatchSrcTcpUdpPort()).andReturn(new Short((short)40000));
+		expect(iFlowEntry.getMatchDstTcpUdpPort()).andReturn(new Short((short)80));
+		expect(iFlowEntry.getActions()).andReturn(actions.toString());
+		expect(floodlightProvider.getOFMessageFactory()).andReturn(basicFactory);
+		expect(basicFactory.getMessage(OFType.FLOW_MOD)).andReturn(new OFFlowMod());
+		expect(iofSwitch.getStringId()).andReturn(new Dpid(100).toString());
+
+		// start the test
+		replayAll();
+		
+		fm.init(context);
+		Boolean result = fm.installFlowEntry(iofSwitch, iFlowPath, iFlowEntry);
+		
+		// verify the test
+		verifyAll();
+		assertTrue(result);
+		// TODO: write more asserts
+	}
+
+	/**
+	 * Test method for {@link FlowManager#installFlowEntry(net.floodlightcontroller.core.IOFSwitch, FlowPath, FlowEntry)}.
+	 * The method seems to be not used for now.
+	 */
+	@Ignore @Test
+	public final void testInstallFlowEntryWithFlowPathSuccessNormally() {
+		fail("not yet implemented");
+	}
+
+	/**
+	 * Test method for {@link FlowManager#removeFlowEntry(net.floodlightcontroller.core.IOFSwitch, FlowPath, FlowEntry)}.
+	 * The method seems to be not implemented and not used for now.
+	 */
+	@Ignore @Test
+	public final void testRemoveFlowEntrySuccessNormally() {
+		fail("not yet implemented");
+	}
+
+	/**
+	 * Test method for {@link FlowManager#installRemoteFlowEntry(FlowPath, FlowEntry)}.
+	 * The method seems to be not implemented and not used for now.
+	 */
+	@Ignore @Test
+	public final void testInstallRemoteFlowEntrySuccessNormally() {
+		fail("not yet implemented");
+	}
+
+	/**
+	 * Test method for {@link FlowManager#removeRemoteFlowEntry(FlowPath, FlowEntry)}.
+	 * The method seems to be not implemented and not used for now.
+	 */
+	@Ignore @Test
+	public final void testRemoveRemoteFlowEntrySuccessNormally() {
+		fail("not yet implemented");
+	}
+}
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java b/src/test/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
similarity index 97%
rename from src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
rename to src/test/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
index 6e99acd..87b48b2 100644
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
+++ b/src/test/java/net/onrc/onos/ofcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
@@ -15,7 +15,7 @@
 *    under the License.
 **/
 
-package net.floodlightcontroller.linkdiscovery.internal;
+package net.onrc.onos.ofcontroller.linkdiscovery.internal;
 
 import static org.easymock.EasyMock.*;
 
@@ -35,10 +35,6 @@
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener;
-import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService;
-import net.floodlightcontroller.linkdiscovery.LinkInfo;
-import net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.restserver.RestApiServer;
 import net.floodlightcontroller.routing.IRoutingService;
@@ -50,6 +46,10 @@
 import net.floodlightcontroller.topology.ITopologyService;
 import net.floodlightcontroller.topology.NodePortTuple;
 import net.floodlightcontroller.topology.TopologyManager;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryListener;
+import net.onrc.onos.ofcontroller.linkdiscovery.ILinkDiscoveryService;
+import net.onrc.onos.ofcontroller.linkdiscovery.LinkInfo;
+import net.onrc.onos.ofcontroller.linkdiscovery.internal.LinkDiscoveryManager;
 
 /**
  *
diff --git a/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java b/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java
new file mode 100644
index 0000000..a33df98
--- /dev/null
+++ b/src/test/java/net/onrc/onos/ofcontroller/routing/TopoRouteServiceTest.java
@@ -0,0 +1,262 @@
+package net.onrc.onos.ofcontroller.routing;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.thinkaurelius.titan.core.TitanGraph;
+import com.thinkaurelius.titan.core.TitanFactory;
+import com.tinkerpop.blueprints.Vertex;
+import com.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine;
+import com.tinkerpop.gremlin.java.GremlinPipeline;
+import com.tinkerpop.pipes.PipeFunction;
+import com.tinkerpop.pipes.branch.LoopPipe.LoopBundle;
+
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
+import net.onrc.onos.graph.GraphDBConnection;
+import net.onrc.onos.graph.GraphDBOperation;
+import net.onrc.onos.ofcontroller.core.internal.TestDatabaseManager;
+import net.onrc.onos.ofcontroller.routing.TopoRouteService;
+import net.onrc.onos.ofcontroller.util.DataPath;
+import net.onrc.onos.ofcontroller.util.Dpid;
+import net.onrc.onos.ofcontroller.util.FlowPathFlags;
+import net.onrc.onos.ofcontroller.util.Port;
+import net.onrc.onos.ofcontroller.util.SwitchPort;
+
+/**
+ * A class for testing the TopoRouteService class.
+ * @see net.onrc.onos.ofcontroller.routing.TopoRouteService
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({TitanFactory.class, GraphDBConnection.class, GraphDBOperation.class, TopoRouteService.class})
+public class TopoRouteServiceTest {
+    String conf;
+    private GraphDBConnection conn = null;
+    private GraphDBOperation oper = null;
+    private TitanGraph titanGraph = null;
+    private TopoRouteService topoRouteService = null;
+
+    /**
+     * Setup the tests.
+     */
+    @Before
+    public void setUp() throws Exception {
+	conf = "/dummy/path/to/db";
+
+	//
+	// Make mock database.
+	// Replace TitanFactory.open() to return the mock database.
+	//
+	titanGraph = TestDatabaseManager.getTestDatabase();
+	PowerMock.mockStatic(TitanFactory.class);
+	EasyMock.expect(TitanFactory.open((String)EasyMock.anyObject())).andReturn(titanGraph);
+	PowerMock.replay(TitanFactory.class);
+
+	// Create the connection to the database
+	conn = GraphDBConnection.getInstance(conf);
+	oper = new GraphDBOperation(conn);
+
+	// Populate the database
+	TestDatabaseManager.populateTestData(titanGraph);
+
+	// Prepare the TopoRouteService instance
+	topoRouteService = new TopoRouteService();
+	topoRouteService.setDbOperationHandler(oper);
+    }
+
+    /**
+     * Cleanup after the tests.
+     */
+    @After
+    public void tearDown() throws Exception {
+	titanGraph.shutdown();
+	TestDatabaseManager.deleteTestDatabase();
+    }
+
+    /**
+     * Test method TopoRouteService.getTopoShortestPath()
+     *
+     * @see net.onrc.onos.ofcontroller.routing.TopoRouteService#getTopoShortestPath
+     */
+    @Test
+    public void test_getTopoShortestPath() {
+	DataPath dataPath = null;
+	String srcDpidStr = "00:00:00:00:00:00:0a:01";
+	String dstDpidStr = "00:00:00:00:00:00:0a:06";
+	short srcPortShort = 1;
+	short dstPortShort = 1;
+
+	//
+	// Initialize the source and destination points
+	//
+	Dpid srcDpid = new Dpid(srcDpidStr);
+	Port srcPort = new Port(srcPortShort);
+	Dpid dstDpid = new Dpid(dstDpidStr);
+	Port dstPort = new Port(dstPortShort);
+	SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
+	SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
+
+	//
+	// Test a valid Shortest-Path computation
+	//
+	Map<Long, ?> shortestPathTopo =
+	    topoRouteService.prepareShortestPathTopo();
+	dataPath = topoRouteService.getTopoShortestPath(shortestPathTopo,
+							srcSwitchPort,
+							dstSwitchPort);
+	assertTrue(dataPath != null);
+	String dataPathSummaryStr = dataPath.dataPathSummary();
+	// System.out.println(dataPathSummaryStr);
+	String expectedResult = "1/00:00:00:00:00:00:0a:01/2;1/00:00:00:00:00:00:0a:03/2;2/00:00:00:00:00:00:0a:04/3;1/00:00:00:00:00:00:0a:06/1;";
+	assertEquals(dataPathSummaryStr, expectedResult);
+
+	// Test if we apply various Flow Path Flags
+	String expectedResult2 = "1/00:00:00:00:00:00:0a:03/2;2/00:00:00:00:00:00:0a:04/3;1/00:00:00:00:00:00:0a:06/1;";
+	String expectedResult3 = "1/00:00:00:00:00:00:0a:03/2;";
+	FlowPathFlags flowPathFlags2 = new FlowPathFlags("DISCARD_FIRST_HOP_ENTRY");
+	FlowPathFlags flowPathFlags3 = new FlowPathFlags("KEEP_ONLY_FIRST_HOP_ENTRY");
+	//
+	dataPath.applyFlowPathFlags(flowPathFlags2);
+	dataPathSummaryStr = dataPath.dataPathSummary();
+	assertEquals(dataPathSummaryStr, expectedResult2);
+	//
+	dataPath.applyFlowPathFlags(flowPathFlags3);
+	dataPathSummaryStr = dataPath.dataPathSummary();
+	assertEquals(dataPathSummaryStr, expectedResult3);
+
+	//
+	// Test Shortest-Path computation to non-existing destination
+	//
+	String noSuchDpidStr = "ff:ff:00:00:00:00:0a:06";
+	Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
+	SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
+	dataPath = topoRouteService.getTopoShortestPath(shortestPathTopo,
+							srcSwitchPort,
+							noSuchDstSwitchPort);
+	assertTrue(dataPath == null);
+
+	topoRouteService.dropShortestPathTopo(shortestPathTopo);
+    }
+
+    /**
+     * Test method TopoRouteService.getShortestPath()
+     *
+     * @see net.onrc.onos.ofcontroller.routing.TopoRouteService#getShortestPath
+     */
+    @Test
+    public void test_getShortestPath() {
+	DataPath dataPath = null;
+	String srcDpidStr = "00:00:00:00:00:00:0a:01";
+	String dstDpidStr = "00:00:00:00:00:00:0a:06";
+	short srcPortShort = 1;
+	short dstPortShort = 1;
+
+	//
+	// Initialize the source and destination points
+	//
+	Dpid srcDpid = new Dpid(srcDpidStr);
+	Port srcPort = new Port(srcPortShort);
+	Dpid dstDpid = new Dpid(dstDpidStr);
+	Port dstPort = new Port(dstPortShort);
+	SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
+	SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
+
+	//
+	// Test a valid Shortest-Path computation
+	//
+	dataPath = topoRouteService.getShortestPath(srcSwitchPort,
+						dstSwitchPort);
+	assertTrue(dataPath != null);
+	String dataPathSummaryStr = dataPath.dataPathSummary();
+	// System.out.println(dataPathSummaryStr);
+	String expectedResult = "1/00:00:00:00:00:00:0a:01/2;1/00:00:00:00:00:00:0a:03/2;2/00:00:00:00:00:00:0a:04/3;1/00:00:00:00:00:00:0a:06/1;";
+	assertEquals(dataPathSummaryStr, expectedResult);
+
+	// Test if we apply various Flow Path Flags
+	String expectedResult2 = "1/00:00:00:00:00:00:0a:03/2;2/00:00:00:00:00:00:0a:04/3;1/00:00:00:00:00:00:0a:06/1;";
+	String expectedResult3 = "1/00:00:00:00:00:00:0a:03/2;";
+	FlowPathFlags flowPathFlags2 = new FlowPathFlags("DISCARD_FIRST_HOP_ENTRY");
+	FlowPathFlags flowPathFlags3 = new FlowPathFlags("KEEP_ONLY_FIRST_HOP_ENTRY");
+	//
+	dataPath.applyFlowPathFlags(flowPathFlags2);
+	dataPathSummaryStr = dataPath.dataPathSummary();
+	assertEquals(dataPathSummaryStr, expectedResult2);
+	//
+	dataPath.applyFlowPathFlags(flowPathFlags3);
+	dataPathSummaryStr = dataPath.dataPathSummary();
+	assertEquals(dataPathSummaryStr, expectedResult3);
+
+	//
+	// Test Shortest-Path computation to non-existing destination
+	//
+	String noSuchDpidStr = "ff:ff:00:00:00:00:0a:06";
+	Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
+	SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
+
+	dataPath = topoRouteService.getShortestPath(srcSwitchPort,
+						    noSuchDstSwitchPort);
+	assertTrue(dataPath == null);
+    }
+
+    /**
+     * Test method TopoRouteService.routeExists()
+     *
+     * @see net.onrc.onos.ofcontroller.routing.TopoRouteService#routeExists
+     */
+    @Test
+    public void test_routeExists() {
+	Boolean result;
+	String srcDpidStr = "00:00:00:00:00:00:0a:01";
+	String dstDpidStr = "00:00:00:00:00:00:0a:06";
+	short srcPortShort = 1;
+	short dstPortShort = 1;
+
+	//
+	// Initialize the source and destination points
+	//
+	Dpid srcDpid = new Dpid(srcDpidStr);
+	Port srcPort = new Port(srcPortShort);
+	Dpid dstDpid = new Dpid(dstDpidStr);
+	Port dstPort = new Port(dstPortShort);
+	SwitchPort srcSwitchPort = new SwitchPort(srcDpid, srcPort);
+	SwitchPort dstSwitchPort = new SwitchPort(dstDpid, dstPort);
+
+	//
+	// Test a valid route
+	//
+	result = topoRouteService.routeExists(srcSwitchPort, dstSwitchPort);
+	assertTrue(result == true);
+
+	//
+	// Test a non-existing route
+	//
+	String noSuchDpidStr = "ff:ff:00:00:00:00:0a:06";
+	Dpid noSuchDstDpid = new Dpid(noSuchDpidStr);
+	SwitchPort noSuchDstSwitchPort = new SwitchPort(noSuchDstDpid, dstPort);
+	result = topoRouteService.routeExists(srcSwitchPort,
+					      noSuchDstSwitchPort);
+	assertTrue(result != true);
+    }
+}
diff --git a/src/test/java/net/onrc/onos/registry/controller/StandaloneRegistryTest.java b/src/test/java/net/onrc/onos/registry/controller/StandaloneRegistryTest.java
new file mode 100644
index 0000000..7c4a1a0
--- /dev/null
+++ b/src/test/java/net/onrc/onos/registry/controller/StandaloneRegistryTest.java
@@ -0,0 +1,461 @@
+package net.onrc.onos.registry.controller;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openflow.util.HexString;
+
+/**
+ * Unit test for {@link StandaloneRegistry}.
+ * @author Naoki Shiota
+ *
+ */
+public class StandaloneRegistryTest {
+	protected static final long TIMEOUT_MSEC = 1000;
+	
+	protected StandaloneRegistry registry;
+	
+	/**
+	 * Implementation of {@link ControlChangeCallback} which defines callback interfaces called by Registry.
+	 * This class remembers past callback parameters and provides methods to access them.
+	 * This class also provides CountDownLatch so one can wait until the callback be called
+	 * specific times (specified by constructor parameter). Particularly, the first time callback
+	 * called is supposed for registration, this class has an independent latch to wait for
+	 * the first callback.
+	 * @author Naoki Shiota
+	 */
+	public static class LoggingCallback implements ControlChangeCallback {
+		private LinkedList<Long> dpidsCalledback = new LinkedList<Long>();
+		private LinkedList<Boolean> controlsCalledback = new LinkedList<Boolean>();
+		private CountDownLatch lock = null, registerLock = null;;
+		
+		/**
+		 * Constructor with number of times callback to be called.
+		 * @param numberToCall Number of times expected callback to be called
+		 */
+		public LoggingCallback(int numberToCall) {
+			lock = new CountDownLatch(numberToCall);
+			registerLock = new CountDownLatch(1);
+		}
+
+		/**
+		 * Wait until registration is finished (callback is called for the first time).
+		 * @throws InterruptedException
+		 */
+		public void waitForRegistration() throws InterruptedException {
+			registerLock.await();
+		}
+		
+		/**
+		 * Wait for registration specifying timeout.
+		 * @param msec Milliseconds to timeout
+		 * @throws InterruptedException
+		 */
+		public void waitForRegistration(long msec) throws InterruptedException {
+			registerLock.await(msec, TimeUnit.MILLISECONDS);
+		}
+
+		/**
+		 * Wait until callback is called specific times.
+		 * @throws InterruptedException
+		 */
+		public void waitUntilCalled() throws InterruptedException {
+			lock.await();
+		}
+		
+		/**
+		 * Wait until callback is called specific times, specifying timeout.
+		 * @param msec Milliseconds to timeout
+		 * @throws InterruptedException
+		 */
+		public void waitUntilCalled(long msec) throws InterruptedException {
+			lock.await(msec, TimeUnit.MILLISECONDS);
+		}
+		
+		/**
+		 * Get DPID parameter given by specific callback time.
+		 * @param index Specify which time to get parameter
+		 * @return DPID value by number.
+		 */
+		public Long getDpid(int index) { return dpidsCalledback.get(index); }
+		
+		/**
+		 * Get hasControl parameter given by specific callback time.
+		 * @param index Specify which time to get parameter
+		 * @return hasControl value
+		 */
+		public Boolean getControl(int index) { return controlsCalledback.get(index); }
+		
+		/**
+		 * Get DPID parameter given by latest call.
+		 * @return DPID value by number
+		 */
+		public Long getLatestDpid() { return dpidsCalledback.peekLast(); }
+		
+		/**
+		 * Get hasControl parameter given by latest call
+		 * @return hasControl value
+		 */
+		public Boolean getLatestControl() { return controlsCalledback.peekLast(); }
+		
+		@Override
+		public void controlChanged(long dpid, boolean hasControl) {
+			dpidsCalledback.addLast(dpid);
+			controlsCalledback.addLast(hasControl);
+			
+			lock.countDown();
+			registerLock.countDown();
+		}
+	};
+	
+	@Before
+	public void setUp() throws Exception {
+        FloodlightModuleContext fmc = new FloodlightModuleContext();
+		registry = new StandaloneRegistry();
+		registry.init(fmc);
+	}
+
+	@After
+	public void tearDown() {
+	}
+	
+	/**
+	 * Test if {@link StandaloneRegistry#registerController(String)} can run without error.
+	 */
+	@Test
+	public void testRegisterController() {
+		String controllerIdToRegister = "test";
+		try {
+			registry.registerController(controllerIdToRegister);
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		
+		// Register Controller ID doubly 
+		try {
+			registry.registerController(controllerIdToRegister);
+			fail("Double registration goes through without exception");
+		} catch (RegistryException e) {
+			// expected behavior
+		}
+	}
+	
+	/**
+	 * Test if {@link StandaloneRegistry#getControllerId()} can return correct ID.
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testGetControllerId() throws RegistryException {
+		String controllerIdToRegister = "test";
+		
+		// try before controller is registered
+		String controllerId = registry.getControllerId();
+		assertNull(controllerId);
+		
+		// register
+		registry.registerController(controllerIdToRegister);
+
+		// call getControllerId and verify
+		controllerId = registry.getControllerId();
+		assertNotNull(controllerId);
+		assertEquals(controllerIdToRegister, controllerId);
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#getAllControllers()} can return correct list of controllers.
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testGetAllControllers() throws RegistryException {
+		String controllerIdToRegister = "test";
+		
+		// Test before register controller
+		try {
+			Collection<String> ctrls = registry.getAllControllers();
+			assertFalse(ctrls.contains(controllerIdToRegister));
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		
+		// register
+		registry.registerController(controllerIdToRegister);
+
+		// Test after register controller
+		try {
+			Collection<String> ctrls = registry.getAllControllers();
+			assertTrue(ctrls.contains(controllerIdToRegister));
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#requestControl(long, ControlChangeCallback)} can correctly take control for switch so that callback is called.
+	 * @throws RegistryException
+	 * @throws InterruptedException
+	 */
+	@Test
+	public void testRequestControl() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+
+		LoggingCallback callback = new LoggingCallback(1);
+		long dpidToRequest = 1000L;
+
+		try {
+			registry.requestControl(dpidToRequest, callback);
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		
+		callback.waitForRegistration();
+		
+		long dpidCallback = callback.getLatestDpid();
+		boolean controlCallback = callback.getLatestControl();
+		
+		assertEquals(dpidToRequest, dpidCallback);
+		assertTrue(controlCallback);
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#releaseControl(long)} can correctly release the control so that callback is called.
+	 * @throws InterruptedException
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testReleaseControl() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+		
+		long dpidToRequest = 1000L;
+		LoggingCallback callback = new LoggingCallback(2);
+		
+		// to request and wait to take control
+		registry.requestControl(dpidToRequest, callback);
+		callback.waitForRegistration();
+		
+		registry.releaseControl(dpidToRequest);
+		
+		// verify
+		callback.waitUntilCalled();
+		assertEquals(dpidToRequest, (long)callback.getLatestDpid());
+		assertFalse(callback.getLatestControl());
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#hasControl(long)} returns correct status.
+	 * @throws InterruptedException
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testHasControl() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+		
+		long dpidToRequest = 1000L;
+		LoggingCallback callback = new LoggingCallback(2);
+		
+		// Test before request control
+		assertFalse(registry.hasControl(dpidToRequest));
+		
+		registry.requestControl(dpidToRequest, callback);
+		callback.waitForRegistration();
+		
+		// Test after take control
+		assertTrue(registry.hasControl(dpidToRequest));
+		
+		registry.releaseControl(dpidToRequest);
+		
+		callback.waitUntilCalled();
+
+		// Test after release control
+		assertFalse(registry.hasControl(dpidToRequest));
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#getControllerForSwitch(long)} returns correct controller ID.
+	 * @throws InterruptedException
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testGetControllerForSwitch() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+		
+		long dpidToRequest = 1000L;
+		LoggingCallback callback = new LoggingCallback(2);
+		
+		// Test before request control
+		try {
+			String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
+			assertNotEquals(controllerId,controllerForSw);
+		} catch (RegistryException e) {
+			fail("Failed before request control : " + e.getMessage());
+			e.printStackTrace();
+		}
+
+		registry.requestControl(dpidToRequest, callback);
+		callback.waitForRegistration();
+
+		// Test after take control
+		try {
+			String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
+			assertEquals(controllerId,controllerForSw);
+		} catch (RegistryException e) {
+			fail("Failed after take control : " + e.getMessage());
+			e.printStackTrace();
+		}
+
+		registry.releaseControl(dpidToRequest);
+		callback.waitUntilCalled();
+
+		// Test after release control
+		try {
+			String controllerForSw = registry.getControllerForSwitch(dpidToRequest);
+			assertNotEquals(controllerId,controllerForSw);
+		} catch (RegistryException e) {
+			fail("Failed after release control : " + e.getMessage());
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#getAllSwitches()} returns correct list of switches.
+	 * @throws InterruptedException
+	 * @throws RegistryException
+	 */
+	@Test
+	public void testGetAllSwitches() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+
+		long dpidToRequest = 1000L;
+		String dpidToRequestStr = HexString.toHexString(dpidToRequest);
+		LoggingCallback callback = new LoggingCallback(2);
+
+		// Test before request control
+		Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
+		assertNotNull(switches);
+		assertFalse(switches.keySet().contains(dpidToRequestStr));
+
+		registry.requestControl(dpidToRequest, callback);
+		callback.waitForRegistration();
+
+		// Test after take control
+		switches = registry.getAllSwitches();
+		assertNotNull(switches);
+		assertTrue(switches.keySet().contains(dpidToRequestStr));
+		int count = 0;
+		for(ControllerRegistryEntry ctrl : switches.get(dpidToRequestStr)) {
+			if(ctrl.getControllerId().equals(controllerId)) {
+				++count;
+			}
+		}
+		assertEquals(1,count);
+		
+		registry.releaseControl(dpidToRequest);
+		callback.waitUntilCalled();
+
+		// Test after release control
+		switches = registry.getAllSwitches();
+		assertNotNull(switches);
+		assertFalse(switches.keySet().contains(dpidToRequestStr));
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#getSwitchesControlledByController(String)} returns correct list of switches.
+	 * @throws InterruptedException
+	 * @throws RegistryException
+	 */
+	// TODO: remove @Ignore after implement StandaloneRegistry#getSwitchesControlledByController
+	@Ignore @Test
+	public void testGetSwitchesControlledByController() throws InterruptedException, RegistryException {
+		String controllerId = "test";
+		registry.registerController(controllerId);
+
+		long dpidToRequest = 1000L;
+		String dpidToRequestStr = HexString.toHexString(dpidToRequest);
+		LoggingCallback callback = new LoggingCallback(2);
+
+		// Test before request control
+		Collection<Long> switches = registry.getSwitchesControlledByController(controllerId);
+		assertNotNull(switches);
+		assertFalse(switches.contains(dpidToRequestStr));
+
+		registry.requestControl(dpidToRequest, callback);
+		callback.waitForRegistration();
+
+		// Test after take control
+		switches = registry.getSwitchesControlledByController(controllerId);
+		assertNotNull(switches);
+		assertTrue(switches.contains(dpidToRequestStr));
+		int count = 0;
+		for(Long dpid : switches) {
+			if((long)dpid == dpidToRequest) {
+				++count;
+			}
+		}
+		assertEquals(1, count);
+		
+		registry.releaseControl(dpidToRequest);
+		callback.waitUntilCalled();
+
+		// Test after release control
+		switches = registry.getSwitchesControlledByController(controllerId);
+		assertNotNull(switches);
+		assertFalse(switches.contains(dpidToRequestStr));
+	}
+
+	/**
+	 * Test if {@link StandaloneRegistry#allocateUniqueIdBlock()} returns appropriate object.
+	 * Get bulk of IdBlocks and check if they do have unique range of IDs.
+	 */
+	@Test
+	public void testAllocateUniqueIdBlock() {
+		// Number of blocks to be verified that any of them has unique block
+		final int NUM_BLOCKS = 100;
+		ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
+		
+		for(int i = 0; i < NUM_BLOCKS; ++i) {
+			blocks.add(registry.allocateUniqueIdBlock());
+		}
+		
+		for(int i = 0; i < NUM_BLOCKS; ++i) {
+			IdBlock block1 = blocks.get(i);
+			for(int j = i + 1; j < NUM_BLOCKS; ++j) {
+				IdBlock block2 = blocks.get(j);
+				IdBlock lower,higher;
+				
+				if(block1.getStart() < block2.getStart()) {
+					lower = block1;
+					higher = block2;
+				} else {
+					lower = block2;
+					higher = block1;
+				}
+				
+				assertTrue(lower.getSize() > 0L);
+				assertTrue(higher.getSize() > 0L);
+				assertTrue(lower.getEnd() < higher.getStart());
+			}
+		}
+	}
+}
diff --git a/src/test/java/net/onrc/onos/registry/controller/ZookeeperRegistryTest.java b/src/test/java/net/onrc/onos/registry/controller/ZookeeperRegistryTest.java
new file mode 100644
index 0000000..3314ad2
--- /dev/null
+++ b/src/test/java/net/onrc/onos/registry/controller/ZookeeperRegistryTest.java
@@ -0,0 +1,597 @@
+package net.onrc.onos.registry.controller;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import net.floodlightcontroller.core.module.FloodlightModuleContext;
+import net.floodlightcontroller.test.FloodlightTestCase;
+import net.onrc.onos.registry.controller.StandaloneRegistryTest.LoggingCallback;
+import net.onrc.onos.registry.controller.ZookeeperRegistry.SwitchLeaderListener;
+
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openflow.util.HexString;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import com.netflix.curator.RetryPolicy;
+import com.netflix.curator.framework.CuratorFramework;
+import com.netflix.curator.framework.CuratorFrameworkFactory;
+import com.netflix.curator.framework.listen.ListenerContainer;
+import com.netflix.curator.framework.recipes.atomic.AtomicValue;
+import com.netflix.curator.framework.recipes.atomic.DistributedAtomicLong;
+import com.netflix.curator.framework.recipes.cache.ChildData;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCacheEvent;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCacheListener;
+import com.netflix.curator.framework.recipes.cache.PathChildrenCache.StartMode;
+import com.netflix.curator.framework.recipes.leader.LeaderLatch;
+import com.netflix.curator.x.discovery.ServiceCache;
+import com.netflix.curator.x.discovery.ServiceCacheBuilder;
+import com.netflix.curator.x.discovery.ServiceDiscovery;
+import com.netflix.curator.x.discovery.ServiceDiscoveryBuilder;
+import com.netflix.curator.x.discovery.ServiceInstance;
+
+/**
+ * Unit test for {@link ZookeeperRegistry}.
+ * NOTE: {@link FloodlightTestCase} conflicts with PowerMock. If FloodLight-related methods need to be tested,
+ *       implement another test class to test them.
+ * @author Naoki Shiota
+ *
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ZookeeperRegistry.class, CuratorFramework.class, CuratorFrameworkFactory.class,
+	ServiceDiscoveryBuilder.class, ServiceDiscovery.class, ServiceCache.class, PathChildrenCache.class,
+	ZookeeperRegistry.SwitchPathCacheListener.class})
+public class ZookeeperRegistryTest extends FloodlightTestCase {
+	private final static Long ID_BLOCK_SIZE = 0x100000000L;
+	
+	protected ZookeeperRegistry registry;
+	protected CuratorFramework client;
+	
+	protected PathChildrenCacheListener pathChildrenCacheListener;
+	protected final String CONTROLLER_ID = "controller2013";
+
+	/**
+	 * Initialize {@link ZookeeperRegistry} Object and inject initial value with {@link ZookeeperRegistry#init(FloodlightModuleContext)} method.
+	 * This setup code also tests {@link ZookeeperRegistry#init(FloodlightModuleContext)} method itself.
+	 */
+	@Before
+	public void setUp() throws Exception {
+		super.setUp();
+		
+		pathChildrenCacheListener = null;
+		
+		// Mock of CuratorFramework
+		client = createCuratorFrameworkMock();
+		
+		// Mock of CuratorFrameworkFactory
+		PowerMock.mockStatic(CuratorFrameworkFactory.class);
+		EasyMock.expect(CuratorFrameworkFactory.newClient((String)EasyMock.anyObject(),
+				EasyMock.anyInt(), EasyMock.anyInt(), (RetryPolicy)EasyMock.anyObject())).andReturn(client);
+		PowerMock.replay(CuratorFrameworkFactory.class);
+
+		FloodlightModuleContext fmc = new FloodlightModuleContext();
+		registry = new ZookeeperRegistry();
+		fmc.addService(ZookeeperRegistry.class, registry);
+		
+		registry.init(fmc);
+		
+		PowerMock.verify(client, CuratorFrameworkFactory.class);
+	}
+
+	/**
+	 * Clean up member variables (empty for now).
+	 */
+	@After
+	public void tearDown() throws Exception {
+		super.tearDown();
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#registerController(String)} method can go through without exception.
+	 * (Exceptions are usually out of test target, but {@link ZookeeperRegistry#registerController(String)} throws an exception in case of invalid registration.)
+	 */
+	@Test
+	public void testRegisterController() {
+		String controllerIdToRegister = "controller2013";
+		
+		try {
+			registry.registerController(controllerIdToRegister);
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#getControllerId()} correctly returns registered ID.
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetControllerId() throws Exception {
+		String controllerIdToRegister = "controller1";
+		
+		// try before controller is registered
+		String controllerId = registry.getControllerId();
+		assertNull(controllerId);
+		
+		// register
+		registry.registerController(controllerIdToRegister);
+	
+		// call getControllerId and verify
+		controllerId = registry.getControllerId();
+		assertNotNull(controllerId);
+		assertEquals(controllerIdToRegister, controllerId);
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#getAllControllers()} returns all controllers.
+	 * Controllers to be returned are injected while setup. See {@link ZookeeperRegistryTest#createCuratorFrameworkMock()}
+	 * to what controllers are injected using mock {@link ServiceCache}.
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetAllControllers() throws Exception {
+		String controllerIdRegistered = "controller1";
+		String controllerIdNotRegistered = "controller2013";
+
+		try {
+			Collection<String> ctrls = registry.getAllControllers();
+			assertTrue(ctrls.contains(controllerIdRegistered));
+			assertFalse(ctrls.contains(controllerIdNotRegistered));
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
+	 * correctly take control of specific switch. Because {@link ZookeeperRegistry#requestControl(long, net.onrc.onos.registry.controller.IControllerRegistryService.ControlChangeCallback)}
+	 * doesn't return values, inject mock {@link LeaderLatch} object and verify latch is correctly set up.
+	 * @throws Exception
+	 */
+	@Test
+	public void testRequestControl() throws Exception {
+		// Mock LeaderLatch
+		LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
+		latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
+		EasyMock.expectLastCall().once();
+		latch.start();
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(latch);
+		
+		PowerMock.expectNew(LeaderLatch.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
+				.andReturn(latch).once();
+		PowerMock.replay(LeaderLatch.class);
+		
+		String controllerId = "controller2013";
+		registry.registerController(controllerId);
+
+		LoggingCallback callback = new LoggingCallback(1);
+		long dpidToRequest = 2000L;
+
+		try {
+			registry.requestControl(dpidToRequest, callback);
+		} catch (RegistryException e) {
+			e.printStackTrace();
+			fail(e.getMessage());
+		}
+		
+		EasyMock.verify(latch);
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#releaseControl(long)} correctly release control of specific switch.
+	 * Because {@link ZookeeperRegistry#releaseControl(long)} doesn't return values, inject mock
+	 * {@link LeaderLatch} object and verify latch is correctly set up.
+	 * @throws Exception
+	 */
+	@Test
+	public void testReleaseControl() throws Exception {
+		// Mock of LeaderLatch
+		LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
+		latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
+		EasyMock.expectLastCall().once();
+		latch.start();
+		EasyMock.expectLastCall().once();
+		latch.removeAllListeners();
+		EasyMock.expectLastCall().once();
+		latch.close();
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(latch);
+		
+		PowerMock.expectNew(LeaderLatch.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
+				.andReturn(latch).once();
+		PowerMock.replay(LeaderLatch.class);
+		
+		String controllerId = "controller2013";
+		registry.registerController(controllerId);
+		
+		long dpidToRequest = 2000L;
+		LoggingCallback callback = new LoggingCallback(1);
+		
+		registry.requestControl(dpidToRequest, callback);
+		registry.releaseControl(dpidToRequest);
+		
+		EasyMock.verify(latch);
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#hasControl(long)} returns correct status whether controller has control of specific switch.
+	 * @throws Exception
+	 */
+	@Test
+	public void testHasControl() throws Exception {
+		// Mock of LeaderLatch
+		LeaderLatch latch = EasyMock.createMock(LeaderLatch.class);
+		latch.addListener(EasyMock.anyObject(SwitchLeaderListener.class));
+		EasyMock.expectLastCall().once();
+		latch.start();
+		EasyMock.expectLastCall().once();
+		EasyMock.expect(latch.hasLeadership()).andReturn(true).anyTimes();
+		latch.removeAllListeners();
+		EasyMock.expectLastCall().once();
+		latch.close();
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(latch);
+		
+		PowerMock.expectNew(LeaderLatch.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(String.class))
+				.andReturn(latch);
+		PowerMock.replay(LeaderLatch.class);
+		
+		String controllerId = "controller2013";
+		registry.registerController(controllerId);
+		
+		long dpidToRequest = 2000L;
+		LoggingCallback callback = new LoggingCallback(2);
+		
+		// Test before request control
+		assertFalse(registry.hasControl(dpidToRequest));
+
+		registry.requestControl(dpidToRequest, callback);
+		
+		// Test after request control
+		assertTrue(registry.hasControl(dpidToRequest));
+		
+		registry.releaseControl(dpidToRequest);
+		
+		// Test after release control
+		assertFalse(registry.hasControl(dpidToRequest));
+		
+		EasyMock.verify(latch);
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#getControllerForSwitch(long)} correctly returns controller ID of specific switch.
+	 * Relation between controllers and switches are defined by {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
+	 * @throws Throwable
+	 */
+	@Test
+	public void testGetControllerForSwitch() throws Throwable {
+		long dpidRegistered = 1000L;
+		long dpidNotRegistered = 2000L;
+		
+		setPathChildrenCache();
+		
+		String controllerForSw = registry.getControllerForSwitch(dpidRegistered);
+		assertEquals("controller1",controllerForSw);
+
+		controllerForSw = registry.getControllerForSwitch(dpidNotRegistered);
+		assertEquals(null, controllerForSw);
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#getSwitchesControlledByController(String)} returns correct list of
+	 * switches controlled by a controller.
+	 * @throws Exception
+	 */
+	// TODO: Test after getSwitchesControlledByController() is implemented.
+	@Ignore @Test
+	public void testGetSwitchesControlledByController() throws Exception {
+		String controllerIdRegistered = "controller1";
+		String dpidRegistered = HexString.toHexString(1000L);
+		String controllerIdNotRegistered = CONTROLLER_ID;
+		
+		Collection<Long> switches = registry.getSwitchesControlledByController(controllerIdRegistered);
+		assertNotNull(switches);
+		assertTrue(switches.contains(dpidRegistered));
+
+		switches = registry.getSwitchesControlledByController(controllerIdNotRegistered);
+		assertNotNull(switches);
+		assertEquals(0, switches.size());
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#getAllSwitches()} returns correct list of all switches.
+	 * Switches are injected in {@link ZookeeperRegistryTest#setPathChildrenCache()} function.
+	 * @throws Exception
+	 */
+	@Test
+	public void testGetAllSwitches() throws Exception {
+		String [] dpids = {
+				HexString.toHexString(1000L),
+				HexString.toHexString(1001L),
+				HexString.toHexString(1002L),
+		};
+		
+		setPathChildrenCache();
+
+		Map<String, List<ControllerRegistryEntry>> switches = registry.getAllSwitches();
+		assertNotNull(switches);
+		assertEquals(dpids.length, switches.size());
+		for(String dpid : dpids) {
+			assertTrue(switches.keySet().contains(dpid));
+		}
+	}
+
+	/**
+	 * Test if {@link ZookeeperRegistry#allocateUniqueIdBlock()} can assign IdBlock without duplication.
+	 */
+	@Test
+	public void testAllocateUniqueIdBlock() {
+		// Number of blocks to be verified that any of them has unique block
+		final int NUM_BLOCKS = 100;
+		ArrayList<IdBlock> blocks = new ArrayList<IdBlock>(NUM_BLOCKS);
+		
+		for(int i = 0; i < NUM_BLOCKS; ++i) {
+			IdBlock block = registry.allocateUniqueIdBlock();
+			assertNotNull(block);
+			blocks.add(block);
+		}
+		
+		for(int i = 0; i < NUM_BLOCKS; ++i) {
+			IdBlock block1 = blocks.get(i);
+			for(int j = i + 1; j < NUM_BLOCKS; ++j) {
+				IdBlock block2 = blocks.get(j);
+				IdBlock lower,higher;
+				
+				if(block1.getStart() < block2.getStart()) {
+					lower = block1;
+					higher = block2;
+				} else {
+					lower = block2;
+					higher = block1;
+				}
+				
+				assertTrue(lower.getSize() > 0L);
+				assertTrue(higher.getSize() > 0L);
+				assertTrue(lower.getEnd() <= higher.getStart());
+			}
+		}
+	}
+	
+	
+	//-------------------------- Creation of mock objects --------------------------
+	/**
+	 * Create mock {@link CuratorFramework} object with initial value below.<br>
+	 *   [Ctrl ID]    : [DPID]<br>
+	 * controller1    :  1000<br>
+	 * controller2    :  1001<br>
+	 * controller2    :  1002<br>
+	 * controller2013 : nothing
+	 * @return Created mock object
+	 * @throws Exception
+	 */
+	@SuppressWarnings({ "serial", "unchecked" })
+	private CuratorFramework createCuratorFrameworkMock() throws Exception {
+		// Mock of AtomicValue
+		AtomicValue<Long> atomicValue = EasyMock.createMock(AtomicValue.class);
+		EasyMock.expect(atomicValue.succeeded()).andReturn(true).anyTimes();
+		EasyMock.expect(atomicValue.preValue()).andAnswer(new IAnswer<Long>() {
+			private long value = 0;
+			@Override
+			public Long answer() throws Throwable {
+				value += ID_BLOCK_SIZE;
+				return value;
+			}
+		}).anyTimes();
+		EasyMock.expect(atomicValue.postValue()).andAnswer(new IAnswer<Long>() {
+			private long value = ID_BLOCK_SIZE;
+			@Override
+			public Long answer() throws Throwable {
+				value += ID_BLOCK_SIZE;
+				return value;
+			}
+		}).anyTimes();
+		EasyMock.replay(atomicValue);
+		
+		// Mock DistributedAtomicLong
+		DistributedAtomicLong daLong = EasyMock.createMock(DistributedAtomicLong.class);
+		EasyMock.expect(daLong.add(EasyMock.anyLong())).andReturn(atomicValue).anyTimes();
+		EasyMock.replay(daLong);
+		PowerMock.expectNew(DistributedAtomicLong.class,
+				new Class<?> [] {CuratorFramework.class, String.class, RetryPolicy.class},
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyObject(RetryPolicy.class)).
+				andReturn(daLong).anyTimes();
+		PowerMock.replay(DistributedAtomicLong.class);
+		
+		// Mock ListenerContainer
+		ListenerContainer<PathChildrenCacheListener> listenerContainer = EasyMock.createMock(ListenerContainer.class);
+		listenerContainer.addListener(EasyMock.anyObject(PathChildrenCacheListener.class));
+		EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
+			@Override
+			public Object answer() throws Throwable {
+				pathChildrenCacheListener = (PathChildrenCacheListener)EasyMock.getCurrentArguments()[0];
+				return null;
+			}
+		}).once();
+		EasyMock.replay(listenerContainer);
+
+		// Mock PathChildrenCache
+		PathChildrenCache pathChildrenCacheMain = createPathChildrenCacheMock(CONTROLLER_ID, new String[] {"/switches"}, listenerContainer);
+		PathChildrenCache pathChildrenCache1 = createPathChildrenCacheMock("controller1", new String[] {HexString.toHexString(1000L)}, listenerContainer);
+		PathChildrenCache pathChildrenCache2 = createPathChildrenCacheMock("controller2", new String[] { 
+			HexString.toHexString(1001L), HexString.toHexString(1002L) },listenerContainer);
+		
+		// Mock PathChildrenCache constructor
+		PowerMock.expectNew(PathChildrenCache.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
+				andReturn(pathChildrenCacheMain).once();
+		PowerMock.expectNew(PathChildrenCache.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
+				andReturn(pathChildrenCache1).once();
+		PowerMock.expectNew(PathChildrenCache.class,
+				EasyMock.anyObject(CuratorFramework.class), EasyMock.anyObject(String.class), EasyMock.anyBoolean()).
+				andReturn(pathChildrenCache2).anyTimes();
+		PowerMock.replay(PathChildrenCache.class);
+		
+		// Mock ServiceCache
+		ServiceCache<ControllerService> serviceCache = EasyMock.createMock(ServiceCache.class);
+		serviceCache.start();
+		EasyMock.expectLastCall().once();
+		EasyMock.expect(serviceCache.getInstances()).andReturn(new ArrayList<ServiceInstance<ControllerService> > () {{
+			add(createServiceInstanceMock("controller1"));
+			add(createServiceInstanceMock("controller2"));
+		}}).anyTimes();
+		EasyMock.replay(serviceCache);
+		
+		// Mock ServiceCacheBuilder
+		ServiceCacheBuilder<ControllerService> serviceCacheBuilder = EasyMock.createMock(ServiceCacheBuilder.class);
+		EasyMock.expect(serviceCacheBuilder.name(EasyMock.anyObject(String.class))).andReturn(serviceCacheBuilder).once();
+		EasyMock.expect(serviceCacheBuilder.build()).andReturn(serviceCache).once();
+		EasyMock.replay(serviceCacheBuilder);
+
+		// Mock ServiceDiscovery
+		ServiceDiscovery<ControllerService> serviceDiscovery = EasyMock.createMock(ServiceDiscovery.class);
+		serviceDiscovery.start();
+		EasyMock.expectLastCall().once();
+		EasyMock.expect(serviceDiscovery.serviceCacheBuilder()).andReturn(serviceCacheBuilder).once();
+		serviceDiscovery.registerService(EasyMock.anyObject(ServiceInstance.class));
+		EasyMock.expectLastCall().once();
+		EasyMock.replay(serviceDiscovery);
+		
+		// Mock CuratorFramework
+		CuratorFramework client = EasyMock.createMock(CuratorFramework.class);
+		client.start();
+		EasyMock.expectLastCall().once();
+		EasyMock.expect(client.usingNamespace(EasyMock.anyObject(String.class))).andReturn(client);
+		EasyMock.replay(client);
+
+		// Mock ServiceDiscoveryBuilder
+		ServiceDiscoveryBuilder<ControllerService> builder = EasyMock.createMock(ServiceDiscoveryBuilder.class);
+		EasyMock.expect(builder.client(client)).andReturn(builder).once();
+		EasyMock.expect(builder.basePath(EasyMock.anyObject(String.class))).andReturn(builder);
+		EasyMock.expect(builder.build()).andReturn(serviceDiscovery);
+		EasyMock.replay(builder);
+		
+		PowerMock.mockStatic(ServiceDiscoveryBuilder.class);
+		EasyMock.expect(ServiceDiscoveryBuilder.builder(ControllerService.class)).andReturn(builder).once();
+		PowerMock.replay(ServiceDiscoveryBuilder.class);
+
+		return client;
+	}
+	
+	/**
+	 * Create mock {@link ServiceInstance} object using given controller ID.
+	 * @param controllerId Controller ID to represent instance's payload (ControllerService).
+	 * @return Mock ServiceInstance object
+	 */
+	private ServiceInstance<ControllerService> createServiceInstanceMock(String controllerId) {
+		ControllerService controllerService = EasyMock.createMock(ControllerService.class);
+		EasyMock.expect(controllerService.getControllerId()).andReturn(controllerId).anyTimes();
+		EasyMock.replay(controllerService);
+		
+		@SuppressWarnings("unchecked")
+		ServiceInstance<ControllerService> serviceInstance = EasyMock.createMock(ServiceInstance.class);
+		EasyMock.expect(serviceInstance.getPayload()).andReturn(controllerService).anyTimes();
+		EasyMock.replay(serviceInstance);
+
+		return serviceInstance;
+	}
+	
+	/**
+	 * Create mock {@link PathChildrenCache} using given controller ID and DPIDs.
+	 * @param controllerId Controller ID to represent current data.
+	 * @param paths List of HexString indicating switch's DPID.
+	 * @param listener Callback object to be set as Listenable.
+	 * @return Mock PathChildrenCache object
+	 * @throws Exception
+	 */
+	private PathChildrenCache createPathChildrenCacheMock(final String controllerId, final String [] paths,
+			ListenerContainer<PathChildrenCacheListener> listener) throws Exception {
+		PathChildrenCache pathChildrenCache = EasyMock.createMock(PathChildrenCache.class);
+		
+		EasyMock.expect(pathChildrenCache.getListenable()).andReturn(listener).anyTimes();
+		
+		pathChildrenCache.start(EasyMock.anyObject(StartMode.class));
+		EasyMock.expectLastCall().anyTimes();
+		
+		List<ChildData> childs = new ArrayList<ChildData>();
+		for(String path : paths) {
+			childs.add(createChildDataMockForCurrentData(controllerId,path));
+		}
+		EasyMock.expect(pathChildrenCache.getCurrentData()).andReturn(childs).anyTimes();
+		
+		pathChildrenCache.rebuild();
+		EasyMock.expectLastCall().anyTimes();
+		
+		EasyMock.replay(pathChildrenCache);
+
+		return pathChildrenCache;
+	}
+	
+	/**
+	 * Create mock {@link ChildData} for {@link PathChildrenCache#getCurrentData()} return value.
+	 * This object need to include 'sequence number' in tail of path string. ("-0" means 0th sequence)
+	 * @param controllerId Controller ID
+	 * @param path HexString indicating switch's DPID
+	 * @return Mock ChildData object
+	 */
+	private ChildData createChildDataMockForCurrentData(String controllerId, String path) {
+		ChildData data = EasyMock.createMock(ChildData.class);
+		EasyMock.expect(data.getPath()).andReturn(path + "-0").anyTimes();
+		EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
+		EasyMock.replay(data);
+		
+		return data;
+	}
+
+	/**
+	 * Inject relations between controllers and switches using callback object.
+	 * @throws Exception
+	 */
+	private void setPathChildrenCache() throws Exception {
+		pathChildrenCacheListener.childEvent(client,
+				createChildrenCacheEventMock("controller1", HexString.toHexString(1000L), PathChildrenCacheEvent.Type.CHILD_ADDED));
+		pathChildrenCacheListener.childEvent(client,
+				createChildrenCacheEventMock("controller2", HexString.toHexString(1001L), PathChildrenCacheEvent.Type.CHILD_ADDED));
+		pathChildrenCacheListener.childEvent(client,
+				createChildrenCacheEventMock("controller2", HexString.toHexString(1002L), PathChildrenCacheEvent.Type.CHILD_ADDED));
+	}
+
+	/**
+	 * Create mock {@link PathChildrenCacheEvent} object using given controller ID and DPID.
+	 * @param controllerId Controller ID.
+	 * @param path HexString of DPID.
+	 * @param type Event type to be set to mock object.
+	 * @return Mock PathChildrenCacheEvent object
+	 */
+	private PathChildrenCacheEvent createChildrenCacheEventMock(String controllerId, String path,
+			PathChildrenCacheEvent.Type type) {
+		PathChildrenCacheEvent event = EasyMock.createMock(PathChildrenCacheEvent.class);
+		ChildData data = EasyMock.createMock(ChildData.class);
+		
+		EasyMock.expect(data.getPath()).andReturn(path).anyTimes();
+		EasyMock.expect(data.getData()).andReturn(controllerId.getBytes()).anyTimes();
+		EasyMock.replay(data);
+		
+		EasyMock.expect(event.getType()).andReturn(type).anyTimes();
+		EasyMock.expect(event.getData()).andReturn(data).anyTimes();
+		EasyMock.replay(event);
+		
+		return event;
+	}
+}
diff --git a/start-cassandra.sh b/start-cassandra.sh
index c06fb14..426fa60 100755
--- a/start-cassandra.sh
+++ b/start-cassandra.sh
@@ -1,10 +1,10 @@
 #!/bin/bash
 
 # Set paths
-FL_HOME=`dirname $0`
-CASSANDRA_DIR=${HOME}/apache-cassandra-1.1.4
-LOGDIR=${HOME}/ONOS/onos-logs
-CASSANDRA_LOG=$LOGDIR/cassandara.`hostname`.log
+ONOS_HOME=`dirname $0`
+CASSANDRA_DIR=${HOME}/apache-cassandra-1.2.4
+LOGDIR=${ONOS_HOME}/ONOS/onos-logs
+CASSANDRA_LOG=${LOGDIR}/cassandara.`hostname`.log
 
 function lotate {
     logfile=$1
@@ -30,6 +30,11 @@
 
   # Run cassandra 
   echo "Starting cassandra"
+#  echo "[WARNING] This script copies conf/cassandra.yaml to $CASSANDRA_DIR/conf/cassandra.yaml (overwrites)"
+#  echo "original cassandra.yaml was backed up as cassandra.yaml.backup"
+#  id=`hostid`
+#  cp ${CASSANDRA_DIR}/conf/cassandra.yaml $CASSANDRA_DIR/conf/cassandra.yaml.backup
+#  cp ${ONOS_HOME}/conf/cassandra.yaml.${id} $CASSANDRA_DIR/conf
   $CASSANDRA_DIR/bin/cassandra > $CASSANDRA_LOG 2>&1 
 }
 
@@ -56,7 +61,7 @@
 case "$1" in
   start)
     deldb
-    cp $FL_HOME/cassandra.titan /tmp
+    cp $ONOS_HOME/conf/cassandra.titan /tmp
     stop
     start 
     ;;
diff --git a/start-onos-embedded.sh b/start-onos-embedded.sh
new file mode 100755
index 0000000..dac0331
--- /dev/null
+++ b/start-onos-embedded.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+
+# Set paths
+if [ -z "${ONOS_HOME}" ]; then
+        ONOS_HOME=`dirname $0`
+fi
+ONOS_LOGBACK="${ONOS_HOME}/logback.xml"
+LOGDIR=${ONOS_HOME}/onos-logs
+ONOS_LOG="${LOGDIR}/onos.`hostname`.log"
+PCAP_LOG="${LOGDIR}/onos.`hostname`.pcap"
+LOGS="$ONOS_LOG $PCAP_LOG"
+
+# Set JVM options
+JVM_OPTS=""
+JVM_OPTS="$JVM_OPTS -server -d64"
+JVM_OPTS="$JVM_OPTS -Xmx2g -Xms2g -Xmn800m"
+#JVM_OPTS="$JVM_OPTS -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
+JVM_OPTS="$JVM_OPTS -XX:+UseConcMarkSweepGC -XX:+UseAdaptiveSizePolicy -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
+JVM_OPTS="$JVM_OPTS -XX:MaxInlineSize=8192 -XX:FreqInlineSize=8192"
+JVM_OPTS="$JVM_OPTS -XX:CompileThreshold=1500 -XX:PreBlockSpin=8 \
+		-XX:+UseThreadPriorities \
+		-XX:ThreadPriorityPolicy=42 \
+                 -XX:+UseCompressedOops \
+		-Dcassandra.compaction.priority=1 \
+            -Dcom.sun.management.jmxremote.port=7199 \
+              -Dcom.sun.management.jmxremote.ssl=false \
+              -Dcom.sun.management.jmxremote.authenticate=false"
+
+#JVM_OPTS="$JVM_OPTS -Dpython.security.respectJavaAccessibility=false"
+
+# Set Main class to start ONOS core
+MAIN_CLASS="net.onrc.onos.ofcontroller.core.Main"
+
+if [ -z "${MVN}" ]; then
+    MVN="mvn"
+fi
+#<logger name="net.floodlightcontroller.linkdiscovery.internal" level="TRACE"/>
+#<appender-ref ref="STDOUT" />
+
+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 start {
+  if [ ! -d ${LOGDIR} ]; then
+    mkdir -p ${LOGDIR}
+  fi
+  # Backup log files
+  for log in ${LOGS}; do
+    echo "rotate log: $log"
+    if [ -f ${log} ]; then
+      lotate ${log}
+    fi
+  done
+
+# Create a logback file if required
+  cat <<EOF_LOGBACK >${ONOS_LOGBACK}
+<configuration scan="true" debug="true">
+<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+<encoder>
+<pattern>%level [%logger:%thread] %msg%n</pattern>
+</encoder>
+</appender>
+
+<appender name="FILE" class="ch.qos.logback.core.FileAppender">
+<file>${ONOS_LOG}</file>
+<encoder>
+<pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
+</encoder>
+</appender>
+
+<logger name="org" level="WARN"/>
+<logger name="LogService" level="WARN"/> <!-- Restlet access logging -->
+<logger name="net.floodlightcontroller.logging" level="WARN"/>
+
+<root level="DEBUG">
+<appender-ref ref="FILE" />
+</root>
+</configuration>
+EOF_LOGBACK
+
+  # Run floodlight
+  echo "Starting ONOS controller ..."
+  echo 
+
+  # XXX MVN has to run at the project top dir..
+  cd ${ONOS_HOME}
+  ${MVN} exec:exec -Dexec.executable="java" -Dexec.args="${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ${ONOS_HOME}/conf/onos-embedded.properties" > ${LOGDIR}/onos.stdout 2>${LOGDIR}/onos.stderr &
+
+  echo "Waiting for ONOS to start..."
+  COUNT=0
+  ESTATE=0
+  while [ "$COUNT" != "10" ]; do
+    COUNT=$((COUNT + 1))
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
+    if [ "$n" -ge "1" ]; then
+      exit 0
+    fi
+    sleep $COUNT
+  done
+  echo "Timed out"
+  exit 1
+
+  sudo -b /usr/sbin/tcpdump -n -i eth0 -s0 -w ${PCAP_LOG} 'tcp port 6633' > /dev/null  2>&1
+}
+
+function stop {
+  # Kill the existing processes
+  flpid=`jps -l |grep ${MAIN_CLASS} | awk '{print $1}'`
+  tdpid=`ps -edalf |grep tcpdump |grep ${PCAP_LOG} | awk '{print $4}'`
+  pids="$flpid $tdpid"
+  for p in ${pids}; do
+    if [ x$p != "x" ]; then
+      kill -KILL $p
+      echo "Killed existing process (pid: $p)"
+    fi
+  done
+}
+
+function deldb {
+   # Delete the cassandra data
+   if [ -d "/tmp/cassandra" ]; then
+      rm -rf /tmp/cassandra/*
+   fi
+}
+
+case "$1" in
+  start)
+    stop
+    start 
+    ;;
+  startifdown)
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
+    if [ $n == 0 ]; then
+      start
+    else 
+      echo "$n instance of onos running"
+    fi
+    ;;
+  stop)
+    stop
+    ;;
+  deldb)
+    deldb
+    ;;
+  status)
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
+    echo "$n instance of onos running"
+    ;;
+  *)
+    echo "Usage: $0 {start|stop|restart|status|startifdown}"
+    exit 1
+esac
diff --git a/start-onos.sh b/start-onos.sh
index 77accd0..a35d181 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -1,28 +1,46 @@
 #!/bin/bash
 
 # Set paths
-FL_HOME=`dirname $0`
-FL_JAR="${FL_HOME}/target/floodlight.jar"
-FL_ONLY_JAR="${FL_HOME}/target/floodlight-only.jar"
-FL_LOGBACK="${FL_HOME}/logback.xml"
-LOGDIR=${FL_HOME}/onos-logs
-FL_LOG="${LOGDIR}/onos.`hostname`.log"
+if [ -z "${ONOS_HOME}" ]; then
+        ONOS_HOME=`dirname $0`
+fi
+
+## Because the script change dir to $ONOS_HOME, we can set ONOS_LOGBACK and LOGDIR relative to $ONOS_HOME
+#ONOS_LOGBACK="${ONOS_HOME}/logback.`hostname`.xml"
+#LOGDIR=${ONOS_HOME}/onos-logs
+ONOS_LOGBACK="./logback.`hostname`.xml"
+LOGDIR=./onos-logs
+ONOS_LOG="${LOGDIR}/onos.`hostname`.log"
 PCAP_LOG="${LOGDIR}/onos.`hostname`.pcap"
-LOGS="$FL_LOG $PCAP_LOG"
+LOGS="$ONOS_LOG $PCAP_LOG"
 
 # Set JVM options
 JVM_OPTS=""
+## If you want JaCoCo Code Coverage reports... uncomment line below
+JVM_OPTS="$JVM_OPTS -javaagent:${ONOS_HOME}/lib/jacocoagent.jar=dumponexit=true,output=file,destfile=${LOGDIR}/jacoco.exec"
 JVM_OPTS="$JVM_OPTS -server -d64"
-JVM_OPTS="$JVM_OPTS -Xmx2g -Xms2g -Xmn800m"
-JVM_OPTS="$JVM_OPTS -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
+#JVM_OPTS="$JVM_OPTS -Xmx2g -Xms2g -Xmn800m"
+JVM_OPTS="$JVM_OPTS -Xmx1g -Xms1g -Xmn800m"
+#JVM_OPTS="$JVM_OPTS -XX:+UseParallelGC -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
+JVM_OPTS="$JVM_OPTS -XX:+UseConcMarkSweepGC -XX:+UseAdaptiveSizePolicy -XX:+AggressiveOpts -XX:+UseFastAccessorMethods"
 JVM_OPTS="$JVM_OPTS -XX:MaxInlineSize=8192 -XX:FreqInlineSize=8192"
 JVM_OPTS="$JVM_OPTS -XX:CompileThreshold=1500 -XX:PreBlockSpin=8"
+JVM_OPTS="$JVM_OPTS -XX:OnError=crash-logger" ;# For dumping core
 #JVM_OPTS="$JVM_OPTS -Dpython.security.respectJavaAccessibility=false"
+JVM_OPTS="$JVM_OPTS -XX:CompileThreshold=1500 -XX:PreBlockSpin=8 \
+		-XX:+UseThreadPriorities \
+		-XX:ThreadPriorityPolicy=42 \
+                 -XX:+UseCompressedOops \
+            -Dcom.sun.management.jmxremote.port=7189 \
+              -Dcom.sun.management.jmxremote.ssl=false \
+              -Dcom.sun.management.jmxremote.authenticate=false"
 
-# Set classpath to include titan libs
-#CLASSPATH=`echo ${FL_HOME}/lib/*.jar ${FL_HOME}/lib/titan/*.jar | sed 's/ /:/g'`
-CLASSPATH="${FL_ONLY_JAR}:${FL_HOME}/lib/*:${FL_HOME}/lib/titan/*"
-MAIN_CLASS="net.floodlightcontroller.core.Main"
+# Set ONOS core main class
+MAIN_CLASS="net.onrc.onos.ofcontroller.core.Main"
+
+if [ -z "${MVN}" ]; then
+    MVN="mvn -o"
+fi
 
 #<logger name="net.floodlightcontroller.linkdiscovery.internal" level="TRACE"/>
 #<appender-ref ref="STDOUT" />
@@ -53,7 +71,7 @@
   done
 
 # Create a logback file if required
-  cat <<EOF_LOGBACK >${FL_LOGBACK}
+  cat <<EOF_LOGBACK >${ONOS_LOGBACK}
 <configuration scan="true" debug="true">
 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
 <encoder>
@@ -62,7 +80,7 @@
 </appender>
 
 <appender name="FILE" class="ch.qos.logback.core.FileAppender">
-<file>${FL_LOG}</file>
+<file>${ONOS_LOG}</file>
 <encoder>
 <pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n</pattern>
 </encoder>
@@ -81,11 +99,33 @@
   # Run floodlight
   echo "Starting ONOS controller ..."
   echo 
-  #java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -jar ${FL_JAR} -cf ${FL_HOME}/onos.properties > /dev/null 2>&1 &
-  java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -cp ${CLASSPATH} ${MAIN_CLASS} -cf ${FL_HOME}/onos.properties > /dev/null 2>&1 &
 
+  # XXX : MVN has to run at the project top dir 
+  echo $ONOS_HOME
+  cd ${ONOS_HOME}
+  pwd 
+  echo "${MVN} exec:exec -Dexec.executable=\"java\" -Dexec.args=\"${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ./conf/onos.properties\""
 
-#  echo "java ${JVM_OPTS} -Dlogback.configurationFile=${FL_LOGBACK} -jar ${FL_JAR} -cf ./onos.properties > /dev/null 2>&1 &"
+  ${MVN} exec:exec -Dexec.executable="java" -Dexec.args="${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ./conf/onos.properties" > ${LOGDIR}/onos.`hostname`.stdout 2>${LOGDIR}/onos.`hostname`.stderr &
+
+  echo "Waiting for ONOS to start..."
+  COUNT=0
+  ESTATE=0
+  while [ "$COUNT" != "10" ]; do
+    echo -n "."
+    sleep 1
+#    COUNT=$((COUNT + 1))
+#    sleep $COUNT
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
+    if [ "$n" -ge "1" ]; then
+      echo ""
+      exit 0
+    fi
+  done
+  echo "Timed out"
+  exit 1
+
+#  echo "java ${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -jar ${ONOS_JAR} -cf ./onos.properties > /dev/null 2>&1 &"
 #  sudo -b /usr/sbin/tcpdump -n -i eth0 -s0 -w ${PCAP_LOG} 'tcp port 6633' > /dev/null  2>&1
 }
 
@@ -96,19 +136,12 @@
   pids="$flpid $tdpid"
   for p in ${pids}; do
     if [ x$p != "x" ]; then
-      kill -KILL $p
-      echo "Killed existing prosess (pid: $p)"
+      kill -TERM $p
+      echo "Killed existing process (pid: $p)"
     fi
   done
 }
 
-function deldb {
-   # Delete the berkeley db database
-   if [ -d "/tmp/cassandra.titan" ]; then
-      rm -rf /tmp/cassandra.titan
-      mkdir /tmp/cassandra.titan
-   fi
-}
 function check_db {
    if [ -d "/tmp/cassandra.titan" ]; then
       echo "Cassandra is running on local berkely db. Exitting"
@@ -128,7 +161,7 @@
     start 
     ;;
   startifdown)
-    n=`jps -l |grep "net.floodlightcontroller.core.Main" | wc -l`
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
     if [ $n == 0 ]; then
       start
     else 
@@ -138,11 +171,8 @@
   stop)
     stop
     ;;
-  deldb)
-    deldb
-    ;;
   status)
-    n=`jps -l |grep "net.floodlightcontroller.core.Main" | wc -l`
+    n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
     echo "$n instance of onos running"
     ;;
   *)
diff --git a/start-zk.sh b/start-zk.sh
new file mode 100755
index 0000000..0853a96
--- /dev/null
+++ b/start-zk.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Set paths
+
+ONOS_HOME=`dirname $0`
+ZK_DIR=${HOME}/zookeeper-3.4.5
+#ZK_CONF=${ONOS_HOME}/conf/zoo.cfg
+
+function start {
+  # Run Zookeeper with our configuration
+  echo "Starting Zookeeper"
+#  echo "[WARNING] This script copies conf/zoo.cfg to $ZK_DIR/conf/zoo.cfg (overwrites)"
+#  echo "original zoo.cfg was backed up as zoo.cfg.backup"
+#  if [ $ZK_DIR/conf/zoo.cfg ]; then
+#    cp $ZK_DIR/conf/zoo.cfg $ZK_DIR/conf/zoo.cfg.backup
+#  fi
+#  hostid > /var/lib/zookeeper/myid
+#  cp $ZK_CONF $ZK_DIR/conf
+#  echo "cp $ZK_CONF $ZK_DIR/conf"
+  $ZK_DIR/bin/zkServer.sh start
+}
+
+function stop {
+  # Kill the existing processes
+  pids=`jps -l | grep org.apache.zookeeper.server | awk '{print $1}'`
+  for p in ${pids}; do
+    if [ x$p != "x" ]; then
+      kill -KILL $p
+      echo "Killed existing prosess (pid: $p)"
+    fi
+  done
+}
+function status {
+  $ZK_DIR/bin/zkServer.sh status
+}
+
+case "$1" in
+  start)
+    start 
+    ;;
+  stop)
+    stop
+    ;;
+  status)
+    status
+    ;;
+  restart)
+    stop
+    start
+    ;;
+  *)
+    echo "Usage: $0 {start|stop|restart|status}"
+    exit 1
+esac
diff --git a/titan/gremlin.sh b/titan/gremlin.sh
index c7155ac..e4895b0 100755
--- a/titan/gremlin.sh
+++ b/titan/gremlin.sh
@@ -1,6 +1,12 @@
 #!/bin/bash
 
-CP=$( echo `dirname $0`/../lib/*.jar `dirname $0`/../lib/titan/*.jar . | sed 's/ /:/g')
+if [ -z "${MVN}" ]; then
+    MVN="mvn"
+fi
+
+ONOS_DIR="`dirname $0`/.."
+#CP=$( echo `dirname $0`/../lib/*.jar `dirname $0`/../lib/titan/*.jar . | sed 's/ /:/g')
+CP=`${MVN} -f ${ONOS_DIR}/pom.xml dependency:build-classpath -Dmdep.outputFile=/dev/stdout -l /dev/stderr`
 
 # Find Java 
 if [ "$JAVA_HOME" = "" ] ; then
diff --git a/titan/schema/dbapi-testdata.graphml b/titan/schema/dbapi-testdata.graphml
index fbf7e2b..952a62a 100644
--- a/titan/schema/dbapi-testdata.graphml
+++ b/titan/schema/dbapi-testdata.graphml
@@ -1 +1 @@
-<?xml version=\"1.0\" ?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\">    <key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"type\" for=\"node\" attr.name=\"type\" attr.type=\"string\"></key>    <key id=\"dpid\" for=\"node\" attr.name=\"dpid\" attr.type=\"string\"></key>    <key id=\"desc\" for=\"node\" attr.name=\"desc\" attr.type=\"string\"></key>    <key id=\"number\" for=\"node\" attr.name=\"number\" attr.type=\"int\"></key>    <key id=\"dl_addr\" for=\"node\" attr.name=\"dl_addr\" attr.type=\"string\"></key>    <key id=\"nw_addr\" for=\"node\" attr.name=\"nw_addr\" attr.type=\"string\"></key>    <key id=\"id\" for=\"edge\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"source\" for=\"edge\" attr.name=\"source\" attr.type=\"string\"></key>    <key id=\"target\" for=\"edge\" attr.name=\"target\" attr.type=\"string\"></key>    <key id=\"label\" for=\"edge\" attr.name=\"label\" attr.type=\"string\"></key>    <graph id=\"G\" edgedefault=\"directed\">        <node id=\"1\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:01</data>            <data key=\"desc\">OpenFlow Switch at SEA</data>        </node>        <node id=\"2\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:02</data>            <data key=\"desc\">OpenFlow Switch at LAX</data>        </node>        <node id=\"3\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:03</data>            <data key=\"desc\">OpenFlow Switch at CHI</data>        </node>        <node id=\"4\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:04</data>            <data key=\"desc\">OpenFlow Switch at IAH</data>        </node>        <node id=\"5\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:05</data>            <data key=\"desc\">OpenFlow Switch at NYC</data>        </node>        <node id=\"6\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:06</data>            <data key=\"desc\">OpenFlow Switch at ATL</data>        </node>        <node id=\"100\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at SEA Switch</data>        </node>        <node id=\"101\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at SEA Switch</data>        </node>        <node id=\"102\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at SEA Switch</data>        </node>        <node id=\"103\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at SEA Switch</data>        </node>        <node id=\"104\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at LAX Switch</data>        </node>        <node id=\"105\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at LAX Switch</data>        </node>        <node id=\"106\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at LAX Switch</data>        </node>        <node id=\"107\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at CHI Switch</data>        </node>        <node id=\"108\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at CHI Switch</data>        </node>        <node id=\"109\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at CHI Switch</data>        </node>        <node id=\"110\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at CHI Switch</data>        </node>        <node id=\"111\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at IAH Switch</data>        </node>        <node id=\"112\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at IAH Switch</data>        </node>        <node id=\"113\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at IAH Switch</data>        </node>        <node id=\"114\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at NYC Switch</data>        </node>        <node id=\"115\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at NYC Switch</data>        </node>        <node id=\"116\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at NYC Switch</data>        </node>        <node id=\"117\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at ATL Switch</data>        </node>        <node id=\"118\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at ATL Switch</data>        </node>        <node id=\"119\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at ATL Switch</data>        </node>        <node id=\"1000\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:73</data>            <data key=\"nw_addr\">192.168.10.101</data>        </node>        <node id=\"1001\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:62</data>            <data key=\"nw_addr\">192.168.20.101</data>        </node>        <node id=\"1002\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">10:40:f3:e6:8d:55</data>            <data key=\"nw_addr\">192.168.10.1</data>        </node>        <node id=\"1003\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">a0:b3:cc:9c:c6:88</data>            <data key=\"nw_addr\">192.168.20.1</data>        </node>        <node id=\"1004\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">00:04:20:e2:50:a2</data>            <data key=\"nw_addr\">192.168.30.1</data>        </node>        <node id=\"1005\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">58:55:ca:c4:1b:a0</data>            <data key=\"nw_addr\">192.168.40.1</data>        </node>        <edge id=\"10000\" source=\"1\" target=\"101\" label=\"on\"></edge>        <edge id=\"10001\" source=\"1\" target=\"102\" label=\"on\"></edge>        <edge id=\"10002\" source=\"1\" target=\"103\" label=\"on\"></edge>        <edge id=\"10003\" source=\"2\" target=\"104\" label=\"on\"></edge>        <edge id=\"10004\" source=\"2\" target=\"105\" label=\"on\"></edge>        <edge id=\"10005\" source=\"2\" target=\"106\" label=\"on\"></edge>        <edge id=\"10006\" source=\"3\" target=\"107\" label=\"on\"></edge>        <edge id=\"10007\" source=\"3\" target=\"108\" label=\"on\"></edge>        <edge id=\"10008\" source=\"3\" target=\"109\" label=\"on\"></edge>        <edge id=\"10009\" source=\"3\" target=\"110\" label=\"on\"></edge>        <edge id=\"10010\" source=\"4\" target=\"111\" label=\"on\"></edge>        <edge id=\"10011\" source=\"4\" target=\"112\" label=\"on\"></edge>        <edge id=\"10012\" source=\"4\" target=\"113\" label=\"on\"></edge>        <edge id=\"10013\" source=\"5\" target=\"114\" label=\"on\"></edge>        <edge id=\"10014\" source=\"5\" target=\"115\" label=\"on\"></edge>        <edge id=\"10015\" source=\"5\" target=\"116\" label=\"on\"></edge>        <edge id=\"10016\" source=\"6\" target=\"117\" label=\"on\"></edge>        <edge id=\"10017\" source=\"6\" target=\"118\" label=\"on\"></edge>        <edge id=\"10018\" source=\"6\" target=\"119\" label=\"on\"></edge>        <edge id=\"11000\" source=\"101\" target=\"107\" label=\"link\"></edge>         <edge id=\"11003\" source=\"105\" target=\"111\" label=\"link\"></edge>        <edge id=\"11004\" source=\"107\" target=\"101\" label=\"link\"></edge>        <edge id=\"11005\" source=\"108\" target=\"112\" label=\"link\"></edge>        <edge id=\"11006\" source=\"109\" target=\"114\" label=\"link\"></edge>        <edge id=\"11007\" source=\"111\" target=\"105\" label=\"link\"></edge>        <edge id=\"11008\" source=\"112\" target=\"108\" label=\"link\"></edge>        <edge id=\"11009\" source=\"113\" target=\"117\" label=\"link\"></edge>        <edge id=\"11010\" source=\"114\" target=\"109\" label=\"link\"></edge>        <edge id=\"11011\" source=\"115\" target=\"118\" label=\"link\"></edge>        <edge id=\"11012\" source=\"117\" target=\"113\" label=\"link\"></edge>        <edge id=\"11013\" source=\"118\" target=\"115\" label=\"link\"></edge>        <edge id=\"12000\" source=\"103\" target=\"1000\" label=\"host\"></edge>        <edge id=\"12001\" source=\"103\" target=\"1001\" label=\"host\"></edge>        <edge id=\"12002\" source=\"110\" target=\"1002\" label=\"host\"></edge>        <edge id=\"12003\" source=\"116\" target=\"1003\" label=\"host\"></edge>        <edge id=\"12004\" source=\"106\" target=\"1004\" label=\"host\"></edge>        <edge id=\"12005\" source=\"119\" target=\"1005\" label=\"host\"></edge>      </graph>    </graphml>
\ No newline at end of file
+<?xml version=\"1.0\" ?><graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\">    <key id=\"id\" for=\"node\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"type\" for=\"node\" attr.name=\"type\" attr.type=\"string\"></key>    <key id=\"dpid\" for=\"node\" attr.name=\"dpid\" attr.type=\"string\"></key>    <key id=\"desc\" for=\"node\" attr.name=\"desc\" attr.type=\"string\"></key>    <key id=\"number\" for=\"node\" attr.name=\"number\" attr.type=\"int\"></key>    <key id=\"dl_add\" for=\"node\" attr.name=\"dl_addr\" attr.type=\"string\"></key>    <key id=\"nw_addr\" for=\"node\" attr.name=\"nw_addr\" attr.type=\"string\"></key>    <key id=\"id\" for=\"edge\" attr.name=\"id\" attr.type=\"string\"></key>    <key id=\"source\" for=\"edge\" attr.name=\"source\" attr.type=\"string\"></key>    <key id=\"target\" for=\"edge\" attr.name=\"target\" attr.type=\"string\"></key>    <key id=\"label\" for=\"edge\" attr.name=\"label\" attr.type=\"string\"></key>    <graph id=\"G\" edgedefault=\"directed\">        <node id=\"1\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:01</data>            <data key=\"desc\">OpenFlow Switch at SEA</data>        </node>        <node id=\"2\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:02</data>            <data key=\"desc\">OpenFlow Switch at LAX</data>        </node>        <node id=\"3\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:03</data>            <data key=\"desc\">OpenFlow Switch at CHI</data>        </node>        <node id=\"4\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:04</data>            <data key=\"desc\">OpenFlow Switch at IAH</data>        </node>        <node id=\"5\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:05</data>            <data key=\"desc\">OpenFlow Switch at NYC</data>        </node>        <node id=\"6\">            <data key=\"type\">switch</data>            <data key=\"dpid\">00:00:00:00:00:00:0a:06</data>            <data key=\"desc\">OpenFlow Switch at ATL</data>        </node>        <node id=\"100\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at SEA Switch</data>        </node>        <node id=\"101\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at SEA Switch</data>        </node>        <node id=\"102\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at SEA Switch</data>        </node>        <node id=\"103\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at SEA Switch</data>        </node>        <node id=\"104\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at LAX Switch</data>        </node>        <node id=\"105\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at LAX Switch</data>        </node>        <node id=\"106\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at LAX Switch</data>        </node>        <node id=\"107\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at CHI Switch</data>        </node>        <node id=\"108\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at CHI Switch</data>        </node>        <node id=\"109\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at CHI Switch</data>        </node>        <node id=\"110\">            <data key=\"type\">port</data>            <data key=\"number\">4</data>            <data key=\"desc\">port 4 at CHI Switch</data>        </node>        <node id=\"111\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at IAH Switch</data>        </node>        <node id=\"112\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at IAH Switch</data>        </node>        <node id=\"113\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at IAH Switch</data>        </node>        <node id=\"114\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at NYC Switch</data>        </node>        <node id=\"115\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at NYC Switch</data>        </node>        <node id=\"116\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at NYC Switch</data>        </node>        <node id=\"117\">            <data key=\"type\">port</data>            <data key=\"number\">1</data>            <data key=\"desc\">port 1 at ATL Switch</data>        </node>        <node id=\"118\">            <data key=\"type\">port</data>            <data key=\"number\">2</data>            <data key=\"desc\">port 2 at ATL Switch</data>        </node>        <node id=\"119\">            <data key=\"type\">port</data>            <data key=\"number\">3</data>            <data key=\"desc\">port 3 at ATL Switch</data>        </node>        <node id=\"1000\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:73</data>            <data key=\"nw_addr\">192.168.10.101</data>        </node>        <node id=\"1001\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">20:c9:d0:4a:e1:62</data>            <data key=\"nw_addr\">192.168.20.101</data>        </node>        <node id=\"1002\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">10:40:f3:e6:8d:55</data>            <data key=\"nw_addr\">192.168.10.1</data>        </node>        <node id=\"1003\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">a0:b3:cc:9c:c6:88</data>            <data key=\"nw_addr\">192.168.20.1</data>        </node>        <node id=\"1004\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">00:04:20:e2:50:a2</data>            <data key=\"nw_addr\">192.168.30.1</data>        </node>        <node id=\"1005\">            <data key=\"type\">device</data>            <data key=\"dl_addr\">58:55:ca:c4:1b:a0</data>            <data key=\"nw_addr\">192.168.40.1</data>        </node>        <edge id=\"10000\" source=\"1\" target=\"101\" label=\"on\"></edge>        <edge id=\"10001\" source=\"1\" target=\"102\" label=\"on\"></edge>        <edge id=\"10002\" source=\"1\" target=\"103\" label=\"on\"></edge>        <edge id=\"10003\" source=\"2\" target=\"104\" label=\"on\"></edge>        <edge id=\"10004\" source=\"2\" target=\"105\" label=\"on\"></edge>        <edge id=\"10005\" source=\"2\" target=\"106\" label=\"on\"></edge>        <edge id=\"10006\" source=\"3\" target=\"107\" label=\"on\"></edge>        <edge id=\"10007\" source=\"3\" target=\"108\" label=\"on\"></edge>        <edge id=\"10008\" source=\"3\" target=\"109\" label=\"on\"></edge>        <edge id=\"10009\" source=\"3\" target=\"110\" label=\"on\"></edge>        <edge id=\"10010\" source=\"4\" target=\"111\" label=\"on\"></edge>        <edge id=\"10011\" source=\"4\" target=\"112\" label=\"on\"></edge>        <edge id=\"10012\" source=\"4\" target=\"113\" label=\"on\"></edge>        <edge id=\"10013\" source=\"5\" target=\"114\" label=\"on\"></edge>        <edge id=\"10014\" source=\"5\" target=\"115\" label=\"on\"></edge>        <edge id=\"10015\" source=\"5\" target=\"116\" label=\"on\"></edge>        <edge id=\"10016\" source=\"6\" target=\"117\" label=\"on\"></edge>        <edge id=\"10017\" source=\"6\" target=\"118\" label=\"on\"></edge>        <edge id=\"10018\" source=\"6\" target=\"119\" label=\"on\"></edge>        <edge id=\"11000\" source=\"101\" target=\"107\" label=\"link\"></edge>         <edge id=\"11003\" source=\"105\" target=\"111\" label=\"link\"></edge>        <edge id=\"11004\" source=\"107\" target=\"101\" label=\"link\"></edge>        <edge id=\"11005\" source=\"108\" target=\"112\" label=\"link\"></edge>        <edge id=\"11006\" source=\"109\" target=\"114\" label=\"link\"></edge>        <edge id=\"11007\" source=\"111\" target=\"105\" label=\"link\"></edge>        <edge id=\"11008\" source=\"112\" target=\"108\" label=\"link\"></edge>        <edge id=\"11009\" source=\"113\" target=\"117\" label=\"link\"></edge>        <edge id=\"11010\" source=\"114\" target=\"109\" label=\"link\"></edge>        <edge id=\"11011\" source=\"115\" target=\"118\" label=\"link\"></edge>        <edge id=\"11012\" source=\"117\" target=\"113\" label=\"link\"></edge>        <edge id=\"11013\" source=\"118\" target=\"115\" label=\"link\"></edge>        <edge id=\"12000\" source=\"103\" target=\"1000\" label=\"host\"></edge>        <edge id=\"12001\" source=\"103\" target=\"1001\" label=\"host\"></edge>        <edge id=\"12002\" source=\"110\" target=\"1002\" label=\"host\"></edge>        <edge id=\"12003\" source=\"116\" target=\"1003\" label=\"host\"></edge>        <edge id=\"12004\" source=\"106\" target=\"1004\" label=\"host\"></edge>        <edge id=\"12005\" source=\"119\" target=\"1005\" label=\"host\"></edge>      </graph>    </graphml>
diff --git a/titan/schema/test-network.xml b/titan/schema/test-network.xml
index a03a99c..630c5da 100644
--- a/titan/schema/test-network.xml
+++ b/titan/schema/test-network.xml
@@ -3,6 +3,7 @@
 
     <key id="id" for="node" attr.name="id" attr.type="string"></key>
     <key id="type" for="node" attr.name="type" attr.type="string"></key>
+    <key id="state" for="node" attr.name="state" attr.type="string"></key>
     <key id="dpid" for="node" attr.name="dpid" attr.type="string"></key>
     <key id="desc" for="node" attr.name="desc" attr.type="string"></key>
     <key id="number" for="node" attr.name="number" attr.type="int"></key>
@@ -17,31 +18,37 @@
         <node id="1">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:01</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at SEA</data>
         </node>
         <node id="2">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:02</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at LAX</data>
         </node>
         <node id="3">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:03</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at CHI</data>
         </node>
         <node id="4">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:04</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at IAH</data>
         </node>
         <node id="5">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:05</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at NYC</data>
         </node>
         <node id="6">
             <data key="type">switch</data>
             <data key="dpid">00:00:00:00:00:00:0a:06</data>
+            <data key="state">ACTIVE</data>
             <data key="desc">OpenFlow Switch at ATL</data>
         </node>
 
@@ -234,4 +241,4 @@
         <edge id="12004" source="106" target="1004" label="host"></edge>
         <edge id="12005" source="119" target="1005" label="host"></edge>
     </graph>
-</graphml>
\ No newline at end of file
+</graphml>
diff --git a/web/add_flow.py b/web/add_flow.py
index 4f502f6..8100f22 100755
--- a/web/add_flow.py
+++ b/web/add_flow.py
@@ -129,8 +129,9 @@
   my_dst_port = my_args[5]
 
   #
-  # Extract the "match" and "action" arguments
+  # Extract the "flowPathFlags", "match" and "action" arguments
   #
+  flowPathFlags = 0L
   match = {}
   matchInPortEnabled = True		# NOTE: Enabled by default
   actions = []
@@ -149,7 +150,12 @@
     arg2 = my_args[idx]
     idx = idx + 1
 
-    if arg1 == "matchInPort":
+    if arg1 == "flowPathFlags":
+      if "DISCARD_FIRST_HOP_ENTRY" in arg2:
+	flowPathFlags = flowPathFlags + 0x1
+      if "KEEP_ONLY_FIRST_HOP_ENTRY" in arg2:
+	flowPathFlags = flowPathFlags + 0x2
+    elif arg1 == "matchInPort":
       # Just mark whether inPort matching is enabled
       matchInPortEnabled = arg2 in ['True', 'true']
       # inPort = {}
@@ -166,21 +172,15 @@
       dstMac['value'] = arg2
       match['dstMac'] = dstMac
       # match['matchDstMac'] = True
+    elif arg1 == "matchEthernetFrameType":
+      match['ethernetFrameType'] = int(arg2, 0)
+      # match['matchEthernetFrameType'] = True
     elif arg1 == "matchVlanId":
       match['vlanId'] = int(arg2, 0)
       # match['matchVlanId'] = True
     elif arg1 == "matchVlanPriority":
       match['vlanPriority'] = int(arg2, 0)
       # match['matchVlanPriority'] = True
-    elif arg1 == "matchEthernetFrameType":
-      match['ethernetFrameType'] = int(arg2, 0)
-      # match['matchEthernetFrameType'] = True
-    elif arg1 == "matchIpToS":
-      match['ipToS'] = int(arg2, 0)
-      # match['matchIpToS'] = True
-    elif arg1 == "matchIpProto":
-      match['ipProto'] = int(arg2, 0)
-      # match['matchIpProto'] = True
     elif arg1 == "matchSrcIPv4Net":
       srcIPv4Net = {}
       srcIPv4Net['value'] = arg2
@@ -191,6 +191,12 @@
       dstIPv4Net['value'] = arg2
       match['dstIPv4Net'] = dstIPv4Net
       # match['matchDstIPv4Net'] = True
+    elif arg1 == "matchIpProto":
+      match['ipProto'] = int(arg2, 0)
+      # match['matchIpProto'] = True
+    elif arg1 == "matchIpToS":
+      match['ipToS'] = int(arg2, 0)
+      # match['matchIpToS'] = True
     elif arg1 == "matchSrcTcpUdpPort":
       match['srcTcpUdpPort'] = int(arg2, 0)
       # match['matchSrcTcpUdpPort'] = True
@@ -198,18 +204,19 @@
       match['dstTcpUdpPort'] = int(arg2, 0)
       # match['matchDstTcpUdpPort'] = True
     elif arg1 == "actionOutput":
-      # Just mark whether ACTION_OUTPUT action is enabled
+      # Mark whether ACTION_OUTPUT action is enabled
       actionOutputEnabled = arg2 in ['True', 'true']
-      #
-      # TODO: Complete the implementation for ACTION_OUTPUT
-      #   actionOutput = {}
-      #   outPort = {}
-      #   outPort['value'] = int(arg2, 0)
-      #   actionOutput['port'] = outPort
-      #   actionOutput['maxLen'] = int(arg3, 0)
-      #   action['actionOutput'] = actionOutput
-      #   # action['actionType'] = 'ACTION_OUTPUT'
-      #   actions.append(action)
+      # If ACTION_OUTPUT is explicitly enabled, add an entry with a fake
+      # port number. We need this entry to preserve the action ordering.
+      if actionOutputEnabled == True:
+        actionOutput = {}
+        outPort = {}
+        outPort['value'] = 0xffff
+        actionOutput['port'] = outPort
+        actionOutput['maxLen'] = 0
+        action['actionOutput'] = actionOutput
+        # action['actionType'] = 'ACTION_OUTPUT'
+        actions.append(action)
       #
     elif arg1 == "actionSetVlanId":
       vlanId = {}
@@ -223,24 +230,6 @@
       action['actionSetVlanPriority'] = vlanPriority
       # action['actionType'] = 'ACTION_SET_VLAN_PCP'
       actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetIpToS":
-      ipToS = {}
-      ipToS['ipToS'] = int(arg2, 0)
-      action['actionSetIpToS'] = ipToS
-      # action['actionType'] = 'ACTION_SET_NW_TOS'
-      actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetTcpUdpSrcPort":
-      tcpUdpSrcPort = {}
-      tcpUdpSrcPort['port'] = int(arg2, 0)
-      action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
-      # action['actionType'] = 'ACTION_SET_TP_SRC'
-      actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetTcpUdpDstPort":
-      tcpUdpDstPort = {}
-      tcpUdpDstPort['port'] = int(arg2, 0)
-      action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
-      # action['actionType'] = 'ACTION_SET_TP_DST'
-      actions.append(copy.deepcopy(action))
     elif arg1 == "actionStripVlan":
       stripVlan = {}
       stripVlan['stripVlan'] = arg2 in ['True', 'true']
@@ -279,6 +268,24 @@
       action['actionSetIPv4DstAddr'] = setIPv4DstAddr
       # action['actionType'] = 'ACTION_SET_NW_DST'
       actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetIpToS":
+      ipToS = {}
+      ipToS['ipToS'] = int(arg2, 0)
+      action['actionSetIpToS'] = ipToS
+      # action['actionType'] = 'ACTION_SET_NW_TOS'
+      actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetTcpUdpSrcPort":
+      tcpUdpSrcPort = {}
+      tcpUdpSrcPort['port'] = int(arg2, 0)
+      action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
+      # action['actionType'] = 'ACTION_SET_TP_SRC'
+      actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetTcpUdpDstPort":
+      tcpUdpDstPort = {}
+      tcpUdpDstPort['port'] = int(arg2, 0)
+      action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
+      # action['actionType'] = 'ACTION_SET_TP_DST'
+      actions.append(copy.deepcopy(action))
     elif arg1 == "actionEnqueue":
       # TODO: Implement ACTION_ENQUEUE
       actionEnqueue = {}
@@ -302,6 +309,7 @@
     'my_src_port' : my_src_port,
     'my_dst_dpid' : my_dst_dpid,
     'my_dst_port' : my_dst_port,
+    'flowPathFlags' : flowPathFlags,
     'match' : match,
     'matchInPortEnabled' : matchInPortEnabled,
     'actions' : actions,
@@ -325,6 +333,7 @@
 
   my_flow_id = parsed_args['my_flow_id']
   my_installer_id = parsed_args['my_installer_id']
+  myFlowPathFlags = parsed_args['flowPathFlags']
   match = parsed_args['match']
   matchInPortEnabled = parsed_args['matchInPortEnabled']
   actions = parsed_args['actions']
@@ -335,10 +344,15 @@
   flow_id['value'] = my_flow_id
   installer_id = {}
   installer_id['value'] = my_installer_id
+  flowPathFlags = {}
+  flowPathFlags['flags'] = myFlowPathFlags
+
+  flowEntryActions = {}
 
   flow_path = {}
   flow_path['flowId'] = flow_id
   flow_path['installerId'] = installer_id
+  flow_path['flowPathFlags'] = flowPathFlags
 
   if (len(match) > 0):
     flow_path['flowEntryMatch'] = copy.deepcopy(match)
@@ -356,6 +370,11 @@
       my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
       idx = idx + 1
 
+
+  if (len(actions) > 0):
+    flowEntryActions['actions'] = copy.deepcopy(actions)
+    flow_path['flowEntryActions'] = flowEntryActions
+
   #
   # Set the actions for each flow entry
   # NOTE: The actions from the command line are aplied
@@ -377,11 +396,12 @@
       action['actionOutput'] = copy.deepcopy(actionOutput)
       # action['actionType'] = 'ACTION_OUTPUT'
       actions.append(copy.deepcopy(action))
+      flowEntryActions = {}
+      flowEntryActions['actions'] = copy.deepcopy(actions)
 
-      my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
+      my_data_path['flowEntries'][idx]['flowEntryActions'] = flowEntryActions
       idx = idx + 1
 
-
   flow_path['dataPath'] = my_data_path
   debug("Flow Path: %s" % flow_path)
   return flow_path
@@ -461,7 +481,7 @@
 
 
 if __name__ == "__main__":
-  usage_msg = "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Match Conditions] [Actions]\n" % (sys.argv[0])
+  usage_msg = "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Flow Path Flags] [Match Conditions] [Actions]\n" % (sys.argv[0])
   usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Flags:\n"
   usage_msg = usage_msg + "        -m [monitorname]  Monitor and maintain the installed shortest path(s)\n"
@@ -472,36 +492,40 @@
   usage_msg = usage_msg + "        -f <filename>     Read the flow(s) to install from a file\n"
   usage_msg = usage_msg + "                          File format: one line per flow starting with <flow-id>\n"
   usage_msg = usage_msg + "\n"
+  usage_msg = usage_msg + "    Flow Path Flags:\n"
+  usage_msg = usage_msg + "        flowPathFlags <Flags> (flag names separated by ',')\n"
+  usage_msg = usage_msg + "\n"
+  usage_msg = usage_msg + "        Known flags:\n"
+  usage_msg = usage_msg + "            DISCARD_FIRST_HOP_ENTRY    : Discard the first-hop flow entry\n"
+  usage_msg = usage_msg + "            KEEP_ONLY_FIRST_HOP_ENTRY  : Keep only the first-hop flow entry\n"
+  usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Match Conditions:\n"
   usage_msg = usage_msg + "        matchInPort <True|False> (default to True)\n"
   usage_msg = usage_msg + "        matchSrcMac <source MAC address>\n"
   usage_msg = usage_msg + "        matchDstMac <destination MAC address>\n"
-  usage_msg = usage_msg + "        matchSrcIPv4Net <source IPv4 network address>\n"
-  usage_msg = usage_msg + "        matchDstIPv4Net <destination IPv4 network address>\n"
   usage_msg = usage_msg + "        matchEthernetFrameType <Ethernet frame type>\n"
-  usage_msg = usage_msg + "\n"
-  usage_msg = usage_msg + "    Match Conditions (not implemented yet):\n"
   usage_msg = usage_msg + "        matchVlanId <VLAN ID>\n"
   usage_msg = usage_msg + "        matchVlanPriority <VLAN priority>\n"
-  usage_msg = usage_msg + "        matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
+  usage_msg = usage_msg + "        matchSrcIPv4Net <source IPv4 network address>\n"
+  usage_msg = usage_msg + "        matchDstIPv4Net <destination IPv4 network address>\n"
   usage_msg = usage_msg + "        matchIpProto <IP protocol>\n"
+  usage_msg = usage_msg + "        matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
   usage_msg = usage_msg + "        matchSrcTcpUdpPort <source TCP/UDP port>\n"
   usage_msg = usage_msg + "        matchDstTcpUdpPort <destination TCP/UDP port>\n"
   usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Actions:\n"
   usage_msg = usage_msg + "        actionOutput <True|False> (default to True)\n"
+  usage_msg = usage_msg + "        actionSetVlanId <VLAN ID>\n"
+  usage_msg = usage_msg + "        actionSetVlanPriority <VLAN priority>\n"
+  usage_msg = usage_msg + "        actionStripVlan <True|False>\n"
   usage_msg = usage_msg + "        actionSetEthernetSrcAddr <source MAC address>\n"
   usage_msg = usage_msg + "        actionSetEthernetDstAddr <destination MAC address>\n"
   usage_msg = usage_msg + "        actionSetIPv4SrcAddr <source IPv4 address>\n"
   usage_msg = usage_msg + "        actionSetIPv4DstAddr <destination IPv4 address>\n"
-  usage_msg = usage_msg + "\n"
-  usage_msg = usage_msg + "    Actions (not implemented yet):\n"
-  usage_msg = usage_msg + "        actionSetVlanId <VLAN ID>\n"
-  usage_msg = usage_msg + "        actionSetVlanPriority <VLAN priority>\n"
   usage_msg = usage_msg + "        actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
   usage_msg = usage_msg + "        actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
   usage_msg = usage_msg + "        actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
-  usage_msg = usage_msg + "        actionStripVlan <True|False>\n"
+  usage_msg = usage_msg + "    Actions (not implemented yet):\n"
   usage_msg = usage_msg + "        actionEnqueue <dummy argument>\n"
 
   # app.debug = False;
diff --git a/web/config.json.dev.1node b/web/config.json.dev.1node
new file mode 100644
index 0000000..580a136
--- /dev/null
+++ b/web/config.json.dev.1node
@@ -0,0 +1,26 @@
+{
+    "LB": false, 
+    "TESTBED": "sw",
+    "ONOS_DEFAULT_HOST": "localhost",
+    "ONOS_GUI3_CONTROL_HOST": "http://localhost:9000", 
+    "ONOS_GUI3_HOST": "http://localhost:9000", 
+    "cluster_basename": "onosdev", 
+    "controllers": [
+        "onosdev1", 
+        "onosdev1", 
+        "onosdev1",
+        "onosdev1", 
+        "onosdev1", 
+        "onosdev1", 
+        "onosdev1", 
+        "onosdev1"
+    ], 
+    "core_switches": [
+        "00:00:00:00:00:00:01:01", 
+        "00:00:00:00:00:00:01:02", 
+        "00:00:00:00:00:00:01:03", 
+        "00:00:00:00:00:00:01:04", 
+        "00:00:00:00:00:00:01:05", 
+        "00:00:00:00:00:00:01:06"
+    ]
+}
diff --git a/web/config.json.devA b/web/config.json.devA
new file mode 100644
index 0000000..b20639e
--- /dev/null
+++ b/web/config.json.devA
@@ -0,0 +1,22 @@
+{
+    "LB": false, 
+    "TESTBED": "sw",
+    "ONOS_DEFAULT_HOST": "localhost",
+    "ONOS_GUI3_CONTROL_HOST": "http://10.128.4.51:9000", 
+    "ONOS_GUI3_HOST": "http://10.128.4.51:9000", 
+    "cluster_basename": "ONOS", 
+    "controllers": [
+        "DevA-ONOS1", 
+        "DevA-ONOS2", 
+        "DevA-ONOS3", 
+        "DevA-ONOS4" 
+    ], 
+ "core_switches": [
+        "00:00:00:00:ba:5e:ba:11", 
+        "00:00:00:00:00:00:ba:12", 
+        "00:00:20:4e:7f:51:8a:35", 
+        "00:00:00:00:ba:5e:ba:13", 
+        "00:00:00:08:a2:08:f9:01", 
+        "00:00:00:16:97:08:9a:46"
+    ]
+}
diff --git a/web/get_flow.py b/web/get_flow.py
index 033176d..9ab55da 100755
--- a/web/get_flow.py
+++ b/web/get_flow.py
@@ -33,78 +33,182 @@
 # Sample output:
 # {"flowId":{"value":"0x5"},"installerId":{"value":"FOOBAR"},"dataPath":{"srcPort":{"dpid":{"value":"00:00:00:00:00:00:00:01"},"port":{"value":0}},"dstPort":{"dpid":{"value":"00:00:00:00:00:00:00:02"},"port":{"value":0}},"flowEntries":[{"flowEntryId":"0x1389","flowEntryMatch":null,"flowEntryActions":null,"dpid":{"value":"00:00:00:00:00:00:00:01"},"inPort":{"value":0},"outPort":{"value":1},"flowEntryUserState":"FE_USER_DELETE","flowEntrySwitchState":"FE_SWITCH_NOT_UPDATED","flowEntryErrorState":null},{"flowEntryId":"0x138a","flowEntryMatch":null,"flowEntryActions":null,"dpid":{"value":"00:00:00:00:00:00:00:02"},"inPort":{"value":9},"outPort":{"value":0},"flowEntryUserState":"FE_USER_DELETE","flowEntrySwitchState":"FE_SWITCH_NOT_UPDATED","flowEntryErrorState":null}]}}
 
+def parse_match(match):
+  result = []
+
+  inPort = match['inPort']
+  matchInPort = match['matchInPort']
+  srcMac = match['srcMac']
+  matchSrcMac = match['matchSrcMac']
+  dstMac = match['dstMac']
+  matchDstMac = match['matchDstMac']
+  ethernetFrameType = match['ethernetFrameType']
+  matchEthernetFrameType = match['matchEthernetFrameType']
+  vlanId = match['vlanId']
+  matchVlanId = match['matchVlanId']
+  vlanPriority = match['vlanPriority']
+  matchVlanPriority = match['matchVlanPriority']
+  srcIPv4Net = match['srcIPv4Net']
+  matchSrcIPv4Net = match['matchSrcIPv4Net']
+  dstIPv4Net = match['dstIPv4Net']
+  matchDstIPv4Net = match['matchDstIPv4Net']
+  ipProto = match['ipProto']
+  matchIpProto = match['matchIpProto']
+  ipToS = match['ipToS']
+  matchIpToS = match['matchIpToS']
+  srcTcpUdpPort = match['srcTcpUdpPort']
+  matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
+  dstTcpUdpPort = match['dstTcpUdpPort']
+  matchDstTcpUdpPort = match['matchDstTcpUdpPort']
+  if matchInPort == True:
+    r = "inPort: %s" % inPort['value']
+    result.append(r)
+  if matchSrcMac == True:
+    r = "srcMac: %s" % srcMac['value']
+    result.append(r)
+  if matchDstMac == True:
+    r = "dstMac: %s" % dstMac['value']
+    result.append(r)
+  if matchEthernetFrameType == True:
+    r = "ethernetFrameType: %s" % hex(ethernetFrameType)
+    result.append(r)
+  if matchVlanId == True:
+    r = "vlanId: %s" % vlanId
+    result.append(r)
+  if matchVlanPriority == True:
+    r = "vlanPriority: %s" % vlanPriority
+    result.append(r)
+  if matchSrcIPv4Net == True:
+    r = "srcIPv4Net: %s" % srcIPv4Net['value']
+    result.append(r)
+  if matchDstIPv4Net == True:
+    r = "dstIPv4Net: %s" % dstIPv4Net['value']
+    result.append(r)
+  if matchIpProto == True:
+    r = "ipProto: %s" % ipProto
+    result.append(r)
+  if matchIpToS == True:
+    r = "ipToS: %s" % ipToS
+    result.append(r)
+  if matchSrcTcpUdpPort == True:
+    r = "srcTcpUdpPort: %s" % srcTcpUdpPort
+    result.append(r)
+  if matchDstTcpUdpPort == True:
+    r = "dstTcpUdpPort: %s" % dstTcpUdpPort
+    result.append(r)
+
+  return result
+
+
+def parse_actions(actions):
+  result = []
+  for a in actions:
+    actionType = a['actionType']
+    if actionType == "ACTION_OUTPUT":
+      port = a['actionOutput']['port']['value']
+      maxLen = a['actionOutput']['maxLen']
+      r = "actionType: %s port: %s maxLen: %s" % (actionType, port, maxLen)
+      result.append(r)
+    if actionType == "ACTION_SET_VLAN_VID":
+      vlanId = a['actionSetVlanId']['vlanId']
+      r = "actionType: %s vlanId: %s" % (actionType, vlanId)
+      result.append(r)
+    if actionType == "ACTION_SET_VLAN_PCP":
+      vlanPriority = a['actionSetVlanPriority']['vlanPriority']
+      r = "actionType: %s vlanPriority: %s" % (actionType, vlanPriority)
+      result.append(r)
+    if actionType == "ACTION_STRIP_VLAN":
+      stripVlan = a['actionStripVlan']['stripVlan']
+      r = "actionType: %s stripVlan: %s" % (actionType, stripVlan)
+      result.append(r)
+    if actionType == "ACTION_SET_DL_SRC":
+      setEthernetSrcAddr = a['actionSetEthernetSrcAddr']['addr']['value']
+      r = "actionType: %s setEthernetSrcAddr: %s" % (actionType, setEthernetSrcAddr)
+      result.append(r)
+    if actionType == "ACTION_SET_DL_DST":
+      setEthernetDstAddr = a['actionSetEthernetDstAddr']['addr']['value']
+      r = "actionType: %s setEthernetDstAddr: %s" % (actionType, setEthernetDstAddr)
+      result.append(r)
+    if actionType == "ACTION_SET_NW_SRC":
+      setIPv4SrcAddr = a['actionSetIPv4SrcAddr']['addr']['value']
+      r = "actionType: %s setIPv4SrcAddr: %s" % (actionType, setIPv4SrcAddr)
+      result.append(r)
+    if actionType == "ACTION_SET_NW_DST":
+      setIPv4DstAddr = a['actionSetIPv4DstAddr']['addr']['value']
+      r = "actionType: %s setIPv4DstAddr: %s" % (actionType, setIPv4DstAddr)
+      result.append(r)
+    if actionType == "ACTION_SET_NW_TOS":
+      setIpToS = a['actionSetIpToS']['ipToS']
+      r = "actionType: %s setIpToS: %s" % (actionType, setIpToS)
+      result.append(r)
+    if actionType == "ACTION_SET_TP_SRC":
+      setTcpUdpSrcPort = a['actionSetTcpUdpSrcPort']['port']
+      r = "actionType: %s setTcpUdpSrcPort: %s" % (actionType, setTcpUdpSrcPort)
+      result.append(r)
+    if actionType == "ACTION_SET_TP_DST":
+      setTcpUdpDstPort = a['actionSetTcpUdpDstPort']['port']
+      r = "actionType: %s setTcpUdpDstPort: %s" % (actionType, setTcpUdpDstPort)
+      result.append(r)
+    if actionType == "ACTION_ENQUEUE":
+      port = a['actionEnqueue']['port']['value']
+      queueId = a['actionEnqueue']['queueId']
+      r = "actionType: %s port: %s queueId: %s" % (actionType, port, queueId)
+      result.append(r)
+
+  return result
+
+
 def print_flow_path(parsedResult):
   flowId = parsedResult['flowId']['value']
   installerId = parsedResult['installerId']['value']
+  flowPathFlags = parsedResult['flowPathFlags']['flags']
   srcSwitch = parsedResult['dataPath']['srcPort']['dpid']['value']
   srcPort = parsedResult['dataPath']['srcPort']['port']['value']
   dstSwitch = parsedResult['dataPath']['dstPort']['dpid']['value']
   dstPort = parsedResult['dataPath']['dstPort']['port']['value']
-
-  print "FlowPath: (flowId = %s installerId = %s src = %s/%s dst = %s/%s)" % (flowId, installerId, srcSwitch, srcPort, dstSwitch, dstPort)
   match = parsedResult['flowEntryMatch'];
+  actions = parsedResult['flowEntryActions']['actions']
+
+  flowPathFlagsStr = ""
+  if (flowPathFlags & 0x1):
+    if flowPathFlagsStr:
+      flowPathFlagsStr += ","
+    flowPathFlagsStr += "DISCARD_FIRST_HOP_ENTRY"
+  if (flowPathFlags & 0x2):
+    if flowPathFlagsStr:
+      flowPathFlagsStr += ","
+    flowPathFlagsStr += "KEEP_ONLY_FIRST_HOP_ENTRY"
+
+  print "FlowPath: (flowId = %s installerId = %s flowPathFlags = 0x%x(%s) src = %s/%s dst = %s/%s)" % (flowId, installerId, flowPathFlags, flowPathFlagsStr, srcSwitch, srcPort, dstSwitch, dstPort)
+
   #
-  # Print the common conditions
+  # Print the common match conditions
   #
   if match == None:
     print "   Match: %s" % (match)
   else:
-    # inPort = match['inPort']
-    # matchInPort = match['matchInPort']
-    srcMac = match['srcMac']
-    matchSrcMac = match['matchSrcMac']
-    dstMac = match['dstMac']
-    matchDstMac = match['matchDstMac']
-    vlanId = match['vlanId']
-    matchVlanId = match['matchVlanId']
-    vlanPriority = match['vlanPriority']
-    matchVlanPriority = match['matchVlanPriority']
-    ethernetFrameType = match['ethernetFrameType']
-    matchEthernetFrameType = match['matchEthernetFrameType']
-    ipToS = match['ipToS']
-    matchIpToS = match['matchIpToS']
-    ipProto = match['ipProto']
-    matchIpProto = match['matchIpProto']
-    srcIPv4Net = match['srcIPv4Net']
-    matchSrcIPv4Net = match['matchSrcIPv4Net']
-    dstIPv4Net = match['dstIPv4Net']
-    matchDstIPv4Net = match['matchDstIPv4Net']
-    srcTcpUdpPort = match['srcTcpUdpPort']
-    matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
-    dstTcpUdpPort = match['dstTcpUdpPort']
-    matchDstTcpUdpPort = match['matchDstTcpUdpPort']
-    # if matchInPort == True:
-    #  print "    inPort: %s" % inPort['value']
-    if matchSrcMac == True:
-      print "    srcMac: %s" % srcMac['value']
-    if matchDstMac == True:
-      print "    dstMac: %s" % dstMac['value']
-    if matchVlanId == True:
-      print "    vlanId: %s" % vlanId
-    if matchVlanPriority == True:
-      print "    vlanPriority: %s" % vlanPriority
-    if matchEthernetFrameType == True:
-      print "    ethernetFrameType: %s" % hex(ethernetFrameType)
-    if matchIpToS == True:
-      print "    ipToS: %s" % ipToS
-    if matchIpProto == True:
-      print "    ipProto: %s" % ipProto
-    if matchSrcIPv4Net == True:
-      print "    srcIPv4Net: %s" % srcIPv4Net['value']
-    if matchDstIPv4Net == True:
-      print "    dstIPv4Net: %s" % dstIPv4Net['value']
-    if matchSrcTcpUdpPort == True:
-      print "    srcTcpUdpPort: %s" % srcTcpUdpPort
-    if matchDstTcpUdpPort == True:
-      print "    dstTcpUdpPort: %s" % dstTcpUdpPort
+    parsedMatch = parse_match(match)
+    for l in parsedMatch:
+      print "    %s" % l
 
+  #
+  # Print the actions
+  #
+  parsedActions = parse_actions(actions)
+  for l in parsedActions:
+    print "    %s" % l
+
+  #
+  # Print each Flow Entry
+  #
   for f in parsedResult['dataPath']['flowEntries']:
     flowEntryId = f['flowEntryId']
     dpid = f['dpid']['value']
     userState = f['flowEntryUserState']
     switchState = f['flowEntrySwitchState']
     match = f['flowEntryMatch'];
-    actions = f['flowEntryActions']
+    actions = f['flowEntryActions']['actions']
+
     print "  FlowEntry: (%s, %s, %s, %s)" % (flowEntryId, dpid, userState, switchState)
 
     #
@@ -113,101 +217,16 @@
     if match == None:
       print "   Match: %s" % (match)
     else:
-      inPort = match['inPort']
-      matchInPort = match['matchInPort']
-      srcMac = match['srcMac']
-      matchSrcMac = match['matchSrcMac']
-      dstMac = match['dstMac']
-      matchDstMac = match['matchDstMac']
-      vlanId = match['vlanId']
-      matchVlanId = match['matchVlanId']
-      vlanPriority = match['vlanPriority']
-      matchVlanPriority = match['matchVlanPriority']
-      ethernetFrameType = match['ethernetFrameType']
-      matchEthernetFrameType = match['matchEthernetFrameType']
-      ipToS = match['ipToS']
-      matchIpToS = match['matchIpToS']
-      ipProto = match['ipProto']
-      matchIpProto = match['matchIpProto']
-      srcIPv4Net = match['srcIPv4Net']
-      matchSrcIPv4Net = match['matchSrcIPv4Net']
-      dstIPv4Net = match['dstIPv4Net']
-      matchDstIPv4Net = match['matchDstIPv4Net']
-      srcTcpUdpPort = match['srcTcpUdpPort']
-      matchSrcTcpUdpPort = match['matchSrcTcpUdpPort']
-      dstTcpUdpPort = match['dstTcpUdpPort']
-      matchDstTcpUdpPort = match['matchDstTcpUdpPort']
-      if matchInPort == True:
-	print "    inPort: %s" % inPort['value']
-      if matchSrcMac == True:
-	print "    srcMac: %s" % srcMac['value']
-      if matchDstMac == True:
-	print "    dstMac: %s" % dstMac['value']
-      if matchVlanId == True:
-	print "    vlanId: %s" % vlanId
-      if matchVlanPriority == True:
-	print "    vlanPriority: %s" % vlanPriority
-      if matchEthernetFrameType == True:
-	print "    ethernetFrameType: %s" % hex(ethernetFrameType)
-      if matchIpToS == True:
-	print "    ipToS: %s" % ipToS
-      if matchIpProto == True:
-	print "    ipProto: %s" % ipProto
-      if matchSrcIPv4Net == True:
-	print "    srcIPv4Net: %s" % srcIPv4Net['value']
-      if matchDstIPv4Net == True:
-	print "    dstIPv4Net: %s" % dstIPv4Net['value']
-      if matchSrcTcpUdpPort == True:
-	print "    srcTcpUdpPort: %s" % srcTcpUdpPort
-      if matchDstTcpUdpPort == True:
-	print "    dstTcpUdpPort: %s" % dstTcpUdpPort
-
+      parsedMatch = parse_match(match)
+      for l in parsedMatch:
+	print "    %s" % l
     #
     # Print the actions
     #
-    if actions == None:
-      print "   Actions: %s" % (actions)
-    else:
-      for a in actions:
-	actionType = a['actionType']
-	if actionType == "ACTION_OUTPUT":
-	  port = a['actionOutput']['port']['value']
-	  maxLen = a['actionOutput']['maxLen']
-	  print "    actionType: %s port: %s maxLen: %s" % (actionType, port, maxLen)
-	if actionType == "ACTION_SET_VLAN_VID":
-	  vlanId = a['actionSetVlanId']['vlanId']
-	  print "    actionType: %s vlanId: %s" % (actionType, vlanId)
-	if actionType == "ACTION_SET_VLAN_PCP":
-	  vlanPriority = a['actionSetVlanPriority']['vlanPriority']
-	  print "    actionType: %s vlanPriority: %s" % (actionType, vlanPriority)
-	if actionType == "ACTION_STRIP_VLAN":
-	  stripVlan = a['actionStripVlan']['stripVlan']
-	  print "    actionType: %s stripVlan: %s" % (actionType, stripVlan)
-	if actionType == "ACTION_SET_DL_SRC":
-	  setEthernetSrcAddr = a['actionSetEthernetSrcAddr']['addr']['value']
-	  print "    actionType: %s setEthernetSrcAddr: %s" % (actionType, setEthernetSrcAddr)
-	if actionType == "ACTION_SET_DL_DST":
-	  setEthernetDstAddr = a['actionSetEthernetDstAddr']['addr']['value']
-	  print "    actionType: %s setEthernetDstAddr: %s" % (actionType, setEthernetDstAddr)
-	if actionType == "ACTION_SET_NW_SRC":
-	  setIPv4SrcAddr = a['actionSetIPv4SrcAddr']['addr']['value']
-	  print "    actionType: %s setIPv4SrcAddr: %s" % (actionType, setIPv4SrcAddr)
-	if actionType == "ACTION_SET_NW_DST":
-	  setIPv4DstAddr = a['actionSetIPv4DstAddr']['addr']['value']
-	  print "    actionType: %s setIPv4DstAddr: %s" % (actionType, setIPv4DstAddr)
-	if actionType == "ACTION_SET_NW_TOS":
-	  setIpToS = a['actionSetIpToS']['ipToS']
-	  print "    actionType: %s setIpToS: %s" % (actionType, setIpToS)
-	if actionType == "ACTION_SET_TP_SRC":
-	  setTcpUdpSrcPort = a['actionSetTcpUdpSrcPort']['port']
-	  print "    actionType: %s setTcpUdpSrcPort: %s" % (actionType, setTcpUdpSrcPort)
-	if actionType == "ACTION_SET_TP_DST":
-	  setTcpUdpDstPort = a['actionSetTcpUdpDstPort']['port']
-	  print "    actionType: %s setTcpUdpDstPort: %s" % (actionType, setTcpUdpDstPort)
-	if actionType == "ACTION_ENQUEUE":
-	  port = a['actionEnqueue']['port']['value']
-	  queueId = a['actionEnqueue']['queueId']
-	  print "    actionType: %s port: %s queueId: %s" % (actionType, port, queueId)
+    parsedActions = parse_actions(actions)
+    for l in parsedActions:
+      print "    %s" % l
+
 
 def get_flow_path(flow_id):
   try:
diff --git a/web/log b/web/log
deleted file mode 100644
index e69de29..0000000
--- a/web/log
+++ /dev/null
diff --git a/web/measurement_get_per_flow_install_time.py b/web/measurement_get_per_flow_install_time.py
new file mode 100755
index 0000000..bf2bcc7
--- /dev/null
+++ b/web/measurement_get_per_flow_install_time.py
@@ -0,0 +1,61 @@
+#! /usr/bin/env python
+# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
+
+import pprint
+import os
+import sys
+import subprocess
+import json
+import argparse
+import io
+import time
+
+from flask import Flask, json, Response, render_template, make_response, request
+
+#
+# TODO: remove this! We don't use JSON argument here!
+# curl http://127.0.0.1:8080/wm/flow/delete/{"value":"0xf"}/json'
+#
+
+## Global Var ##
+ControllerIP="127.0.0.1"
+ControllerPort=8080
+
+DEBUG=0
+pp = pprint.PrettyPrinter(indent=4)
+
+app = Flask(__name__)
+
+## Worker Functions ##
+def log_error(txt):
+  print '%s' % (txt)
+
+def debug(txt):
+  if DEBUG:
+    print '%s' % (txt)
+
+# @app.route("/wm/flow/measurement-get-per-flow-install-time/json")
+def measurement_get_per_flow_install_time():
+  command = "curl -s \"http://%s:%s/wm/flow/measurement-get-per-flow-install-time/json\"" % (ControllerIP, ControllerPort)
+  debug("measurement_get_per_flow_install_time %s" % command)
+  result = os.popen(command).read()
+  print '%s' % (result)
+  # parsedResult = json.loads(result)
+  # debug("parsed %s" % parsedResult)
+
+if __name__ == "__main__":
+  usage_msg = "Get the measured time per flow to install each stored flow path\n"
+  usage_msg = usage_msg + "Usage: %s\n" % (sys.argv[0])
+  usage_msg = usage_msg + "\n"
+
+  # app.debug = False;
+
+  # Usage info
+  if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
+    print(usage_msg)
+    exit(0)
+
+  # Check arguments
+
+  # Do the work
+  measurement_get_per_flow_install_time()
diff --git a/web/measurement_process.py b/web/measurement_process.py
new file mode 100755
index 0000000..3187299
--- /dev/null
+++ b/web/measurement_process.py
@@ -0,0 +1,59 @@
+#! /usr/bin/env python
+# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
+
+import functools
+import math
+import sys
+
+## {{{ http://code.activestate.com/recipes/511478/ (r1)
+
+def percentile(N, percent, key=lambda x:x):
+    """
+    Find the percentile of a list of values.
+
+    @parameter N - is a list of values. Note N MUST BE already sorted.
+    @parameter percent - a float value from 0.0 to 1.0.
+    @parameter key - optional key function to compute value from each element of N.
+
+    @return - the percentile of the values
+    """
+    if not N:
+        return None
+    k = (len(N)-1) * percent
+    f = math.floor(k)
+    c = math.ceil(k)
+    if f == c:
+        return key(N[int(k)])
+    d0 = key(N[int(f)]) * (c-k)
+    d1 = key(N[int(c)]) * (k-f)
+    return d0+d1
+
+# median is 50th percentile.
+# median = functools.partial(percentile, percent=0.5)
+## end of http://code.activestate.com/recipes/511478/ }}}
+
+if __name__ == "__main__":
+
+    dict = {}
+
+    #
+    # Read the data from the stdin, and store it in a dictionary.
+    # The dictionary uses lists as values.
+    #
+    data = sys.stdin.readlines()
+    for line in data:
+	words = line.split()
+	thread_n = int(words[0])
+	msec = float(words[1])
+	dict.setdefault(thread_n, []).append(msec)
+
+    #
+    # Compute and print the values: median (50-th), 10-th, and 90-th
+    # percentile:
+    # <key> <median> <10-percentile> <90-percentile>
+    #
+    for key, val_list in sorted(dict.items()):
+	val_10 = percentile(sorted(val_list), 0.1)
+	val_50 = percentile(sorted(val_list), 0.5)
+	val_90 = percentile(sorted(val_list), 0.9)
+	print "%s %s %s %s" % (str(key), str(val_50), str(val_10), str(val_90))
diff --git a/web/measurement_run.py b/web/measurement_run.py
new file mode 100755
index 0000000..80d0517
--- /dev/null
+++ b/web/measurement_run.py
@@ -0,0 +1,104 @@
+#! /usr/bin/env python
+# -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
+
+import os
+import string
+import subprocess
+import time
+
+# flow_n = 252
+# threads_n = [1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100]
+# iterations_n = 10
+
+flow_n = 1
+threads_n = [1]
+iterations_n = 10
+# iterations_n = 100
+
+# flow_n = 42
+# flow_n = 420
+# flow_n = 1008
+
+def run_command(cmd):
+    """
+    - Run an external command, and return a tuple: stdout as the
+    first argument, and stderr as the second argument.
+    - Returns None if error.
+    """
+    try:
+	pr = subprocess.Popen(cmd, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
+	ret_tuple = pr.communicate();
+	if pr.returncode:
+	    print "%s failed with error code: %s" % (cmd, str(pr.returncode))
+	return ret_tuple
+    except OSError:
+	print "OS Error running %s" % cmd
+
+def run_install_paths(flowdef_filename):
+    # Prepare the flows to measure
+    cmd = "web/measurement_store_flow.py -f " + flowdef_filename
+    os.system(cmd)
+
+def run_measurement(thread_n):
+    # Install the Flow Paths
+    cmd = ["web/measurement_install_paths.py", str(thread_n)]
+    run_command(cmd)
+
+    # Get the measurement data and print it
+    cmd = "web/measurement_get_install_paths_time_nsec.py"
+    r = run_command(cmd)		# Tuple: [<stdout>, <stderr>]
+    res = r[0].split()			# Tuple: [<num>, nsec]
+    nsec_str = res[0]
+    msec = float(nsec_str) / (1000 * 1000)
+
+    # Get the measurement data and print it
+    cmd = "web/measurement_get_per_flow_install_time.py"
+    r = run_command(cmd)		# Tuple: [<stdout>, <stderr>]
+    res = r[0]
+    print res
+
+    # Keep checking until all Flow Paths are installed
+    while True:
+	# time.sleep(3)
+	cmd = ["web/get_flow.py", "all"]
+	r = run_command(cmd)
+	if string.count(r[0], "FlowPath") != flow_n:
+	    continue
+	if string.find(r[0], "NOT") == -1:
+	    break
+
+    # Remove the installed Flow Paths
+    cmd = ["web/delete_flow.py", "all"]
+    run_command(cmd)
+
+    # Keep checking until all Flows are removed
+    while True:
+	# time.sleep(3)
+	cmd = ["web/get_flow.py", "all"]
+	r = run_command(cmd)
+	if r[0] == "":
+	    break
+
+    return msec
+
+
+if __name__ == "__main__":
+
+    # Initial cleanup
+    cmd = "web/measurement_clear_all_paths.py"
+    run_command(cmd)
+
+    # Install the Flow Paths to measure
+    flowdef_filename = "web/flowdef_8node_" + str(flow_n) + ".txt"
+    run_install_paths(flowdef_filename)
+
+    # Do the work
+    for thread_n in threads_n:
+	for n in range(iterations_n):
+	    msec = run_measurement(thread_n)
+	    # Format: <number of threads> <time in ms>
+	    print "%d %f" % (thread_n, msec / flow_n)
+
+    # Cleanup on exit
+    cmd = "web/measurement_clear_all_paths.py"
+    run_command(cmd)
diff --git a/web/measurement_store_flow.py b/web/measurement_store_flow.py
index 637ab3e..0e39465 100755
--- a/web/measurement_store_flow.py
+++ b/web/measurement_store_flow.py
@@ -60,8 +60,9 @@
   my_dst_port = my_args[5]
 
   #
-  # Extract the "match" and "action" arguments
+  # Extract the "flowPathFlags", "match" and "action" arguments
   #
+  flowPathFlags = 0L
   match = {}
   matchInPortEnabled = True		# NOTE: Enabled by default
   actions = []
@@ -80,8 +81,13 @@
     arg2 = my_args[idx]
     idx = idx + 1
 
-    if arg1 == "matchInPort":
-      # Just mark whether inPort matching is enabled
+    if arg1 == "flowPathFlags":
+      if "DISCARD_FIRST_HOP_ENTRY" in arg2:
+	flowPathFlags = flowPathFlags + 0x1
+      if "KEEP_ONLY_FIRST_HOP_ENTRY" in arg2:
+	flowPathFlags = flowPathFlags + 0x2
+    elif arg1 == "matchInPort":
+      # Mark whether ACTION_OUTPUT action is enabled
       matchInPortEnabled = arg2 in ['True', 'true']
       # inPort = {}
       # inPort['value'] = int(arg2, 0)
@@ -97,21 +103,15 @@
       dstMac['value'] = arg2
       match['dstMac'] = dstMac
       # match['matchDstMac'] = True
+    elif arg1 == "matchEthernetFrameType":
+      match['ethernetFrameType'] = int(arg2, 0)
+      # match['matchEthernetFrameType'] = True
     elif arg1 == "matchVlanId":
       match['vlanId'] = int(arg2, 0)
       # match['matchVlanId'] = True
     elif arg1 == "matchVlanPriority":
       match['vlanPriority'] = int(arg2, 0)
       # match['matchVlanPriority'] = True
-    elif arg1 == "matchEthernetFrameType":
-      match['ethernetFrameType'] = int(arg2, 0)
-      # match['matchEthernetFrameType'] = True
-    elif arg1 == "matchIpToS":
-      match['ipToS'] = int(arg2, 0)
-      # match['matchIpToS'] = True
-    elif arg1 == "matchIpProto":
-      match['ipProto'] = int(arg2, 0)
-      # match['matchIpProto'] = True
     elif arg1 == "matchSrcIPv4Net":
       srcIPv4Net = {}
       srcIPv4Net['value'] = arg2
@@ -122,6 +122,12 @@
       dstIPv4Net['value'] = arg2
       match['dstIPv4Net'] = dstIPv4Net
       # match['matchDstIPv4Net'] = True
+    elif arg1 == "matchIpProto":
+      match['ipProto'] = int(arg2, 0)
+      # match['matchIpProto'] = True
+    elif arg1 == "matchIpToS":
+      match['ipToS'] = int(arg2, 0)
+      # match['matchIpToS'] = True
     elif arg1 == "matchSrcTcpUdpPort":
       match['srcTcpUdpPort'] = int(arg2, 0)
       # match['matchSrcTcpUdpPort'] = True
@@ -129,18 +135,19 @@
       match['dstTcpUdpPort'] = int(arg2, 0)
       # match['matchDstTcpUdpPort'] = True
     elif arg1 == "actionOutput":
-      # Just mark whether ACTION_OUTPUT action is enabled
+      # Mark whether ACTION_OUTPUT action is enabled
       actionOutputEnabled = arg2 in ['True', 'true']
-      #
-      # TODO: Complete the implementation for ACTION_OUTPUT
-      #   actionOutput = {}
-      #   outPort = {}
-      #   outPort['value'] = int(arg2, 0)
-      #   actionOutput['port'] = outPort
-      #   actionOutput['maxLen'] = int(arg3, 0)
-      #   action['actionOutput'] = actionOutput
-      #   # action['actionType'] = 'ACTION_OUTPUT'
-      #   actions.append(action)
+      # If ACTION_OUTPUT is explicitly enabled, add an entry with a fake
+      # port number. We need this entry to preserve the action ordering.
+      if actionOutputEnabled == True:
+        actionOutput = {}
+        outPort = {}
+        outPort['value'] = 0xffff
+        actionOutput['port'] = outPort
+        actionOutput['maxLen'] = 0
+        action['actionOutput'] = actionOutput
+        # action['actionType'] = 'ACTION_OUTPUT'
+        actions.append(action)
       #
     elif arg1 == "actionSetVlanId":
       vlanId = {}
@@ -154,24 +161,6 @@
       action['actionSetVlanPriority'] = vlanPriority
       # action['actionType'] = 'ACTION_SET_VLAN_PCP'
       actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetIpToS":
-      ipToS = {}
-      ipToS['ipToS'] = int(arg2, 0)
-      action['actionSetIpToS'] = ipToS
-      # action['actionType'] = 'ACTION_SET_NW_TOS'
-      actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetTcpUdpSrcPort":
-      tcpUdpSrcPort = {}
-      tcpUdpSrcPort['port'] = int(arg2, 0)
-      action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
-      # action['actionType'] = 'ACTION_SET_TP_SRC'
-      actions.append(copy.deepcopy(action))
-    elif arg1 == "actionSetTcpUdpDstPort":
-      tcpUdpDstPort = {}
-      tcpUdpDstPort['port'] = int(arg2, 0)
-      action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
-      # action['actionType'] = 'ACTION_SET_TP_DST'
-      actions.append(copy.deepcopy(action))
     elif arg1 == "actionStripVlan":
       stripVlan = {}
       stripVlan['stripVlan'] = arg2 in ['True', 'true']
@@ -210,6 +199,24 @@
       action['actionSetIPv4DstAddr'] = setIPv4DstAddr
       # action['actionType'] = 'ACTION_SET_NW_DST'
       actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetIpToS":
+      ipToS = {}
+      ipToS['ipToS'] = int(arg2, 0)
+      action['actionSetIpToS'] = ipToS
+      # action['actionType'] = 'ACTION_SET_NW_TOS'
+      actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetTcpUdpSrcPort":
+      tcpUdpSrcPort = {}
+      tcpUdpSrcPort['port'] = int(arg2, 0)
+      action['actionSetTcpUdpSrcPort'] = tcpUdpSrcPort
+      # action['actionType'] = 'ACTION_SET_TP_SRC'
+      actions.append(copy.deepcopy(action))
+    elif arg1 == "actionSetTcpUdpDstPort":
+      tcpUdpDstPort = {}
+      tcpUdpDstPort['port'] = int(arg2, 0)
+      action['actionSetTcpUdpDstPort'] = tcpUdpDstPort
+      # action['actionType'] = 'ACTION_SET_TP_DST'
+      actions.append(copy.deepcopy(action))
     elif arg1 == "actionEnqueue":
       # TODO: Implement ACTION_ENQUEUE
       actionEnqueue = {}
@@ -233,6 +240,7 @@
     'my_src_port' : my_src_port,
     'my_dst_dpid' : my_dst_dpid,
     'my_dst_port' : my_dst_port,
+    'flowPathFlags' : flowPathFlags,
     'match' : match,
     'matchInPortEnabled' : matchInPortEnabled,
     'actions' : actions,
@@ -243,6 +251,7 @@
 
   my_flow_id = parsed_args['my_flow_id']
   my_installer_id = parsed_args['my_installer_id']
+  myFlowPathFlags = parsed_args['flowPathFlags']
   match = parsed_args['match']
   matchInPortEnabled = parsed_args['matchInPortEnabled']
   actions = parsed_args['actions']
@@ -253,10 +262,15 @@
   flow_id['value'] = my_flow_id
   installer_id = {}
   installer_id['value'] = my_installer_id
+  flowPathFlags = {}
+  flowPathFlags['flags'] = myFlowPathFlags
+
+  flowEntryActions = {}
 
   flow_path = {}
   flow_path['flowId'] = flow_id
   flow_path['installerId'] = installer_id
+  flow_path['flowPathFlags'] = flowPathFlags
 
   if (len(match) > 0):
     flow_path['flowEntryMatch'] = copy.deepcopy(match)
@@ -274,6 +288,11 @@
       my_data_path['flowEntries'][idx]['flowEntryMatch'] = copy.deepcopy(match)
       idx = idx + 1
 
+
+  if (len(actions) > 0):
+    flowEntryActions['actions'] = copy.deepcopy(actions)
+    flow_path['flowEntryActions'] = flowEntryActions
+
   #
   # Set the actions for each flow entry
   # NOTE: The actions from the command line are aplied
@@ -295,11 +314,12 @@
       action['actionOutput'] = copy.deepcopy(actionOutput)
       # action['actionType'] = 'ACTION_OUTPUT'
       actions.append(copy.deepcopy(action))
+      flowEntryActions = {}
+      flowEntryActions['actions'] = copy.deepcopy(actions)
 
-      my_data_path['flowEntries'][idx]['flowEntryActions'] = copy.deepcopy(actions)
+      my_data_path['flowEntries'][idx]['flowEntryActions'] = flowEntryActions
       idx = idx + 1
 
-
   flow_path['dataPath'] = my_data_path
   debug("Flow Path: %s" % flow_path)
   return flow_path
@@ -346,42 +366,46 @@
 if __name__ == "__main__":
   usage_msg = "Store Flow Paths into ONOS for measurement purpose.\n"
   usage_msg = usage_msg + "\n"
-  usage_msg = usage_msg + "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Match Conditions] [Actions]\n" % (sys.argv[0])
+  usage_msg = usage_msg + "Usage: %s [Flags] <flow-id> <installer-id> <src-dpid> <src-port> <dest-dpid> <dest-port> [Flow Path Flags] [Match Conditions] [Actions]\n" % (sys.argv[0])
   usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Flags:\n"
   usage_msg = usage_msg + "        -f <filename>     Read the flow(s) to install from a file\n"
   usage_msg = usage_msg + "                          File format: one line per flow starting with <flow-id>\n"
   usage_msg = usage_msg + "\n"
+  usage_msg = usage_msg + "    Flow Path Flags:\n"
+  usage_msg = usage_msg + "        flowPathFlags <Flags> (flag names separated by ',')\n"
+  usage_msg = usage_msg + "\n"
+  usage_msg = usage_msg + "        Known flags:\n"
+  usage_msg = usage_msg + "            DISCARD_FIRST_HOP_ENTRY    : Discard the first-hop flow entry\n"
+  usage_msg = usage_msg + "            KEEP_ONLY_FIRST_HOP_ENTRY  : Keep only the first-hop flow entry\n"
+  usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Match Conditions:\n"
   usage_msg = usage_msg + "        matchInPort <True|False> (default to True)\n"
   usage_msg = usage_msg + "        matchSrcMac <source MAC address>\n"
   usage_msg = usage_msg + "        matchDstMac <destination MAC address>\n"
-  usage_msg = usage_msg + "        matchSrcIPv4Net <source IPv4 network address>\n"
-  usage_msg = usage_msg + "        matchDstIPv4Net <destination IPv4 network address>\n"
   usage_msg = usage_msg + "        matchEthernetFrameType <Ethernet frame type>\n"
-  usage_msg = usage_msg + "\n"
-  usage_msg = usage_msg + "    Match Conditions (not implemented yet):\n"
   usage_msg = usage_msg + "        matchVlanId <VLAN ID>\n"
   usage_msg = usage_msg + "        matchVlanPriority <VLAN priority>\n"
-  usage_msg = usage_msg + "        matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
+  usage_msg = usage_msg + "        matchSrcIPv4Net <source IPv4 network address>\n"
+  usage_msg = usage_msg + "        matchDstIPv4Net <destination IPv4 network address>\n"
   usage_msg = usage_msg + "        matchIpProto <IP protocol>\n"
+  usage_msg = usage_msg + "        matchIpToS <IP ToS (DSCP field, 6 bits)>\n"
   usage_msg = usage_msg + "        matchSrcTcpUdpPort <source TCP/UDP port>\n"
   usage_msg = usage_msg + "        matchDstTcpUdpPort <destination TCP/UDP port>\n"
   usage_msg = usage_msg + "\n"
   usage_msg = usage_msg + "    Actions:\n"
   usage_msg = usage_msg + "        actionOutput <True|False> (default to True)\n"
+  usage_msg = usage_msg + "        actionSetVlanId <VLAN ID>\n"
+  usage_msg = usage_msg + "        actionSetVlanPriority <VLAN priority>\n"
+  usage_msg = usage_msg + "        actionStripVlan <True|False>\n"
   usage_msg = usage_msg + "        actionSetEthernetSrcAddr <source MAC address>\n"
   usage_msg = usage_msg + "        actionSetEthernetDstAddr <destination MAC address>\n"
   usage_msg = usage_msg + "        actionSetIPv4SrcAddr <source IPv4 address>\n"
   usage_msg = usage_msg + "        actionSetIPv4DstAddr <destination IPv4 address>\n"
-  usage_msg = usage_msg + "\n"
-  usage_msg = usage_msg + "    Actions (not implemented yet):\n"
-  usage_msg = usage_msg + "        actionSetVlanId <VLAN ID>\n"
-  usage_msg = usage_msg + "        actionSetVlanPriority <VLAN priority>\n"
   usage_msg = usage_msg + "        actionSetIpToS <IP ToS (DSCP field, 6 bits)>\n"
   usage_msg = usage_msg + "        actionSetTcpUdpSrcPort <source TCP/UDP port>\n"
   usage_msg = usage_msg + "        actionSetTcpUdpDstPort <destination TCP/UDP port>\n"
-  usage_msg = usage_msg + "        actionStripVlan <True|False>\n"
+  usage_msg = usage_msg + "    Actions (not implemented yet):\n"
   usage_msg = usage_msg + "        actionEnqueue <dummy argument>\n"
 
   # app.debug = False;
diff --git a/web/onos-topology.html b/web/onos-topology.html
index 72e9fc4..d72c0e1 100644
--- a/web/onos-topology.html
+++ b/web/onos-topology.html
@@ -52,8 +52,8 @@
 <div id="topology"></div>
 <script type="text/javascript" src="js/controller-status.js"></script>
 <script type="text/javascript">
-controller_status("http://gui3.onlab.us:8081/controller_status");
-gui("http://gui3.onlab.us:8081/topology");
+controller_status("controller_status");
+gui("topology"); 
 </script>
 </svg>
 </body>
diff --git a/web/ons-demo/data/configuration.json.devA b/web/ons-demo/data/configuration.json.devA
new file mode 100644
index 0000000..f8a6e63
--- /dev/null
+++ b/web/ons-demo/data/configuration.json.devA
@@ -0,0 +1,78 @@
+{
+	"core": [
+		"00:00:00:08:a2:08:f9:01",
+		"00:00:00:00:ba:5e:ba:11",
+		"00:00:20:4e:7f:51:8a:35",
+		"00:00:00:00:00:00:ba:12",
+		"00:00:00:00:ba:5e:ba:13",
+		"00:00:00:16:97:08:9a:46"
+	],
+	"aggregation": [
+		"00:00:00:00:00:00:02:01",
+		"00:00:00:00:00:00:03:01",
+		"00:00:00:00:00:00:04:01",
+		"00:00:00:00:00:00:05:01",
+		"00:00:00:00:00:00:06:01",
+		"00:00:00:00:00:00:07:01",
+		"00:00:00:00:00:00:08:01"
+	],
+	"association": {
+		"00:00:20:4e:7f:51:8a:35": [
+			"00:00:00:00:00:00:07:01"
+		],
+		"00:00:00:00:ba:5e:ba:13": [
+			"00:00:00:00:00:00:06:01"
+		],
+		"00:00:00:08:a2:08:f9:01": [
+			"00:00:00:00:00:00:03:01"
+		],
+		"00:00:00:00:00:00:ba:12": [
+			"00:00:00:00:00:00:04:01",
+			"00:00:00:00:00:00:05:01"
+		],
+		"00:00:00:00:ba:5e:ba:11": [
+			"00:00:00:00:00:00:02:01"
+		],
+		"00:00:00:16:97:08:9a:46": [
+			"00:00:00:00:00:00:08:01"
+		]
+	},
+	"geo": {
+		"00:00:20:4e:7f:51:8a:35": {
+			"lat": 41.891033,
+			"lng": -87.628326,
+			"label": "CHI",
+			"fanOutAngle": 180
+		},
+		"00:00:00:00:ba:5e:ba:13": {
+			"lat": 47.611024,
+			"lng": -122.33242,
+			"label": "SEA",
+			"fanOutAngle": 270
+		},
+		"00:00:00:08:a2:08:f9:01": {
+			"lat": 33.758599,
+			"lng": -84.387360,
+			"label": "ATL",
+			"fanOutAngle": 5
+		},
+		"00:00:00:16:97:08:9a:46": {
+			"lat": 41.225925,
+			"lng": -74.00528,
+			"label": "NYC",
+			"fanOutAngle": 150
+		},
+		"00:00:00:00:ba:5e:ba:11": {
+			"lat": 37.901187,
+			"lng": -76.037163,
+			"label": "DC",
+			"fanOutAngle": 45
+		},
+		"00:00:00:00:00:00:ba:12": {
+			"lat": 34.102708,
+			"lng": -118.238983,
+			"label": "LA",
+			"fanOutAngle": 315
+		}
+	}
+}
diff --git a/web/ons-demo/data/controllers.json.dev b/web/ons-demo/data/controllers.json.dev
index 4abcf5a..b936d96 100644
--- a/web/ons-demo/data/controllers.json.dev
+++ b/web/ons-demo/data/controllers.json.dev
@@ -1,10 +1,10 @@
 [
-	"onosdevb1",
-	"onosdevb2",
-	"onosdevb3",
-	"onosdevb4",
-	"onosdevb5",
-	"onosdevb6",
-	"onosdevb7",
-	"onosdevb8"
-]
\ No newline at end of file
+	"onosdev1",
+	"onosdev2",
+	"onosdev3",
+	"onosdev4",
+	"onosdev5",
+	"onosdev6",
+	"onosdev7",
+	"onosdev8"
+]
diff --git a/web/ons-demo/index.html b/web/ons-demo/index.html
index 5c1a650..ab13250 100644
--- a/web/ons-demo/index.html
+++ b/web/ons-demo/index.html
@@ -15,6 +15,7 @@
 		<div id='status'>
 			<div class='status'><span class='dynamic' id='activeFlows'>????</span><span class='static'>Flows</span></div>
 			<div class='status'><span class='dynamic' id='activeSwitches'>???</span><span class='static'>Active Switches</span></div>
+			<div class='status'><span class='dynamic' id='activeLinks'>???</span><span class='static'>Links</span></div>
 		</div>
 		<div id='lastUpdated' class='status'><span class='static'>Last updated:</span><span id='lastUpdate' class='dynamic'>Mon Mar 18 11:11:12 PDT 2013</span></div>
 	</div>
diff --git a/web/ons-demo/js/constants.js b/web/ons-demo/js/constants.js
index 51b3aa6..236d79a 100644
--- a/web/ons-demo/js/constants.js
+++ b/web/ons-demo/js/constants.js
@@ -2,7 +2,8 @@
 timeout used by controller functions. after the timeout expires the "pending" action
 is removed and the topology view is whatever is reported by the API
 ***************************************************************************************************/
-var pendingTimeout = 30000;
+/* var pendingTimeout = 30000; */
+var pendingTimeout = 60000;
 
 /***************************************************************************************************
 CSS names for the pallette of colors used by the topology view
@@ -27,4 +28,4 @@
 	edge: 6,
 	aggregation: 16,
 	core: 20
-}
\ No newline at end of file
+}
diff --git a/web/ons-demo/js/utils.js b/web/ons-demo/js/utils.js
index 68e567f..d7220c5 100644
--- a/web/ons-demo/js/utils.js
+++ b/web/ons-demo/js/utils.js
@@ -103,6 +103,7 @@
 
 
 	d3.select('#activeFlows').text(model.flows.length);
+	d3.select('#activeLinks').text(model.links.length);
 }
 
 /***************************************************************************************************
diff --git a/web/topology_rest.py b/web/topology_rest.py
index 6c2ea15..ea33a00 100755
--- a/web/topology_rest.py
+++ b/web/topology_rest.py
@@ -13,9 +13,9 @@
 
 from flask import Flask, json, Response, render_template, make_response, request
 
-
 CONFIG_FILE=os.getenv("HOME") + "/ONOS/web/config.json"
 LINK_FILE=os.getenv("HOME") + "/ONOS/web/link.json"
+ONOSDIR=os.getenv("HOME") + "/ONOS"
 
 ## Global Var for ON.Lab local REST ##
 RestIP="localhost"
@@ -216,19 +216,6 @@
   resp = Response(result, status=200, mimetype='application/json')
   return resp
 
-@app.route("/proxy/gui/switchctrl/<cmd>")
-def proxy_switch_controller_setting(cmd):
-  try:
-    command = "curl -s %s/gui/switchctrl/%s" % (ONOS_GUI3_CONTROL_HOST, cmd)
-    print command
-    result = os.popen(command).read()
-  except:
-    print "REST IF has issue"
-    exit
-
-  resp = Response(result, status=200, mimetype='application/json')
-  return resp
-
 @app.route("/proxy/gui/reset")
 def proxy_gui_reset():
   result = ""
@@ -373,7 +360,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   topo = {}
   switches = []
@@ -439,7 +427,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   for v in parsedResult:
     link = {}
@@ -479,7 +468,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   topo = {}
   switches = []
@@ -526,7 +516,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   for v in parsedResult:
     link = {}
@@ -565,7 +556,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
 #  print command
 #  print result
@@ -594,7 +586,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   devices = []
   for v in parsedResult:
@@ -656,7 +649,8 @@
   except:
     log_error("REST IF has issue: %s" % command)
     log_error("%s" % result)
-    sys.exit(0)
+    return
+#    sys.exit(0)
 
   debug("query_links %s" % command)
 #  pp.pprint(parsedResult)
@@ -672,7 +666,8 @@
     except:
       log_error("REST IF has issue: %s" % command)
       log_error("%s" % result)
-      sys.exit(0)
+      return
+#      sys.exit(0)
 
     for p in linkResults:
       if p.has_key('type') and p['type'] == "port":
@@ -697,14 +692,14 @@
 @app.route("/controller_status")
 def controller_status():
 #  onos_check="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh status | awk '{print $1}'"
-  onos_check="cd; onos status %s | grep %s | awk '{print $2}'"
+  onos_check="cd; onos status | grep %s | awk '{print $2}'"
   #cassandra_check="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-cassandra.sh status"
 
   cont_status=[]
   for i in controllers:
     status={}
     onos=os.popen(onos_check % i).read()[:-1]
-    onos=os.popen(onos_check % (i, i.lower())).read()[:-1]
+#    onos=os.popen(onos_check % (i, i.lower())).read()[:-1]
     status["name"]=i
     status["onos"]=onos
     status["cassandra"]=0
@@ -724,8 +719,11 @@
 #    stop_onos="/home/admin/bin/onos stop %s > /tmp/debug " % (controller_name[-1:])
 #    print "Debug: Controller command %s called %s" % (cmd, controller_name)
   else:
-    start_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh start" % (controller_name)
-    stop_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh stop" % (controller_name)
+    # No longer use -i to specify keys (use .ssh/config to specify it)
+    start_onos="ssh %s ONOS/start-onos.sh start" % (controller_name)
+    stop_onos="ssh %s ONOS/start-onos.sh stop" % (controller_name)
+#    start_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh start" % (controller_name)
+#    stop_onos="ssh -i ~/.ssh/onlabkey.pem %s ONOS/start-onos.sh stop" % (controller_name)
 
   if cmd == "up":
     result=os.popen(start_onos).read()
@@ -743,8 +741,8 @@
     result=""
     if (TESTBED == "sw"):
       for i in range(1, len(controllers)):
-        cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./ctrl-local.sh'" % (controllers[i])
-        result += os.popen(cmd_string).read()
+          cmd_string="ssh %s 'cd ONOS/scripts; ./ctrl-local.sh'" % (controllers[i])
+          result += os.popen(cmd_string).read()
     else:
       cmd_string="cd; switch local > /tmp/watch"
       result += os.popen(cmd_string).read()
@@ -753,7 +751,8 @@
     result=""
     if (TESTBED == "sw"):
       for i in range(1, len(controllers)):
-        cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./ctrl-add-ext.sh'" % (controllers[i])
+        cmd_string="ssh %s 'cd ONOS/scripts; ./ctrl-add-ext.sh'" % (controllers[i])
+#        cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./ctrl-add-ext.sh'" % (controllers[i])
         print "cmd is: "+cmd_string
         result += os.popen(cmd_string).read()
     else:
@@ -789,7 +788,8 @@
   r = re.compile(':')
   dpid = re.sub(r, '', dpid)
   host=controllers[0]
-  cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./switch.sh %s %s'" % (host, dpid, cmd)
+  cmd_string="ssh %s 'cd ONOS/scripts; ./switch.sh %s %s'" % (host, dpid, cmd)
+#  cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./switch.sh %s %s'" % (host, dpid, cmd)
   get_status="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./switch.sh %s'" % (host, dpid)
   print "cmd_string"
 
@@ -829,7 +829,8 @@
     else:
       (port, dontcare) = get_link_ports(dpid, src_dpid)
 
-    cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./link.sh %s %s %s'" % (host, dpid, port, cmd)
+#    cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./link.sh %s %s %s'" % (host, dpid, port, cmd)
+    cmd_string="ssh %s 'cd ONOS/scripts; ./link.sh %s %s %s'" % (host, dpid, port, cmd)
     print cmd_string
     res=os.popen(cmd_string).read()
     result = result + ' ' + res
@@ -936,7 +937,7 @@
     host = controllers[hostid-1]
 
   if (TESTBED == "sw"):
-    cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; ./link.sh %s %s %s'" % (host, src_dpid, src_port, cmd)
+    cmd_string="ssh %s 'cd ONOS/scripts; ./link.sh %s %s %s'" % (host, src_dpid, src_port, cmd)
   else:
     if ( src_dpid == "00:00:00:08:a2:08:f9:01" ):
       cmd_string="~/ONOS/scripts/link-hw.sh %s %s %s " % ( dst_dpid, dst_port, cmd)
@@ -957,11 +958,17 @@
   url ="%s/wm/flow/getsummary/%s/%s/json" % (host, 0, 0)
   (code, result) = get_json(url)
   parsedResult = json.loads(result)
-  flow_nr = int(parsedResult[-1]['flowId'], 16)
+  if len(parsedResult) > 0:
+    if parsedResult[-1].has_key('flowId'):
+      flow_nr = int(parsedResult[-1]['flowId'], 16)
+  else:
+    flow_nr = -1  # first flow
+    print "first flow"
+
   flow_nr += 1
-  command =  "/home/ubuntu/ONOS/web/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (flow_nr, "dummy", src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC)
+  command =  "%s/web/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (ONOSDIR, flow_nr, "dummy", src_dpid, src_port, dst_dpid, dst_port, srcMAC, dstMAC)
   flow_nr += 1
-  command1 = "/home/ubuntu/ONOS/web/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (flow_nr, "dummy", dst_dpid, dst_port, src_dpid, src_port, dstMAC, srcMAC)
+  command1 = "%s/web/add_flow.py -m onos %d %s %s %s %s %s matchSrcMac %s matchDstMac %s" % (ONOSDIR, flow_nr, "dummy", dst_dpid, dst_port, src_dpid, src_port, dstMAC, srcMAC)
   print "add flow: %s, %s" % (command, command1)
   errcode = os.popen(command).read()
   errcode1 = os.popen(command1).read()
@@ -973,7 +980,7 @@
 #http://localhost:9000/gui/delflow/<flow_id>
 @app.route("/gui/delflow/<flow_id>")
 def del_flow(flow_id):
-  command = "/home/ubuntu/ONOS/web/delete_flow.py %s" % (flow_id)
+  command = "%/web/delete_flow.py %s" % (ONOSDIR, flow_id)
   print command
   errcode = os.popen(command).read()
   return errcode
@@ -1027,7 +1034,7 @@
   if TESTBED == "hw":
     cmd_string="dsh -w %s 'cd ONOS/scripts; " % dst_host
   else:
-    cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts; " % dst_host
+    cmd_string="ssh %s 'cd ONOS/scripts; " % dst_host
   cmd_string += "./runiperf.sh %d %s %s %s:%s %s/%s/%s/%s'" % (flowId, src_dpid, dst_dpid, TESTBED, "svr", protocol, duration, interval, samples)
   print cmd_string
   os.popen(cmd_string)
@@ -1035,7 +1042,7 @@
   if TESTBED == "hw":
     cmd_string="dsh -w %s 'cd ONOS/scripts; " % src_host
   else:
-    cmd_string="ssh -i ~/.ssh/onlabkey.pem %s 'cd ONOS/scripts;" % src_host
+    cmd_string="ssh %s 'cd ONOS/scripts;" % src_host
   cmd_string+="./runiperf.sh %d %s %s %s:%s %s/%s/%s/%s'" % (flowId, src_dpid, dst_dpid, TESTBED, "client", protocol, duration, interval, samples)
   print cmd_string
   os.popen(cmd_string)