diff --git a/drivers/default/src/main/java/org/onosproject/driver/traceable/OfdpaPipelineTraceable.java b/drivers/default/src/main/java/org/onosproject/driver/traceable/OfdpaPipelineTraceable.java
new file mode 100644
index 0000000..c269022
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/traceable/OfdpaPipelineTraceable.java
@@ -0,0 +1,785 @@
+/*
+ * Copyright 2020-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.traceable;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.GroupId;
+import org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline;
+import org.onosproject.driver.pipeline.ofdpa.OvsOfdpaPipeline;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PipelineTraceableHitChain;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DataPlaneEntity;
+import org.onosproject.net.PipelineTraceableInput;
+import org.onosproject.net.PipelineTraceableOutput;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.PipelineTraceable;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.IndexTableId;
+import org.onosproject.net.flow.TableId;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.criteria.Criteria;
+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.IPCriterion;
+import org.onosproject.net.flow.criteria.MetadataCriterion;
+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.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_FLOOD_TYPE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_INTERFACE_TYPE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_MULTICAST_TYPE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L3_MULTICAST_TYPE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.ACL_TABLE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.BRIDGING_TABLE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.MPLS_L3_TYPE_TABLE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.MULTICAST_ROUTING_TABLE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.TMAC_TABLE;
+import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.VLAN_TABLE;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implements a driver behavior that enables a logical probe packet to traverse the device pipeline
+ * and to return dataplane entities that matched against the logical probe packet.
+ */
+public class OfdpaPipelineTraceable extends AbstractHandlerBehaviour implements PipelineTraceable {
+
+    private static final Logger log = getLogger(OfdpaPipelineTraceable.class);
+    // Behavior context
+    private DeviceId deviceId;
+    private String driverName;
+    // Utility
+    private final Comparator<FlowEntry> comparatorById = Comparator.comparing(
+            (FlowEntry f) -> ((IndexTableId) f.table()).id());
+    private final Comparator<FlowEntry> comparatorByPriority = Comparator.comparing(
+            FlowRule::priority);
+
+    @Override
+    public void init() {
+        this.deviceId = this.data().deviceId();
+        this.driverName = this.data().driver().name();
+    }
+
+    @Override
+    public PipelineTraceableOutput apply(PipelineTraceableInput input) {
+        PipelineTraceableOutput.Builder outputBuilder = PipelineTraceableOutput.builder();
+        log.debug("Current packet {} - applying flow tables", input.ingressPacket());
+        List<FlowEntry> outputFlows = new ArrayList<>();
+        List<Instruction> deferredInstructions = new ArrayList<>();
+        PipelineTraceableHitChain currentHitChain = PipelineTraceableHitChain.emptyHitChain();
+        TrafficSelector currentPacket = DefaultTrafficSelector.builder(input.ingressPacket()).build();
+
+        // Init step - find out the first table
+        int initialTableId = -1;
+        FlowEntry nextTableIdEntry = findNextTableIdEntry(initialTableId, input.flows());
+        if (nextTableIdEntry == null) {
+            currentHitChain.setEgressPacket(currentPacket);
+            currentHitChain.dropped();
+            return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting")
+                    .noFlows()
+                    .addHitChain(currentHitChain)
+                    .build();
+        }
+
+        // Iterates over the flow tables until the end of the pipeline
+        TableId tableId = nextTableIdEntry.table();
+        FlowEntry flowEntry;
+        boolean lastTable = false;
+        while (!lastTable) {
+            log.debug("Searching a Flow Entry on table {} for packet {}", tableId, currentPacket);
+
+            // Gets the rule that matches the incoming packet
+            flowEntry = matchHighestPriority(currentPacket, tableId, input.flows());
+            log.debug("Found Flow Entry {}", flowEntry);
+
+            // If the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
+            if (flowEntry == null && isHardwareSwitch()) {
+                log.debug("Ofdpa Hw setup, no flow rule means table miss");
+
+                if (((IndexTableId) tableId).id() == MPLS_L3_TYPE_TABLE) {
+                    // Apparently a miss but Table 27 on OFDPA is a fixed table
+                    currentPacket = handleOfdpa27FixedTable(input.ingressPacket(), currentPacket);
+                    // The nextTable should be ACL
+                    tableId = IndexTableId.of(ACL_TABLE - 1);
+                }
+
+                // Finding next table to go In case of miss
+                nextTableIdEntry = findNextTableIdEntry(((IndexTableId) tableId).id(), input.flows());
+                log.debug("Next table id entry {}", nextTableIdEntry);
+                // FIXME Find better solution that enable granularity greater than 0 or all rules
+                // (another possibility is max tableId)
+                if (nextTableIdEntry == null && currentHitChain.getHitChain().size() == 0) {
+                    currentHitChain.setEgressPacket(currentPacket);
+                    currentHitChain.dropped();
+                    return outputBuilder.appendToLog("No flow rules for device " + deviceId + ". Aborting")
+                            .noFlows()
+                            .addHitChain(currentHitChain)
+                            .build();
+
+                } else if (nextTableIdEntry == null) {
+                    // Means that no more flow rules are present
+                    lastTable = true;
+
+                } else if (((IndexTableId) tableId).id() == TMAC_TABLE) {
+                    // If the table is 20 OFDPA skips to table 50
+                    log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
+                    tableId = IndexTableId.of(BRIDGING_TABLE);
+
+                } else if (((IndexTableId) tableId).id() == MULTICAST_ROUTING_TABLE) {
+                    // If the table is 40 OFDPA skips to table 60
+                    log.debug("A miss on Table 40 on OFDPA means that we skip directly to table 60");
+                    tableId = IndexTableId.of(ACL_TABLE);
+                } else {
+                    tableId = nextTableIdEntry.table();
+                }
+
+            } else if (flowEntry == null) {
+                currentHitChain.setEgressPacket(currentPacket);
+                currentHitChain.dropped();
+                return outputBuilder.appendToLog("Packet has no match on table " + tableId
+                        + " in device " + deviceId + ". Dropping")
+                        .noFlows()
+                        .addHitChain(currentHitChain)
+                        .build();
+            } else {
+
+                // If the table has a transition
+                if (flowEntry.treatment().tableTransition() != null) {
+                    // Updates the next table we transitions to
+                    tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
+                    log.debug("Flow Entry has transition to table Id {}", tableId);
+                    currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
+                } else {
+                    // Table has no transition so it means that it's an output rule if on the last table
+                    log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
+                    currentHitChain.addDataPlaneEntity(new DataPlaneEntity(flowEntry));
+                    outputFlows.add(flowEntry);
+                    lastTable = true;
+                }
+
+                // Updates the packet according to the immediate actions of this flow rule.
+                currentPacket = updatePacket(currentPacket, flowEntry.treatment().immediate()).build();
+
+                // Saves the deferred rules for later maintaining the order
+                deferredInstructions.addAll(flowEntry.treatment().deferred());
+
+                // If the flow requires to clear deferred actions we do so for all the ones we encountered.
+                if (flowEntry.treatment().clearedDeferred()) {
+                    deferredInstructions.clear();
+                }
+
+                // On table 10 OFDPA needs two rules to apply the vlan if none and then to transition to the next table.
+                if (shouldMatchSecondVlanFlow(flowEntry)) {
+
+                    // Let's get the packet vlanId instruction
+                    VlanIdCriterion packetVlanIdCriterion =
+                            (VlanIdCriterion) currentPacket.getCriterion(Criterion.Type.VLAN_VID);
+
+                    // Let's get the flow entry vlan mod instructions
+                    ModVlanIdInstruction entryModVlanIdInstruction = (ModVlanIdInstruction) flowEntry.treatment()
+                            .immediate().stream()
+                            .filter(instruction -> instruction instanceof ModVlanIdInstruction)
+                            .findFirst().orElse(null);
+
+                    // If the entry modVlan is not null we need to make sure that the packet has been updated and there
+                    // is a flow rule that matches on same criteria and with updated vlanId
+                    if (entryModVlanIdInstruction != null) {
+
+                        FlowEntry secondVlanFlow = getSecondFlowEntryOnTable10(currentPacket,
+                                packetVlanIdCriterion, entryModVlanIdInstruction, input.flows());
+
+                        // We found the flow that we expected
+                        if (secondVlanFlow != null) {
+                            currentHitChain.addDataPlaneEntity(new DataPlaneEntity(secondVlanFlow));
+                        } else {
+                            currentHitChain.setEgressPacket(currentPacket);
+                            currentHitChain.dropped();
+                            return outputBuilder.appendToLog("Missing forwarding rule for tagged"
+                                    + " packet on " + deviceId)
+                                    .noFlows()
+                                    .addHitChain(currentHitChain)
+                                    .build();
+                        }
+                    }
+                }
+            }
+        }
+
+        // Creating a modifiable builder for the egress packet
+        TrafficSelector.Builder egressPacket = DefaultTrafficSelector.builder(currentPacket);
+
+        log.debug("Current packet {} - applying output flows", currentPacket);
+        // Handling output flows which basically means handling output to controller.
+        // OVS and OFDPA have both immediate -> OUTPUT:CONTROLLER. Theoretically there is no
+        // need to reflect the updates performed on the packets and on the chain.
+        List<PortNumber> outputPorts = new ArrayList<>();
+        handleOutputFlows(currentPacket, outputFlows, egressPacket, outputPorts, currentHitChain,
+                outputBuilder, input.ingressPacket());
+
+        // Immediate instructions
+        log.debug("Current packet {} - applying immediate instructions", currentPacket);
+        // Handling immediate instructions which basically means handling output to controller.
+        // OVS has immediate -> group -> OUTPUT:CONTROLLER.
+        List<DataPlaneEntity> entries = ImmutableList.copyOf(currentHitChain.getHitChain());
+        // Go to the next step - using a copy of the egress packet and of the hit chain
+        PipelineTraceableHitChain newHitChain = PipelineTraceableHitChain.emptyHitChain();
+        currentHitChain.getHitChain().forEach(newHitChain::addDataPlaneEntity);
+        TrafficSelector.Builder newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
+        for (DataPlaneEntity entry : entries) {
+            flowEntry = entry.getFlowEntry();
+            if (flowEntry != null) {
+                getGroupsFromInstructions(input.groups(), flowEntry.treatment().immediate(), newEgressPacket,
+                        outputPorts, newHitChain, outputBuilder, input, false);
+            }
+        }
+
+        // Deferred instructions
+        log.debug("Current packet {} - applying deferred instructions", egressPacket.build());
+        // If we have deferred instructions at this point we handle them.
+        // Here, we are basically handling the normal forwarding scenarios that
+        // always happen through deferred:group. Here we don't care about the
+        // egress packet and of the hit chain. This is the last step.
+        if (deferredInstructions.size() > 0) {
+            handleDeferredActions(egressPacket.build(), input.groups(), deferredInstructions, outputPorts,
+                    currentHitChain, outputBuilder, input);
+        }
+
+        // If there are no outputs - packet is dropped
+        // Let's store the partial hit chain and set a message
+        if (outputPorts.isEmpty()) {
+            currentHitChain.setEgressPacket(egressPacket.build());
+            currentHitChain.dropped();
+            outputBuilder.appendToLog("Packet has no output in device " + deviceId + ". Dropping")
+                    .dropped()
+                    .addHitChain(currentHitChain);
+        }
+
+        // Done!
+        return outputBuilder.build();
+    }
+
+    // Finds the flow entry with the minimum next table Id.
+    private FlowEntry findNextTableIdEntry(int currentId, List<FlowEntry> flows) {
+        return flows.stream()
+                .filter(f -> ((IndexTableId) f.table()).id() > currentId)
+                .min(comparatorById).orElse(null);
+    }
+
+    // Finds the rule in the device that matches the input packet and has the highest priority.
+    // TODO Candidate for an AbstractBehavior implementation
+    private FlowEntry matchHighestPriority(TrafficSelector packet, TableId tableId, List<FlowEntry> flows) {
+        //Computing the possible match rules.
+        return flows.stream()
+                .filter(flowEntry -> flowEntry.table().equals(tableId))
+                .filter(flowEntry -> match(packet, flowEntry))
+                .max(comparatorByPriority).orElse(null);
+    }
+
+    // Matches the packet with the given flow entry
+    // TODO Candidate for an AbstractBehavior implementation
+    private boolean match(TrafficSelector packet, FlowEntry flowEntry) {
+        return flowEntry.selector().criteria().stream().allMatch(criterion -> {
+            Criterion.Type type = criterion.type();
+            //If the criterion has IP we need to do LPM to establish matching.
+            if (type.equals(Criterion.Type.IPV4_SRC) || type.equals(Criterion.Type.IPV4_DST) ||
+                    type.equals(Criterion.Type.IPV6_SRC) || type.equals(Criterion.Type.IPV6_DST)) {
+                return matchIp(packet, (IPCriterion) criterion);
+                //we check that the packet contains the criterion provided by the flow rule.
+            } else if (type.equals(Criterion.Type.ETH_SRC_MASKED)) {
+                return matchMac(packet, (EthCriterion) criterion, false);
+            } else if (type.equals(Criterion.Type.ETH_DST_MASKED)) {
+                return matchMac(packet, (EthCriterion) criterion, true);
+            } else {
+                return packet.criteria().contains(criterion);
+            }
+        });
+    }
+
+    // Checks if the packet has an dst or src IP and if that IP matches the subnet of the ip criterion
+    // TODO Candidate for an AbstractBehavior implementation
+    private boolean matchIp(TrafficSelector packet, IPCriterion criterion) {
+        IPCriterion matchCriterion = (IPCriterion) packet.getCriterion(criterion.type());
+        // if the packet does not have an IPv4 or IPv6 criterion we return true
+        if (matchCriterion == null) {
+            return false;
+        }
+        log.debug("Checking if {} is under {}", matchCriterion.ip(), criterion.ip());
+        IpPrefix subnet = criterion.ip();
+        return subnet.contains(matchCriterion.ip().address());
+    }
+
+    // Checks if the packet has a dst or src MAC and if that Mac matches the mask of the mac criterion
+    // TODO Candidate for an AbstractBehavior implementation
+    private boolean matchMac(TrafficSelector packet, EthCriterion hitCriterion, boolean dst) {
+        //Packet can have only one EthCriterion
+        EthCriterion matchCriterion;
+        if (dst) {
+            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 ->
+                    criterion1.type().equals(Criterion.Type.ETH_DST_MASKED) ||
+                            criterion1.type().equals(Criterion.Type.ETH_DST))
+                    .findFirst().orElse(null);
+        } else {
+            matchCriterion = (EthCriterion) packet.criteria().stream().filter(criterion1 ->
+                    criterion1.type().equals(Criterion.Type.ETH_SRC_MASKED) ||
+                            criterion1.type().equals(Criterion.Type.ETH_SRC))
+                    .findFirst().orElse(null);
+        }
+        //if the packet does not have an ETH criterion we return true
+        if (matchCriterion == null) {
+            return true;
+        }
+        log.debug("Checking if {} is under {}/{}", matchCriterion.mac(), hitCriterion.mac(), hitCriterion.mask());
+        return matchCriterion.mac().inRange(hitCriterion.mac(), hitCriterion.mask());
+    }
+
+    // Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
+    private TrafficSelector handleOfdpa27FixedTable(TrafficSelector initialPacket, TrafficSelector packet) {
+        log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");
+
+        Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
+        // T3 was using the initial packet of the trace - using the metadata in the packet to carry this info
+        Criterion metadataCriterion = initialPacket.getCriterion(Criterion.Type.METADATA);
+        ImmutableList.Builder<Instruction> builder = ImmutableList.builder();
+
+        // If the packet comes in with the expected elements we update it as per OFDPA spec.
+        if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType()
+                .equals(EthType.EtherType.MPLS_UNICAST.ethType()) && metadataCriterion != null) {
+
+            // Get the metadata to restore the original ethertype
+            long ethType = ((MetadataCriterion) metadataCriterion).metadata();
+            //TODO update with parsing with eth MPLS pop Instruction for treating label an bos
+            Instruction ethInstruction = Instructions.popMpls(EthType.EtherType.lookup((short) ethType).ethType());
+            //FIXME what do we use as L3_Unicast mpls Label ?
+            //translateInstruction(builder, ethInstruction);
+            builder.add(ethInstruction);
+
+            // Filtering out metadata
+            TrafficSelector.Builder currentPacketBuilder = DefaultTrafficSelector.builder();
+            packet.criteria().stream()
+                    .filter(criterion -> criterion.type() != Criterion.Type.METADATA)
+                    .forEach(currentPacketBuilder::add);
+            packet = currentPacketBuilder.build();
+        }
+        packet = updatePacket(packet, builder.build()).build();
+        return packet;
+    }
+
+    // Applies all give instructions to the input packet
+    private TrafficSelector.Builder updatePacket(TrafficSelector packet, List<Instruction> instructions) {
+        TrafficSelector.Builder newSelector = DefaultTrafficSelector.builder(packet);
+
+        //FIXME optimize
+        for (Instruction instruction : instructions) {
+            newSelector = translateInstruction(newSelector, instruction);
+        }
+        return newSelector;
+    }
+
+    // Applies an instruction to the packet in the form of a selector
+    private TrafficSelector.Builder translateInstruction(TrafficSelector.Builder newSelector, Instruction instruction) {
+        log.debug("Translating instruction {}", instruction);
+        log.debug("New Selector {}", newSelector.build());
+        //TODO add as required
+        Criterion criterion = null;
+        if (instruction.type() == Instruction.Type.L2MODIFICATION) {
+            L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
+            switch (l2Instruction.subtype()) {
+                case VLAN_ID:
+                    ModVlanIdInstruction vlanIdInstruction =
+                            (ModVlanIdInstruction) instruction;
+                    VlanId id = vlanIdInstruction.vlanId();
+                    criterion = Criteria.matchVlanId(id);
+                    break;
+                case VLAN_POP:
+                    criterion = Criteria.matchVlanId(VlanId.NONE);
+                    break;
+                case MPLS_PUSH:
+                    L2ModificationInstruction.ModMplsHeaderInstruction mplsEthInstruction =
+                            (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
+                    criterion = Criteria.matchEthType(mplsEthInstruction.ethernetType().toShort());
+
+                    // When pushing MPLS adding metadata to remember the original ethtype
+                    if (isHardwareSwitch()) {
+                        TrafficSelector temporaryPacket = newSelector.build();
+                        Criterion ethCriterion = temporaryPacket.getCriterion(Criterion.Type.ETH_TYPE);
+                        if (ethCriterion != null) {
+                            TrafficSelector.Builder tempSelector = DefaultTrafficSelector.builder(temporaryPacket);
+                            // Store the old ether type for the
+                            tempSelector.matchMetadata(((EthTypeCriterion) ethCriterion).ethType().toShort());
+                            newSelector = tempSelector;
+                        }
+                    }
+
+                    break;
+                case MPLS_POP:
+                    L2ModificationInstruction.ModMplsHeaderInstruction mplsPopInstruction =
+                            (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
+                    criterion = Criteria.matchEthType(mplsPopInstruction.ethernetType().toShort());
+
+                    //When popping MPLS we remove label and BOS
+                    TrafficSelector temporaryPacket = newSelector.build();
+                    if (temporaryPacket.getCriterion(Criterion.Type.MPLS_LABEL) != null) {
+                        TrafficSelector.Builder noMplsSelector = DefaultTrafficSelector.builder();
+                        temporaryPacket.criteria().stream().filter(c ->
+                                !c.type().equals(Criterion.Type.MPLS_LABEL) &&
+                                        !c.type().equals(Criterion.Type.MPLS_BOS))
+                                .forEach(noMplsSelector::add);
+                        newSelector = noMplsSelector;
+                    }
+
+                    break;
+                case MPLS_LABEL:
+                    L2ModificationInstruction.ModMplsLabelInstruction mplsLabelInstruction =
+                            (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
+                    criterion = Criteria.matchMplsLabel(mplsLabelInstruction.label());
+                    newSelector.matchMplsBos(true);
+                    break;
+                case ETH_DST:
+                    L2ModificationInstruction.ModEtherInstruction modEtherDstInstruction =
+                            (L2ModificationInstruction.ModEtherInstruction) instruction;
+                    criterion = Criteria.matchEthDst(modEtherDstInstruction.mac());
+                    break;
+                case ETH_SRC:
+                    L2ModificationInstruction.ModEtherInstruction modEtherSrcInstruction =
+                            (L2ModificationInstruction.ModEtherInstruction) instruction;
+                    criterion = Criteria.matchEthSrc(modEtherSrcInstruction.mac());
+                    break;
+                default:
+                    log.debug("Unsupported L2 Instruction");
+                    break;
+            }
+        } else {
+            log.debug("Unsupported Instruction");
+        }
+        if (criterion != null) {
+            log.debug("Adding criterion {}", criterion);
+            newSelector.add(criterion);
+        }
+        return newSelector;
+    }
+
+    // Method that finds a flow rule on table 10 that matches the packet and the VLAN of the already
+    // found rule on table 10. This is because OFDPA needs two rules on table 10, first to apply the rule,
+    // second to transition to following table
+    private FlowEntry getSecondFlowEntryOnTable10(TrafficSelector packet, VlanIdCriterion packetVlanIdCriterion,
+                                                  ModVlanIdInstruction entryModVlanIdInstruction,
+                                                  List<FlowEntry> flows) {
+        FlowEntry secondVlanFlow = null;
+        // Check the packet has been update from the first rule.
+        if (packetVlanIdCriterion.vlanId().equals(entryModVlanIdInstruction.vlanId())) {
+            // find a rule on the same table that matches the vlan and
+            // also all the other elements of the flow such as input port
+            secondVlanFlow = flows.stream()
+                    .filter(entry -> entry.table().equals(IndexTableId.of(VLAN_TABLE)))
+                    .filter(entry -> {
+                        VlanIdCriterion criterion = (VlanIdCriterion) entry.selector()
+                                .getCriterion(Criterion.Type.VLAN_VID);
+                        return criterion != null && match(packet, entry)
+                                && criterion.vlanId().equals(entryModVlanIdInstruction.vlanId());
+                    }).findFirst().orElse(null);
+
+        }
+        return secondVlanFlow;
+    }
+
+    // Handles output flows
+    private List<FlowEntry> handleOutputFlows(TrafficSelector currentPacket, List<FlowEntry> outputFlows,
+                                              TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts,
+                                              PipelineTraceableHitChain currentHitChain,
+                                              PipelineTraceableOutput.Builder outputBuilder,
+                                              TrafficSelector initialPacket) {
+        // TODO optimization
+        // outputFlows contains also last rule of device, so we need filtering for OUTPUT instructions.
+        List<FlowEntry> outputFlowEntries = outputFlows.stream().filter(flow -> flow.treatment()
+                .allInstructions().stream().filter(instruction -> instruction.type()
+                        .equals(Instruction.Type.OUTPUT)).count() > 0).collect(Collectors.toList());
+
+        if (outputFlowEntries.size() > 1) {
+            outputBuilder.appendToLog("More than one flow rule with OUTPUT instruction");
+            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", currentPacket);
+        }
+
+        if (outputFlowEntries.size() == 1) {
+            OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.get(0).treatment()
+                    .allInstructions().stream()
+                    .filter(instruction -> instruction.type().equals(Instruction.Type.OUTPUT))
+                    .findFirst().get();
+            buildOutputFromDevice(egressPacket, outputPorts, outputInstruction, currentHitChain,
+                    outputBuilder, initialPacket, false);
+        }
+
+        return outputFlowEntries;
+    }
+
+    // Builds a possible output from this device
+    private void buildOutputFromDevice(TrafficSelector.Builder egressPacket,
+                                       List<PortNumber> outputPorts,
+                                       OutputInstruction outputInstruction,
+                                       PipelineTraceableHitChain currentHitChain,
+                                       PipelineTraceableOutput.Builder outputBuilder,
+                                       TrafficSelector initialPacket,
+                                       boolean dropped) {
+        // Store the output port for further processing
+        outputPorts.add(outputInstruction.port());
+        // Create the final hit chain from the current one (deep copy)
+        ConnectPoint outputPort = new ConnectPoint(deviceId, outputInstruction.port());
+        PipelineTraceableHitChain finalHitChain = new PipelineTraceableHitChain(outputPort,
+                Lists.newArrayList(currentHitChain.getHitChain()),
+                egressPacket.build());
+        // Dropped early
+        if (dropped) {
+            log.debug("Packet {} has been dropped", egressPacket.build());
+        } else {
+            finalHitChain.pass();
+        }
+        if (outputPort.port().equals(PortNumber.CONTROLLER)) {
+            handleVlanToController(finalHitChain, initialPacket);
+        }
+        // If there is already a chain do not add a copy
+        outputBuilder.addHitChain(finalHitChain);
+    }
+
+    // If the initial packet comes tagged with a Vlan we output it with that to ONOS.
+    // If ONOS applied a vlan we remove it.
+    // TODO Candidate for an AbstractBehavior implementation
+    private void handleVlanToController(PipelineTraceableHitChain currentHitChain, TrafficSelector initialPacket) {
+
+        VlanIdCriterion initialVid = (VlanIdCriterion) initialPacket
+                .getCriterion(Criterion.Type.VLAN_VID);
+        VlanIdCriterion finalVid = (VlanIdCriterion) currentHitChain.getEgressPacket()
+                .getCriterion(Criterion.Type.VLAN_VID);
+
+        if (initialVid != null && !initialVid.equals(finalVid) && initialVid.vlanId().equals(VlanId.NONE)) {
+            Set<Criterion> finalCriteria = new HashSet<>(currentHitChain.getEgressPacket().criteria());
+            //removing the final vlanId
+            finalCriteria.remove(finalVid);
+            TrafficSelector.Builder packetUpdated = DefaultTrafficSelector.builder();
+            finalCriteria.forEach(packetUpdated::add);
+            //Initial was none so we set it to that
+            packetUpdated.add(Criteria.matchVlanId(VlanId.NONE));
+            //Update final packet
+            currentHitChain.setEgressPacket(packetUpdated.build());
+        }
+    }
+
+    // Gets group information from instructions.
+    private void getGroupsFromInstructions(Map<GroupId, Group> groups, List<Instruction> instructions,
+                                           TrafficSelector.Builder egressPacket, List<PortNumber> outputPorts,
+                                           PipelineTraceableHitChain currentHitChain,
+                                           PipelineTraceableOutput.Builder outputBuilder,
+                                           PipelineTraceableInput input,
+                                           boolean dropped) {
+
+        List<Instruction> groupInstructionlist = new ArrayList<>();
+        // sort instructions according to priority (larger Instruction.Type ENUM constant first)
+        // which enables to treat other actions before the OUTPUT action
+        // TODO improve the priority scheme according to the OpenFlow ActionSet spec
+        List<Instruction> instructionsSorted = new ArrayList<>();
+        instructionsSorted.addAll(instructions);
+        instructionsSorted.sort((instr1, instr2) ->
+                Integer.compare(instr2.type().ordinal(), instr1.type().ordinal()));
+
+        // Handles first all non-group instructions
+        for (Instruction instruction : instructionsSorted) {
+            log.debug("Considering Instruction {}", instruction);
+            // if the instruction is not group we need to update the packet or add the output
+            // to the possible outputs for this packet
+            if (!instruction.type().equals(Instruction.Type.GROUP)) {
+                // FIXME ?? if the instruction is not group we need to update the packet
+                // or add the output to the possible outputs for this packet
+                if (instruction.type().equals(Instruction.Type.OUTPUT)) {
+                    buildOutputFromDevice(egressPacket, outputPorts, (OutputInstruction) instruction,
+                            currentHitChain, outputBuilder, input.ingressPacket(), dropped);
+                } else {
+                    egressPacket = translateInstruction(egressPacket, instruction);
+                }
+            } else {
+                // Store for later if the instruction is pointing to a group
+                groupInstructionlist.add(instruction);
+            }
+        }
+
+        // handle all the internal instructions pointing to a group.
+        for (Instruction instr : groupInstructionlist) {
+            Instructions.GroupInstruction groupInstruction = (Instructions.GroupInstruction) instr;
+            Group group = groups.get(groupInstruction.groupId());
+
+            // group does not exist in the dataplane
+            if (group == null) {
+                currentHitChain.setEgressPacket(egressPacket.build());
+                currentHitChain.dropped();
+                outputBuilder.appendToLog("Null group for Instruction " + instr)
+                        .noGroups()
+                        .addHitChain(currentHitChain);
+                break;
+            }
+
+            log.debug("Analyzing group {}", group.id());
+
+            // group is there but there are no members/buckets
+            if (group.buckets().buckets().size() == 0) {
+                // add the group to the traversed groups
+                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
+                currentHitChain.setEgressPacket(egressPacket.build());
+                currentHitChain.dropped();
+                outputBuilder.appendToLog("Group " + group.id() + " has no buckets")
+                        .noMembers()
+                        .addHitChain(currentHitChain);
+                break;
+            }
+
+            PipelineTraceableHitChain newHitChain;
+            TrafficSelector.Builder newEgressPacket;
+            // Cycle in each of the group's buckets and add them to the groups for this Device.
+            for (GroupBucket bucket : group.buckets().buckets()) {
+
+                // add the group to the traversed groups
+                currentHitChain.addDataPlaneEntity(new DataPlaneEntity(group));
+
+                // Go to the next step - using a copy of the egress packet and of the hit chain
+                newHitChain = PipelineTraceableHitChain.emptyHitChain();
+                currentHitChain.getHitChain().forEach(newHitChain::addDataPlaneEntity);
+                newEgressPacket = DefaultTrafficSelector.builder(egressPacket.build());
+                getGroupsFromInstructions(groups, bucket.treatment().allInstructions(), newEgressPacket,
+                        outputPorts, newHitChain, outputBuilder, input,
+                        dropped | isDropped(group.id(), bucket, input.ingressPort()));
+            }
+        }
+    }
+
+    private boolean isDropped(GroupId groupId, GroupBucket bucket, ConnectPoint ingressPort) {
+        log.debug("Verify if the packet has to be dropped by the input port {}",
+                ingressPort);
+        // if It is not a l2 flood group and l2/l3 mcast skip
+        int maskedId = groupId.id() & 0xF0000000;
+        if (maskedId != L2_FLOOD_TYPE && maskedId != L2_MULTICAST_TYPE &&
+                maskedId != L3_MULTICAST_TYPE) {
+            return false;
+        }
+        // Verify if the bucket points to the ingress port
+        Instructions.GroupInstruction groupInstruction;
+        for (Instruction instr : bucket.treatment().allInstructions()) {
+            if (instr.type().equals(Instruction.Type.GROUP)) {
+                groupInstruction = (Instructions.GroupInstruction) instr;
+                // FIXME According to the OFDPA spec for L3 MCAST if the VLAN is changed packet is not dropped
+                if ((groupInstruction.groupId().id() & 0xF0000000) == L2_INTERFACE_TYPE) {
+                    return (groupInstruction.groupId().id() & 0x0000FFFF) == ingressPort.port().toLong();
+                }
+            }
+        }
+        return false;
+    }
+
+    // Handles deferred instructions taken from the flows
+    private void handleDeferredActions(TrafficSelector egressPacket, Map<GroupId, Group> groups,
+                                       List<Instruction> deferredInstructions, List<PortNumber> outputPorts,
+                                       PipelineTraceableHitChain currentHitChain,
+                                       PipelineTraceableOutput.Builder outputBuilder,
+                                       PipelineTraceableInput input) {
+        // Update the packet with the deferred instructions
+        TrafficSelector.Builder newEgressPacket = updatePacket(egressPacket, deferredInstructions);
+
+        //Gather any output instructions from the deferred instruction
+        List<Instruction> outputFlowInstruction = deferredInstructions.stream().filter(instruction ->
+                instruction.type().equals(Instruction.Type.OUTPUT))
+                .collect(Collectors.toList());
+
+        //We are considering deferred instructions from flows, there can only be one output.
+        if (outputFlowInstruction.size() > 1) {
+            outputBuilder.appendToLog("More than one flow rule with OUTPUT instruction");
+            log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", egressPacket);
+        }
+
+        // If there is one output let's go through that. No need to make a copy
+        // of the egress packet and of the current hit chain.
+        if (outputFlowInstruction.size() == 1) {
+            buildOutputFromDevice(newEgressPacket, outputPorts, (OutputInstruction) outputFlowInstruction.get(0),
+                    currentHitChain, outputBuilder, input.ingressPacket(), false);
+        }
+
+        // If there is no output let's see if there any deferred instruction point to groups.
+        // No need to make a copy of the egress packet and of the current chain.
+        if (outputFlowInstruction.size() == 0) {
+            getGroupsFromInstructions(groups, deferredInstructions, newEgressPacket, outputPorts,
+                    currentHitChain, outputBuilder, input, false);
+        }
+    }
+
+    // Checks whether it is an hw device based on different means.
+    // throws an exception if the behavior has been used with wrong drivers
+    private boolean isHardwareSwitch() {
+        // Check if we are using ofdpa hw device by looking at the pipeliner
+        // if we need to support a device that does not have a pipeliner
+        // we can add an exclusion rules before this
+        if (!this.handler().hasBehaviour(Pipeliner.class)) {
+            throw new UnsupportedOperationException("Not supported device");
+        }
+        Pipeliner pipeliner = this.handler().behaviour(Pipeliner.class);
+        if (pipeliner instanceof OvsOfdpaPipeline) {
+            return false;
+        } else if (pipeliner instanceof Ofdpa2Pipeline) {
+            return true;
+        }
+        throw new UnsupportedOperationException("Not supported device");
+    }
+
+    // OF-DPA hardware requires one VLAN filtering rule and one VLAN assignment flow in the VLAN table.
+    // This method is used to determine whether there is a need to match a second VLAN flow after
+    // matching the given flowEntry.
+    private boolean shouldMatchSecondVlanFlow(FlowEntry flowEntry) {
+        // if we need to support a device that does not have a pipeliner
+        // we can add an exclusion rules before this
+        if (!this.handler().hasBehaviour(Pipeliner.class)) {
+            throw new UnsupportedOperationException("Not supported device");
+        }
+        Pipeliner pipeliner = this.handler().behaviour(Pipeliner.class);
+        if (!(pipeliner instanceof Ofdpa2Pipeline)) {
+            return false;
+        }
+        return ((Ofdpa2Pipeline) pipeliner).requireSecondVlanTableEntry() &&
+                flowEntry.table().equals(IndexTableId.of(VLAN_TABLE)) &&
+                flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID) != null &&
+                ((VlanIdCriterion) flowEntry.selector().getCriterion(Criterion.Type.VLAN_VID))
+                        .vlanId().equals(VlanId.NONE);
+    }
+
+}
