Ray Milkey

Unit Tests for Bandwidth and Lambda allocations

These tests are for checking the valid path calculation logic
in the intent compilers and the PathIntent installer.

Change-Id: I2986729ae27202a2f42a71e64a53026383ddfb0b
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onlab.onos.net; 16 package org.onlab.onos.net;
17 17
18 +import org.onlab.onos.TestApplicationId;
19 +import org.onlab.onos.core.ApplicationId;
18 import org.onlab.onos.net.provider.ProviderId; 20 import org.onlab.onos.net.provider.ProviderId;
19 import org.onlab.packet.ChassisId; 21 import org.onlab.packet.ChassisId;
20 import org.onlab.packet.IpAddress; 22 import org.onlab.packet.IpAddress;
...@@ -39,6 +41,7 @@ public final class NetTestTools { ...@@ -39,6 +41,7 @@ public final class NetTestTools {
39 } 41 }
40 42
41 public static final ProviderId PID = new ProviderId("of", "foo"); 43 public static final ProviderId PID = new ProviderId("of", "foo");
44 + public static final ApplicationId APP_ID = new TestApplicationId("foo");
42 45
43 // Short-hand for producing a device id from a string 46 // Short-hand for producing a device id from a string
44 public static DeviceId did(String id) { 47 public static DeviceId did(String id) {
......
...@@ -67,7 +67,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> { ...@@ -67,7 +67,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected LinkResourceService resourceService; 68 protected LinkResourceService resourceService;
69 69
70 - private ApplicationId appId; 70 + protected ApplicationId appId;
71 71
72 @Activate 72 @Activate
73 public void activate() { 73 public void activate() {
......
...@@ -16,23 +16,39 @@ ...@@ -16,23 +16,39 @@
16 package org.onlab.onos.net.intent; 16 package org.onlab.onos.net.intent;
17 17
18 import static org.onlab.onos.net.NetTestTools.createPath; 18 import static org.onlab.onos.net.NetTestTools.createPath;
19 +import static org.onlab.onos.net.NetTestTools.link;
19 20
20 import java.util.ArrayList; 21 import java.util.ArrayList;
21 import java.util.Arrays; 22 import java.util.Arrays;
23 +import java.util.Collection;
22 import java.util.Collections; 24 import java.util.Collections;
23 import java.util.HashSet; 25 import java.util.HashSet;
26 +import java.util.LinkedList;
24 import java.util.List; 27 import java.util.List;
25 import java.util.Set; 28 import java.util.Set;
26 29
30 +import org.onlab.onos.net.DeviceId;
27 import org.onlab.onos.net.ElementId; 31 import org.onlab.onos.net.ElementId;
32 +import org.onlab.onos.net.Link;
28 import org.onlab.onos.net.Path; 33 import org.onlab.onos.net.Path;
29 import org.onlab.onos.net.flow.TrafficSelector; 34 import org.onlab.onos.net.flow.TrafficSelector;
30 import org.onlab.onos.net.flow.TrafficTreatment; 35 import org.onlab.onos.net.flow.TrafficTreatment;
31 import org.onlab.onos.net.flow.criteria.Criterion; 36 import org.onlab.onos.net.flow.criteria.Criterion;
32 import org.onlab.onos.net.flow.criteria.Criterion.Type; 37 import org.onlab.onos.net.flow.criteria.Criterion.Type;
33 import org.onlab.onos.net.flow.instructions.Instruction; 38 import org.onlab.onos.net.flow.instructions.Instruction;
39 +import org.onlab.onos.net.resource.BandwidthResourceRequest;
40 +import org.onlab.onos.net.resource.LambdaResourceRequest;
41 +import org.onlab.onos.net.resource.LinkResourceAllocations;
42 +import org.onlab.onos.net.resource.LinkResourceRequest;
43 +import org.onlab.onos.net.resource.LinkResourceService;
44 +import org.onlab.onos.net.resource.ResourceAllocation;
45 +import org.onlab.onos.net.resource.ResourceRequest;
46 +import org.onlab.onos.net.resource.ResourceType;
47 +import org.onlab.onos.net.topology.DefaultTopologyEdge;
48 +import org.onlab.onos.net.topology.DefaultTopologyVertex;
34 import org.onlab.onos.net.topology.LinkWeight; 49 import org.onlab.onos.net.topology.LinkWeight;
35 import org.onlab.onos.net.topology.PathService; 50 import org.onlab.onos.net.topology.PathService;
51 +import org.onlab.onos.net.topology.TopologyVertex;
36 52
37 /** 53 /**
38 * Common mocks used by the intent framework tests. 54 * Common mocks used by the intent framework tests.
...@@ -101,7 +117,158 @@ public class IntentTestsMocks { ...@@ -101,7 +117,158 @@ public class IntentTestsMocks {
101 117
102 @Override 118 @Override
103 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) { 119 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
104 - return getPaths(src, dst); 120 + final Set<Path> paths = getPaths(src, dst);
121 +
122 + for (Path path : paths) {
123 + final DeviceId srcDevice = path.src().deviceId();
124 + final DeviceId dstDevice = path.dst().deviceId();
125 + final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
126 + final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
127 + final Link link = link(src.toString(), 1, dst.toString(), 1);
128 +
129 + final double weightValue = weight.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
130 + if (weightValue < 0) {
131 + return new HashSet<>();
132 + }
133 + }
134 + return paths;
135 + }
136 + }
137 +
138 + public static class MockLinkResourceAllocations implements LinkResourceAllocations {
139 + @Override
140 + public Set<ResourceAllocation> getResourceAllocation(Link link) {
141 + return null;
142 + }
143 +
144 + @Override
145 + public IntentId intendId() {
146 + return null;
147 + }
148 +
149 + @Override
150 + public Collection<Link> links() {
151 + return null;
152 + }
153 +
154 + @Override
155 + public Set<ResourceRequest> resources() {
156 + return null;
105 } 157 }
158 +
159 + @Override
160 + public ResourceType type() {
161 + return null;
162 + }
163 + }
164 +
165 + public static class MockedAllocationFailure extends RuntimeException { }
166 +
167 + public static class MockResourceService implements LinkResourceService {
168 +
169 + double availableBandwidth = -1.0;
170 + int availableLambda = -1;
171 +
172 + /**
173 + * Allocates a resource service that will allow bandwidth allocations
174 + * up to a limit.
175 + *
176 + * @param bandwidth available bandwidth limit
177 + * @return resource manager for bandwidth requests
178 + */
179 + public static MockResourceService makeBandwidthResourceService(double bandwidth) {
180 + final MockResourceService result = new MockResourceService();
181 + result.availableBandwidth = bandwidth;
182 + return result;
106 } 183 }
184 +
185 + /**
186 + * Allocates a resource service that will allow lambda allocations.
187 + *
188 + * @param lambda Lambda to return for allocation requests. Currently unused
189 + * @return resource manager for lambda requests
190 + */
191 + public static MockResourceService makeLambdaResourceService(int lambda) {
192 + final MockResourceService result = new MockResourceService();
193 + result.availableLambda = lambda;
194 + return result;
195 + }
196 +
197 + public void setAvailableBandwidth(double availableBandwidth) {
198 + this.availableBandwidth = availableBandwidth;
199 + }
200 +
201 + public void setAvailableLambda(int availableLambda) {
202 + this.availableLambda = availableLambda;
203 + }
204 +
205 +
206 + @Override
207 + public LinkResourceAllocations requestResources(LinkResourceRequest req) {
208 + int lambda = -1;
209 + double bandwidth = -1.0;
210 +
211 + for (ResourceRequest resourceRequest : req.resources()) {
212 + if (resourceRequest.type() == ResourceType.BANDWIDTH) {
213 + final BandwidthResourceRequest brr = (BandwidthResourceRequest) resourceRequest;
214 + bandwidth = brr.bandwidth().toDouble();
215 + } else if (resourceRequest.type() == ResourceType.LAMBDA) {
216 + lambda = 1;
217 + }
218 + }
219 +
220 + if (availableBandwidth < bandwidth) {
221 + throw new MockedAllocationFailure();
222 + }
223 + if (lambda > 0 && availableLambda == 0) {
224 + throw new MockedAllocationFailure();
225 + }
226 +
227 + return new IntentTestsMocks.MockLinkResourceAllocations();
228 + }
229 +
230 + @Override
231 + public void releaseResources(LinkResourceAllocations allocations) {
232 + // Mock
233 + }
234 +
235 + @Override
236 + public LinkResourceAllocations updateResources(LinkResourceRequest req,
237 + LinkResourceAllocations oldAllocations) {
238 + return null;
239 + }
240 +
241 + @Override
242 + public Iterable<LinkResourceAllocations> getAllocations() {
243 + return null;
244 + }
245 +
246 + @Override
247 + public Iterable<LinkResourceAllocations> getAllocations(Link link) {
248 + return null;
249 + }
250 +
251 + @Override
252 + public LinkResourceAllocations getAllocations(IntentId intentId) {
253 + return null;
254 + }
255 +
256 + @Override
257 + public Iterable<ResourceRequest> getAvailableResources(Link link) {
258 + final List<ResourceRequest> result = new LinkedList<>();
259 + if (availableBandwidth > 0.0) {
260 + result.add(new BandwidthResourceRequest(availableBandwidth));
261 + }
262 + if (availableLambda > 0) {
263 + result.add(new LambdaResourceRequest());
264 + }
265 + return result;
266 + }
267 +
268 + @Override
269 + public ResourceRequest getAvailableResources(Link link, LinkResourceAllocations allocations) {
270 + return null;
271 + }
272 + }
273 +
107 } 274 }
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onlab.onos.net.intent.impl;
17 +
18 +import java.util.LinkedList;
19 +import java.util.List;
20 +
21 +import org.junit.Test;
22 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
23 +import org.onlab.onos.net.flow.TrafficSelector;
24 +import org.onlab.onos.net.flow.TrafficTreatment;
25 +import org.onlab.onos.net.intent.Constraint;
26 +import org.onlab.onos.net.intent.Intent;
27 +import org.onlab.onos.net.intent.IntentTestsMocks;
28 +import org.onlab.onos.net.intent.PathIntent;
29 +import org.onlab.onos.net.intent.PointToPointIntent;
30 +import org.onlab.onos.net.intent.constraint.BandwidthConstraint;
31 +import org.onlab.onos.net.intent.constraint.LambdaConstraint;
32 +import org.onlab.onos.net.resource.Bandwidth;
33 +import org.onlab.onos.net.resource.Lambda;
34 +import org.onlab.onos.net.resource.LinkResourceService;
35 +
36 +import static org.hamcrest.MatcherAssert.assertThat;
37 +import static org.hamcrest.Matchers.containsString;
38 +import static org.hamcrest.Matchers.hasSize;
39 +import static org.hamcrest.Matchers.instanceOf;
40 +import static org.hamcrest.Matchers.notNullValue;
41 +import static org.junit.Assert.fail;
42 +import static org.onlab.onos.net.NetTestTools.APP_ID;
43 +import static org.onlab.onos.net.NetTestTools.connectPoint;
44 +
45 +/**
46 + * Unit tests for calculating paths for intents with constraints.
47 + */
48 +
49 +public class PathConstraintCalculationTest {
50 +
51 + /**
52 + * Creates a point to point intent compiler for a three switch linear
53 + * topology.
54 + *
55 + * @param resourceService service to use for resource allocation requests
56 + * @return point to point compiler
57 + */
58 + private PointToPointIntentCompiler makeCompiler(LinkResourceService resourceService) {
59 + final String[] hops = {"s1", "s2", "s3"};
60 + final PointToPointIntentCompiler compiler = new PointToPointIntentCompiler();
61 + compiler.resourceService = resourceService;
62 + compiler.pathService = new IntentTestsMocks.MockPathService(hops);
63 + return compiler;
64 + }
65 +
66 + /**
67 + * Creates an intent with a given constraint and compiles it. The compiler
68 + * will throw PathNotFoundException if the allocations cannot be satisfied.
69 + *
70 + * @param constraint constraint to apply to the created intent
71 + * @param resourceService service to use for resource allocation requests
72 + * @return List of compiled intents
73 + */
74 + private List<Intent> compileIntent(Constraint constraint,
75 + LinkResourceService resourceService) {
76 + final List<Constraint> constraints = new LinkedList<>();
77 + constraints.add(constraint);
78 + final TrafficSelector selector = new IntentTestsMocks.MockSelector();
79 + final TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
80 +
81 + final PointToPointIntent intent =
82 + new PointToPointIntent(APP_ID,
83 + selector,
84 + treatment,
85 + connectPoint("s1", 1),
86 + connectPoint("s3", 1),
87 + constraints);
88 + final PointToPointIntentCompiler compiler = makeCompiler(resourceService);
89 +
90 + return compiler.compile(intent);
91 + }
92 +
93 + /**
94 + * Installs a compiled path intent and returns the flow rules it generates.
95 + *
96 + * @param compiledIntents list of compiled intents
97 + * @param resourceService service to use for resource allocation requests
98 + * @return
99 + */
100 + private List<FlowRuleBatchOperation> installIntents(List<Intent> compiledIntents,
101 + LinkResourceService resourceService) {
102 + final PathIntent path = (PathIntent) compiledIntents.get(0);
103 +
104 + final PathIntentInstaller installer = new PathIntentInstaller();
105 + installer.resourceService = resourceService;
106 + installer.appId = APP_ID;
107 + return installer.install(path);
108 + }
109 +
110 + /**
111 + * Tests that requests with sufficient available bandwidth succeed.
112 + */
113 + @Test
114 + public void testBandwidthConstrainedIntentSuccess() {
115 +
116 + final LinkResourceService resourceService =
117 + IntentTestsMocks.MockResourceService.makeBandwidthResourceService(1000.0);
118 + final Constraint constraint = new BandwidthConstraint(Bandwidth.valueOf(100.0));
119 +
120 + final List<Intent> compiledIntents = compileIntent(constraint, resourceService);
121 + assertThat(compiledIntents, notNullValue());
122 + assertThat(compiledIntents, hasSize(1));
123 + }
124 +
125 + /**
126 + * Tests that requests with insufficient available bandwidth fail.
127 + */
128 + @Test
129 + public void testBandwidthConstrainedIntentFailure() {
130 +
131 + final LinkResourceService resourceService =
132 + IntentTestsMocks.MockResourceService.makeBandwidthResourceService(10.0);
133 + final Constraint constraint = new BandwidthConstraint(Bandwidth.valueOf(100.0));
134 +
135 + try {
136 + compileIntent(constraint, resourceService);
137 + fail("Point to Point compilation with insufficient bandwidth does "
138 + + "not throw exception.");
139 + } catch (PathNotFoundException noPath) {
140 + assertThat(noPath.getMessage(), containsString("No packet path"));
141 + }
142 + }
143 +
144 + /**
145 + * Tests that requests for available lambdas are successful.
146 + */
147 + @Test
148 + public void testLambdaConstrainedIntentSuccess() {
149 +
150 + final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
151 + final LinkResourceService resourceService =
152 + IntentTestsMocks.MockResourceService.makeLambdaResourceService(1);
153 +
154 + final List<Intent> compiledIntents =
155 + compileIntent(constraint, resourceService);
156 + assertThat(compiledIntents, notNullValue());
157 + assertThat(compiledIntents, hasSize(1));
158 + }
159 +
160 + /**
161 + * Tests that requests for lambdas when there are no available lambdas
162 + * fail.
163 + */
164 + @Test
165 + public void testLambdaConstrainedIntentFailure() {
166 +
167 + final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
168 + final LinkResourceService resourceService =
169 + IntentTestsMocks.MockResourceService.makeBandwidthResourceService(10.0);
170 + try {
171 + compileIntent(constraint, resourceService);
172 + fail("Point to Point compilation with no available lambda does "
173 + + "not throw exception.");
174 + } catch (PathNotFoundException noPath) {
175 + assertThat(noPath.getMessage(), containsString("No packet path"));
176 + }
177 + }
178 +
179 + /**
180 + * Tests that installation of bandwidth constrained path intents are
181 + * successful.
182 + */
183 + @Test
184 + public void testInstallBandwidthConstrainedIntentSuccess() {
185 +
186 + final IntentTestsMocks.MockResourceService resourceService =
187 + IntentTestsMocks.MockResourceService.makeBandwidthResourceService(1000.0);
188 + final Constraint constraint = new BandwidthConstraint(Bandwidth.valueOf(100.0));
189 +
190 + final List<Intent> compiledIntents = compileIntent(constraint, resourceService);
191 + assertThat(compiledIntents, notNullValue());
192 + assertThat(compiledIntents, hasSize(1));
193 +
194 + final List<FlowRuleBatchOperation> flowOperations =
195 + installIntents(compiledIntents, resourceService);
196 +
197 + assertThat(flowOperations, notNullValue());
198 + assertThat(flowOperations, hasSize(1));
199 + }
200 +
201 + /**
202 + * Tests that installation of bandwidth constrained path intents fail
203 + * if there are no available resources.
204 + */
205 + @Test
206 + public void testInstallBandwidthConstrainedIntentFailure() {
207 +
208 + final IntentTestsMocks.MockResourceService resourceService =
209 + IntentTestsMocks.MockResourceService.makeBandwidthResourceService(1000.0);
210 + final Constraint constraint = new BandwidthConstraint(Bandwidth.valueOf(100.0));
211 +
212 + final List<Intent> compiledIntents = compileIntent(constraint, resourceService);
213 + assertThat(compiledIntents, notNullValue());
214 + assertThat(compiledIntents, hasSize(1));
215 +
216 + // Make it look like the available bandwidth was consumed
217 + resourceService.setAvailableBandwidth(1.0);
218 +
219 + try {
220 + installIntents(compiledIntents, resourceService);
221 + fail("Bandwidth request with no available bandwidth did not fail.");
222 + } catch (IntentTestsMocks.MockedAllocationFailure failure) {
223 + assertThat(failure,
224 + instanceOf(IntentTestsMocks.MockedAllocationFailure.class));
225 + }
226 + }
227 +
228 + /**
229 + * Tests that installation of lambda constrained path intents are
230 + * successful.
231 + */
232 + @Test
233 + public void testInstallLambdaConstrainedIntentSuccess() {
234 +
235 + final IntentTestsMocks.MockResourceService resourceService =
236 + IntentTestsMocks.MockResourceService.makeLambdaResourceService(1);
237 + final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
238 +
239 + final List<Intent> compiledIntents = compileIntent(constraint, resourceService);
240 + assertThat(compiledIntents, notNullValue());
241 + assertThat(compiledIntents, hasSize(1));
242 +
243 + final List<FlowRuleBatchOperation> flowOperations =
244 + installIntents(compiledIntents, resourceService);
245 +
246 + assertThat(flowOperations, notNullValue());
247 + assertThat(flowOperations, hasSize(1));
248 + }
249 +
250 + /**
251 + * Tests that installation of lambda constrained path intents fail
252 + * if there are no available resources.
253 + */
254 + @Test
255 + public void testInstallLambdaConstrainedIntentFailure() {
256 +
257 + final IntentTestsMocks.MockResourceService resourceService =
258 + IntentTestsMocks.MockResourceService.makeLambdaResourceService(1);
259 + final Constraint constraint = new LambdaConstraint(Lambda.valueOf(1));
260 +
261 + final List<Intent> compiledIntents = compileIntent(constraint, resourceService);
262 + assertThat(compiledIntents, notNullValue());
263 + assertThat(compiledIntents, hasSize(1));
264 +
265 + // Make it look like the available lambda was consumed
266 + resourceService.setAvailableLambda(0);
267 +
268 + try {
269 + installIntents(compiledIntents, resourceService);
270 + fail("Lambda request with no available lambda did not fail.");
271 + } catch (IntentTestsMocks.MockedAllocationFailure failure) {
272 + assertThat(failure,
273 + instanceOf(IntentTestsMocks.MockedAllocationFailure.class));
274 + }
275 + }
276 +
277 +}