blob: 99f5db928116f07c31ff40a7f7be9e2bc2e19bd8 [file] [log] [blame]
Yi Tsengc927a062017-05-02 15:02:37 -07001/*
2 * Copyright 2017-present 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
17package org.onosproject.net.intent.impl.installer;
18
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.Lists;
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.packet.VlanId;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.NetworkResource;
28import org.onosproject.net.flow.DefaultTrafficSelector;
29import org.onosproject.net.flow.DefaultTrafficTreatment;
30import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
32import org.onosproject.net.flow.criteria.Criterion;
33import org.onosproject.net.flowobjective.DefaultFilteringObjective;
34import org.onosproject.net.flowobjective.DefaultForwardingObjective;
35import org.onosproject.net.flowobjective.DefaultNextObjective;
36import org.onosproject.net.flowobjective.FilteringObjective;
37import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
38import org.onosproject.net.flowobjective.ForwardingObjective;
39import org.onosproject.net.flowobjective.NextObjective;
40import org.onosproject.net.flowobjective.Objective;
41import org.onosproject.net.flowobjective.ObjectiveError;
42import org.onosproject.net.intent.FlowObjectiveIntent;
43import org.onosproject.net.intent.Intent;
44import org.onosproject.net.intent.IntentData;
45import org.onosproject.net.intent.IntentInstallationContext;
46import org.onosproject.net.intent.IntentOperationContext;
47import org.onosproject.net.intent.IntentState;
48import org.onosproject.store.service.WallClockTimestamp;
49
50import java.util.List;
51import java.util.Set;
52
53import static org.junit.Assert.*;
54import static org.onosproject.net.flowobjective.ObjectiveError.*;
55
56/**
57 * Tests for flow objective Intent installer.
58 */
59public class FlowObjectiveIntentInstallerTest extends AbstractIntentInstallerTest {
60 private static final int NEXT_ID_1 = 1;
61 protected FlowObjectiveIntentInstaller installer;
62 protected TestFlowObjectiveService flowObjectiveService;
63
64 @Before
65 public void setup() {
66 super.setup();
67 flowObjectiveService = new TestFlowObjectiveService();
68 installer = new FlowObjectiveIntentInstaller();
69 installer.flowObjectiveService = flowObjectiveService;
70 installer.trackerService = trackerService;
71 installer.intentExtensionService = intentExtensionService;
72 installer.intentInstallCoordinator = intentInstallCoordinator;
73
74 installer.activate();
75 }
76
77 @After
78 public void tearDown() {
79 super.tearDown();
80 installer.deactivated();
81 }
82
83 /**
84 * Installs flow objective Intents.
85 */
86 @Test
87 public void testInstallIntent() {
88 List<Intent> intentsToUninstall = Lists.newArrayList();
89 List<Intent> intentsToInstall = createFlowObjectiveIntents();
90
91 IntentData toUninstall = null;
92 IntentData toInstall = new IntentData(createP2PIntent(),
93 IntentState.INSTALLING,
94 new WallClockTimestamp());
95 toInstall = new IntentData(toInstall, intentsToInstall);
96
97
98 IntentOperationContext<FlowObjectiveIntent> operationContext;
99 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
100 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
101
102 installer.apply(operationContext);
103
104 IntentOperationContext successContext = intentInstallCoordinator.successContext;
105 assertEquals(successContext, operationContext);
106 }
107
108 /**
109 * Uninstalls flow objective Intents.
110 */
111 @Test
112 public void testUninstallIntent() {
113 List<Intent> intentsToUninstall = createFlowObjectiveIntents();
114 List<Intent> intentsToInstall = Lists.newArrayList();
115
116
117 IntentData toInstall = null;
118 IntentData toUninstall = new IntentData(createP2PIntent(),
119 IntentState.WITHDRAWING,
120 new WallClockTimestamp());
121 toUninstall = new IntentData(toUninstall, intentsToUninstall);
122 IntentOperationContext<FlowObjectiveIntent> operationContext;
123 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
124 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
125
126 installer.apply(operationContext);
127
128 IntentOperationContext successContext = intentInstallCoordinator.successContext;
129 assertEquals(successContext, operationContext);
130 }
131
132 /**
133 * Do both uninstall and install flow objective Intents.
134 */
135 @Test
136 public void testUninstallAndInstallIntent() {
137 List<Intent> intentsToUninstall = createFlowObjectiveIntents();
138 List<Intent> intentsToInstall = createAnotherFlowObjectiveIntents();
139 IntentData toInstall = new IntentData(createP2PIntent(),
140 IntentState.INSTALLING,
141 new WallClockTimestamp());
142 toInstall = new IntentData(toInstall, intentsToInstall);
143 IntentData toUninstall = new IntentData(createP2PIntent(),
144 IntentState.INSTALLED,
145 new WallClockTimestamp());
146 toUninstall = new IntentData(toUninstall, intentsToUninstall);
147
148 IntentOperationContext<FlowObjectiveIntent> operationContext;
149 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
150 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
151
152 installer.apply(operationContext);
153
154 IntentOperationContext successContext = intentInstallCoordinator.successContext;
155 assertEquals(successContext, operationContext);
156 }
157
158 /**
159 * Nothing to uninstall or install.
160 */
161 @Test
162 public void testNoAnyIntentToApply() {
163 IntentData toInstall = null;
164 IntentData toUninstall = null;
165 IntentOperationContext<FlowObjectiveIntent> operationContext;
166 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
167 operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
168 installer.apply(operationContext);
169
170 IntentOperationContext successContext = intentInstallCoordinator.successContext;
171 assertEquals(successContext, operationContext);
172 }
173
174 /*
175 * Error handling
176 */
177 IntentOperationContext context;
178 IntentOperationContext failedContext;
179 IntentOperationContext successContext;
180 List<ObjectiveError> errors;
181
182 /**
183 * Handles UNSUPPORTED error.
184 */
185 @Test
186 public void testUnsupportedError() {
187 // Unsupported, should just failed
188 intentInstallCoordinator = new TestIntentInstallCoordinator();
189 installer.intentInstallCoordinator = intentInstallCoordinator;
190 installer.flowObjectiveService = new TestFailedFlowObjectiveService();
191 context = createInstallContext();
192 installer.apply(context);
193 assertEquals(intentInstallCoordinator.failedContext, context);
194 }
195
196 /**
197 * Handles FLOWINSTALLATIONFAILED error with touch the threshold.
198 */
199 @Test
200 public void testFlowInstallationFailedError() {
201 // flow install failed, should retry until retry threshold
202 intentInstallCoordinator = new TestIntentInstallCoordinator();
203 installer.intentInstallCoordinator = intentInstallCoordinator;
204 errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
205 FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
206 FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED,
207 FLOWINSTALLATIONFAILED);
208 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
209 context = createInstallContext();
210 installer.apply(context);
211 failedContext = intentInstallCoordinator.failedContext;
212 assertEquals(failedContext, context);
213 }
214
215 /**
216 * Handles FLOWINSTALLATIONFAILED error without touch the threshold.
217 */
218 @Test
219 public void testFlowInstallationFailedErrorUnderThreshold() {
220 // And retry two times and success
221 intentInstallCoordinator = new TestIntentInstallCoordinator();
222 installer.intentInstallCoordinator = intentInstallCoordinator;
223 errors = ImmutableList.of(FLOWINSTALLATIONFAILED, FLOWINSTALLATIONFAILED);
224 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
225 context = createInstallContext();
226 installer.apply(context);
227 successContext = intentInstallCoordinator.successContext;
228 assertEquals(successContext, context);
229 }
230
231 /**
232 * Handles GROUPINSTALLATIONFAILED error with touch the threshold.
233 */
234 @Test
235 public void testGroupInstallationFailedError() {
236 // Group install failed, and retry threshold exceed
237 intentInstallCoordinator = new TestIntentInstallCoordinator();
238 installer.intentInstallCoordinator = intentInstallCoordinator;
239 errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
240 GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
241 GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED,
242 GROUPINSTALLATIONFAILED);
243 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
244 context = createInstallContext();
245 installer.apply(context);
246 failedContext = intentInstallCoordinator.failedContext;
247 assertEquals(failedContext, context);
248
249 }
250
251 /**
252 * Handles GROUPINSTALLATIONFAILED error without touch the threshold.
253 */
254 @Test
255 public void testGroupInstallationFailedErrorUnderThreshold() {
256 // group install failed, and retry two times.
257 intentInstallCoordinator = new TestIntentInstallCoordinator();
258 installer.intentInstallCoordinator = intentInstallCoordinator;
259 errors = ImmutableList.of(GROUPINSTALLATIONFAILED, GROUPINSTALLATIONFAILED);
260 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
261 context = createInstallContext();
262 installer.apply(context);
263 successContext = intentInstallCoordinator.successContext;
264 assertEquals(successContext, context);
265
266 }
267
268 /**
269 * Handles GROUPEXISTS error.
270 */
271 @Test
272 public void testGroupExistError() {
273 // group exists, retry by using add to exist
274 intentInstallCoordinator = new TestIntentInstallCoordinator();
275 installer.intentInstallCoordinator = intentInstallCoordinator;
276 errors = ImmutableList.of(GROUPEXISTS);
277 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
278 context = createInstallContext();
279 installer.apply(context);
280 successContext = intentInstallCoordinator.successContext;
281 assertEquals(successContext, context);
282 }
283
284 /**
285 * Handles GROUPMISSING error with ADD_TO_EXIST operation.
286 */
287 @Test
288 public void testGroupMissingError() {
289 // group exist -> group missing -> add group
290 intentInstallCoordinator = new TestIntentInstallCoordinator();
291 installer.intentInstallCoordinator = intentInstallCoordinator;
292 errors = ImmutableList.of(GROUPEXISTS, GROUPMISSING);
293 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
294 context = createInstallContext();
295 installer.apply(context);
296 successContext = intentInstallCoordinator.successContext;
297 assertEquals(successContext, context);
298 }
299
300 /**
301 * Handles GROUPMISSING error with ADD operation.
302 */
303 @Test
304 public void testGroupChainElementMissingError() {
305 // group chain element missing
306 intentInstallCoordinator = new TestIntentInstallCoordinator();
307 installer.intentInstallCoordinator = intentInstallCoordinator;
308 errors = ImmutableList.of(GROUPMISSING);
309 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
310 context = createInstallContext();
311 installer.apply(context);
312 successContext = intentInstallCoordinator.successContext;
313 assertEquals(successContext, context);
314 }
315
316 /**
317 * Handles GROUPMISSING error with REMOVE operation.
318 */
319 @Test
320 public void testGroupAlreadyRemoved() {
321 // group already removed
322 intentInstallCoordinator = new TestIntentInstallCoordinator();
323 installer.intentInstallCoordinator = intentInstallCoordinator;
324 errors = ImmutableList.of(GROUPMISSING);
325 installer.flowObjectiveService = new TestFailedFlowObjectiveService(errors);
326 context = createUninstallContext();
327 installer.apply(context);
328 successContext = intentInstallCoordinator.successContext;
329 assertEquals(successContext, context);
330 }
331
332 /**
333 * Creates Intent operation context for uninstall Intents.
334 *
335 * @return the context
336 */
337 private IntentOperationContext createUninstallContext() {
338 List<Intent> intentsToUninstall = createFlowObjectiveIntents();
339 List<Intent> intentsToInstall = Lists.newArrayList();
340 IntentData toInstall = null;
341 IntentData toUninstall = new IntentData(createP2PIntent(),
342 IntentState.INSTALLING,
343 new WallClockTimestamp());
344 toUninstall = new IntentData(toUninstall, intentsToUninstall);
345 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
346 return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
347 }
348
349 /**
350 * Creates Intent operation context for install Intents.
351 *
352 * @return the context
353 */
354 private IntentOperationContext createInstallContext() {
355 List<Intent> intentsToUninstall = Lists.newArrayList();
356 List<Intent> intentsToInstall = createFlowObjectiveIntents();
357 IntentData toUninstall = null;
358 IntentData toInstall = new IntentData(createP2PIntent(),
359 IntentState.INSTALLING,
360 new WallClockTimestamp());
361 toInstall = new IntentData(toInstall, intentsToInstall);
362 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
363 return new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
364 }
365
366 /**
367 * Creates flow objective Intents.
368 *
369 * @return the flow objective intents
370 */
371 private List<Intent> createFlowObjectiveIntents() {
372 TrafficSelector selector = DefaultTrafficSelector.builder()
373 .matchInPort(CP1.port())
374 .build();
375 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
376 .setOutput(CP2.port())
377 .build();
378
379 FilteringObjective filt = DefaultFilteringObjective.builder()
380 .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
381 .withPriority(DEFAULT_PRIORITY)
382 .fromApp(APP_ID)
383 .permit()
384 .add();
385
386 NextObjective next = DefaultNextObjective.builder()
387 .withMeta(selector)
388 .addTreatment(treatment)
389 .makePermanent()
390 .withPriority(DEFAULT_PRIORITY)
391 .fromApp(APP_ID)
392 .withType(NextObjective.Type.SIMPLE)
393 .withId(NEXT_ID_1)
394 .add();
395
396 ForwardingObjective fwd = DefaultForwardingObjective.builder()
397 .withSelector(selector)
398 .fromApp(APP_ID)
399 .withPriority(DEFAULT_PRIORITY)
400 .makePermanent()
401 .withFlag(ForwardingObjective.Flag.SPECIFIC)
402 .nextStep(NEXT_ID_1)
403 .add();
404
405 List<Objective> objectives = ImmutableList.of(filt, next, fwd);
406 List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
407 List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
408
409 Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
410 return ImmutableList.of(intent);
411 }
412
413 /**
414 * Creates flow objective Intents with different selector.
415 *
416 * @return the flow objective Intents
417 */
418 private List<Intent> createAnotherFlowObjectiveIntents() {
419 TrafficSelector selector = DefaultTrafficSelector.builder()
420 .matchVlanId(VlanId.vlanId("100"))
421 .matchInPort(CP1.port())
422 .build();
423 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
424 .setOutput(CP2.port())
425 .build();
426
427 FilteringObjective filt = DefaultFilteringObjective.builder()
428 .addCondition(selector.getCriterion(Criterion.Type.IN_PORT))
429 .addCondition(selector.getCriterion(Criterion.Type.VLAN_VID))
430 .withPriority(DEFAULT_PRIORITY)
431 .fromApp(APP_ID)
432 .permit()
433 .add();
434
435 NextObjective next = DefaultNextObjective.builder()
436 .withMeta(selector)
437 .addTreatment(treatment)
438 .makePermanent()
439 .withPriority(DEFAULT_PRIORITY)
440 .fromApp(APP_ID)
441 .withType(NextObjective.Type.SIMPLE)
442 .withId(NEXT_ID_1)
443 .add();
444
445 ForwardingObjective fwd = DefaultForwardingObjective.builder()
446 .withSelector(selector)
447 .fromApp(APP_ID)
448 .withPriority(DEFAULT_PRIORITY)
449 .makePermanent()
450 .withFlag(ForwardingObjective.Flag.SPECIFIC)
451 .nextStep(NEXT_ID_1)
452 .add();
453
454 List<Objective> objectives = ImmutableList.of(filt, next, fwd);
455 List<DeviceId> deviceIds = ImmutableList.of(CP1.deviceId(), CP1.deviceId(), CP1.deviceId());
456 List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
457
458 Intent intent = new FlowObjectiveIntent(APP_ID, KEY1, deviceIds, objectives, resources, RG1);
459 return ImmutableList.of(intent);
460 }
461
462 /**
463 * Flow objective service for test; always successful for every flow objectives.
464 */
465 class TestFlowObjectiveService extends FlowObjectiveServiceAdapter {
466 List<DeviceId> devices = Lists.newArrayList();
467 List<Objective> objectives = Lists.newArrayList();
468
469 @Override
470 public void apply(DeviceId deviceId, Objective objective) {
471 devices.add(deviceId);
472 objectives.add(objective);
473 objective.context().ifPresent(context -> context.onSuccess(objective));
474 }
475 }
476
477 /**
478 * Flow objective service for test; contains errors for every flow objective
479 * submission.
480 */
481 class TestFailedFlowObjectiveService extends TestFlowObjectiveService {
482 private final Set<ObjectiveError> groupErrors =
483 ImmutableSet.of(GROUPEXISTS, GROUPINSTALLATIONFAILED,
484 GROUPMISSING, GROUPREMOVALFAILED);
485
486 /**
487 * Error states to test error handler by given error queue
488 * e.g.
489 * FLOWINSTALLATIONFAILED -> FLOWINSTALLATIONFAILED -> null: should be success
490 * FLOWINSTALLATIONFAILED -> five same error -> .... : should be failed
491 */
492 List<ObjectiveError> errors;
493
494 public TestFailedFlowObjectiveService() {
495 errors = Lists.newArrayList();
496 errors.add(UNSUPPORTED);
497 }
498
499 public TestFailedFlowObjectiveService(List<ObjectiveError> errors) {
500 this.errors = Lists.newArrayList(errors);
501 }
502
503 @Override
504 public void apply(DeviceId deviceId, Objective objective) {
505 if (errors.size() != 0) {
506 if (groupErrors.contains(errors.get(0)) && objective instanceof NextObjective) {
507 ObjectiveError error = errors.remove(0);
508 objective.context().ifPresent(context -> context.onError(objective, error));
509 return;
510 }
511 if (!groupErrors.contains(errors.get(0)) && !(objective instanceof NextObjective)) {
512 ObjectiveError error = errors.remove(0);
513 objective.context().ifPresent(context -> context.onError(objective, error));
514 return;
515 }
516 }
517 objective.context().ifPresent(context -> context.onSuccess(objective));
518
519 }
520 }
521}