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 1838 additions and 2 deletions
...@@ -38,7 +38,8 @@ public class ExtensionSelectorType { ...@@ -38,7 +38,8 @@ public class ExtensionSelectorType {
38 NICIRA_MATCH_NSH_CH2(3), 38 NICIRA_MATCH_NSH_CH2(3),
39 NICIRA_MATCH_NSH_CH3(4), 39 NICIRA_MATCH_NSH_CH3(4),
40 NICIRA_MATCH_NSH_CH4(5), 40 NICIRA_MATCH_NSH_CH4(5),
41 - OFDPA_MATCH_VLAN_VID(16); 41 + OFDPA_MATCH_VLAN_VID(16),
42 + P4_BMV2_MATCH_KEY(128);
42 43
43 private ExtensionSelectorType type; 44 private ExtensionSelectorType type;
44 45
......
...@@ -45,7 +45,8 @@ public final class ExtensionTreatmentType { ...@@ -45,7 +45,8 @@ public final class ExtensionTreatmentType {
45 NICIRA_SET_NSH_CH2(35), 45 NICIRA_SET_NSH_CH2(35),
46 NICIRA_SET_NSH_CH3(36), 46 NICIRA_SET_NSH_CH3(36),
47 NICIRA_SET_NSH_CH4(37), 47 NICIRA_SET_NSH_CH4(37),
48 - OFDPA_SET_VLAN_ID(64); 48 + OFDPA_SET_VLAN_ID(64),
49 + P4_BMV2_ACTION(128);
49 50
50 private ExtensionTreatmentType type; 51 private ExtensionTreatmentType type;
51 52
......
1 +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 +
3 +<!--
4 + ~ Copyright 2014-2016 Open Networking Laboratory
5 + ~
6 + ~ Licensed under the Apache License, Version 2.0 (the "License");
7 + ~ you may not use this file except in compliance with the License.
8 + ~ You may obtain a copy of the License at
9 + ~
10 + ~ http://www.apache.org/licenses/LICENSE-2.0
11 + ~
12 + ~ Unless required by applicable law or agreed to in writing, software
13 + ~ distributed under the License is distributed on an "AS IS" BASIS,
14 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 + ~ See the License for the specific language governing permissions and
16 + ~ limitations under the License.
17 + -->
18 +
19 +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
20 + <feature name="${project.artifactId}" version="${project.version}"
21 + description="${project.description}">
22 + <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
23 + <bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle>
24 + </feature>
25 +</features>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014-2016 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +
18 +<project xmlns="http://maven.apache.org/POM/4.0.0"
19 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21 + <parent>
22 + <artifactId>onos-drivers-general</artifactId>
23 + <groupId>org.onosproject</groupId>
24 + <version>1.6.0-SNAPSHOT</version>
25 + </parent>
26 + <modelVersion>4.0.0</modelVersion>
27 +
28 + <artifactId>onos-drivers-bmv2</artifactId>
29 + <version>1.6.0-SNAPSHOT</version>
30 +
31 + <packaging>bundle</packaging>
32 +
33 + <description>Device drivers for p4.org reference softswitch BMv2</description>
34 +
35 + <properties>
36 + <onos.app.name>org.onosproject.drivers.bmv2</onos.app.name>
37 + <onos.app.origin>ON.Lab</onos.app.origin>
38 + <onos.app.category>Drivers</onos.app.category>
39 + <onos.app.title>BMv2 Device Drivers</onos.app.title>
40 + <onos.app.url>http://onosproject.org</onos.app.url>
41 + <onos.app.requires>
42 + org.onosproject.bmv2
43 + </onos.app.requires>
44 + </properties>
45 +
46 + <dependencies>
47 + <dependency>
48 + <groupId>org.onosproject</groupId>
49 + <artifactId>onos-bmv2-protocol</artifactId>
50 + <version>${project.version}</version>
51 + </dependency>
52 + </dependencies>
53 +
54 +</project>
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.drivers.bmv2;
18 +
19 +import org.apache.felix.scr.annotations.Component;
20 +import org.onosproject.net.driver.AbstractDriverLoader;
21 +
22 +/**
23 + * Loader for barefoot drivers from specific xml.
24 + */
25 +@Component(immediate = true)
26 +public class Bmv2DriversLoader extends AbstractDriverLoader {
27 +
28 + private static final String DRIVERS_XML = "/bmv2-drivers.xml";
29 +
30 + public Bmv2DriversLoader() {
31 + super(DRIVERS_XML);
32 + }
33 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.drivers.bmv2;
18 +
19 +import com.google.common.base.Preconditions;
20 +import com.google.common.collect.Lists;
21 +import com.google.common.collect.Maps;
22 +import com.google.common.collect.Sets;
23 +import org.onosproject.bmv2.api.Bmv2ExtensionSelector;
24 +import org.onosproject.bmv2.api.Bmv2ExtensionTreatment;
25 +import org.onosproject.bmv2.api.Bmv2TableEntry;
26 +import org.onosproject.bmv2.api.Bmv2Exception;
27 +import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
28 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
29 +import org.onosproject.net.flow.DefaultFlowEntry;
30 +import org.onosproject.net.flow.FlowEntry;
31 +import org.onosproject.net.flow.FlowRule;
32 +import org.onosproject.net.flow.FlowRuleProgrammable;
33 +import org.onosproject.net.flow.criteria.Criterion;
34 +import org.onosproject.net.flow.criteria.ExtensionCriterion;
35 +import org.onosproject.net.flow.criteria.ExtensionSelector;
36 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
37 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
38 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
39 +import org.onosproject.net.flow.instructions.Instruction;
40 +import org.onosproject.net.flow.instructions.Instructions;
41 +import org.slf4j.Logger;
42 +import org.slf4j.LoggerFactory;
43 +
44 +import java.util.Collection;
45 +import java.util.Collections;
46 +import java.util.List;
47 +import java.util.Map;
48 +import java.util.Set;
49 +
50 +public class Bmv2FlowRuleDriver extends AbstractHandlerBehaviour
51 + implements FlowRuleProgrammable {
52 +
53 + private final Logger log =
54 + LoggerFactory.getLogger(this.getClass());
55 +
56 + // Bmv2 doesn't support proper table dump, use a local store
57 + // FIXME: synchronize entries with device
58 + private final Map<FlowRule, FlowEntry> deviceEntriesMap = Maps.newHashMap();
59 + private final Map<Integer, Set<FlowRule>> tableRulesMap = Maps.newHashMap();
60 + private final Map<FlowRule, Long> tableEntryIdsMap = Maps.newHashMap();
61 +
62 + @Override
63 + public Collection<FlowEntry> getFlowEntries() {
64 + return Collections.unmodifiableCollection(
65 + deviceEntriesMap.values());
66 + }
67 +
68 + @Override
69 + public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
70 + Bmv2ThriftClient deviceClient;
71 + try {
72 + deviceClient = getDeviceClient();
73 + } catch (Bmv2Exception e) {
74 + return Collections.emptyList();
75 + }
76 +
77 + List<FlowRule> appliedFlowRules = Lists.newArrayList();
78 +
79 + for (FlowRule rule : rules) {
80 +
81 + Bmv2TableEntry entry;
82 +
83 + try {
84 + entry = parseFlowRule(rule);
85 + } catch (IllegalStateException e) {
86 + log.error("Unable to parse flow rule", e);
87 + continue;
88 + }
89 +
90 + // Instantiate flowrule set for table if it does not exist
91 + if (!tableRulesMap.containsKey(rule.tableId())) {
92 + tableRulesMap.put(rule.tableId(), Sets.newHashSet());
93 + }
94 +
95 + if (tableRulesMap.get(rule.tableId()).contains(rule)) {
96 + /* Rule is already installed in the table */
97 + long entryId = tableEntryIdsMap.get(rule);
98 +
99 + try {
100 + deviceClient.modifyTableEntry(
101 + entry.tableName(), entryId, entry.action());
102 +
103 + // Replace stored rule as treatment, etc. might have changed
104 + // Java Set doesn't replace on add, remove first
105 + tableRulesMap.get(rule.tableId()).remove(rule);
106 + tableRulesMap.get(rule.tableId()).add(rule);
107 + tableEntryIdsMap.put(rule, entryId);
108 + deviceEntriesMap.put(rule, new DefaultFlowEntry(
109 + rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
110 + } catch (Bmv2Exception e) {
111 + log.error("Unable to update flow rule", e);
112 + continue;
113 + }
114 +
115 + } else {
116 + /* Rule is new */
117 + try {
118 + long entryId = deviceClient.addTableEntry(entry);
119 +
120 + tableRulesMap.get(rule.tableId()).add(rule);
121 + tableEntryIdsMap.put(rule, entryId);
122 + deviceEntriesMap.put(rule, new DefaultFlowEntry(
123 + rule, FlowEntry.FlowEntryState.ADDED, 0, 0, 0));
124 + } catch (Bmv2Exception e) {
125 + log.error("Unable to add flow rule", e);
126 + continue;
127 + }
128 + }
129 +
130 + appliedFlowRules.add(rule);
131 + }
132 +
133 + return Collections.unmodifiableCollection(appliedFlowRules);
134 + }
135 +
136 + @Override
137 + public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
138 + Bmv2ThriftClient deviceClient;
139 + try {
140 + deviceClient = getDeviceClient();
141 + } catch (Bmv2Exception e) {
142 + return Collections.emptyList();
143 + }
144 +
145 + List<FlowRule> removedFlowRules = Lists.newArrayList();
146 +
147 + for (FlowRule rule : rules) {
148 +
149 + if (tableEntryIdsMap.containsKey(rule)) {
150 + long entryId = tableEntryIdsMap.get(rule);
151 + String tableName = parseTableName(rule.tableId());
152 +
153 + try {
154 + deviceClient.deleteTableEntry(tableName, entryId);
155 + } catch (Bmv2Exception e) {
156 + log.error("Unable to delete flow rule", e);
157 + continue;
158 + }
159 +
160 + /* remove from local store */
161 + tableEntryIdsMap.remove(rule);
162 + tableRulesMap.get(rule.tableId()).remove(rule);
163 + deviceEntriesMap.remove(rule);
164 +
165 + removedFlowRules.add(rule);
166 + }
167 + }
168 +
169 + return Collections.unmodifiableCollection(removedFlowRules);
170 + }
171 +
172 + private Bmv2TableEntry parseFlowRule(FlowRule flowRule) {
173 +
174 + // TODO make it pipeline dependant, i.e. implement mapping
175 +
176 + Bmv2TableEntry.Builder entryBuilder = Bmv2TableEntry.builder();
177 +
178 + // Check selector
179 + ExtensionCriterion ec =
180 + (ExtensionCriterion) flowRule
181 + .selector().getCriterion(Criterion.Type.EXTENSION);
182 + Preconditions.checkState(
183 + flowRule.selector().criteria().size() == 1
184 + && ec != null,
185 + "Selector must have only 1 criterion of type EXTENSION");
186 + ExtensionSelector es = ec.extensionSelector();
187 + Preconditions.checkState(
188 + es.type() == ExtensionSelectorType.ExtensionSelectorTypes.P4_BMV2_MATCH_KEY.type(),
189 + "ExtensionSelectorType must be P4_BMV2_MATCH_KEY");
190 +
191 + // Selector OK, get Bmv2MatchKey
192 + entryBuilder.withMatchKey(((Bmv2ExtensionSelector) es).matchKey());
193 +
194 + // Check treatment
195 + Instruction inst = flowRule.treatment().allInstructions().get(0);
196 + Preconditions.checkState(
197 + flowRule.treatment().allInstructions().size() == 1
198 + && inst.type() == Instruction.Type.EXTENSION,
199 + "Treatment must have only 1 instruction of type EXTENSION");
200 + ExtensionTreatment et =
201 + ((Instructions.ExtensionInstructionWrapper) inst)
202 + .extensionInstruction();
203 +
204 + Preconditions.checkState(
205 + et.type() == ExtensionTreatmentType.ExtensionTreatmentTypes.P4_BMV2_ACTION.type(),
206 + "ExtensionTreatmentType must be P4_BMV2_ACTION");
207 +
208 + // Treatment OK, get Bmv2Action
209 + entryBuilder.withAction(((Bmv2ExtensionTreatment) et).getAction());
210 +
211 + // Table name
212 + entryBuilder.withTableName(parseTableName(flowRule.tableId()));
213 +
214 + if (!flowRule.isPermanent()) {
215 + entryBuilder.withTimeout(flowRule.timeout());
216 + }
217 +
218 + entryBuilder.withPriority(flowRule.priority());
219 +
220 + return entryBuilder.build();
221 + }
222 +
223 + private String parseTableName(int tableId) {
224 + // TODO: map tableId with tableName according to P4 JSON
225 + return "table" + String.valueOf(tableId);
226 + }
227 +
228 + private Bmv2ThriftClient getDeviceClient() throws Bmv2Exception {
229 + try {
230 + return Bmv2ThriftClient.of(handler().data().deviceId());
231 + } catch (Bmv2Exception e) {
232 + log.error("Failed to connect to Bmv2 device", e);
233 + throw e;
234 + }
235 + }
236 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.drivers.bmv2;
18 +
19 +import com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.Lists;
21 +import org.onosproject.bmv2.api.Bmv2Exception;
22 +import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
23 +import org.onosproject.net.DefaultAnnotations;
24 +import org.onosproject.net.PortNumber;
25 +import org.onosproject.net.SparseAnnotations;
26 +import org.onosproject.net.behaviour.PortDiscovery;
27 +import org.onosproject.net.device.DefaultPortDescription;
28 +import org.onosproject.net.device.PortDescription;
29 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
30 +import org.slf4j.Logger;
31 +import org.slf4j.LoggerFactory;
32 +
33 +import java.util.Collections;
34 +import java.util.List;
35 +
36 +public class Bmv2PortGetterDriver extends AbstractHandlerBehaviour
37 + implements PortDiscovery {
38 +
39 + private final Logger log =
40 + LoggerFactory.getLogger(this.getClass());
41 +
42 + @Override
43 + public List<PortDescription> getPorts() {
44 + Bmv2ThriftClient deviceClient;
45 + try {
46 + deviceClient = Bmv2ThriftClient.of(handler().data().deviceId());
47 + } catch (Bmv2Exception e) {
48 + log.error("Failed to connect to Bmv2 device", e);
49 + return Collections.emptyList();
50 + }
51 +
52 + List<PortDescription> portDescriptions = Lists.newArrayList();
53 +
54 + try {
55 +
56 + deviceClient.getPortsInfo().forEach(
57 + p -> {
58 + DefaultAnnotations.Builder builder =
59 + DefaultAnnotations.builder();
60 + p.getExtraProperties().forEach(builder::set);
61 + SparseAnnotations annotations = builder.build();
62 +
63 + portDescriptions.add(new DefaultPortDescription(
64 + PortNumber.portNumber(
65 + (long) p.portNumber(),
66 + p.ifaceName()),
67 + p.isUp(),
68 + annotations
69 + ));
70 + });
71 + } catch (Bmv2Exception e) {
72 + log.error("Unable to get port description from Bmv2 device", e);
73 + }
74 +
75 + return ImmutableList.copyOf(portDescriptions);
76 + }
77 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * BMv2 driver implementation.
19 + */
20 +package org.onosproject.drivers.bmv2;
...\ No newline at end of file ...\ No newline at end of file
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +
3 +<!--
4 + ~ Copyright 2014-2016 Open Networking Laboratory
5 + ~
6 + ~ Licensed under the Apache License, Version 2.0 (the "License");
7 + ~ you may not use this file except in compliance with the License.
8 + ~ You may obtain a copy of the License at
9 + ~
10 + ~ http://www.apache.org/licenses/LICENSE-2.0
11 + ~
12 + ~ Unless required by applicable law or agreed to in writing, software
13 + ~ distributed under the License is distributed on an "AS IS" BASIS,
14 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 + ~ See the License for the specific language governing permissions and
16 + ~ limitations under the License.
17 + -->
18 +<drivers>
19 + <driver name="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="unknown">
20 + <behaviour api="org.onosproject.net.behaviour.PortDiscovery"
21 + impl="org.onosproject.drivers.bmv2.Bmv2PortGetterDriver"/>
22 + <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
23 + impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleDriver"/>
24 + </driver>
25 +</drivers>
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
41 <module>utilities</module> 41 <module>utilities</module>
42 <module>lumentum</module> 42 <module>lumentum</module>
43 <module>bti</module> 43 <module>bti</module>
44 + <module>bmv2</module>
44 </modules> 45 </modules>
45 46
46 <!--<properties> 47 <!--<properties>
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<!--
3 + ~ Copyright 2014-2016 Open Networking Laboratory
4 + ~
5 + ~ Licensed under the Apache License, Version 2.0 (the "License");
6 + ~ you may not use this file except in compliance with the License.
7 + ~ You may obtain a copy of the License at
8 + ~
9 + ~ http://www.apache.org/licenses/LICENSE-2.0
10 + ~
11 + ~ Unless required by applicable law or agreed to in writing, software
12 + ~ distributed under the License is distributed on an "AS IS" BASIS,
13 + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + ~ See the License for the specific language governing permissions and
15 + ~ limitations under the License.
16 + -->
17 +
18 +<project xmlns="http://maven.apache.org/POM/4.0.0"
19 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
20 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
21 + <parent>
22 + <artifactId>onos-protocols</artifactId>
23 + <groupId>org.onosproject</groupId>
24 + <version>1.6.0-SNAPSHOT</version>
25 + </parent>
26 + <modelVersion>4.0.0</modelVersion>
27 +
28 + <artifactId>onos-bmv2-protocol</artifactId>
29 + <version>1.6.0-SNAPSHOT</version>
30 +
31 + <packaging>bundle</packaging>
32 +
33 + <description>BMv2 protocol subsystem</description>
34 +
35 + <properties>
36 + <!-- BMv2 Commit ID and Thrift version -->
37 + <bmv2.commit>a012ee4124c1892a91a359660824d311d5d7fe88</bmv2.commit>
38 + <bmv2.thrift.version>0.9.3</bmv2.thrift.version>
39 + <!-- Do not change below -->
40 + <bmv2.baseurl>
41 + https://raw.githubusercontent.com/p4lang/behavioral-model/${bmv2.commit}
42 + </bmv2.baseurl>
43 + <bmv2.thrift.srcdir>${project.basedir}/src/main/thrift</bmv2.thrift.srcdir>
44 + <thrift.path>${project.build.directory}/thrift-compiler/</thrift.path>
45 + <thrift.filename>thrift-${os.detected.classifier}.exe</thrift.filename>
46 + </properties>
47 +
48 + <dependencies>
49 + <dependency>
50 + <groupId>org.apache.thrift</groupId>
51 + <artifactId>libthrift</artifactId>
52 + <version>${bmv2.thrift.version}</version>
53 + </dependency>
54 + <dependency>
55 + <groupId>org.onosproject</groupId>
56 + <artifactId>onos-api</artifactId>
57 + <version>${project.version}</version>
58 + </dependency>
59 + </dependencies>
60 +
61 + <repositories>
62 + <!-- Needed for thrift-compiler, which is hosted on GitHub -->
63 + <repository>
64 + <id>jitpack.io</id>
65 + <url>https://jitpack.io</url>
66 + </repository>
67 + </repositories>
68 +
69 + <build>
70 + <extensions>
71 + <extension>
72 + <groupId>kr.motd.maven</groupId>
73 + <artifactId>os-maven-plugin</artifactId>
74 + <version>1.4.0.Final</version>
75 + </extension>
76 + </extensions>
77 +
78 + <plugins>
79 + <!-- Download Thrift source files from BMv2 Github repo -->
80 + <plugin>
81 + <groupId>org.codehaus.mojo</groupId>
82 + <artifactId>wagon-maven-plugin</artifactId>
83 + <version>1.0</version>
84 + <executions>
85 + <execution>
86 + <id>download-bmv2-thrift-standard</id>
87 + <phase>validate</phase>
88 + <goals>
89 + <goal>download-single</goal>
90 + </goals>
91 + <configuration>
92 + <url>${bmv2.baseurl}</url>
93 + <fromFile>thrift_src/standard.thrift</fromFile>
94 + <toDir>${bmv2.thrift.srcdir}</toDir>
95 + </configuration>
96 + </execution>
97 + <execution>
98 + <id>download-bmv2-thrift-simple_pre</id>
99 + <phase>initialize</phase>
100 + <goals>
101 + <goal>download-single</goal>
102 + </goals>
103 + <configuration>
104 + <url>${bmv2.baseurl}</url>
105 + <fromFile>thrift_src/simple_pre.thrift</fromFile>
106 + <toDir>${bmv2.thrift.srcdir}</toDir>
107 + </configuration>
108 + </execution>
109 + <execution>
110 + <id>download-bmv2-thrift-simple_pre_lag</id>
111 + <phase>initialize</phase>
112 + <goals>
113 + <goal>download-single</goal>
114 + </goals>
115 + <configuration>
116 + <url>${bmv2.baseurl}</url>
117 + <fromFile>thrift_src/simple_pre_lag.thrift
118 + </fromFile>
119 + <toDir>${bmv2.thrift.srcdir}</toDir>
120 + </configuration>
121 + </execution>
122 + <execution>
123 + <id>download-bmv2-thrift-simple_switch</id>
124 + <phase>initialize</phase>
125 + <goals>
126 + <goal>download-single</goal>
127 + </goals>
128 + <configuration>
129 + <url>${bmv2.baseurl}</url>
130 + <fromFile>
131 + targets/simple_switch/thrift/simple_switch.thrift
132 + </fromFile>
133 + <toDir>${bmv2.thrift.srcdir}</toDir>
134 + </configuration>
135 + </execution>
136 + </executions>
137 + </plugin>
138 + <!-- Extract Thrift compiler -->
139 + <plugin>
140 + <groupId>org.apache.maven.plugins</groupId>
141 + <artifactId>maven-dependency-plugin</artifactId>
142 + <executions>
143 + <execution>
144 + <id>unpack</id>
145 + <phase>initialize</phase>
146 + <goals>
147 + <goal>unpack</goal>
148 + </goals>
149 + <configuration>
150 + <artifactItems>
151 + <artifactItem>
152 + <groupId>com.github.ccascone</groupId>
153 + <artifactId>mvn-thrift-compiler</artifactId>
154 + <version>1.1_${bmv2.thrift.version}</version>
155 + <type>jar</type>
156 + <includes>${thrift.filename}</includes>
157 + <outputDirectory>${project.build.directory}/thrift-compiler</outputDirectory>
158 + </artifactItem>
159 + </artifactItems>
160 + </configuration>
161 + </execution>
162 + </executions>
163 + </plugin>
164 + <!-- Add missing java namespace to Thrift files -->
165 + <plugin>
166 + <groupId>org.codehaus.mojo</groupId>
167 + <artifactId>exec-maven-plugin</artifactId>
168 + <version>1.4.0</version>
169 + <executions>
170 + <execution>
171 + <id>add-bmv2-thrift-java-namespace</id>
172 + <phase>initialize</phase>
173 + <goals>
174 + <goal>exec</goal>
175 + </goals>
176 + <configuration>
177 + <executable>${bmv2.thrift.srcdir}/patch.sh
178 + </executable>
179 + </configuration>
180 + </execution>
181 + <execution>
182 + <id>set-thrift-compiler-permissions</id>
183 + <phase>initialize</phase>
184 + <goals>
185 + <goal>exec</goal>
186 + </goals>
187 + <configuration>
188 + <executable>chmod</executable>
189 + <arguments>
190 + <argument>+x</argument>
191 + <argument>${thrift.path}/${thrift.filename}</argument>
192 + </arguments>
193 + </configuration>
194 + </execution>
195 + </executions>
196 + </plugin>
197 + <!-- Compile Thrift files -->
198 + <plugin>
199 + <groupId>org.apache.thrift.tools</groupId>
200 + <artifactId>maven-thrift-plugin</artifactId>
201 + <version>0.1.11</version>
202 + <configuration>
203 + <thriftExecutable>${thrift.path}/${thrift.filename}</thriftExecutable>
204 + </configuration>
205 + <executions>
206 + <execution>
207 + <id>thrift-sources</id>
208 + <phase>generate-sources</phase>
209 + <goals>
210 + <goal>compile</goal>
211 + </goals>
212 + </execution>
213 + </executions>
214 + </plugin>
215 + <!-- Make generated sources visible -->
216 + <plugin>
217 + <groupId>org.codehaus.mojo</groupId>
218 + <artifactId>build-helper-maven-plugin</artifactId>
219 + <version>1.4</version>
220 + <executions>
221 + <execution>
222 + <id>add-thrift-sources-to-path</id>
223 + <phase>generate-sources</phase>
224 + <goals>
225 + <goal>add-source</goal>
226 + </goals>
227 + <configuration>
228 + <sources>
229 + <source>
230 + ${project.build.directory}/target/generated-sources/thrift
231 + </source>
232 + </sources>
233 + </configuration>
234 + </execution>
235 + </executions>
236 + </plugin>
237 + </plugins>
238 + </build>
239 +
240 +</project>
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import com.google.common.collect.Lists;
21 +
22 +import java.nio.ByteBuffer;
23 +import java.util.Collections;
24 +import java.util.List;
25 +import java.util.Objects;
26 +
27 +import static com.google.common.base.Preconditions.checkNotNull;
28 +
29 +/**
30 + * Bmv2 Action representation.
31 + */
32 +public final class Bmv2Action {
33 +
34 + private final String name;
35 + private final List<ByteBuffer> parameters;
36 +
37 + private Bmv2Action(String name, List<ByteBuffer> parameters) {
38 + // hide constructor
39 + this.name = name;
40 + this.parameters = parameters;
41 + }
42 +
43 + /**
44 + * Returns a new action builder.
45 + */
46 + public static Builder builder() {
47 + return new Builder();
48 + }
49 +
50 + /**
51 + * Get action name.
52 + *
53 + * @return action name
54 + */
55 + public final String name() {
56 + return name;
57 + }
58 +
59 + /**
60 + * Get list of action parameters ordered as per P4 action definition.
61 + *
62 + * @return List of action parameters
63 + */
64 + public final List<ByteBuffer> parameters() {
65 + return Collections.unmodifiableList(parameters);
66 + }
67 +
68 + @Override
69 + public final int hashCode() {
70 + return Objects.hash(name, parameters);
71 + }
72 +
73 + @Override
74 + public final boolean equals(Object obj) {
75 + if (this == obj) {
76 + return true;
77 + }
78 + if (obj == null || getClass() != obj.getClass()) {
79 + return false;
80 + }
81 + final Bmv2Action other = (Bmv2Action) obj;
82 + return Objects.equals(this.name, other.name)
83 + && Objects.equals(this.parameters, other.parameters);
84 + }
85 +
86 + @Override
87 + public final String toString() {
88 + return MoreObjects.toStringHelper(this)
89 + .add("name", name)
90 + .add("parameters", parameters)
91 + .toString();
92 + }
93 +
94 + /**
95 + * A Bmv2 action builder.
96 + */
97 + public static final class Builder {
98 +
99 + private String name;
100 + private List<ByteBuffer> parameters;
101 +
102 + private Builder() {
103 + this.parameters = Lists.newArrayList();
104 + }
105 +
106 + /**
107 + * Set the action name.
108 + *
109 + * @param actionName a string value
110 + * @return this
111 + */
112 + public Builder withName(String actionName) {
113 + this.name = actionName;
114 + return this;
115 + }
116 +
117 + /**
118 + * Add a parameter at the end of the parameters list.
119 + *
120 + * @param parameter a ByteBuffer value
121 + * @return this
122 + */
123 + public Builder addParameter(ByteBuffer parameter) {
124 + parameters.add(parameter);
125 + return this;
126 + }
127 +
128 + /**
129 + * Builds a Bmv2 action object.
130 + *
131 + * @return a Bmv2 action
132 + */
133 + public Bmv2Action build() {
134 + checkNotNull(name, "Action name not set");
135 + return new Bmv2Action(name, parameters);
136 + }
137 + }
138 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +/**
20 + * General Bmv2 exception.
21 + */
22 +public class Bmv2Exception extends Exception {
23 +
24 + public Bmv2Exception(String message, Throwable cause) {
25 + super(message, cause);
26 + }
27 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import org.onlab.util.KryoNamespace;
20 +import org.onosproject.net.flow.AbstractExtension;
21 +import org.onosproject.net.flow.criteria.ExtensionSelector;
22 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
23 +
24 +public class Bmv2ExtensionSelector extends AbstractExtension implements ExtensionSelector {
25 +
26 + private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
27 + private Bmv2MatchKey matchKey;
28 +
29 + public Bmv2ExtensionSelector(Bmv2MatchKey matchKey) {
30 + this.matchKey = matchKey;
31 + }
32 +
33 + public Bmv2MatchKey matchKey() {
34 + return matchKey;
35 + }
36 +
37 + @Override
38 + public ExtensionSelectorType type() {
39 + return ExtensionSelectorType.ExtensionSelectorTypes.P4_BMV2_MATCH_KEY.type();
40 + }
41 +
42 + @Override
43 + public byte[] serialize() {
44 + return appKryo.serialize(matchKey);
45 + }
46 +
47 + @Override
48 + public void deserialize(byte[] data) {
49 + matchKey = appKryo.deserialize(data);
50 + }
51 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import org.onlab.util.KryoNamespace;
20 +import org.onosproject.net.flow.AbstractExtension;
21 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
22 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
23 +
24 +public class Bmv2ExtensionTreatment extends AbstractExtension implements ExtensionTreatment {
25 +
26 + private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
27 + private Bmv2Action action;
28 +
29 + public Bmv2ExtensionTreatment(Bmv2Action action) {
30 + this.action = action;
31 + }
32 +
33 + public Bmv2Action getAction() {
34 + return action;
35 + }
36 +
37 + @Override
38 + public ExtensionTreatmentType type() {
39 + return ExtensionTreatmentType.ExtensionTreatmentTypes.P4_BMV2_ACTION.type();
40 + }
41 +
42 + @Override
43 + public byte[] serialize() {
44 + return appKryo.serialize(action);
45 + }
46 +
47 + @Override
48 + public void deserialize(byte[] data) {
49 + action = appKryo.deserialize(data);
50 + }
51 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import com.google.common.collect.Lists;
21 +import org.p4.bmv2.thrift.BmMatchParam;
22 +import org.p4.bmv2.thrift.BmMatchParamExact;
23 +import org.p4.bmv2.thrift.BmMatchParamLPM;
24 +import org.p4.bmv2.thrift.BmMatchParamTernary;
25 +import org.p4.bmv2.thrift.BmMatchParamType;
26 +import org.p4.bmv2.thrift.BmMatchParamValid;
27 +
28 +import java.nio.ByteBuffer;
29 +import java.util.Arrays;
30 +import java.util.Collections;
31 +import java.util.List;
32 +import java.util.Objects;
33 +
34 +/**
35 + * Bmv2 match key representation.
36 + */
37 +public final class Bmv2MatchKey {
38 +
39 + private final List<BmMatchParam> matchParams;
40 +
41 + /**
42 + * Creates a new match key.
43 + *
44 + * @param matchParams The ordered list of match parameters
45 + */
46 + private Bmv2MatchKey(List<BmMatchParam> matchParams) {
47 + this.matchParams = matchParams;
48 + }
49 +
50 + public static Builder builder() {
51 + return new Builder();
52 + }
53 +
54 + /**
55 + * Returns the match parameters defined for this match key (read-only).
56 + *
57 + * @return match parameters
58 + */
59 + public final List<BmMatchParam> bmMatchParams() {
60 + return Collections.unmodifiableList(matchParams);
61 + }
62 +
63 + @Override
64 + public final int hashCode() {
65 + return Objects.hashCode(matchParams);
66 + }
67 +
68 + @Override
69 + public final boolean equals(Object obj) {
70 + if (this == obj) {
71 + return true;
72 + }
73 + if (obj == null || getClass() != obj.getClass()) {
74 + return false;
75 + }
76 + final Bmv2MatchKey other = (Bmv2MatchKey) obj;
77 +
78 + return Objects.equals(this.matchParams, other.matchParams);
79 + }
80 +
81 + @Override
82 + public final String toString() {
83 + return MoreObjects.toStringHelper(this)
84 + .addValue(matchParams)
85 + .toString();
86 + }
87 +
88 + /**
89 + * Builder of a Bmv2 match key.
90 + */
91 + public static final class Builder {
92 +
93 + private List<BmMatchParam> matchParams;
94 +
95 + private Builder() {
96 + this.matchParams = Lists.newArrayList();
97 + }
98 +
99 + /**
100 + * Adds an exact match parameter.
101 + *
102 + * @param key a ByteBuffer value
103 + * @return this
104 + */
105 + public Builder withExact(ByteBuffer key) {
106 + this.matchParams.add(
107 + new BmMatchParam(BmMatchParamType.EXACT)
108 + .setExact(new BmMatchParamExact(key)));
109 + return this;
110 + }
111 +
112 +
113 + /**
114 + * Adds a longest prefix match parameter.
115 + *
116 + * @param key a ByteBuffer value
117 + * @param prefixLength an integer value
118 + * @return this
119 + */
120 + public Builder withLpm(ByteBuffer key, int prefixLength) {
121 + this.matchParams.add(
122 + new BmMatchParam(BmMatchParamType.LPM)
123 + .setLpm(new BmMatchParamLPM(key, prefixLength)));
124 + return this;
125 + }
126 +
127 + /**
128 + * Adds a ternary match parameter.
129 + *
130 + * @param key a ByteBuffer value
131 + * @param mask an ByteBuffer value
132 + * @return this
133 + */
134 + public Builder withTernary(ByteBuffer key, ByteBuffer mask) {
135 + this.matchParams.add(
136 + new BmMatchParam(BmMatchParamType.TERNARY).
137 + setTernary(new BmMatchParamTernary(key, mask)));
138 + return this;
139 + }
140 +
141 + /**
142 + * Adds a ternary match parameter where all bits are don't-care.
143 + *
144 + * @param byteLength an integer value representing the length in byte of the parameter
145 + * @return this
146 + */
147 + public Builder withWildcard(int byteLength) {
148 + byte[] zeros = new byte[byteLength];
149 + Arrays.fill(zeros, (byte) 0);
150 + return this.withTernary(ByteBuffer.wrap(zeros), ByteBuffer.wrap(zeros));
151 + }
152 +
153 + /**
154 + * Adds a valid match parameter.
155 + *
156 + * @param key a boolean value
157 + * @return this
158 + */
159 + public Builder withValid(boolean key) {
160 + this.matchParams.add(
161 + new BmMatchParam(BmMatchParamType.VALID)
162 + .setValid(new BmMatchParamValid(key)));
163 + return this;
164 + }
165 +
166 + /**
167 + * Builds a new match key object.
168 + *
169 + * @return match key
170 + */
171 + public Bmv2MatchKey build() {
172 + return new Bmv2MatchKey(this.matchParams);
173 + }
174 + }
175 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import com.google.common.base.MoreObjects;
20 +import org.p4.bmv2.thrift.DevMgrPortInfo;
21 +
22 +import java.util.Collections;
23 +import java.util.Map;
24 +
25 +/**
26 + * Bmv2 representation of a switch port information.
27 + */
28 +public final class Bmv2PortInfo {
29 +
30 + private final DevMgrPortInfo portInfo;
31 +
32 + public Bmv2PortInfo(DevMgrPortInfo portInfo) {
33 + this.portInfo = portInfo;
34 + }
35 +
36 + public final String ifaceName() {
37 + return portInfo.getIface_name();
38 + }
39 +
40 + public final int portNumber() {
41 + return portInfo.getPort_num();
42 + }
43 +
44 + public final boolean isUp() {
45 + return portInfo.isIs_up();
46 + }
47 +
48 + public final Map<String, String> getExtraProperties() {
49 + return Collections.unmodifiableMap(portInfo.getExtra());
50 + }
51 +
52 + @Override
53 + public final String toString() {
54 + return MoreObjects.toStringHelper(this)
55 + .addValue(portInfo)
56 + .toString();
57 + }
58 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.api;
18 +
19 +import com.google.common.base.Preconditions;
20 +
21 +import java.util.Objects;
22 +
23 +/**
24 + * Bmv2 representation of a table entry.
25 + */
26 +public final class Bmv2TableEntry {
27 +
28 + private static final int NO_PRIORITY_VALUE = -1;
29 + private static final int NO_TIMEOUT_VALUE = -1;
30 +
31 + private final String tableName;
32 + private final Bmv2MatchKey matchKey;
33 + private final Bmv2Action action;
34 + private final int priority;
35 + private final double timeout;
36 +
37 + private Bmv2TableEntry(String tableName, Bmv2MatchKey matchKey,
38 + Bmv2Action action, int priority, double timeout) {
39 + this.tableName = tableName;
40 + this.matchKey = matchKey;
41 + this.action = action;
42 + this.priority = priority;
43 + this.timeout = timeout;
44 + }
45 +
46 + public static Builder builder() {
47 + return new Builder();
48 + }
49 +
50 + /**
51 + * Returns the name of the table where this entry is installed.
52 + *
53 + * @return table name
54 + */
55 + public final String tableName() {
56 + return this.tableName;
57 + }
58 +
59 + /**
60 + * Returns the match key.
61 + *
62 + * @return match key
63 + */
64 + public final Bmv2MatchKey matchKey() {
65 + return matchKey;
66 + }
67 +
68 + /**
69 + * Returns the action.
70 + *
71 + * @return action
72 + */
73 + public final Bmv2Action action() {
74 + return action;
75 + }
76 +
77 + /**
78 + * Returns true is the entry has a valid priority value set.
79 + *
80 + * @return true if priority is set, false elsewhere
81 + */
82 + public final boolean hasPriority() {
83 + return this.priority != NO_PRIORITY_VALUE;
84 + }
85 +
86 + /**
87 + * Return the entry priority.
88 + *
89 + * @return priority
90 + */
91 + public final int priority() {
92 + return priority;
93 + }
94 +
95 + /**
96 + * Returns true is the entry has a valid timeout value set.
97 + *
98 + * @return true if timeout is set, false elsewhere
99 + */
100 + public final boolean hasTimeout() {
101 + return this.timeout != NO_PRIORITY_VALUE;
102 + }
103 +
104 + /**
105 + * Returns the entry timeout in fractional seconds.
106 + *
107 + * @return timeout
108 + */
109 + public final double timeout() {
110 + return timeout;
111 + }
112 +
113 + @Override
114 + public final int hashCode() {
115 + return Objects.hash(matchKey, action, priority, timeout);
116 + }
117 +
118 + @Override
119 + public final boolean equals(Object obj) {
120 + if (this == obj) {
121 + return true;
122 + }
123 + if (obj == null || getClass() != obj.getClass()) {
124 + return false;
125 + }
126 + final Bmv2TableEntry other = (Bmv2TableEntry) obj;
127 + return Objects.equals(this.matchKey, other.matchKey)
128 + && Objects.equals(this.action, other.action)
129 + && Objects.equals(this.priority, other.priority)
130 + && Objects.equals(this.timeout, other.timeout);
131 + }
132 +
133 + @Override
134 + public final String toString() {
135 + return com.google.common.base.MoreObjects.toStringHelper(this)
136 + .addValue(matchKey)
137 + .addValue(action)
138 + .add("priority", priority)
139 + .add("timeout", timeout)
140 + .toString();
141 + }
142 +
143 + public static final class Builder {
144 +
145 + private String tableName;
146 + private Bmv2MatchKey matchKey;
147 + private Bmv2Action action;
148 + private int priority = NO_PRIORITY_VALUE;
149 + private double timeout = NO_TIMEOUT_VALUE;
150 +
151 + private Builder() {
152 + // hide constructor
153 + }
154 +
155 + /**
156 + * Sets the table name.
157 + *
158 + * @param tableName a string value
159 + * @return this
160 + */
161 + public Builder withTableName(String tableName) {
162 + this.tableName = tableName;
163 + return this;
164 + }
165 +
166 + /**
167 + * Sets the match key.
168 + *
169 + * @param matchKey a match key value
170 + * @return this
171 + */
172 + public Builder withMatchKey(Bmv2MatchKey matchKey) {
173 + this.matchKey = matchKey;
174 + return this;
175 + }
176 +
177 + /**
178 + * Sets the action.
179 + *
180 + * @param action an action value
181 + * @return this
182 + */
183 + public Builder withAction(Bmv2Action action) {
184 + this.action = action;
185 + return this;
186 + }
187 +
188 + public Builder withPriority(int priority) {
189 + this.priority = priority;
190 + return this;
191 + }
192 +
193 + /**
194 + * Sets the timeout.
195 + *
196 + * @param timeout a timeout value in fractional seconds
197 + * @return this
198 + */
199 + public Builder withTimeout(double timeout) {
200 + this.timeout = timeout;
201 + return this;
202 + }
203 +
204 + /**
205 + * Build the table entry.
206 + *
207 + * @return a new table entry object
208 + */
209 + public Bmv2TableEntry build() {
210 + Preconditions.checkNotNull(tableName);
211 + Preconditions.checkNotNull(matchKey);
212 + Preconditions.checkNotNull(action);
213 +
214 + return new Bmv2TableEntry(tableName, matchKey, action, priority,
215 + timeout);
216 +
217 + }
218 + }
219 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * Bmv2 API abstractions.
19 + */
20 +package org.onosproject.bmv2.api;
...\ No newline at end of file ...\ No newline at end of file
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.bmv2.ctl;
18 +
19 +import com.google.common.cache.CacheBuilder;
20 +import com.google.common.cache.CacheLoader;
21 +import com.google.common.cache.LoadingCache;
22 +import com.google.common.cache.RemovalListener;
23 +import com.google.common.cache.RemovalNotification;
24 +import com.google.common.collect.Lists;
25 +import org.apache.commons.lang3.tuple.ImmutablePair;
26 +import org.apache.commons.lang3.tuple.Pair;
27 +import org.apache.thrift.TException;
28 +import org.apache.thrift.protocol.TBinaryProtocol;
29 +import org.apache.thrift.protocol.TMultiplexedProtocol;
30 +import org.apache.thrift.protocol.TProtocol;
31 +import org.apache.thrift.transport.TSocket;
32 +import org.apache.thrift.transport.TTransport;
33 +import org.apache.thrift.transport.TTransportException;
34 +import org.onosproject.bmv2.api.Bmv2Action;
35 +import org.onosproject.bmv2.api.Bmv2Exception;
36 +import org.onosproject.bmv2.api.Bmv2PortInfo;
37 +import org.onosproject.bmv2.api.Bmv2TableEntry;
38 +import org.onosproject.net.DeviceId;
39 +import org.p4.bmv2.thrift.BmAddEntryOptions;
40 +import org.p4.bmv2.thrift.DevMgrPortInfo;
41 +import org.p4.bmv2.thrift.Standard;
42 +
43 +import java.util.Collection;
44 +import java.util.List;
45 +import java.util.concurrent.ExecutionException;
46 +import java.util.concurrent.TimeUnit;
47 +import java.util.stream.Collectors;
48 +
49 +import static com.google.common.base.Preconditions.checkNotNull;
50 +
51 +/**
52 + * Implementation of a Thrift client to control the Bmv2 switch.
53 + */
54 +public final class Bmv2ThriftClient {
55 + /*
56 + FIXME: derive context_id from device id
57 + Using different context id values should serve to control different
58 + switches responding to the same IP address and port
59 + */
60 + private static final int CONTEXT_ID = 0;
61 + /*
62 + Static transport/client cache:
63 + - avoids opening a new transport session when there's one already open
64 + - close the connection after a predefined timeout of 5 seconds
65 + */
66 + private static LoadingCache<DeviceId, Pair<TTransport, Standard.Iface>>
67 + clientCache = CacheBuilder.newBuilder()
68 + .expireAfterAccess(5, TimeUnit.SECONDS)
69 + .removalListener(new ClientRemovalListener())
70 + .build(new ClientLoader());
71 + private final Standard.Iface stdClient;
72 +
73 + // ban constructor
74 + private Bmv2ThriftClient(Standard.Iface stdClient) {
75 + this.stdClient = stdClient;
76 + }
77 +
78 + /**
79 + * Returns a client object to control the passed device.
80 + *
81 + * @param deviceId device id
82 + * @return bmv2 client object
83 + * @throws Bmv2Exception if a connection to the device cannot be established
84 + */
85 + public static Bmv2ThriftClient of(DeviceId deviceId) throws Bmv2Exception {
86 + try {
87 + checkNotNull(deviceId, "deviceId cannot be null");
88 + return new Bmv2ThriftClient(clientCache.get(deviceId).getValue());
89 + } catch (ExecutionException e) {
90 + throw new Bmv2Exception(e.getMessage(), e.getCause());
91 + }
92 + }
93 +
94 + /**
95 + * Pings the device. Returns true if the device is reachable,
96 + * false otherwise.
97 + *
98 + * @param deviceId device id
99 + * @return true if reachable, false otherwise
100 + */
101 + public static boolean ping(DeviceId deviceId) {
102 + // poll ports status as workaround to assess device reachability
103 + try {
104 + of(deviceId).stdClient.bm_dev_mgr_show_ports();
105 + return true;
106 + } catch (TException | Bmv2Exception e) {
107 + return false;
108 + }
109 + }
110 +
111 + /**
112 + * Parse device ID into host and port.
113 + *
114 + * @param did device ID
115 + * @return a pair of host and port
116 + */
117 + private static Pair<String, Integer> parseDeviceId(DeviceId did) {
118 + String[] info = did.toString().split(":");
119 + if (info.length == 3) {
120 + String host = info[1];
121 + int port = Integer.parseInt(info[2]);
122 + return ImmutablePair.of(host, port);
123 + } else {
124 + throw new IllegalArgumentException(
125 + "Unable to parse BMv2 device ID "
126 + + did.toString()
127 + + ", expected format is scheme:host:port");
128 + }
129 + }
130 +
131 + /**
132 + * Adds a new table entry.
133 + *
134 + * @param entry a table entry value
135 + * @return table-specific entry ID
136 + * @throws Bmv2Exception if any error occurs
137 + */
138 + public final long addTableEntry(Bmv2TableEntry entry) throws Bmv2Exception {
139 +
140 + long entryId = -1;
141 +
142 + try {
143 + BmAddEntryOptions options = new BmAddEntryOptions();
144 +
145 + if (entry.hasPriority()) {
146 + options.setPriority(entry.priority());
147 + }
148 +
149 + entryId = stdClient.bm_mt_add_entry(
150 + CONTEXT_ID,
151 + entry.tableName(),
152 + entry.matchKey().bmMatchParams(),
153 + entry.action().name(),
154 + entry.action().parameters(),
155 + options);
156 +
157 + if (entry.hasTimeout()) {
158 + /* bmv2 accepts timeouts in milliseconds */
159 + int msTimeout = (int) Math.round(entry.timeout() * 1_000);
160 + stdClient.bm_mt_set_entry_ttl(
161 + CONTEXT_ID, entry.tableName(), entryId, msTimeout);
162 + }
163 +
164 + return entryId;
165 +
166 + } catch (TException e) {
167 + if (entryId != -1) {
168 + try {
169 + stdClient.bm_mt_delete_entry(
170 + CONTEXT_ID, entry.tableName(), entryId);
171 + } catch (TException e1) {
172 + // this should never happen as we know the entry is there
173 + throw new Bmv2Exception(e1.getMessage(), e1);
174 + }
175 + }
176 + throw new Bmv2Exception(e.getMessage(), e);
177 + }
178 + }
179 +
180 + /**
181 + * Modifies a currently installed entry by updating its action.
182 + *
183 + * @param tableName string value of table name
184 + * @param entryId long value of entry ID
185 + * @param action an action value
186 + * @throws Bmv2Exception if any error occurs
187 + */
188 + public final void modifyTableEntry(String tableName,
189 + long entryId, Bmv2Action action)
190 + throws Bmv2Exception {
191 +
192 + try {
193 + stdClient.bm_mt_modify_entry(
194 + CONTEXT_ID,
195 + tableName,
196 + entryId,
197 + action.name(),
198 + action.parameters()
199 + );
200 + } catch (TException e) {
201 + throw new Bmv2Exception(e.getMessage(), e);
202 + }
203 + }
204 +
205 + /**
206 + * Deletes currently installed entry.
207 + *
208 + * @param tableName string value of table name
209 + * @param entryId long value of entry ID
210 + * @throws Bmv2Exception if any error occurs
211 + */
212 + public final void deleteTableEntry(String tableName,
213 + long entryId) throws Bmv2Exception {
214 +
215 + try {
216 + stdClient.bm_mt_delete_entry(CONTEXT_ID, tableName, entryId);
217 + } catch (TException e) {
218 + throw new Bmv2Exception(e.getMessage(), e);
219 + }
220 + }
221 +
222 + /**
223 + * Sets table default action.
224 + *
225 + * @param tableName string value of table name
226 + * @param action an action value
227 + * @throws Bmv2Exception if any error occurs
228 + */
229 + public final void setTableDefaultAction(String tableName, Bmv2Action action)
230 + throws Bmv2Exception {
231 +
232 + try {
233 + stdClient.bm_mt_set_default_action(
234 + CONTEXT_ID,
235 + tableName,
236 + action.name(),
237 + action.parameters());
238 + } catch (TException e) {
239 + throw new Bmv2Exception(e.getMessage(), e);
240 + }
241 + }
242 +
243 + /**
244 + * Returns information of the ports currently configured in the switch.
245 + *
246 + * @return collection of port information
247 + * @throws Bmv2Exception if any error occurs
248 + */
249 + public Collection<Bmv2PortInfo> getPortsInfo() throws Bmv2Exception {
250 +
251 + try {
252 + List<DevMgrPortInfo> portInfos = stdClient.bm_dev_mgr_show_ports();
253 +
254 + Collection<Bmv2PortInfo> bmv2PortInfos = Lists.newArrayList();
255 +
256 + bmv2PortInfos.addAll(
257 + portInfos.stream()
258 + .map(Bmv2PortInfo::new)
259 + .collect(Collectors.toList()));
260 +
261 + return bmv2PortInfos;
262 +
263 + } catch (TException e) {
264 + throw new Bmv2Exception(e.getMessage(), e);
265 + }
266 + }
267 +
268 + /**
269 + * Return a string representation of a table content.
270 + *
271 + * @param tableName string value of table name
272 + * @return table string dump
273 + * @throws Bmv2Exception if any error occurs
274 + */
275 + public String dumpTable(String tableName) throws Bmv2Exception {
276 +
277 + try {
278 + return stdClient.bm_dump_table(CONTEXT_ID, tableName);
279 + } catch (TException e) {
280 + throw new Bmv2Exception(e.getMessage(), e);
281 + }
282 + }
283 +
284 + /**
285 + * Reset the state of the switch (e.g. delete all entries, etc.).
286 + *
287 + * @throws Bmv2Exception if any error occurs
288 + */
289 + public void resetState() throws Bmv2Exception {
290 +
291 + try {
292 + stdClient.bm_reset_state();
293 + } catch (TException e) {
294 + throw new Bmv2Exception(e.getMessage(), e);
295 + }
296 + }
297 +
298 + /**
299 + * Transport/client cache loader.
300 + */
301 + private static class ClientLoader
302 + extends CacheLoader<DeviceId, Pair<TTransport, Standard.Iface>> {
303 +
304 + @Override
305 + public Pair<TTransport, Standard.Iface> load(DeviceId deviceId)
306 + throws TTransportException {
307 + Pair<String, Integer> info = parseDeviceId(deviceId);
308 + //make the expensive call
309 + TTransport transport = new TSocket(
310 + info.getLeft(), info.getRight());
311 + TProtocol protocol = new TBinaryProtocol(transport);
312 + Standard.Iface stdClient = new Standard.Client(
313 + new TMultiplexedProtocol(protocol, "standard"));
314 +
315 + transport.open();
316 +
317 + return ImmutablePair.of(transport, stdClient);
318 + }
319 + }
320 +
321 + /**
322 + * Client cache removal listener. Close the connection on cache removal.
323 + */
324 + private static class ClientRemovalListener implements
325 + RemovalListener<DeviceId, Pair<TTransport, Standard.Iface>> {
326 +
327 + @Override
328 + public void onRemoval(
329 + RemovalNotification<DeviceId, Pair<TTransport, Standard.Iface>>
330 + notification) {
331 + // close the transport connection
332 + notification.getValue().getKey().close();
333 + }
334 + }
335 +}
1 +/*
2 + * Copyright 2014-2016 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * BMv2 Thrift client implementation.
19 + */
20 +package org.onosproject.bmv2.ctl;
...\ No newline at end of file ...\ No newline at end of file
1 +*.thrift
...\ No newline at end of file ...\ No newline at end of file
1 +#! /bin/bash
2 +#
3 +# Copyright 2014-2016 Open Networking Laboratory
4 +#
5 +# Licensed under the Apache License, Version 2.0 (the "License");
6 +# you may not use this file except in compliance with the License.
7 +# You may obtain a copy of the License at
8 +#
9 +# http://www.apache.org/licenses/LICENSE-2.0
10 +#
11 +# Unless required by applicable law or agreed to in writing, software
12 +# distributed under the License is distributed on an "AS IS" BASIS,
13 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 +# See the License for the specific language governing permissions and
15 +# limitations under the License.
16 +
17 +# exit on errors
18 +set -e
19 +
20 +basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
21 +ns="org.p4.bmv2.thrift"
22 +
23 +# add java namespace at beginning of file
24 +for f in ${basedir}/*.thrift
25 +do
26 + echo "namespace java ${ns}" | cat - ${f} > temp && mv temp ${f}
27 +done
...\ No newline at end of file ...\ No newline at end of file
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
41 <module>ospf</module> 41 <module>ospf</module>
42 <module>isis</module> 42 <module>isis</module>
43 <module>snmp</module> 43 <module>snmp</module>
44 + <module>bmv2</module>
44 </modules> 45 </modules>
45 46
46 <dependencies> 47 <dependencies>
......