diff --git a/apps/circuitpusher/circuitpusher.py b/apps/circuitpusher/circuitpusher.py
new file mode 100755
index 0000000000000000000000000000000000000000..68c5df53c940e19813648b3e5b0c087a8d4de925
--- /dev/null
+++ b/apps/circuitpusher/circuitpusher.py
@@ -0,0 +1,201 @@
+#! /usr/bin/python
+"""
+circuitpusher utilizes floodlight rest APIs to create a bidirectional circuit, 
+i.e., permanent flow entry, on all switches in route between two devices based 
+on IP addresses with specified priority.
+ 
+Notes:
+ 1. The circuit pusher currently only creates circuit with two IP end points 
+ 2. Prior to sending restAPI requests to the circuit pusher, the specified end
+    points must already been known to the controller (i.e., already have sent
+    packets on the network, easy way to assure this is to do a ping (to any
+    target) from the two hosts.
+ 3. The current supported command syntax format is:
+    a) circuitpusher.py --controller={IP}:{rest port} --type ip --src {IP} --dst {IP} --add --name {circuit-name}
+ 
+       adds a new circuit between src and dst devices Currently ip circuit is supported. ARP is automatically supported.
+    
+       Currently a simple circuit record storage is provided in a text file circuits.json in the working directory.
+       The file is not protected and does not clean itself between controller restarts.  The file is needed for correct operation
+       and the user should make sure deleting the file when floodlight controller is restarted.
+
+    b) circuitpusher.py --controller={IP}:{rest port} --delete --name {circuit-name}
+
+       deletes a created circuit (as recorded in circuits.json) using the previously given name
+
+@author kcwang
+"""
+
+import os
+import sys
+import subprocess
+import json
+import argparse
+import io
+import time
+
+# parse circuit options.  Currently supports add and delete actions.
+# Syntax:
+#   circuitpusher --controller {IP:REST_PORT} --add --name {CIRCUIT_NAME} --type ip --src {IP} --dst {IP} 
+#   circuitpusher --controller {IP:REST_PORT} --delete --name {CIRCUIT_NAME}
+
+parser = argparse.ArgumentParser(description='Circuit Pusher')
+parser.add_argument('--controller', dest='controllerRestIp', action='store', default='localhost:8080', help='controller IP:RESTport, e.g., localhost:8080 or A.B.C.D:8080')
+parser.add_argument('--add', dest='action', action='store_const', const='add', default='add', help='action: add, delete')
+parser.add_argument('--delete', dest='action', action='store_const', const='delete', default='add', help='action: add, delete')
+parser.add_argument('--type', dest='type', action='store', default='ip', help='valid types: ip')
+parser.add_argument('--src', dest='srcAddress', action='store', default='0.0.0.0', help='source address: if type=ip, A.B.C.D')
+parser.add_argument('--dst', dest='dstAddress', action='store', default='0.0.0.0', help='destination address: if type=ip, A.B.C.D')
+parser.add_argument('--name', dest='circuitName', action='store', default='circuit-1', help='name for circuit, e.g., circuit-1')
+
+args = parser.parse_args()
+print args
+
+controllerRestIp = args.controllerRestIp
+
+# first check if a local file exists, which needs to be updated after add/delete
+if os.path.exists('./circuits.json'):
+    circuitDb = open('./circuits.json','r')
+    lines = circuitDb.readlines()
+    circuitDb.close()
+else:
+    lines={}
+
+if args.action=='add':
+
+    circuitDb = open('./circuits.json','a')
+    
+    for line in lines:
+        data = json.loads(line)
+        if data['name']==(args.circuitName):
+            print "Circuit %s exists already. Use new name to create." % args.circuitName
+            sys.exit()
+        else:
+            circuitExists = False
+    
+    # retrieve source and destination device attachment points
+    # using DeviceManager rest API 
+    
+    command = "curl -s http://%s/wm/device/?ipv4=%s" % (args.controllerRestIp, args.srcAddress)
+    result = os.popen(command).read()
+    parsedResult = json.loads(result)
+    print command+"\n"
+    sourceSwitch = parsedResult[0]['attachmentPoint'][0]['switchDPID']
+    sourcePort = parsedResult[0]['attachmentPoint'][0]['port']
+    
+    command = "curl -s http://%s/wm/device/?ipv4=%s" % (args.controllerRestIp, args.dstAddress)
+    result = os.popen(command).read()
+    parsedResult = json.loads(result)
+    print command+"\n"
+    destSwitch = parsedResult[0]['attachmentPoint'][0]['switchDPID']
+    destPort = parsedResult[0]['attachmentPoint'][0]['port']
+    
+    print "Creating circuit:"
+    print "from source device at switch %s port %s" % (sourceSwitch,sourcePort)
+    print "to destination device at switch %s port %s"% (destSwitch,destPort)
+    
+    # retrieving route from source to destination
+    # using Routing rest API
+    
+    command = "curl -s http://%s/wm/topology/route/%s/%s/%s/%s/json" % (controllerRestIp, sourceSwitch, sourcePort, destSwitch, destPort)
+    
+    result = os.popen(command).read()
+    parsedResult = json.loads(result)
+
+    print command+"\n"
+    print result+"\n"
+
+    for i in range(len(parsedResult)):
+        if i % 2 == 0:
+            ap1Dpid = parsedResult[i]['switch']
+            ap1Port = parsedResult[i]['port']
+            print ap1Dpid, ap1Port
+            
+        else:
+            ap2Dpid = parsedResult[i]['switch']
+            ap2Port = parsedResult[i]['port']
+            print ap2Dpid, ap2Port
+            
+            # send one flow mod per pair of APs in route
+            # using StaticFlowPusher rest API
+
+            # IMPORTANT NOTE: current Floodlight StaticflowEntryPusher
+            # assumes all flow entries to have unique name across all switches
+            # this will most possibly be relaxed later, but for now we
+            # encode each flow entry's name with both switch dpid, user
+            # specified name, and flow type (f: forward, r: reverse, farp/rarp: arp)
+
+            command = "curl -s -d '{\"switch\": \"%s\", \"name\":\"%s\", \"src-ip\":\"%s\", \"dst-ip\":\"%s\", \"ether-type\":\"%s\", \"cookie\":\"0\", \"priority\":\"32768\", \"ingress-port\":\"%s\",\"active\":\"true\", \"actions\":\"output=%s\"}' http://%s/wm/staticflowentrypusher/json" % (ap1Dpid, ap1Dpid+"."+args.circuitName+".f", args.srcAddress, args.dstAddress, "0x800", ap1Port, ap2Port, controllerRestIp)
+            result = os.popen(command).read()
+            print command
+
+            command = "curl -s -d '{\"switch\": \"%s\", \"name\":\"%s\", \"ether-type\":\"%s\", \"cookie\":\"0\", \"priority\":\"32768\", \"ingress-port\":\"%s\",\"active\":\"true\", \"actions\":\"output=%s\"}' http://%s/wm/staticflowentrypusher/json" % (ap1Dpid, ap1Dpid+"."+args.circuitName+".farp", "0x806", ap1Port, ap2Port, controllerRestIp)
+            result = os.popen(command).read()
+            print command
+
+
+            command = "curl -s -d '{\"switch\": \"%s\", \"name\":\"%s\", \"src-ip\":\"%s\", \"dst-ip\":\"%s\", \"ether-type\":\"%s\", \"cookie\":\"0\", \"priority\":\"32768\", \"ingress-port\":\"%s\",\"active\":\"true\", \"actions\":\"output=%s\"}' http://%s/wm/staticflowentrypusher/json" % (ap1Dpid, ap1Dpid+"."+args.circuitName+".r", args.dstAddress, args.srcAddress, "0x800", ap2Port, ap1Port, controllerRestIp)
+            result = os.popen(command).read()
+            print command
+
+            command = "curl -s -d '{\"switch\": \"%s\", \"name\":\"%s\", \"ether-type\":\"%s\", \"cookie\":\"0\", \"priority\":\"32768\", \"ingress-port\":\"%s\",\"active\":\"true\", \"actions\":\"output=%s\"}' http://%s/wm/staticflowentrypusher/json" % (ap1Dpid, ap1Dpid+"."+args.circuitName+".rarp", "0x806", ap2Port, ap1Port, controllerRestIp)
+            result = os.popen(command).read()
+            print command
+            
+            # store created circuit attributes in local ./circuits.json
+            datetime = time.asctime()
+            circuitParams = {'name':args.circuitName, 'Dpid':ap1Dpid, 'inPort':ap1Port, 'outPort':ap2Port, 'datetime':datetime}
+            str = json.dumps(circuitParams)
+            circuitDb.write(str+"\n")
+
+        # confirm successful circuit creation
+        # using controller rest API
+            
+        command="curl -s http://%s/wm/core/switch/all/flow/json| python -mjson.tool" % (controllerRestIp)
+        result = os.popen(command).read()
+        print command + "\n" + result
+
+elif args.action=='delete':
+    
+    circuitDb = open('./circuits.json','w')
+
+    # removing previously created flow from switches
+    # using StaticFlowPusher rest API       
+    # currently, circuitpusher records created circuits in local file ./circuits.db 
+    # with circuit name and list of switches                                  
+
+    circuitExists = False
+
+    for line in lines:
+        data = json.loads(line)
+        if data['name']==(args.circuitName):
+            circuitExists = True
+
+            sw = data['Dpid']
+            print data, sw
+
+            command = "curl -X DELETE -d '{\"name\":\"%s\", \"switch\":\"%s\"}' http://%s/wm/staticflowentrypusher/json" % (sw+"."+args.circuitName+".f", sw, controllerRestIp)
+            result = os.popen(command).read()
+            print command, result
+
+            command = "curl -X DELETE -d '{\"name\":\"%s\", \"switch\":\"%s\"}' http://%s/wm/staticflowentrypusher/json" % (sw+"."+args.circuitName+".farp", sw, controllerRestIp)
+            result = os.popen(command).read()
+            print command, result
+
+            command = "curl -X DELETE -d '{\"name\":\"%s\", \"switch\":\"%s\"}' http://%s/wm/staticflowentrypusher/json" % (sw+"."+args.circuitName+".r", sw, controllerRestIp)
+            result = os.popen(command).read()
+            print command, result
+
+            command = "curl -X DELETE -d '{\"name\":\"%s\", \"switch\":\"%s\"}' http://%s/wm/staticflowentrypusher/json" % (sw+"."+args.circuitName+".rarp", sw, controllerRestIp)
+            result = os.popen(command).read()
+            print command, result            
+            
+        else:
+            circuitDb.write(line)
+
+    circuitDb.close()
+
+    if not circuitExists:
+        print "specified circuit does not exist"
+        sys.exit()
+
diff --git a/src/main/java/net/floodlightcontroller/topology/web/RouteResource.java b/src/main/java/net/floodlightcontroller/topology/web/RouteResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..70e406fcc25946a4c1275c2e351c6c4513838932
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/topology/web/RouteResource.java
@@ -0,0 +1,47 @@
+package net.floodlightcontroller.topology.web;
+
+import java.util.List;
+
+import net.floodlightcontroller.routing.IRoutingService;
+import net.floodlightcontroller.routing.Route;
+import net.floodlightcontroller.topology.NodePortTuple;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RouteResource extends ServerResource {
+
+    protected static Logger log = LoggerFactory.getLogger(RouteResource.class);
+
+    @Get("json")
+    public List<NodePortTuple> retrieve() {
+        IRoutingService routing = 
+                (IRoutingService)getContext().getAttributes().
+                    get(IRoutingService.class.getCanonicalName());
+        
+        String srcDpid = (String) getRequestAttributes().get("src-dpid");
+        String srcPort = (String) getRequestAttributes().get("src-port");
+        String dstDpid = (String) getRequestAttributes().get("dst-dpid");
+        String dstPort = (String) getRequestAttributes().get("dst-port");
+
+        log.debug( srcDpid + "--" + srcPort + "--" + dstDpid + "--" + dstPort);
+
+        long longSrcDpid = HexString.toLong(srcDpid);
+        short shortSrcPort = Short.parseShort(srcPort);
+        long longDstDpid = HexString.toLong(dstDpid);
+        short shortDstPort = Short.parseShort(dstPort);
+        
+        Route result = routing.getRoute(longSrcDpid, shortSrcPort, longDstDpid, shortDstPort);
+        
+        if (result!=null) {
+            return routing.getRoute(longSrcDpid, shortSrcPort, longDstDpid, shortDstPort).getPath();
+        }
+        else {
+            log.debug("ERROR! no route found");
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
index 7335f261d95ef8f037d8ab8612816bd6a8a8a296..1c15d8a65dde9c7b8e678e0c2325fbb0ffc43135 100644
--- a/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/topology/web/TopologyWebRoutable.java
@@ -18,6 +18,7 @@ public class TopologyWebRoutable implements RestletRoutable {
         router.attach("/switchclusters/json", SwitchClustersResource.class);
         router.attach("/broadcastdomainports/json", BroadcastDomainResource.class);
         router.attach("/blockedports/json", BlockedPortsResource.class);
+        router.attach("/route/{src-dpid}/{src-port}/{dst-dpid}/{dst-port}/json", RouteResource.class);
         return router;
     }