Adds OfdpaPipelineUtility

Change-Id: I96086e408dd9d7265325414dace512b64a048e9a
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
index 3d09258..b5b202d 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java
@@ -22,6 +22,8 @@
 import org.onosproject.driver.pipeline.ofdpa.Ofdpa3Pipeline;
 import java.util.Collection;
 
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.ACL_TABLE;
+
 public class XpliantPipeline extends Ofdpa3Pipeline {
 
     @Override
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2GroupHandler.java
index 078e120..e4f71c4 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2GroupHandler.java
@@ -225,7 +225,7 @@
         // the transport of a VPWS. The necessary info are contained in the
         // meta selector. In particular we are looking for the case of BoS==False;
         TrafficSelector metaSelector = nextObjective.meta();
-        if (metaSelector != null && Ofdpa2Pipeline.isNotMplsBos(metaSelector)) {
+        if (metaSelector != null && OfdpaPipelineUtility.isNotMplsBos(metaSelector)) {
             // storage for all group keys in the chain of groups created
             List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
             List<GroupInfo> unsentGroups = new ArrayList<>();
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
index 72b2e8a..797d79f 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
@@ -84,6 +84,7 @@
 import static org.onlab.packet.MacAddress.NONE;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*;
 import static org.slf4j.LoggerFactory.getLogger;
 
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
index e9dc316..53d8fe1 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
@@ -51,6 +51,7 @@
 import org.onosproject.net.group.GroupKey;
 import org.slf4j.Logger;
 
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*;
 
 /**
  * Driver for software switch emulation of the OFDPA 2.0 pipeline.
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 b5bf40f..e6cb219 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
@@ -83,6 +83,7 @@
 
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.*;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_MULTICAST_TYPE;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey;
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 e8d172c..330ef49 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
@@ -43,7 +43,6 @@
 import org.onosproject.net.behaviour.PipelinerContext;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.net.driver.Driver;
 import org.onosproject.net.flow.DefaultFlowRule;
 import org.onosproject.net.flow.DefaultTrafficSelector;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -57,8 +56,6 @@
 import org.onosproject.net.flow.criteria.Criterion;
 import org.onosproject.net.flow.criteria.EthCriterion;
 import org.onosproject.net.flow.criteria.EthTypeCriterion;
-import org.onosproject.net.flow.criteria.ExtensionCriterion;
-import org.onosproject.net.flow.criteria.ExtensionSelector;
 import org.onosproject.net.flow.criteria.IPCriterion;
 import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
 import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
@@ -73,8 +70,6 @@
 import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
 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.ModEtherInstruction;
 import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
 import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType;
@@ -110,7 +105,7 @@
 import static org.onlab.packet.MacAddress.NONE;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*;
-import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*;
 import static org.onosproject.net.group.GroupDescription.Type.SELECT;
 import static org.slf4j.LoggerFactory.getLogger;
 import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS;
@@ -122,36 +117,7 @@
     // Timer for the accumulator
     private static final Timer TIMER = new Timer("fwdobj-batching");
     private Accumulator<Pair<ForwardingObjective, Collection<FlowRule>>> accumulator;
-
-    protected static final int PORT_TABLE = 0;
-    protected static final int VLAN_TABLE = 10;
-    protected static final int VLAN_1_TABLE = 11;
-    protected static final int MPLS_L2_PORT_FLOW_TABLE = 13;
-    protected static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16;
-    protected static final int TMAC_TABLE = 20;
-    protected static final int UNICAST_ROUTING_TABLE = 30;
-    protected static final int MULTICAST_ROUTING_TABLE = 40;
-    protected static final int MPLS_TABLE_0 = 23;
-    protected static final int MPLS_TABLE_1 = 24;
-    protected static final int MPLS_L3_TYPE_TABLE = 27;
-    protected static final int MPLS_TYPE_TABLE = 29;
-    protected static final int BRIDGING_TABLE = 50;
-    protected static final int ACL_TABLE = 60;
-    protected static final int MAC_LEARNING_TABLE = 254;
-    protected static final long OFPP_MAX = 0xffffff00L;
-
-    protected static final int HIGHEST_PRIORITY = 0xffff;
-    protected static final int DEFAULT_PRIORITY = 0x8000;
-    protected static final int LOWEST_PRIORITY = 0x0;
-
-    protected static final int MPLS_L2_PORT_PRIORITY = 2;
-    protected static final int MPLS_TUNNEL_ID_BASE = 0x10000;
-    protected static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF;
-
-    protected static final int MPLS_UNI_PORT_MAX = 0x0000FFFF;
-    protected static final int MPLS_NNI_PORT_BASE = 0x00020000;
-    protected static final int MPLS_NNI_PORT_MAX = 0x0002FFFF;
-
+    // Internal objects
     private final Logger log = getLogger(getClass());
     protected ServiceDirectory serviceDirectory;
     protected FlowRuleService flowRuleService;
@@ -174,8 +140,6 @@
     // flows installations to be retried
     private ScheduledExecutorService retryExecutorService
         = newScheduledThreadPool(5, groupedThreads("OfdpaPipeliner", "retry-%d", log));
-    private static final int MAX_RETRY_ATTEMPTS = 10;
-    private static final int RETRY_MS = 1000;
 
     // accumulator executor service
     private ScheduledExecutorService accumulatorExecutorService
@@ -192,7 +156,7 @@
         flowObjectiveStore = context.store();
         deviceService = serviceDirectory.get(DeviceService.class);
         // Init the accumulator, if enabled
-        if (isAccumulatorEnabled()) {
+        if (isAccumulatorEnabled(this)) {
             accumulator = new ForwardingObjectiveAccumulator(context.accumulatorMaxObjectives(),
                                                              context.accumulatorMaxBatchMillis(),
                                                              context.accumulatorMaxIdleMillis());
@@ -220,15 +184,6 @@
         // software switches does require table-miss-entries.
     }
 
-    public boolean isAccumulatorEnabled() {
-        Driver driver = super.data().driver();
-        // we cannot determine the property
-        if (driver == null) {
-            return false;
-        }
-        return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
-    }
-
     /**
      * Determines whether this pipeline requires MPLS POP instruction.
      *
@@ -384,7 +339,7 @@
             @Override
             public void onSuccess(FlowRuleOperations ops) {
                 log.trace("Flow rule operations onSuccess {}", ops);
-                fwdObjs.forEach(Ofdpa2Pipeline::pass);
+                fwdObjs.forEach(OfdpaPipelineUtility::pass);
             }
 
             @Override
@@ -1687,14 +1642,6 @@
         return null;
     }
 
-    protected static void pass(Objective obj) {
-        obj.context().ifPresent(context -> context.onSuccess(obj));
-    }
-
-    protected static void fail(Objective obj, ObjectiveError error) {
-        obj.context().ifPresent(context -> context.onError(obj, error));
-    }
-
     @Override
     public List<String> getNextMappings(NextGroup nextGroup) {
         List<String> mappings = new ArrayList<>();
@@ -1729,119 +1676,6 @@
     }
 
     /**
-     * Returns true iff the given selector matches on BOS==true, indicating that
-     * the selector is trying to match on a label that is bottom-of-stack.
-     *
-     * @param selector the given match
-     * @return true iff BoS==true; false if BOS==false, or BOS matching is not
-     *         expressed in the given selector
-     */
-    static boolean isMplsBos(TrafficSelector selector) {
-        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
-        return bosCriterion != null && bosCriterion.mplsBos();
-    }
-
-    /**
-     * Returns true iff the given selector matches on BOS==false, indicating
-     * that the selector is trying to match on a label that is not the
-     * bottom-of-stack label.
-     *
-     * @param selector the given match
-     * @return true iff BoS==false;
-     *         false if BOS==true, or BOS matching is not expressed in the given selector
-     */
-    static boolean isNotMplsBos(TrafficSelector selector) {
-        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
-        return bosCriterion != null && !bosCriterion.mplsBos();
-    }
-
-    /**
-     * Returns true iff the forwarding objective includes a treatment to pop the
-     * MPLS label.
-     *
-     * @param fwd the given forwarding objective
-     * @return true iff mpls pop treatment exists
-     */
-    static boolean isMplsPop(ForwardingObjective fwd) {
-        if (fwd.treatment() != null) {
-            for (Instruction instr : fwd.treatment().allInstructions()) {
-                if (instr instanceof L2ModificationInstruction
-                        && ((L2ModificationInstruction) instr)
-                                .subtype() == L2SubType.MPLS_POP) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static boolean isIpv6(TrafficSelector selector) {
-        EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE);
-        return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6;
-    }
-
-    static VlanId readVlanFromSelector(TrafficSelector selector) {
-        if (selector == null) {
-            return null;
-        }
-        Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
-        return (criterion == null)
-                ? null : ((VlanIdCriterion) criterion).vlanId();
-    }
-
-    static MacAddress readEthDstFromSelector(TrafficSelector selector) {
-        if (selector == null) {
-            return null;
-        }
-        Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST);
-        return (criterion == null)
-                ? null : ((EthCriterion) criterion).mac();
-    }
-
-    static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
-        if (selector == null) {
-            return null;
-        }
-        Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
-        return (criterion == null) ? null : ((IPCriterion) criterion).ip();
-    }
-
-    private static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
-        if (treatment == null) {
-            return null;
-        }
-        for (Instruction i : treatment.allInstructions()) {
-            if (i instanceof ModVlanIdInstruction) {
-                return ((ModVlanIdInstruction) i).vlanId();
-            }
-        }
-        return null;
-    }
-
-    private static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) {
-        if (treatment == null) {
-            return null;
-        }
-        for (Instruction i : treatment.allInstructions()) {
-            if (i instanceof ModEtherInstruction) {
-                ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i;
-                if (modEtherInstruction.subtype() == L2SubType.ETH_DST) {
-                    return modEtherInstruction.mac();
-                }
-            }
-        }
-        return null;
-    }
-
-    static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) {
-        if (selector == null) {
-            return null;
-        }
-        ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION);
-        return (criterion == null) ? null : criterion.extensionSelector();
-    }
-
-    /**
      *  Utility class that retries sending flows a fixed number of times, even if
      *  some of the attempts are successful. Used only for forwarding objectives.
      */
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java
index e0e5099..e19e2b3 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java
@@ -91,7 +91,7 @@
         );
         if (groupInfo == null) {
             log.error("Could not process nextObj={} in dev:{}", nextObjective.id(), deviceId);
-            Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED);
+            OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED);
             return;
         }
         // We update the chain with the last two groups;
