Added AVOID policy feature : for now it supports only single node to avoid (Sanity check passed)
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/ECMPShortestPathGraph.java b/src/main/java/net/onrc/onos/apps/segmentrouting/ECMPShortestPathGraph.java
index b7fbbc9..f8ba3eb 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/ECMPShortestPathGraph.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/ECMPShortestPathGraph.java
@@ -41,6 +41,11 @@
         calcECMPShortestPathGraph();
     }
 
+    public ECMPShortestPathGraph(Switch rootSw, Switch swToAvoid) {
+        this.rootSwitch = rootSw;
+        calcECMPShortestPathGraph(swToAvoid.getDpid());
+    }
+
     /**
      * Calculates the BFS tree using any provided constraints and Intents.
      */
@@ -122,6 +127,90 @@
         }*/
     }
 
+    /**
+     * Calculates the BFS tree using any provided constraints and Intents.
+     */
+    private void calcECMPShortestPathGraph(Dpid avoid) {
+        switchQueue.add(rootSwitch);
+        int currDistance = 0;
+        distanceQueue.add(currDistance);
+        switchSearched.put(rootSwitch.getDpid(), currDistance);
+        while (!switchQueue.isEmpty()) {
+            Switch sw = switchQueue.poll();
+            Switch prevSw = null;
+            currDistance = distanceQueue.poll();
+            for (Link link : sw.getOutgoingLinks()) {
+                Switch reachedSwitch = link.getDstPort().getSwitch();
+                if (reachedSwitch.getDpid().equals(avoid))
+                    continue;
+                if ((prevSw != null)
+                        && (prevSw.getDpid().equals(reachedSwitch.getDpid())))
+                {
+                    /* Ignore LAG links between the same set of switches */
+                    continue;
+                }
+                else
+                {
+                    prevSw = reachedSwitch;
+                }
+
+                Integer distance = switchSearched.get(reachedSwitch.getDpid());
+                if ((distance != null) && (distance.intValue() < (currDistance + 1))) {
+                    continue;
+                }
+                if (distance == null) {
+                    /* First time visiting this switch node */
+                    switchQueue.add(reachedSwitch);
+                    distanceQueue.add(currDistance + 1);
+                    switchSearched.put(reachedSwitch.getDpid(), currDistance + 1);
+
+                    ArrayList<Switch> distanceSwArray = distanceSwitchMap
+                            .get(currDistance + 1);
+                    if (distanceSwArray == null)
+                    {
+                        distanceSwArray = new ArrayList<Switch>();
+                        distanceSwArray.add(reachedSwitch);
+                        distanceSwitchMap.put(currDistance + 1, distanceSwArray);
+                    }
+                    else
+                        distanceSwArray.add(reachedSwitch);
+                }
+
+                ArrayList<LinkData> upstreamLinkArray =
+                        upstreamLinks.get(reachedSwitch.getDpid());
+                if (upstreamLinkArray == null)
+                {
+                    upstreamLinkArray = new ArrayList<LinkData>();
+                    upstreamLinkArray.add(new LinkData(link));
+                    upstreamLinks.put(reachedSwitch.getDpid(), upstreamLinkArray);
+                }
+                else
+                    /* ECMP links */
+                    upstreamLinkArray.add(new LinkData(link));
+            }
+        }
+
+        /*
+        log.debug("ECMPShortestPathGraph:switchSearched for switch {} is {}",
+                HexString.toHexString(rootSwitch.getDpid().value()), switchSearched);
+        log.debug("ECMPShortestPathGraph:upstreamLinks for switch {} is {}",
+                HexString.toHexString(rootSwitch.getDpid().value()), upstreamLinks);
+        log.debug("ECMPShortestPathGraph:distanceSwitchMap for switch {} is {}",
+                HexString.toHexString(rootSwitch.getDpid().value()), distanceSwitchMap);
+        */
+        /*
+        for (Integer distance: distanceSwitchMap.keySet()){
+                for (Switch sw: distanceSwitchMap.get(distance)){
+                        ArrayList<Path> path = getPath(sw);
+                        log.debug("ECMPShortestPathGraph:Paths in Pass{} from switch {} to switch {} is {}",
+                                        distance,
+                                        HexString.toHexString(rootSwitch.getDpid().value()),
+                                        HexString.toHexString(sw.getDpid().value()), path);
+                }
+        }*/
+    }
+
+
     private void getDFSPaths(Dpid dstSwitchDpid, Path path, ArrayList<Path> paths) {
         Dpid rootSwitchDpid = rootSwitch.getDpid();
         for (LinkData upstreamLink : upstreamLinks.get(dstSwitchDpid)) {
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java b/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
index e8b1b31..9924ad7 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
@@ -7,7 +7,7 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.util.MACAddress;
 import net.onrc.onos.apps.segmentrouting.SegmentRoutingManager.removeTunnelMessages;
-import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
+import net.onrc.onos.core.topology.Link;
 import net.onrc.onos.core.util.IPv4Net;
 
 /**
@@ -51,26 +51,32 @@
      */
     public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
             Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
-            Short srcPort, Short dstPort, int priority, String tid, PolicyType type);
+            Short srcPort, Short dstPort, int priority, String tid);
+
 
     /**
-     * Create a policy for policy based segment routing
+     * Create a policy with the type of avoid
      *
-     * @param pid Unique Policy Identifier
-     * @param srcIP Source IP address in CIDR format
-     * @param dstIP Destination IP address in CIDR format
-     * @param ipProto IP protocol type
-     * @param srcPort Source L4 port
-     * @param dstPort Destination L4 port
-     * @param priority Priority of the policy
-     * @param tid SR Tunnel Id to be associated with this policy
-     *
-     * @return "true/false" depending tunnel creation status
+     * @param pid policy ID
+     * @param srcMac source MAC address of the match
+     * @param dstMac destination MAC address of the match
+     * @param etherType Ethernet Type of the match
+     * @param srcIp source IP address of the match
+     * @param dstIp destination IP address of the match
+     * @param ipProto IP protocol type of the match
+     * @param srcPort source port of the match
+     * @param dstPort destination port of the match
+     * @param priority priority of the policy
+     * @param srcNode source node of the avoid policy
+     * @param dstNode destination node of the avoid policy
+     * @param nodesToAvoid nodes to avoid
+     * @param linksToAvoid links to avoid
+     * @return true if successful, false otherwise
      */
     public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
             Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
