Xpliant ONOS driver support added

Change-Id: I3691a1d6035a8f7d8727b8bded70339e3df0dd94
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantGroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantGroupHandler.java
new file mode 100644
index 0000000..ca01b3b
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantGroupHandler.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017 Open Networking Foundation
+ *
+ * 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.driver.pipeline;
+
+import org.onosproject.driver.pipeline.ofdpa.Ofdpa3GroupHandler;
+
+
+public class XpliantGroupHandler extends Ofdpa3GroupHandler {
+
+    /**
+     * Determines whether this pipeline support copy ttl instructions or not.
+     *
+     * @return false if copy ttl instructions is not supported
+     */
+    @Override
+    protected boolean supportCopyTtl() {
+        return false;
+    }
+
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java
new file mode 100644
index 0000000..3d09258
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 Open Networking Foundation
+ *
+ * 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.driver.pipeline;
+
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.driver.pipeline.ofdpa.Ofdpa3Pipeline;
+import java.util.Collection;
+
+public class XpliantPipeline extends Ofdpa3Pipeline {
+
+    @Override
+    protected void initDriverId() {
+        driverId = coreService.registerApplication(
+                "org.onosproject.driver.XpliantPipeline");
+    }
+
+    @Override
+    protected void initGroupHander(PipelinerContext context) {
+        groupHandler = new XpliantGroupHandler();
+        groupHandler.init(deviceId, context);
+    }
+
+    @Override
+    protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
+        return processEthTypeSpecificInternal(fwd, true, ACL_TABLE);
+    }
+
+    @Override
+    public boolean requireMplsPop() {
+        return false;
+    }
+
+    @Override
+    public boolean requireMplsBosMatch() {
+        return false;
+    }
+
+    @Override
+    public boolean requireMplsTtlModification() {
+        return false;
+    }
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
index 8641076..bec569e 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
@@ -156,7 +156,7 @@
         return false;
     }
 
-    protected void init(DeviceId deviceId, PipelinerContext context) {
+    public void init(DeviceId deviceId, PipelinerContext context) {
         ServiceDirectory serviceDirectory = context.directory();
         this.deviceId = deviceId;
         this.flowObjectiveStore = context.store();
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
index 430d424..fdefb88 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
@@ -19,6 +19,7 @@
 import com.google.common.collect.Sets;
 import org.onlab.osgi.ServiceDirectory;
 import org.onlab.packet.Ethernet;
+import org.onlab.packet.EthType.EtherType;
 import org.onlab.packet.IpAddress;
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.VlanId;
@@ -65,6 +66,7 @@
 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
 import org.onosproject.net.flowobjective.FilteringObjective;
@@ -197,6 +199,33 @@
     }
 
     /**
+     * Determines whether this pipeline requires MPLS POP instruction.
+     *
+     * @return true to use MPLS POP instruction
+     */
+    public boolean requireMplsPop() {
+        return true;
+    }
+
+    /**
+     * Determines whether this pipeline requires MPLS BOS match.
+     *
+     * @return true to use MPLS BOS match
+     */
+    public boolean requireMplsBosMatch() {
+        return true;
+    }
+
+    /**
+     * Determines whether this pipeline requires MPLS TTL decrement and copy.
+     *
+     * @return true to use MPLS TTL decrement and copy
+     */
+    public boolean requireMplsTtlModification() {
+        return true;
+    }
+
+    /**
      * Determines whether this pipeline requires OFDPA match and set VLAN extensions.
      *
      * @return true to use the extensions
@@ -1175,7 +1204,7 @@
                         selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
             MplsBosCriterion bos = (MplsBosCriterion) selector
                                         .getCriterion(MPLS_BOS);
-            if (bos != null) {
+            if (bos != null && requireMplsBosMatch()) {
                 filteredSelector.matchMplsBos(bos.mplsBos());
             }
             forTableId = MPLS_TABLE_1;
@@ -1189,18 +1218,30 @@
                         popMpls = true;
                         // OF-DPA does not pop in MPLS table in some cases. For the L3 VPN, it requires
                         // setting the MPLS_TYPE so pop can happen down the pipeline
-                        if (mplsNextTable == MPLS_TYPE_TABLE && isNotMplsBos(selector)) {
-                            tb.immediate().popMpls();
+                        if (requireMplsPop()) {
+                            if (mplsNextTable == MPLS_TYPE_TABLE && isNotMplsBos(selector)) {
+                                tb.immediate().popMpls();
+                            }
+                        } else {
+                            // Skip mpls pop action for mpls_unicast label
+                            if (instr instanceof ModMplsHeaderInstruction &&
+                                    !((ModMplsHeaderInstruction) instr).ethernetType()
+                                            .equals(EtherType.MPLS_UNICAST.ethType())) {
+                                tb.immediate().add(instr);
+                            }
                         }
                     }
-                    if (instr instanceof L3ModificationInstruction &&
-                            ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
-                        // FIXME Should modify the app to send the correct DEC_MPLS_TTL instruction
-                        tb.immediate().decMplsTtl();
-                    }
-                    if (instr instanceof L3ModificationInstruction &&
-                            ((L3ModificationInstruction) instr).subtype() == L3SubType.TTL_IN) {
-                        tb.immediate().add(instr);
+
+                    if (requireMplsTtlModification()) {
+                        if (instr instanceof L3ModificationInstruction &&
+                                ((L3ModificationInstruction) instr).subtype() == L3SubType.DEC_TTL) {
+                            // FIXME Should modify the app to send the correct DEC_MPLS_TTL instruction
+                            tb.immediate().decMplsTtl();
+                        }
+                        if (instr instanceof L3ModificationInstruction &&
+                                ((L3ModificationInstruction) instr).subtype() == L3SubType.TTL_IN) {
+                            tb.immediate().add(instr);
+                        }
                     }
                 }
             }
@@ -1592,7 +1633,7 @@
         return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6;
     }
 
-    static VlanId readVlanFromSelector(TrafficSelector selector) {
+    public static VlanId readVlanFromSelector(TrafficSelector selector) {
         if (selector == null) {
             return null;
         }
@@ -1625,12 +1666,12 @@
      *  Utility class that retries sending flows a fixed number of times, even if
      *  some of the attempts are successful. Used only for forwarding objectives.
      */
-    protected final class RetryFlows implements Runnable {
+    public final class RetryFlows implements Runnable {
         int attempts = MAX_RETRY_ATTEMPTS;
         private Collection<FlowRule> retryFlows;
         private ForwardingObjective fwd;
 
-        RetryFlows(ForwardingObjective fwd, Collection<FlowRule> retryFlows) {
+        public RetryFlows(ForwardingObjective fwd, Collection<FlowRule> retryFlows) {
             this.fwd = fwd;
             this.retryFlows = retryFlows;
         }
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index a6b9356..dec58e5 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -95,6 +95,14 @@
                    impl="org.onosproject.driver.extensions.Ofdpa3ExtensionSelectorInterpreter" />
     </driver>
 
+    <driver name="xpliant" extends="ofdpa3"
+            manufacturer="Cavium, Inc\." hwVersion=".*" swVersion=".*">
+        <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
+                   impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/>
+        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+                   impl="org.onosproject.driver.pipeline.XpliantPipeline"/>
+    </driver>
+
     <!--  Driver for OFDPA 3.0 EA* for Qumran based switches.
        ~  Note: driver needs to be configured using onos-netcfg.
       -->