@@ -118,7 +118,7 @@
             log.error("Next Objective for pseudo wire should have at "
                               + "most {} mpls instruction sets. Next Objective Id:{}",
                       MAX_DEPTH_UNPROTECTED_PW, nextObjective.id());
-            Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS);
+            OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.BADPARAMS);
             return;
         }
 
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
index c0418b7..d906953 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java
@@ -58,6 +58,7 @@
 import java.util.Deque;
 import java.util.List;
 
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*;
 import static org.onosproject.driver.extensions.Ofdpa3MplsType.VPWS;
 import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID;
 import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT;
@@ -235,32 +236,6 @@
     }
 
     /**
-     * Determines if the filtering objective will be used for a pseudowire.
-     *
-     * @param filteringObjective
-     * @return True if objective was created for a pseudowire, false otherwise.
-     */
-    private boolean isPseudowire(FilteringObjective filteringObjective) {
-
-
-        if (filteringObjective.meta() != null) {
-
-            TrafficTreatment treatment = filteringObjective.meta();
-            for (Instruction instr : treatment.immediate()) {
-                if (instr.type().equals(Instruction.Type.L2MODIFICATION)) {
-
-                    L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr;
-                    if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) {
-                        return true;
-                    }
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
      * Method to process the pw related filtering objectives.
      *
      * @param portCriterion the in port match
@@ -589,52 +564,6 @@
     }
 
     /**
-     * Utility function to get the mod tunnel id instruction
-     * if present.
-     *
-     * @param treatment the treatment to analyze
-     * @return the mod tunnel id instruction if present,
-     * otherwise null
-     */
-    private ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) {
-        if (treatment == null) {
-            return null;
-        }
-
-        L2ModificationInstruction l2ModificationInstruction;
-        for (Instruction instruction : treatment.allInstructions()) {
-            if (instruction.type() == L2MODIFICATION) {
-                l2ModificationInstruction = (L2ModificationInstruction) instruction;
-                if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) {
-                    return (ModTunnelIdInstruction) l2ModificationInstruction;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Utility function to get the output instruction
-     * if present.
-     *
-     * @param treatment the treatment to analyze
-     * @return the output instruction if present,
-     * otherwise null
-     */
-    private OutputInstruction getOutputInstruction(TrafficTreatment treatment) {
-        if (treatment == null) {
-            return null;
-        }
-
-        for (Instruction instruction : treatment.allInstructions()) {
-            if (instruction.type() == Instruction.Type.OUTPUT) {
-                return (OutputInstruction) instruction;
-            }
-        }
-        return null;
-    }
-
-    /**
      * Helper method for dividing the tunnel instructions from the mpls
      * instructions.
      *
@@ -685,4 +614,5 @@
             }
         }
     }
+
 }
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
index bab63f4..335cfe6 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
@@ -49,7 +49,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
-import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.isNotMplsBos;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.isNotMplsBos;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_GROUP_TYPE_SHIFT;
 import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_MPLS_SUBTYPE_SHIFT;
 import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED;
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java
new file mode 100644
index 0000000..790e340
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2019-present 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.ofdpa;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.ExtensionCriterion;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.MplsBosCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+
+import static org.onosproject.net.behaviour.Pipeliner.ACCUMULATOR_ENABLED;
+import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE;
+import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS;
+import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+
+public final class OfdpaPipelineUtility {
+
+    private OfdpaPipelineUtility() {
+        // Utility classes should not have a public or default constructor.
+    }
+
+    // Ofdpa specific tables number
+    static final int PORT_TABLE = 0;
+    static final int VLAN_TABLE = 10;
+    static final int VLAN_1_TABLE = 11;
+    static final int MPLS_L2_PORT_FLOW_TABLE = 13;
+    static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16;
+    static final int TMAC_TABLE = 20;
+    static final int UNICAST_ROUTING_TABLE = 30;
+    static final int MULTICAST_ROUTING_TABLE = 40;
+    static final int MPLS_TABLE_0 = 23;
+    static final int MPLS_TABLE_1 = 24;
+    static final int MPLS_L3_TYPE_TABLE = 27;
+    static final int MPLS_TYPE_TABLE = 29;
+    static final int BRIDGING_TABLE = 50;
+    public static final int ACL_TABLE = 60;
+    static final int MAC_LEARNING_TABLE = 254;
+
+    // OF max port number
+    static final long OFPP_MAX = 0xffffff00L;
+
+    // Priority values
+    static final int HIGHEST_PRIORITY = 0xffff;
+    static final int DEFAULT_PRIORITY = 0x8000;
+    static final int LOWEST_PRIORITY = 0x0;
+
+    // MPLS L2 table values
+    static final int MPLS_L2_PORT_PRIORITY = 2;
+    static final int MPLS_TUNNEL_ID_BASE = 0x10000;
+    static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF;
+    static final int MPLS_UNI_PORT_MAX = 0x0000FFFF;
+    static final int MPLS_NNI_PORT_BASE = 0x00020000;
+    static final int MPLS_NNI_PORT_MAX = 0x0002FFFF;
+
+    // Flow retry values
+    static final int MAX_RETRY_ATTEMPTS = 10;
+    static final int RETRY_MS = 1000;
+
+    //////////////////////////////
+    // Helper and utility methods
+    //////////////////////////////
+
+    /**
+     * Check whether the accumulator is enabled or not.
+     * @param pipeline the pipeline
+     * @return true if the accumulator is enabled. Otherwise not
+     */
+    static boolean isAccumulatorEnabled(Ofdpa2Pipeline pipeline) {
+        Driver driver = pipeline.data().driver();
+        // we cannot determine the property
+        if (driver == null) {
+            return false;
+        }
+        return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED));
+    }
+
+    static void pass(Objective obj) {
+        obj.context().ifPresent(context -> context.onSuccess(obj));
+    }
+
+    static void fail(Objective obj, ObjectiveError error) {
+        obj.context().ifPresent(context -> context.onError(obj, error));
+    }
+
+    /**
+     * Returns true iff the given selector matches on BOS==true, indicating that
+     * the selector is trying to match on a label that is bottom-of-stack.
+     *
+     * @param selector the given match
+     * @return true iff BoS==true; false if BOS==false, or BOS matching is not
+     *         expressed in the given selector
+     */
+    static boolean isMplsBos(TrafficSelector selector) {
+        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
+        return bosCriterion != null && bosCriterion.mplsBos();
+    }
+
+    /**
+     * Returns true iff the given selector matches on BOS==false, indicating
+     * that the selector is trying to match on a label that is not the
+     * bottom-of-stack label.
+     *
+     * @param selector the given match
+     * @return true iff BoS==false;
+     *         false if BOS==true, or BOS matching is not expressed in the given selector
+     */
+    static boolean isNotMplsBos(TrafficSelector selector) {
+        MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS);
+        return bosCriterion != null && !bosCriterion.mplsBos();
+    }
+
+    /**
+     * Returns true iff the forwarding objective includes a treatment to pop the
+     * MPLS label.
+     *
+     * @param fwd the given forwarding objective
+     * @return true iff mpls pop treatment exists
+     */
+    static boolean isMplsPop(ForwardingObjective fwd) {
+        if (fwd.treatment() != null) {
+            for (Instruction instr : fwd.treatment().allInstructions()) {
+                if (instr instanceof L2ModificationInstruction
+                        && ((L2ModificationInstruction) instr)
+                        .subtype() == L2SubType.MPLS_POP) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true iff the given selector matches on ethtype==ipv6, indicating
+     * that the selector is trying to match on ipv6 traffic.
+     *
+     * @param selector the given match
+     * @return true iff ethtype==ipv6; false otherwise
+     */
+    static boolean isIpv6(TrafficSelector selector) {
+        EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE);
+        return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6;
+    }
+
+    /**
+     * Reads vlan id from selector.
+     *
+     * @param selector the given match
+     * @return the vlan id if found. null otherwise
+     */
+    static VlanId readVlanFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
+        Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID);
+        return (criterion == null)
+                ? null : ((VlanIdCriterion) criterion).vlanId();
+    }
+
+    /**
+     * Reads eth dst from selector.
+     *
+     * @param selector the given match
+     * @return the eth dst if found. null otherwise
+     */
+    static MacAddress readEthDstFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
+        Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST);
+        return (criterion == null)
+                ? null : ((EthCriterion) criterion).mac();
+    }
+
+    /**
+     * Reads ipv4 dst from selector.
+     *
+     * @param selector the given match
+     * @return the ipv4 dst if found. null otherwise
+     */
+    static IpPrefix readIpDstFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
+        Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST);
+        return (criterion == null) ? null : ((IPCriterion) criterion).ip();
+    }
+
+    /**
+     * Reads vlan id from treatment.
+     *
+     * @param treatment the given actions
+     * @return the vlan id if found. null otherwise
+     */
+    static VlanId readVlanFromTreatment(TrafficTreatment treatment) {
+        if (treatment == null) {
+            return null;
+        }
+        for (Instruction i : treatment.allInstructions()) {
+            if (i instanceof ModVlanIdInstruction) {
+                return ((ModVlanIdInstruction) i).vlanId();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Reads eth dst from treatment.
+     *
+     * @param treatment the given actions
+     * @return the eth dst if found. null otherwise
+     */
+    static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) {
+        if (treatment == null) {
+            return null;
+        }
+        for (Instruction i : treatment.allInstructions()) {
+            if (i instanceof ModEtherInstruction) {
+                ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i;
+                if (modEtherInstruction.subtype() == L2SubType.ETH_DST) {
+                    return modEtherInstruction.mac();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Reads extensions from selector.
+     * @param selector the given match
+     * @return the extensions if found. null otherwise
+     */
+    static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) {
+        if (selector == null) {
+            return null;
+        }
+        ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION);
+        return (criterion == null) ? null : criterion.extensionSelector();
+    }
+
+    /**
+     * Determines if the filtering objective will be used for a pseudowire.
+     *
+     * @param filteringObjective the filtering objective
+     * @return True if objective was created for a pseudowire, false otherwise.
+     */
+    static boolean isPseudowire(FilteringObjective filteringObjective) {
+        if (filteringObjective.meta() != null) {
+            TrafficTreatment treatment = filteringObjective.meta();
+            for (Instruction instr : treatment.immediate()) {
+                if (instr.type().equals(Instruction.Type.L2MODIFICATION)) {
+
+                    L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr;
+                    if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Utility function to get the mod tunnel id instruction
+     * if present.
+     *
+     * @param treatment the treatment to analyze
+     * @return the mod tunnel id instruction if present,
+     * otherwise null
+     */
+    static ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) {
+        if (treatment == null) {
+            return null;
+        }
+        L2ModificationInstruction l2ModificationInstruction;
+        for (Instruction instruction : treatment.allInstructions()) {
+            if (instruction.type() == L2MODIFICATION) {
+                l2ModificationInstruction = (L2ModificationInstruction) instruction;
+                if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) {
+                    return (ModTunnelIdInstruction) l2ModificationInstruction;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Utility function to get the output instruction
+     * if present.
+     *
+     * @param treatment the treatment to analyze
+     * @return the output instruction if present,
+     * otherwise null
+     */
+    static Instructions.OutputInstruction getOutputInstruction(TrafficTreatment treatment) {
+        if (treatment == null) {
+            return null;
+        }
+        for (Instruction instruction : treatment.allInstructions()) {
+            if (instruction.type() == Instruction.Type.OUTPUT) {
+                return (Instructions.OutputInstruction) instruction;
+            }
+        }
+        return null;
+    }
+
+}