-            Short srcPort, Short dstPort, int priority, String tid);
-
+            Short srcPort, Short dstPort, int priority, int srcNode, int dstNode,
+            List<Integer> nodesToAvoid, List<Link> linksToAvoid);
 
     /**
      * Remove a policy given policy Id
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 d1f8966..0eee543 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -139,8 +139,6 @@
     // Flag whether transit router supports ECMP or not
     // private boolean supportTransitECMP = true;
 
-    private int testMode = 0;
-
     private int numOfEvents = 0;
     private int numOfEventProcess = 0;
     private int numOfPopulation = 0;
@@ -153,15 +151,19 @@
     private static final String SR_TUNNEL_CHANNEL_NAME = "onos.sr_tunnel";
 
     private final int DELAY_TO_ADD_LINK = 10;
-    private final int MAX_NUM_LABELS = 3;
 
-    private final int POLICY_ADD1 = 1;
-    private final int POLICY_ADD2 = 2;
-    private final int POLICY_REMOVE1 = 3;
-    private final int POLICY_REMOVE2 = 4;
-    private final int TUNNEL_REMOVE1 = 5;
-    private final int TUNNEL_REMOVE2 = 6;
+    private enum TEST_MODE {
+        NO_TEST,
+        POLICY_ADD1,
+        POLICY_ADD2,
+        POLICY_REMOVE1,
+        POLICY_REMOVE2,
+        TUNNEL_REMOVE1,
+        TUNNEL_REMOVE2,
+        POLICY_AVOID
+    }
 
+    private TEST_MODE testMode = TEST_MODE.NO_TEST;
 
     // ************************************
     // IFloodlightModule implementation
@@ -272,7 +274,7 @@
             }
         });
 
-        testMode = POLICY_ADD1;
+        //testMode = TEST_MODE.POLICY_AVOID;
         //testTask.reschedule(20, TimeUnit.SECONDS);
     }
 
@@ -1343,28 +1345,13 @@
     }
 
     /**
-     *  Create a policy
-     *  TODO: To be removed
+     *  Create a policy with tunnel type
      */
     @Override
     public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
             Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
             Short srcPort, Short dstPort, int priority, String tid) {
 
-        return createPolicy(pid, srcMac, dstMac, etherType, srcIp, dstIp, ipProto,
-                srcPort, dstPort, priority, tid, PolicyType.TUNNEL_FLOW);
-    }
-
-    /**
-     * Create a policy
-     *
-     */
-    @Override
-    public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
-            Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
-            Short srcTcpPort, Short dstTcpPort, int priority, String tid,
-            PolicyType type) {
-
         // Sanity check
         SegmentRoutingTunnel tunnelInfo = tunnelTable.get(tid);
         if (tunnelInfo == null) {
@@ -1372,65 +1359,68 @@
             return false;
         }
 
-        PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
+        PacketMatch policyMatch = buildPacketMatch(srcMac, dstMac, etherType,
+                srcIp, dstIp, ipProto, srcPort, dstPort);
 
-        if (srcMac != null)
-            packetBuilder.setSrcMac(srcMac);
-        if (dstMac != null)
-            packetBuilder.setDstMac(dstMac);
-        if (etherType == null) // Cqpd requires the type of IPV4
-            packetBuilder.setEtherType(Ethernet.TYPE_IPV4);
-        else
-            packetBuilder.setEtherType(etherType);
-        if (srcIp != null)
-            packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
-        if (dstIp != null)
-            packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
-        if (ipProto != null)
-            packetBuilder.setIpProto(ipProto);
-        if (srcTcpPort > 0)
-            packetBuilder.setSrcTcpPort(srcTcpPort);
-        if (dstTcpPort > 0)
-            packetBuilder.setDstTcpPort(dstTcpPort);
-        PacketMatch policyMatch = packetBuilder.build();
-
-        if (type == PolicyType.TUNNEL_FLOW) {
-            SegmentRoutingPolicy srPolicy =
-                    new SegmentRoutingPolicyTunnel(this,pid, type, policyMatch,
-                           priority, tid);
-            if (srPolicy.createPolicy()) {
-                policyTable.put(pid, srPolicy);
-                PolicyNotification policyNotification =
-                        new PolicyNotification(srPolicy);
-                policyEventChannel.addEntry(pid,
-                        policyNotification);
-                return true;
-            }
-            else {
-                log.warn("Failed to create a policy");
-                return false;
-            }
+        SegmentRoutingPolicy srPolicy =
+                new SegmentRoutingPolicyTunnel(this,pid, PolicyType.TUNNEL_FLOW,
+                        policyMatch, priority, tid);
+        if (srPolicy.createPolicy()) {
+            policyTable.put(pid, srPolicy);
+            PolicyNotification policyNotification =
+                    new PolicyNotification(srPolicy);
+            policyEventChannel.addEntry(pid,
+                    policyNotification);
+            return true;
         }
         else {
-            log.warn("No other policy is supported yet.");
+            log.warn("Failed to create a policy");
+            return false;
+        }
+    }
+
+    /**
+     * Create a policy with avoid type
+     */
+    @Override
+    public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
+            Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
+            Short srcPort, Short dstPort, int priority, int srcNode, int dstNode,
+            List<Integer> nodesToAvoid, List<Link> linksToAvoid) {
+
+        PacketMatch policyMatch = buildPacketMatch(srcMac, dstMac, etherType,
+                srcIp, dstIp, ipProto, srcPort, dstPort);
+
+        Switch srcSwitch = mutableTopology.getSwitch(new Dpid(srcNode));
+        Switch dstSwitch = mutableTopology.getSwitch(new Dpid(dstNode));
+        Switch swToAvoid =
+                mutableTopology.getSwitch(new Dpid(nodesToAvoid.get(0)));
+        if (srcSwitch == null || dstSwitch == null || swToAvoid == null) {
+            log.warn("Switches are not found!");
+            return false;
+        }
+
+        SegmentRoutingPolicy avoidPolicy = new SegmentRoutingPolicyAvoid(this,
+                pid, policyMatch, priority, srcSwitch, dstSwitch, swToAvoid);
+        if (avoidPolicy.createPolicy()) {
+            policyTable.put(pid, avoidPolicy);
+            // TODO: handle multi-instance
+            //PolicyNotification policyNotification =
+            //        new PolicyNotification(avoidPolicy);
+            //policyEventChannel.addEntry(pid,
+            //        policyNotification);
+            return true;
+        }
+        else {
+            log.warn("Error in creating an avoid policy");
             return false;
         }
     }
 
     /**
      * Remove all policies applied to specific tunnel.
-     *
-     * @param srcMac
-     * @param dstMac
-     * @param etherType
-     * @param srcIp
-     * @param dstIp
-     * @param ipProto
-     * @param srcTcpPort
-     * @param dstTcpPort
-     * @param tid
-     * @return
      */
