aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core/net
diff options
context:
space:
mode:
authorAshlee Young <ashlee@wildernessvoice.com>2015-11-03 14:08:10 -0800
committerAshlee Young <ashlee@wildernessvoice.com>2015-11-03 14:08:10 -0800
commit643ee33289bd2cb9e6afbfb09b4ed72d467ba1c2 (patch)
treec2c376a44a359544fe3d4c45eb0cc0e2ec4a7080 /framework/src/onos/core/net
parent46eeb79b54345bdafb6055b8ee4bad4ce8b01274 (diff)
This updates ONOS src tree to commit id
03fa5e571cabbd001ddb1598847e1150b11c7333 Change-Id: I13b554026d6f902933e35887d29bd5fdb669c0bd Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/core/net')
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java48
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java116
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java2
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java24
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java110
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java3
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java108
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java13
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java98
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java100
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java15
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java395
12 files changed, 809 insertions, 223 deletions
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
index 04d1dfdf..7ddac0ce 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
@@ -25,17 +25,26 @@ import org.apache.karaf.system.SystemService;
import org.joda.time.DateTime;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterAdminService;
-import org.onosproject.cluster.ClusterDefinitionService;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.Partition;
import org.onosproject.event.AbstractListenerManager;
import org.slf4j.Logger;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
@@ -44,8 +53,6 @@ import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
-
-
/**
* Implementation of the cluster service.
*/
@@ -61,7 +68,7 @@ public class ClusterManager
private ClusterStoreDelegate delegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterStore store;
@@ -73,8 +80,9 @@ public class ClusterManager
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(ClusterEvent.class, listenerRegistry);
- clusterDefinitionService.seedNodes()
- .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
+ clusterMetadataService.getClusterMetadata()
+ .getNodes()
+ .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
log.info("Started");
}
@@ -119,11 +127,16 @@ public class ClusterManager
}
@Override
- public void formCluster(Set<ControllerNode> nodes, String ipPrefix) {
+ public void formCluster(Set<ControllerNode> nodes) {
checkNotNull(nodes, "Nodes cannot be null");
checkArgument(!nodes.isEmpty(), "Nodes cannot be empty");
- checkNotNull(ipPrefix, "IP prefix cannot be null");
- clusterDefinitionService.formCluster(nodes, ipPrefix);
+
+ ClusterMetadata metadata = ClusterMetadata.builder()
+ .withName("default")
+ .withControllerNodes(nodes)
+ .withPartitions(buildDefaultPartitions(nodes))
+ .build();
+ clusterMetadataService.setClusterMetadata(metadata);
try {
log.warn("Shutting down container for cluster reconfiguration!");
systemService.reboot("now", SystemService.Swipe.NONE);
@@ -153,4 +166,21 @@ public class ClusterManager
post(event);
}
}
+
+ private static Collection<Partition> buildDefaultPartitions(Collection<ControllerNode> nodes) {
+ List<ControllerNode> sorted = new ArrayList<>(nodes);
+ Collections.sort(sorted, (o1, o2) -> o1.id().toString().compareTo(o2.id().toString()));
+ Collection<Partition> partitions = Lists.newArrayList();
+
+ int length = nodes.size();
+ int count = 3;
+ for (int i = 0; i < length; i++) {
+ Set<NodeId> set = new HashSet<>(count);
+ for (int j = 0; j < count; j++) {
+ set.add(sorted.get((i + j) % length).id());
+ }
+ partitions.add(new Partition("p" + (i + 1), set));
+ }
+ return partitions;
+ }
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
new file mode 100644
index 00000000..a0f7a833
--- /dev/null
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
@@ -0,0 +1,116 @@
+package org.onosproject.cluster.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collection;
+import java.util.Enumeration;
+
+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.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataEventListener;
+import org.onosproject.cluster.ClusterMetadataService;
+import org.onosproject.cluster.ClusterMetadataStore;
+import org.onosproject.cluster.ClusterMetadataStoreDelegate;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of ClusterMetadataService.
+ */
+@Component(immediate = true)
+@Service
+public class ClusterMetadataManager
+ extends AbstractListenerManager<ClusterMetadataEvent, ClusterMetadataEventListener>
+ implements ClusterMetadataService {
+
+ private ControllerNode localNode;
+ private final Logger log = getLogger(getClass());
+
+ private ClusterMetadataStoreDelegate delegate = new InternalStoreDelegate();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterMetadataStore store;
+
+ @Activate
+ public void activate() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
+ establishSelfIdentity();
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(ClusterMetadataEvent.class);
+ log.info("Stopped");
+ }
+
+ @Override
+ public ClusterMetadata getClusterMetadata() {
+ return Versioned.valueOrElse(store.getClusterMetadata(), null);
+ }
+
+ @Override
+ public ControllerNode getLocalNode() {
+ return localNode;
+ }
+
+ @Override
+ public void setClusterMetadata(ClusterMetadata metadata) {
+ checkNotNull(metadata, "Cluster metadata cannot be null");
+ store.setClusterMetadata(metadata);
+ }
+
+ // Store delegate to re-post events emitted from the store.
+ private class InternalStoreDelegate implements ClusterMetadataStoreDelegate {
+ @Override
+ public void notify(ClusterMetadataEvent event) {
+ post(event);
+ }
+ }
+
+ private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
+ Enumeration<NetworkInterface> interfaces =
+ NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface iface = interfaces.nextElement();
+ Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
+ while (inetAddresses.hasMoreElements()) {
+ IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
+ if (controllerNodes.stream()
+ .map(ControllerNode::ip)
+ .anyMatch(nodeIp -> ip.equals(nodeIp))) {
+ return ip;
+ }
+ }
+ }
+ throw new IllegalStateException("Unable to determine local ip");
+ }
+
+ private void establishSelfIdentity() {
+ try {
+ IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
+ localNode = getClusterMetadata().getNodes()
+ .stream()
+ .filter(node -> node.ip().equals(ip))
+ .findFirst()
+ .get();
+ } catch (SocketException e) {
+ throw new IllegalStateException("Cannot determine local IP", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
index 19377cf6..8f601497 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
@@ -112,10 +112,10 @@ public final class OpticalPortOperator implements ConfigOperator {
return new OduCltPortDescription(port, odu.isEnabled(), odu.signalType(), sa);
case PACKET:
case FIBER:
+ case COPPER:
return new DefaultPortDescription(port, descr.isEnabled(), descr.type(),
descr.portSpeed(), sa);
default:
- // this includes copper ports.
log.warn("Unsupported optical port type {} - can't update", descr.type());
return descr;
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
index 137aca1e..0a1af6f5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
@@ -29,9 +29,11 @@ import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -155,6 +157,7 @@ public final class FlowObjectiveCompositionUtil {
return treatmentBuilder.build();
}
+ //CHECKSTYLE:OFF
public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
TrafficSelector trafficSelector) {
@@ -195,14 +198,30 @@ public final class FlowObjectiveCompositionUtil {
} else {
return null;
}
- } else {
- break;
}
default:
break;
}
break;
}
+ case L1MODIFICATION: {
+ L1ModificationInstruction l1 = (L1ModificationInstruction) instruction;
+ switch (l1.subtype()) {
+ case ODU_SIGID:
+ if (criterionMap.containsKey(Criterion.Type.ODU_SIGID)) {
+ if (((OduSignalIdCriterion) criterionMap.get((Criterion.Type.ODU_SIGID))).oduSignalId()
+ .equals(((L1ModificationInstruction.ModOduSignalIdInstruction) l1)
+ .oduSignalId())) {
+ criterionMap.remove(Criterion.Type.ODU_SIGID);
+ } else {
+ return null;
+ }
+ }
+ default:
+ break;
+ }
+ break;
+ }
case L2MODIFICATION: {
L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
switch (l2.subtype()) {
@@ -344,6 +363,7 @@ public final class FlowObjectiveCompositionUtil {
return selectorBuilder.build();
}
+ //CHECKSTYLE:ON
public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
Set<Criterion.Type> typeSet = new HashSet<>();
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
index 5fd1c85d..acc5a5d5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
@@ -24,12 +24,14 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -46,24 +48,23 @@ import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.net.link.LinkStore;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
-import org.onosproject.net.resource.link.MplsLabel;
-import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceType;
import org.slf4j.Logger;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.LinkKey.linkKey;
import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
@@ -78,18 +79,15 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService resourceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkStore linkStore;
+ protected ResourceService resourceService;
protected ApplicationId appId;
@Override
public List<Intent> compile(MplsPathIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
- LinkResourceAllocations allocations = assignMplsLabel(intent);
- List<FlowRule> rules = generateRules(intent, allocations);
+ Map<LinkKey, MplsLabel> labels = assignMplsLabel(intent);
+ List<FlowRule> rules = generateRules(intent, labels);
return Collections.singletonList(new FlowRuleIntent(appId, rules, intent.resources()));
}
@@ -105,39 +103,60 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
intentExtensionService.unregisterCompiler(MplsPathIntent.class);
}
- private LinkResourceAllocations assignMplsLabel(MplsPathIntent intent) {
+ private Map<LinkKey, MplsLabel> assignMplsLabel(MplsPathIntent intent) {
// TODO: do it better... Suggestions?
- Set<Link> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
+ Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
.links().size() - 2);
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
- Link link = intent.path().links().get(i);
+ LinkKey link = linkKey(intent.path().links().get(i));
linkRequest.add(link);
// add the inverse link. I want that the label is reserved both for
// the direct and inverse link
- linkRequest.add(linkStore.getLink(link.dst(), link.src()));
+ linkRequest.add(linkKey(link.dst(), link.src()));
}
- LinkResourceRequest.Builder request = DefaultLinkResourceRequest
- .builder(intent.id(), linkRequest).addMplsRequest();
- LinkResourceAllocations reqMpls = resourceService
- .requestResources(request.build());
- return reqMpls;
- }
+ Map<LinkKey, MplsLabel> labels = findMplsLabels(linkRequest);
+ if (labels.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ List<ResourcePath> resources = labels.entrySet().stream()
+ .map(x -> new ResourcePath(linkKey(x.getKey().src(), x.getKey().src()), x.getValue()))
+ .collect(Collectors.toList());
+ List<org.onosproject.net.newresource.ResourceAllocation> allocations =
+ resourceService.allocate(intent.id(), resources);
+ if (allocations.isEmpty()) {
+ Collections.emptyMap();
+ }
- private MplsLabel getMplsLabel(LinkResourceAllocations allocations, Link link) {
- for (ResourceAllocation allocation : allocations
- .getResourceAllocation(link)) {
- if (allocation.type() == ResourceType.MPLS_LABEL) {
- return ((MplsLabelResourceAllocation) allocation).mplsLabel();
+ return labels;
+ }
+ private Map<LinkKey, MplsLabel> findMplsLabels(Set<LinkKey> links) {
+ Map<LinkKey, MplsLabel> labels = new HashMap<>();
+ for (LinkKey link : links) {
+ Optional<MplsLabel> label = findMplsLabel(link);
+ if (label.isPresent()) {
+ labels.put(link, label.get());
}
}
- log.warn("MPLS label was not assigned successfully");
- return null;
+
+ return labels;
+ }
+
+ private Optional<MplsLabel> findMplsLabel(LinkKey link) {
+ return resourceService.getAvailableResources(new ResourcePath(link)).stream()
+ .filter(x -> x.lastComponent() instanceof MplsLabel)
+ .map(x -> (MplsLabel) x.lastComponent())
+ .findFirst();
+ }
+
+ private MplsLabel getMplsLabel(Map<LinkKey, MplsLabel> labels, LinkKey link) {
+ return labels.get(link);
}
private List<FlowRule> generateRules(MplsPathIntent intent,
- LinkResourceAllocations allocations) {
+ Map<LinkKey, MplsLabel> labels) {
Iterator<Link> links = intent.path().links().iterator();
Link srcLink = links.next();
@@ -149,7 +168,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
// Ingress traffic
// Get the new MPLS label
- MplsLabel mpls = getMplsLabel(allocations, link);
+ MplsLabel mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
MplsLabel prevLabel = mpls;
rules.add(ingressFlow(prev.port(), link, intent, mpls));
@@ -163,7 +182,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
if (links.hasNext()) {
// Transit traffic
// Get the new MPLS label
- mpls = getMplsLabel(allocations, link);
+ mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
rules.add(transitFlow(prev.port(), link, intent,
prevLabel, mpls));
@@ -181,7 +200,8 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule ingressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent, MplsLabel label) {
+ MplsPathIntent intent,
+ MplsLabel label) {
TrafficSelector.Builder ingressSelector = DefaultTrafficSelector
.builder(intent.selector());
@@ -193,10 +213,10 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
.matchMplsLabel(intent.ingressLabel().get());
// Swap the MPLS label
- treat.setMpls(label.label());
+ treat.setMpls(label);
} else {
// Push and set the MPLS label
- treat.pushMpls().setMpls(label.label());
+ treat.pushMpls().setMpls(label);
}
// Add the output action
treat.setOutput(link.src().port());
@@ -205,21 +225,21 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule transitFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel,
- MplsLabel outLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel,
+ MplsLabel outLabel) {
// Ignore the ingress Traffic Selector and use only the MPLS label
// assigned in the previous link
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
// Set the new label only if the label on the packet is
// different
if (!prevLabel.equals(outLabel)) {
- treat.setMpls(outLabel.label());
+ treat.setMpls(outLabel);
}
treat.setOutput(link.src().port());
@@ -227,14 +247,14 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule egressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel) {
// egress point: either set the egress MPLS label or pop the
// MPLS label based on the intent annotations
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
// apply the intent's treatments
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(intent
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
index c6eb7c5a..fce8498c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
@@ -17,6 +17,7 @@ package org.onosproject.net.intent.impl.compiler;
import org.apache.commons.lang3.tuple.Pair;
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.Modified;
import org.apache.felix.scr.annotations.Property;
@@ -70,7 +71,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* An intent compiler for {@link org.onosproject.net.intent.OpticalCircuitIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircuitIntent> {
private static final Logger log = LoggerFactory.getLogger(OpticalCircuitIntentCompiler.class);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
index eb5b4af8..d6725b7c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
@@ -16,7 +16,11 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
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;
@@ -24,6 +28,7 @@ import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
@@ -38,32 +43,29 @@ import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.intent.impl.IntentCompilationException;
+import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceService;
-import org.onosproject.net.resource.ResourceType;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
-import org.onosproject.net.resource.link.LambdaResource;
-import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.LinkKey.linkKey;
/**
* An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
@@ -80,9 +82,6 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService linkResourceService;
-
@Activate
public void activate() {
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
@@ -138,13 +137,12 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
ochSignal = srcOchPort.lambda();
} else {
// Request and reserve lambda on path
- LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
- if (linkAllocs == null) {
+ IndexedLambda lambda = assignWavelength(intent, path);
+ if (lambda == null) {
continue;
}
- LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
- ochSignal = new OchSignal(lambdaAlloc.lambda().toInt(), omsPort.maxFrequency(), omsPort.grid());
+ ochSignal = new OchSignal((int) lambda.index(), omsPort.maxFrequency(), omsPort.grid());
}
// Create installable optical path intent
@@ -171,72 +169,46 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
}
/**
- * Find the lambda allocated to the path.
- *
- * @param path the path
- * @param linkAllocs the link allocations
- * @return lambda allocated to the given path
- */
- private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
- return path.links().stream()
- .flatMap(x -> linkAllocs.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .findFirst()
- .map(x -> (LambdaResourceAllocation) x)
- .orElse(null);
- }
-
- /**
* Request and reserve first available wavelength across path.
*
* @param path path in WDM topology
- * @return first available lambda resource allocation
+ * @return first available lambda allocated
*/
- private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
- LinkResourceRequest.Builder request =
- DefaultLinkResourceRequest.builder(intent.id(), path.links())
- .addLambdaRequest();
-
- LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
-
- if (!checkWavelengthContinuity(allocations, path)) {
- linkResourceService.releaseResources(allocations);
+ private IndexedLambda assignWavelength(Intent intent, Path path) {
+ Set<IndexedLambda> lambdas = findCommonLambdasOverLinks(path.links());
+ if (lambdas.isEmpty()) {
return null;
}
- return allocations;
- }
+ IndexedLambda minLambda = findFirstLambda(lambdas);
+ List<ResourcePath> lambdaResources = path.links().stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(x -> ResourcePath.child(x, minLambda))
+ .collect(Collectors.toList());
- /**
- * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
- * @return true if wavelength continuity is met, false otherwise
- */
- private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
- if (allocations == null) {
- return false;
+ List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
+ if (allocations.isEmpty()) {
+ log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources);
}
- List<LambdaResource> lambdas = path.links().stream()
- .flatMap(x -> allocations.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .map(x -> ((LambdaResourceAllocation) x).lambda())
- .collect(Collectors.toList());
+ return minLambda;
+ }
- LambdaResource lambda = null;
- for (LambdaResource nextLambda: lambdas) {
- if (nextLambda == null) {
- return false;
- }
- if (lambda == null) {
- lambda = nextLambda;
- continue;
- }
- if (!lambda.equals(nextLambda)) {
- return false;
- }
- }
+ private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) {
+ return links.stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(resourceService::getAvailableResources)
+ .map(x -> Iterables.filter(x, r -> r.lastComponent() instanceof IndexedLambda))
+ .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.lastComponent()))
+ .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x))
+ .reduce(Sets::intersection)
+ .orElse(Collections.emptySet());
+ }
- return true;
+ private IndexedLambda findFirstLambda(Set<IndexedLambda> lambdas) {
+ return lambdas.stream()
+ .findFirst()
+ .get();
}
private ConnectPoint staticPort(ConnectPoint connectPoint) {
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
index 5226967f..10fe75ea 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
@@ -41,7 +41,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* An implementation of ResourceService.
*/
-@Component(immediate = true, enabled = false)
+@Component(immediate = true)
@Service
@Beta
public final class ResourceManager implements ResourceService, ResourceAdminService {
@@ -127,6 +127,17 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ
}
@Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ checkNotNull(parent);
+
+ Collection<ResourcePath> children = store.getChildResources(parent);
+ return children.stream()
+ // We access store twice in this method, then the store may be updated by others
+ .filter(x -> !store.getConsumer(x).isPresent())
+ .collect(Collectors.toList());
+ }
+
+ @Override
public boolean isAvailable(ResourcePath resource) {
checkNotNull(resource);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
index 8b9952ed..7eb189e5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
@@ -31,7 +31,6 @@ import org.onosproject.net.resource.ResourceType;
import org.onosproject.net.resource.link.BandwidthResourceAllocation;
import org.onosproject.net.resource.link.BandwidthResourceRequest;
import org.onosproject.net.resource.link.DefaultLinkResourceAllocations;
-import org.onosproject.net.resource.link.LambdaResource;
import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LambdaResourceRequest;
import org.onosproject.net.resource.link.LinkResourceAllocations;
@@ -46,15 +45,12 @@ import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
import org.slf4j.Logger;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
@@ -86,67 +82,6 @@ public class LinkResourceManager
log.info("Stopped");
}
- /**
- * Returns available lambdas on specified link.
- *
- * @param link the link
- * @return available lambdas on specified link
- */
- private Set<LambdaResource> getAvailableLambdas(Link link) {
- checkNotNull(link);
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<LambdaResource> lambdas = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.LAMBDA) {
- lambdas.add(((LambdaResourceAllocation) res).lambda());
- }
- }
- return lambdas;
- }
-
-
- /**
- * Returns available lambdas on specified links.
- *
- * @param links the links
- * @return available lambdas on specified links
- */
- private Iterable<LambdaResource> getAvailableLambdas(Iterable<Link> links) {
- checkNotNull(links);
- Iterator<Link> i = links.iterator();
- checkArgument(i.hasNext());
- Set<LambdaResource> lambdas = new HashSet<>(getAvailableLambdas(i.next()));
- while (i.hasNext()) {
- lambdas.retainAll(getAvailableLambdas(i.next()));
- }
- return lambdas;
- }
-
-
- /**
- * Returns available MPLS label on specified link.
- *
- * @param link the link
- * @return available MPLS labels on specified link
- */
- private Iterable<MplsLabel> getAvailableMplsLabels(Link link) {
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<MplsLabel> mplsLabels = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.MPLS_LABEL) {
-
- mplsLabels.add(((MplsLabelResourceAllocation) res).mplsLabel());
- }
- }
-
- return mplsLabels;
- }
@Override
public LinkResourceAllocations requestResources(LinkResourceRequest req) {
@@ -164,26 +99,23 @@ public class LinkResourceManager
allocs.add(new BandwidthResourceAllocation(br.bandwidth()));
break;
case LAMBDA:
- Iterator<LambdaResource> lambdaIterator =
- getAvailableLambdas(req.links()).iterator();
- if (lambdaIterator.hasNext()) {
- allocs.add(new LambdaResourceAllocation(lambdaIterator.next()));
- } else {
- log.info("Failed to allocate lambda resource.");
- return null;
- }
+ LambdaResourceRequest lr = (LambdaResourceRequest) r;
+ allocs.add(new LambdaResourceAllocation(lr.lambda()));
break;
case MPLS_LABEL:
for (Link link : req.links()) {
if (allocsPerLink.get(link) == null) {
allocsPerLink.put(link, new HashSet<>());
}
- Iterator<MplsLabel> mplsIter = getAvailableMplsLabels(link)
- .iterator();
- if (mplsIter.hasNext()) {
- allocsPerLink.get(link)
- .add(new MplsLabelResourceAllocation(mplsIter
- .next()));
+
+ Optional<MplsLabel> label = req.resources(link).stream()
+ .filter(x -> x.type() == ResourceType.MPLS_LABEL)
+ .map(x -> (MplsLabelResourceRequest) x)
+ .map(MplsLabelResourceRequest::mplsLabel)
+ .findFirst();
+
+ if (label.isPresent()) {
+ allocsPerLink.get(link).add(new MplsLabelResourceAllocation(label.get()));
} else {
log.info("Failed to allocate MPLS resource.");
break;
@@ -258,10 +190,12 @@ public class LinkResourceManager
((BandwidthResourceAllocation) alloc).bandwidth()));
break;
case LAMBDA:
- result.add(new LambdaResourceRequest());
+ result.add(new LambdaResourceRequest(
+ ((LambdaResourceAllocation) alloc).lambda()));
break;
case MPLS_LABEL:
- result.add(new MplsLabelResourceRequest());
+ result.add(new MplsLabelResourceRequest(
+ ((MplsLabelResourceAllocation) alloc).mplsLabel()));
break;
default:
break;
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
new file mode 100644
index 00000000..06b2c81e
--- /dev/null
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 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.net.intent.impl.compiler;
+
+import com.google.common.collect.ImmutableList;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.net.newresource.ResourceAllocation;
+import org.onosproject.net.newresource.ResourceConsumer;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class MockResourceService implements ResourceService {
+
+ private final Map<ResourcePath, ResourceConsumer> assignment = new HashMap<>();
+
+ @Override
+ public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources) {
+ assignment.putAll(
+ resources.stream().collect(Collectors.toMap(x -> x, x -> consumer))
+ );
+
+ return resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean release(List<ResourceAllocation> allocations) {
+ allocations.forEach(x -> assignment.remove(x.resource()));
+
+ return true;
+ }
+
+ @Override
+ public boolean release(ResourceConsumer consumer) {
+ List<ResourcePath> resources = assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ List<ResourceAllocation> allocations = resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+
+ return release(allocations);
+ }
+
+ @Override
+ public Optional<ResourceAllocation> getResourceAllocation(ResourcePath resource) {
+ return Optional.ofNullable(assignment.get(resource))
+ .map(x -> new ResourceAllocation(resource, x));
+ }
+
+ @Override
+ public <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getKey().parent().isPresent())
+ .filter(x -> x.getKey().parent().get().equals(parent))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ ResourcePath resource = ResourcePath.child(parent, MplsLabel.mplsLabel(10));
+ return ImmutableList.of(resource);
+ }
+
+ @Override
+ public boolean isAvailable(ResourcePath resource) {
+ return true;
+ }
+}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
index 771a9883..6cceee12 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
@@ -41,10 +41,8 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.store.trivial.SimpleLinkStore;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -52,6 +50,7 @@ import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.PID;
@@ -61,10 +60,12 @@ public class MplsPathIntentCompilerTest {
private final ApplicationId appId = new TestApplicationId("test");
+ private final ConnectPoint d1pi = connectPoint("s1", 100);
private final ConnectPoint d1p1 = connectPoint("s1", 0);
private final ConnectPoint d2p0 = connectPoint("s2", 0);
private final ConnectPoint d2p1 = connectPoint("s2", 1);
private final ConnectPoint d3p1 = connectPoint("s3", 1);
+ private final ConnectPoint d3pe = connectPoint("s3", 100);
private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
@@ -75,8 +76,10 @@ public class MplsPathIntentCompilerTest {
Optional.of(MplsLabel.mplsLabel(20));
private final List<Link> links = Arrays.asList(
+ createEdgeLink(d1pi, true),
new DefaultLink(PID, d1p1, d2p0, DIRECT),
- new DefaultLink(PID, d2p1, d3p1, DIRECT)
+ new DefaultLink(PID, d2p1, d3p1, DIRECT),
+ createEdgeLink(d3pe, false)
);
private IdGenerator idGenerator = new MockIdGenerator();
@@ -92,8 +95,7 @@ public class MplsPathIntentCompilerTest {
expect(coreService.registerApplication("org.onosproject.net.intent"))
.andReturn(appId);
sut.coreService = coreService;
- sut.linkStore = new SimpleLinkStore();
- sut.resourceService = new IntentTestsMocks.MockResourceService();
+ sut.resourceService = new MockResourceService();
Intent.bindIdGenerator(idGenerator);
@@ -128,7 +130,7 @@ public class MplsPathIntentCompilerTest {
assertThat(compiled, hasSize(1));
Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
- assertThat(rules, hasSize(1));
+ assertThat(rules, hasSize(3));
FlowRule rule = rules.stream()
.filter(x -> x.deviceId().equals(d2p0.deviceId()))
@@ -139,4 +141,5 @@ public class MplsPathIntentCompilerTest {
sut.deactivate();
}
+
}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
index 1a160d98..3e806a73 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -21,11 +21,19 @@ import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPacket;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.packet.ndp.NeighborAdvertisement;
+import org.onlab.packet.ndp.NeighborDiscoveryOptions;
+import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
@@ -66,9 +74,13 @@ import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.anyOf;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
@@ -83,6 +95,8 @@ public class ProxyArpManagerTest {
private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
+ private static final Ip6Address IP3 = Ip6Address.valueOf("1000::1");
+ private static final Ip6Address IP4 = Ip6Address.valueOf("1000::2");
private static final ProviderId PID = new ProviderId("of", "foo");
@@ -90,8 +104,14 @@ public class ProxyArpManagerTest {
private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01");
private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
+ private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
+ private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04");
+ private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
+ private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
+ private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
+ private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1);
private static final DeviceId DID1 = getDeviceId(1);
private static final DeviceId DID2 = getDeviceId(2);
@@ -222,21 +242,29 @@ public class ProxyArpManagerTest {
for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) {
ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
- Ip4Prefix prefix1 =
- Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
- Ip4Address addr1 =
- Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
+
+ // Interface address for IPv4
+ Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
+ Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
- Interface intf1 = new Interface(cp, Sets.newHashSet(ia1),
+
+ // Interface address for IPv6
+ Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
+ Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
+ Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
+ Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::1");
+ InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
+ InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
+
+ Interface intf1 = new Interface(cp, Sets.newHashSet(ia1, ia3),
MacAddress.valueOf(2 * i - 1),
VlanId.vlanId((short) 1));
- Interface intf2 = new Interface(cp, Sets.newHashSet(ia2),
+ Interface intf2 = new Interface(cp, Sets.newHashSet(ia2, ia4),
MacAddress.valueOf(2 * i),
VlanId.NONE);
-
interfaces.add(intf1);
interfaces.add(intf2);
@@ -321,6 +349,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct NDP reply is sent out the correct port.
+ */
+ @Test
+ public void testReplyKnownIpv6() {
+ //Set the return value of isEdgePoint from the edgemanager.
+ isEdgePointReturn = true;
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+
+ assertEquals(1, packetService.packets.size());
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ MAC3, MAC4, IP3, IP4);
+ verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the ARP request is flooded out the correct edge ports.
*/
@@ -337,7 +400,6 @@ public class ProxyArpManagerTest {
.andReturn(Collections.emptySet());
expect(hostService.getHost(HID2)).andReturn(requestor);
-
replay(hostService);
replay(interfaceService);
@@ -355,6 +417,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyUnknownIpv6() {
+ isEdgePointReturn = true;
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup the set of edge ports to be used in the reply method
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is known for that IP address, but is not on the same
* VLAN as the source host.
* Verifies the ARP request is flooded out the correct edge ports.
@@ -388,6 +485,46 @@ public class ProxyArpManagerTest {
verifyFlood(arpRequest);
}
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known for that IP address, but is not on the same
+ * VLAN as the source host.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyDifferentVlanIpv6() {
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup for flood test
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Test ARP request from external network to an internal host.
+ */
@Test
public void testReplyToRequestForUs() {
Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
@@ -422,6 +559,63 @@ public class ProxyArpManagerTest {
verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
}
+ /**
+ * Test NDP request from external network to an internal host.
+ */
+ @Test
+ public void testReplyToRequestForUsIpv6() {
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+ Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
+ Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1");
+ MacAddress firstMac = MacAddress.valueOf(1L);
+ MacAddress secondMac = MacAddress.valueOf(2L);
+
+ Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
+ Collections.singleton(theirIp));
+
+ expect(hostService.getHost(HID2)).andReturn(requestor);
+ expect(hostService.getHostsByIp(ourFirstIp))
+ .andReturn(Collections.singleton(requestor));
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourFirstIp);
+ isEdgePointReturn = true;
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ firstMac,
+ MAC2,
+ ourFirstIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+
+ // Test a request for the second address on that port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourSecondIp);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ secondMac,
+ MAC2,
+ ourSecondIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+ }
+
+ /**
+ * Request for a valid external IPv4 address but coming in the wrong port.
+ */
@Test
public void testReplyExternalPortBadRequest() {
replay(hostService); // no further host service expectations
@@ -442,6 +636,38 @@ public class ProxyArpManagerTest {
assertEquals(0, packetService.packets.size());
}
+ /**
+ * Request for a valid external IPv6 address but coming in the wrong port.
+ */
+ @Test
+ public void testReplyExternalPortBadRequestIpv6() {
+ replay(hostService); // no further host service expectations
+ replay(interfaceService);
+
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ Ip6Address.valueOf("3000::1"));
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+
+ // Request for a valid internal IP address but coming in an external port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ IP3);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
+ * Test ARP request from internal network to an external host.
+ */
@Test
public void testReplyToRequestFromUs() {
Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
@@ -474,6 +700,48 @@ public class ProxyArpManagerTest {
}
/**
+ * Test NDP request from internal network to an external host.
+ */
+ @Test
+ public void testReplyToRequestFromUsIpv6() {
+ Ip6Address ourIp = Ip6Address.valueOf("1000::1");
+ MacAddress ourMac = MacAddress.valueOf(1L);
+ Ip6Address theirIp = Ip6Address.valueOf("1000::100");
+
+ expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(ourIp))
+ .andReturn(Collections.singleton(new Interface(getLocation(1),
+ Collections.singleton(new InterfaceIpAddress(
+ ourIp,
+ IpPrefix.valueOf("1000::1/64"))),
+ ourMac,
+ VLAN1)));
+ expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ // This is a request from something inside our network (like a BGP
+ // daemon) to an external host.
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ ourMac,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ ourIp,
+ theirIp);
+
+ //Ensure the packet is allowed through (it is not to an internal port)
+ isEdgePointReturn = true;
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+ assertEquals(1, packetService.packets.size());
+ verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
+
+ // The same request from a random external port should fail
+ packetService.packets.clear();
+ proxyArp.reply(ndpRequest, getLocation(2));
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is known.
* Verifies the correct ARP request is sent out the correct port.
@@ -502,6 +770,35 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct ARP request is sent out the correct port.
+ */
+ @Test
+ public void testForwardToHostIpv6() {
+ Host host1 = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
+ Collections.singleton(IP3));
+ Host host2 = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
+ Collections.singleton(IP4));
+
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(host1);
+ expect(hostService.getHost(HID4)).andReturn(host2);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.forward(ndpRequest, LOC2);
+
+ assertEquals(1, packetService.packets.size());
+ OutboundPacket packet = packetService.packets.get(0);
+
+ verifyPacketOut(ndpRequest, LOC1, packet);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the correct ARP request is flooded out the correct edge ports.
*/
@@ -526,6 +823,33 @@ public class ProxyArpManagerTest {
}
/**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the correct NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testForwardFloodIpv6() {
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //populate the list of edges when so that when forward hits flood in the manager it contains the values
+ //that should continue on
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.forward(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
* Verifies that the given packet was flooded out all available edge ports,
* except for the input port.
*
@@ -626,6 +950,61 @@ public class ProxyArpManagerTest {
}
/**
+ * Builds an NDP packet with the given parameters.
+ *
+ * @param type NeighborSolicitation or NeighborAdvertisement
+ * @param srcMac source MAC address
+ * @param dstMac destination MAC address, or null if this is a request
+ * @param srcIp source IP address
+ * @param dstIp destination IP address
+ * @return the NDP packet
+ */
+ private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac,
+ Ip6Address srcIp, Ip6Address dstIp) {
+ assertThat(type, anyOf(
+ is(ICMP6.NEIGHBOR_SOLICITATION),
+ is(ICMP6.NEIGHBOR_ADVERTISEMENT)
+ ));
+ assertNotNull(srcMac);
+ assertNotNull(dstMac);
+ assertNotNull(srcIp);
+ assertNotNull(dstIp);
+
+ IPacket ndp;
+ if (type == ICMP6.NEIGHBOR_SOLICITATION) {
+ ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
+ } else {
+ ndp = new NeighborAdvertisement()
+ .setSolicitedFlag((byte) 1)
+ .setOverrideFlag((byte) 1)
+ .setTargetAddress(srcIp.toOctets())
+ .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
+ srcMac.toBytes());
+ }
+
+ ICMP6 icmp6 = new ICMP6();
+ icmp6.setIcmpType(type);
+ icmp6.setIcmpCode((byte) 0);
+ icmp6.setPayload(ndp);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setDestinationAddress(dstIp.toOctets());
+ ipv6.setSourceAddress(srcIp.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
+ ipv6.setHopLimit((byte) 255);
+ ipv6.setPayload(icmp6);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(dstMac);
+ eth.setSourceMACAddress(srcMac);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setVlanID(VLAN1.toShort());
+ eth.setPayload(ipv6);
+
+ return eth;
+ }
+
+ /**
* Test PacketService implementation that simply stores OutboundPackets
* passed to {@link #emit(OutboundPacket)} for later verification.
*/