Carmelo Cascone
Committed by Gerrit Code Review

ONOS-3961 ONOS-4285 Implemented BMv2 drivers and protocol

Provides Thrift-based implementation for FlowRuleProgrammable and
PortDiscovery behaviours.

Change-Id: Ibbf8720d92301bcd23c5c583d156f464015ff1ef
Showing 24 changed files with 1503 additions and 2 deletions
......@@ -38,7 +38,8 @@ public class ExtensionSelectorType {
NICIRA_MATCH_NSH_CH2(3),
NICIRA_MATCH_NSH_CH3(4),
NICIRA_MATCH_NSH_CH4(5),
OFDPA_MATCH_VLAN_VID(16);
OFDPA_MATCH_VLAN_VID(16),
P4_BMV2_MATCH_KEY(128);
private ExtensionSelectorType type;
......
......@@ -45,7 +45,8 @@ public final class ExtensionTreatmentType {
NICIRA_SET_NSH_CH2(35),
NICIRA_SET_NSH_CH3(36),
NICIRA_SET_NSH_CH4(37),
OFDPA_SET_VLAN_ID(64);
OFDPA_SET_VLAN_ID(64),
P4_BMV2_ACTION(128);
private ExtensionTreatmentType type;
......
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
~ Copyright 2014-2016 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}">
<bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle>
</feature>
</features>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014-2016 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="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>onos-drivers-bmv2</artifactId>
<version>1.6.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<description>Device drivers for p4.org reference softswitch BMv2</description>
<properties>
<onos.app.name>org.onosproject.drivers.bmv2</onos.app.name>
<onos.app.origin>ON.Lab</onos.app.origin>
<onos.app.category>Drivers</onos.app.category>
<onos.app.title>BMv2 Device Drivers</onos.app.title>
<onos.app.url>http://onosproject.org</onos.app.url>
<onos.app.requires>
org.onosproject.bmv2
</onos.app.requires>
</properties>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-bmv2-protocol</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
/*
* Copyright 2014-2016 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.bmv2;
import org.apache.felix.scr.annotations.Component;
import org.onosproject.net.driver.AbstractDriverLoader;
/**
* Loader for barefoot drivers from specific xml.
*/
@Component(immediate = true)
public class Bmv2DriversLoader extends AbstractDriverLoader {
private static final String DRIVERS_XML = "/bmv2-drivers.xml";
public Bmv2DriversLoader() {
super(DRIVERS_XML);
}
}
\ No newline at end of file
/*
* Copyright 2014-2016 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.bmv2;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.onosproject.bmv2.api.Bmv2ExtensionSelector;
import org.onosproject.bmv2.api.Bmv2ExtensionTreatment;
import org.onosproject.bmv2.api.Bmv2TableEntry;
import org.onosproject.bmv2.api.Bmv2Exception;
import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.ExtensionCriterion;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Bmv2FlowRuleDriver extends AbstractHandlerBehaviour
implements FlowRuleProgrammable {
private final Logger log =
LoggerFactory.getLogger(this.getClass());
// Bmv2 doesn't support proper table dump, use a local store
// FIXME: synchronize entries with device
private final Map<FlowRule, FlowEntry> deviceEntriesMap = Maps.newHashMap();
private final Map<Integer, Set<FlowRule>> tableRulesMap = Maps.newHashMap();
private final Map<FlowRule, Long> tableEntryIdsMap = Maps.newHashMap();
@Override
public Collection<FlowEntry> getFlowEntries() {
return Collections.unmodifiableCollection(
deviceEntriesMap.values());
}
@Override
public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
Bmv2ThriftClient deviceClient;
try {
deviceClient = getDeviceClient();
} catch (Bmv2Exception e) {
return Collections.emptyList();
}
List<FlowRule> appliedFlowRules = Lists.newArrayList();
for (FlowRule rule : rules) {
Bmv2TableEntry entry;
try {
entry = parseFlowRule(rule);
} catch (IllegalStateException e) {
log.error("Unable to parse flow rule", e);
continue;
}
// Instantiate flowrule set for table if it does not exist
if (!tableRulesMap.containsKey(rule.tableId())) {
tableRulesMap.put(rule.tableId(), Sets.newHashSet());
}
if (tableRulesMap.get(rule.tableId()).contains(rule)) {
/* Rule is already installed in the table */
long entryId = tableEntryIdsMap.get(rule);
try {
deviceClient.modifyTableEntry(
entry.tableName(), entryId, entry.action());
// Replace stored rule as treatment, etc. might have changed
// Java Set doesn't replace on add, remove first
tableRulesMap.get(rule.tableId()).remove(rule);
tableRulesMap.get(rule.tableId()).add(rule);
tableEntryIdsMap.put(rule, entryId);
deviceEntriesMap.put(rule, new DefaultFlowEntry(
rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
} catch (Bmv2Exception e) {
log.error("Unable to update flow rule", e);
continue;
}
} else {
/* Rule is new */
try {
long entryId = deviceClient.addTableEntry(entry);
tableRulesMap.get(rule.tableId()).add(rule);
tableEntryIdsMap.put(rule, entryId);
deviceEntriesMap.put(rule, new DefaultFlowEntry(
rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
} catch (Bmv2Exception e) {
log.error("Unable to add flow rule", e);
continue;
}
}
appliedFlowRules.add(rule);
}
return Collections.unmodifiableCollection(appliedFlowRules);
}
@Override
public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
Bmv2ThriftClient deviceClient;
try {
deviceClient = getDeviceClient();
} catch (Bmv2Exception e) {
return Collections.emptyList();
}
List<FlowRule> removedFlowRules = Lists.newArrayList();
for (FlowRule rule : rules) {
if (tableEntryIdsMap.containsKey(rule)) {
long entryId = tableEntryIdsMap.get(rule);
String tableName = parseTableName(rule.tableId());
try {
deviceClient.deleteTableEntry(tableName, entryId);
} catch (Bmv2Exception e) {
log.error("Unable to delete flow rule", e);
continue;
}
/* remove from local store */
tableEntryIdsMap.remove(rule);
tableRulesMap.get(rule.tableId()).remove(rule);
deviceEntriesMap.remove(rule);
removedFlowRules.add(rule);
}
}
return Collections.unmodifiableCollection(removedFlowRules);
}
private Bmv2TableEntry parseFlowRule(FlowRule flowRule) {
// TODO make it pipeline dependant, i.e. implement mapping
Bmv2TableEntry.Builder entryBuilder = Bmv2TableEntry.builder();
// Check selector
ExtensionCriterion ec =
(ExtensionCriterion) flowRule
.selector().getCriterion(Criterion.Type.EXTENSION);
Preconditions.checkState(
flowRule.selector().criteria().size() == 1
&& ec != null,
"Selector must have only 1 criterion of type EXTENSION");
ExtensionSelector es = ec.extensionSelector();
Preconditions.checkState(
es.type() == ExtensionSelectorType.ExtensionSelectorTypes.P4_BMV2_MATCH_KEY.type(),
"ExtensionSelectorType must be P4_BMV2_MATCH_KEY");
// Selector OK, get Bmv2MatchKey
entryBuilder.withMatchKey(((Bmv2ExtensionSelector) es).matchKey());
// Check treatment
Instruction inst = flowRule.treatment().allInstructions().get(0);
Preconditions.checkState(
flowRule.treatment().allInstructions().size() == 1
&& inst.type() == Instruction.Type.EXTENSION,
"Treatment must have only 1 instruction of type EXTENSION");
ExtensionTreatment et =
((Instructions.ExtensionInstructionWrapper) inst)
.extensionInstruction();
Preconditions.checkState(
et.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.P4_BMV2_ACTION.type(),
"ExtensionTreatmentType must be P4_BMV2_ACTION");
// Treatment OK, get Bmv2Action
entryBuilder.withAction(((Bmv2ExtensionTreatment) et).getAction());
// Table name
entryBuilder.withTableName(parseTableName(flowRule.tableId()));
if (!flowRule.isPermanent()) {
entryBuilder.withTimeout(flowRule.timeout());
}
entryBuilder.withPriority(flowRule.priority());
return entryBuilder.build();
}
private String parseTableName(int tableId) {
// TODO: map tableId with tableName according to P4 JSON
return "table" + String.valueOf(tableId);
}
private Bmv2ThriftClient getDeviceClient() throws Bmv2Exception {
try {
return Bmv2ThriftClient.of(handler().data().deviceId());
} catch (Bmv2Exception e) {
log.error("Failed to connect to Bmv2 device", e);
throw e;
}
}
}
/*
* Copyright 2014-2016 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.bmv2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.onosproject.bmv2.api.Bmv2Exception;
import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.behaviour.PortDiscovery;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.List;
public class Bmv2PortGetterDriver extends AbstractHandlerBehaviour
implements PortDiscovery {
private final Logger log =
LoggerFactory.getLogger(this.getClass());
@Override
public List<PortDescription> getPorts() {
Bmv2ThriftClient deviceClient;
try {
deviceClient = Bmv2ThriftClient.of(handler().data().deviceId());
} catch (Bmv2Exception e) {
log.error("Failed to connect to Bmv2 device", e);
return Collections.emptyList();
}
List<PortDescription> portDescriptions = Lists.newArrayList();
try {
deviceClient.getPortsInfo().forEach(
p -> {
DefaultAnnotations.Builder builder =
DefaultAnnotations.builder();
p.getExtraProperties().forEach(builder::set);
SparseAnnotations annotations = builder.build();
portDescriptions.add(new DefaultPortDescription(
PortNumber.portNumber(
(long) p.portNumber(),
p.ifaceName()),
p.isUp(),
annotations
));
});
} catch (Bmv2Exception e) {
log.error("Unable to get port description from Bmv2 device", e);
}
return ImmutableList.copyOf(portDescriptions);
}
}
/*
* Copyright 2014-2016 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.
*/
/**
* BMv2 driver implementation.
*/
package org.onosproject.drivers.bmv2;
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014-2016 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="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="unknown">
<behaviour api="org.onosproject.net.behaviour.PortDiscovery"
impl="org.onosproject.drivers.bmv2.Bmv2PortGetterDriver"/>
<behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleDriver"/>
</driver>
</drivers>
......@@ -41,6 +41,7 @@
<module>utilities</module>
<module>lumentum</module>
<module>bti</module>
<module>bmv2</module>
</modules>
<!--<properties>
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2014-2016 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="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>onos-protocols</artifactId>
<groupId>org.onosproject</groupId>
<version>1.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>onos-bmv2-protocol</artifactId>
<version>1.6.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<description>BMv2 protocol subsystem</description>
<properties>
<!-- BMv2 Commit ID and Thrift version -->
<bmv2.commit>a012ee4124c1892a91a359660824d311d5d7fe88</bmv2.commit>
<bmv2.thrift.version>0.9.3</bmv2.thrift.version>
<!-- Do not change below -->
<bmv2.baseurl>
https://raw.githubusercontent.com/p4lang/behavioral-model/${bmv2.commit}
</bmv2.baseurl>
<bmv2.thrift.srcdir>${project.basedir}/src/main/thrift</bmv2.thrift.srcdir>
<thrift.path>${project.build.directory}/thrift-compiler/</thrift.path>
<thrift.filename>thrift-${os.detected.classifier}.exe</thrift.filename>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>${bmv2.thrift.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<repositories>
<!-- Needed for thrift-compiler, which is hosted on GitHub -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.0.Final</version>
</extension>
</extensions>
<plugins>
<!-- Download Thrift source files from BMv2 Github repo -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>wagon-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>download-bmv2-thrift-standard</id>
<phase>validate</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>${bmv2.baseurl}</url>
<fromFile>thrift_src/standard.thrift</fromFile>
<toDir>${bmv2.thrift.srcdir}</toDir>
</configuration>
</execution>
<execution>
<id>download-bmv2-thrift-simple_pre</id>
<phase>initialize</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>${bmv2.baseurl}</url>
<fromFile>thrift_src/simple_pre.thrift</fromFile>
<toDir>${bmv2.thrift.srcdir}</toDir>
</configuration>
</execution>
<execution>
<id>download-bmv2-thrift-simple_pre_lag</id>
<phase>initialize</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>${bmv2.baseurl}</url>
<fromFile>thrift_src/simple_pre_lag.thrift
</fromFile>
<toDir>${bmv2.thrift.srcdir}</toDir>
</configuration>
</execution>
<execution>
<id>download-bmv2-thrift-simple_switch</id>
<phase>initialize</phase>
<goals>
<goal>download-single</goal>
</goals>
<configuration>
<url>${bmv2.baseurl}</url>
<fromFile>
targets/simple_switch/thrift/simple_switch.thrift
</fromFile>
<toDir>${bmv2.thrift.srcdir}</toDir>
</configuration>
</execution>
</executions>
</plugin>
<!-- Extract Thrift compiler -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>initialize</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.github.ccascone</groupId>
<artifactId>mvn-thrift-compiler</artifactId>
<version>1.1_${bmv2.thrift.version}</version>
<type>jar</type>
<includes>${thrift.filename}</includes>
<outputDirectory>${project.build.directory}/thrift-compiler</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- Add missing java namespace to Thrift files -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<id>add-bmv2-thrift-java-namespace</id>
<phase>initialize</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>${bmv2.thrift.srcdir}/patch.sh
</executable>
</configuration>
</execution>
<execution>
<id>set-thrift-compiler-permissions</id>
<phase>initialize</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>chmod</executable>
<arguments>
<argument>+x</argument>
<argument>${thrift.path}/${thrift.filename}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<!-- Compile Thrift files -->
<plugin>
<groupId>org.apache.thrift.tools</groupId>
<artifactId>maven-thrift-plugin</artifactId>
<version>0.1.11</version>
<configuration>
<thriftExecutable>${thrift.path}/${thrift.filename}</thriftExecutable>
</configuration>
<executions>
<execution>
<id>thrift-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Make generated sources visible -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>add-thrift-sources-to-path</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>
${project.build.directory}/target/generated-sources/thrift
</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
/*
* Copyright 2014-2016 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.bmv2.api;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Bmv2 Action representation.
*/
public final class Bmv2Action {
private final String name;
private final List<ByteBuffer> parameters;
private Bmv2Action(String name, List<ByteBuffer> parameters) {
// hide constructor
this.name = name;
this.parameters = parameters;
}
/**
* Returns a new action builder.
*/
public static Builder builder() {
return new Builder();
}
/**
* Get action name.
*
* @return action name
*/
public final String name() {
return name;
}
/**
* Get list of action parameters ordered as per P4 action definition.
*
* @return List of action parameters
*/
public final List<ByteBuffer> parameters() {
return Collections.unmodifiableList(parameters);
}
@Override
public final int hashCode() {
return Objects.hash(name, parameters);
}
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final Bmv2Action other = (Bmv2Action) obj;
return Objects.equals(this.name, other.name)
&& Objects.equals(this.parameters, other.parameters);
}
@Override
public final String toString() {
return MoreObjects.toStringHelper(this)
.add("name", name)
.add("parameters", parameters)
.toString();
}
/**
* A Bmv2 action builder.
*/
public static final class Builder {
private String name;
private List<ByteBuffer> parameters;
private Builder() {
this.parameters = Lists.newArrayList();
}
/**
* Set the action name.
*
* @param actionName a string value
* @return this
*/
public Builder withName(String actionName) {
this.name = actionName;
return this;
}
/**
* Add a parameter at the end of the parameters list.
*
* @param parameter a ByteBuffer value
* @return this
*/
public Builder addParameter(ByteBuffer parameter) {
parameters.add(parameter);
return this;
}
/**
* Builds a Bmv2 action object.
*
* @return a Bmv2 action
*/
public Bmv2Action build() {
checkNotNull(name, "Action name not set");
return new Bmv2Action(name, parameters);
}
}
}
/*
* Copyright 2014-2016 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.bmv2.api;
/**
* General Bmv2 exception.
*/
public class Bmv2Exception extends Exception {
public Bmv2Exception(String message, Throwable cause) {
super(message, cause);
}
}
/*
* Copyright 2014-2016 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.bmv2.api;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.flow.AbstractExtension;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType;
public class Bmv2ExtensionSelector extends AbstractExtension implements ExtensionSelector {
private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
private Bmv2MatchKey matchKey;
public Bmv2ExtensionSelector(Bmv2MatchKey matchKey) {
this.matchKey = matchKey;
}
public Bmv2MatchKey matchKey() {
return matchKey;
}
@Override
public ExtensionSelectorType type() {
return ExtensionSelectorType.ExtensionSelectorTypes.P4_BMV2_MATCH_KEY.type();
}
@Override
public byte[] serialize() {
return appKryo.serialize(matchKey);
}
@Override
public void deserialize(byte[] data) {
matchKey = appKryo.deserialize(data);
}
}
/*
* Copyright 2014-2016 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.bmv2.api;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.flow.AbstractExtension;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
public class Bmv2ExtensionTreatment extends AbstractExtension implements ExtensionTreatment {
private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
private Bmv2Action action;
public Bmv2ExtensionTreatment(Bmv2Action action) {
this.action = action;
}
public Bmv2Action getAction() {
return action;
}
@Override
public ExtensionTreatmentType type() {
return ExtensionTreatmentType.ExtensionTreatmentTypes.P4_BMV2_ACTION.type();
}
@Override
public byte[] serialize() {
return appKryo.serialize(action);
}
@Override
public void deserialize(byte[] data) {
action = appKryo.deserialize(data);
}
}
/*
* Copyright 2014-2016 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.bmv2.api;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import org.p4.bmv2.thrift.BmMatchParam;
import org.p4.bmv2.thrift.BmMatchParamExact;
import org.p4.bmv2.thrift.BmMatchParamLPM;
import org.p4.bmv2.thrift.BmMatchParamTernary;
import org.p4.bmv2.thrift.BmMatchParamType;
import org.p4.bmv2.thrift.BmMatchParamValid;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
* Bmv2 match key representation.
*/
public final class Bmv2MatchKey {
private final List<BmMatchParam> matchParams;
/**
* Creates a new match key.
*
* @param matchParams The ordered list of match parameters
*/
private Bmv2MatchKey(List<BmMatchParam> matchParams) {
this.matchParams = matchParams;
}
public static Builder builder() {
return new Builder();
}
/**
* Returns the match parameters defined for this match key (read-only).
*
* @return match parameters
*/
public final List<BmMatchParam> bmMatchParams() {
return Collections.unmodifiableList(matchParams);
}
@Override
public final int hashCode() {
return Objects.hashCode(matchParams);
}
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final Bmv2MatchKey other = (Bmv2MatchKey) obj;
return Objects.equals(this.matchParams, other.matchParams);
}
@Override
public final String toString() {
return MoreObjects.toStringHelper(this)
.addValue(matchParams)
.toString();
}
/**
* Builder of a Bmv2 match key.
*/
public static final class Builder {
private List<BmMatchParam> matchParams;
private Builder() {
this.matchParams = Lists.newArrayList();
}
/**
* Adds an exact match parameter.
*
* @param key a ByteBuffer value
* @return this
*/
public Builder withExact(ByteBuffer key) {
this.matchParams.add(
new BmMatchParam(BmMatchParamType.EXACT)
.setExact(new BmMatchParamExact(key)));
return this;
}
/**
* Adds a longest prefix match parameter.
*
* @param key a ByteBuffer value
* @param prefixLength an integer value
* @return this
*/
public Builder withLpm(ByteBuffer key, int prefixLength) {
this.matchParams.add(
new BmMatchParam(BmMatchParamType.LPM)
.setLpm(new BmMatchParamLPM(key, prefixLength)));
return this;
}
/**
* Adds a ternary match parameter.
*
* @param key a ByteBuffer value
* @param mask an ByteBuffer value
* @return this
*/
public Builder withTernary(ByteBuffer key, ByteBuffer mask) {
this.matchParams.add(
new BmMatchParam(BmMatchParamType.TERNARY).
setTernary(new BmMatchParamTernary(key, mask)));
return this;
}
/**
* Adds a ternary match parameter where all bits are don't-care.
*
* @param byteLength an integer value representing the length in byte of the parameter
* @return this
*/
public Builder withWildcard(int byteLength) {
byte[] zeros = new byte[byteLength];
Arrays.fill(zeros, (byte) 0);
return this.withTernary(ByteBuffer.wrap(zeros), ByteBuffer.wrap(zeros));
}
/**
* Adds a valid match parameter.
*
* @param key a boolean value
* @return this
*/
public Builder withValid(boolean key) {
this.matchParams.add(
new BmMatchParam(BmMatchParamType.VALID)
.setValid(new BmMatchParamValid(key)));
return this;
}
/**
* Builds a new match key object.
*
* @return match key
*/
public Bmv2MatchKey build() {
return new Bmv2MatchKey(this.matchParams);
}
}
}
\ No newline at end of file
/*
* Copyright 2014-2016 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.bmv2.api;
import com.google.common.base.MoreObjects;
import org.p4.bmv2.thrift.DevMgrPortInfo;
import java.util.Collections;
import java.util.Map;
/**
* Bmv2 representation of a switch port information.
*/
public final class Bmv2PortInfo {
private final DevMgrPortInfo portInfo;
public Bmv2PortInfo(DevMgrPortInfo portInfo) {
this.portInfo = portInfo;
}
public final String ifaceName() {
return portInfo.getIface_name();
}
public final int portNumber() {
return portInfo.getPort_num();
}
public final boolean isUp() {
return portInfo.isIs_up();
}
public final Map<String, String> getExtraProperties() {
return Collections.unmodifiableMap(portInfo.getExtra());
}
@Override
public final String toString() {
return MoreObjects.toStringHelper(this)
.addValue(portInfo)
.toString();
}
}
/*
* Copyright 2014-2016 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.bmv2.api;
import com.google.common.base.Preconditions;
import java.util.Objects;
/**
* Bmv2 representation of a table entry.
*/
public final class Bmv2TableEntry {
private static final int NO_PRIORITY_VALUE = -1;
private static final int NO_TIMEOUT_VALUE = -1;
private final String tableName;
private final Bmv2MatchKey matchKey;
private final Bmv2Action action;
private final int priority;
private final double timeout;
private Bmv2TableEntry(String tableName, Bmv2MatchKey matchKey,
Bmv2Action action, int priority, double timeout) {
this.tableName = tableName;
this.matchKey = matchKey;
this.action = action;
this.priority = priority;
this.timeout = timeout;
}
public static Builder builder() {
return new Builder();
}
/**
* Returns the name of the table where this entry is installed.
*
* @return table name
*/
public final String tableName() {
return this.tableName;
}
/**
* Returns the match key.
*
* @return match key
*/
public final Bmv2MatchKey matchKey() {
return matchKey;
}
/**
* Returns the action.
*
* @return action
*/
public final Bmv2Action action() {
return action;
}
/**
* Returns true is the entry has a valid priority value set.
*
* @return true if priority is set, false elsewhere
*/
public final boolean hasPriority() {
return this.priority != NO_PRIORITY_VALUE;
}
/**
* Return the entry priority.
*
* @return priority
*/
public final int priority() {
return priority;
}
/**
* Returns true is the entry has a valid timeout value set.
*
* @return true if timeout is set, false elsewhere
*/
public final boolean hasTimeout() {
return this.timeout != NO_PRIORITY_VALUE;
}
/**
* Returns the entry timeout in fractional seconds.
*
* @return timeout
*/
public final double timeout() {
return timeout;
}
@Override
public final int hashCode() {
return Objects.hash(matchKey, action, priority, timeout);
}
@Override
public final boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final Bmv2TableEntry other = (Bmv2TableEntry) obj;
return Objects.equals(this.matchKey, other.matchKey)
&& Objects.equals(this.action, other.action)
&& Objects.equals(this.priority, other.priority)
&& Objects.equals(this.timeout, other.timeout);
}
@Override
public final String toString() {
return com.google.common.base.MoreObjects.toStringHelper(this)
.addValue(matchKey)
.addValue(action)
.add("priority", priority)
.add("timeout", timeout)
.toString();
}
public static final class Builder {
private String tableName;
private Bmv2MatchKey matchKey;
private Bmv2Action action;
private int priority = NO_PRIORITY_VALUE;
private double timeout = NO_TIMEOUT_VALUE;
private Builder() {
// hide constructor
}
/**
* Sets the table name.
*
* @param tableName a string value
* @return this
*/
public Builder withTableName(String tableName) {
this.tableName = tableName;
return this;
}
/**
* Sets the match key.
*
* @param matchKey a match key value
* @return this
*/
public Builder withMatchKey(Bmv2MatchKey matchKey) {
this.matchKey = matchKey;
return this;
}
/**
* Sets the action.
*
* @param action an action value
* @return this
*/
public Builder withAction(Bmv2Action action) {
this.action = action;
return this;
}
public Builder withPriority(int priority) {
this.priority = priority;
return this;
}
/**
* Sets the timeout.
*
* @param timeout a timeout value in fractional seconds
* @return this
*/
public Builder withTimeout(double timeout) {
this.timeout = timeout;
return this;
}
/**
* Build the table entry.
*
* @return a new table entry object
*/
public Bmv2TableEntry build() {
Preconditions.checkNotNull(tableName);
Preconditions.checkNotNull(matchKey);
Preconditions.checkNotNull(action);
return new Bmv2TableEntry(tableName, matchKey, action, priority,
timeout);
}
}
}
/*
* Copyright 2014-2016 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.
*/
/**
* Bmv2 API abstractions.
*/
package org.onosproject.bmv2.api;
\ No newline at end of file
/*
* Copyright 2014-2016 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.
*/
/**
* BMv2 Thrift client implementation.
*/
package org.onosproject.bmv2.ctl;
\ No newline at end of file
*.thrift
\ No newline at end of file
#! /bin/bash
#
# Copyright 2014-2016 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.
# exit on errors
set -e
basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
ns="org.p4.bmv2.thrift"
# add java namespace at beginning of file
for f in ${basedir}/*.thrift
do
echo "namespace java ${ns}" | cat - ${f} > temp && mv temp ${f}
done
\ No newline at end of file
......@@ -41,6 +41,7 @@
<module>ospf</module>
<module>isis</module>
<module>snmp</module>
<module>bmv2</module>
</modules>
<dependencies>
......