[ONOS-6616] Revise VirtualPacketContext and DefaultVirtualPacketProvider
The constructor of VirtualPacketContext needs a parameter of DefaultVirtualPacketProvider type.
It is not flexible for us to use another packet provider to replace the default virtual packet provider.
To improve the code flexibility, I think it is better for us to use an interface type parameter in a method.
It alse seems redundant to use emit() method of DefaultVirtualPacketProvider in devirtualizeContext().
Thus, I think it will be more efficient to use core PacketService in VirtualPacketContext
when triger send() method.
Some other bugs are fixed.
Change-Id: I161a8929dc4e5a1d2ad716bc5da8b0b6f84340a9
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java
new file mode 100644
index 0000000..54239e4
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2015-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.incubator.net.virtual;
+
+import org.onosproject.net.packet.PacketContext;
+
+/**
+ * Represents context for processing an inbound packet for a virtual network,
+ * and (optionally) emitting a corresponding outbound packet.
+ */
+public interface VirtualPacketContext extends PacketContext {
+ /**
+ * Returns the network identifier.
+ *
+ * @return network id
+ */
+ NetworkId networkId();
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualPacketContext.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketContext.java
similarity index 69%
rename from incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualPacketContext.java
rename to incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketContext.java
index 9d03b0dc..1d59a10 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/VirtualPacketContext.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketContext.java
@@ -17,18 +17,19 @@
package org.onosproject.incubator.net.virtual.impl.provider;
import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualPacketContext;
import org.onosproject.net.packet.DefaultPacketContext;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
/**
- * Represents context for processing an inbound packet for a virtual network
- * and (optionally) emitting a corresponding outbound packet.
- * The translation of context is handled by VirtualPacketProvider.
+ *Default implementation of a virtual packet context.
*/
-public class VirtualPacketContext extends DefaultPacketContext {
- private DefaultVirtualPacketProvider dvpp;
+public class DefaultVirtualPacketContext extends DefaultPacketContext
+ implements VirtualPacketContext {
+
private NetworkId networkId;
+ private DefaultVirtualPacketProvider dvpp;
/**
* Creates a new packet context.
@@ -38,13 +39,13 @@
* @param outPkt outbound packet
* @param block whether the context is blocked or not
* @param networkId virtual network ID where this context is handled
- * @param dvpp The pointer for DefaultVirtualPacketProvider
+ * @param dvpp pointer to default virtual packet provider
*/
- protected VirtualPacketContext(long time, InboundPacket inPkt,
- OutboundPacket outPkt, boolean block,
- NetworkId networkId,
- DefaultVirtualPacketProvider dvpp) {
+ protected DefaultVirtualPacketContext(long time, InboundPacket inPkt,
+ OutboundPacket outPkt, boolean block,
+ NetworkId networkId,
+ DefaultVirtualPacketProvider dvpp) {
super(time, inPkt, outPkt, block);
this.networkId = networkId;
@@ -54,11 +55,12 @@
@Override
public void send() {
if (!this.block()) {
- dvpp.devirtualizeContext(this);
+ dvpp.send(this);
}
}
- public NetworkId getNetworkId() {
+ @Override
+ public NetworkId networkId() {
return networkId;
}
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketProvider.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketProvider.java
index 5eaa3b0..ad81063 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketProvider.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualPacketProvider.java
@@ -16,7 +16,6 @@
package org.onosproject.incubator.net.virtual.impl.provider;
-import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -32,6 +31,7 @@
import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualNetwork;
import org.onosproject.incubator.net.virtual.VirtualNetworkAdminService;
+import org.onosproject.incubator.net.virtual.VirtualPacketContext;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
import org.onosproject.incubator.net.virtual.provider.VirtualPacketProvider;
@@ -59,7 +59,6 @@
import java.nio.ByteBuffer;
import java.util.Dictionary;
import java.util.HashSet;
-import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -87,10 +86,8 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected VirtualProviderRegistryService providerRegistryService;
- ApplicationId appId;
- InternalPacketProcessor processor;
-
- private Map<VirtualPacketContext, PacketContext> contextMap;
+ private ApplicationId appId;
+ private InternalPacketProcessor processor;
private Set<NetworkId> requestsSet = Sets.newHashSet();
@@ -106,8 +103,6 @@
appId = coreService.registerApplication("org.onosproject.virtual.virtual-packet");
providerRegistryService.registerProvider(this);
- contextMap = Maps.newConcurrentMap();
-
log.info("Started");
}
@@ -128,7 +123,8 @@
@Override
public void emit(NetworkId networkId, OutboundPacket packet) {
- packetService.emit(devirtualize(networkId, packet));
+ devirtualize(networkId, packet)
+ .forEach(outboundPacket -> packetService.emit(outboundPacket));
}
@Override
@@ -150,8 +146,21 @@
}
/**
+ * Send the outbound packet of a virtual context.
+ * This method is designed to support Context's send() method that invoked
+ * by applications.
+ * See {@link org.onosproject.net.packet.PacketContext}
+ *
+ * @param virtualPacketContext virtual packet context
+ */
+ protected void send(VirtualPacketContext virtualPacketContext) {
+ devirtualizeContext(virtualPacketContext)
+ .forEach(outboundPacket -> packetService.emit(outboundPacket));
+ }
+
+ /**
* Translate the requested physical PacketContext into a virtual PacketContext.
- * See {@link org.onosproject.net.packet.OutboundPacket}
+ * See {@link org.onosproject.net.packet.PacketContext}
*
* @param context A physical PacketContext be translated
* @return A translated virtual PacketContext
@@ -177,12 +186,10 @@
ByteBuffer.wrap(eth.serialize()));
VirtualPacketContext vContext =
- new VirtualPacketContext(context.time(), inPacket, outPkt,
- false, vPort.networkId(),
+ new DefaultVirtualPacketContext(context.time(), inPacket, outPkt,
+ context.isHandled(), vPort.networkId(),
this);
- contextMap.put(vContext, context);
-
return vContext;
} else {
return null;
@@ -222,33 +229,18 @@
}
/**
- * Translate the requested a virtual outbound packet into
- * a physical OutboundPacket.
- * See {@link org.onosproject.net.packet.PacketContext}
+ * Translate the requested virtual outbound packet into
+ * a set of physical OutboundPacket.
+ * See {@link org.onosproject.net.packet.OutboundPacket}
*
- * @param packet A OutboundPacket to be translated
- * @return de-virtualized (physical) OutboundPacket
+ * @param packet an OutboundPacket to be translated
+ * @return a set of de-virtualized (physical) OutboundPacket
*/
- private OutboundPacket devirtualize(NetworkId networkId, OutboundPacket packet) {
+ private Set<OutboundPacket> devirtualize(NetworkId networkId, OutboundPacket packet) {
+ Set<OutboundPacket> outboundPackets = new HashSet<>();
Set<VirtualPort> vPorts = vnaService
.getVirtualPorts(networkId, packet.sendThrough());
- PortNumber vOutPortNum = packet.treatment().allInstructions().stream()
- .filter(i -> i.type() == Instruction.Type.OUTPUT)
- .map(i -> ((Instructions.OutputInstruction) i).port())
- .findFirst().get();
-
- Optional<ConnectPoint> optionalCpOut = vPorts.stream()
- .filter(v -> v.number().equals(vOutPortNum))
- .map(v -> v.realizedBy())
- .findFirst();
- if (!optionalCpOut.isPresent()) {
- log.warn("Port {} is not realized yet, in Network {}, Device {}",
- vOutPortNum, networkId, packet.sendThrough());
- return null;
- }
- ConnectPoint egressPoint = optionalCpOut.get();
-
TrafficTreatment.Builder commonTreatmentBuilder
= DefaultTrafficTreatment.builder();
packet.treatment().allInstructions().stream()
@@ -256,31 +248,69 @@
.forEach(i -> commonTreatmentBuilder.add(i));
TrafficTreatment commonTreatment = commonTreatmentBuilder.build();
- TrafficTreatment treatment = DefaultTrafficTreatment
- .builder(commonTreatment)
- .setOutput(egressPoint.port()).build();
+ PortNumber vOutPortNum = packet.treatment().allInstructions().stream()
+ .filter(i -> i.type() == Instruction.Type.OUTPUT)
+ .map(i -> ((Instructions.OutputInstruction) i).port())
+ .findFirst().get();
- OutboundPacket outboundPacket = new DefaultOutboundPacket(
- egressPoint.deviceId(), treatment, packet.data());
- return outboundPacket;
+ if (!vOutPortNum.isLogical()) {
+ Optional<ConnectPoint> optionalCpOut = vPorts.stream()
+ .filter(v -> v.number().equals(vOutPortNum))
+ .map(v -> v.realizedBy())
+ .findFirst();
+ if (!optionalCpOut.isPresent()) {
+ log.warn("Port {} is not realized yet, in Network {}, Device {}",
+ vOutPortNum, networkId, packet.sendThrough());
+ return outboundPackets;
+ }
+ ConnectPoint egressPoint = optionalCpOut.get();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment
+ .builder(commonTreatment)
+ .setOutput(egressPoint.port()).build();
+
+ OutboundPacket outboundPacket = new DefaultOutboundPacket(
+ egressPoint.deviceId(), treatment, packet.data());
+ outboundPackets.add(outboundPacket);
+ } else {
+ if (vOutPortNum == PortNumber.FLOOD) {
+ for (VirtualPort outPort : vPorts) {
+ ConnectPoint cpOut = outPort.realizedBy();
+ if (cpOut != null) {
+ TrafficTreatment treatment = DefaultTrafficTreatment
+ .builder(commonTreatment)
+ .setOutput(cpOut.port()).build();
+ OutboundPacket outboundPacket = new DefaultOutboundPacket(
+ cpOut.deviceId(), treatment, packet.data());
+ outboundPackets.add(outboundPacket);
+ } else {
+ log.warn("Port {} is not realized yet, in Network {}, Device {}",
+ outPort.number(), networkId, packet.sendThrough());
+ }
+ }
+ }
+ }
+
+ return outboundPackets;
}
/**
- * Translate the requested a virtual Packet Context into
- * a physical Packet Context.
- * This method is designed to support Context's send() method that invoked
- * by applications.
- * See {@link org.onosproject.net.packet.PacketContext}
+ * Translate the requested virtual packet context into
+ * a set of physical outbound packets.
*
- * @param context A handled packet context
+ * @param context A handled virtual packet context
*/
- public void devirtualizeContext(VirtualPacketContext context) {
- NetworkId networkId = context.getNetworkId();
+ private Set<OutboundPacket> devirtualizeContext(VirtualPacketContext context) {
+ Set<OutboundPacket> outboundPackets = new HashSet<>();
+
+ NetworkId networkId = context.networkId();
TrafficTreatment vTreatment = context.treatmentBuilder().build();
-
DeviceId sendThrough = context.outPacket().sendThrough();
+ Set<VirtualPort> vPorts = vnaService
+ .getVirtualPorts(networkId, sendThrough);
+
PortNumber vOutPortNum = vTreatment.allInstructions().stream()
.filter(i -> i.type() == Instruction.Type.OUTPUT)
.map(i -> ((Instructions.OutputInstruction) i).port())
@@ -294,20 +324,26 @@
TrafficTreatment commonTreatment = commonTreatmentBuilder.build();
if (!vOutPortNum.isLogical()) {
- TrafficTreatment treatment = DefaultTrafficTreatment
- .builder()
- .addTreatment(commonTreatment)
- .setOutput(vOutPortNum)
- .build();
+ Optional<ConnectPoint> optionalCpOut = vPorts.stream()
+ .filter(v -> v.number().equals(vOutPortNum))
+ .map(v -> v.realizedBy())
+ .findFirst();
+ if (!optionalCpOut.isPresent()) {
+ log.warn("Port {} is not realized yet, in Network {}, Device {}",
+ vOutPortNum, networkId, sendThrough);
+ return outboundPackets;
+ }
+ ConnectPoint egressPoint = optionalCpOut.get();
- emit(networkId, new DefaultOutboundPacket(sendThrough,
- treatment,
- context.outPacket().data()));
+ TrafficTreatment treatment = DefaultTrafficTreatment
+ .builder(commonTreatment)
+ .setOutput(egressPoint.port()).build();
+
+ OutboundPacket outboundPacket = new DefaultOutboundPacket(
+ egressPoint.deviceId(), treatment, context.outPacket().data());
+ outboundPackets.add(outboundPacket);
} else {
if (vOutPortNum == PortNumber.FLOOD) {
- Set<VirtualPort> vPorts = vnaService
- .getVirtualPorts(networkId, sendThrough);
-
Set<VirtualPort> outPorts = vPorts.stream()
.filter(vp -> !vp.number().isLogical())
.filter(vp -> vp.number() !=
@@ -315,18 +351,22 @@
.collect(Collectors.toSet());
for (VirtualPort outPort : outPorts) {
- TrafficTreatment treatment = DefaultTrafficTreatment
- .builder()
- .addTreatment(commonTreatment)
- .setOutput(outPort.number())
- .build();
-
- emit(networkId, new DefaultOutboundPacket(sendThrough,
- treatment,
- context.outPacket().data()));
+ ConnectPoint cpOut = outPort.realizedBy();
+ if (cpOut != null) {
+ TrafficTreatment treatment = DefaultTrafficTreatment
+ .builder(commonTreatment)
+ .setOutput(cpOut.port()).build();
+ OutboundPacket outboundPacket = new DefaultOutboundPacket(
+ cpOut.deviceId(), treatment, context.outPacket().data());
+ outboundPackets.add(outboundPacket);
+ } else {
+ log.warn("Port {} is not realized yet, in Network {}, Device {}",
+ outPort.number(), networkId, sendThrough);
+ }
}
}
}
+ return outboundPackets;
}
private final class InternalPacketProcessor implements PacketProcessor {
@@ -341,7 +381,7 @@
VirtualPacketProviderService service =
(VirtualPacketProviderService) providerRegistryService
- .getProviderService(vContexts.getNetworkId(),
+ .getProviderService(vContexts.networkId(),
VirtualPacketProvider.class);
if (service != null) {
service.processPacket(vContexts);