From bee92f62f702bc9e00e9d4c19d5439af6bb6bc27 Mon Sep 17 00:00:00 2001 From: Harold Huang Date: Wed, 7 Jun 2017 22:39:37 +0800 Subject: [PATCH] [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 --- .../net/virtual/VirtualPacketContext.java | 31 +++ ....java => DefaultVirtualPacketContext.java} | 26 +-- .../DefaultVirtualPacketProvider.java | 184 +++++++++++------- 3 files changed, 157 insertions(+), 84 deletions(-) create mode 100644 incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualPacketContext.java rename incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/{VirtualPacketContext.java => DefaultVirtualPacketContext.java} (68%) 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 0000000000..54239e4704 --- /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 68% 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 9d03b0dc46..1d59a10d8d 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 @@ public class VirtualPacketContext extends DefaultPacketContext { * @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 @@ public class VirtualPacketContext extends DefaultPacketContext { @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 5eaa3b045a..ad810638a3 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.TenantId; 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 org.slf4j.Logger; 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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected VirtualProviderRegistryService providerRegistryService; - ApplicationId appId; - InternalPacketProcessor processor; - - private Map contextMap; + private ApplicationId appId; + private InternalPacketProcessor processor; private Set requestsSet = Sets.newHashSet(); @@ -106,8 +103,6 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider appId = coreService.registerApplication("org.onosproject.virtual.virtual-packet"); providerRegistryService.registerProvider(this); - contextMap = Maps.newConcurrentMap(); - log.info("Started"); } @@ -128,7 +123,8 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider @Override public void emit(NetworkId networkId, OutboundPacket packet) { - packetService.emit(devirtualize(networkId, packet)); + devirtualize(networkId, packet) + .forEach(outboundPacket -> packetService.emit(outboundPacket)); } @Override @@ -149,9 +145,22 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider } } + /** + * 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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider 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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider } /** - * 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 devirtualize(NetworkId networkId, OutboundPacket packet) { + Set outboundPackets = new HashSet<>(); Set 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 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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider .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 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 devirtualizeContext(VirtualPacketContext context) { + Set outboundPackets = new HashSet<>(); + + NetworkId networkId = context.networkId(); TrafficTreatment vTreatment = context.treatmentBuilder().build(); - DeviceId sendThrough = context.outPacket().sendThrough(); + Set 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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider TrafficTreatment commonTreatment = commonTreatmentBuilder.build(); if (!vOutPortNum.isLogical()) { - TrafficTreatment treatment = DefaultTrafficTreatment - .builder() - .addTreatment(commonTreatment) - .setOutput(vOutPortNum) - .build(); + Optional 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 vPorts = vnaService - .getVirtualPorts(networkId, sendThrough); - Set outPorts = vPorts.stream() .filter(vp -> !vp.number().isLogical()) .filter(vp -> vp.number() != @@ -315,18 +351,22 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider .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 @@ public class DefaultVirtualPacketProvider extends AbstractVirtualProvider VirtualPacketProviderService service = (VirtualPacketProviderService) providerRegistryService - .getProviderService(vContexts.getNetworkId(), + .getProviderService(vContexts.networkId(), VirtualPacketProvider.class); if (service != null) { service.processPacket(vContexts);