ONOS-688 (ONOS-1835,1836,1837) :
 - Implements features to create and remove tunnels and tunnel flow policies.
 - Implements REST API to create/show/delete tunnels and policies.
 - Supports only single instance for now.
 - Fix "apply" actions to "write" actions of all flow rules
Change-Id: I3740ed82fed8eab4ab8b03839192da72d3e223f1
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 87282b4..23eb668 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -20,6 +20,7 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.IPv4;
 import org.onlab.util.KryoNamespace;
@@ -60,6 +61,7 @@
 
 import java.net.URI;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentLinkedQueue;
@@ -69,8 +71,9 @@
 import java.util.concurrent.TimeUnit;
 
 @SuppressWarnings("ALL")
+@Service
 @Component(immediate = true)
-public class SegmentRoutingManager {
+public class SegmentRoutingManager implements SegmentRoutingService {
 
     private static Logger log = LoggerFactory
             .getLogger(SegmentRoutingManager.class);
@@ -101,6 +104,7 @@
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected MastershipService mastershipService;
+
     protected ArpHandler arpHandler = null;
     protected IcmpHandler icmpHandler = null;
     protected IpHandler ipHandler = null;
@@ -108,7 +112,10 @@
     protected ApplicationId appId;
     protected DeviceConfiguration deviceConfiguration = null;
 
+
     private DefaultRoutingHandler defaultRoutingHandler = null;
+    private TunnelHandler tunnelHandler = null;
+    private PolicyHandler policyHandler = null;
     private InternalPacketProcessor processor = new InternalPacketProcessor();
     private InternalEventHandler eventHandler = new InternalEventHandler();
 
@@ -165,6 +172,8 @@
         ipHandler = new IpHandler(this);
         routingRulePopulator = new RoutingRulePopulator(this);
         defaultRoutingHandler = new DefaultRoutingHandler(this);
+        tunnelHandler = new TunnelHandler();
+        policyHandler = new PolicyHandler();
 
         packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
         linkService.addListener(new InternalLinkListener());
@@ -187,6 +196,7 @@
 
         defaultRoutingHandler.startPopulationProcess();
         log.info("Started");
+
     }
 
     @Deactivate
@@ -196,6 +206,51 @@
         log.info("Stopped");
     }
 
+
+    @Override
+    public List<Tunnel> getTunnels() {
+        return tunnelHandler.getTunnels();
+    }
+
+    @Override
+    public void createTunnel(Tunnel tunnel) {
+        tunnelHandler.createTunnel(tunnel);
+    }
+
+    @Override
+    public void removeTunnel(Tunnel tunnel) {
+        for (Policy policy: policyHandler.getPolicies()) {
+            if (policy.type() == Policy.Type.TUNNEL_FLOW) {
+                TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
+                if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
+                    log.warn("Cannot remove the tunnel used by a policy");
+                    return;
+                }
+            }
+        }
+        tunnelHandler.removeTunnel(tunnel);
+    }
+
+    @Override
+    public void removePolicy(Policy policy) {
+        policyHandler.removePolicy(policy);
+
+    }
+
+    @Override
+    public void createPolicy(Policy policy) {
+        policyHandler.createPolicy(policy);
+    }
+
+    @Override
+    public List<Policy> getPolicies() {
+        return policyHandler.getPolicies();
+    }
+
+    public Tunnel getTunnel(String tunnelId) {
+        return tunnelHandler.getTunnel(tunnelId);
+    }
+
     /**
      * Returns the GrouopKey object for the device and the NighborSet given.
      *
@@ -211,6 +266,12 @@
         return null;
     }
 
+    /**
+     *
+     * @param deviceId
+     * @param ns
+     * @return
+     */
     public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
 
         if (groupHandlerMap.get(deviceId) != null) {
@@ -223,6 +284,16 @@
         }
     }
 
+    /**
+     *
+     * @param deviceId
+     * @param objectiveId
+     * @return
+     */
+    public boolean removeNextObjective(DeviceId deviceId, int objectiveId) {
+        return groupHandlerMap.get(deviceId).removeGroup(objectiveId);
+    }
+
     private class InternalPacketProcessor implements PacketProcessor {
 
         @Override
@@ -295,7 +366,7 @@
         }
 
         log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
-                  numOfHandlerScheduled);
+                numOfHandlerScheduled);
 
     }
 
@@ -403,4 +474,7 @@
             groupHandler.portDown(port.number());
         }
     }
+
+
+
 }