diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/AbstractHPPipeline.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/AbstractHPPipeline.java
new file mode 100644
index 0000000..3718e01
--- /dev/null
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/AbstractHPPipeline.java
@@ -0,0 +1,414 @@
+/*
+ * 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.hp;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
+import com.google.common.cache.RemovalNotification;
+import com.google.common.collect.ImmutableList;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.NextGroup;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+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.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveStore;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupService;
+import org.onosproject.net.meter.MeterService;
+import org.slf4j.Logger;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.onosproject.net.flow.FlowRule.Builder;
+import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+/**
+ * Abstraction of the HP pipeline handler.
+ * Possibly compliant with all HP OF switches but tested only with HP3800.
+ */
+public abstract class AbstractHPPipeline extends AbstractHandlerBehaviour implements Pipeliner {
+
+
+    protected static final String APPLICATION_ID = "org.onosproject.drivers.hp.HPPipeline";
+    public static final int CACHE_ENTRY_EXPIRATION_PERIOD = 20;
+    private final Logger log = getLogger(getClass());
+    protected FlowRuleService flowRuleService;
+    protected GroupService groupService;
+    protected MeterService meterService;
+    protected FlowObjectiveStore flowObjectiveStore;
+    protected DeviceId deviceId;
+    protected ApplicationId appId;
+    protected DeviceService deviceService;
+    protected KryoNamespace appKryo = new KryoNamespace.Builder()
+            .register(GroupKey.class)
+            .register(DefaultGroupKey.class)
+            .register(byte[].class)
+            .build("AbstractHPPipeline");
+    private ServiceDirectory serviceDirectory;
+    private CoreService coreService;
+    private Cache<Integer, NextObjective> pendingAddNext = CacheBuilder.newBuilder()
+            .expireAfterWrite(CACHE_ENTRY_EXPIRATION_PERIOD, TimeUnit.SECONDS)
+            .removalListener((RemovalNotification<Integer, NextObjective> notification) -> {
+                if (notification.getCause() == RemovalCause.EXPIRED) {
+                    notification.getValue().context()
+                            .ifPresent(c -> c.onError(notification.getValue(),
+                                                      ObjectiveError.FLOWINSTALLATIONFAILED));
+                }
+            }).build();
+
+    /**
+     * Sets default table id.
+     * HP3800 switches have 3 tables, so one of them has to be default.
+     *
+     * @param ruleBuilder flow rule builder to be set table id
+     * @return flow rule builder with set table id for flow
+     */
+    protected abstract FlowRule.Builder setDefaultTableIdForFlowObjective(Builder ruleBuilder);
+
+    @Override
+    public void init(DeviceId deviceId, PipelinerContext context) {
+        this.serviceDirectory = context.directory();
+        this.deviceId = deviceId;
+
+        coreService = serviceDirectory.get(CoreService.class);
+        flowRuleService = serviceDirectory.get(FlowRuleService.class);
+        groupService = serviceDirectory.get(GroupService.class);
+        meterService = serviceDirectory.get(MeterService.class);
+        deviceService = serviceDirectory.get(DeviceService.class);
+        flowObjectiveStore = context.store();
+
+        appId = coreService.registerApplication(APPLICATION_ID);
+
+        initializePipeline();
+    }
+
+    /**
+     * Initializes pipeline.
+     */
+    protected abstract void initializePipeline();
+
+    protected void pass(Objective obj) {
+        obj.context().ifPresent(context -> context.onSuccess(obj));
+    }
+
+    protected void fail(Objective obj, ObjectiveError error) {
+        obj.context().ifPresent(context -> context.onError(obj, error));
+    }
+
+    @Override
+    public void forward(ForwardingObjective fwd) {
+
+        if (fwd.treatment() != null) {
+            // Deal with SPECIFIC and VERSATILE in the same manner.
+
+            TrafficTreatment.Builder noClearTreatment = DefaultTrafficTreatment.builder();
+            fwd.treatment().allInstructions().stream()
+                    .filter(i -> i.type() != Instruction.Type.QUEUE).forEach(noClearTreatment::add);
+            if (fwd.treatment().metered() != null) {
+                noClearTreatment.meter(fwd.treatment().metered().meterId());
+            }
+
+            TrafficSelector.Builder noVlanSelector = DefaultTrafficSelector.builder();
+            fwd.selector().criteria().stream()
+                    .filter(c -> c.type() != Criterion.Type.ETH_TYPE || (c.type() == Criterion.Type.ETH_TYPE
+                            && ((EthTypeCriterion) c).ethType().toShort() != Ethernet.TYPE_VLAN))
+                    .forEach(noVlanSelector::add);
+
+            // Then we create a new forwarding rule without the unsupported actions
+            FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                    .forDevice(deviceId)
+                    .withSelector(noVlanSelector.build())
+                    .withTreatment(noClearTreatment.build())
+                    .withPriority(fwd.priority())
+                    .withPriority(fwd.priority())
+                    .fromApp(fwd.appId());
+
+            //TODO: check whether ForwardingObjective can specify table
+            setDefaultTableIdForFlowObjective(ruleBuilder);
+
+            if (fwd.permanent()) {
+                ruleBuilder.makePermanent();
+            } else {
+                ruleBuilder.makeTemporary(fwd.timeout());
+            }
+
+            installObjective(ruleBuilder, fwd);
+
+        } else {
+            NextObjective nextObjective;
+            NextGroup next;
+            TrafficTreatment treatment;
+            if (fwd.op() == ADD) {
+                // Give a try to the cache. Doing an operation
+                // on the store seems to be very expensive.
+                nextObjective = pendingAddNext.getIfPresent(fwd.nextId());
+                // If the next objective is not present
+                // We will try with the store
+                if (nextObjective == null) {
+                    next = flowObjectiveStore.getNextGroup(fwd.nextId());
+                    // We verify that next was in the store and then de-serialize
+                    // the treatment in order to re-build the flow rule.
+                    if (next == null) {
+                        fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
+                        return;
+                    }
+                    treatment = appKryo.deserialize(next.data());
+                } else {
+                    pendingAddNext.invalidate(fwd.nextId());
+                    treatment = nextObjective.next().iterator().next();
+                }
+            } else {
+                // We get the NextGroup from the remove operation.
+                // Doing an operation on the store seems to be very expensive.
+                next = flowObjectiveStore.removeNextGroup(fwd.nextId());
+                if (next == null) {
+                    fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
+                    return;
+                }
+                treatment = appKryo.deserialize(next.data());
+            }
+            // If the treatment is null we cannot re-build the original flow
+            if (treatment == null) {
+                fwd.context().ifPresent(c -> c.onError(fwd, ObjectiveError.GROUPMISSING));
+                return;
+            }
+            // Finally we build the flow rule and push to the flowrule subsystem.
+            FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+                    .forDevice(deviceId)
+                    .withSelector(fwd.selector())
+                    .fromApp(fwd.appId())
+                    .withPriority(fwd.priority())
+                    .withTreatment(treatment);
+            if (fwd.permanent()) {
+                ruleBuilder.makePermanent();
+            } else {
+                ruleBuilder.makeTemporary(fwd.timeout());
+            }
+            installObjective(ruleBuilder, fwd);
+        }
+    }
+
+    /**
+     * Installs objective.
+     *
+     * @param ruleBuilder flow rule builder used to build rule from objective
+     * @param objective   objective to be installed
+     */
+    protected void installObjective(FlowRule.Builder ruleBuilder, Objective objective) {
+        FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
+
+        switch (objective.op()) {
+            case ADD:
+                log.trace("Requested installation of objective " + objective.toString());
+                FlowRule addRule = ruleBuilder.build();
+                log.trace("built rule is " + addRule.toString());
+                flowBuilder.add(addRule);
+                break;
+            case REMOVE:
+                log.trace("Requested installation of objective " + objective.toString());
+                FlowRule removeRule = ruleBuilder.build();
+                log.trace("built rule is " + removeRule.toString());
+                flowBuilder.remove(removeRule);
+                break;
+            default:
+                log.warn("Unknown operation {}", objective.op());
+        }
+
+        flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                objective.context().ifPresent(context -> context.onSuccess(objective));
+                log.trace("Installed objective " + objective.toString());
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                objective.context()
+                        .ifPresent(context -> context.onError(objective, ObjectiveError.FLOWINSTALLATIONFAILED));
+                log.trace("Objective installation failed" + objective.toString());
+            }
+        }));
+    }
+
+    @Override
+    public void next(NextObjective nextObjective) {
+        switch (nextObjective.op()) {
+            case ADD:
+                // We insert the value in the cache
+                pendingAddNext.put(nextObjective.id(), nextObjective);
+                // Then in the store, this will unblock the queued fwd obj
+                flowObjectiveStore.putNextGroup(
+                        nextObjective.id(),
+                        new SingleGroup(nextObjective.next().iterator().next())
+                );
+                break;
+            case REMOVE:
+                break;
+            default:
+                log.warn("Unsupported operation {}", nextObjective.op());
+        }
+        nextObjective.context().ifPresent(context -> context.onSuccess(nextObjective));
+    }
+
+    @Override
+    public List<String> getNextMappings(NextGroup nextGroup) {
+        //TODO: to be implemented
+        return ImmutableList.of();
+    }
+
+    @Override
+    public void filter(FilteringObjective filteringObjective) {
+        if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
+            processFilter(filteringObjective,
+                          filteringObjective.op() == Objective.Operation.ADD,
+                          filteringObjective.appId());
+        } else {
+            fail(filteringObjective, ObjectiveError.UNSUPPORTED);
+        }
+    }
+
+    /**
+     * Filter processing and installation.
+     * Processes and installs filtering rules.
+     *
+     * @param filt
+     * @param install
+     * @param applicationId
+     */
+    private void processFilter(FilteringObjective filt, boolean install,
+                               ApplicationId applicationId) {
+        // This driver only processes filtering criteria defined with switch
+        // ports as the key
+        PortCriterion port;
+        if (!filt.key().equals(Criteria.dummy()) &&
+                filt.key().type() == Criterion.Type.IN_PORT) {
+            port = (PortCriterion) filt.key();
+        } else {
+            log.warn("No key defined in filtering objective from app: {}. Not"
+                             + "processing filtering objective", applicationId);
+            fail(filt, ObjectiveError.UNKNOWN);
+            return;
+        }
+        // convert filtering conditions for switch-intfs into flowrules
+        FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+        for (Criterion c : filt.conditions()) {
+            if (c.type() == Criterion.Type.ETH_DST) {
+                EthCriterion eth = (EthCriterion) c;
+                FlowRule.Builder rule = processEthFiler(filt, eth, port);
+                rule.forDevice(deviceId)
+                        .fromApp(applicationId);
+                ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
+
+            } else if (c.type() == Criterion.Type.VLAN_VID) {
+                VlanIdCriterion vlan = (VlanIdCriterion) c;
+                FlowRule.Builder rule = processVlanFiler(filt, vlan, port);
+                rule.forDevice(deviceId)
+                        .fromApp(applicationId);
+                ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
+
+            } else if (c.type() == Criterion.Type.IPV4_DST) {
+                IPCriterion ip = (IPCriterion) c;
+                FlowRule.Builder rule = processIpFilter(filt, ip, port);
+                rule.forDevice(deviceId)
+                        .fromApp(applicationId);
+                ops = install ? ops.add(rule.build()) : ops.remove(rule.build());
+
+            } else {
+                log.warn("Driver does not currently process filtering condition"
+                                 + " of type: {}", c.type());
+                fail(filt, ObjectiveError.UNSUPPORTED);
+            }
+        }
+        // apply filtering flow rules
+        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                pass(filt);
+                log.trace("Applied filtering rules");
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
+                log.info("Failed to apply filtering rules");
+            }
+        }));
+    }
+
+    protected abstract Builder processEthFiler(FilteringObjective filt,
+                                               EthCriterion eth, PortCriterion port);
+
+    protected abstract Builder processVlanFiler(FilteringObjective filt,
+                                                VlanIdCriterion vlan, PortCriterion port);
+
+    protected abstract Builder processIpFilter(FilteringObjective filt,
+                                               IPCriterion ip, PortCriterion port);
+
+    private class SingleGroup implements NextGroup {
+
+        private TrafficTreatment nextActions;
+
+        SingleGroup(TrafficTreatment next) {
+            this.nextActions = next;
+        }
+
+        @Override
+        public byte[] data() {
+            return appKryo.serialize(nextActions);
+        }
+
+        public TrafficTreatment treatment() {
+            return nextActions;
+        }
+
+    }
+
+
+}
