[ONOS-6033] Corsa pipelines should filter the clear deferred actions

Changes:
- Fix for Corsa CDP6410
- Fix for Corsa CDP2100

Change-Id: I5e9d2869c76f8ad65adc697955094dcf6dd101e2
diff --git a/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java b/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java
index f076fda..9a6952f 100644
--- a/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java
+++ b/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultForwardingObjective.java
@@ -181,6 +181,17 @@
         return new Builder();
     }
 
+    /**
+     * Returns a new builder primed to produce entities
+     * patterned after the supplied forwarding objective.
+     *
+     * @param fwd base fwd
+     * @return forwarding objective builder
+     */
+    public static Builder builder(ForwardingObjective fwd) {
+        return new Builder(fwd);
+    }
+
 
     @Override
     public Builder copy() {
diff --git a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/AbstractCorsaPipeline.java b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/AbstractCorsaPipeline.java
index 2133db2..fb32655 100644
--- a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/AbstractCorsaPipeline.java
+++ b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/AbstractCorsaPipeline.java
@@ -48,6 +48,7 @@
 import org.onosproject.net.flow.criteria.IPCriterion;
 import org.onosproject.net.flow.criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
 import org.onosproject.net.flowobjective.FilteringObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveStore;
 import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -80,6 +81,7 @@
 
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.flow.FlowRule.Builder;
+import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -237,7 +239,7 @@
     public void filter(FilteringObjective filteringObjective) {
         if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
             processFilter(filteringObjective,
-                    filteringObjective.op() == Objective.Operation.ADD,
+                    filteringObjective.op() == ADD,
                     filteringObjective.appId());
         } else {
             fail(filteringObjective, ObjectiveError.UNSUPPORTED);
@@ -356,6 +358,7 @@
             case SPECIFIC:
                 return processSpecific(fwd);
             case VERSATILE:
+                fwd = preProcessVersatile(fwd);
                 return processVersatile(fwd);
             default:
                 fail(fwd, ObjectiveError.UNKNOWN);
@@ -394,6 +397,33 @@
         return ImmutableSet.of();
     }
 
+    private ForwardingObjective preProcessVersatile(ForwardingObjective fwd) {
+        // The Corsa devices don't support the clear deferred actions
+        // so for now we have to filter this instruction for the fwd
+        // objectives sent by the Packet Manager before to create the
+        // flow rule
+        if (fwd.treatment().clearedDeferred()) {
+            // First we create a new treatment without the unsupported action
+            TrafficTreatment.Builder noClearTreatment = DefaultTrafficTreatment.builder();
+            fwd.treatment().allInstructions().forEach(noClearTreatment::add);
+            // Then we create a new forwarding objective without the unsupported action
+            ForwardingObjective.Builder noClearFwd = DefaultForwardingObjective.builder(fwd);
+            noClearFwd.withTreatment(noClearTreatment.build());
+            // According to the operation we substitute fwd with the correct objective
+            switch (fwd.op()) {
+                case ADD:
+                    fwd = noClearFwd.add(fwd.context().orElse(null));
+                    break;
+                case REMOVE:
+                    fwd = noClearFwd.remove(fwd.context().orElse(null));
+                    break;
+                default:
+                    log.warn("Unknown operation {}", fwd.op());
+            }
+        }
+        return fwd;
+    }
+
     private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
         log.debug("Processing vesatile forwarding objective");
         TrafficSelector selector = fwd.selector();
diff --git a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaL2OverlayPipeline.java b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaL2OverlayPipeline.java
new file mode 100644
index 0000000..615863c
--- /dev/null
+++ b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaL2OverlayPipeline.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.corsa;
+
+import org.onosproject.driver.pipeline.DefaultSingleTablePipeline;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.slf4j.Logger;
+
+import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Abstraction of the Corsa L2 Overlay pipeline.
+ * This pipeline is single table with groups support.
+ */
+public class CorsaL2OverlayPipeline extends DefaultSingleTablePipeline implements Pipeliner {
+
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    public void forward(ForwardingObjective fwd) {
+        // The Corsa devices don't support the clear deferred actions
+        // so for now we have to filter this instruction for the fwd
+        // objectives sent by the Packet Manager before to create the
+        // flow rule
+        if (fwd.flag() == VERSATILE && fwd.treatment().clearedDeferred()) {
+            // First we create a new treatment without the unsupported action
+            TrafficTreatment.Builder noClearTreatment = DefaultTrafficTreatment.builder();
+            fwd.treatment().allInstructions().forEach(noClearTreatment::add);
+            // Then we create a new forwarding objective without the unsupported action
+            ForwardingObjective.Builder noClearFwd = DefaultForwardingObjective.builder(fwd);
+            noClearFwd.withTreatment(noClearTreatment.build());
+            // According to the operation we substitute fwd with the correct objective
+            switch (fwd.op()) {
+                case ADD:
+                    fwd = noClearFwd.add(fwd.context().orElse(null));
+                    break;
+                case REMOVE:
+                    fwd = noClearFwd.remove(fwd.context().orElse(null));
+                    break;
+                default:
+                    log.warn("Unknown operation {}", fwd.op());
+                    return;
+            }
+        }
+        // Finally we send to the DefaultSingleTablePipeline for the real processing
+        super.forward(fwd);
+    }
+
+}
diff --git a/drivers/corsa/src/main/resources/corsa-drivers.xml b/drivers/corsa/src/main/resources/corsa-drivers.xml
index 377a30e..6ddacb2 100644
--- a/drivers/corsa/src/main/resources/corsa-drivers.xml
+++ b/drivers/corsa/src/main/resources/corsa-drivers.xml
@@ -53,4 +53,9 @@
     <driver name="corsa-CDP6410" extends="corsa-v39"
             manufacturer="Corsa" hwVersion="CDP6410-A00" swVersion="corsa-ovs-datapath 1.4.105.4">
     </driver>
+    <driver name="corsa-l2-overlay" extends="default"
+            manufacturer="Corsa" hwVersion="CDP2.*" swVersion="corsa-ovs-datapath 1.5\..*">
+        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+                   impl="org.onosproject.drivers.corsa.CorsaL2OverlayPipeline"/>
+    </driver>
 </drivers>