diff --git a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Device.java b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Device.java index 446a514bd3..e289615c1f 100644 --- a/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Device.java +++ b/protocols/bmv2/src/main/java/org/onosproject/bmv2/api/runtime/Bmv2Device.java @@ -17,6 +17,10 @@ package org.onosproject.bmv2.api.runtime; import com.google.common.base.Objects; +import org.onosproject.net.DeviceId; + +import java.net.URI; +import java.net.URISyntaxException; import static com.google.common.base.Preconditions.checkNotNull; @@ -25,6 +29,10 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public final class Bmv2Device { + public static final String SCHEME = "bmv2"; + public static final String MANUFACTURER = "p4.org"; + public static final String HW_VERSION = "bmv2"; + private final String thriftServerHost; private final int thriftServerPort; private final int internalDeviceId; @@ -66,10 +74,24 @@ public final class Bmv2Device { * * @return an integer value */ - public int getInternalDeviceId() { + public int internalDeviceId() { return internalDeviceId; } + /** + * Returns a new ONOS device ID for this device. + * + * @return a new device ID + */ + public DeviceId asDeviceId() { + try { + // TODO: include internalDeviceId number in the deviceId URI + return DeviceId.deviceId(new URI(SCHEME, this.thriftServerHost + ":" + this.thriftServerPort, null)); + } catch (URISyntaxException e) { + throw new IllegalArgumentException("Unable to build deviceID for device " + this.toString(), e); + } + } + @Override public int hashCode() { return Objects.hashCode(thriftServerHost, thriftServerPort, internalDeviceId); diff --git a/providers/bmv2/app/features.xml b/providers/bmv2/app/features.xml index 8886c0c4cd..f13d07c922 100644 --- a/providers/bmv2/app/features.xml +++ b/providers/bmv2/app/features.xml @@ -20,6 +20,7 @@ onos-drivers-bmv2 mvn:${project.groupId}/${project.artifactId}/${project.version} mvn:${project.groupId}/onos-bmv2-provider-device/${project.version} + mvn:${project.groupId}/onos-bmv2-provider-packet/${project.version} mvn:org.apache.thrift/libthrift/0.9.3 mvn:${project.groupId}/onos-bmv2-protocol/${project.version} diff --git a/providers/bmv2/app/pom.xml b/providers/bmv2/app/pom.xml index 27074092ff..e996b0c9d7 100644 --- a/providers/bmv2/app/pom.xml +++ b/providers/bmv2/app/pom.xml @@ -36,13 +36,18 @@ BMv2 Provider Provider - + org.onosproject onos-bmv2-provider-device ${project.version} + + org.onosproject + onos-bmv2-provider-packet + ${project.version} + \ No newline at end of file diff --git a/providers/bmv2/device/pom.xml b/providers/bmv2/device/pom.xml index 021d90f40c..80f42e1861 100644 --- a/providers/bmv2/device/pom.xml +++ b/providers/bmv2/device/pom.xml @@ -39,7 +39,7 @@ org.onosproject onos-core-common - 1.6.0-SNAPSHOT + ${project.version} \ No newline at end of file diff --git a/providers/bmv2/device/src/main/java/org/onosproject/provider/bmv2/device/impl/Bmv2DeviceProvider.java b/providers/bmv2/device/src/main/java/org/onosproject/provider/bmv2/device/impl/Bmv2DeviceProvider.java index 2d16ff2f52..d9ac3a40fc 100644 --- a/providers/bmv2/device/src/main/java/org/onosproject/provider/bmv2/device/impl/Bmv2DeviceProvider.java +++ b/providers/bmv2/device/src/main/java/org/onosproject/provider/bmv2/device/impl/Bmv2DeviceProvider.java @@ -50,8 +50,6 @@ import org.onosproject.net.device.PortDescription; import org.onosproject.net.provider.ProviderId; import org.slf4j.Logger; -import java.net.URI; -import java.net.URISyntaxException; import java.util.List; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; @@ -63,6 +61,9 @@ import static org.onosproject.bmv2.ctl.Bmv2ThriftClient.forceDisconnectOf; import static org.onosproject.bmv2.ctl.Bmv2ThriftClient.ping; import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; import static org.slf4j.LoggerFactory.getLogger; +import static org.onosproject.bmv2.api.runtime.Bmv2Device.SCHEME; +import static org.onosproject.bmv2.api.runtime.Bmv2Device.MANUFACTURER; +import static org.onosproject.bmv2.api.runtime.Bmv2Device.HW_VERSION; /** * BMv2 device provider. @@ -72,9 +73,6 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { private static final Logger LOG = getLogger(Bmv2DeviceProvider.class); - public static final String MANUFACTURER = "p4.org"; - public static final String HW_VERSION = "bmv2"; - public static final String SCHEME = "bmv2"; private static final String APP_NAME = "org.onosproject.bmv2"; private static final String UNKNOWN = "unknown"; private static final int POLL_INTERVAL = 5; // seconds @@ -108,25 +106,6 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { super(new ProviderId("bmv2", "org.onosproject.provider.device")); } - private static DeviceId deviceIdOf(String ip, int port) { - try { - return DeviceId.deviceId(new URI(SCHEME, ip + ":" + port, null)); - } catch (URISyntaxException e) { - throw new IllegalArgumentException("Unable to build deviceID for device " + ip + ":" + port, e); - } - } - - /** - * Creates a new device ID for the given BMv2 device. - * - * @param device a BMv2 device object - * - * @return a new device ID - */ - public static DeviceId deviceIdOf(Bmv2Device device) { - return deviceIdOf(device.thriftServerHost(), device.thriftServerPort()); - } - @Override protected void activate() { appId = coreService.registerApplication(APP_NAME); @@ -258,7 +237,9 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { if (cfg != null) { try { cfg.getDevicesInfo().stream().forEach(info -> { - triggerProbe(deviceIdOf(info.ip().toString(), info.port())); + // TODO: require also bmv2 internal device id from net-cfg (now is default 0) + Bmv2Device bmv2Device = new Bmv2Device(info.ip().toString(), info.port(), 0); + triggerProbe(bmv2Device.asDeviceId()); }); } catch (ConfigException e) { LOG.error("Unable to read config: " + e); @@ -283,7 +264,7 @@ public class Bmv2DeviceProvider extends AbstractDeviceProvider { @Override public void handleHello(Bmv2Device device) { log.debug("Received hello from {}", device); - triggerProbe(deviceIdOf(device)); + triggerProbe(device.asDeviceId()); } } diff --git a/providers/bmv2/packet/pom.xml b/providers/bmv2/packet/pom.xml new file mode 100644 index 0000000000..0b98e307d5 --- /dev/null +++ b/providers/bmv2/packet/pom.xml @@ -0,0 +1,46 @@ + + + + + + onos-bmv2-providers + org.onosproject + 1.6.0-SNAPSHOT + + 4.0.0 + + onos-bmv2-provider-packet + + bundle + + ONOS BMv2 packet provider + + + + org.onosproject + onos-drivers-bmv2 + ${project.version} + + + org.onosproject + onos-core-common + ${project.version} + + + \ No newline at end of file diff --git a/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/Bmv2PacketProvider.java b/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/Bmv2PacketProvider.java new file mode 100644 index 0000000000..edb6159144 --- /dev/null +++ b/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/Bmv2PacketProvider.java @@ -0,0 +1,164 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onosproject.provider.bmv2.packet.impl; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.packet.Ethernet; +import org.onlab.util.ImmutableByteSequence; +import org.onosproject.bmv2.api.runtime.Bmv2ControlPlaneServer; +import org.onosproject.bmv2.api.runtime.Bmv2Device; +import org.onosproject.core.CoreService; +import org.onosproject.net.ConnectPoint; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.flow.DefaultTrafficTreatment; +import org.onosproject.net.flow.TrafficTreatment; +import org.onosproject.net.packet.DefaultInboundPacket; +import org.onosproject.net.packet.DefaultOutboundPacket; +import org.onosproject.net.packet.DefaultPacketContext; +import org.onosproject.net.packet.InboundPacket; +import org.onosproject.net.packet.OutboundPacket; +import org.onosproject.net.packet.PacketContext; +import org.onosproject.net.packet.PacketProgrammable; +import org.onosproject.net.packet.PacketProvider; +import org.onosproject.net.packet.PacketProviderRegistry; +import org.onosproject.net.packet.PacketProviderService; +import org.onosproject.net.provider.AbstractProvider; +import org.onosproject.net.provider.ProviderId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.ByteBuffer; + +/** + * Implementation of a packet provider for BMv2. + */ +@Component(immediate = true) +public class Bmv2PacketProvider extends AbstractProvider implements PacketProvider { + + private static final Logger LOG = LoggerFactory.getLogger(Bmv2PacketProvider.class); + private static final String APP_NAME = "org.onosproject.bmv2"; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected Bmv2ControlPlaneServer controlPlaneServer; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected PacketProviderRegistry providerRegistry; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + private PacketProviderService providerService; + + private InternalPacketListener packetListener = new InternalPacketListener(); + + /** + * Creates a new BMv2 packet provider. + */ + public Bmv2PacketProvider() { + super(new ProviderId("bmv2", "org.onosproject.provider.packet")); + } + + @Activate + protected void activate() { + providerService = providerRegistry.register(this); + coreService.registerApplication(APP_NAME); + controlPlaneServer.addPacketListener(packetListener); + LOG.info("Started"); + } + + @Deactivate + public void deactivate() { + controlPlaneServer.removePacketListener(packetListener); + providerRegistry.unregister(this); + providerService = null; + LOG.info("Stopped"); + } + + @Override + public void emit(OutboundPacket packet) { + if (packet != null) { + DeviceId did = packet.sendThrough(); + Device device = deviceService.getDevice(did); + if (device.is(PacketProgrammable.class)) { + PacketProgrammable packetProgrammable = device.as(PacketProgrammable.class); + packetProgrammable.emit(packet); + } else { + LOG.info("Unable to send packet, no PacketProgrammable behavior for device {}", did); + } + } + } + + /** + * Internal packet context implementation. + */ + private class Bmv2PacketContext extends DefaultPacketContext { + + public Bmv2PacketContext(long time, InboundPacket inPkt, OutboundPacket outPkt, boolean block) { + super(time, inPkt, outPkt, block); + } + + @Override + public void send() { + if (!this.block()) { + if (this.outPacket().treatment() == null) { + TrafficTreatment treatment = (this.treatmentBuilder() == null) + ? DefaultTrafficTreatment.emptyTreatment() + : this.treatmentBuilder().build(); + OutboundPacket newPkt = new DefaultOutboundPacket(this.outPacket().sendThrough(), + treatment, + this.outPacket().data()); + emit(newPkt); + } else { + emit(outPacket()); + } + } else { + LOG.info("Unable to send, packet context not blocked"); + } + } + } + + /** + * Internal packet listener to get packet events from the Bmv2ControlPlaneServer. + */ + private class InternalPacketListener implements Bmv2ControlPlaneServer.PacketListener { + @Override + public void handlePacketIn(Bmv2Device device, int inputPort, long reason, int tableId, int contextId, + ImmutableByteSequence packet) { + + Ethernet eth = new Ethernet(); + eth.deserialize(packet.asArray(), 0, packet.size()); + + InboundPacket inPkt = new DefaultInboundPacket(new ConnectPoint(device.asDeviceId(), + PortNumber.portNumber(inputPort)), + eth, ByteBuffer.wrap(packet.asArray())); + OutboundPacket outPkt = new DefaultOutboundPacket(device.asDeviceId(), null, + ByteBuffer.wrap(packet.asArray())); + PacketContext pktCtx = new Bmv2PacketContext(System.currentTimeMillis(), inPkt, outPkt, false); + providerService.processPacket(pktCtx); + } + } +} diff --git a/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/package-info.java b/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/package-info.java new file mode 100644 index 0000000000..3d83eadbfc --- /dev/null +++ b/providers/bmv2/packet/src/main/java/org/onosproject/provider/bmv2/packet/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2016-present Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Provider that use Thrift as a mean of listening for packet-ins and emitting packet-outs. + */ +package org.onosproject.provider.bmv2.packet.impl; \ No newline at end of file diff --git a/providers/bmv2/pom.xml b/providers/bmv2/pom.xml index 6b6517983b..8a3ad6fc8b 100644 --- a/providers/bmv2/pom.xml +++ b/providers/bmv2/pom.xml @@ -34,6 +34,7 @@ app device + packet \ No newline at end of file