Carmelo Cascone
Committed by Brian O'Connor

Various changes in BMv2 driver and provider modules

Driver notable changes:
- Implemented new behaviors, removed deprecated ones
- Removed flow rule translator classes (now under protocol module)
- Improved FlowRuleProgrammable: now it uses BMv2TableEntryService
	to lookup/bind flow rules with BMv2 table entries, retrieves flow
	statistics, better exception handling when adding/replacing/removing
	table entries.
- Improved PacketProgrammable: better exception handling and logging

Provider notable changes:
- Bmv2DeviceProvider: detects and notifies device configuration
	changes and reboots to Bmv2DeviceContextService, added support for
	periodic polling of port statistics
- Bmv2PacketProvider: implemented workaround for OutboundPackets with
	flood treatment

Change-Id: I79b756b533d4afb6b70025a137b2e811fd42a4e8
Showing 31 changed files with 418 additions and 595 deletions
...@@ -20,6 +20,6 @@ ...@@ -20,6 +20,6 @@
20 <feature name="${project.artifactId}" version="${project.version}" 20 <feature name="${project.artifactId}" version="${project.version}"
21 description="${project.description}"> 21 description="${project.description}">
22 <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle> 22 <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
23 - <bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle> 23 + <bundle>mvn:${project.groupId}/onos-bmv2-protocol-api/${project.version}</bundle>
24 </feature> 24 </feature>
25 </features> 25 </features>
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-drivers-general</artifactId> 22 <artifactId>onos-drivers-general</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
...@@ -36,7 +37,7 @@ ...@@ -36,7 +37,7 @@
36 <onos.app.name>org.onosproject.drivers.bmv2</onos.app.name> 37 <onos.app.name>org.onosproject.drivers.bmv2</onos.app.name>
37 <onos.app.origin>ON.Lab</onos.app.origin> 38 <onos.app.origin>ON.Lab</onos.app.origin>
38 <onos.app.category>Drivers</onos.app.category> 39 <onos.app.category>Drivers</onos.app.category>
39 - <onos.app.title>BMv2 Device Drivers</onos.app.title> 40 + <onos.app.title>BMv2 Drivers</onos.app.title>
40 <onos.app.url>http://onosproject.org</onos.app.url> 41 <onos.app.url>http://onosproject.org</onos.app.url>
41 <onos.app.requires> 42 <onos.app.requires>
42 org.onosproject.bmv2 43 org.onosproject.bmv2
...@@ -46,7 +47,7 @@ ...@@ -46,7 +47,7 @@
46 <dependencies> 47 <dependencies>
47 <dependency> 48 <dependency>
48 <groupId>org.onosproject</groupId> 49 <groupId>org.onosproject</groupId>
49 - <artifactId>onos-bmv2-protocol</artifactId> 50 + <artifactId>onos-bmv2-protocol-api</artifactId>
50 <version>${project.version}</version> 51 <version>${project.version}</version>
51 </dependency> 52 </dependency>
52 <dependency> 53 <dependency>
......
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 com.google.common.collect.ImmutableList;
20 +import com.google.common.collect.Lists;
21 +import org.onlab.packet.ChassisId;
22 +import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent;
23 +import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
24 +import org.onosproject.bmv2.api.service.Bmv2Controller;
25 +import org.onosproject.net.AnnotationKeys;
26 +import org.onosproject.net.DefaultAnnotations;
27 +import org.onosproject.net.DeviceId;
28 +import org.onosproject.net.PortNumber;
29 +import org.onosproject.net.device.DefaultDeviceDescription;
30 +import org.onosproject.net.device.DefaultPortDescription;
31 +import org.onosproject.net.device.DeviceDescription;
32 +import org.onosproject.net.device.DeviceDescriptionDiscovery;
33 +import org.onosproject.net.device.PortDescription;
34 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
35 +import org.slf4j.Logger;
36 +import org.slf4j.LoggerFactory;
37 +
38 +import java.math.BigInteger;
39 +import java.util.List;
40 +
41 +import static org.onosproject.bmv2.api.runtime.Bmv2Device.*;
42 +import static org.onosproject.net.Device.Type.SWITCH;
43 +
44 +/**
45 + * Implementation of the device description discovery behaviour for BMv2.
46 + */
47 +public class Bmv2DeviceDescriptionDiscovery extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery {
48 +
49 + private static final String JSON_CONFIG_MD5 = "bmv2JsonConfigMd5";
50 + private static final String PROCESS_INSTANCE_ID = "bmv2ProcessInstanceId";
51 +
52 + private final Logger log = LoggerFactory.getLogger(this.getClass());
53 +
54 + private Bmv2Controller controller;
55 +
56 + private boolean init() {
57 + controller = handler().get(Bmv2Controller.class);
58 + if (controller == null) {
59 + log.warn("Failed to get a BMv2 controller");
60 + return false;
61 + }
62 + return true;
63 + }
64 +
65 + @Override
66 + public DeviceDescription discoverDeviceDetails() {
67 +
68 + if (!init()) {
69 + return null;
70 + }
71 +
72 + DeviceId deviceId = handler().data().deviceId();
73 +
74 + Bmv2DeviceAgent deviceAgent;
75 + try {
76 + deviceAgent = controller.getAgent(deviceId);
77 + } catch (Bmv2RuntimeException e) {
78 + log.error("Failed to connect to Bmv2 device", e);
79 + return null;
80 + }
81 +
82 + DefaultAnnotations.Builder annotationsBuilder = DefaultAnnotations.builder();
83 +
84 + try {
85 + String md5 = deviceAgent.getJsonConfigMd5();
86 + BigInteger i = new BigInteger(1, md5.getBytes());
87 + annotationsBuilder.set(JSON_CONFIG_MD5, String.format("%1$032X", i).toLowerCase());
88 + } catch (Bmv2RuntimeException e) {
89 + log.warn("Unable to dump JSON configuration from {}: {}", deviceId, e.explain());
90 + }
91 + try {
92 + int instanceId = deviceAgent.getProcessInstanceId();
93 + annotationsBuilder.set(PROCESS_INSTANCE_ID, String.valueOf(instanceId));
94 + } catch (Bmv2RuntimeException e) {
95 + log.warn("Unable to get process instance ID from {}: {}", deviceId, e.explain());
96 + }
97 +
98 + annotationsBuilder.set(AnnotationKeys.PROTOCOL, PROTOCOL);
99 +
100 + return new DefaultDeviceDescription(deviceId.uri(),
101 + SWITCH,
102 + MANUFACTURER,
103 + HW_VERSION,
104 + SW_VERSION,
105 + SERIAL_NUMBER,
106 + new ChassisId(),
107 + annotationsBuilder.build());
108 + }
109 +
110 + @Override
111 + public List<PortDescription> discoverPortDetails() {
112 +
113 + if (!init()) {
114 + return null;
115 + }
116 +
117 + DeviceId deviceId = handler().data().deviceId();
118 +
119 + Bmv2DeviceAgent deviceAgent;
120 + try {
121 + deviceAgent = controller.getAgent(deviceId);
122 + } catch (Bmv2RuntimeException e) {
123 + log.error("Failed to connect to Bmv2 device", e);
124 + return null;
125 + }
126 +
127 + List<PortDescription> portDescriptions = Lists.newArrayList();
128 +
129 + try {
130 + deviceAgent.getPortsInfo().forEach(p -> {
131 + PortNumber portNumber = PortNumber.portNumber((long) p.number(), p.ifaceName());
132 + portDescriptions.add(new DefaultPortDescription(portNumber, p.isUp(), DefaultAnnotations.EMPTY));
133 + });
134 + } catch (Bmv2RuntimeException e) {
135 + log.error("Unable to get port descriptions of {}: {}", deviceId, e);
136 + }
137 +
138 + return ImmutableList.copyOf(portDescriptions);
139 + }
140 +}
...@@ -20,7 +20,7 @@ import org.apache.felix.scr.annotations.Component; ...@@ -20,7 +20,7 @@ import org.apache.felix.scr.annotations.Component;
20 import org.onosproject.net.driver.AbstractDriverLoader; 20 import org.onosproject.net.driver.AbstractDriverLoader;
21 21
22 /** 22 /**
23 - * Loader for barefoot drivers from specific xml. 23 + * Loader for BMv2 drivers from xml file.
24 */ 24 */
25 @Component(immediate = true) 25 @Component(immediate = true)
26 public class Bmv2DriversLoader extends AbstractDriverLoader { 26 public class Bmv2DriversLoader extends AbstractDriverLoader {
......
...@@ -14,7 +14,29 @@ ...@@ -14,7 +14,29 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 +package org.onosproject.drivers.bmv2;
18 +
19 +import org.onosproject.bmv2.api.runtime.Bmv2ExtensionSelector;
20 +import org.onosproject.net.behaviour.ExtensionSelectorResolver;
21 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
22 +import org.onosproject.net.flow.criteria.ExtensionSelector;
23 +import org.onosproject.net.flow.criteria.ExtensionSelectorType;
24 +
25 +import java.util.Collections;
26 +
27 +import static org.onosproject.net.flow.criteria.ExtensionSelectorType.ExtensionSelectorTypes.BMV2_MATCH_PARAMS;
28 +
17 /** 29 /**
18 - * Translators of ONOS abstractions to BMv2 model-dependent abstractions. 30 + * Implementation of the extension selector resolver behaviour for BMv2.
19 */ 31 */
20 -package org.onosproject.drivers.bmv2.translators;
...\ No newline at end of file ...\ No newline at end of file
32 +public class Bmv2ExtensionSelectorResolver extends AbstractHandlerBehaviour implements ExtensionSelectorResolver {
33 +
34 + @Override
35 + public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
36 + if (type.equals(BMV2_MATCH_PARAMS.type())) {
37 + return new Bmv2ExtensionSelector(Collections.emptyMap());
38 + }
39 +
40 + return null;
41 + }
42 +}
......
...@@ -14,14 +14,26 @@ ...@@ -14,14 +14,26 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
17 -package org.onosproject.drivers.bmv2.translators; 17 +package org.onosproject.drivers.bmv2;
18 +
19 +import org.onosproject.bmv2.api.runtime.Bmv2ExtensionTreatment;
20 +import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
21 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
22 +import org.onosproject.net.flow.instructions.ExtensionTreatment;
23 +import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
24 +
25 +import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.BMV2_ACTION;
18 26
19 /** 27 /**
20 - * BMv2 flow rule translator exception. 28 + * Implementation of the extension treatment resolver behavior for BMv2.
21 */ 29 */
22 -public class Bmv2FlowRuleTranslatorException extends Exception { 30 +public class Bmv2ExtensionTreatmentResolver extends AbstractHandlerBehaviour implements ExtensionTreatmentResolver {
23 31
24 - Bmv2FlowRuleTranslatorException(String msg) { 32 + @Override
25 - super(msg); 33 + public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) {
34 + if (type.equals(BMV2_ACTION.type())) {
35 + return new Bmv2ExtensionTreatment(null);
36 + }
37 + return null;
26 } 38 }
27 } 39 }
......
...@@ -17,56 +17,59 @@ ...@@ -17,56 +17,59 @@
17 package org.onosproject.drivers.bmv2; 17 package org.onosproject.drivers.bmv2;
18 18
19 import org.onlab.util.ImmutableByteSequence; 19 import org.onlab.util.ImmutableByteSequence;
20 -import org.onosproject.bmv2.api.runtime.Bmv2Client; 20 +import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent;
21 import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException; 21 import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
22 -import org.onosproject.bmv2.ctl.Bmv2ThriftClient; 22 +import org.onosproject.bmv2.api.service.Bmv2Controller;
23 import org.onosproject.net.DeviceId; 23 import org.onosproject.net.DeviceId;
24 import org.onosproject.net.driver.AbstractHandlerBehaviour; 24 import org.onosproject.net.driver.AbstractHandlerBehaviour;
25 import org.onosproject.net.flow.TrafficTreatment; 25 import org.onosproject.net.flow.TrafficTreatment;
26 -import org.onosproject.net.flow.instructions.Instructions;
27 import org.onosproject.net.packet.OutboundPacket; 26 import org.onosproject.net.packet.OutboundPacket;
28 import org.onosproject.net.packet.PacketProgrammable; 27 import org.onosproject.net.packet.PacketProgrammable;
29 import org.slf4j.Logger; 28 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory; 29 import org.slf4j.LoggerFactory;
31 30
31 +import java.util.List;
32 +
32 import static java.lang.Math.toIntExact; 33 import static java.lang.Math.toIntExact;
33 -import static org.onosproject.net.PortNumber.FLOOD; 34 +import static java.util.stream.Collectors.toList;
34 import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT; 35 import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
36 +import static org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
35 37
36 /** 38 /**
37 - * Packet programmable device behaviour implementation for BMv2. 39 + * Implementation of the packet programmable behaviour for BMv2.
38 */ 40 */
39 public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable { 41 public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable {
40 42
41 - private static final Logger LOG = 43 + private final Logger log = LoggerFactory.getLogger(this.getClass());
42 - LoggerFactory.getLogger(Bmv2PacketProgrammable.class);
43 44
44 @Override 45 @Override
45 public void emit(OutboundPacket packet) { 46 public void emit(OutboundPacket packet) {
46 47
47 TrafficTreatment treatment = packet.treatment(); 48 TrafficTreatment treatment = packet.treatment();
48 49
49 - treatment.allInstructions().forEach(inst -> { 50 + // BMv2 supports only OUTPUT instructions.
50 - if (inst.type().equals(OUTPUT)) { 51 + List<OutputInstruction> outInstructions = treatment.allInstructions()
51 - Instructions.OutputInstruction outInst = (Instructions.OutputInstruction) inst; 52 + .stream()
52 - if (outInst.port().isLogical()) { 53 + .filter(i -> i.type().equals(OUTPUT))
53 - if (outInst.port() == FLOOD) { 54 + .map(i -> (OutputInstruction) i)
54 - // TODO: implement flood 55 + .collect(toList());
55 - LOG.info("Flood not implemented", outInst); 56 +
56 - } 57 + if (treatment.allInstructions().size() != outInstructions.size()) {
57 - LOG.info("Output on logical port not supported: {}", outInst); 58 + // There are other instructions that are not of type OUTPUT
58 - } else { 59 + log.warn("Dropping emit request, treatment nor supported: {}", treatment);
59 - try { 60 + return;
60 - long longPort = outInst.port().toLong(); 61 + }
61 - int portNumber = toIntExact(longPort); 62 +
62 - send(portNumber, packet); 63 + outInstructions.forEach(outInst -> {
63 - } catch (ArithmeticException e) { 64 + if (outInst.port().isLogical()) {
64 - LOG.error("Port number overflow! Cannot send packet on port {} (long), as the bmv2" + 65 + log.warn("Dropping emit request, logical port not supported: {}", outInst.port());
65 - " device only accepts int port values.");
66 - }
67 - }
68 } else { 66 } else {
69 - LOG.info("Instruction type not supported: {}", inst.type().name()); 67 + try {
68 + int portNumber = toIntExact(outInst.port().toLong());
69 + send(portNumber, packet);
70 + } catch (ArithmeticException e) {
71 + log.error("Dropping emit request, port number too big: {}", outInst.port().toLong());
72 + }
70 } 73 }
71 }); 74 });
72 } 75 }
...@@ -75,19 +78,25 @@ public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements ...@@ -75,19 +78,25 @@ public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements
75 78
76 DeviceId deviceId = handler().data().deviceId(); 79 DeviceId deviceId = handler().data().deviceId();
77 80
78 - Bmv2Client deviceClient; 81 + Bmv2Controller controller = handler().get(Bmv2Controller.class);
82 + if (controller == null) {
83 + log.error("Failed to get BMv2 controller");
84 + return;
85 + }
86 +
87 + Bmv2DeviceAgent deviceAgent;
79 try { 88 try {
80 - deviceClient = Bmv2ThriftClient.of(deviceId); 89 + deviceAgent = controller.getAgent(deviceId);
81 } catch (Bmv2RuntimeException e) { 90 } catch (Bmv2RuntimeException e) {
82 - LOG.error("Failed to connect to Bmv2 device", e); 91 + log.error("Failed to get Bmv2 device agent for {}: {}", deviceId, e.explain());
83 return; 92 return;
84 } 93 }
85 94
86 ImmutableByteSequence bs = ImmutableByteSequence.copyFrom(packet.data()); 95 ImmutableByteSequence bs = ImmutableByteSequence.copyFrom(packet.data());
87 try { 96 try {
88 - deviceClient.transmitPacket(port, bs); 97 + deviceAgent.transmitPacket(port, bs);
89 } catch (Bmv2RuntimeException e) { 98 } catch (Bmv2RuntimeException e) {
90 - LOG.info("Unable to push packet to device: deviceId={}, packet={}", deviceId, bs); 99 + log.warn("Unable to emit packet trough {}: {}", deviceId, e.explain());
91 } 100 }
92 } 101 }
93 } 102 }
......
...@@ -37,8 +37,8 @@ public class Bmv2Pipeliner extends AbstractHandlerBehaviour implements Pipeliner ...@@ -37,8 +37,8 @@ public class Bmv2Pipeliner extends AbstractHandlerBehaviour implements Pipeliner
37 37
38 @Override 38 @Override
39 public void init(DeviceId deviceId, PipelinerContext context) { 39 public void init(DeviceId deviceId, PipelinerContext context) {
40 - // TODO: get multi-table pipeliner dynamically based on BMv2 device running model 40 + // TODO: get multi-table pipeliner dynamically based on BMv2 device running model (hard).
41 - // Right now we only support single table pipelines 41 + // Right now we are able to map flow objectives only in the first table of the pipeline.
42 pipeliner = new DefaultSingleTablePipeline(); 42 pipeliner = new DefaultSingleTablePipeline();
43 pipeliner.init(deviceId, context); 43 pipeliner.init(deviceId, context);
44 } 44 }
......
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.runtime.Bmv2Client;
22 -import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
23 -import org.onosproject.bmv2.ctl.Bmv2ThriftClient;
24 -import org.onosproject.net.DefaultAnnotations;
25 -import org.onosproject.net.PortNumber;
26 -import org.onosproject.net.SparseAnnotations;
27 -import org.onosproject.net.behaviour.PortDiscovery;
28 -import org.onosproject.net.device.DefaultPortDescription;
29 -import org.onosproject.net.device.PortDescription;
30 -import org.onosproject.net.driver.AbstractHandlerBehaviour;
31 -import org.slf4j.Logger;
32 -import org.slf4j.LoggerFactory;
33 -
34 -import java.util.Collections;
35 -import java.util.List;
36 -
37 -public class Bmv2PortDiscovery extends AbstractHandlerBehaviour
38 - implements PortDiscovery {
39 -
40 - private final Logger log =
41 - LoggerFactory.getLogger(this.getClass());
42 -
43 - @Override
44 - public List<PortDescription> getPorts() {
45 - Bmv2Client deviceClient;
46 - try {
47 - deviceClient = Bmv2ThriftClient.of(handler().data().deviceId());
48 - } catch (Bmv2RuntimeException e) {
49 - log.error("Failed to connect to Bmv2 device", e);
50 - return Collections.emptyList();
51 - }
52 -
53 - List<PortDescription> portDescriptions = Lists.newArrayList();
54 -
55 - try {
56 -
57 - deviceClient.getPortsInfo().forEach(
58 - p -> {
59 - DefaultAnnotations.Builder builder =
60 - DefaultAnnotations.builder();
61 - p.getExtraProperties().forEach(builder::set);
62 - SparseAnnotations annotations = builder.build();
63 -
64 - portDescriptions.add(new DefaultPortDescription(
65 - PortNumber.portNumber(
66 - (long) p.portNumber(),
67 - p.ifaceName()),
68 - p.isUp(),
69 - annotations
70 - ));
71 - });
72 - } catch (Bmv2RuntimeException e) {
73 - log.error("Unable to get port description from Bmv2 device", e);
74 - }
75 -
76 - return ImmutableList.copyOf(portDescriptions);
77 - }
78 -}
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.translators;
18 -
19 -import com.google.common.annotations.Beta;
20 -import org.onosproject.bmv2.api.model.Bmv2Model;
21 -import org.onosproject.net.flow.criteria.Criterion;
22 -
23 -import java.util.Map;
24 -
25 -import static org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslator.TranslatorConfig;
26 -
27 -/**
28 - * Default implementation of a BMv2 flow rule translator configuration.
29 - */
30 -@Beta
31 -public abstract class Bmv2DefaultTranslatorConfig implements TranslatorConfig {
32 -
33 - private final Bmv2Model model;
34 - private final Map<String, Criterion.Type> fieldMap;
35 -
36 - /**
37 - * Creates a new translator configuration.
38 - *
39 - * @param model a BMv2 packet processing model
40 - * @param fieldMap a field-to-criterion type map
41 - */
42 - protected Bmv2DefaultTranslatorConfig(Bmv2Model model, Map<String, Criterion.Type> fieldMap) {
43 - this.model = model;
44 - this.fieldMap = fieldMap;
45 - }
46 -
47 - @Override
48 - public Bmv2Model model() {
49 - return this.model;
50 - }
51 -
52 - @Override
53 - public Map<String, Criterion.Type> fieldToCriterionTypeMap() {
54 - return this.fieldMap;
55 - }
56 -}
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.translators;
18 -
19 -import com.google.common.annotations.Beta;
20 -import org.onosproject.bmv2.api.model.Bmv2Model;
21 -import org.onosproject.bmv2.api.runtime.Bmv2Action;
22 -import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
23 -import org.onosproject.net.flow.FlowRule;
24 -import org.onosproject.net.flow.TrafficTreatment;
25 -import org.onosproject.net.flow.criteria.Criterion;
26 -
27 -import java.util.Map;
28 -
29 -/**
30 - * Translator of ONOS flow rules to BMv2 table entries. Translation depends on a
31 - * {@link TranslatorConfig translator configuration}.
32 - */
33 -@Beta
34 -public interface Bmv2FlowRuleTranslator {
35 -
36 - /**
37 - * Returns a new BMv2 table entry equivalent to the given flow rule.
38 - *
39 - * @param rule a flow rule
40 - * @return a BMv2 table entry
41 - * @throws Bmv2FlowRuleTranslatorException if the flow rule cannot be
42 - * translated
43 - */
44 - Bmv2TableEntry translate(FlowRule rule) throws Bmv2FlowRuleTranslatorException;
45 -
46 - /**
47 - * Returns the configuration of this translator.
48 - *
49 - * @return a translator configuration
50 - */
51 - TranslatorConfig config();
52 -
53 - /**
54 - * BMv2 flow rules translator configuration. Such a configuration is used to
55 - * generate table entries that are compatible with a given {@link Bmv2Model}.
56 - */
57 - @Beta
58 - interface TranslatorConfig {
59 - /**
60 - * Return the {@link Bmv2Model} associated with this configuration.
61 - *
62 - * @return a BMv2 model
63 - */
64 - Bmv2Model model();
65 -
66 - /**
67 - * Returns a map describing a one-to-one relationship between BMv2
68 - * header field names and ONOS criterion types. Header field names are
69 - * formatted using the notation {@code header_name.field_name}
70 - * representing a specific header field instance extracted by the BMv2
71 - * parser (e.g. {@code ethernet.dstAddr}).
72 - *
73 - * @return a map where the keys represent BMv2 header field names and
74 - * values are criterion types
75 - */
76 - Map<String, Criterion.Type> fieldToCriterionTypeMap();
77 -
78 - /**
79 - * Return a BMv2 action that is equivalent to the given ONOS traffic
80 - * treatment.
81 - *
82 - * @param treatment a traffic treatment
83 - * @return a BMv2 action object
84 - * @throws Bmv2FlowRuleTranslatorException if the treatment cannot be
85 - * translated to a BMv2 action
86 - */
87 - Bmv2Action buildAction(TrafficTreatment treatment)
88 - throws Bmv2FlowRuleTranslatorException;
89 - }
90 -}
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.translators;
18 -
19 -import com.google.common.annotations.Beta;
20 -import com.google.common.collect.ImmutableMap;
21 -import org.onlab.util.ImmutableByteSequence;
22 -import org.onosproject.bmv2.api.model.Bmv2Model;
23 -import org.onosproject.bmv2.api.runtime.Bmv2Action;
24 -import org.onosproject.net.PortNumber;
25 -import org.onosproject.net.flow.TrafficTreatment;
26 -import org.onosproject.net.flow.criteria.Criterion;
27 -import org.onosproject.net.flow.instructions.Instruction;
28 -import org.onosproject.net.flow.instructions.Instructions;
29 -
30 -import java.util.Map;
31 -
32 -/**
33 - * Implementation of a Bmv2 flow rule translator configuration for the
34 - * simple.p4 model.
35 - */
36 -@Beta
37 -public class Bmv2SimpleTranslatorConfig extends Bmv2DefaultTranslatorConfig {
38 -
39 - // Lazily populate field map.
40 - private static final Map<String, Criterion.Type> FIELD_MAP = ImmutableMap.of(
41 - "standard_metadata.ingress_port", Criterion.Type.IN_PORT,
42 - "ethernet.dstAddr", Criterion.Type.ETH_DST,
43 - "ethernet.srcAddr", Criterion.Type.ETH_SRC,
44 - "ethernet.etherType", Criterion.Type.ETH_TYPE);
45 -
46 - /**
47 - * Creates a new simple pipeline translator configuration.
48 - */
49 - public Bmv2SimpleTranslatorConfig(Bmv2Model model) {
50 - // Populate fieldMap.
51 - super(model, FIELD_MAP);
52 - }
53 -
54 - private static Bmv2Action buildDropAction() {
55 - return Bmv2Action.builder()
56 - .withName("_drop")
57 - .build();
58 - }
59 -
60 - private static Bmv2Action buildPushToCpAction() {
61 - return Bmv2Action.builder()
62 - .withName("send_to_cpu")
63 - .build();
64 - }
65 -
66 - private static Bmv2Action buildFwdAction(Instructions.OutputInstruction inst)
67 - throws Bmv2FlowRuleTranslatorException {
68 -
69 - Bmv2Action.Builder actionBuilder = Bmv2Action.builder();
70 -
71 - actionBuilder.withName("fwd");
72 -
73 - if (inst.port().isLogical()) {
74 - if (inst.port() == PortNumber.CONTROLLER) {
75 - return buildPushToCpAction();
76 - } else {
77 - throw new Bmv2FlowRuleTranslatorException(
78 - "Output logic port number not supported: " + inst);
79 - }
80 - }
81 -
82 - actionBuilder.addParameter(
83 - ImmutableByteSequence.copyFrom((short) inst.port().toLong()));
84 -
85 - return actionBuilder.build();
86 - }
87 -
88 - @Override
89 - public Bmv2Action buildAction(TrafficTreatment treatment)
90 - throws Bmv2FlowRuleTranslatorException {
91 -
92 -
93 - if (treatment.allInstructions().size() == 0) {
94 - // No instructions means drop.
95 - return buildDropAction();
96 - } else if (treatment.allInstructions().size() > 1) {
97 - // Otherwise, we understand treatments with only 1 instruction.
98 - throw new Bmv2FlowRuleTranslatorException(
99 - "Treatment not supported, more than 1 instructions found: "
100 - + treatment.toString());
101 - }
102 -
103 - Instruction instruction = treatment.allInstructions().get(0);
104 -
105 - switch (instruction.type()) {
106 - case OUTPUT:
107 - return buildFwdAction((Instructions.OutputInstruction) instruction);
108 - case NOACTION:
109 - return buildDropAction();
110 - default:
111 - throw new Bmv2FlowRuleTranslatorException(
112 - "Instruction type not supported: "
113 - + instruction.type().name());
114 - }
115 - }
116 -}
...@@ -16,14 +16,18 @@ ...@@ -16,14 +16,18 @@
16 ~ limitations under the License. 16 ~ limitations under the License.
17 --> 17 -->
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="n/a">
20 - <behaviour api="org.onosproject.net.behaviour.PortDiscovery" 20 + <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
21 - impl="org.onosproject.drivers.bmv2.Bmv2PortDiscovery"/> 21 + impl="org.onosproject.drivers.bmv2.Bmv2DeviceDescriptionDiscovery"/>
22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable" 22 <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
23 impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable"/> 23 impl="org.onosproject.drivers.bmv2.Bmv2FlowRuleProgrammable"/>
24 <behaviour api="org.onosproject.net.behaviour.Pipeliner" 24 <behaviour api="org.onosproject.net.behaviour.Pipeliner"
25 impl="org.onosproject.drivers.bmv2.Bmv2Pipeliner"/> 25 impl="org.onosproject.drivers.bmv2.Bmv2Pipeliner"/>
26 <behaviour api="org.onosproject.net.packet.PacketProgrammable" 26 <behaviour api="org.onosproject.net.packet.PacketProgrammable"
27 impl="org.onosproject.drivers.bmv2.Bmv2PacketProgrammable"/> 27 impl="org.onosproject.drivers.bmv2.Bmv2PacketProgrammable"/>
28 + <behaviour api="org.onosproject.net.behaviour.ExtensionSelectorResolver"
29 + impl="org.onosproject.drivers.bmv2.Bmv2ExtensionSelectorResolver"/>
30 + <behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
31 + impl="org.onosproject.drivers.bmv2.Bmv2ExtensionTreatmentResolver"/>
28 </driver> 32 </driver>
29 </drivers> 33 </drivers>
......
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.eclipsesource.json.Json;
20 -import com.eclipsesource.json.JsonObject;
21 -import com.google.common.testing.EqualsTester;
22 -import org.junit.Before;
23 -import org.junit.Test;
24 -import org.onlab.packet.MacAddress;
25 -import org.onosproject.bmv2.api.model.Bmv2Model;
26 -import org.onosproject.bmv2.api.runtime.Bmv2TableEntry;
27 -import org.onosproject.bmv2.api.runtime.Bmv2TernaryMatchParam;
28 -import org.onosproject.core.ApplicationId;
29 -import org.onosproject.core.DefaultApplicationId;
30 -import org.onosproject.drivers.bmv2.translators.Bmv2DefaultFlowRuleTranslator;
31 -import org.onosproject.drivers.bmv2.translators.Bmv2FlowRuleTranslator;
32 -import org.onosproject.drivers.bmv2.translators.Bmv2SimpleTranslatorConfig;
33 -import org.onosproject.net.DeviceId;
34 -import org.onosproject.net.PortNumber;
35 -import org.onosproject.net.flow.DefaultFlowRule;
36 -import org.onosproject.net.flow.DefaultTrafficSelector;
37 -import org.onosproject.net.flow.DefaultTrafficTreatment;
38 -import org.onosproject.net.flow.FlowRule;
39 -import org.onosproject.net.flow.TrafficSelector;
40 -import org.onosproject.net.flow.TrafficTreatment;
41 -
42 -import java.io.BufferedReader;
43 -import java.io.IOException;
44 -import java.io.InputStream;
45 -import java.io.InputStreamReader;
46 -import java.util.Random;
47 -
48 -import static org.hamcrest.CoreMatchers.equalTo;
49 -import static org.hamcrest.CoreMatchers.is;
50 -import static org.hamcrest.MatcherAssert.assertThat;
51 -
52 -/**
53 - * Tests for {@link Bmv2DefaultFlowRuleTranslator}.
54 - */
55 -public class Bmv2DefaultFlowRuleTranslatorTest {
56 -
57 - private static final String JSON_CONFIG_PATH = "/simple.json";
58 - private Random random = new Random();
59 - private Bmv2Model model;
60 - private Bmv2FlowRuleTranslator.TranslatorConfig config;
61 - private Bmv2FlowRuleTranslator translator;
62 -
63 - @Before
64 - public void setUp() throws Exception {
65 - InputStream inputStream = Bmv2SimpleTranslatorConfig.class
66 - .getResourceAsStream(JSON_CONFIG_PATH);
67 - InputStreamReader reader = new InputStreamReader(inputStream);
68 - BufferedReader bufReader = new BufferedReader(reader);
69 - JsonObject json = null;
70 - try {
71 - json = Json.parse(bufReader).asObject();
72 - } catch (IOException e) {
73 - throw new RuntimeException("Unable to parse JSON file: " + e.getMessage());
74 - }
75 -
76 - this.model = Bmv2Model.parse(json);
77 - this.config = new Bmv2SimpleTranslatorConfig(model);
78 - this.translator = new Bmv2DefaultFlowRuleTranslator(config);
79 -
80 - }
81 -
82 -
83 - @Test
84 - public void testCompiler() throws Exception {
85 -
86 - DeviceId deviceId = DeviceId.NONE;
87 - ApplicationId appId = new DefaultApplicationId(1, "test");
88 - int tableId = 0;
89 - MacAddress ethDstMac = MacAddress.valueOf(random.nextLong());
90 - MacAddress ethSrcMac = MacAddress.valueOf(random.nextLong());
91 - short ethType = (short) (0x0000FFFF & random.nextInt());
92 - short outPort = (short) random.nextInt(65);
93 - short inPort = (short) random.nextInt(65);
94 - int timeout = random.nextInt(100);
95 - int priority = random.nextInt(100);
96 -
97 - TrafficSelector matchInPort1 = DefaultTrafficSelector
98 - .builder()
99 - .matchInPort(PortNumber.portNumber(inPort))
100 - .matchEthDst(ethDstMac)
101 - .matchEthSrc(ethSrcMac)
102 - .matchEthType(ethType)
103 - .build();
104 -
105 - TrafficTreatment outPort2 = DefaultTrafficTreatment
106 - .builder()
107 - .setOutput(PortNumber.portNumber(outPort))
108 - .build();
109 -
110 - FlowRule rule1 = DefaultFlowRule.builder()
111 - .forDevice(deviceId)
112 - .forTable(tableId)
113 - .fromApp(appId)
114 - .withSelector(matchInPort1)
115 - .withTreatment(outPort2)
116 - .makeTemporary(timeout)
117 - .withPriority(priority)
118 - .build();
119 -
120 - FlowRule rule2 = DefaultFlowRule.builder()
121 - .forDevice(deviceId)
122 - .forTable(tableId)
123 - .fromApp(appId)
124 - .withSelector(matchInPort1)
125 - .withTreatment(outPort2)
126 - .makeTemporary(timeout)
127 - .withPriority(priority)
128 - .build();
129 -
130 - Bmv2TableEntry entry1 = translator.translate(rule1);
131 - Bmv2TableEntry entry2 = translator.translate(rule1);
132 -
133 - // check equality, i.e. same rules must produce same entries
134 - new EqualsTester()
135 - .addEqualityGroup(rule1, rule2)
136 - .addEqualityGroup(entry1, entry2)
137 - .testEquals();
138 -
139 - int numMatchParams = model.table(0).keys().size();
140 - // parse values stored in entry1
141 - Bmv2TernaryMatchParam inPortParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(0);
142 - Bmv2TernaryMatchParam ethDstParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(1);
143 - Bmv2TernaryMatchParam ethSrcParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(2);
144 - Bmv2TernaryMatchParam ethTypeParam = (Bmv2TernaryMatchParam) entry1.matchKey().matchParams().get(3);
145 - double expectedTimeout = (double) (model.table(0).hasTimeouts() ? rule1.timeout() : -1);
146 -
147 - // check that the number of parameters in the entry is the same as the number of table keys
148 - assertThat("Incorrect number of match parameters",
149 - entry1.matchKey().matchParams().size(), is(equalTo(numMatchParams)));
150 -
151 - // check that values stored in entry are the same used for the flow rule
152 - assertThat("Incorrect inPort match param value",
153 - inPortParam.value().asReadOnlyBuffer().getShort(), is(equalTo(inPort)));
154 - assertThat("Incorrect ethDestMac match param value",
155 - ethDstParam.value().asArray(), is(equalTo(ethDstMac.toBytes())));
156 - assertThat("Incorrect ethSrcMac match param value",
157 - ethSrcParam.value().asArray(), is(equalTo(ethSrcMac.toBytes())));
158 - assertThat("Incorrect ethType match param value",
159 - ethTypeParam.value().asReadOnlyBuffer().getShort(), is(equalTo(ethType)));
160 - assertThat("Incorrect priority value",
161 - entry1.priority(), is(equalTo(Integer.MAX_VALUE - rule1.priority())));
162 - assertThat("Incorrect timeout value",
163 - entry1.timeout(), is(equalTo(expectedTimeout)));
164 -
165 - }
166 -}
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
...@@ -41,7 +41,7 @@ ...@@ -41,7 +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 + <module>bmv2</module>
45 <module>corsa</module> 45 <module>corsa</module>
46 <module>optical</module> 46 <module>optical</module>
47 </modules> 47 </modules>
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-protocol</artifactId> 22 <artifactId>onos-bmv2-protocol</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-protocol</artifactId> 22 <artifactId>onos-bmv2-protocol</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-protocols</artifactId> 22 <artifactId>onos-protocols</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-protocol</artifactId> 22 <artifactId>onos-bmv2-protocol</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 27
27 <modelVersion>4.0.0</modelVersion> 28 <modelVersion>4.0.0</modelVersion>
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
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:${project.groupId}/onos-bmv2-provider-packet/${project.version}</bundle> 23 <bundle>mvn:${project.groupId}/onos-bmv2-provider-packet/${project.version}</bundle>
24 <bundle>mvn:org.apache.thrift/libthrift/0.9.3</bundle> 24 <bundle>mvn:org.apache.thrift/libthrift/0.9.3</bundle>
25 - <bundle>mvn:${project.groupId}/onos-bmv2-protocol/${project.version}</bundle> 25 + <bundle>mvn:${project.groupId}/onos-bmv2-protocol-api/${project.version}</bundle>
26 + <bundle>mvn:${project.groupId}/onos-bmv2-protocol-ctl/${project.version}</bundle>
27 + <bundle>mvn:${project.groupId}/onos-bmv2-protocol-thrift-api/${project.version}</bundle>
26 </feature> 28 </feature>
27 </features> 29 </features>
28 30
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-providers</artifactId> 22 <artifactId>onos-bmv2-providers</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 27
27 <modelVersion>4.0.0</modelVersion> 28 <modelVersion>4.0.0</modelVersion>
...@@ -33,7 +34,7 @@ ...@@ -33,7 +34,7 @@
33 34
34 <properties> 35 <properties>
35 <onos.app.name>org.onosproject.bmv2</onos.app.name> 36 <onos.app.name>org.onosproject.bmv2</onos.app.name>
36 - <onos.app.title>BMv2 Provider</onos.app.title> 37 + <onos.app.title>BMv2 Providers</onos.app.title>
37 <onos.app.category>Provider</onos.app.category> 38 <onos.app.category>Provider</onos.app.category>
38 </properties> 39 </properties>
39 40
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-providers</artifactId> 22 <artifactId>onos-bmv2-providers</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
...@@ -33,12 +34,12 @@ ...@@ -33,12 +34,12 @@
33 <dependencies> 34 <dependencies>
34 <dependency> 35 <dependency>
35 <groupId>org.onosproject</groupId> 36 <groupId>org.onosproject</groupId>
36 - <artifactId>onos-drivers-bmv2</artifactId> 37 + <artifactId>onos-core-common</artifactId>
37 <version>${project.version}</version> 38 <version>${project.version}</version>
38 </dependency> 39 </dependency>
39 <dependency> 40 <dependency>
40 <groupId>org.onosproject</groupId> 41 <groupId>org.onosproject</groupId>
41 - <artifactId>onos-core-common</artifactId> 42 + <artifactId>onos-bmv2-protocol-api</artifactId>
42 <version>${project.version}</version> 43 <version>${project.version}</version>
43 </dependency> 44 </dependency>
44 </dependencies> 45 </dependencies>
......
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.provider.bmv2.device.impl;
18 +
19 +import com.google.common.collect.Lists;
20 +import org.apache.commons.lang3.tuple.Pair;
21 +import org.onosproject.bmv2.api.runtime.Bmv2Action;
22 +import org.onosproject.bmv2.api.runtime.Bmv2DeviceAgent;
23 +import org.onosproject.bmv2.api.runtime.Bmv2RuntimeException;
24 +import org.onosproject.net.Port;
25 +import org.onosproject.net.device.DefaultPortStatistics;
26 +import org.onosproject.net.device.PortStatistics;
27 +import org.slf4j.Logger;
28 +import org.slf4j.LoggerFactory;
29 +
30 +import java.util.Collection;
31 +import java.util.List;
32 +
33 +/**
34 + * Utility class to read port statistics from a BMv2 device.
35 + */
36 +final class Bmv2PortStatisticsGetter {
37 +
38 + // TODO: make counters configuration dependent
39 +
40 + private static final String TABLE_NAME = "port_count_table";
41 + private static final String ACTION_NAME = "count_packet";
42 + private static final String EGRESS_COUNTER = "egress_port_counter";
43 + private static final String INGRESS_COUNTER = "ingress_port_counter";
44 +
45 + private static final Logger log = LoggerFactory.getLogger(Bmv2PortStatisticsGetter.class);
46 +
47 + private Bmv2PortStatisticsGetter() {
48 + // ban constructor.
49 + }
50 +
51 + /**
52 + * Returns a collection of port statistics for given ports using the given BMv2 device agent.
53 + *
54 + * @param deviceAgent a device agent
55 + * @param ports a collection of ports
56 + * @return a collection of port statistics
57 + */
58 + static Collection<PortStatistics> getPortStatistics(Bmv2DeviceAgent deviceAgent, Collection<Port> ports) {
59 +
60 + List<PortStatistics> ps = Lists.newArrayList();
61 +
62 + for (Port port : ports) {
63 + int portNumber = (int) port.number().toLong();
64 + try {
65 + Pair<Long, Long> egressCounter = deviceAgent.readCounter(EGRESS_COUNTER, portNumber);
66 + Pair<Long, Long> ingressCounter = deviceAgent.readCounter(INGRESS_COUNTER, portNumber);
67 + ps.add(DefaultPortStatistics.builder()
68 + .setPort(portNumber)
69 + .setBytesSent(egressCounter.getLeft())
70 + .setPacketsSent(egressCounter.getRight())
71 + .setBytesReceived(ingressCounter.getLeft())
72 + .setPacketsReceived(ingressCounter.getRight())
73 + .build());
74 + } catch (Bmv2RuntimeException e) {
75 + log.info("Unable to read port statistics from {}: {}", port, e.explain());
76 + }
77 + }
78 +
79 + return ps;
80 + }
81 +
82 + /**
83 + * Initialize port counters on the given device agent.
84 + *
85 + * @param deviceAgent a device agent.
86 + */
87 + static void initCounters(Bmv2DeviceAgent deviceAgent) {
88 + try {
89 + deviceAgent.setTableDefaultAction(TABLE_NAME, Bmv2Action.builder().withName(ACTION_NAME).build());
90 + } catch (Bmv2RuntimeException e) {
91 + log.debug("Failed to provision counters on {}: {}", deviceAgent.deviceId(), e.explain());
92 + }
93 + }
94 +}
95 +
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-bmv2-providers</artifactId> 22 <artifactId>onos-bmv2-providers</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 <modelVersion>4.0.0</modelVersion> 27 <modelVersion>4.0.0</modelVersion>
27 28
...@@ -34,12 +35,12 @@ ...@@ -34,12 +35,12 @@
34 <dependencies> 35 <dependencies>
35 <dependency> 36 <dependency>
36 <groupId>org.onosproject</groupId> 37 <groupId>org.onosproject</groupId>
37 - <artifactId>onos-drivers-bmv2</artifactId> 38 + <artifactId>onos-core-common</artifactId>
38 <version>${project.version}</version> 39 <version>${project.version}</version>
39 </dependency> 40 </dependency>
40 <dependency> 41 <dependency>
41 <groupId>org.onosproject</groupId> 42 <groupId>org.onosproject</groupId>
42 - <artifactId>onos-core-common</artifactId> 43 + <artifactId>onos-bmv2-protocol-api</artifactId>
43 <version>${project.version}</version> 44 <version>${project.version}</version>
44 </dependency> 45 </dependency>
45 </dependencies> 46 </dependencies>
......
...@@ -23,12 +23,14 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -23,12 +23,14 @@ import org.apache.felix.scr.annotations.Reference;
23 import org.apache.felix.scr.annotations.ReferenceCardinality; 23 import org.apache.felix.scr.annotations.ReferenceCardinality;
24 import org.onlab.packet.Ethernet; 24 import org.onlab.packet.Ethernet;
25 import org.onlab.util.ImmutableByteSequence; 25 import org.onlab.util.ImmutableByteSequence;
26 -import org.onosproject.bmv2.api.runtime.Bmv2ControlPlaneServer;
27 import org.onosproject.bmv2.api.runtime.Bmv2Device; 26 import org.onosproject.bmv2.api.runtime.Bmv2Device;
27 +import org.onosproject.bmv2.api.service.Bmv2Controller;
28 +import org.onosproject.bmv2.api.service.Bmv2PacketListener;
28 import org.onosproject.core.CoreService; 29 import org.onosproject.core.CoreService;
29 import org.onosproject.net.ConnectPoint; 30 import org.onosproject.net.ConnectPoint;
30 import org.onosproject.net.Device; 31 import org.onosproject.net.Device;
31 import org.onosproject.net.DeviceId; 32 import org.onosproject.net.DeviceId;
33 +import org.onosproject.net.Port;
32 import org.onosproject.net.PortNumber; 34 import org.onosproject.net.PortNumber;
33 import org.onosproject.net.device.DeviceService; 35 import org.onosproject.net.device.DeviceService;
34 import org.onosproject.net.flow.DefaultTrafficTreatment; 36 import org.onosproject.net.flow.DefaultTrafficTreatment;
...@@ -49,6 +51,12 @@ import org.slf4j.Logger; ...@@ -49,6 +51,12 @@ import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory; 51 import org.slf4j.LoggerFactory;
50 52
51 import java.nio.ByteBuffer; 53 import java.nio.ByteBuffer;
54 +import java.util.Optional;
55 +
56 +import static org.onosproject.net.PortNumber.FLOOD;
57 +import static org.onosproject.net.flow.DefaultTrafficTreatment.emptyTreatment;
58 +import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
59 +import static org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
52 60
53 /** 61 /**
54 * Implementation of a packet provider for BMv2. 62 * Implementation of a packet provider for BMv2.
...@@ -56,11 +64,11 @@ import java.nio.ByteBuffer; ...@@ -56,11 +64,11 @@ import java.nio.ByteBuffer;
56 @Component(immediate = true) 64 @Component(immediate = true)
57 public class Bmv2PacketProvider extends AbstractProvider implements PacketProvider { 65 public class Bmv2PacketProvider extends AbstractProvider implements PacketProvider {
58 66
59 - private static final Logger LOG = LoggerFactory.getLogger(Bmv2PacketProvider.class); 67 + private final Logger log = LoggerFactory.getLogger(Bmv2PacketProvider.class);
60 private static final String APP_NAME = "org.onosproject.bmv2"; 68 private static final String APP_NAME = "org.onosproject.bmv2";
61 69
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 - protected Bmv2ControlPlaneServer controlPlaneServer; 71 + protected Bmv2Controller controller;
64 72
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected CoreService coreService; 74 protected CoreService coreService;
...@@ -86,28 +94,28 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid ...@@ -86,28 +94,28 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid
86 protected void activate() { 94 protected void activate() {
87 providerService = providerRegistry.register(this); 95 providerService = providerRegistry.register(this);
88 coreService.registerApplication(APP_NAME); 96 coreService.registerApplication(APP_NAME);
89 - controlPlaneServer.addPacketListener(packetListener); 97 + controller.addPacketListener(packetListener);
90 - LOG.info("Started"); 98 + log.info("Started");
91 } 99 }
92 100
93 @Deactivate 101 @Deactivate
94 public void deactivate() { 102 public void deactivate() {
95 - controlPlaneServer.removePacketListener(packetListener); 103 + controller.removePacketListener(packetListener);
96 providerRegistry.unregister(this); 104 providerRegistry.unregister(this);
97 providerService = null; 105 providerService = null;
98 - LOG.info("Stopped"); 106 + log.info("Stopped");
99 } 107 }
100 108
101 @Override 109 @Override
102 public void emit(OutboundPacket packet) { 110 public void emit(OutboundPacket packet) {
103 if (packet != null) { 111 if (packet != null) {
104 - DeviceId did = packet.sendThrough(); 112 + DeviceId deviceId = packet.sendThrough();
105 - Device device = deviceService.getDevice(did); 113 + Device device = deviceService.getDevice(deviceId);
106 if (device.is(PacketProgrammable.class)) { 114 if (device.is(PacketProgrammable.class)) {
107 PacketProgrammable packetProgrammable = device.as(PacketProgrammable.class); 115 PacketProgrammable packetProgrammable = device.as(PacketProgrammable.class);
108 packetProgrammable.emit(packet); 116 packetProgrammable.emit(packet);
109 } else { 117 } else {
110 - LOG.info("Unable to send packet, no PacketProgrammable behavior for device {}", did); 118 + log.info("No PacketProgrammable behavior for device {}", deviceId);
111 } 119 }
112 } 120 }
113 } 121 }
...@@ -117,47 +125,75 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid ...@@ -117,47 +125,75 @@ public class Bmv2PacketProvider extends AbstractProvider implements PacketProvid
117 */ 125 */
118 private class Bmv2PacketContext extends DefaultPacketContext { 126 private class Bmv2PacketContext extends DefaultPacketContext {
119 127
120 - public Bmv2PacketContext(long time, InboundPacket inPkt, OutboundPacket outPkt, boolean block) { 128 + Bmv2PacketContext(long time, InboundPacket inPkt, OutboundPacket outPkt, boolean block) {
121 super(time, inPkt, outPkt, block); 129 super(time, inPkt, outPkt, block);
122 } 130 }
123 131
124 @Override 132 @Override
125 public void send() { 133 public void send() {
126 - if (!this.block()) { 134 +
127 - if (this.outPacket().treatment() == null) { 135 + if (this.block()) {
128 - TrafficTreatment treatment = (this.treatmentBuilder() == null) 136 + log.info("Unable to send, packet context not blocked");
129 - ? DefaultTrafficTreatment.emptyTreatment() 137 + return;
130 - : this.treatmentBuilder().build(); 138 + }
131 - OutboundPacket newPkt = new DefaultOutboundPacket(this.outPacket().sendThrough(), 139 +
132 - treatment, 140 + DeviceId deviceId = outPacket().sendThrough();
133 - this.outPacket().data()); 141 + ByteBuffer rawData = outPacket().data();
134 - emit(newPkt); 142 +
135 - } else { 143 + TrafficTreatment treatment;
136 - emit(outPacket()); 144 + if (outPacket().treatment() == null) {
137 - } 145 + treatment = (treatmentBuilder() == null) ? emptyTreatment() : treatmentBuilder().build();
146 + } else {
147 + treatment = outPacket().treatment();
148 + }
149 +
150 + // BMv2 doesn't support FLOOD for packet-outs.
151 + // Workaround here is to perform multiple emits, one for each device port != packet inPort.
152 + Optional<OutputInstruction> floodInst = treatment.allInstructions()
153 + .stream()
154 + .filter(i -> i.type().equals(OUTPUT))
155 + .map(i -> (OutputInstruction) i)
156 + .filter(i -> i.port().equals(FLOOD))
157 + .findAny();
158 +
159 + if (floodInst.isPresent() && treatment.allInstructions().size() == 1) {
160 + // Only one instruction and is FLOOD. Do the trick.
161 + PortNumber inPort = inPacket().receivedFrom().port();
162 + deviceService.getPorts(outPacket().sendThrough())
163 + .stream()
164 + .map(Port::number)
165 + .filter(port -> !port.equals(inPort))
166 + .map(outPort -> DefaultTrafficTreatment.builder().setOutput(outPort).build())
167 + .map(outTreatment -> new DefaultOutboundPacket(deviceId, outTreatment, rawData))
168 + .forEach(Bmv2PacketProvider.this::emit);
138 } else { 169 } else {
139 - LOG.info("Unable to send, packet context not blocked"); 170 + // Not FLOOD treatment, what to do is up to driver.
171 + emit(new DefaultOutboundPacket(deviceId, treatment, rawData));
140 } 172 }
141 } 173 }
142 } 174 }
143 175
144 /** 176 /**
145 - * Internal packet listener to get packet events from the Bmv2ControlPlaneServer. 177 + * Internal packet listener to handle packet-in events received from the BMv2 controller.
146 */ 178 */
147 - private class InternalPacketListener implements Bmv2ControlPlaneServer.PacketListener { 179 + private class InternalPacketListener implements Bmv2PacketListener {
180 +
148 @Override 181 @Override
149 public void handlePacketIn(Bmv2Device device, int inputPort, long reason, int tableId, int contextId, 182 public void handlePacketIn(Bmv2Device device, int inputPort, long reason, int tableId, int contextId,
150 ImmutableByteSequence packet) { 183 ImmutableByteSequence packet) {
184 + Ethernet ethPkt = new Ethernet();
185 + ethPkt.deserialize(packet.asArray(), 0, packet.size());
151 186
152 - Ethernet eth = new Ethernet(); 187 + DeviceId deviceId = device.asDeviceId();
153 - eth.deserialize(packet.asArray(), 0, packet.size()); 188 + ConnectPoint receivedFrom = new ConnectPoint(deviceId, PortNumber.portNumber(inputPort));
189 +
190 + ByteBuffer rawData = ByteBuffer.wrap(packet.asArray());
191 +
192 + InboundPacket inPkt = new DefaultInboundPacket(receivedFrom, ethPkt, rawData);
193 + OutboundPacket outPkt = new DefaultOutboundPacket(deviceId, null, rawData);
154 194
155 - InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(device.asDeviceId(),
156 - PortNumber.portNumber(inputPort)),
157 - eth, ByteBuffer.wrap(packet.asArray()));
158 - OutboundPacket outPkt = new DefaultOutboundPacket(device.asDeviceId(), null,
159 - ByteBuffer.wrap(packet.asArray()));
160 PacketContext pktCtx = new Bmv2PacketContext(System.currentTimeMillis(), inPkt, outPkt, false); 195 PacketContext pktCtx = new Bmv2PacketContext(System.currentTimeMillis(), inPkt, outPkt, false);
196 +
161 providerService.processPacket(pktCtx); 197 providerService.processPacket(pktCtx);
162 } 198 }
163 } 199 }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 <artifactId>onos-providers</artifactId> 22 <artifactId>onos-providers</artifactId>
23 <groupId>org.onosproject</groupId> 23 <groupId>org.onosproject</groupId>
24 <version>1.6.0-SNAPSHOT</version> 24 <version>1.6.0-SNAPSHOT</version>
25 + <relativePath>../pom.xml</relativePath>
25 </parent> 26 </parent>
26 27
27 <modelVersion>4.0.0</modelVersion> 28 <modelVersion>4.0.0</modelVersion>
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
46 <module>lldpcommon</module> 46 <module>lldpcommon</module>
47 <module>lldp</module> 47 <module>lldp</module>
48 <module>netcfglinks</module> 48 <module>netcfglinks</module>
49 - <!--<module>bmv2</module>--> 49 + <module>bmv2</module>
50 <module>isis</module> 50 <module>isis</module>
51 </modules> 51 </modules>
52 52
......