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 = [