ONOS-6545:  HP3800 driver based on patches developed by Lancaster University (contact point Charalampos Rotsos: c.rotsos@lancaster.ac.uk). Driver was tested on Janet HP3800 switches.

Change-Id: Icd4aa22de9e718f830285dd1a9fb88e208cce2db
diff --git a/drivers/hp/BUCK b/drivers/hp/BUCK
new file mode 100644
index 0000000..ddb62af
--- /dev/null
+++ b/drivers/hp/BUCK
@@ -0,0 +1,28 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:openflowj',
+    '//drivers/default:onos-drivers-default',
+    '//drivers/utilities:onos-drivers-utilities',
+    '//protocols/openflow/api:onos-protocols-openflow-api',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//core/api:onos-api-tests',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+    resources_root = 'src/main/resources',
+    resources = glob(['src/main/resources/**']),
+)
+
+onos_app (
+    app_name = 'org.onosproject.drivers.hp',
+    title = 'HP driver',
+    category = 'Drivers',
+    url = 'http://onosproject.org',
+    description = 'ONOS HP device drivers application.',
+    required_apps = [ 'org.onosproject.openflow' ],
+)
diff --git a/drivers/hp/features.xml b/drivers/hp/features.xml
new file mode 100644
index 0000000..c13cf62
--- /dev/null
+++ b/drivers/hp/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+        <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+        <bundle>mvn:${project.groupId}/onos-drivers-utilities/${project.version}</bundle>
+    </feature>
+</features>
diff --git a/drivers/hp/pom.xml b/drivers/hp/pom.xml
new file mode 100644
index 0000000..ecc7bcd
--- /dev/null
+++ b/drivers/hp/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>onos-drivers-general</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>onos-drivers-hp</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>HP driver</description>
+
+    <properties>
+        <onos.app.name>org.onosproject.drivers.hp</onos.app.name>
+        <onos.app.origin>ON.Lab</onos.app.origin>
+        <onos.app.title>HP Driver</onos.app.title>
+        <onos.app.category>Drivers</onos.app.category>
+        <onos.app.url>http://onosproject.org</onos.app.url>
+        <onos.app.requires>
+            org.onosproject.openflow
+        </onos.app.requires>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>openflowj</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-drivers</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
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;
+        }
+
+    }
+
+
+}
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPDriverLoader.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPDriverLoader.java
new file mode 100644
index 0000000..ad19c1b
--- /dev/null
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPDriverLoader.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for HP drivers.
+ */
+@Component(immediate = true)
+public class HPDriverLoader extends AbstractDriverLoader {
+    public HPDriverLoader() {
+        super("/hp-driver.xml");
+    }
+}
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3800.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3800.java
new file mode 100644
index 0000000..c48f190
--- /dev/null
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3800.java
@@ -0,0 +1,169 @@
+/*
+ * 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 org.onosproject.net.PortNumber;
+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.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Driver for HP3800 hybrid switches.
+ */
+public class HPPipelineV3800 extends AbstractHPPipeline {
+
+    private static final int HP_TABLE_ZERO = 0;
+    private static final int HP_HARDWARE_TABLE = 100;
+    private static final int HP_SOFTWARE_TABLE = 200;
+
+    private final Logger log = getLogger(getClass());
+
+
+    @Override
+    protected FlowRule.Builder setDefaultTableIdForFlowObjective(FlowRule.Builder ruleBuilder) {
+        log.debug("Setting default table id to hardware table {}", HP_HARDWARE_TABLE);
+        return ruleBuilder.forTable(HP_HARDWARE_TABLE);
+    }
+
+    @Override
+    protected void initializePipeline() {
+        log.debug("Installing table zero {}", HP_TABLE_ZERO);
+        installHPTableZero();
+        log.debug("Installing scavenger rule to hardware table {} because it is default objective table",
+                 HP_HARDWARE_TABLE);
+        installHPHardwareTable();
+        log.debug("Installing software table {}", HP_SOFTWARE_TABLE);
+        installHPSoftwareTable();
+    }
+
+    @Override
+    public void filter(FilteringObjective filter) {
+        log.error("Unsupported FilteringObjective: : filtering method send");
+    }
+
+    @Override
+    protected FlowRule.Builder processEthFiler(FilteringObjective filt, EthCriterion eth, PortCriterion port) {
+        log.error("Unsupported FilteringObjective: processEthFilter invoked");
+        return null;
+    }
+
+    @Override
+    protected FlowRule.Builder processVlanFiler(FilteringObjective filt, VlanIdCriterion vlan, PortCriterion port) {
+        log.error("Unsupported FilteringObjective: processVlanFilter invoked");
+        return null;
+    }
+
+    @Override
+    protected FlowRule.Builder processIpFilter(FilteringObjective filt, IPCriterion ip, PortCriterion port) {
+        log.error("Unsupported FilteringObjective: processIpFilter invoked");
+        return null;
+    }
+
+    /**
+     * HP Table 0 initialization.
+     * Installs rule goto HP hardware table in HP table zero
+     */
+    private void installHPTableZero() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+        treatment.transition(HP_HARDWARE_TABLE);
+
+        FlowRule rule = DefaultFlowRule.builder().forDevice(this.deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(0)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(HP_TABLE_ZERO)
+                .build();
+
+        this.applyRules(true, rule);
+
+        log.info("Installed table {}", HP_TABLE_ZERO);
+    }
+
+    /**
+     * HP hardware table initialization.
+     * Installs scavenger rule in HP hardware table.
+     */
+    private void installHPHardwareTable() {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        treatment.setOutput(PortNumber.NORMAL);
+
+        FlowRule rule = DefaultFlowRule.builder().forDevice(this.deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(0)
+                .fromApp(appId)
+                .makePermanent()
+                .forTable(HP_HARDWARE_TABLE)
+                .build();
+
+        this.applyRules(true, rule);
+
+        log.info("Installed table {}", HP_HARDWARE_TABLE);
+    }
+
+    /**
+     * HP software table initialization.
+     */
+    private void installHPSoftwareTable() {
+        log.info("No rules installed in table {}", HP_SOFTWARE_TABLE);
+    }
+
+
+    /**
+     * Applies FlowRule.
+     * Installs or removes FlowRule.
+     *
+     * @param install - whether to install or remove rule
+     * @param rule    - the rule to be installed or removed
+     */
+    private void applyRules(boolean install, FlowRule rule) {
+        FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+
+        ops = install ? ops.add(rule) : ops.remove(rule);
+        flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+            @Override
+            public void onSuccess(FlowRuleOperations ops) {
+                log.trace("Provisioned rule: " + rule.toString());
+                log.trace("HP3800 driver: provisioned " + rule.tableId() + " table");
+            }
+
+            @Override
+            public void onError(FlowRuleOperations ops) {
+                log.info("HP3800 driver: failed to provision " + rule.tableId() + " table");
+            }
+        }));
+    }
+}
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPSwitchHandshaker.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPSwitchHandshaker.java
new file mode 100644
index 0000000..47c953d
--- /dev/null
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPSwitchHandshaker.java
@@ -0,0 +1,91 @@
+/*
+ * 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.collect.ImmutableList;
+import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
+import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.projectfloodlight.openflow.protocol.OFGroupMod;
+import org.projectfloodlight.openflow.protocol.OFGroupType;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.types.OFGroup;
+import org.projectfloodlight.openflow.types.TableId;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+
+/**
+ * HP switch handshaker.
+ * Possibly compliant with all HP OF switches but tested only with HP3800.
+ */
+public class HPSwitchHandshaker extends AbstractOpenFlowSwitch {
+
+    private AtomicBoolean handshakeComplete = new AtomicBoolean(false);
+
+
+    @Override
+    public Boolean supportNxRole() {
+        return false;
+    }
+
+    @Override
+    public void startDriverHandshake() {
+        if (startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeAlreadyStarted();
+        }
+        startDriverHandshakeCalled = true;
+        OFFlowMod fm = factory().buildFlowDelete()
+                .setTableId(TableId.ALL)
+                .setOutGroup(OFGroup.ANY)
+                .build();
+
+        sendMsg(ImmutableList.of(fm));
+
+        OFGroupMod gm = factory().buildGroupDelete()
+                .setGroup(OFGroup.ALL)
+                .setGroupType(OFGroupType.ALL)
+                .build();
+
+        sendMsg(ImmutableList.of(gm));
+
+        handshakeComplete.set(true);
+
+        log.info("Handshake with device {} ended", super.getStringId());
+
+    }
+
+    @Override
+    public boolean isDriverHandshakeComplete() {
+        if (!startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeAlreadyStarted();
+        }
+        return handshakeComplete.get();
+    }
+
+    @Override
+    public void processDriverHandshakeMessage(OFMessage m) {
+        if (!startDriverHandshakeCalled) {
+            throw new SwitchDriverSubHandshakeNotStarted();
+        }
+        if (handshakeComplete.get()) {
+            throw new SwitchDriverSubHandshakeCompleted(m);
+        }
+    }
+
+}
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/package-info.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/package-info.java
new file mode 100644
index 0000000..bbb4bcb
--- /dev/null
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Driver for HP devices.
+ */
+package org.onosproject.drivers.hp;
\ No newline at end of file
diff --git a/drivers/hp/src/main/resources/hp-driver.xml b/drivers/hp/src/main/resources/hp-driver.xml
new file mode 100644
index 0000000..49fa41c
--- /dev/null
+++ b/drivers/hp/src/main/resources/hp-driver.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<drivers>
+   <driver name="hp3800"
+            manufacturer="HP" hwVersion="3800-48G-4SFP+ Switch" swVersion="KA.16.03.0003">
+        <behaviour api="org.onosproject.net.behaviour.Pipeliner"
+                   impl="org.onosproject.drivers.hp.HPPipelineV3800"/>
+        <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
+                   impl="org.onosproject.drivers.hp.HPSwitchHandshaker"/>
+    </driver>
+</drivers>
diff --git a/drivers/hp/src/test/java/org/onosproject/drivers/hp/HPDriverLoaderTest.java b/drivers/hp/src/test/java/org/onosproject/drivers/hp/HPDriverLoaderTest.java
new file mode 100644
index 0000000..8abc312
--- /dev/null
+++ b/drivers/hp/src/test/java/org/onosproject/drivers/hp/HPDriverLoaderTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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 org.junit.Before;
+import org.onosproject.net.driver.AbstractDriverLoaderTest;
+
+/**
+ * HP driver loader test.
+ */
+public class HPDriverLoaderTest extends AbstractDriverLoaderTest {
+
+    @Before
+    public void setUp() {
+        loader = new HPDriverLoader();
+    }
+}
diff --git a/drivers/pom.xml b/drivers/pom.xml
index 72fa76f..a7ddf0c 100644
--- a/drivers/pom.xml
+++ b/drivers/pom.xml
@@ -50,6 +50,7 @@
         <module>microsemi</module>
         <module>oplink</module>
         <module>bmv2</module>
+        <module>hp</module>
     </modules>
 
     <!--<properties>
diff --git a/modules.defs b/modules.defs
index df4530a..9aa0cbe 100644
--- a/modules.defs
+++ b/modules.defs
@@ -104,6 +104,7 @@
 #   '//drivers/microsemi/ea1000driver:onos-drivers-microsemi-ea1000driver-oar',
     '//drivers/oplink:onos-drivers-oplink-oar',
     '//drivers/bmv2:onos-drivers-bmv2-oar',
+    '//drivers/hp:onos-drivers-hp-oar',
 ]
 
 ONOS_PROVIDERS = [