+    @Override
     public boolean removePolicy(String pid) {
         //Sanity check
         SegmentRoutingPolicy policy =  policyTable.get(pid);
@@ -1534,6 +1524,34 @@
     // return this.matchActionId++;
     // }
 
+    private PacketMatch buildPacketMatch(MACAddress srcMac, MACAddress dstMac,
+            Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
+            Short srcPort, Short dstPort) {
+
+        PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
+
+        if (srcMac != null)
+            packetBuilder.setSrcMac(srcMac);
+        if (dstMac != null)
+            packetBuilder.setDstMac(dstMac);
+        if (etherType == null) // Cqpd requires the type of IPV4
+            packetBuilder.setEtherType(Ethernet.TYPE_IPV4);
+        else
+            packetBuilder.setEtherType(etherType);
+        if (srcIp != null)
+            packetBuilder.setSrcIp(srcIp.address(), srcIp.prefixLen());
+        if (dstIp != null)
+            packetBuilder.setDstIp(dstIp.address(), dstIp.prefixLen());
+        if (ipProto != null)
+            packetBuilder.setIpProto(ipProto);
+        if (srcPort > 0)
+            packetBuilder.setSrcTcpPort(srcPort);
+        if (dstPort > 0)
+            packetBuilder.setDstTcpPort(dstPort);
+
+        return packetBuilder.build();
+    }
+
     /**
      * Get ports for the adjacency SID given
      *
@@ -2068,7 +2086,7 @@
 
     private void runTest() {
 
-        if (testMode == POLICY_ADD1) {
+        if (testMode == TEST_MODE.POLICY_ADD1) {
             Integer[] routeArray = {101, 105, 110};
             /*List<Dpid> routeList = new ArrayList<Dpid>();
             for (int i = 0; i < routeArray.length; i++) {
@@ -2084,7 +2102,7 @@
                 this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
                         dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
                         "1");
-                testMode = POLICY_ADD2;
+                testMode = TEST_MODE.POLICY_ADD2;
                 testTask.reschedule(5, TimeUnit.SECONDS);
             }
             else {
@@ -2092,7 +2110,7 @@
                 testTask.reschedule(5, TimeUnit.SECONDS);
             }
         }
-        else if (testMode == POLICY_ADD2) {
+        else if (testMode == TEST_MODE.POLICY_ADD2) {
             Integer[] routeArray = {101, 102, 103, 104, 105, 108, 110};
 
             if (createTunnel("2", Arrays.asList(routeArray))) {
@@ -2111,31 +2129,79 @@
                 testTask.reschedule(5, TimeUnit.SECONDS);
             }
         }
-        else if (testMode == POLICY_REMOVE2){
+        else if (testMode == TEST_MODE.POLICY_REMOVE2){
             log.debug("Remove the policy 2");
             this.removePolicy("2");
-            testMode = POLICY_REMOVE1;
+            testMode = TEST_MODE.POLICY_REMOVE1;
             testTask.reschedule(5, TimeUnit.SECONDS);
         }
-        else if (testMode == POLICY_REMOVE1){
+        else if (testMode == TEST_MODE.POLICY_REMOVE1){
             log.debug("Remove the policy 1");
             this.removePolicy("1");
 
-            testMode = TUNNEL_REMOVE1;
+            testMode = TEST_MODE.TUNNEL_REMOVE1;
             testTask.reschedule(5, TimeUnit.SECONDS);
         }
-        else if (testMode == TUNNEL_REMOVE1) {
+        else if (testMode == TEST_MODE.TUNNEL_REMOVE1) {
             log.debug("Remove the tunnel 1");
             this.removeTunnel("1");
 
-            testMode = TUNNEL_REMOVE2;
+            testMode = TEST_MODE.TUNNEL_REMOVE2;
             testTask.reschedule(5, TimeUnit.SECONDS);
         }
-        else if (testMode == TUNNEL_REMOVE2) {
+        else if (testMode == TEST_MODE.TUNNEL_REMOVE2) {
             log.debug("Remove the tunnel 2");
             this.removeTunnel("2");
             log.debug("The end of test");
         }
+        else if (testMode == TEST_MODE.POLICY_AVOID) {
+            /*
+            Switch rootSw = mutableTopology.getSwitch(new Dpid(1));
+            Switch swToAvoid = mutableTopology.getSwitch(new Dpid(5));
+            Switch targetSw = mutableTopology.getSwitch(new Dpid(6));
+            ECMPShortestPathGraph graph = new ECMPShortestPathGraph(rootSw, swToAvoid);
+            List<Path> ecmpPaths = graph.getECMPPaths(targetSw);
+            log.debug("Path from {} to {} avoiding {}", rootSw, targetSw, swToAvoid);
+            printEcmpPaths(ecmpPaths);
+
+
+            Switch rootSw2 = mutableTopology.getSwitch(new Dpid(1));
+            Switch swToAvoid2 = mutableTopology.getSwitch(new Dpid(3));
+            Switch targetSw2 = mutableTopology.getSwitch(new Dpid(6));
+            ECMPShortestPathGraph graph2 = new ECMPShortestPathGraph(rootSw2, swToAvoid2);
+            List<Path> ecmpPaths2 = graph2.getECMPPaths(targetSw2);
+            log.debug("Path from {} to {} avoiding {}", rootSw2, targetSw2, swToAvoid2);
+            printEcmpPaths(ecmpPaths2);
+            */
+
+            String pid = "p1";
+            MACAddress srcMac = null;
+            MACAddress dstMac = null;
+            Short etherType = Ethernet.TYPE_IPV4;
+            IPv4Net srcIp = new IPv4Net("10.0.1.1/32");
+            IPv4Net dstIp = new IPv4Net("7.7.7.7/32");
+            Byte ipProto = IPv4.PROTOCOL_ICMP;
+            Short srcPort = 0;
+            Short dstPort = 0;
+            int priority = 10000;
+            int srcNode = 1;
+            int dstNode = 6;
+            List<Integer> nodesToAvoid = new ArrayList<Integer>();
+            nodesToAvoid.add(5);
+            List<Link> linksToAvoid = null;
+            createPolicy(pid, srcMac, dstMac, etherType, srcIp, dstIp, ipProto,
+                    srcPort, dstPort, priority, srcNode, dstNode, nodesToAvoid, linksToAvoid);
+
+        }
+    }
+
+    private void printEcmpPaths(List<Path> ecmpPaths) {
+        for (Path path: ecmpPaths) {
+            for (LinkData link: path) {
+                log.debug("{} - {}", link.getSrc().getDpid(), link.getDst().getDpid());
+            }
+            log.debug("----------------------------------");
+        }
     }
 
     private void runTest1() {
@@ -2399,5 +2465,4 @@
     }
 
 
