Carmelo Cascone
Committed by Gerrit Code Review

ONOS-4410 Implemented PacketProgrammable and Pipeliner behaviors in the

BMv2 driver

Also other minor fixes / refactorings

Change-Id: I2205890b76471e8e8490beccd6b36e5358f8d407
...@@ -49,6 +49,11 @@ ...@@ -49,6 +49,11 @@
49 <artifactId>onos-bmv2-protocol</artifactId> 49 <artifactId>onos-bmv2-protocol</artifactId>
50 <version>${project.version}</version> 50 <version>${project.version}</version>
51 </dependency> 51 </dependency>
52 + <dependency>
53 + <groupId>org.onosproject</groupId>
54 + <artifactId>onos-drivers</artifactId>
55 + <version>${project.version}</version>
56 + </dependency>
52 </dependencies> 57 </dependencies>
53 58
54 </project> 59 </project>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -42,11 +42,14 @@ import java.util.Collections; ...@@ -42,11 +42,14 @@ import java.util.Collections;
42 import java.util.List; 42 import java.util.List;
43 import java.util.concurrent.ConcurrentMap; 43 import java.util.concurrent.ConcurrentMap;
44 44
45 -public class Bmv2FlowRuleDriver extends AbstractHandlerBehaviour 45 +/**
46 + * Flow rule programmable device behaviour implementation for BMv2.
47 + */
48 +public class Bmv2FlowRuleProgrammable extends AbstractHandlerBehaviour
46 implements FlowRuleProgrammable { 49 implements FlowRuleProgrammable {
47 50
48 private static final Logger LOG = 51 private static final Logger LOG =
49 - LoggerFactory.getLogger(Bmv2FlowRuleDriver.class); 52 + LoggerFactory.getLogger(Bmv2FlowRuleProgrammable.class);
50 // There's no Bmv2 client method to poll flow entries from the device device. gitNeed a local store. 53 // There's no Bmv2 client method to poll flow entries from the device device. gitNeed a local store.
51 private static final ConcurrentMap<Triple<DeviceId, String, Bmv2MatchKey>, Pair<Long, FlowEntry>> 54 private static final ConcurrentMap<Triple<DeviceId, String, Bmv2MatchKey>, Pair<Long, FlowEntry>>
52 ENTRIES_MAP = Maps.newConcurrentMap(); 55 ENTRIES_MAP = Maps.newConcurrentMap();
......
1 +/*
2 + * Copyright 2016-present 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.onlab.util.ImmutableByteSequence;
20 +import org.onosproject.bmv2.api.runtime.Bmv2Client;
21 +import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
22 +import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
23 +import org.onosproject.net.DeviceId;
24 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
25 +import org.onosproject.net.flow.TrafficTreatment;
26 +import org.onosproject.net.flow.instructions.Instructions;
27 +import org.onosproject.net.packet.OutboundPacket;
28 +import org.onosproject.net.packet.PacketProgrammable;
29 +import org.slf4j.Logger;
30 +import org.slf4j.LoggerFactory;
31 +
32 +import static java.lang.Math.toIntExact;
33 +import static org.onosproject.net.PortNumber.FLOOD;
34 +import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
35 +
36 +/**
37 + * Packet programmable device behaviour implementation for BMv2.
38 + */
39 +public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable {
40 +
41 + private static final Logger LOG =
42 + LoggerFactory.getLogger(Bmv2FlowRuleProgrammable.class);
43 +
44 + @Override
45 + public void emit(OutboundPacket packet) {
46 +
47 + TrafficTreatment treatment = packet.treatment();
48 +
49 + treatment.allInstructions().forEach(inst -> {
50 + if (inst.type().equals(OUTPUT)) {
51 + Instructions.OutputInstruction outInst = (Instructions.OutputInstruction) inst;
52 + if (outInst.port().isLogical()) {
53 + if (outInst.port() == FLOOD) {
54 + // TODO: implement flood
55 + LOG.info("Flood not implemented", outInst);
56 + }
57 + LOG.info("Output on logical port not supported: {}", outInst);
58 + } else {
59 + try {
60 + long longPort = outInst.port().toLong();
61 + int portNumber = toIntExact(longPort);
62 + send(portNumber, packet);
63 + } catch (ArithmeticException e) {
64 + LOG.error("Port number overflow! Cannot send packet on port {} (long), as the bmv2" +
65 + " device only accepts int port values.");
66 + }
67 + }
68 + } else {
69 + LOG.info("Instruction type not supported: {}", inst.type().name());
70 + }
71 + });
72 + }
73 +
74 + private void send(int port, OutboundPacket packet) {
75 +
76 + DeviceId deviceId = handler().data().deviceId();
77 +
78 + Bmv2Client deviceClient;
79 + try {
80 + deviceClient = Bmv2ThriftClient.of(deviceId);
81 + } catch (Bmv2RuntimeException e) {
82 + LOG.error("Failed to connect to Bmv2 device", e);
83 + return;
84 + }
85 +
86 + ImmutableByteSequence bs = ImmutableByteSequence.copyFrom(packet.data());
87 + try {
88 + deviceClient.transmitPacket(port, bs);
89 + } catch (Bmv2RuntimeException e) {
90 + LOG.info("Unable to push packet to device: deviceId={}, packet={}", deviceId, bs);
91 + }
92 + }
93 +}
1 +/*
2 + * Copyright 2016-present 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.onosproject.driver.pipeline.DefaultSingleTablePipeline;
20 +import org.onosproject.net.DeviceId;
21 +import org.onosproject.net.behaviour.NextGroup;
22 +import org.onosproject.net.behaviour.Pipeliner;
23 +import org.onosproject.net.behaviour.PipelinerContext;
24 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
25 +import org.onosproject.net.flowobjective.FilteringObjective;
26 +import org.onosproject.net.flowobjective.ForwardingObjective;
27 +import org.onosproject.net.flowobjective.NextObjective;
28 +
29 +import java.util.List;
30 +
31 +/**
32 + * Pipeliner device behaviour implementation for BMv2.
33 + */
34 +public class Bmv2Pipeliner extends AbstractHandlerBehaviour implements Pipeliner {
35 +
36 + private Pipeliner pipeliner;
37 +
38 + @Override
39 + public void init(DeviceId deviceId, PipelinerContext context) {
40 + // TODO: get multi-table pipeliner dynamically based on BMv2 device running model
41 + // Right now we only support single table pipelines
42 + pipeliner = new DefaultSingleTablePipeline();
43 + pipeliner.init(deviceId, context);
44 + }
45 +
46 + @Override
47 + public void filter(FilteringObjective filterObjective) {
48 + pipeliner.filter(filterObjective);
49 + }
50 +
51 + @Override
52 + public void forward(ForwardingObjective forwardObjective) {
53 + pipeliner.forward(forwardObjective);
54 + }
55 +
56 + @Override
57 + public void next(NextObjective nextObjective) {
58 + pipeliner.next(nextObjective);
59 + }
60 +
61 + @Override
62 + public List<String> getNextMappings(NextGroup nextGroup) {
63 + return pipeliner.getNextMappings(nextGroup);
64 + }
65 +}
...@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory; ...@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
34 import java.util.Collections; 34 import java.util.Collections;
35 import java.util.List; 35 import java.util.List;
36 36
37 -public class Bmv2PortGetterDriver extends AbstractHandlerBehaviour 37 +public class Bmv2PortDiscovery extends AbstractHandlerBehaviour
38 implements PortDiscovery { 38 implements PortDiscovery {
39 39
40 private final Logger log = 40 private final Logger log =
......
...@@ -67,7 +67,7 @@ import org.onosproject.net.flow.instructions.Instructions.ExtensionInstructionWr ...@@ -67,7 +67,7 @@ import org.onosproject.net.flow.instructions.Instructions.ExtensionInstructionWr
67 public class Bmv2DefaultFlowRuleTranslator implements Bmv2FlowRuleTranslator { 67 public class Bmv2DefaultFlowRuleTranslator implements Bmv2FlowRuleTranslator {
68 68
69 // TODO: config is harcoded now, instead it should be selected based on device model 69 // TODO: config is harcoded now, instead it should be selected based on device model
70 - private final TranslatorConfig config = new Bmv2SimplePipelineTranslatorConfig(); 70 + private final TranslatorConfig config = new Bmv2SimpleTranslatorConfig();
71 private final Bmv2Model model = config.model(); 71 private final Bmv2Model model = config.model();
72 72
73 private static Bmv2TernaryMatchParam buildTernaryParam(Bmv2ModelField field, Criterion criterion, int byteWidth) 73 private static Bmv2TernaryMatchParam buildTernaryParam(Bmv2ModelField field, Criterion criterion, int byteWidth)
......
...@@ -23,6 +23,7 @@ import com.google.common.collect.Maps; ...@@ -23,6 +23,7 @@ import com.google.common.collect.Maps;
23 import org.onlab.util.ImmutableByteSequence; 23 import org.onlab.util.ImmutableByteSequence;
24 import org.onosproject.bmv2.api.model.Bmv2Model; 24 import org.onosproject.bmv2.api.model.Bmv2Model;
25 import org.onosproject.bmv2.api.runtime.Bmv2Action; 25 import org.onosproject.bmv2.api.runtime.Bmv2Action;
26 +import org.onosproject.net.PortNumber;
26 import org.onosproject.net.flow.TrafficTreatment; 27 import org.onosproject.net.flow.TrafficTreatment;
27 import org.onosproject.net.flow.criteria.Criterion; 28 import org.onosproject.net.flow.criteria.Criterion;
28 import org.onosproject.net.flow.instructions.Instruction; 29 import org.onosproject.net.flow.instructions.Instruction;
...@@ -36,19 +37,19 @@ import java.util.Map; ...@@ -36,19 +37,19 @@ import java.util.Map;
36 37
37 /** 38 /**
38 * Implementation of a Bmv2 flow rule translator configuration for the 39 * Implementation of a Bmv2 flow rule translator configuration for the
39 - * simple_pipeline.p4 model. 40 + * simple.p4 model.
40 */ 41 */
41 @Beta 42 @Beta
42 -public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslator.TranslatorConfig { 43 +public class Bmv2SimpleTranslatorConfig implements Bmv2FlowRuleTranslator.TranslatorConfig {
43 44
44 - private static final String JSON_CONFIG_PATH = "/simple_pipeline.json"; 45 + private static final String JSON_CONFIG_PATH = "/simple.json";
45 private final Map<String, Criterion.Type> fieldMap = Maps.newHashMap(); 46 private final Map<String, Criterion.Type> fieldMap = Maps.newHashMap();
46 private final Bmv2Model model; 47 private final Bmv2Model model;
47 48
48 /** 49 /**
49 * Creates a new simple pipeline translator configuration. 50 * Creates a new simple pipeline translator configuration.
50 */ 51 */
51 - public Bmv2SimplePipelineTranslatorConfig() { 52 + public Bmv2SimpleTranslatorConfig() {
52 53
53 this.model = getModel(); 54 this.model = getModel();
54 55
...@@ -65,6 +66,12 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato ...@@ -65,6 +66,12 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato
65 .build(); 66 .build();
66 } 67 }
67 68
69 + private static Bmv2Action buildPushToCpAction() {
70 + return Bmv2Action.builder()
71 + .withName("send_to_cpu")
72 + .build();
73 + }
74 +
68 private static Bmv2Action buildFwdAction(Instructions.OutputInstruction inst) 75 private static Bmv2Action buildFwdAction(Instructions.OutputInstruction inst)
69 throws Bmv2FlowRuleTranslatorException { 76 throws Bmv2FlowRuleTranslatorException {
70 77
...@@ -73,8 +80,12 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato ...@@ -73,8 +80,12 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato
73 actionBuilder.withName("fwd"); 80 actionBuilder.withName("fwd");
74 81
75 if (inst.port().isLogical()) { 82 if (inst.port().isLogical()) {
76 - throw new Bmv2FlowRuleTranslatorException( 83 + if (inst.port() == PortNumber.CONTROLLER) {
77 - "Output logic port numbers not supported: " + inst); 84 + return buildPushToCpAction();
85 + } else {
86 + throw new Bmv2FlowRuleTranslatorException(
87 + "Output logic port number not supported: " + inst);
88 + }
78 } 89 }
79 90
80 actionBuilder.addParameter( 91 actionBuilder.addParameter(
...@@ -84,7 +95,7 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato ...@@ -84,7 +95,7 @@ public class Bmv2SimplePipelineTranslatorConfig implements Bmv2FlowRuleTranslato
84 } 95 }
85 96
86 private static Bmv2Model getModel() { 97 private static Bmv2Model getModel() {
87 - InputStream inputStream = Bmv2SimplePipelineTranslatorConfig.class 98 + InputStream inputStream = Bmv2SimpleTranslatorConfig.class
88 .getResourceAsStream(JSON_CONFIG_PATH); 99 .getResourceAsStream(JSON_CONFIG_PATH);
89 InputStreamReader reader = new InputStreamReader(inputStream); 100 InputStreamReader reader = new InputStreamReader(inputStream);
90 BufferedReader bufReader = new BufferedReader(reader); 101 BufferedReader bufReader = new BufferedReader(reader);
......
...@@ -18,8 +18,12 @@ ...@@ -18,8 +18,12 @@
18 <drivers> 18 <drivers>
19 <driver name="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="unknown"> 19 <driver name="bmv2-thrift" manufacturer="p4.org" hwVersion="bmv2" swVersion="unknown">
20 <behaviour api="org.onosproject.net.behaviour.PortDiscovery" 20 <behaviour api="org.onosproject.net.behaviour.PortDiscovery"
21 - impl="org.onosproject.drivers.bmv2.Bmv2PortGetterDriver"/> 21 + impl="org.onosproject.drivers.bmv2.Bmv2PortDiscovery"/>
22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable" 22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
23 - impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleDriver"/> 23 + impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable"/>
24 + <behaviour api="org.onosproject.net.behaviour.Pipeliner"
25 + impl="org.onosproject.drivers.bmv2.Bmv2Pipeliner"/>
26 + <behaviour api="org.onosproject.net.packet.PacketProgrammable"
27 + impl="org.onosproject.drivers.bmv2.Bmv2PacketProgrammable"/>
24 </driver> 28 </driver>
25 </drivers> 29 </drivers>
......
...@@ -83,22 +83,6 @@ ...@@ -83,22 +83,6 @@
83 ], 83 ],
84 "length_exp": null, 84 "length_exp": null,
85 "max_length": null 85 "max_length": null
86 - },
87 - {
88 - "name": "cpu_header_t",
89 - "id": 3,
90 - "fields": [
91 - [
92 - "device",
93 - 8
94 - ],
95 - [
96 - "reason",
97 - 8
98 - ]
99 - ],
100 - "length_exp": null,
101 - "max_length": null
102 } 86 }
103 ], 87 ],
104 "headers": [ 88 "headers": [
...@@ -119,12 +103,6 @@ ...@@ -119,12 +103,6 @@
119 "id": 2, 103 "id": 2,
120 "header_type": "intrinsic_metadata_t", 104 "header_type": "intrinsic_metadata_t",
121 "metadata": true 105 "metadata": true
122 - },
123 - {
124 - "name": "cpu_header",
125 - "id": 3,
126 - "header_type": "cpu_header_t",
127 - "metadata": false
128 } 106 }
129 ], 107 ],
130 "header_stacks": [], 108 "header_stacks": [],
...@@ -138,42 +116,6 @@ ...@@ -138,42 +116,6 @@
138 "name": "start", 116 "name": "start",
139 "id": 0, 117 "id": 0,
140 "parser_ops": [], 118 "parser_ops": [],
141 - "transition_key": [
142 - {
143 - "type": "lookahead",
144 - "value": [
145 - 0,
146 - 64
147 - ]
148 - }
149 - ],
150 - "transitions": [
151 - {
152 - "value": "0x0000000000000000",
153 - "mask": null,
154 - "next_state": "parse_cpu_header"
155 - },
156 - {
157 - "value": "default",
158 - "mask": null,
159 - "next_state": "parse_ethernet"
160 - }
161 - ]
162 - },
163 - {
164 - "name": "parse_cpu_header",
165 - "id": 1,
166 - "parser_ops": [
167 - {
168 - "op": "extract",
169 - "parameters": [
170 - {
171 - "type": "regular",
172 - "value": "cpu_header"
173 - }
174 - ]
175 - }
176 - ],
177 "transition_key": [], 119 "transition_key": [],
178 "transitions": [ 120 "transitions": [
179 { 121 {
...@@ -185,7 +127,7 @@ ...@@ -185,7 +127,7 @@
185 }, 127 },
186 { 128 {
187 "name": "parse_ethernet", 129 "name": "parse_ethernet",
188 - "id": 2, 130 + "id": 1,
189 "parser_ops": [ 131 "parser_ops": [
190 { 132 {
191 "op": "extract", 133 "op": "extract",
...@@ -214,7 +156,6 @@ ...@@ -214,7 +156,6 @@
214 "name": "deparser", 156 "name": "deparser",
215 "id": 0, 157 "id": 0,
216 "order": [ 158 "order": [
217 - "cpu_header",
218 "ethernet" 159 "ethernet"
219 ] 160 ]
220 } 161 }
...@@ -301,59 +242,9 @@ ...@@ -301,59 +242,9 @@
301 { 242 {
302 "name": "send_to_cpu", 243 "name": "send_to_cpu",
303 "id": 3, 244 "id": 3,
304 - "runtime_data": [ 245 + "runtime_data": [],
305 - {
306 - "name": "device",
307 - "bitwidth": 8
308 - },
309 - {
310 - "name": "reason",
311 - "bitwidth": 8
312 - }
313 - ],
314 "primitives": [ 246 "primitives": [
315 { 247 {
316 - "op": "add_header",
317 - "parameters": [
318 - {
319 - "type": "header",
320 - "value": "cpu_header"
321 - }
322 - ]
323 - },
324 - {
325 - "op": "modify_field",
326 - "parameters": [
327 - {
328 - "type": "field",
329 - "value": [
330 - "cpu_header",
331 - "device"
332 - ]
333 - },
334 - {
335 - "type": "runtime_data",
336 - "value": 0
337 - }
338 - ]
339 - },
340 - {
341 - "op": "modify_field",
342 - "parameters": [
343 - {
344 - "type": "field",
345 - "value": [
346 - "cpu_header",
347 - "reason"
348 - ]
349 - },
350 - {
351 - "type": "runtime_data",
352 - "value": 1
353 - }
354 - ]
355 - },
356 - {
357 "op": "modify_field", 248 "op": "modify_field",
358 "parameters": [ 249 "parameters": [
359 { 250 {
...@@ -365,7 +256,7 @@ ...@@ -365,7 +256,7 @@
365 }, 256 },
366 { 257 {
367 "type": "hexstr", 258 "type": "hexstr",
368 - "value": "0xfa" 259 + "value": "0xff"
369 } 260 }
370 ] 261 ]
371 } 262 }
...@@ -433,7 +324,8 @@ ...@@ -433,7 +324,8 @@
433 "send_to_cpu": null, 324 "send_to_cpu": null,
434 "_drop": null 325 "_drop": null
435 }, 326 },
436 - "default_action": null 327 + "default_action": null,
328 + "base_default_next": null
437 } 329 }
438 ], 330 ],
439 "conditionals": [] 331 "conditionals": []
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 <feature>onos-drivers-bmv2</feature> 20 <feature>onos-drivers-bmv2</feature>
21 <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle> 21 <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
22 <bundle>mvn:${project.groupId}/onos-bmv2-provider-device/${project.version}</bundle> 22 <bundle>mvn:${project.groupId}/onos-bmv2-provider-device/${project.version}</bundle>
23 - <bundle>mvn:org.apache.thrift/libthrift/0.9.2</bundle> 23 + <bundle>mvn:org.apache.thrift/libthrift/0.9.3</bundle>
24 <bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle> 24 <bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle>
25 </feature> 25 </feature>
26 </features> 26 </features>
......