Added the function to remove policy rules from routers

Change-Id: Ief6610e15f4125b50a63cb70fa83760202f6b4da
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 8f52964..fca1dfb 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -105,6 +105,9 @@
     private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
     private HashMap<Integer, HashMap<String, PolicyRouteInfo>> stitchInfo;
     private HashMap<Integer, HashMap<String, Integer>> tunnelGroupMap;
+    private HashMap<Integer, HashMap<PacketMatch, Integer>> policyMap;
+
+    private int testMode = 0;
 
     private int numOfEvents = 0;
     private int numOfEventProcess = 0;
@@ -113,6 +116,9 @@
     private final int DELAY_TO_ADD_LINK = 10;
     private final int MAX_NUM_LABELS = 3;
 
+    private final int POLICY_ADD = 1;
+    private final int POLICY_REMOVE = 2;
+
     @Override
     public Collection<Class<? extends IFloodlightService>> getModuleServices() {
         // TODO Auto-generated method stub
@@ -158,6 +164,7 @@
         stitchInfo = new HashMap<Integer, HashMap<String, PolicyRouteInfo>>();
         packetService = context.getServiceImpl(IPacketService.class);
         tunnelGroupMap = new HashMap<Integer, HashMap<String, Integer>>();
+        policyMap = new HashMap<Integer, HashMap<PacketMatch, Integer>>();
 
         packetService.registerPacketListener(this);
         topologyService.addListener(this, false);
@@ -190,11 +197,11 @@
             }
         });
 
-        // policy routing test task
-        //testTask.reschedule(20, TimeUnit.SECONDS);
+        //policy routing test task
+        testMode = POLICY_ADD;
+        testTask.reschedule(20, TimeUnit.SECONDS);
     }
 
-
     @Override
     public void receive(Switch sw, Port inPort, Ethernet payload) {
         if (payload.getEtherType() == Ethernet.TYPE_ARP)
@@ -674,7 +681,6 @@
 
     }
 
-
     /**
      * This class is used only for link recovery optimization in
      * modifyEcmpRoutingRules() function.
@@ -1152,46 +1158,45 @@
         return true;
     }
 
+    public void removeTunnel(int tunnelId) {
+
+    }
+
     /**
      * Set policy table for policy routing
      *
      * @param sw
      * @param mplsLabel
      */
-    public void setPolicyTable(MACAddress srcMac, MACAddress dstMac,
+    public void setPolicyTable(int pid, MACAddress srcMac, MACAddress dstMac,
             Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
             Short srcTcpPort, Short dstTcpPort, int tid) {
 
         HashMap<String, PolicyRouteInfo> routeInfo = stitchInfo.get(Integer.valueOf(tid));
         HashMap<String, Integer> switchGroupPair = tunnelGroupMap.get(Integer.valueOf(tid));
+        HashMap<PacketMatch, Integer> policyInfo = new HashMap<PacketMatch, Integer>();
+
+        PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
+
+        if (srcMac != null)
+            packetBuilder.setSrcMac(srcMac);
+        if (dstMac != null)
+            packetBuilder.setDstMac(dstMac);
+        if (etherType != null)
+            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 packetMatch = packetBuilder.build();
+
         for (String srcDpid: routeInfo.keySet()) {
-
-            PacketMatchBuilder packetBuilder = new PacketMatchBuilder();
-
-            if (srcMac != null)
-                packetBuilder.setSrcMac(srcMac);
-            if (dstMac != null)
-                packetBuilder.setDstMac(dstMac);
-            if (etherType != null) {
-                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();
-
             List<Action> actions = new ArrayList<>();
             GroupAction groupAction = new GroupAction();
             int gropuId = switchGroupPair.get(srcDpid);
@@ -1200,7 +1205,7 @@
 
             MatchAction matchAction = new MatchAction(new MatchActionId(
                     matchActionId++),
-                    new SwitchPort((long) 0, (short) 0), policyMatch, actions);
+                    new SwitchPort((long) 0, (short) 0), packetMatch, actions);
             MatchActionOperationEntry maEntry =
                     new MatchActionOperationEntry(Operator.ADD, matchAction);
 
@@ -1213,9 +1218,65 @@
                     sw13.pushFlow(maEntry);
                 } catch (IOException e) {
                     e.printStackTrace();
+                    log.debug("Policy was not set due to pushFlow() error");
                 }
             }
         }
+        policyInfo.put(packetMatch, Integer.valueOf(tid));
+        policyMap.put(Integer.valueOf(pid), policyInfo);
+    }
+
+    /**
+     * 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
+     */
+    public void removePolicy(int pid) {
+
+        HashMap<PacketMatch, Integer> policyInfo =  policyMap.get(Integer.valueOf(pid));
+        PacketMatch policyMatch = (PacketMatch) policyInfo.keySet().toArray()[0];
+        int tid = policyInfo.get(policyMatch).intValue();
+
+        List<Action> actions = new ArrayList<>();
+        int gropuId = 0; // dummy group ID
+        GroupAction groupAction = new GroupAction();
+        groupAction.setGroupId(gropuId);
+        actions.add(groupAction);
+
+        MatchAction matchAction = new MatchAction(new MatchActionId(
+                matchActionId++),
+                new SwitchPort((long) 0, (short) 0), policyMatch, actions);
+        MatchActionOperationEntry maEntry =
+                new MatchActionOperationEntry(Operator.REMOVE, matchAction);
+
+        HashMap<String, Integer> groupInfo = tunnelGroupMap.get(
+                Integer.valueOf(tid));
+
+        for (String dpid: groupInfo.keySet()) {
+            IOF13Switch sw13 = (IOF13Switch) floodlightProvider.getMasterSwitch(
+                    getSwId(dpid));
+
+            if (sw13 != null) {
+                printMatchActionOperationEntry(sw13, maEntry);
+                try {
+                    sw13.pushFlow(maEntry);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                    log.debug("policy remove failed due to pushFlow() exception");
+                    return;
+                }
+            }
+        }
+
+        log.debug("Policy {} is removed.", pid);
     }
 
     /**
@@ -1300,19 +1361,29 @@
 
     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 (testMode == POLICY_ADD) {
+            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");
+            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);
+                this.setPolicyTable(1, null, null, Ethernet.TYPE_IPV4, srcIp,
+                        dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 1);
+
+                testMode = POLICY_REMOVE;
+                testTask.reschedule(10, TimeUnit.SECONDS);
+            }
+            else {
+                testTask.reschedule(5, TimeUnit.SECONDS);
+            }
         }
-        else {
-            testTask.reschedule(5, TimeUnit.SECONDS);
+        else if (testMode == POLICY_REMOVE) {
+            this.removePolicy(1);
         }
     }
 
@@ -1386,7 +1457,9 @@
 
     }
 
-
+    /**
+     * Strore policy routing info
+     */
     class PolicyRouteInfo {
 
         String srcSwDpid;
@@ -1427,7 +1500,6 @@
         }
     }
 
-
     /**
      *
      *
@@ -1545,8 +1617,6 @@
 
     }
 
-
-
     /**
      * Debugging function to print out the Match Action Entry
      * @param sw13