diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index 668ceaa..ce91138 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -27,6 +27,7 @@
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
+import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.api.packet.IPacketListener;
@@ -70,7 +71,6 @@
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.IPv4Net;
 import net.onrc.onos.core.util.SwitchPort;
-import net.floodlightcontroller.restserver.IRestApiService;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -115,6 +115,10 @@
     private final int DELAY_TO_ADD_LINK = 10;
     private final int MAX_NUM_LABELS = 3;
 
+    // ************************************
+    // IFloodlightModule implementation
+    // ************************************
+
     @Override
     public Collection<Class<? extends IFloodlightService>> getModuleServices() {
         // TODO Auto-generated method stub
@@ -199,13 +203,12 @@
         //testTask.reschedule(20, TimeUnit.SECONDS);
     }
 
-
     @Override
     public void receive(Switch sw, Port inPort, Ethernet payload) {
         if (payload.getEtherType() == Ethernet.TYPE_ARP)
             arpHandler.processPacketIn(sw, inPort, payload);
         if (payload.getEtherType() == Ethernet.TYPE_IPV4) {
-            addPacket((IPv4) payload.getPayload());
+            addPacketToPacketBuffer((IPv4) payload.getPayload());
             if (((IPv4) payload.getPayload()).getProtocol() == IPv4.PROTOCOL_ICMP)
                 icmpHandler.processPacketIn(sw, inPort, payload);
             else
@@ -216,78 +219,10 @@
         }
     }
 
