optical intent module

Change-Id: Ifa405ab1d883b293d349f1b66d26a05a0724691f
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java
index d888ed3..e44a01b 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalConnectivityIntentCompiler.java
@@ -3,7 +3,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 import java.util.ArrayList;
-
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -12,24 +12,28 @@
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.CoreService;
 import org.onlab.onos.net.ConnectPoint;
 import org.onlab.onos.net.DefaultEdgeLink;
-
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.Path;
 import org.onlab.onos.net.flow.TrafficSelector;
 import org.onlab.onos.net.flow.TrafficTreatment;
 
-import org.onlab.onos.net.intent.IdGenerator;
 import org.onlab.onos.net.intent.Intent;
 import org.onlab.onos.net.intent.IntentCompiler;
 import org.onlab.onos.net.intent.IntentExtensionService;
-import org.onlab.onos.net.intent.IntentId;
+
 import org.onlab.onos.net.intent.OpticalConnectivityIntent;
 import org.onlab.onos.net.intent.OpticalPathIntent;
-
 import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.topology.LinkWeight;
 import org.onlab.onos.net.topology.PathService;
+import org.onlab.onos.net.topology.Topology;
+import org.onlab.onos.net.topology.TopologyEdge;
+
+import org.onlab.onos.net.topology.TopologyService;
 import org.slf4j.Logger;
 
 /**
@@ -49,14 +53,17 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PathService pathService;
 
-    // protected LinkResourceService resourceService;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
 
-    protected IdGenerator<IntentId> intentIdGenerator;
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
 
     @Activate
     public void activate() {
-        IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
-        intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
         intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
     }
 
@@ -67,29 +74,29 @@
 
     @Override
     public List<Intent> compile(OpticalConnectivityIntent intent) {
-        // TO DO: compute multiple paths using the K-shortest path algorithm
+        // TODO: compute multiple paths using the K-shortest path algorithm
+        List<Intent> retList = new ArrayList<>();
         Path path = calculatePath(intent.getSrcConnectPoint(), intent.getDst());
-        log.info("calculate the lightpath: {}.", path.toString());
+        if (path == null) {
+            return retList;
+        } else {
+            log.info("the computed lightpath is : {}.", path.toString());
+        }
 
         List<Link> links = new ArrayList<>();
         links.add(DefaultEdgeLink.createEdgeLink(intent.getSrcConnectPoint(), true));
         links.addAll(path.links());
         links.add(DefaultEdgeLink.createEdgeLink(intent.getDst(), false));
 
-        // TO DO: choose a wavelength using the first-fit algorithm
         TrafficSelector opticalSelector = null;
         TrafficTreatment opticalTreatment = null;
 
-        List<Intent> retList = new ArrayList<>();
-        int wavelength = assignWavelength(path);
-        log.info("assign the wavelength: {}.", wavelength);
-
         // create a new opticalPathIntent
-        Intent newIntent = new OpticalPathIntent(intentIdGenerator.getNewId(),
-                opticalSelector,
-                opticalTreatment,
+        Intent newIntent = new OpticalPathIntent(intent.appId(),
                 path.src(),
                 path.dst(),
+                opticalSelector,
+                opticalTreatment,
                 path);
 
         retList.add(newIntent);
@@ -97,18 +104,45 @@
         return retList;
     }
 
-    private Path calculatePath(ConnectPoint one, ConnectPoint two) {
-        // TODO: K-shortest path computation algorithm
-        Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
-        if (paths.isEmpty()) {
-            throw new PathNotFoundException("No optical path from " + one + " to " + two);
-        }
-        return paths.iterator().next();
-    }
+    private Path calculatePath(ConnectPoint start, ConnectPoint end) {
+        // TODO: support user policies
+        Topology topology = topologyService.currentTopology();
+        LinkWeight weight = new LinkWeight() {
+            @Override
+            public double weight(TopologyEdge edge) {
+                boolean isOptical = false;
+                String t = edge.link().annotations().value("linkType");
+                if (t.equals("WDM")) {
+                   isOptical = true;
+                }
+                if (isOptical) {
+                    return 1; // optical links
+                } else {
+                    return 10000; // packet links
+                }
+            }
+        };
 
-    private int assignWavelength(Path path) {
-        // TODO: wavelength assignment
-        return 1;
+        Set<Path> paths = topologyService.getPaths(topology,
+                start.deviceId(),
+                end.deviceId(),
+                weight);
+
+        Iterator<Path> itr = paths.iterator();
+        while (itr.hasNext()) {
+            Path path = itr.next();
+            if (path.cost() >= 10000) {
+                itr.remove();
+            }
+        }
+
+        if (paths.isEmpty()) {
+            log.info("No optical path found from " + start + " to " + end);
+            return null;
+        } else {
+            return paths.iterator().next();
+        }
+
     }
 
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java
index 2e4f2fd..1f7ef68 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/OpticalPathIntentInstaller.java
@@ -19,6 +19,7 @@
 import org.onlab.onos.net.flow.CompletedBatchOperation;
 import org.onlab.onos.net.flow.DefaultFlowRule;
 import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.FlowRuleBatchEntry;
 import org.onlab.onos.net.flow.FlowRuleBatchOperation;
@@ -29,6 +30,12 @@
 import org.onlab.onos.net.intent.IntentExtensionService;
 import org.onlab.onos.net.intent.IntentInstaller;
 import org.onlab.onos.net.intent.OpticalPathIntent;
+import org.onlab.onos.net.resource.Lambda;
+import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceRequest;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.resource.ResourceRequest;
+import org.onlab.onos.net.topology.TopologyService;
 import org.slf4j.Logger;
 
 import com.google.common.collect.Lists;
@@ -41,7 +48,6 @@
 
 @Component(immediate = true)
 public class OpticalPathIntentInstaller implements IntentInstaller<OpticalPathIntent> {
-
     private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -53,8 +59,16 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected TopologyService topologyService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkResourceService resourceService;
+
     private ApplicationId appId;
 
+    final static short WAVELENGTH = 80;
+
     @Activate
     public void activate() {
         appId = coreService.registerApplication("org.onlab.onos.net.intent");
@@ -67,42 +81,25 @@
     }
 
     @Override
-    public Future<CompletedBatchOperation> install(OpticalPathIntent intent) {
-        TrafficSelector.Builder builder =
-                DefaultTrafficSelector.builder(intent.selector());
-        Iterator<Link> links = intent.path().links().iterator();
-        ConnectPoint prev = links.next().dst();
-        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
-        while (links.hasNext()) {
-            builder.matchInport(prev.port());
-            Link link = links.next();
-            TrafficTreatment treatment = builder()
-                    .setOutput(link.src().port()).build();
-
-            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
-                    builder.build(),
-                    treatment,
-                    100,   // priority is set to 100
-                    appId,
-                    100); // ROADM may need longer cross-connect time, here it is assumed 100ms.
-
-            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
-            prev = link.dst();
+    public List<FlowRuleBatchOperation> install(OpticalPathIntent intent) {
+        Lambda la = assignWavelength(intent.path().links());
+        if (la == null) {
+            return null;
         }
+        // resourceService.requestResources(la);
+        // la.toInt();
+        //intent.selector().criteria();
 
-        FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
-        Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
-        return future;
-    }
+        //TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
+        //builder.matchLambdaType(la.toInt())
+        //        .matchInport(intent.getSrcConnectPoint().port());
 
-    @Override
-    public Future<CompletedBatchOperation> uninstall(OpticalPathIntent intent) {
         TrafficSelector.Builder builder =
                 DefaultTrafficSelector.builder(intent.selector());
         Iterator<Link> links = intent.path().links().iterator();
         ConnectPoint prev = links.next().dst();
         List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
-
+        // TODO Generate multiple batches
         while (links.hasNext()) {
             builder.matchInport(prev.port());
             Link link = links.next();
@@ -114,15 +111,75 @@
                     treatment,
                     100,
                     appId,
-                    100);
+                    100,
+                    true);
+            rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
+            prev = link.dst();
+        }
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
+    }
 
+    private Lambda assignWavelength(List<Link> links) {
+        // TODO More wavelength assignment algorithm
+        int wavenum = 0;
+        Iterator<Link> itrlink = links.iterator();
+        for (int i = 1; i <= WAVELENGTH; i++) {
+            wavenum = i;
+            boolean found = true;
+            while (itrlink.hasNext()) {
+                Link link = itrlink.next();
+                if (isWavelengthUsed(link, i)) {
+                    found = false;
+                    break;
+                }
+            }
+            // First-Fit wavelength assignment algorithm
+            if (found) {
+                break;
+            }
+        }
+
+        if (wavenum == 0) {
+            return null;
+        }
+
+        Lambda wave = Lambda.valueOf(wavenum);
+        return wave;
+    }
+
+    private boolean isWavelengthUsed(Link link, int i) {
+        Iterable<LinkResourceAllocations> wave = resourceService.getAllocations(link);
+        for (LinkResourceAllocations ir : wave) {
+            //if ir.resources().contains(i) {
+            //}
+        }
+        return false;
+    }
+
+    @Override
+    public List<FlowRuleBatchOperation> uninstall(OpticalPathIntent intent) {
+        TrafficSelector.Builder builder =
+                DefaultTrafficSelector.builder(intent.selector());
+        Iterator<Link> links = intent.path().links().iterator();
+        ConnectPoint prev = links.next().dst();
+        List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+        // TODO Generate multiple batches
+        while (links.hasNext()) {
+            builder.matchInport(prev.port());
+            Link link = links.next();
+            TrafficTreatment treatment = builder()
+                    .setOutput(link.src().port()).build();
+            FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
+                    builder.build(),
+                    treatment,
+                    100,
+                    appId,
+                    100,
+                    true);
             rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
             prev = link.dst();
         }
-
-        FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
-        Future<CompletedBatchOperation> future = flowRuleService.applyBatch(batch);
-        return future;
+        return Lists.newArrayList(new FlowRuleBatchOperation(rules));
     }
 
 }