-
 }
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicy.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicy.java
index 81b1870..94f18ad 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicy.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicy.java
@@ -1,6 +1,24 @@
 package net.onrc.onos.apps.segmentrouting;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import net.onrc.onos.core.matchaction.MatchAction;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
+import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
+import net.onrc.onos.core.matchaction.action.GroupAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.action.SetDAAction;
+import net.onrc.onos.core.matchaction.action.SetSAAction;
 import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.topology.Switch;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+
+import org.projectfloodlight.openflow.types.MacAddress;
 
 public class SegmentRoutingPolicy {
 
@@ -47,6 +65,55 @@
         this.type = PolicyType.valueOf(policyNotication.getPolicyType());
     }
 
+    protected void populateAclRule(List<TunnelRouteInfo> routes) {
+        for (TunnelRouteInfo route : routes) {
+            List<Action> actions = new ArrayList<>();
+
+            // Check PHP was done by stitching
+            // If no MPLS label is added, then NW TTL needs to be decremented
+
+            if (route.getRoute().isEmpty()) {
+
+                DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
+                actions.add(decNwTtlAction);
+
+                Switch srcSw = srManager.getSwitch(route.getSrcSwDpid());
+                Switch destSwitch = srManager.getSwitch(route.getFwdSwDpid().get(0).toString());
+                MacAddress srcMac =
+                        MacAddress.of(srcSw.getStringAttribute("routerMac"));
+                MacAddress dstMac =
+                        MacAddress.of(destSwitch.getStringAttribute("routerMac"));
+                SetSAAction setSAAction = new SetSAAction(srcMac);
+                SetDAAction setDAAction = new SetDAAction(dstMac);
+                actions.add(setSAAction);
+                actions.add(setDAAction);
+
+                List<String> fwdSwDpids = new ArrayList<String>();
+                for (Dpid dpid: route.getFwdSwDpid()) {
+                    fwdSwDpids.add(dpid.toString());
+                }
+                PortNumber port = srManager.pickOnePort(srcSw, fwdSwDpids);
+                OutputAction outputAction = new OutputAction(port);
+                actions.add(outputAction);
+            }
+            else {
+                GroupAction groupAction = new GroupAction();
+                groupAction.setGroupId(route.getGroupId());
+                actions.add(groupAction);
+            }
+
+            MatchAction matchAction = new MatchAction(
+                    srManager.getMatchActionId(),
+                    new SwitchPort((new Dpid(route.getSrcSwDpid())).value(), (long)0), match, priority,
+                    actions);
+            MatchActionOperationEntry maEntry =
+                    new MatchActionOperationEntry(Operator.ADD, matchAction);
+
+            srManager.executeMatchActionOpEntry(maEntry);
+
+        }
+    }
+
     /**
      * Get the policy ID
      *
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
index e6b2649..27b98fd 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
@@ -7,18 +7,11 @@
 import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
 import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
 import net.onrc.onos.core.matchaction.action.Action;
-import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
 import net.onrc.onos.core.matchaction.action.GroupAction;
-import net.onrc.onos.core.matchaction.action.OutputAction;
-import net.onrc.onos.core.matchaction.action.SetDAAction;
-import net.onrc.onos.core.matchaction.action.SetSAAction;
 import net.onrc.onos.core.matchaction.match.PacketMatch;
-import net.onrc.onos.core.topology.Switch;
 import net.onrc.onos.core.util.Dpid;
-import net.onrc.onos.core.util.PortNumber;
 import net.onrc.onos.core.util.SwitchPort;
 
-import org.projectfloodlight.openflow.types.MacAddress;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -48,69 +41,7 @@
 
         List<TunnelRouteInfo> routes = tunnelInfo.getRoutes();
 
-        for (TunnelRouteInfo route : routes) {
-            List<Action> actions = new ArrayList<>();
-
-            // Check PHP was done by stitching
-            // If no MPLS label is added, then NW TTL needs to be decremented
-
-            if (route.getRoute().isEmpty()) {
-
-                DecNwTtlAction decNwTtlAction = new DecNwTtlAction(1);
-                actions.add(decNwTtlAction);
-
-                Switch srcSw = srManager.getSwitch(route.getSrcSwDpid());
-                Switch destSwitch = srManager.getSwitch(route.getFwdSwDpid().get(0).toString());
-                MacAddress srcMac =
-                        MacAddress.of(srcSw.getStringAttribute("routerMac"));
-                MacAddress dstMac =
-                        MacAddress.of(destSwitch.getStringAttribute("routerMac"));
-                SetSAAction setSAAction = new SetSAAction(srcMac);
-                SetDAAction setDAAction = new SetDAAction(dstMac);
-                actions.add(setSAAction);
-                actions.add(setDAAction);
-
-                List<String> fwdSwDpids = new ArrayList<String>();
-                for (Dpid dpid: route.getFwdSwDpid()) {
-                    fwdSwDpids.add(dpid.toString());
-                }
-                PortNumber port = srManager.pickOnePort(srcSw, fwdSwDpids);
-                OutputAction outputAction = new OutputAction(port);
-                actions.add(outputAction);
-            }
-            else {
-                GroupAction groupAction = new GroupAction();
-                groupAction.setGroupId(route.getGroupId());
-                actions.add(groupAction);
-            }
-
-            MatchAction matchAction = new MatchAction(
-                    srManager.getMatchActionId(),
-                    new SwitchPort((new Dpid(route.getSrcSwDpid())).value(), (long)0), match, priority,
-                    actions);
-            MatchActionOperationEntry maEntry =
-                    new MatchActionOperationEntry(Operator.ADD, matchAction);
-
-            srManager.executeMatchActionOpEntry(maEntry);
-
-            /*
-            IOF13Switch sw13 = srManager.getIOF13Switch(route.getSrcSwDpid());
-
-            if (sw13 != null) {
-                srManager.printMatchActionOperationEntry(sw13, maEntry);
-                try {
-                    sw13.pushFlow(maEntry);
-                } catch (IOException e) {
-                    e.printStackTrace();
-                    return false;
-                }
-            }
-            else {
-                Log.warn("Cannot find the target switch {}", route.getSrcSwDpid());
-                return false;
-            }
-            */
-        }
+        populateAclRule(routes);
 
         return true;
     }