ONOS-5808: Allocate BW from ConnectivityIntentCompiler and unit tests for partial failure
Change-Id: I2eb3c16efbce619db6d0d2ba415a35752a61ece4
diff --git a/core/api/src/main/java/org/onosproject/net/intent/Key.java b/core/api/src/main/java/org/onosproject/net/intent/Key.java
index b4dab2d..e8e4af7 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/Key.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/Key.java
@@ -19,6 +19,8 @@
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceConsumerId;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
@@ -28,7 +30,7 @@
*/
// TODO maybe pull this up to utils
@Beta
-public abstract class Key implements Comparable<Key> {
+public abstract class Key implements Comparable<Key>, ResourceConsumer {
//TODO consider making this a HashCode object (worry about performance)
private final long hash;
@@ -54,6 +56,8 @@
* Creates a key based on the provided string.
* <p>
* Note: Two keys with equal value, but different appId, are not equal.
+ * Warning: it is caller responsibility to make sure the hashed value of
+ * {@code value} is unique.
* </p>
*
* @param key the provided string
@@ -79,6 +83,11 @@
return new LongKey(key, appId);
}
+ @Override
+ public ResourceConsumerId consumerId() {
+ return ResourceConsumerId.of(hash(), getClass());
+ }
+
private static final class StringKey extends Key {
private final ApplicationId appId;
diff --git a/core/api/src/test/java/org/onosproject/net/NetTestTools.java b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
index d6227a7..dd03a09 100644
--- a/core/api/src/test/java/org/onosproject/net/NetTestTools.java
+++ b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
@@ -76,17 +76,27 @@
}
// Crates a new host with the specified id
- public static Host host(String id, String did) {
+ public static Host host(String id, String did, long port) {
return new DefaultHost(PID, hid(id), valueOf(1234), vlanId((short) 2),
- new HostLocation(did(did), portNumber(1), 321),
+ new HostLocation(did(did), portNumber(port), 321),
new HashSet<>());
}
+ // Crates a new host with the specified id
+ public static Host host(String id, String did) {
+ return host(id, did, 1);
+ }
+
// Short-hand for creating a connection point.
public static ConnectPoint connectPoint(String id, int port) {
return new ConnectPoint(did(id), portNumber(port));
}
+ // Short-hand for creating a connection point.
+ public static ConnectPoint connectPointNoOF(String id, int port) {
+ return new ConnectPoint(DeviceId.deviceId(id), portNumber(port));
+ }
+
// Short-hand for creating a link.
public static Link link(String src, int sp, String dst, int dp) {
return new DefaultLink(PID,
@@ -95,6 +105,14 @@
Link.Type.DIRECT, Link.State.ACTIVE);
}
+ // Short-hand for creating a link.
+ public static Link linkNoPrefixes(String src, int sp, String dst, int dp) {
+ return new DefaultLink(PID,
+ connectPointNoOF(src, sp),
+ connectPointNoOF(dst, dp),
+ Link.Type.DIRECT, Link.State.ACTIVE);
+ }
+
/**
* Short-hand for creating a link.
*
@@ -110,21 +128,21 @@
public static Path createPath(String... ids) {
List<Link> links = new ArrayList<>();
for (int i = 0; i < ids.length - 1; i++) {
- links.add(link(ids[i], i, ids[i + 1], i));
+ links.add(link(ids[i], 2, ids[i + 1], 1));
}
return new DefaultPath(PID, links, ids.length);
}
- // Creates a path that leads through the given devices.
+ // Creates a path that leads through the given hosts.
public static Path createPath(boolean srcIsEdge, boolean dstIsEdge, String... ids) {
List<Link> links = new ArrayList<>();
for (int i = 0; i < ids.length - 1; i++) {
if (i == 0 && srcIsEdge) {
- links.add(DefaultEdgeLink.createEdgeLink(host(ids[i], ids[i + 1]), true));
+ links.add(DefaultEdgeLink.createEdgeLink(host(ids[i], ids[i + 1], 1), true));
} else if (i == ids.length - 2 && dstIsEdge) {
- links.add(DefaultEdgeLink.createEdgeLink(host(ids[i + 1], ids[i]), false));
+ links.add(DefaultEdgeLink.createEdgeLink(host(ids[i + 1], ids[i], 2), false));
} else {
- links.add(link(ids[i], i, ids[i + 1], i));
+ links.add(link(ids[i], 2, ids[i + 1], 1));
}
}
return new DefaultPath(PID, links, ids.length);
diff --git a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
index a944ca6..cef5b67 100644
--- a/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
+++ b/core/api/src/test/java/org/onosproject/net/intent/IntentTestsMocks.java
@@ -17,9 +17,9 @@
import com.google.common.base.MoreObjects;
import org.onlab.graph.Weight;
-import org.onlab.util.Bandwidth;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.HostId;
@@ -38,13 +38,7 @@
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
-import org.onosproject.net.resource.DiscreteResourceId;
-import org.onosproject.net.resource.Resource;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceConsumer;
-import org.onosproject.net.resource.ResourceId;
-import org.onosproject.net.resource.ResourceListener;
-import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.topology.DefaultTopologyEdge;
import org.onosproject.net.topology.DefaultTopologyVertex;
import org.onosproject.net.topology.LinkWeigher;
@@ -52,13 +46,13 @@
import org.onosproject.net.topology.TopologyVertex;
import org.onosproject.store.Timestamp;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@@ -185,8 +179,7 @@
* Mock path service for creating paths within the test.
*
*/
- public static class Mp2MpMockPathService
- extends PathServiceAdapter {
+ public static class Mp2MpMockPathService extends PathServiceAdapter {
final String[] pathHops;
final String[] reversePathHops;
@@ -242,84 +235,74 @@
}
}
- public static final class MockResourceService implements ResourceService {
+ /**
+ * Mock path service for creating paths for MP2SP intent tests, returning
+ * pre-determined paths.
+ */
+ public static class FixedMP2MPMockPathService extends PathServiceAdapter {
- private final double bandwidth;
+ final String[] pathHops;
- public static ResourceService makeBandwidthResourceService(double bandwidth) {
- return new MockResourceService(bandwidth);
- }
+ public static final String DPID_1 = "of:s1";
+ public static final String DPID_2 = "of:s2";
+ public static final String DPID_3 = "of:s3";
+ public static final String DPID_4 = "of:s4";
- private MockResourceService(double bandwidth) {
- this.bandwidth = bandwidth;
+ /**
+ * Constructor that provides a set of hops to mock.
+ *
+ * @param pathHops path hops to mock
+ */
+ public FixedMP2MPMockPathService(String[] pathHops) {
+ this.pathHops = pathHops;
}
@Override
- public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<? extends Resource> resources) {
- return null;
- }
-
- @Override
- public boolean release(List<ResourceAllocation> allocations) {
- return false;
- }
-
- @Override
- public boolean release(ResourceConsumer consumer) {
- return false;
- }
-
- @Override
- public List<ResourceAllocation> getResourceAllocations(ResourceId id) {
- return null;
- }
-
- @Override
- public <T> Collection<ResourceAllocation> getResourceAllocations(DiscreteResourceId parent, Class<T> cls) {
- return null;
- }
-
- @Override
- public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
- return null;
- }
-
- @Override
- public Set<Resource> getAvailableResources(DiscreteResourceId parent) {
- return null;
- }
-
- @Override
- public <T> Set<Resource> getAvailableResources(DiscreteResourceId parent, Class<T> cls) {
- return null;
- }
-
- @Override
- public <T> Set<T> getAvailableResourceValues(DiscreteResourceId parent, Class<T> cls) {
- return null;
- }
-
- @Override
- public Set<Resource> getRegisteredResources(DiscreteResourceId parent) {
- return null;
- }
-
- @Override
- public boolean isAvailable(Resource resource) {
- if (!resource.isTypeOf(Bandwidth.class)) {
- return false;
+ public Set<Path> getPaths(ElementId src, ElementId dst) {
+ List<Link> links = new ArrayList<>();
+ Set<Path> result = new HashSet<>();
+ ProviderId providerId = new ProviderId("of", "foo");
+ DefaultPath path;
+ if (src.toString().equals(DPID_1) && dst.toString().equals(DPID_4)) {
+ links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+ links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+ } else if (src.toString().equals(DPID_2) && dst.toString().equals(DPID_4)) {
+ links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 3));
+ links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+ } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_1)) {
+ links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+ links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
+ } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_2)) {
+ links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
+ links.add(NetTestTools.linkNoPrefixes(pathHops[0], 3, dst.toString(), 1));
+ } else {
+ return result;
}
+ path = new DefaultPath(providerId, links, 3);
+ result.add(path);
- Optional<Double> value = resource.valueAs(Double.class);
- return value.filter(requested -> requested <= bandwidth).isPresent();
+ return result;
}
@Override
- public void addListener(ResourceListener listener) {
- }
+ public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
+ final Set<Path> paths = getPaths(src, dst);
- @Override
- public void removeListener(ResourceListener listener) {
+ for (Path path : paths) {
+ final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
+ final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
+ if (srcDevice != null && dstDevice != null) {
+ final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
+ final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
+ final Link link = link(src.toString(), 1, dst.toString(), 1);
+
+ final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
+ if (weightValue.isNegative()) {
+ return new HashSet<>();
+ }
+ }
+ }
+ return paths;
}
}
@@ -500,5 +483,4 @@
return true;
}
}
-
}
diff --git a/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java b/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
index 436a763..3a8b4e4 100644
--- a/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
+++ b/core/api/src/test/java/org/onosproject/net/resource/MockResourceService.java
@@ -20,6 +20,7 @@
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
import org.onlab.util.Tools;
import org.onosproject.net.TributarySlot;
@@ -35,10 +36,22 @@
public class MockResourceService implements ResourceService {
+ private double bandwidth = 1000.0;
private final Map<Resource, ResourceConsumer> assignment = new HashMap<>();
public Set<Short> availableVlanLabels = new HashSet<>();
public Set<Integer> availableMplsLabels = new HashSet<>();
+ public MockResourceService(){}
+
+ // To express a custom bandwidth available (in bps)
+ public static ResourceService makeCustomBandwidthResourceService(double bandwidth) {
+ return new MockResourceService(bandwidth);
+ }
+
+ private MockResourceService(double bandwidth) {
+ this.bandwidth = bandwidth;
+ }
+
@Override
public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<? extends Resource> resources) {
assignment.putAll(
@@ -181,6 +194,11 @@
@Override
public boolean isAvailable(Resource resource) {
+ if (resource.isTypeOf(Bandwidth.class)) {
+ // If there's is enough bandwidth available return true; false otherwise
+ Optional<Double> value = resource.valueAs(Double.class);
+ return value.filter(requested -> requested <= bandwidth).isPresent();
+ }
return true;
}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
index 6f2ed13..7b79f95 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentManager.java
@@ -51,8 +51,9 @@
import org.onosproject.net.intent.impl.phase.FinalIntentProcessPhase;
import org.onosproject.net.intent.impl.phase.IntentProcessPhase;
import org.onosproject.net.intent.impl.phase.Skipped;
-import org.osgi.service.component.ComponentContext;
+import org.onosproject.net.resource.ResourceConsumer;
import org.onosproject.net.resource.ResourceService;
+import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Collection;
@@ -344,9 +345,8 @@
post(event);
switch (event.type()) {
case WITHDRAWN:
- // release resources allocated to withdrawn intent
- if (!resourceService.release(event.subject().id())) {
- log.error("Failed to release resources allocated to {}", event.subject().id());
+ if (!skipReleaseResourcesOnWithdrawal) {
+ releaseResources(event.subject());
}
break;
default:
@@ -363,6 +363,41 @@
public void onUpdate(IntentData intentData) {
trackerService.trackIntent(intentData);
}
+
+ private void releaseResources(Intent intent) {
+ // If a resource group is set on the intent, the resource consumer is
+ // set equal to it. Otherwise it's set to the intent key
+ ResourceConsumer resourceConsumer =
+ intent.resourceGroup() != null ? intent.resourceGroup() : intent.key();
+
+ // By default the resource doesn't get released
+ boolean removeResource = false;
+
+ if (intent.resourceGroup() == null) {
+ // If the intent doesn't have a resource group, it means the
+ // resource was registered using the intent key, so it can be
+ // released
+ removeResource = true;
+ } else {
+ // When a resource group is set, we make sure there are no other
+ // intents using the same resource group, before deleting the
+ // related resources.
+ Long remainingIntents =
+ Tools.stream(store.getIntents())
+ .filter(i -> i.resourceGroup().equals(intent.resourceGroup()))
+ .count();
+ if (remainingIntents == 0) {
+ removeResource = true;
+ }
+ }
+
+ if (removeResource) {
+ // Release resources allocated to withdrawn intent
+ if (!resourceService.release(resourceConsumer)) {
+ log.error("Failed to release resources allocated to {}", resourceConsumer);
+ }
+ }
+ }
}
// Store delegate enabled only when performing intent throughput tests
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
index 43923b5..7d3c312 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
@@ -17,32 +17,48 @@
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.graph.DefaultEdgeWeigher;
import org.onlab.graph.ScalarWeight;
import org.onlab.graph.Weight;
+import org.onlab.util.Bandwidth;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.DisjointPath;
import org.onosproject.net.ElementId;
import org.onosproject.net.Path;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.ConnectivityIntent;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.HashedPathSelectionConstraint;
import org.onosproject.net.intent.impl.PathNotFoundException;
-import org.onosproject.net.resource.ResourceQueryService;
import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.resource.Resource;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceConsumer;
+import org.onosproject.net.resource.ResourceId;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyVertex;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Base class for compilers of various
@@ -54,6 +70,11 @@
private static final ProviderId PID = new ProviderId("core", "org.onosproject.core", true);
+ private static final Logger log = LoggerFactory.getLogger(ConnectivityIntentCompiler.class);
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@@ -61,7 +82,7 @@
protected PathService pathService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ResourceQueryService resourceService;
+ protected ResourceService resourceService;
/**
* Returns an edge-weight capable of evaluating links on the basis of the
@@ -164,6 +185,155 @@
}
/**
+ * Allocates the bandwidth specified as intent constraint on each link
+ * composing the intent, if a bandwidth constraint is specified.
+ *
+ * @param intent the intent requesting bandwidth allocation
+ * @param connectPoints the connect points composing the intent path computed
+ */
+ protected void allocateBandwidth(ConnectivityIntent intent,
+ List<ConnectPoint> connectPoints) {
+ // Retrieve bandwidth constraint if exists
+ List<Constraint> constraints = intent.constraints();
+
+ if (constraints == null) {
+ return;
+ }
+
+ Optional<Constraint> constraint =
+ constraints.stream()
+ .filter(c -> c instanceof BandwidthConstraint)
+ .findAny();
+
+ // If there is no bandwidth constraint continue
+ if (!constraint.isPresent()) {
+ return;
+ }
+
+ BandwidthConstraint bwConstraint = (BandwidthConstraint) constraint.get();
+
+ double bw = bwConstraint.bandwidth().bps();
+
+ // If a resource group is set on the intent, the resource consumer is
+ // set equal to it. Otherwise it's set to the intent key
+ ResourceConsumer newResourceConsumer =
+ intent.resourceGroup() != null ? intent.resourceGroup() : intent.key();
+
+ // Get the list of current resource allocations
+ Collection<ResourceAllocation> resourceAllocations =
+ resourceService.getResourceAllocations(newResourceConsumer);
+
+ // Get the list of resources already allocated from resource allocations
+ List<Resource> resourcesAllocated =
+ resourcesFromAllocations(resourceAllocations);
+
+ // Get the list of resource ids for resources already allocated
+ List<ResourceId> idsResourcesAllocated = resourceIds(resourcesAllocated);
+
+ // Create the list of incoming resources requested. Exclude resources
+ // already allocated.
+ List<Resource> incomingResources =
+ resources(connectPoints, bw).stream()
+ .filter(r -> !resourcesAllocated.contains(r))
+ .collect(Collectors.toList());
+
+ if (incomingResources.isEmpty()) {
+ return;
+ }
+
+ // Create the list of resources to be added, meaning their key is not
+ // present in the resources already allocated
+ List<Resource> resourcesToAdd =
+ incomingResources.stream()
+ .filter(r -> !idsResourcesAllocated.contains(r.id()))
+ .collect(Collectors.toList());
+
+ // Resources to updated are all the new valid resources except the
+ // resources to be added
+ List<Resource> resourcesToUpdate = Lists.newArrayList(incomingResources);
+ resourcesToUpdate.removeAll(resourcesToAdd);
+
+ // If there are no resources to update skip update procedures
+ if (!resourcesToUpdate.isEmpty()) {
+ // Remove old resources that need to be updated
+ // TODO: use transaction updates when available in the resource service
+ List<ResourceAllocation> resourceAllocationsToUpdate =
+ resourceAllocations.stream()
+ .filter(rA -> resourceIds(resourcesToUpdate).contains(rA.resource().id()))
+ .collect(Collectors.toList());
+ log.debug("Releasing bandwidth for intent {}: {} bps", newResourceConsumer, resourcesToUpdate);
+ resourceService.release(resourceAllocationsToUpdate);
+
+ // Update resourcesToAdd with the list of both the new resources and
+ // the resources to update
+ resourcesToAdd.addAll(resourcesToUpdate);
+ }
+
+ // Look also for resources allocated using the intent key and -if any-
+ // remove them
+ if (intent.resourceGroup() != null) {
+ // Get the list of current resource allocations made by intent key
+ Collection<ResourceAllocation> resourceAllocationsByKey =
+ resourceService.getResourceAllocations(intent.key());
+
+ resourceService.release(Lists.newArrayList(resourceAllocationsByKey));
+ }
+
+ // Allocate resources
+ log.debug("Allocating bandwidth for intent {}: {} bps", newResourceConsumer, resourcesToAdd);
+ List<ResourceAllocation> allocations =
+ resourceService.allocate(newResourceConsumer, resourcesToAdd);
+
+ if (allocations.isEmpty()) {
+ log.debug("No resources allocated for intent {}", newResourceConsumer);
+ }
+
+ log.debug("Done allocating bandwidth for intent {}", newResourceConsumer);
+ }
+
+ /**
+ * Produces a list of resources from a list of resource allocations.
+ *
+ * @param rAs the list of resource allocations
+ * @return a list of resources retrieved from the resource allocations given
+ */
+ private static List<Resource> resourcesFromAllocations(Collection<ResourceAllocation> rAs) {
+ return rAs.stream()
+ .map(ResourceAllocation::resource)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Creates a list of continuous bandwidth resources given a list of connect
+ * points and a bandwidth.
+ *
+ * @param cps the list of connect points
+ * @param bw the bandwidth expressed as a double
+ * @return the list of resources
+ */
+ private static List<Resource> resources(List<ConnectPoint> cps, double bw) {
+ return cps.stream()
+ // Make sure the element id is a valid device id
+ .filter(cp -> cp.elementId() instanceof DeviceId)
+ // Create a continuous resource for each CP we're going through
+ .map(cp -> Resources.continuous(cp.deviceId(), cp.port(),
+ Bandwidth.class).resource(bw))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Returns a list of resource ids given a list of resources.
+ *
+ * @param resources the list of resources
+ * @return the list of resource ids retrieved from the resources given
+ */
+ private static List<ResourceId> resourceIds(List<Resource> resources) {
+ return resources.stream()
+ .map(Resource::id)
+ .collect(Collectors.toList());
+ }
+
+ /**
* Edge-weight capable of evaluating link cost using a set of constraints.
*/
protected class ConstraintBasedLinkWeigher extends DefaultEdgeWeigher<TopologyVertex, TopologyEdge>
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
index f2283a0..4d6270a 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
@@ -22,6 +22,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
@@ -35,7 +36,6 @@
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompilationException;
import org.onosproject.net.intent.LinkCollectionIntent;
-import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
import org.slf4j.Logger;
@@ -45,6 +45,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.onosproject.net.Link.Type.EDGE;
import static org.onosproject.net.flow.DefaultTrafficSelector.builder;
@@ -115,22 +116,6 @@
.build();
}
- // Creates a path intent from the specified path and original connectivity intent.
- private Intent createPathIntent(Path path, Host src, Host dst,
- HostToHostIntent intent) {
- TrafficSelector selector = builder(intent.selector())
- .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build();
- return PathIntent.builder()
- .appId(intent.appId())
- .key(intent.key())
- .selector(selector)
- .treatment(intent.treatment())
- .path(path)
- .constraints(intent.constraints())
- .priority(intent.priority())
- .build();
- }
-
private FilteredConnectPoint getFilteredPointFromLink(Link link) {
FilteredConnectPoint filteredConnectPoint;
if (link.src().elementId() instanceof DeviceId) {
@@ -147,14 +132,13 @@
Host src,
Host dst,
HostToHostIntent intent) {
- /*
- * The path contains also the edge links, these are not necessary
- * for the LinkCollectionIntent.
- */
- Set<Link> coreLinks = path.links()
- .stream()
- .filter(link -> !link.type().equals(EDGE))
- .collect(Collectors.toSet());
+ // Try to allocate bandwidth
+ List<ConnectPoint> pathCPs =
+ path.links().stream()
+ .flatMap(l -> Stream.of(l.src(), l.dst()))
+ .collect(Collectors.toList());
+
+ allocateBandwidth(intent, pathCPs);
Link ingressLink = path.links().get(0);
Link egressLink = path.links().get(path.links().size() - 1);
@@ -167,6 +151,15 @@
.matchEthDst(dst.mac())
.build();
+ /*
+ * The path contains also the edge links, these are not necessary
+ * for the LinkCollectionIntent.
+ */
+ Set<Link> coreLinks = path.links()
+ .stream()
+ .filter(link -> !link.type().equals(EDGE))
+ .collect(Collectors.toSet());
+
return LinkCollectionIntent.builder()
.key(intent.key())
.appId(intent.appId())
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index 3b4dca9..7e6cf3d 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -38,6 +38,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
@@ -85,7 +87,7 @@
continue;
}
- Path path = getPath(intent, ingressPoint.deviceId(), intent.egressPoint().deviceId());
+ Path path = getPath(intent, ingressPoint.deviceId(), egressPoint.deviceId());
if (path != null) {
hasPaths = true;
@@ -106,6 +108,23 @@
}
}
+ // Allocate bandwidth on existing paths if a bandwidth constraint is set
+ List<ConnectPoint> ingressCPs =
+ intent.filteredIngressPoints().stream()
+ .map(fcp -> fcp.connectPoint())
+ .collect(Collectors.toList());
+ ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+ List<ConnectPoint> pathCPs =
+ links.values().stream()
+ .flatMap(l -> Stream.of(l.src(), l.dst()))
+ .collect(Collectors.toList());
+
+ pathCPs.addAll(ingressCPs);
+ pathCPs.add(egressCP);
+
+ allocateBandwidth(intent, pathCPs);
+
if (!hasPaths) {
throw new IntentException("Cannot find any path between ingress and egress points.");
} else if (!allowMissingPaths && missingSomePaths) {
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
index 94fe6ed..10e24eb 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
@@ -73,6 +73,8 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
@@ -122,8 +124,8 @@
@Override
public List<Intent> compile(PointToPointIntent intent, List<Intent> installable) {
log.trace("compiling {} {}", intent, installable);
- ConnectPoint ingressPoint = intent.ingressPoint();
- ConnectPoint egressPoint = intent.egressPoint();
+ ConnectPoint ingressPoint = intent.filteredIngressPoint().connectPoint();
+ ConnectPoint egressPoint = intent.filteredEgressPoint().connectPoint();
if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
return createZeroHopLinkCollectionIntent(intent);
@@ -157,6 +159,15 @@
intent));
}
+ /**
+ * Creates an unprotected intent.
+ * @param ingressPoint the ingress connect point
+ * @param egressPoint the egress connect point
+ * @param intent the original intent
+ * @return the compilation result
+ * @deprecated 1.10.0
+ */
+ @Deprecated
private List<Intent> createUnprotectedIntent(ConnectPoint ingressPoint,
ConnectPoint egressPoint,
PointToPointIntent intent) {
@@ -177,6 +188,20 @@
Path path = getPathOrException(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
intent.filteredEgressPoint().connectPoint().deviceId());
+ // Allocate bandwidth if a bandwidth constraint is set
+ ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+ ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+ List<ConnectPoint> pathCPs =
+ path.links().stream()
+ .flatMap(l -> Stream.of(l.src(), l.dst()))
+ .collect(Collectors.toList());
+
+ pathCPs.add(ingressCP);
+ pathCPs.add(egressCP);
+
+ allocateBandwidth(intent, pathCPs);
+
return asList(createLinkCollectionIntent(ImmutableSet.copyOf(path.links()),
path.cost(),
intent));
@@ -292,6 +317,21 @@
if (reusableIntents != null && reusableIntents.size() > 1) {
return reusableIntents;
} else {
+ // Allocate bandwidth if a bandwidth constraint is set
+ ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+ ConnectPoint egressCP = intent.filteredEgressPoint().connectPoint();
+
+ List<ConnectPoint> pathCPs =
+ onlyPath.links().stream()
+ .flatMap(l -> Stream.of(l.src(), l.dst()))
+ .collect(Collectors.toList());
+
+ pathCPs.add(ingressCP);
+ pathCPs.add(egressCP);
+
+ // Allocate bandwidth if a bandwidth constraint is set
+ allocateBandwidth(intent, pathCPs);
+
links.add(createEdgeLink(ingressPoint, true));
links.addAll(onlyPath.links());
links.add(createEdgeLink(egressPoint, false));
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
index 504e4f3..369e52b 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
@@ -34,6 +34,8 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
@@ -76,6 +78,7 @@
}
Path path = getPath(intent, intent.ingressPoint().deviceId(), egressPoint.deviceId());
+
if (path != null) {
hasPaths = true;
links.addAll(path.links());
@@ -84,6 +87,23 @@
}
}
+ // Allocate bandwidth if a bandwidth constraint is set
+ ConnectPoint ingressCP = intent.filteredIngressPoint().connectPoint();
+ List<ConnectPoint> egressCPs =
+ intent.filteredEgressPoints().stream()
+ .map(fcp -> fcp.connectPoint())
+ .collect(Collectors.toList());
+
+ List<ConnectPoint> pathCPs =
+ links.stream()
+ .flatMap(l -> Stream.of(l.src(), l.dst()))
+ .collect(Collectors.toList());
+
+ pathCPs.add(ingressCP);
+ pathCPs.addAll(egressCPs);
+
+ allocateBandwidth(intent, pathCPs);
+
if (!hasPaths) {
throw new IntentException("Cannot find any path between ingress and egress points.");
} else if (!allowMissingPaths && missingSomePaths) {
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
index d6333ff..a0104a1 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompilerTest.java
@@ -16,27 +16,40 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.HostToHostIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.resource.ContinuousResource;
import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -44,10 +57,8 @@
import static org.easymock.EasyMock.*;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertEquals;
import static org.onosproject.net.NetTestTools.hid;
import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
@@ -55,6 +66,8 @@
* Unit tests for the HostToHost intent compiler.
*/
public class HostToHostIntentCompilerTest extends AbstractIntentTest {
+ private static final ApplicationId APPID = new TestApplicationId("foo");
+
private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
private static final String HOST_ONE_VLAN = "None";
@@ -62,24 +75,29 @@
private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
- private static final int PORT_1 = 1;
+ private static final String S1 = "s1";
+ private static final String S2 = "s2";
+ private static final String S3 = "s3";
+ private static final String S4 = "s4";
+ private static final String S5 = "s5";
+ private static final String S6 = "s6";
+ private static final String S7 = "s7";
+ private static final String S8 = "s8";
- private static final String HOP_1 = "h1";
- private static final String HOP_2 = "h2";
- private static final String HOP_3 = "h3";
- private static final String HOP_4 = "h4";
- private static final String HOP_5 = "h5";
- private static final String HOP_6 = "h6";
- private static final String HOP_7 = "h7";
- private static final String HOP_8 = "h8";
+ private static final DeviceId DID_S1 = DeviceId.deviceId("of:" + S1);
+ private static final DeviceId DID_S2 = DeviceId.deviceId("of:" + S2);
+ private static final DeviceId DID_S3 = DeviceId.deviceId("of:" + S3);
+ private static final DeviceId DID_S8 = DeviceId.deviceId("of:" + S8);
- private static final ApplicationId APPID = new TestApplicationId("foo");
+ private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_2 = PortNumber.portNumber(2);
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private HostId hostOneId = HostId.hostId(HOST_ONE);
private HostId hostTwoId = HostId.hostId(HOST_TWO);
+
private HostService mockHostService;
@Override
@@ -105,17 +123,34 @@
/**
* Creates a HostToHost intent based on two host Ids.
*
- * @param oneIdString string for host one id
- * @param twoIdString string for host two id
+ * @param oneIdString the string for host one id
+ * @param twoIdString the string for host two id
* @return HostToHostIntent for the two hosts
*/
- private HostToHostIntent makeIntent(String oneIdString, String twoIdString) {
+ private HostToHostIntent makeIntent(String oneIdString,
+ String twoIdString) {
+ return makeIntent(oneIdString, twoIdString, Lists.newArrayList());
+ }
+
+ /**
+ * Creates a HostToHost intent based on two host Ids and a list of
+ * constraints.
+ *
+ * @param oneIdString the string for host one id
+ * @param twoIdString the string for host two id
+ * @param constraints the intent constraints
+ * @return HostToHostIntent for the two hosts
+ */
+ private HostToHostIntent makeIntent(String oneIdString,
+ String twoIdString,
+ List<Constraint> constraints) {
return HostToHostIntent.builder()
.appId(APPID)
.one(hid(oneIdString))
.two(hid(twoIdString))
.selector(selector)
.treatment(treatment)
+ .constraints(constraints)
.build();
}
@@ -126,11 +161,29 @@
* @return HostToHost intent compiler
*/
private HostToHostIntentCompiler makeCompiler(String[] hops) {
+ return makeCompiler(hops, null);
+ }
+
+ /**
+ * Creates a compiler for HostToHost intents.
+ *
+ * @param hops string array describing the path hops to use when compiling
+ * @param resourceService the resource service
+ * @return HostToHost intent compiler
+ */
+ private HostToHostIntentCompiler makeCompiler(String[] hops,
+ ResourceService resourceService) {
HostToHostIntentCompiler compiler =
new HostToHostIntentCompiler();
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
compiler.hostService = mockHostService;
- compiler.resourceService = new MockResourceService();
+
+ if (resourceService == null) {
+ compiler.resourceService = new MockResourceService();
+ } else {
+ compiler.resourceService = resourceService;
+ }
+
return compiler;
}
@@ -145,7 +198,7 @@
HOST_TWO);
assertThat(intent, is(notNullValue()));
- String[] hops = {HOST_ONE, HOP_1, HOP_2, HOP_3, HOP_4, HOP_5, HOP_6, HOP_7, HOP_8, HOST_TWO};
+ String[] hops = {HOST_ONE, S1, S2, S3, S4, S5, S6, S7, S8, HOST_TWO};
HostToHostIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -161,34 +214,34 @@
Set<Link> links = forwardLCIntent.links();
assertThat(links, hasSize(7));
Set<FilteredConnectPoint> ingressPoints = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint(HOP_1, PORT_1))
+ new FilteredConnectPoint(new ConnectPoint(DID_S1, PORT_1))
);
assertThat(forwardLCIntent.filteredIngressPoints(), is(ingressPoints));
- assertThat(links, linksHasPath(HOP_1, HOP_2));
- assertThat(links, linksHasPath(HOP_2, HOP_3));
- assertThat(links, linksHasPath(HOP_3, HOP_4));
- assertThat(links, linksHasPath(HOP_4, HOP_5));
- assertThat(links, linksHasPath(HOP_5, HOP_6));
- assertThat(links, linksHasPath(HOP_6, HOP_7));
- assertThat(links, linksHasPath(HOP_7, HOP_8));
+ assertThat(links, linksHasPath(S1, S2));
+ assertThat(links, linksHasPath(S2, S3));
+ assertThat(links, linksHasPath(S3, S4));
+ assertThat(links, linksHasPath(S4, S5));
+ assertThat(links, linksHasPath(S5, S6));
+ assertThat(links, linksHasPath(S6, S7));
+ assertThat(links, linksHasPath(S7, S8));
Set<FilteredConnectPoint> egressPoints = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint(HOP_8, PORT_1))
+ new FilteredConnectPoint(new ConnectPoint(DID_S8, PORT_2))
);
assertThat(forwardLCIntent.filteredEgressPoints(), is(egressPoints));
LinkCollectionIntent reverseLCIntent = (LinkCollectionIntent) reverseIntent;
links = reverseLCIntent.links();
assertThat(reverseLCIntent.links(), hasSize(7));
- ingressPoints = ImmutableSet.of(new FilteredConnectPoint(connectPoint(HOP_8, PORT_1)));
+ ingressPoints = ImmutableSet.of(new FilteredConnectPoint(new ConnectPoint(DID_S8, PORT_2)));
assertThat(reverseLCIntent.filteredIngressPoints(), is(ingressPoints));
- assertThat(links, linksHasPath(HOP_2, HOP_1));
- assertThat(links, linksHasPath(HOP_3, HOP_2));
- assertThat(links, linksHasPath(HOP_4, HOP_3));
- assertThat(links, linksHasPath(HOP_5, HOP_4));
- assertThat(links, linksHasPath(HOP_6, HOP_5));
- assertThat(links, linksHasPath(HOP_7, HOP_6));
- assertThat(links, linksHasPath(HOP_8, HOP_7));
- egressPoints = ImmutableSet.of(new FilteredConnectPoint(connectPoint(HOP_1, PORT_1)));
+ assertThat(links, linksHasPath(S2, S1));
+ assertThat(links, linksHasPath(S3, S2));
+ assertThat(links, linksHasPath(S4, S3));
+ assertThat(links, linksHasPath(S5, S4));
+ assertThat(links, linksHasPath(S6, S5));
+ assertThat(links, linksHasPath(S7, S6));
+ assertThat(links, linksHasPath(S8, S7));
+ egressPoints = ImmutableSet.of(new FilteredConnectPoint(new ConnectPoint(DID_S1, PORT_1)));
assertThat(reverseLCIntent.filteredEgressPoints(), is(egressPoints));
@@ -196,4 +249,63 @@
result.stream().map(Intent::key).collect(Collectors.toList()),
everyItem(is(intent.key())));
}
+
+ /**
+ * Tests if bandwidth resources get allocated correctly.
+ */
+ @Test
+ public void testBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+ final double bpsToReserve = 100.0;
+
+ ContinuousResource resourceSw1P1 =
+ Resources.continuous(DID_S1, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw1P2 =
+ Resources.continuous(DID_S1, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P1 =
+ Resources.continuous(DID_S2, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P2 =
+ Resources.continuous(DID_S2, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P1 =
+ Resources.continuous(DID_S3, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P2 =
+ Resources.continuous(DID_S3, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+
+ String[] hops = {HOST_ONE, S1, S2, S3, HOST_TWO};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+ final HostToHostIntent intent = makeIntent(HOST_ONE, HOST_TWO, constraints);
+
+ HostToHostIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceAllocation rAOne = new ResourceAllocation(resourceSw1P1, intentKey);
+ ResourceAllocation rATwo = new ResourceAllocation(resourceSw1P2, intentKey);
+ ResourceAllocation rAThree = new ResourceAllocation(resourceSw2P1, intentKey);
+ ResourceAllocation rAFour = new ResourceAllocation(resourceSw2P2, intentKey);
+ ResourceAllocation rAFive = new ResourceAllocation(resourceSw3P1, intentKey);
+ ResourceAllocation rASix = new ResourceAllocation(resourceSw3P2, intentKey);
+
+ Set<ResourceAllocation> expectedresourceAllocations =
+ ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+ assertThat(resourceAllocations, hasSize(6));
+ assertEquals(expectedresourceAllocations, resourceAllocations);
+ }
}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
index 2eb4d9f..6c7d9c1 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
@@ -16,24 +16,42 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import org.hamcrest.Matchers;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.PartialFailureConstraint;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.topology.PathService;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -42,7 +60,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.junit.Assert.assertEquals;
import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
@@ -52,6 +70,26 @@
private static final ApplicationId APPID = new TestApplicationId("foo");
+ private static final String S1 = "s1";
+ private static final String S2 = "s2";
+ private static final String S3 = "s3";
+ private static final String S4 = "s4";
+ private static final String S5 = "s5";
+ private static final String S6 = "s6";
+ private static final String S7 = "s7";
+ private static final String S8 = "s8";
+
+ private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+ private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+ private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+ private static final DeviceId DID_4 = DeviceId.deviceId("of:" + S4);
+ private static final DeviceId DID_5 = DeviceId.deviceId("of:" + S5);
+ private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+ private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_2 = PortNumber.portNumber(2);
+ private static final PortNumber PORT_3 = PortNumber.portNumber(3);
+
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
@@ -59,43 +97,65 @@
* Creates a MultiPointToSinglePoint intent for a group of ingress points
* and an egress point.
*
- * @param ingressIds array of ingress device ids
- * @param egressId device id of the egress point
- * @return MultiPointToSinglePoint intent
+ * @param ingress the filtered ingress points
+ * @param egress the filtered egress point
+ * @return a MultiPointToSinglePoint intent
*/
- private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
- Set<ConnectPoint> ingressPoints = new HashSet<>();
- ConnectPoint egressPoint = connectPoint(egressId, 2);
-
- for (String ingressId : ingressIds) {
- ingressPoints.add(connectPoint(ingressId, 1));
- }
-
- return MultiPointToSinglePointIntent.builder()
- .appId(APPID)
- .selector(selector)
- .treatment(treatment)
- .ingressPoints(ingressPoints)
- .egressPoint(egressPoint)
- .build();
+ private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+ FilteredConnectPoint egress) {
+ return makeIntent(ingress, egress, Lists.newArrayList());
}
/**
- * Generate MultiPointToSinglePointIntent with filtered connection point.
+ * Generates a MultiPointToSinglePointIntent with filtered connection point.
*
* @param ingress filtered ingress points
* @param egress filtered egress point
* @return
*/
- private MultiPointToSinglePointIntent makeFilteredConnectPointIntent(Set<FilteredConnectPoint> ingress,
- FilteredConnectPoint egress,
- TrafficSelector trafficSelector) {
+ private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+ FilteredConnectPoint egress,
+ TrafficSelector trafficSelector) {
+ return makeIntent(ingress,
+ egress,
+ trafficSelector,
+ Lists.newArrayList());
+ }
+
+ /**
+ * Creates a MultiPointToSinglePoint intent for a group of ingress points,
+ * egress points and a list of constraints.
+ *
+ * @param ingress the filtered ingress point
+ * @param egress the filtered egress point
+ * @param constraints the list of intent constraints
+ * @return a MultiPointToSinglePoint intent
+ */
+ private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+ FilteredConnectPoint egress,
+ List<Constraint> constraints) {
+ return makeIntent(ingress, egress, selector, constraints);
+ }
+
+ /**
+ * Generates a MultiPointToSinglePointIntent with filtered connection point.
+ *
+ * @param ingress filtered ingress points
+ * @param egress filtered egress point
+ * @param constraints the list of intent constraints
+ * @return
+ */
+ private MultiPointToSinglePointIntent makeIntent(Set<FilteredConnectPoint> ingress,
+ FilteredConnectPoint egress,
+ TrafficSelector trafficSelector,
+ List<Constraint> constraints) {
return MultiPointToSinglePointIntent.builder()
.appId(APPID)
.treatment(treatment)
.selector(trafficSelector)
.filteredIngressPoints(ingress)
.filteredEgressPoint(egress)
+ .constraints(constraints)
.build();
}
@@ -103,14 +163,41 @@
* Creates a compiler for MultiPointToSinglePoint intents.
*
* @param hops hops to use while computing paths for this intent
+ * @param pathService the path service
+ * @param resourceService the resource service
+ * @return MultiPointToSinglePoint intent
+ */
+ private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops,
+ PathService pathService,
+ ResourceService resourceService) {
+ MultiPointToSinglePointIntentCompiler compiler =
+ new MultiPointToSinglePointIntentCompiler();
+
+ compiler.deviceService = new IntentTestsMocks.MockDeviceService();
+
+ if (pathService == null) {
+ compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+ } else {
+ compiler.pathService = pathService;
+ }
+
+ if (resourceService == null) {
+ compiler.resourceService = new MockResourceService();
+ } else {
+ compiler.resourceService = resourceService;
+ }
+
+ return compiler;
+ }
+
+ /**
+ * Creates a compiler for MultiPointToSinglePoint intents.
+ *
+ * @param hops hops to use while computing paths for this intent
* @return MultiPointToSinglePoint intent
*/
private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops) {
- MultiPointToSinglePointIntentCompiler compiler =
- new MultiPointToSinglePointIntentCompiler();
- compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
- compiler.deviceService = new IntentTestsMocks.MockDeviceService();
- return compiler;
+ return makeCompiler(hops, null, null);
}
/**
@@ -118,14 +205,15 @@
*/
@Test
public void testSingleLongPathCompilation() {
-
- String[] ingress = {"ingress"};
- String egress = "egress";
+ Set<FilteredConnectPoint> ingress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)));
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
- String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8"};
+ String[] hops = {S2, S3, S4, S5, S6, S7};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -137,14 +225,14 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(9));
- assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
- assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
- assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
- assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
- assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
- assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
- assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
+ assertThat(linkIntent.links(), hasSize(7));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ assertThat(linkIntent.links(), linksHasPath(S4, S5));
+ assertThat(linkIntent.links(), linksHasPath(S5, S6));
+ assertThat(linkIntent.links(), linksHasPath(S6, S7));
+ assertThat(linkIntent.links(), linksHasPath(S7, S8));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
@@ -155,13 +243,52 @@
*/
@Test
public void testTwoIngressCompilation() {
- String[] ingress = {"ingress1", "ingress2"};
- String egress = "egress";
+ Set<FilteredConnectPoint> ingress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)));
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1));
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
- final String[] hops = {"inner1", "inner2"};
+ final String[] hops = {S3};
+ MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent, null);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(3));
+ assertThat(linkIntent.links(), linksHasPath(S1, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ }
+ assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+ }
+
+ /**
+ * Tests a large number of ingress points that share a common path to the
+ * egress point.
+ */
+ @Test
+ public void testMultiIngressCompilation() {
+ Set<FilteredConnectPoint> ingress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1)));
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1));
+
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+ assertThat(intent, is(notNullValue()));
+
+ final String[] hops = {S4};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -174,46 +301,10 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(4));
- assertThat(linkIntent.links(), linksHasPath("ingress1", "inner1"));
- assertThat(linkIntent.links(), linksHasPath("ingress2", "inner1"));
- assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
- assertThat(linkIntent.links(), linksHasPath("inner2", "egress"));
- }
- assertThat("key is inherited", resultIntent.key(), is(intent.key()));
- }
-
- /**
- * Tests a large number of ingress points that share a common path to the
- * egress point.
- */
- @Test
- public void testMultiIngressCompilation() {
- String[] ingress = {"i1", "i2", "i3", "i4", "i5",
- "i6", "i7", "i8", "i9", "i10"};
- String egress = "e";
-
- MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
- assertThat(intent, is(notNullValue()));
-
- final String[] hops = {"n1"};
- MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
- assertThat(compiler, is(notNullValue()));
-
- List<Intent> result = compiler.compile(intent, null);
- assertThat(result, is(notNullValue()));
- assertThat(result, hasSize(1));
- Intent resultIntent = result.get(0);
- assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
-
- if (resultIntent instanceof LinkCollectionIntent) {
- LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(ingress.length + 1));
- for (String ingressToCheck : ingress) {
- assertThat(linkIntent.links(),
- linksHasPath(ingressToCheck,
- "n1"));
- }
- assertThat(linkIntent.links(), linksHasPath("n1", egress));
+ assertThat(linkIntent.links(), linksHasPath(S1, S4));
+ assertThat(linkIntent.links(), linksHasPath(S2, S4));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ assertThat(linkIntent.links(), linksHasPath(S4, S5));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
@@ -223,8 +314,11 @@
*/
@Test
public void testSameDeviceCompilation() {
- String[] ingress = {"i1", "i2"};
- String egress = "i3";
+ Set<FilteredConnectPoint> ingress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)));
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_3));
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
@@ -241,10 +335,7 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(ingress.length));
-
- assertThat(linkIntent.links(), linksHasPath("i1", "i3"));
- assertThat(linkIntent.links(), linksHasPath("i2", "i3"));
+ assertThat(linkIntent.links(), hasSize(0));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
@@ -256,16 +347,16 @@
public void testFilteredConnectPointIntent() {
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint("of1", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
- new FilteredConnectPoint(connectPoint("of2", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
);
- FilteredConnectPoint egress = new FilteredConnectPoint(connectPoint("of4", 1));
+ FilteredConnectPoint egress = new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
- MultiPointToSinglePointIntent intent = makeFilteredConnectPointIntent(ingress, egress, selector);
- String[] hops = {"of3"};
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress, selector);
+ String[] hops = {S3};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -280,9 +371,9 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(3));
- assertThat(linkIntent.links(), linksHasPath("of1", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of3", "of4"));
+ assertThat(linkIntent.links(), linksHasPath(S1, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
@@ -294,20 +385,22 @@
@Test
public void testNonTrivialSelectorsIntent() {
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint("of1", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
- new FilteredConnectPoint(connectPoint("of2", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
);
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
.matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
.build();
- FilteredConnectPoint egress = new FilteredConnectPoint(connectPoint("of4", 1));
- MultiPointToSinglePointIntent intent = makeFilteredConnectPointIntent(ingress, egress, ipPrefixSelector);
- String[] hops = {"of3"};
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress, ipPrefixSelector);
+ String[] hops = {S3};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -322,14 +415,177 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(3));
- assertThat(linkIntent.links(), linksHasPath("of1", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of3", "of4"));
+ assertThat(linkIntent.links(), linksHasPath(S1, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
assertThat(linkIntent.selector(), is(ipPrefixSelector));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
-
}
+ /**
+ * Tests if bandwidth resources get allocated correctly.
+ */
+ @Test
+ public void testBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+ final double bpsToReserve = 100.0;
+ ContinuousResource resourceSw1P1 =
+ Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw1P2 =
+ Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P1 =
+ Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P2 =
+ Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P1 =
+ Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P2 =
+ Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P3 =
+ Resources.continuous(DID_3, PORT_3, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw4P1 =
+ Resources.continuous(DID_4, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw4P2 =
+ Resources.continuous(DID_4, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+
+ String[] hops = {DID_3.toString()};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_1)));
+
+ TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
+ .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
+ .build();
+
+ FilteredConnectPoint egress = new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+ MultiPointToSinglePointIntent intent =
+ makeIntent(ingress, egress, ipPrefixSelector, constraints);
+
+ MultiPointToSinglePointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ resourceService);
+
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceAllocation rA1 = new ResourceAllocation(resourceSw1P1, intentKey);
+ ResourceAllocation rA2 = new ResourceAllocation(resourceSw1P2, intentKey);
+ ResourceAllocation rA3 = new ResourceAllocation(resourceSw2P1, intentKey);
+ ResourceAllocation rA4 = new ResourceAllocation(resourceSw2P2, intentKey);
+ ResourceAllocation rA5 = new ResourceAllocation(resourceSw3P1, intentKey);
+ ResourceAllocation rA6 = new ResourceAllocation(resourceSw3P2, intentKey);
+ ResourceAllocation rA7 = new ResourceAllocation(resourceSw3P3, intentKey);
+ ResourceAllocation rA8 = new ResourceAllocation(resourceSw4P1, intentKey);
+ ResourceAllocation rA9 = new ResourceAllocation(resourceSw4P2, intentKey);
+
+ Set<ResourceAllocation> expectedResourceAllocations =
+ ImmutableSet.of(rA1, rA2, rA3, rA4, rA5, rA6, rA7, rA8, rA9);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+ assertThat(resourceAllocations, hasSize(9));
+ assertEquals(expectedResourceAllocations, resourceAllocations);
+ }
+
+ /**
+ * Tests if all expected links are present when a partial failure
+ * constraint is used and one ingress is not present.
+ */
+ @Test
+ public void testPartialFailureConstraintSuccess() {
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1)));
+
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+ final List<Constraint> constraints =
+ Collections.singletonList(new PartialFailureConstraint());
+
+ MultiPointToSinglePointIntent intent =
+ makeIntent(ingress, egress, constraints);
+
+ String[] hops = {S3};
+
+ MultiPointToSinglePointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ null);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent, null);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(2));
+ assertThat(linkIntent.links(), linksHasPath(S1, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ }
+ assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+ }
+
+ /**
+ * Exception expected to be raised when an intent does not find all paths
+ * and a partiale failure constraint is not specified.
+ */
+ @Rule
+ public ExpectedException intentException = ExpectedException.none();
+
+ /**
+ * Tests if compiling an intent without partial failure constraints set and
+ * with a missing ingress connect point generates an exception and no other
+ * results.
+ */
+ @Test
+ public void testPartialFailureConstraintFailure() {
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1)),
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_1)));
+
+ FilteredConnectPoint egress =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+
+ MultiPointToSinglePointIntent intent =
+ makeIntent(ingress, egress);
+
+ String[] hops = {S3};
+
+ MultiPointToSinglePointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ null);
+ assertThat(compiler, is(notNullValue()));
+
+ intentException.expect(IntentException.class);
+
+ List<Intent> result = compiler.compile(intent, null);
+ assertThat(result, null);
+ }
}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
index 65251dd..56b6cc2 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompilerTest.java
@@ -22,19 +22,27 @@
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.FilteredConnectPoint;
import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.ResourceGroup;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.impl.PathNotFoundException;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
import java.util.Collections;
import java.util.List;
@@ -43,15 +51,9 @@
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.everyItem;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import static org.onosproject.net.DeviceId.deviceId;
-import static org.onosproject.net.NetTestTools.APP_ID;
-import static org.onosproject.net.NetTestTools.connectPoint;
-import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
@@ -61,43 +63,138 @@
private static final ApplicationId APPID = new TestApplicationId("foo");
+ private static final String S1 = "s1";
+ private static final String S2 = "s2";
+ private static final String S3 = "s3";
+ private static final String S4 = "s4";
+ private static final String S5 = "s5";
+ private static final String S6 = "s6";
+ private static final String S7 = "s7";
+ private static final String S8 = "s8";
+
+ private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+ private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+ private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+ private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+ private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_2 = PortNumber.portNumber(2);
+
+ private static final double BPS_TO_RESERVE = 100.0;
+
+ private static final ContinuousResource RESOURCE_SW1_P1 =
+ Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+ private static final ContinuousResource RESOURCE_SW1_P2 =
+ Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+ private static final ContinuousResource RESOURCE_SW2_P1 =
+ Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+ private static final ContinuousResource RESOURCE_SW2_P2 =
+ Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+ private static final ContinuousResource RESOURCE_SW3_P1 =
+ Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+ private static final ContinuousResource RESOURCE_SW3_P2 =
+ Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+ .resource(BPS_TO_RESERVE);
+
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
/**
* Creates a PointToPoint intent based on ingress and egress device Ids.
*
- * @param ingressIdString string for id of ingress device
- * @param egressIdString string for id of egress device
+ * @param ingress the ingress connect point
+ * @param egress the egress connect point
* @return PointToPointIntent for the two devices
*/
- private PointToPointIntent makeIntent(String ingressIdString,
- String egressIdString) {
+ private PointToPointIntent makeIntent(ConnectPoint ingress, ConnectPoint egress) {
return PointToPointIntent.builder()
.appId(APPID)
.selector(selector)
.treatment(treatment)
- .filteredIngressPoint(new FilteredConnectPoint(connectPoint(ingressIdString, 1)))
- .filteredEgressPoint(new FilteredConnectPoint(connectPoint(egressIdString, 1)))
+ .filteredIngressPoint(new FilteredConnectPoint(ingress))
+ .filteredEgressPoint(new FilteredConnectPoint(egress))
.build();
}
/**
- * Creates a PointToPoint intent based on ingress and egress deviceIds and constraints.
+ * Creates a PointToPoint intent based on ingress and egress deviceIds and
+ * constraints.
*
- * @param ingressIdString string for id of ingress device
- * @param egressIdString string for id of egress device
+ * @param ingress the ingress connect point
+ * @param egress the egress connect point
* @param constraints constraints
- * @return PointToPointIntent for the two device with constraints
+ * @return the PointToPointIntent connecting the two connect points with
+ * constraints
*/
- private PointToPointIntent makeIntent(String ingressIdString,
- String egressIdString, List<Constraint> constraints) {
+ private PointToPointIntent makeIntent(ConnectPoint ingress,
+ ConnectPoint egress,
+ List<Constraint> constraints) {
return PointToPointIntent.builder()
.appId(APPID)
.selector(selector)
.treatment(treatment)
- .filteredIngressPoint(new FilteredConnectPoint(connectPoint(ingressIdString, 1)))
- .filteredEgressPoint(new FilteredConnectPoint(connectPoint(egressIdString, 1)))
+ .filteredIngressPoint(new FilteredConnectPoint(ingress))
+ .filteredEgressPoint(new FilteredConnectPoint(egress))
+ .constraints(constraints)
+ .build();
+ }
+
+ /**
+ * Creates a PointToPoint intent based on ingress and egress deviceIds,
+ * constraints and a resource group.
+ *
+ * @param ingress the ingress connect point
+ * @param egress the egress connect point
+ * @param constraints constraints
+ * @param resourceGroup the resource group
+ * @return the PointToPointIntent connecting the two connect points with
+ * constraints
+ */
+ private PointToPointIntent makeIntent(ConnectPoint ingress,
+ ConnectPoint egress,
+ List<Constraint> constraints,
+ ResourceGroup resourceGroup) {
+ return PointToPointIntent.builder()
+ .appId(APPID)
+ .resourceGroup(resourceGroup)
+ .selector(selector)
+ .treatment(treatment)
+ .filteredIngressPoint(new FilteredConnectPoint(ingress))
+ .filteredEgressPoint(new FilteredConnectPoint(egress))
+ .constraints(constraints)
+ .build();
+ }
+
+ /**
+ * Creates a PointToPoint intent based on an intent key, ingress and egress
+ * deviceIds, constraints and a resource group.
+ *
+ * @param key the intent key
+ * @param ingress the ingress connect point
+ * @param egress the egress connect point
+ * @param constraints constraints
+ * @param resourceGroup the resource group
+ * @return the PointToPointIntent connecting the two connect points with
+ * constraints
+ */
+ private PointToPointIntent makeIntent(Key key,
+ ConnectPoint ingress,
+ ConnectPoint egress,
+ List<Constraint> constraints,
+ ResourceGroup resourceGroup) {
+ return PointToPointIntent.builder()
+ .appId(APPID)
+ .key(key)
+ .resourceGroup(resourceGroup)
+ .selector(selector)
+ .treatment(treatment)
+ .filteredIngressPoint(new FilteredConnectPoint(ingress))
+ .filteredEgressPoint(new FilteredConnectPoint(egress))
.constraints(constraints)
.build();
}
@@ -109,9 +206,7 @@
* @return HostToHost intent compiler
*/
private PointToPointIntentCompiler makeCompiler(String[] hops) {
- PointToPointIntentCompiler compiler = new PointToPointIntentCompiler();
- compiler.pathService = new IntentTestsMocks.MockPathService(hops);
- return compiler;
+ return makeCompiler(hops, null);
}
/**
@@ -121,10 +216,17 @@
* @param resourceService service to use for resource allocation requests
* @return point to point compiler
*/
- private PointToPointIntentCompiler makeCompiler(String[] hops, ResourceService resourceService) {
+ private PointToPointIntentCompiler makeCompiler(String[] hops,
+ ResourceService resourceService) {
final PointToPointIntentCompiler compiler = new PointToPointIntentCompiler();
- compiler.resourceService = resourceService;
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
+
+ if (resourceService == null) {
+ compiler.resourceService = new MockResourceService();
+ } else {
+ compiler.resourceService = resourceService;
+ }
+
return compiler;
}
@@ -134,9 +236,10 @@
@Test
public void testForwardPathCompilation() {
- PointToPointIntent intent = makeIntent("d1", "d8");
+ PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_8, PORT_1));
- String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+ String[] hops = {S1, S2, S3, S4, S5, S6, S7, S8};
PointToPointIntentCompiler compiler = makeCompiler(hops);
List<Intent> result = compiler.compile(intent, null);
@@ -147,17 +250,17 @@
if (forwardResultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent forwardIntent = (LinkCollectionIntent) forwardResultIntent;
- FilteredConnectPoint ingressPoint = new FilteredConnectPoint(connectPoint("d1", 1));
- FilteredConnectPoint egressPoint = new FilteredConnectPoint(connectPoint("d8", 1));
+ FilteredConnectPoint ingressPoint = new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+ FilteredConnectPoint egressPoint = new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
// 7 links for the hops, plus one default lnk on ingress and egress
assertThat(forwardIntent.links(), hasSize(hops.length - 1));
- assertThat(forwardIntent.links(), linksHasPath("d1", "d2"));
- assertThat(forwardIntent.links(), linksHasPath("d2", "d3"));
- assertThat(forwardIntent.links(), linksHasPath("d3", "d4"));
- assertThat(forwardIntent.links(), linksHasPath("d4", "d5"));
- assertThat(forwardIntent.links(), linksHasPath("d5", "d6"));
- assertThat(forwardIntent.links(), linksHasPath("d6", "d7"));
- assertThat(forwardIntent.links(), linksHasPath("d7", "d8"));
+ assertThat(forwardIntent.links(), linksHasPath(S1, S2));
+ assertThat(forwardIntent.links(), linksHasPath(S2, S3));
+ assertThat(forwardIntent.links(), linksHasPath(S3, S4));
+ assertThat(forwardIntent.links(), linksHasPath(S4, S5));
+ assertThat(forwardIntent.links(), linksHasPath(S5, S6));
+ assertThat(forwardIntent.links(), linksHasPath(S6, S7));
+ assertThat(forwardIntent.links(), linksHasPath(S7, S8));
assertThat(forwardIntent.filteredIngressPoints(), is(ImmutableSet.of(ingressPoint)));
assertThat(forwardIntent.filteredEgressPoints(), is(ImmutableSet.of(egressPoint)));
}
@@ -170,9 +273,10 @@
@Test
public void testReversePathCompilation() {
- PointToPointIntent intent = makeIntent("d8", "d1");
+ PointToPointIntent intent = makeIntent(new ConnectPoint(DID_8, PORT_1),
+ new ConnectPoint(DID_1, PORT_1));
- String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
+ String[] hops = {S1, S2, S3, S4, S5, S6, S7, S8};
PointToPointIntentCompiler compiler = makeCompiler(hops);
List<Intent> result = compiler.compile(intent, null);
@@ -183,16 +287,16 @@
if (reverseResultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent reverseLinkCollectionIntent = (LinkCollectionIntent) reverseResultIntent;
- FilteredConnectPoint egressPoint = new FilteredConnectPoint(connectPoint("d1", 1));
- FilteredConnectPoint ingressPoint = new FilteredConnectPoint(connectPoint("d8", 1));
+ FilteredConnectPoint egressPoint = new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+ FilteredConnectPoint ingressPoint = new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_1));
assertThat(reverseLinkCollectionIntent.links(), hasSize(hops.length - 1));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d2", "d1"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d3", "d2"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d4", "d3"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d5", "d4"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d6", "d5"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d7", "d6"));
- assertThat(reverseLinkCollectionIntent.links(), linksHasPath("d8", "d7"));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S2, S1));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S3, S2));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S4, S3));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S5, S4));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S6, S5));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S7, S6));
+ assertThat(reverseLinkCollectionIntent.links(), linksHasPath(S8, S7));
assertThat(reverseLinkCollectionIntent.filteredIngressPoints(), is(ImmutableSet.of(ingressPoint)));
assertThat(reverseLinkCollectionIntent.filteredEgressPoints(), is(ImmutableSet.of(egressPoint)));
}
@@ -200,24 +304,23 @@
}
/**
- * Tests compilation of the intent which designates two different ports on the same switch.
+ * Tests the compilation of an intent which designates two different ports
+ * on the same switch.
*/
@Test
public void testSameSwitchDifferentPortsIntentCompilation() {
- FilteredConnectPoint src = new FilteredConnectPoint(new ConnectPoint(deviceId("1"), portNumber(1)));
- FilteredConnectPoint dst = new FilteredConnectPoint(new ConnectPoint(deviceId("1"), portNumber(2)));
- PointToPointIntent intent = PointToPointIntent.builder()
- .appId(APP_ID)
- .selector(selector)
- .treatment(treatment)
- .filteredIngressPoint(src)
- .filteredEgressPoint(dst)
- .build();
+ FilteredConnectPoint src =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+ FilteredConnectPoint dst =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2));
- String[] hops = {"1"};
- PointToPointIntentCompiler sut = makeCompiler(hops);
+ PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_1, PORT_2));
- List<Intent> compiled = sut.compile(intent, null);
+ String[] hops = {S1};
+ PointToPointIntentCompiler compiler = makeCompiler(hops);
+
+ List<Intent> compiled = compiler.compile(intent, null);
assertThat("key is inherited",
compiled.stream().map(Intent::key).collect(Collectors.toList()),
@@ -238,16 +341,21 @@
*/
@Test
public void testBandwidthConstrainedIntentSuccess() {
+ final double bpsTotal = 1000.0;
+ final double bpsToReserve = 100.0;
final ResourceService resourceService =
- IntentTestsMocks.MockResourceService.makeBandwidthResourceService(1000.0);
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
final List<Constraint> constraints =
- Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(100.0)));
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
- final PointToPointIntent intent = makeIntent("s1", "s3", constraints);
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints);
- String[] hops = {"s1", "s2", "s3"};
- final PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+ String[] hops = {S1, S2, S3};
+ final PointToPointIntentCompiler compiler = makeCompiler(hops,
+ resourceService);
final List<Intent> compiledIntents = compiler.compile(intent, null);
@@ -265,17 +373,21 @@
*/
@Test
public void testBandwidthConstrainedIntentFailure() {
+ final double bpsTotal = 10.0;
final ResourceService resourceService =
- IntentTestsMocks.MockResourceService.makeBandwidthResourceService(10.0);
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
final List<Constraint> constraints =
- Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(100.0)));
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
try {
- final PointToPointIntent intent = makeIntent("s1", "s3", constraints);
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints);
- String[] hops = {"s1", "s2", "s3"};
- final PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+ String[] hops = {S1, S2, S3};
+ final PointToPointIntentCompiler compiler = makeCompiler(hops,
+ resourceService);
compiler.compile(intent, null);
@@ -285,4 +397,189 @@
assertThat(noPath.getMessage(), containsString("No path"));
}
}
+
+ /**
+ * Tests if bandwidth resources get allocated correctly. An intent with a
+ * key only is submitted.
+ */
+ @Test
+ public void testBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+
+ String[] hops = {S1, S2, S3};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints);
+
+ PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, intentKey);
+ ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, intentKey);
+ ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, intentKey);
+ ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, intentKey);
+ ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, intentKey);
+ ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, intentKey);
+
+ Set<ResourceAllocation> expectedresourceAllocations =
+ ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+ assertThat(resourceAllocations, hasSize(6));
+ assertEquals(expectedresourceAllocations, resourceAllocations);
+ }
+
+ /**
+ * Tests if bandwidth resources get allocated correctly using the resource
+ * group. An intent with a resource group is submitted.
+ */
+ @Test
+ public void testRGBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+
+ ResourceGroup resourceGroup = ResourceGroup.of(100);
+
+ String[] hops = {S1, S2, S3};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints,
+ resourceGroup);
+
+ PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+ compiler.compile(intent, null);
+
+ ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, resourceGroup);
+ ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, resourceGroup);
+ ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, resourceGroup);
+ ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, resourceGroup);
+ ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, resourceGroup);
+ ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, resourceGroup);
+
+ Set<ResourceAllocation> expectedresourceAllocations =
+ ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(resourceGroup));
+
+ assertThat(resourceAllocations, hasSize(6));
+ assertEquals(expectedresourceAllocations, resourceAllocations);
+ }
+
+ /**
+ * Tests that bandwidth resources don't get allocated twice if the intent
+ * is submitted twice.
+ */
+ @Test
+ public void testTwoBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+
+ String[] hops = {S1, S2, S3};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints);
+
+ PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+ compiler.compile(intent, null);
+
+ // Resubmit the same intent
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, intentKey);
+ ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, intentKey);
+ ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, intentKey);
+ ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, intentKey);
+ ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, intentKey);
+ ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, intentKey);
+
+ Set<ResourceAllocation> expectedresourceAllocations =
+ ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+ assertThat(resourceAllocations, hasSize(6));
+ assertEquals(expectedresourceAllocations, resourceAllocations);
+ }
+
+ /**
+ * Tests if bandwidth resources get allocated correctly using groups.
+ * An intent asks to allocate bandwidth using the intent key as a reference.
+ * Then, the intent is submitted with the same key and a group set.
+ * Previous allocations should be released and new resources should be
+ * allocated using the group.
+ */
+ @Test
+ public void testKeyRGBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+
+ String[] hops = {S1, S2, S3};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(BPS_TO_RESERVE)));
+
+ final PointToPointIntent intent = makeIntent(new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints);
+
+ PointToPointIntentCompiler compiler = makeCompiler(hops, resourceService);
+
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceGroup resourceGroup = ResourceGroup.of(100);
+
+ final PointToPointIntent newIntent = makeIntent(intentKey,
+ new ConnectPoint(DID_1, PORT_1),
+ new ConnectPoint(DID_3, PORT_2),
+ constraints,
+ resourceGroup);
+
+ compiler.compile(newIntent, null);
+
+ ResourceAllocation rAOne = new ResourceAllocation(RESOURCE_SW1_P1, resourceGroup);
+ ResourceAllocation rATwo = new ResourceAllocation(RESOURCE_SW1_P2, resourceGroup);
+ ResourceAllocation rAThree = new ResourceAllocation(RESOURCE_SW2_P1, resourceGroup);
+ ResourceAllocation rAFour = new ResourceAllocation(RESOURCE_SW2_P2, resourceGroup);
+ ResourceAllocation rAFive = new ResourceAllocation(RESOURCE_SW3_P1, resourceGroup);
+ ResourceAllocation rASix = new ResourceAllocation(RESOURCE_SW3_P2, resourceGroup);
+
+ Set<ResourceAllocation> expectedresourceAllocations =
+ ImmutableSet.of(rAOne, rATwo, rAThree, rAFour, rAFive, rASix);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(resourceGroup));
+
+ assertThat(resourceAllocations, hasSize(6));
+ assertEquals(expectedresourceAllocations, resourceAllocations);
+ }
}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
index eec242c..ec761d4 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompilerTest.java
@@ -17,32 +17,51 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import org.hamcrest.Matchers;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.VlanId;
+import org.onlab.util.Bandwidth;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
import org.onosproject.net.intent.IntentTestsMocks;
+import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.PartialFailureConstraint;
+import org.onosproject.net.resource.ContinuousResource;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceAllocation;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.Resources;
+import org.onosproject.net.topology.PathService;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
+
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.NetTestTools.connectPoint;
+import static org.junit.Assert.assertEquals;
import static org.onosproject.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
@@ -51,54 +70,93 @@
public class SinglePointToMultiPointIntentCompilerTest extends AbstractIntentTest {
private static final ApplicationId APPID = new TestApplicationId("foo");
+ private static final String S1 = "s1";
+ private static final String S2 = "s2";
+ private static final String S3 = "s3";
+ private static final String S4 = "s4";
+ private static final String S5 = "s5";
+ private static final String S6 = "s6";
+ private static final String S7 = "s7";
+ private static final String S8 = "s8";
+
+ private static final DeviceId DID_1 = DeviceId.deviceId("of:" + S1);
+ private static final DeviceId DID_2 = DeviceId.deviceId("of:" + S2);
+ private static final DeviceId DID_3 = DeviceId.deviceId("of:" + S3);
+ private static final DeviceId DID_4 = DeviceId.deviceId("of:" + S4);
+ private static final DeviceId DID_5 = DeviceId.deviceId("of:" + S5);
+ private static final DeviceId DID_8 = DeviceId.deviceId("of:" + S8);
+
+ private static final PortNumber PORT_1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_2 = PortNumber.portNumber(2);
+ private static final PortNumber PORT_3 = PortNumber.portNumber(3);
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
-
-
/**
* Creates a SinglePointToMultiPoint intent for an ingress point
* and a group of egress points.
*
- * @param ingressId device id of the ingress point
- * @param egressIds array of egress device ids
- * @return MultiPointToSinglePoint intent
+ * @param ingress the filtered ingress point
+ * @param egress the set of filtered egress points
+ * @return a single point to multi point intent
*/
- private SinglePointToMultiPointIntent makeIntent(String ingressId, String[] egressIds) {
- ConnectPoint ingressPoint = connectPoint(ingressId, 2);
- Set<ConnectPoint> egressPoints = new HashSet<>();
-
-
- for (String egressId : egressIds) {
- egressPoints.add(connectPoint(egressId, 1));
- }
-
- return SinglePointToMultiPointIntent.builder()
- .appId(APPID)
- .selector(selector)
- .treatment(treatment)
- .ingressPoint(ingressPoint)
- .egressPoints(egressPoints)
- .build();
+ private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+ Set<FilteredConnectPoint> egress) {
+ return makeIntent(ingress, egress, selector);
}
/**
- * Generate SinglePointToMultiPointIntent with filtered connection point.
+ * Generates SinglePointToMultiPointIntent with filtered connection point
+ * and the specified selector.
*
- * @param ingress filtered ingress point
- * @param egress filtered egress point
- * @return
+ * @param ingress the filtered ingress point
+ * @param egress the filtered egress point
+ * @param trafficSelector the intent traffic selector
+ * @return a single point to multi point intent
*/
- private SinglePointToMultiPointIntent makeFilteredConnectPointIntent(FilteredConnectPoint ingress,
- Set<FilteredConnectPoint> egress,
- TrafficSelector trafficSelector) {
+ private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+ Set<FilteredConnectPoint> egress,
+ TrafficSelector trafficSelector) {
+ return makeIntent(ingress, egress, trafficSelector, Lists.newArrayList());
+ }
+
+ /**
+ * Generates SinglePointToMultiPointIntent with filtered connection point
+ * and the given constraints set.
+ *
+ * @param ingress the filtered ingress point
+ * @param egress the filtered egress point
+ * @param constraints the list of intent constraints
+ * @return a single point to multi point intent
+ */
+ private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+ Set<FilteredConnectPoint> egress,
+ List<Constraint> constraints) {
+ return makeIntent(ingress, egress, selector, constraints);
+ }
+
+ /**
+ * Generates SinglePointToMultiPointIntent with filtered connection point,
+ * and the specified traffic selector and intent constraints.
+ *
+ * @param ingress the filtered ingress point
+ * @param egress the set of filtered egress points
+ * @param trafficSelector the intent traffic selector
+ * @param constraints the list of intent constraints
+ * @return a single point to multi point intent
+ */
+ private SinglePointToMultiPointIntent makeIntent(FilteredConnectPoint ingress,
+ Set<FilteredConnectPoint> egress,
+ TrafficSelector trafficSelector,
+ List<Constraint> constraints) {
return SinglePointToMultiPointIntent.builder()
.appId(APPID)
.treatment(treatment)
.selector(trafficSelector)
.filteredIngressPoint(ingress)
.filteredEgressPoints(egress)
+ .constraints(constraints)
.build();
}
@@ -106,29 +164,58 @@
* Creates a compiler for SinglePointToMultiPoint intents.
*
* @param hops hops to use while computing paths for this intent
- * @return SinglePointToMultiPoint intent
+ * @param pathService the path service
+ * @param resourceService the resource service
+ * @return a single point to multi point intent compiler
*/
- private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops) {
+ private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops,
+ PathService pathService,
+ ResourceService resourceService) {
SinglePointToMultiPointIntentCompiler compiler =
new SinglePointToMultiPointIntentCompiler();
+ compiler.deviceService = new IntentTestsMocks.MockDeviceService();
- compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+ if (pathService == null) {
+ compiler.pathService = new IntentTestsMocks.Mp2MpMockPathService(hops);
+ } else {
+ compiler.pathService = pathService;
+ }
+
+ if (resourceService == null) {
+ compiler.resourceService = new MockResourceService();
+ } else {
+ compiler.resourceService = resourceService;
+ }
+
return compiler;
}
/**
+ * Creates a compiler for SinglePointToMultiPoint intents.
+ *
+ * @param hops the hops to use while computing paths for this intent
+ * @return a single point to multi point intent compiler
+ */
+ private SinglePointToMultiPointIntentCompiler makeCompiler(String[] hops) {
+ return makeCompiler(hops, null, null);
+ }
+
+ /**
* Tests a single ingress point with 8 hops to its egress point.
*/
@Test
public void testSingleLongPathCompilation() {
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+ Set<FilteredConnectPoint> egress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_8, PORT_2)));
- String ingress = "ingress";
- String[] egress = {"egress"};
+ SinglePointToMultiPointIntent intent =
+ makeIntent(ingress, egress);
- SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
- String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8"};
+ String[] hops = {S2, S3, S4, S5, S6, S7};
SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -140,14 +227,14 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(9));
- assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
- assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
- assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
- assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
- assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
- assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
- assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
+ assertThat(linkIntent.links(), hasSize(7));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ assertThat(linkIntent.links(), linksHasPath(S4, S5));
+ assertThat(linkIntent.links(), linksHasPath(S5, S6));
+ assertThat(linkIntent.links(), linksHasPath(S6, S7));
+ assertThat(linkIntent.links(), linksHasPath(S7, S8));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
@@ -157,14 +244,21 @@
* and some path segments are not shared.
*/
@Test
- public void testTwoIngressCompilation() {
- String ingress = "ingress";
- String[] egress = {"egress1", "egress2"};
+ public void testTwoEgressCompilation() {
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+ FilteredConnectPoint egressOne =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+ FilteredConnectPoint egressTwo =
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2));
+ Set<FilteredConnectPoint> egress = Sets.newHashSet(egressOne, egressTwo);
SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
+
assertThat(intent, is(notNullValue()));
- final String[] hops = {"inner1", "inner2"};
+ final String[] hops = {S2, S3};
SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -177,28 +271,38 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(4));
- assertThat(linkIntent.links(), linksHasPath("ingress", "inner1"));
- assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
- assertThat(linkIntent.links(), linksHasPath("inner2", "egress1"));
- assertThat(linkIntent.links(), linksHasPath("inner2", "egress2"));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ assertThat(linkIntent.links(), linksHasPath(S3, S5));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
/**
- * Tests a large number of ingress points that share a common path to the
- * egress point.
+ * Tests multiple egress points that share a common path to the ingress
+ * point.
*/
@Test
- public void testMultiIngressCompilation() {
- String ingress = "i";
- String[] egress = {"e1", "e2", "e3", "e4", "e5",
- "e6", "e7", "e8", "e9", "e10"};
+ public void testMultiEgressCompilation() {
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+ FilteredConnectPoint egressOne =
+ new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_2));
+ FilteredConnectPoint egressTwo =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2));
+ FilteredConnectPoint egressThree =
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2));
+ Set<FilteredConnectPoint> egress = Sets.newHashSet(egressOne,
+ egressTwo,
+ egressThree);
SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
+
assertThat(intent, is(notNullValue()));
- final String[] hops = {"n1"};
+ final String[] hops = {S2};
SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -210,11 +314,11 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(egress.length + 1));
- for (String egressToCheck : egress) {
- assertThat(linkIntent.links(), linksHasPath("n1", egressToCheck));
- }
- assertThat(linkIntent.links(), linksHasPath(ingress, "n1"));
+ assertThat(linkIntent.links(), hasSize(4));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S4));
+ assertThat(linkIntent.links(), linksHasPath(S2, S5));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
@@ -224,8 +328,12 @@
*/
@Test
public void testSameDeviceCompilation() {
- String ingress = "i1";
- String[] egress = {"i2", "i3"};
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+ Set<FilteredConnectPoint> egress =
+ Sets.newHashSet(new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)),
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_3)));
SinglePointToMultiPointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
@@ -242,32 +350,29 @@
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
- assertThat(linkIntent.links(), hasSize(egress.length));
-
- assertThat(linkIntent.links(), linksHasPath("i1", "i2"));
- assertThat(linkIntent.links(), linksHasPath("i1", "i3"));
+ assertThat(linkIntent.links(), hasSize(0));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
}
/**
- * Tests filtered ingress and egress.
+ * Tests filtered ingress and egress connect points.
*/
@Test
public void testFilteredConnectPointIntent() {
- FilteredConnectPoint ingress = new FilteredConnectPoint(connectPoint("of1", 1));
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
Set<FilteredConnectPoint> egress = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint("of3", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
- new FilteredConnectPoint(connectPoint("of4", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
);
-
- SinglePointToMultiPointIntent intent = makeFilteredConnectPointIntent(ingress, egress, selector);
- String[] hops = {"of2"};
+ SinglePointToMultiPointIntent intent = makeIntent(ingress, egress, selector);
+ String[] hops = {S2};
SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -283,9 +388,9 @@
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(3));
- assertThat(linkIntent.links(), linksHasPath("of1", "of2"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of4"));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S4));
Set<FilteredConnectPoint> ingressPoints = linkIntent.filteredIngressPoints();
assertThat("Link collection ingress points do not match base intent",
@@ -299,17 +404,18 @@
}
/**
- * Tests selector, filtered ingress and egress.
+ * Tests filtered ingress and egress points with an intent selector set.
*/
@Test
public void testNonTrivialSelectorsIntent() {
- FilteredConnectPoint ingress = new FilteredConnectPoint(connectPoint("of1", 1));
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
Set<FilteredConnectPoint> egress = ImmutableSet.of(
- new FilteredConnectPoint(connectPoint("of3", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_3, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
- new FilteredConnectPoint(connectPoint("of4", 1),
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("200")).build())
);
@@ -317,8 +423,8 @@
.matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
.build();
- SinglePointToMultiPointIntent intent = makeFilteredConnectPointIntent(ingress, egress, ipPrefixSelector);
- String[] hops = {"of2"};
+ SinglePointToMultiPointIntent intent = makeIntent(ingress, egress, ipPrefixSelector);
+ String[] hops = {S2};
SinglePointToMultiPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
@@ -334,9 +440,9 @@
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(3));
- assertThat(linkIntent.links(), linksHasPath("of1", "of2"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of3"));
- assertThat(linkIntent.links(), linksHasPath("of2", "of4"));
+ assertThat(linkIntent.links(), linksHasPath(S1, S2));
+ assertThat(linkIntent.links(), linksHasPath(S2, S3));
+ assertThat(linkIntent.links(), linksHasPath(S2, S4));
Set<FilteredConnectPoint> ingressPoints = linkIntent.filteredIngressPoints();
assertThat("Link collection ingress points do not match base intent",
@@ -347,6 +453,172 @@
assertThat(linkIntent.selector(), is(ipPrefixSelector));
}
assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+ }
+ /**
+ * Tests if bandwidth resources get allocated correctly.
+ */
+ @Test
+ public void testBandwidthConstrainedIntentAllocation() {
+ final double bpsTotal = 1000.0;
+ final double bpsToReserve = 100.0;
+
+ ContinuousResource resourceSw1P1 =
+ Resources.continuous(DID_1, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw1P2 =
+ Resources.continuous(DID_1, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P1 =
+ Resources.continuous(DID_2, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw2P2 =
+ Resources.continuous(DID_2, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P1 =
+ Resources.continuous(DID_3, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P2 =
+ Resources.continuous(DID_3, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw3P3 =
+ Resources.continuous(DID_3, PORT_3, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw4P1 =
+ Resources.continuous(DID_4, PORT_1, Bandwidth.class)
+ .resource(bpsToReserve);
+ ContinuousResource resourceSw4P2 =
+ Resources.continuous(DID_4, PORT_2, Bandwidth.class)
+ .resource(bpsToReserve);
+
+ String[] hops = {DID_3.toString()};
+
+ final ResourceService resourceService =
+ MockResourceService.makeCustomBandwidthResourceService(bpsTotal);
+ final List<Constraint> constraints =
+ Collections.singletonList(new BandwidthConstraint(Bandwidth.bps(bpsToReserve)));
+
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_1));
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_2)),
+ new FilteredConnectPoint(new ConnectPoint(DID_2, PORT_2)));
+
+ TrafficSelector ipPrefixSelector = DefaultTrafficSelector.builder()
+ .matchIPDst(IpPrefix.valueOf("192.168.100.0/24"))
+ .build();
+
+ SinglePointToMultiPointIntent intent =
+ makeIntent(ingress, egress, ipPrefixSelector, constraints);
+
+ SinglePointToMultiPointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ resourceService);
+
+ compiler.compile(intent, null);
+
+ Key intentKey = intent.key();
+
+ ResourceAllocation rA1 = new ResourceAllocation(resourceSw1P1, intentKey);
+ ResourceAllocation rA2 = new ResourceAllocation(resourceSw1P2, intentKey);
+ ResourceAllocation rA3 = new ResourceAllocation(resourceSw2P1, intentKey);
+ ResourceAllocation rA4 = new ResourceAllocation(resourceSw2P2, intentKey);
+ ResourceAllocation rA5 = new ResourceAllocation(resourceSw3P1, intentKey);
+ ResourceAllocation rA6 = new ResourceAllocation(resourceSw3P2, intentKey);
+ ResourceAllocation rA7 = new ResourceAllocation(resourceSw3P3, intentKey);
+ ResourceAllocation rA8 = new ResourceAllocation(resourceSw4P1, intentKey);
+ ResourceAllocation rA9 = new ResourceAllocation(resourceSw4P2, intentKey);
+
+ Set<ResourceAllocation> expectedResourceAllocations =
+ ImmutableSet.of(rA1, rA2, rA3, rA4, rA5, rA6, rA7, rA8, rA9);
+
+ Set<ResourceAllocation> resourceAllocations =
+ ImmutableSet.copyOf(resourceService.getResourceAllocations(intentKey));
+
+ assertThat(resourceAllocations, hasSize(9));
+ assertEquals(expectedResourceAllocations, resourceAllocations);
+ }
+
+ /**
+ * Tests if all expected links are present when a partial failure
+ * constraint is used and one ingress is not present.
+ */
+ @Test
+ public void testPartialFailureConstraintSuccess() {
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2)),
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2)));
+
+ final List<Constraint> constraints =
+ Collections.singletonList(new PartialFailureConstraint());
+
+ SinglePointToMultiPointIntent intent =
+ makeIntent(ingress, egress, constraints);
+
+ String[] hops = {S3};
+
+ SinglePointToMultiPointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ null);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent, null);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(2));
+ assertThat(linkIntent.links(), linksHasPath(S1, S3));
+ assertThat(linkIntent.links(), linksHasPath(S3, S4));
+ }
+ assertThat("key is inherited", resultIntent.key(), is(intent.key()));
+ }
+
+ /**
+ * Exception expected to be raised when an intent does not find all paths
+ * and a partiale failure constraint is not specified.
+ */
+ @Rule
+ public ExpectedException intentException = ExpectedException.none();
+
+ /**
+ * Tests if compiling an intent without partial failure constraints set and
+ * with a missing egress connect point generates an exception and no other
+ * results.
+ */
+ @Test
+ public void testPartialFailureConstraintFailure() {
+ FilteredConnectPoint ingress =
+ new FilteredConnectPoint(new ConnectPoint(DID_1, PORT_1));
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(new ConnectPoint(DID_4, PORT_2)),
+ new FilteredConnectPoint(new ConnectPoint(DID_5, PORT_2)));
+
+ SinglePointToMultiPointIntent intent =
+ makeIntent(ingress, egress);
+
+ String[] hops = {S3};
+
+ SinglePointToMultiPointIntentCompiler compiler =
+ makeCompiler(null,
+ new IntentTestsMocks.FixedMP2MPMockPathService(hops),
+ null);
+ assertThat(compiler, is(notNullValue()));
+
+ intentException.expect(IntentException.class);
+
+ List<Intent> result = compiler.compile(intent, null);
+ assertThat(result, null);
}
}