-    /**
-     * Update ARP Cache using ARP packets It is used to set destination MAC
-     * address to forward packets to known hosts. But, it will be replace with
-     * Host information of Topology service later.
-     *
-     * @param arp APR packets to use for updating ARP entries
-     */
-    public void updateArpCache(ARP arp) {
 
-        ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
-                arp.getSenderProtocolAddress());
-        // TODO: Need to check the duplication
-        arpEntries.add(arpEntry);
-    }
-
-    /**
-     * Get MAC address to known hosts
-     *
-     * @param destinationAddress IP address to get MAC address
-     * @return MAC Address to given IP address
-     */
-    public byte[] getMacAddressFromIpAddress(int destinationAddress) {
-
-        // Can't we get the host IP address from the TopologyService ??
-
-        Iterator<ArpEntry> iterator = arpEntries.iterator();
-
-        IPv4Address ipAddress = IPv4Address.of(destinationAddress);
-        byte[] ipAddressInByte = ipAddress.getBytes();
-
-        while (iterator.hasNext()) {
-            ArpEntry arpEntry = iterator.next();
-            byte[] address = arpEntry.targetIpAddress;
-
-            IPv4Address a = IPv4Address.of(address);
-            IPv4Address b = IPv4Address.of(ipAddressInByte);
-
-            if (a.equals(b)) {
-                log.debug("Found an arp entry");
-                return arpEntry.targetMacAddress;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Send an ARP request via ArpHandler
-     *
-     * @param destinationAddress
-     * @param sw
-     * @param inPort
-     *
-     */
-    public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
-        arpHandler.sendArpRequest(sw, destinationAddress, inPort);
-    }
-
-    /**
-     * Temporary class to to keep ARP entry
-     *
-     */
-    private class ArpEntry {
-
-        byte[] targetMacAddress;
-        byte[] targetIpAddress;
-
-        private ArpEntry(byte[] macAddress, byte[] ipAddress) {
-            this.targetMacAddress = macAddress;
-            this.targetIpAddress = ipAddress;
-        }
-    }
+    // ************************************
+    // Topology event handlers
+    // ************************************
 
     /**
      * Topology events that have been generated.
@@ -400,17 +335,6 @@
     }
 
     /**
-     * Add the link immediately
-     * The function is scheduled when link add event happens and called
-     * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
-     */
-    private void delayedAddLink() {
-
-        processLinkAdd(linksToAdd.values(), true);
-
-    }
-
-    /**
      * Process the SwitchAdded events from topologyMananger.
      * It does nothing. When a switch is added, then link will be added too.
      * LinkAdded event will handle process all re-computation.
@@ -595,6 +519,22 @@
     }
 
     /**
+     * Add the link immediately
+     * The function is scheduled when link add event happens and called
+     * DELAY_TO_ADD_LINK seconds after the event to avoid link flip-flop.
+     */
+    private void delayedAddLink() {
+
+        processLinkAdd(linksToAdd.values(), true);
+
+    }
+
+
+    // ************************************
+    // ECMP shorted path routing functions
+    // ************************************
+
+    /**
      * Populate routing rules walking through the ECMP shortest paths
      *
      * @param modified if true, it "modifies" the rules
@@ -679,100 +619,6 @@
 
     }
 
-
-    /**
-     * This class is used only for link recovery optimization in
-     * modifyEcmpRoutingRules() function.
-     * TODO: please remove if the optimization is not used at all
-     */
-    private class SwitchPair {
-        private Switch src;
-        private Switch dst;
-
-        public SwitchPair(Switch src, Switch dst) {
-            this.src = src;
-            this.dst = dst;
-        }
-
-        public Switch getSource() {
-            return src;
-        }
-
-        public Switch getDestination() {
-            return dst;
-        }
-    }
-
-    /**
-     * Modify the routing rules for the lost links
-     * - Recompute the path if the link failed is included in the path
-     * (including src and dest).
-     *
-     * @param newLink
-     */
-    private void modifyEcmpRoutingRules(LinkData linkRemoved) {
-
-        //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
-        Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
-
-        for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
-            Switch rootSw = ecmpSPG.getRootSwitch();
-            HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
-                    ecmpSPG.getCompleteLearnedSwitchesAndPaths();
-            for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
-                for (Switch destSw: p.keySet()) {
-                    ArrayList<Path> path = p.get(destSw);
-                    if  (checkPath(path, linkRemoved)) {
-                        boolean found = false;
-                        for (SwitchPair pair: linksToRecompute) {
-                            if (pair.getSource().getDpid() == rootSw.getDpid() &&
-                                    pair.getSource().getDpid() == destSw.getDpid()) {
-                                found = true;
-                            }
-                        }
-                        if (!found) {
-                            linksToRecompute.add(new SwitchPair(rootSw, destSw));
-                        }
-                    }
-                }
-            }
-        }
-
-        // Recompute the path for the specific route
-        for (SwitchPair pair: linksToRecompute) {
-
-            log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
-            // We need the following function for optimization
-            //ECMPShortestPathGraph ecmpSPG =
-            //     new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
-            ECMPShortestPathGraph ecmpSPG =
-                    new ECMPShortestPathGraph(pair.getSource());
-            populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
-        }
-    }
-
-    /**
-     * Check if the path is affected from the link removed
-     *
-     * @param path Path to check
-     * @param linkRemoved link removed
-     * @return true if the path contains the link removed
-     */
-    private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
-
-        for (Path ppp: path) {
-            // TODO: need to check if this is a bidirectional or
-            // unidirectional
-            for (LinkData link: ppp) {
-                if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
-                        link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
-                    return true;
-            }
-        }
-
-        return false;
-    }
-
     /**
      *
      * Set routing rules in targetSw {forward packets to fwdToSw switches in
@@ -869,38 +715,6 @@
     }
 
     /**
-     * Check if the switch is the edge router or not.
-     *
-     * @param dpid Dpid of the switch to check
-     * @return true if it is an edge router, otherwise false
-     */
-    private boolean IsEdgeRouter(String dpid) {
-
-        for (Switch sw : mutableTopology.getSwitches()) {
-            String dpidStr = sw.getDpid().toString();
-            if (dpid.equals(dpidStr)) {
-                /*
-                String subnetInfo = sw.getStringAttribute("subnets");
-                if (subnetInfo == null || subnetInfo.equals("[]")) {
-                    return false;
-                }
-                else
-                    return true;
-                */
-                String isEdge = sw.getStringAttribute("isEdgeRouter");
-                if (isEdge != null) {
-                    if (isEdge.equals("true"))
-                        return true;
-                    else
-                        return false;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
      * Set IP forwarding rule - If the destination is the next hop, then do not
      * push MPLS, just decrease the NW TTL - Otherwise, push MPLS label and set
      * the MPLS ID
@@ -1104,6 +918,51 @@
         }
     }
 
+
+    // ************************************
+    // Policy routing classes and functions
+    // ************************************
+
+    class PolicyRouteInfo {
+
+        String srcSwDpid;
+        List<Dpid> fwdSwDpids;
+        List<String> route;
+
+        PolicyRouteInfo() {
+            fwdSwDpids = new ArrayList<Dpid>();
+            route = new ArrayList<String>();
+        }
+
+        void setSrcDpid(String dpid) {
+            this.srcSwDpid = dpid;
+        }
+
+        void setFwdSwDpid(List<Dpid> dpid) {
+            this.fwdSwDpids = dpid;
+        }
+
+        void addRoute(String id) {
+            route.add(id);
+        }
+
+        void setRoute(List<String> r) {
+            this.route = r;
+        }
+
+        String getSrcSwDpid() {
+            return this.srcSwDpid;
+        }
+
+        List<Dpid> getFwdSwDpid() {
+            return this.fwdSwDpids;
+        }
+
+        List<String> getRoute() {
+            return this.route;
+        }
+    }
+
     /**
      * Create a tunnel for policy routing
      * It delivers the node IDs of tunnels to driver.
@@ -1224,216 +1083,6 @@
     }
 
     /**
-     * Get the forwarding Switch DPIDs to send packets to a node
-     *
-     * @param srcSw source switch
-     * @param nodeId destination node Id
-     * @return list of switch DPID to forward packets to
-     */
-
-    private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
-
-        List<Dpid> fwdSws = new ArrayList<Dpid>();
-        Switch destSw = null;
-
-        destSw = getSwitchFromNodeId(nodeId);
-
-        if (destSw == null) {
-            log.debug("Cannot find the switch with ID {}", nodeId);
-            return null;
-        }
-
-        ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
-
-        HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
-                ecmpSPG.getAllLearnedSwitchesAndVia();
-        for (Integer itrIdx : switchVia.keySet()) {
-            HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
-                    switchVia.get(itrIdx);
-            for (Switch targetSw : swViaMap.keySet()) {
-                String destSwDpid = destSw.getDpid().toString();
-                if (targetSw.getDpid().toString().equals(destSwDpid)) {
-                    for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
-                        if (via.isEmpty()) {
-                            fwdSws.add(destSw.getDpid());
-                        }
-                        else {
-                            fwdSws.add(via.get(0));
-                        }
-                    }
-                }
-            }
-        }
-
-        return fwdSws;
-    }
-
-    /**
-     * Get switch for the node Id specified
-     *
-     * @param nodeId node ID for switch
-     * @return Switch
-     */
-    private Switch getSwitchFromNodeId(String nodeId) {
-
-        for (Switch sw : mutableTopology.getSwitches()) {
-            String id = sw.getStringAttribute("nodeSid");
-            if (id.equals(nodeId)) {
-                return sw;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Convert a string DPID to its Switch Id (integer)
-     *
-     * @param dpid
-     * @return
-     */
-    private long getSwId(String dpid) {
-
-        long swId = 0;
-
-        String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
-        if (swIdHexStr != null)
-            swId = Integer.decode(swIdHexStr);
-
-        return swId;
-    }
-
-    private void runTest() {
-
-        String[] routeArray = {"101", "102", "103", "104", "105", "108", "110"};
-        List<String> routeList = new ArrayList<String>();
-        for (int i = 0; i < routeArray.length; i++)
-            routeList.add(routeArray[i]);
-
-        if (createTunnel(1, routeList)) {
-            IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
-            IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
-
-            this.setPolicyTable(null, null, Ethernet.TYPE_IPV4, srcIp, dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
-        }
-        else {
-            testTask.reschedule(5, TimeUnit.SECONDS);
-        }
-    }
-
-    private void runTest1() {
-
-        String dpid1 = "00:00:00:00:00:00:00:01";
-        String dpid2 = "00:00:00:00:00:00:00:0a";
-        Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
-        Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
-
-        if (srcSw == null || dstSw == null) {
-            testTask.reschedule(1, TimeUnit.SECONDS);
-            log.debug("Switch is gone. Reschedule the test");
-            return;
-        }
-
-        String[] routeArray = {"101", "102", "105", "108", "110"};
-        List<String> routeList = new ArrayList<String>();
-        for (int i = 0; i < routeArray.length; i++)
-            routeList.add(routeArray[i]);
-
-        List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
-
-        log.debug("Test set is {}", routeList.toString());
-        log.debug("Result set is {}", optimizedRoute.toString());
-
-
-    }
-
-    /**
-     * Optimize the mpls label
-     * The feature will be used only for policy of "avoid a specific switch".
-     * Check route to each router in route backward.
-     * If there is only one route to the router and the routers are included in
-     * the route, remove the id from the path.
-     * A-B-C-D-E  => A-B-C-D-E -> A-E
-     *   |   |    => A-B-H-I   -> A-I
-     *   F-G-H-I  => A-D-I     -> A-D-I
-     */
-    private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
-
-        List<String> optimizedPath = new ArrayList<String>();
-        optimizedPath.addAll(route);
-        ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
-
-        HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
-                ecmpSPG.getCompleteLearnedSwitchesAndPaths();
-        for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
-            for (Switch s: p.keySet()) {
-                if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
-                    ArrayList<Path> ecmpPaths = p.get(s);
-                    if (ecmpPaths!= null && ecmpPaths.size() == 1) {
-                        for (Path path: ecmpPaths) {
-                            for (LinkData link: path) {
-                                String srcId = getMplsLabel(link.getSrc().getDpid().toString());
-                                String dstId = getMplsLabel(link.getSrc().getDpid().toString());
-                                if (optimizedPath.contains(srcId)) {
-                                    optimizedPath.remove(srcId);
-                                }
-                                if (optimizedPath.contains(dstId)) {
-                                    optimizedPath.remove(dstId);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        return optimizedPath;
-
-    }
-
-
-    class PolicyRouteInfo {
-
-        String srcSwDpid;
-        List<Dpid> fwdSwDpids;
-        List<String> route;
-
-        PolicyRouteInfo() {
-            fwdSwDpids = new ArrayList<Dpid>();
-            route = new ArrayList<String>();
-        }
-
-        void setSrcDpid(String dpid) {
-            this.srcSwDpid = dpid;
-        }
-
-        void setFwdSwDpid(List<Dpid> dpid) {
-            this.fwdSwDpids = dpid;
-        }
-
-        void addRoute(String id) {
-            route.add(id);
-        }
-
-        void setRoute(List<String> r) {
-            this.route = r;
-        }
-
-        String getSrcSwDpid() {
-            return this.srcSwDpid;
-        }
-
-        List<Dpid> getFwdSwDpid() {
-            return this.fwdSwDpids;
-        }
-
-        List<String> getRoute() {
-            return this.route;
-        }
-    }
-
-
-    /**
      *
      *
      * @param srcSw
@@ -1528,96 +1177,120 @@
         return rules;
     }
 
+
+    // ************************************
+    // Utility functions
+    // ************************************
+
     /**
-     * print tunnel info - used only for debugging.
-     * @param targetSw
+     * Get the forwarding Switch DPIDs to send packets to a node
      *
-     * @param fwdSwDpids
-     * @param ids
-     * @param tunnelId
+     * @param srcSw source switch
+     * @param nodeId destination node Id
+     * @return list of switch DPID to forward packets to
      */
-    private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
-            List<String> ids, NeighborSet ns) {
-        StringBuilder logStr = new StringBuilder("In switch " +
-            targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
-        for (String id: ids)
-            logStr.append(id + "-");
-        logStr.append(" output to ");
-        for (Dpid dpid: ns.getDpids())
-            logStr.append(dpid + " - ");
+    private List<Dpid> getForwardingSwitchForNodeId(Switch srcSw, String nodeId) {
 
-        log.debug(logStr.toString());
+        List<Dpid> fwdSws = new ArrayList<Dpid>();
+        Switch destSw = null;
 
+        destSw = getSwitchFromNodeId(nodeId);
+
+        if (destSw == null) {
+            log.debug("Cannot find the switch with ID {}", nodeId);
+            return null;
+        }
+
+        ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
+
+        HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchVia =
+                ecmpSPG.getAllLearnedSwitchesAndVia();
+        for (Integer itrIdx : switchVia.keySet()) {
+            HashMap<Switch, ArrayList<ArrayList<Dpid>>> swViaMap =
+                    switchVia.get(itrIdx);
+            for (Switch targetSw : swViaMap.keySet()) {
+                String destSwDpid = destSw.getDpid().toString();
+                if (targetSw.getDpid().toString().equals(destSwDpid)) {
+                    for (ArrayList<Dpid> via : swViaMap.get(targetSw)) {
+                        if (via.isEmpty()) {
+                            fwdSws.add(destSw.getDpid());
+                        }
+                        else {
+                            fwdSws.add(via.get(0));
+                        }
+                    }
+                }
+            }
+        }
+
+        return fwdSws;
     }
 
+    /**
+     * Get switch for the node Id specified
+     *
+     * @param nodeId node ID for switch
+     * @return Switch
+     */
+    private Switch getSwitchFromNodeId(String nodeId) {
 
+        for (Switch sw : mutableTopology.getSwitches()) {
+            String id = sw.getStringAttribute("nodeSid");
+            if (id.equals(nodeId)) {
+                return sw;
+            }
+        }
+
+        return null;
+    }
 
     /**
-     * Debugging function to print out the Match Action Entry
-     * @param sw13
+     * Convert a string DPID to its Switch Id (integer)
      *
-     * @param maEntry
+     * @param dpid
+     * @return
      */
-    private void printMatchActionOperationEntry(
-            IOF13Switch sw13, MatchActionOperationEntry maEntry) {
+    private long getSwId(String dpid) {
 
-        StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
+        long swId = 0;
 
-        MatchAction ma = maEntry.getTarget();
-        Match m = ma.getMatch();
-        List<Action> actions = ma.getActions();
+        String swIdHexStr = "0x"+dpid.substring(dpid.lastIndexOf(":") + 1);
+        if (swIdHexStr != null)
+            swId = Integer.decode(swIdHexStr);
 
-        if (m instanceof Ipv4Match) {
-            logStr.append("If the IP matches with ");
-            IPv4Net ip = ((Ipv4Match) m).getDestination();
-            logStr.append(ip.toString());
-            logStr.append(" then ");
-        }
-        else if (m instanceof MplsMatch) {
-            logStr.append("If the MPLS label matches with ");
-            int mplsLabel = ((MplsMatch) m).getMplsLabel();
-            logStr.append(mplsLabel);
-            logStr.append(" then ");
-        }
-        else if (m instanceof PacketMatch) {
-            GroupAction ga = (GroupAction)actions.get(0);
-            logStr.append("if the policy match is XXX then go to group " +
-                    ga.getGroupId());
-            log.debug(logStr.toString());
-            return;
-        }
+        return swId;
+    }
 
-        logStr.append(" do { ");
-        for (Action action : actions) {
-            if (action instanceof CopyTtlInAction) {
-                logStr.append("copy ttl In, ");
-            }
-            else if (action instanceof CopyTtlOutAction) {
-                logStr.append("copy ttl Out, ");
-            }
-            else if (action instanceof DecMplsTtlAction) {
-                logStr.append("Dec MPLS TTL , ");
-            }
-            else if (action instanceof GroupAction) {
-                logStr.append("Forward packet to < ");
-                NeighborSet dpids = ((GroupAction) action).getDpids();
-                logStr.append(dpids.toString() + ",");
+    /**
+     * Check if the switch is the edge router or not.
+     *
+     * @param dpid Dpid of the switch to check
+     * @return true if it is an edge router, otherwise false
+     */
+    private boolean IsEdgeRouter(String dpid) {
 
-            }
-            else if (action instanceof PopMplsAction) {
-                logStr.append("Pop MPLS label, ");
-            }
-            else if (action instanceof PushMplsAction) {
-                logStr.append("Push MPLS label, ");
-            }
-            else if (action instanceof SetMplsIdAction) {
-                int id = ((SetMplsIdAction) action).getMplsId();
-                logStr.append("Set MPLS ID as " + id + ", ");
+        for (Switch sw : mutableTopology.getSwitches()) {
+            String dpidStr = sw.getDpid().toString();
+            if (dpid.equals(dpidStr)) {
+                /*
+                String subnetInfo = sw.getStringAttribute("subnets");
+                if (subnetInfo == null || subnetInfo.equals("[]")) {
+                    return false;
+                }
+                else
+                    return true;
+                */
+                String isEdge = sw.getStringAttribute("isEdgeRouter");
+                if (isEdge != null) {
+                    if (isEdge.equals("true"))
+                        return true;
+                    else
+                        return false;
+                }
             }
         }
 
-        log.debug(logStr.toString());
-
+        return false;
     }
 
     /**
@@ -1626,7 +1299,6 @@
      * @param dipid DPID of the switch
      * @return MPLS label for the switch
      */
-
     private String getMplsLabel(String dpid) {
 
         String mplsLabel = null;
@@ -1704,7 +1376,6 @@
      */
     public void addRouteToHost(Switch sw, int hostIpAddress, byte[] hostMacAddress) {
         ipHandler.addRouteToHost(sw, hostIpAddress, hostMacAddress);
-
     }
 
     /**
@@ -1712,7 +1383,7 @@
      *
      * @param ipv4
      */
-    public void addPacket(IPv4 ipv4) {
+    public void addPacketToPacketBuffer(IPv4 ipv4) {
         ipPacketQueue.add(ipv4);
     }
 
@@ -1739,6 +1410,359 @@
         return bufferedPackets;
     }
 
+    /**
+     * Get MAC address to known hosts
+     *
+     * @param destinationAddress IP address to get MAC address
+     * @return MAC Address to given IP address
+     */
+    public byte[] getMacAddressFromIpAddress(int destinationAddress) {
+
+        // Can't we get the host IP address from the TopologyService ??
+
+        Iterator<ArpEntry> iterator = arpEntries.iterator();
+
+        IPv4Address ipAddress = IPv4Address.of(destinationAddress);
+        byte[] ipAddressInByte = ipAddress.getBytes();
+
+        while (iterator.hasNext()) {
+            ArpEntry arpEntry = iterator.next();
+            byte[] address = arpEntry.targetIpAddress;
+
+            IPv4Address a = IPv4Address.of(address);
+            IPv4Address b = IPv4Address.of(ipAddressInByte);
+
+            if (a.equals(b)) {
+                log.debug("Found an arp entry");
+                return arpEntry.targetMacAddress;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Send an ARP request via ArpHandler
+     *
+     * @param destinationAddress
+     * @param sw
+     * @param inPort
+     *
+     */
+    public void sendArpRequest(Switch sw, int destinationAddress, Port inPort) {
+        arpHandler.sendArpRequest(sw, destinationAddress, inPort);
+    }
+
+
+    // ************************************
+    // Test functions
+    // ************************************
+
+    private void runTest() {
+
+        String[] routeArray = {"101", "102", "103", "104", "105", "108", "110"};
+        List<String> routeList = new ArrayList<String>();
+        for (int i = 0; i < routeArray.length; i++)
+            routeList.add(routeArray[i]);
+
+        if (createTunnel(1, routeList)) {
+            IPv4Net srcIp = new IPv4Net("10.0.1.1/24");
+            IPv4Net dstIp = new IPv4Net("10.1.2.1/24");
+
+            this.setPolicyTable(null, null, Ethernet.TYPE_IPV4, srcIp, dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
+        }
+        else {
+            testTask.reschedule(5, TimeUnit.SECONDS);
+        }
+    }
+
+    private void runTest1() {
+
+        String dpid1 = "00:00:00:00:00:00:00:01";
+        String dpid2 = "00:00:00:00:00:00:00:0a";
+        Switch srcSw = mutableTopology.getSwitch(new Dpid(dpid1));
+        Switch dstSw = mutableTopology.getSwitch(new Dpid(dpid2));
+
+        if (srcSw == null || dstSw == null) {
+            testTask.reschedule(1, TimeUnit.SECONDS);
+            log.debug("Switch is gone. Reschedule the test");
+            return;
+        }
+
+        String[] routeArray = {"101", "102", "105", "108", "110"};
+        List<String> routeList = new ArrayList<String>();
+        for (int i = 0; i < routeArray.length; i++)
+            routeList.add(routeArray[i]);
+
+        List<String> optimizedRoute = this.getOptimizedPath(srcSw, dstSw, routeList);
+
+        log.debug("Test set is {}", routeList.toString());
+        log.debug("Result set is {}", optimizedRoute.toString());
+
+
+    }
+
+    /**
+     * print tunnel info - used only for debugging.
+     * @param targetSw
+     *
+     * @param fwdSwDpids
+     * @param ids
+     * @param tunnelId
+     */
+    private void printTunnelInfo(IOF13Switch targetSw, int tunnelId,
+            List<String> ids, NeighborSet ns) {
+        StringBuilder logStr = new StringBuilder("In switch " +
+            targetSw.getId() + ", create a tunnel " + tunnelId + " " + " of push ");
+        for (String id: ids)
+            logStr.append(id + "-");
+        logStr.append(" output to ");
+        for (Dpid dpid: ns.getDpids())
+            logStr.append(dpid + " - ");
+
+        log.debug(logStr.toString());
+
+    }
+
+    /**
+     * Debugging function to print out the Match Action Entry
+     * @param sw13
+     *
+     * @param maEntry
+     */
+    private void printMatchActionOperationEntry(
+            IOF13Switch sw13, MatchActionOperationEntry maEntry) {
+
+        StringBuilder logStr = new StringBuilder("In switch " + sw13.getId() + ", ");
+
+        MatchAction ma = maEntry.getTarget();
+        Match m = ma.getMatch();
+        List<Action> actions = ma.getActions();
+
+        if (m instanceof Ipv4Match) {
+            logStr.append("If the IP matches with ");
+            IPv4Net ip = ((Ipv4Match) m).getDestination();
+            logStr.append(ip.toString());
+            logStr.append(" then ");
+        }
+        else if (m instanceof MplsMatch) {
+            logStr.append("If the MPLS label matches with ");
+            int mplsLabel = ((MplsMatch) m).getMplsLabel();
+            logStr.append(mplsLabel);
+            logStr.append(" then ");
+        }
+        else if (m instanceof PacketMatch) {
+            GroupAction ga = (GroupAction)actions.get(0);
+            logStr.append("if the policy match is XXX then go to group " +
+                    ga.getGroupId());
+            log.debug(logStr.toString());
+            return;
+        }
+
+        logStr.append(" do { ");
+        for (Action action : actions) {
+            if (action instanceof CopyTtlInAction) {
+                logStr.append("copy ttl In, ");
+            }
+            else if (action instanceof CopyTtlOutAction) {
+                logStr.append("copy ttl Out, ");
+            }
+            else if (action instanceof DecMplsTtlAction) {
+                logStr.append("Dec MPLS TTL , ");
+            }
+            else if (action instanceof GroupAction) {
+                logStr.append("Forward packet to < ");
+                NeighborSet dpids = ((GroupAction) action).getDpids();
+                logStr.append(dpids.toString() + ",");
+
+            }
+            else if (action instanceof PopMplsAction) {
+                logStr.append("Pop MPLS label, ");
+            }
+            else if (action instanceof PushMplsAction) {
+                logStr.append("Push MPLS label, ");
+            }
+            else if (action instanceof SetMplsIdAction) {
+                int id = ((SetMplsIdAction) action).getMplsId();
+                logStr.append("Set MPLS ID as " + id + ", ");
+            }
+        }
+
+        log.debug(logStr.toString());
+
+    }
+
+
+    // ************************************
+    // Unused classes and functions
+    // ************************************
+
+    /**
+     * Temporary class to to keep ARP entry
+     *
+     */
+    private class ArpEntry {
+
+        byte[] targetMacAddress;
+        byte[] targetIpAddress;
+
+        private ArpEntry(byte[] macAddress, byte[] ipAddress) {
+            this.targetMacAddress = macAddress;
+            this.targetIpAddress = ipAddress;
+        }
+    }
+
+    /**
+     * This class is used only for link recovery optimization in
+     * modifyEcmpRoutingRules() function.
+     * TODO: please remove if the optimization is not used at all
+     */
+    private class SwitchPair {
+        private Switch src;
+        private Switch dst;
+
+        public SwitchPair(Switch src, Switch dst) {
+            this.src = src;
+            this.dst = dst;
+        }
+
+        public Switch getSource() {
+            return src;
+        }
+
+        public Switch getDestination() {
+            return dst;
+        }
+    }
+
+    /**
+     * Update ARP Cache using ARP packets It is used to set destination MAC
+     * address to forward packets to known hosts. But, it will be replace with
+     * Host information of Topology service later.
+     *
+     * @param arp APR packets to use for updating ARP entries
+     */
+    public void updateArpCache(ARP arp) {
+
+        ArpEntry arpEntry = new ArpEntry(arp.getSenderHardwareAddress(),
+                arp.getSenderProtocolAddress());
+        // TODO: Need to check the duplication
+        arpEntries.add(arpEntry);
+    }
+
+    /**
+     * Modify the routing rules for the lost links
+     * - Recompute the path if the link failed is included in the path
+     * (including src and dest).
+     *
+     * @param newLink
+     */
+    private void modifyEcmpRoutingRules(LinkData linkRemoved) {
+
+        //HashMap<Switch, SwitchPair> linksToRecompute = new HashMap<Switch, SwitchPair>();
+        Set<SwitchPair> linksToRecompute = new HashSet<SwitchPair>();
+
+        for (ECMPShortestPathGraph ecmpSPG : graphs.values()) {
+            Switch rootSw = ecmpSPG.getRootSwitch();
+            HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
+                    ecmpSPG.getCompleteLearnedSwitchesAndPaths();
+            for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
+                for (Switch destSw: p.keySet()) {
+                    ArrayList<Path> path = p.get(destSw);
+                    if  (checkPath(path, linkRemoved)) {
+                        boolean found = false;
+                        for (SwitchPair pair: linksToRecompute) {
+                            if (pair.getSource().getDpid() == rootSw.getDpid() &&
+                                    pair.getSource().getDpid() == destSw.getDpid()) {
+                                found = true;
+                            }
+                        }
+                        if (!found) {
+                            linksToRecompute.add(new SwitchPair(rootSw, destSw));
+                        }
+                    }
+                }
+            }
+        }
+
+        // Recompute the path for the specific route
+        for (SwitchPair pair: linksToRecompute) {
+
+            log.debug("Recompute path from {} to {}", pair.getSource(), pair.getDestination());
+            // We need the following function for optimization
+            //ECMPShortestPathGraph ecmpSPG =
+            //     new ECMPShortestPathGraph(pair.getSource(), pair.getDestination());
+            ECMPShortestPathGraph ecmpSPG =
+                    new ECMPShortestPathGraph(pair.getSource());
+            populateEcmpRoutingRulesForPath(pair.getSource(), ecmpSPG, true);
+        }
+    }
+
+    /**
+     * Optimize the mpls label
+     * The feature will be used only for policy of "avoid a specific switch".
+     * Check route to each router in route backward.
+     * If there is only one route to the router and the routers are included in
+     * the route, remove the id from the path.
+     * A-B-C-D-E  => A-B-C-D-E -> A-E
+     *   |   |    => A-B-H-I   -> A-I
+     *   F-G-H-I  => A-D-I     -> A-D-I
+     */
+    private List<String> getOptimizedPath(Switch srcSw, Switch dstSw, List<String> route) {
+
+        List<String> optimizedPath = new ArrayList<String>();
+        optimizedPath.addAll(route);
+        ECMPShortestPathGraph ecmpSPG = new ECMPShortestPathGraph(srcSw);
+
+        HashMap<Integer, HashMap<Switch, ArrayList<Path>>> paths =
+                ecmpSPG.getCompleteLearnedSwitchesAndPaths();
+        for (HashMap<Switch, ArrayList<Path>> p: paths.values()) {
+            for (Switch s: p.keySet()) {
+                if (s.getDpid().toString().equals(dstSw.getDpid().toString())) {
+                    ArrayList<Path> ecmpPaths = p.get(s);
+                    if (ecmpPaths!= null && ecmpPaths.size() == 1) {
+                        for (Path path: ecmpPaths) {
+                            for (LinkData link: path) {
+                                String srcId = getMplsLabel(link.getSrc().getDpid().toString());
+                                String dstId = getMplsLabel(link.getSrc().getDpid().toString());
+                                if (optimizedPath.contains(srcId)) {
+                                    optimizedPath.remove(srcId);
+                                }
+                                if (optimizedPath.contains(dstId)) {
+                                    optimizedPath.remove(dstId);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        return optimizedPath;
+
+    }
+
+    /**
+     * Check if the path is affected from the link removed
+     *
+     * @param path Path to check
+     * @param linkRemoved link removed
+     * @return true if the path contains the link removed
+     */
+    private boolean checkPath(ArrayList<Path> path, LinkData linkRemoved) {
+
+        for (Path ppp: path) {
+            // TODO: need to check if this is a bidirectional or
+            // unidirectional
+            for (LinkData link: ppp) {
+                if (link.getDst().getDpid().equals(linkRemoved.getDst().getDpid()) &&
+                        link.getSrc().getDpid().equals(linkRemoved.getSrc().getDpid()))
+                    return true;
+            }
+        }
+
+        return false;
+    }
 
 
 }
