blob: 5c00a8387d75db1b9773671e1745aed95c888d0e [file] [log] [blame]
Yi Tsengc927a062017-05-02 15:02:37 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tsengc927a062017-05-02 15:02:37 -07003 *
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.Lists;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010021import com.google.common.collect.Maps;
Yi Tsengc927a062017-05-02 15:02:37 -070022import com.google.common.collect.Sets;
23import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
26import org.onlab.packet.VlanId;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010027import org.onosproject.cfg.ComponentConfigService;
28import org.onosproject.net.ConnectPoint;
David Glantz0a5779c2021-09-22 14:34:14 -050029import org.onosproject.net.DeviceId;
Yi Tsengc927a062017-05-02 15:02:37 -070030import org.onosproject.net.NetworkResource;
David Glantz0a5779c2021-09-22 14:34:14 -050031import org.onosproject.net.flow.DefaultFlowEntry;
Yi Tsengc927a062017-05-02 15:02:37 -070032import org.onosproject.net.flow.DefaultFlowRule;
33import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
David Glantz0a5779c2021-09-22 14:34:14 -050035import org.onosproject.net.flow.FlowEntry;
Yi Tsengc927a062017-05-02 15:02:37 -070036import org.onosproject.net.flow.FlowRule;
Pier68c025b2018-03-26 17:56:18 -070037import org.onosproject.net.flow.FlowRuleOperation;
Yi Tsengc927a062017-05-02 15:02:37 -070038import org.onosproject.net.flow.FlowRuleOperations;
39import org.onosproject.net.flow.FlowRuleServiceAdapter;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
42import org.onosproject.net.intent.FlowRuleIntent;
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.net.intent.PathIntent;
49import org.onosproject.store.service.WallClockTimestamp;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010050import org.onosproject.store.trivial.SimpleIntentStore;
Yi Tsengc927a062017-05-02 15:02:37 -070051
52import java.util.Collection;
53import java.util.List;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010054import java.util.Map;
Yi Tsengc927a062017-05-02 15:02:37 -070055import java.util.Set;
56import java.util.stream.Collectors;
57
Antonio Marsico4f68ec92017-03-09 11:16:32 +010058import static org.easymock.EasyMock.mock;
59import static org.junit.Assert.assertEquals;
60import static org.junit.Assert.assertTrue;
Pier68c025b2018-03-26 17:56:18 -070061import static org.onosproject.net.flow.FlowRuleOperation.Type.ADD;
62import static org.onosproject.net.flow.FlowRuleOperation.Type.REMOVE;
Yi Tsengc927a062017-05-02 15:02:37 -070063
64/**
65 * Tests for flow rule Intent installer.
66 */
67public class FlowRuleIntentInstallerTest extends AbstractIntentInstallerTest {
68
69 private TestFlowRuleService flowRuleService;
Pier68c025b2018-03-26 17:56:18 -070070 private final TestFlowRuleServiceNonDisruptive flowRuleServiceNonDisruptive =
71 new TestFlowRuleServiceNonDisruptive();
Yi Tsengc927a062017-05-02 15:02:37 -070072 private FlowRuleIntentInstaller installer;
73
74 @Before
75 public void setup() {
76 super.setup();
77 flowRuleService = new TestFlowRuleService();
78 installer = new FlowRuleIntentInstaller();
79 installer.flowRuleService = flowRuleService;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010080 installer.store = new SimpleIntentStore();
Yi Tsengc927a062017-05-02 15:02:37 -070081 installer.intentExtensionService = intentExtensionService;
82 installer.intentInstallCoordinator = intentInstallCoordinator;
83 installer.trackerService = trackerService;
Antonio Marsico4f68ec92017-03-09 11:16:32 +010084 installer.configService = mock(ComponentConfigService.class);
Yi Tsengc927a062017-05-02 15:02:37 -070085
86 installer.activate();
87 }
88
89 @After
90 public void tearDown() {
91 super.tearDown();
92 installer.deactivated();
93 }
94
95 /**
96 * Installs Intents only, no Intents to be uninstall.
97 */
98 @Test
99 public void testInstallOnly() {
100 List<Intent> intentsToUninstall = Lists.newArrayList();
101 List<Intent> intentsToInstall = createFlowRuleIntents();
102
103 IntentData toUninstall = null;
104 IntentData toInstall = new IntentData(createP2PIntent(),
105 IntentState.INSTALLING,
106 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800107 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700108
109
110 IntentOperationContext<FlowRuleIntent> operationContext;
111 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
112 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
113
114 installer.apply(operationContext);
115
116 IntentOperationContext successContext = intentInstallCoordinator.successContext;
117 assertEquals(successContext, operationContext);
118
119 Set<FlowRule> expectedFlowRules = intentsToInstall.stream()
120 .map(intent -> (FlowRuleIntent) intent)
121 .map(FlowRuleIntent::flowRules)
122 .flatMap(Collection::stream)
123 .collect(Collectors.toSet());
124
125 assertEquals(expectedFlowRules, flowRuleService.flowRulesAdd);
126 }
127
128 /**
129 * Uninstalls Intents only, no Intents to be install.
130 */
131 @Test
132 public void testUninstallOnly() {
133 List<Intent> intentsToInstall = Lists.newArrayList();
134 List<Intent> intentsToUninstall = createFlowRuleIntents();
135
136 IntentData toInstall = null;
137 IntentData toUninstall = new IntentData(createP2PIntent(),
138 IntentState.WITHDRAWING,
139 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800140 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700141
142
143 IntentOperationContext<FlowRuleIntent> operationContext;
144 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
145 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
146
David Glantz0a5779c2021-09-22 14:34:14 -0500147 flowRuleService.load(operationContext.intentsToUninstall());
148
Yi Tsengc927a062017-05-02 15:02:37 -0700149 installer.apply(operationContext);
150
151 IntentOperationContext successContext = intentInstallCoordinator.successContext;
152 assertEquals(successContext, operationContext);
153
154 Set<FlowRule> expectedFlowRules = intentsToUninstall.stream()
155 .map(intent -> (FlowRuleIntent) intent)
156 .map(FlowRuleIntent::flowRules)
157 .flatMap(Collection::stream)
158 .collect(Collectors.toSet());
159
160 assertEquals(expectedFlowRules, flowRuleService.flowRulesRemove);
161 }
162
163 /**
David Glantz0a5779c2021-09-22 14:34:14 -0500164 * Uninstalls Intents only, no Intents to be install. However, the flow rules do not exist
165 * in the FlowRuleService.
166 */
167 @Test
168 public void testUninstallOnlyMissing() {
169 List<Intent> intentsToInstall = Lists.newArrayList();
170 List<Intent> intentsToUninstall = createFlowRuleIntents();
171
172 IntentData toInstall = null;
173 IntentData toUninstall = new IntentData(createP2PIntent(),
174 IntentState.WITHDRAWING,
175 new WallClockTimestamp());
176 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
177
178
179 IntentOperationContext<FlowRuleIntent> operationContext;
180 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
181 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
182
183 installer.apply(operationContext);
184
185 IntentOperationContext successContext = intentInstallCoordinator.successContext;
186 assertEquals(successContext, operationContext);
187
188 assertEquals(0, flowRuleService.flowRulesRemove.size());
189 assertEquals(0, flowRuleService.flowRulesAdd.size());
190 assertEquals(0, flowRuleService.flowRulesModify.size());
191 }
192
193 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700194 * Do both install and uninstall Intents with different flow rules.
195 */
196 @Test
197 public void testUninstallAndInstall() {
198 List<Intent> intentsToInstall = createAnotherFlowRuleIntents();
199 List<Intent> intentsToUninstall = createFlowRuleIntents();
200
201 IntentData toInstall = new IntentData(createP2PIntent(),
202 IntentState.INSTALLING,
203 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800204 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700205 IntentData toUninstall = new IntentData(createP2PIntent(),
206 IntentState.INSTALLED,
207 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800208 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700209
210 IntentOperationContext<FlowRuleIntent> operationContext;
211 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
212 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
213
David Glantz0a5779c2021-09-22 14:34:14 -0500214 flowRuleService.load(operationContext.intentsToUninstall());
215
Yi Tsengc927a062017-05-02 15:02:37 -0700216 installer.apply(operationContext);
217
218 IntentOperationContext successContext = intentInstallCoordinator.successContext;
219 assertEquals(successContext, operationContext);
220
221 Set<FlowRule> expectedFlowRules = intentsToUninstall.stream()
222 .map(intent -> (FlowRuleIntent) intent)
223 .map(FlowRuleIntent::flowRules)
224 .flatMap(Collection::stream)
225 .collect(Collectors.toSet());
226
227 assertEquals(expectedFlowRules, flowRuleService.flowRulesRemove);
228
229 expectedFlowRules = intentsToInstall.stream()
230 .map(intent -> (FlowRuleIntent) intent)
231 .map(FlowRuleIntent::flowRules)
232 .flatMap(Collection::stream)
233 .collect(Collectors.toSet());
234
235 assertEquals(expectedFlowRules, flowRuleService.flowRulesAdd);
236 }
237
238 /**
David Glantz0a5779c2021-09-22 14:34:14 -0500239 * Do both install and uninstall Intents with different flow rules. However, the flow rules do not exist
240 * in the FlowRuleService.
241 */
242 @Test
243 public void testUninstallAndInstallMissing() {
244 List<Intent> intentsToInstall = createAnotherFlowRuleIntents();
245 List<Intent> intentsToUninstall = createFlowRuleIntents();
246
247 IntentData toInstall = new IntentData(createP2PIntent(),
248 IntentState.INSTALLING,
249 new WallClockTimestamp());
250 toInstall = IntentData.compiled(toInstall, intentsToInstall);
251 IntentData toUninstall = new IntentData(createP2PIntent(),
252 IntentState.INSTALLED,
253 new WallClockTimestamp());
254 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
255
256 IntentOperationContext<FlowRuleIntent> operationContext;
257 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
258 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
259
260 installer.apply(operationContext);
261
262 IntentOperationContext successContext = intentInstallCoordinator.successContext;
263 assertEquals(successContext, operationContext);
264
265 Set<FlowRule> expectedFlowRules = Sets.newHashSet();
266
267 assertEquals(expectedFlowRules, flowRuleService.flowRulesRemove);
268
269 expectedFlowRules = intentsToInstall.stream()
270 .map(intent -> (FlowRuleIntent) intent)
271 .map(FlowRuleIntent::flowRules)
272 .flatMap(Collection::stream)
273 .collect(Collectors.toSet());
274
275 assertEquals(expectedFlowRules, flowRuleService.flowRulesAdd);
276 }
277
278 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700279 * Do both install and uninstall Intents with same flow rules.
280 */
281 @Test
282 public void testUninstallAndInstallUnchanged() {
283 List<Intent> intentsToInstall = createFlowRuleIntents();
284 List<Intent> intentsToUninstall = createFlowRuleIntents();
285
286 IntentData toInstall = new IntentData(createP2PIntent(),
287 IntentState.INSTALLING,
288 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800289 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700290 IntentData toUninstall = new IntentData(createP2PIntent(),
291 IntentState.INSTALLED,
292 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800293 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700294
295 IntentOperationContext<FlowRuleIntent> operationContext;
296 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
297 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
298
David Glantz0a5779c2021-09-22 14:34:14 -0500299 flowRuleService.load(operationContext.intentsToUninstall());
300
Yi Tsengc927a062017-05-02 15:02:37 -0700301 installer.apply(operationContext);
302
303 IntentOperationContext successContext = intentInstallCoordinator.successContext;
304 assertEquals(successContext, operationContext);
305
306 assertEquals(0, flowRuleService.flowRulesRemove.size());
307 assertEquals(0, flowRuleService.flowRulesAdd.size());
Yi Tsengc29d8822017-10-25 16:19:25 -0700308 assertEquals(0, flowRuleService.flowRulesModify.size());
Yi Tsengc927a062017-05-02 15:02:37 -0700309 }
310
311 /**
David Glantz0a5779c2021-09-22 14:34:14 -0500312 * Do both install and uninstall Intents with same flow rules. However, the flow rules do not exist
313 * in the FlowRuleService.
314 */
315 @Test
316 public void testUninstallAndInstallUnchangedMissing() {
317 List<Intent> intentsToInstall = createFlowRuleIntents();
318 List<Intent> intentsToUninstall = createFlowRuleIntents();
319
320 IntentData toInstall = new IntentData(createP2PIntent(),
321 IntentState.INSTALLING,
322 new WallClockTimestamp());
323 toInstall = IntentData.compiled(toInstall, intentsToInstall);
324 IntentData toUninstall = new IntentData(createP2PIntent(),
325 IntentState.INSTALLED,
326 new WallClockTimestamp());
327 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
328
329 IntentOperationContext<FlowRuleIntent> operationContext;
330 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
331 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
332
333 installer.apply(operationContext);
334
335 IntentOperationContext successContext = intentInstallCoordinator.successContext;
336 assertEquals(successContext, operationContext);
337
338 assertEquals(0, flowRuleService.flowRulesRemove.size());
339 assertEquals(1, flowRuleService.flowRulesAdd.size());
340 assertEquals(0, flowRuleService.flowRulesModify.size());
341 }
342
343 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700344 * Do both install and uninstall Intents with same flow rule Intent.
345 */
346 @Test
347 public void testUninstallAndInstallSame() {
348 List<Intent> intentsToInstall = createFlowRuleIntents();
349 List<Intent> intentsToUninstall = intentsToInstall;
350
351 IntentData toInstall = new IntentData(createP2PIntent(),
352 IntentState.INSTALLING,
353 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800354 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700355 IntentData toUninstall = new IntentData(createP2PIntent(),
356 IntentState.INSTALLED,
357 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800358 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700359
360 IntentOperationContext<FlowRuleIntent> operationContext;
361 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
362 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
363
David Glantz0a5779c2021-09-22 14:34:14 -0500364 flowRuleService.load(operationContext.intentsToUninstall());
365
Yi Tsengc927a062017-05-02 15:02:37 -0700366 installer.apply(operationContext);
367
368 IntentOperationContext successContext = intentInstallCoordinator.successContext;
369 assertEquals(successContext, operationContext);
370
371 assertEquals(0, flowRuleService.flowRulesRemove.size());
372 assertEquals(0, flowRuleService.flowRulesAdd.size());
Yi Tsengc29d8822017-10-25 16:19:25 -0700373 assertEquals(0, flowRuleService.flowRulesModify.size());
Yi Tsengc927a062017-05-02 15:02:37 -0700374 }
375
376 /**
David Glantz0a5779c2021-09-22 14:34:14 -0500377 * Do both install and uninstall Intents with same flow rule Intent. However, the flow rules do not exist
378 * in the FlowRuleService.
379 */
380 @Test
381 public void testUninstallAndInstallSameMissing() {
382 List<Intent> intentsToInstall = createFlowRuleIntents();
383 List<Intent> intentsToUninstall = intentsToInstall;
384
385 IntentData toInstall = new IntentData(createP2PIntent(),
386 IntentState.INSTALLING,
387 new WallClockTimestamp());
388 toInstall = IntentData.compiled(toInstall, intentsToInstall);
389 IntentData toUninstall = new IntentData(createP2PIntent(),
390 IntentState.INSTALLED,
391 new WallClockTimestamp());
392 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
393
394 IntentOperationContext<FlowRuleIntent> operationContext;
395 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
396 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
397
398 installer.apply(operationContext);
399
400 IntentOperationContext successContext = intentInstallCoordinator.successContext;
401 assertEquals(successContext, operationContext);
402
403 assertEquals(0, flowRuleService.flowRulesRemove.size());
404 assertEquals(1, flowRuleService.flowRulesAdd.size());
405 assertEquals(0, flowRuleService.flowRulesModify.size());
406 }
407
408 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700409 * Nothing to uninstall or install.
410 */
411 @Test
412 public void testNoAnyIntentToApply() {
413 IntentData toInstall = null;
414 IntentData toUninstall = null;
415 IntentOperationContext<FlowRuleIntent> operationContext;
416 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
417 operationContext = new IntentOperationContext<>(ImmutableList.of(), ImmutableList.of(), context);
418 installer.apply(operationContext);
419
420 IntentOperationContext successContext = intentInstallCoordinator.successContext;
421 assertEquals(successContext, operationContext);
422
423 assertEquals(0, flowRuleService.flowRulesRemove.size());
424 assertEquals(0, flowRuleService.flowRulesAdd.size());
Yi Tsengc29d8822017-10-25 16:19:25 -0700425 assertEquals(0, flowRuleService.flowRulesModify.size());
Yi Tsengc927a062017-05-02 15:02:37 -0700426 }
427
428 /**
429 * Test if the flow installation failed.
430 */
431 @Test
432 public void testFailed() {
433 installer.flowRuleService = new TestFailedFlowRuleService();
434 List<Intent> intentsToUninstall = Lists.newArrayList();
435 List<Intent> intentsToInstall = createFlowRuleIntents();
436
437 IntentData toUninstall = null;
438 IntentData toInstall = new IntentData(createP2PIntent(),
439 IntentState.INSTALLING,
440 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800441 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc927a062017-05-02 15:02:37 -0700442
443
444 IntentOperationContext<FlowRuleIntent> operationContext;
445 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
446 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
447
448 installer.apply(operationContext);
449
450 IntentOperationContext failedContext = intentInstallCoordinator.failedContext;
451 assertEquals(failedContext, operationContext);
452 }
453
454 /**
Yi Tsengc29d8822017-10-25 16:19:25 -0700455 * Test intents with same match rules, should do modify instead of add.
456 */
457 @Test
458 public void testRuleModify() {
459 List<Intent> intentsToInstall = createFlowRuleIntents();
460 List<Intent> intentsToUninstall = createFlowRuleIntentsWithSameMatch();
461
462 IntentData toInstall = new IntentData(createP2PIntent(),
463 IntentState.INSTALLING,
464 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800465 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Yi Tsengc29d8822017-10-25 16:19:25 -0700466 IntentData toUninstall = new IntentData(createP2PIntent(),
467 IntentState.INSTALLED,
468 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800469 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Yi Tsengc29d8822017-10-25 16:19:25 -0700470
471 IntentOperationContext<FlowRuleIntent> operationContext;
472 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
473 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
474
David Glantz0a5779c2021-09-22 14:34:14 -0500475 flowRuleService.load(operationContext.intentsToUninstall());
476
Yi Tsengc29d8822017-10-25 16:19:25 -0700477 installer.apply(operationContext);
478
479 IntentOperationContext successContext = intentInstallCoordinator.successContext;
480 assertEquals(successContext, operationContext);
481
482 assertEquals(0, flowRuleService.flowRulesRemove.size());
483 assertEquals(0, flowRuleService.flowRulesAdd.size());
484 assertEquals(1, flowRuleService.flowRulesModify.size());
485
486 FlowRuleIntent installedIntent = (FlowRuleIntent) intentsToInstall.get(0);
487 assertEquals(flowRuleService.flowRulesModify.size(), installedIntent.flowRules().size());
488 assertTrue(flowRuleService.flowRulesModify.containsAll(installedIntent.flowRules()));
489 }
490
491 /**
David Glantz0a5779c2021-09-22 14:34:14 -0500492 * Test intents with same match rules, should do modify instead of add. However, the flow rules do not exist
493 * in the FlowRuleService.
494 */
495 @Test
496 public void testRuleModifyMissing() {
497 List<Intent> intentsToInstall = createFlowRuleIntents();
498 List<Intent> intentsToUninstall = createFlowRuleIntentsWithSameMatch();
499
500 IntentData toInstall = new IntentData(createP2PIntent(),
501 IntentState.INSTALLING,
502 new WallClockTimestamp());
503 toInstall = IntentData.compiled(toInstall, intentsToInstall);
504 IntentData toUninstall = new IntentData(createP2PIntent(),
505 IntentState.INSTALLED,
506 new WallClockTimestamp());
507 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
508
509 IntentOperationContext<FlowRuleIntent> operationContext;
510 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
511 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
512
513 installer.apply(operationContext);
514
515 IntentOperationContext successContext = intentInstallCoordinator.successContext;
516 assertEquals(successContext, operationContext);
517
518 assertEquals(0, flowRuleService.flowRulesRemove.size());
519 assertEquals(1, flowRuleService.flowRulesAdd.size());
520 assertEquals(0, flowRuleService.flowRulesModify.size());
521
522 FlowRuleIntent installedIntent = (FlowRuleIntent) intentsToInstall.get(0);
523 assertEquals(flowRuleService.flowRulesAdd.size(), installedIntent.flowRules().size());
524 assertTrue(flowRuleService.flowRulesAdd.containsAll(installedIntent.flowRules()));
525 }
526
527 /**
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100528 * Testing the non-disruptive reallocation.
529 */
530 @Test
531 public void testUninstallAndInstallNonDisruptive() throws InterruptedException {
532
533 installer.flowRuleService = flowRuleServiceNonDisruptive;
534
535 List<Intent> intentsToInstall = createAnotherFlowRuleIntentsNonDisruptive();
536 List<Intent> intentsToUninstall = createFlowRuleIntentsNonDisruptive();
537
538 IntentData toInstall = new IntentData(createP2PIntentNonDisruptive(),
539 IntentState.INSTALLING,
540 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800541 toInstall = IntentData.compiled(toInstall, intentsToInstall);
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100542 IntentData toUninstall = new IntentData(createP2PIntentNonDisruptive(),
543 IntentState.INSTALLED,
544 new WallClockTimestamp());
Ray Milkeye1077f82019-02-20 09:31:12 -0800545 toUninstall = IntentData.compiled(toUninstall, intentsToUninstall);
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100546
547 IntentOperationContext<FlowRuleIntent> operationContext;
548 IntentInstallationContext context = new IntentInstallationContext(toUninstall, toInstall);
549 operationContext = new IntentOperationContext(intentsToUninstall, intentsToInstall, context);
550
551 installer.apply(operationContext);
552
553 //A single FlowRule is evaluated for every non-disruptive stage
554 TrafficSelector selector = DefaultTrafficSelector.builder()
555 .matchInPhyPort(CP1.port())
556 .build();
557 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
558 .setOutput(CP3.port())
559 .build();
560
561 FlowRule firstStageInstalledRule = DefaultFlowRule.builder()
562 .forDevice(CP1.deviceId())
563 .withSelector(selector)
564 .withTreatment(treatment)
565 .fromApp(APP_ID)
566 .withPriority(DEFAULT_PRIORITY - 1)
567 .makePermanent()
568 .build();
569
Pier68c025b2018-03-26 17:56:18 -0700570 // We need to wait a bit in order to avoid
571 // race conditions and failing builds
572 synchronized (flowRuleServiceNonDisruptive) {
573 while (!verifyFlowRule(ADD, firstStageInstalledRule)) {
574 flowRuleServiceNonDisruptive.wait();
575 }
576 }
577
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100578 assertTrue(flowRuleServiceNonDisruptive.flowRulesAdd.contains(firstStageInstalledRule));
579
580 selector = DefaultTrafficSelector.builder()
581 .matchInPhyPort(CP4_2.port())
582 .build();
583 treatment = DefaultTrafficTreatment.builder()
584 .setOutput(CP4_1.port())
585 .build();
586
587 FlowRule secondStageUninstalledRule = DefaultFlowRule.builder()
588 .forDevice(CP4_1.deviceId())
589 .withSelector(selector)
590 .withTreatment(treatment)
591 .fromApp(APP_ID)
592 .withPriority(DEFAULT_PRIORITY)
593 .makePermanent()
594 .build();
595
Pier68c025b2018-03-26 17:56:18 -0700596 synchronized (flowRuleServiceNonDisruptive) {
597 while (!verifyFlowRule(REMOVE, secondStageUninstalledRule)) {
598 flowRuleServiceNonDisruptive.wait();
599 }
600 }
601
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100602 assertTrue(flowRuleServiceNonDisruptive.flowRulesRemove.contains(secondStageUninstalledRule));
603
604 selector = DefaultTrafficSelector.builder()
605 .matchInPhyPort(CP4_3.port())
606 .build();
607 treatment = DefaultTrafficTreatment.builder()
608 .setOutput(CP4_1.port())
609 .build();
610
611 FlowRule thirdStageInstalledRule = DefaultFlowRule.builder()
612 .forDevice(CP4_1.deviceId())
613 .withSelector(selector)
614 .withTreatment(treatment)
615 .fromApp(APP_ID)
616 .withPriority(DEFAULT_PRIORITY)
617 .makePermanent()
618 .build();
619
Pier68c025b2018-03-26 17:56:18 -0700620 synchronized (flowRuleServiceNonDisruptive) {
621 while (!verifyFlowRule(ADD, thirdStageInstalledRule)) {
622 flowRuleServiceNonDisruptive.wait();
623 }
624 }
625
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100626 assertTrue(flowRuleServiceNonDisruptive.flowRulesAdd.contains(thirdStageInstalledRule));
627
628 selector = DefaultTrafficSelector.builder()
629 .matchInPhyPort(CP2_1.port())
630 .build();
631 treatment = DefaultTrafficTreatment.builder()
632 .setOutput(CP2_2.port())
633 .build();
634
635 FlowRule lastStageUninstalledRule = DefaultFlowRule.builder()
636 .forDevice(CP2_1.deviceId())
637 .withSelector(selector)
638 .withTreatment(treatment)
639 .fromApp(APP_ID)
640 .withPriority(DEFAULT_PRIORITY)
641 .makePermanent()
642 .build();
643
Pier68c025b2018-03-26 17:56:18 -0700644 synchronized (flowRuleServiceNonDisruptive) {
645 while (!verifyFlowRule(REMOVE, lastStageUninstalledRule)) {
646 flowRuleServiceNonDisruptive.wait();
647 }
648 }
649
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100650 assertTrue(flowRuleServiceNonDisruptive.flowRulesRemove.contains(lastStageUninstalledRule));
651
652 IntentOperationContext successContext = intentInstallCoordinator.successContext;
653 assertEquals(successContext, operationContext);
654 }
655
Pier68c025b2018-03-26 17:56:18 -0700656 private boolean verifyFlowRule(FlowRuleOperation.Type type, FlowRule flowRule) {
657 return type == ADD ? flowRuleServiceNonDisruptive.flowRulesAdd.contains(flowRule) :
658 flowRuleServiceNonDisruptive.flowRulesRemove.contains(flowRule);
659 }
660
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100661 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700662 * Generates FlowRuleIntents for test.
663 *
664 * @return the FlowRuleIntents for test
665 */
666 public List<Intent> createFlowRuleIntents() {
667 TrafficSelector selector = DefaultTrafficSelector.builder()
668 .matchInPhyPort(CP1.port())
669 .build();
670 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
671 .setOutput(CP2.port())
672 .build();
673
674 FlowRule flowRule = DefaultFlowRule.builder()
675 .forDevice(CP1.deviceId())
676 .withSelector(selector)
677 .withTreatment(treatment)
678 .fromApp(APP_ID)
679 .withPriority(DEFAULT_PRIORITY)
680 .makePermanent()
681 .build();
682
683 List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
684
685 FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
686 KEY1,
687 ImmutableList.of(flowRule),
688 resources,
689 PathIntent.ProtectionType.PRIMARY,
690 RG1);
691
692 List<Intent> flowRuleIntents = Lists.newArrayList();
693 flowRuleIntents.add(intent);
694
695 return flowRuleIntents;
696 }
697
698 /**
Yi Tsengc29d8822017-10-25 16:19:25 -0700699 * Generates FlowRuleIntents for test. Flow rules in Intent should have same
700 * match as we created by createFlowRuleIntents method, but action will be
701 * different.
702 *
703 * @return the FlowRuleIntents for test
704 */
705 public List<Intent> createFlowRuleIntentsWithSameMatch() {
706 TrafficSelector selector = DefaultTrafficSelector.builder()
707 .matchInPhyPort(CP1.port())
708 .build();
709 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
710 .punt()
711 .build();
712
713 FlowRule flowRule = DefaultFlowRule.builder()
714 .forDevice(CP1.deviceId())
715 .withSelector(selector)
716 .withTreatment(treatment)
717 .fromApp(APP_ID)
718 .withPriority(DEFAULT_PRIORITY)
719 .makePermanent()
720 .build();
721
722 List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
723
724 FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
725 KEY1,
726 ImmutableList.of(flowRule),
727 resources,
728 PathIntent.ProtectionType.PRIMARY,
729 RG1);
730
731 List<Intent> flowRuleIntents = Lists.newArrayList();
732 flowRuleIntents.add(intent);
733
734 return flowRuleIntents;
735 }
736
737 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700738 * Generates another different FlowRuleIntents for test.
739 *
740 * @return the FlowRuleIntents for test
741 */
742 public List<Intent> createAnotherFlowRuleIntents() {
743 TrafficSelector selector = DefaultTrafficSelector.builder()
744 .matchVlanId(VlanId.vlanId("100"))
745 .matchInPhyPort(CP1.port())
746 .build();
747 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
748 .setOutput(CP2.port())
749 .build();
750
751 FlowRule flowRule = DefaultFlowRule.builder()
752 .forDevice(CP1.deviceId())
753 .withSelector(selector)
754 .withTreatment(treatment)
755 .fromApp(APP_ID)
756 .withPriority(DEFAULT_PRIORITY)
757 .makePermanent()
758 .build();
759
760 List<NetworkResource> resources = ImmutableList.of(CP1.deviceId());
761
762 FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
763 KEY1,
764 ImmutableList.of(flowRule),
765 resources,
766 PathIntent.ProtectionType.PRIMARY,
767 RG1);
768
769 List<Intent> flowRuleIntents = Lists.newArrayList();
770 flowRuleIntents.add(intent);
771
772 return flowRuleIntents;
773 }
774
775 /**
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100776 * Generates FlowRuleIntents for testing non-disruptive reallocation.
777 *
778 * @return the FlowRuleIntents for test
779 */
780 public List<Intent> createFlowRuleIntentsNonDisruptive() {
781
782 Map<ConnectPoint, ConnectPoint> portsAssociation = Maps.newHashMap();
783 portsAssociation.put(CP1, CP2);
784 portsAssociation.put(CP2_1, CP2_2);
785 portsAssociation.put(CP4_2, CP4_1);
786
787 List<FlowRule> flowRules = Lists.newArrayList();
788
789 for (ConnectPoint srcPoint : portsAssociation.keySet()) {
790
791 TrafficSelector selector = DefaultTrafficSelector.builder()
792 .matchInPhyPort(srcPoint.port())
793 .build();
794 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
795 .setOutput(portsAssociation.get(srcPoint).port())
796 .build();
797
798 FlowRule flowRule = DefaultFlowRule.builder()
799 .forDevice(srcPoint.deviceId())
800 .withSelector(selector)
801 .withTreatment(treatment)
802 .fromApp(APP_ID)
803 .withPriority(DEFAULT_PRIORITY)
804 .makePermanent()
805 .build();
806 flowRules.add(flowRule);
807 }
808
809
810
811 List<NetworkResource> resources = ImmutableList.of(S1_S2, S2_S4);
812
813 FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
814 KEY1,
815 flowRules,
816 resources,
817 PathIntent.ProtectionType.PRIMARY,
818 RG1);
819
820 List<Intent> flowRuleIntents = Lists.newArrayList();
821 flowRuleIntents.add(intent);
822
823 return flowRuleIntents;
824 }
825
826 /**
827 * Generates another FlowRuleIntent, going through a different path, for testing non-disruptive reallocation.
828 *
829 * @return the FlowRuleIntents for test
830 */
831 public List<Intent> createAnotherFlowRuleIntentsNonDisruptive() {
832 Map<ConnectPoint, ConnectPoint> portsAssociation = Maps.newHashMap();
833 portsAssociation.put(CP1, CP3);
834 portsAssociation.put(CP3_1, CP3_2);
835 portsAssociation.put(CP4_3, CP4_1);
836
837 List<FlowRule> flowRules = Lists.newArrayList();
838
839 for (ConnectPoint srcPoint : portsAssociation.keySet()) {
840
841 TrafficSelector selector = DefaultTrafficSelector.builder()
842 .matchInPhyPort(srcPoint.port())
843 .build();
844 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
845 .setOutput(portsAssociation.get(srcPoint).port())
846 .build();
847
848 FlowRule flowRule = DefaultFlowRule.builder()
849 .forDevice(srcPoint.deviceId())
850 .withSelector(selector)
851 .withTreatment(treatment)
852 .fromApp(APP_ID)
853 .withPriority(DEFAULT_PRIORITY)
854 .makePermanent()
855 .build();
856 flowRules.add(flowRule);
857 }
858
859
860
861 List<NetworkResource> resources = ImmutableList.of(S1_S3, S3_S4);
862
863 FlowRuleIntent intent = new FlowRuleIntent(APP_ID,
864 KEY1,
865 flowRules,
866 resources,
867 PathIntent.ProtectionType.PRIMARY,
868 RG1);
869
870 List<Intent> flowRuleIntents = Lists.newArrayList();
871 flowRuleIntents.add(intent);
872
873 return flowRuleIntents;
874 }
875
David Glantz0a5779c2021-09-22 14:34:14 -0500876
877
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100878 /**
Yi Tsengc927a062017-05-02 15:02:37 -0700879 * The FlowRuleService for test; always success for any flow rule operations.
880 */
881 class TestFlowRuleService extends FlowRuleServiceAdapter {
882
David Glantz0a5779c2021-09-22 14:34:14 -0500883 Set<FlowEntry> flowEntries = Sets.newHashSet();
Yi Tsengc927a062017-05-02 15:02:37 -0700884 Set<FlowRule> flowRulesAdd = Sets.newHashSet();
Yi Tsengc29d8822017-10-25 16:19:25 -0700885 Set<FlowRule> flowRulesModify = Sets.newHashSet();
Yi Tsengc927a062017-05-02 15:02:37 -0700886 Set<FlowRule> flowRulesRemove = Sets.newHashSet();
887
David Glantz0a5779c2021-09-22 14:34:14 -0500888 @Override
889 public FlowEntry getFlowEntry(FlowRule flowRule) {
890 for (FlowEntry entry : flowEntries) {
891 if (entry.id().equals(flowRule.id()) && entry.deviceId().equals(flowRule.deviceId())) {
892 return entry;
893 }
894 }
895 return null;
896 }
897
898 @Override
899 public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
900 return flowEntries.stream()
901 .filter(flow -> flow.deviceId().equals(deviceId))
902 .collect(Collectors.toList());
903 }
904
905 public void load(List<FlowRuleIntent> intents) {
906 for (FlowRuleIntent flowRuleIntent : intents) {
907 for (FlowRule flowRule : flowRuleIntent.flowRules()) {
908 flowEntries.add(new DefaultFlowEntry(flowRule, FlowEntry.FlowEntryState.ADDED));
909 }
910 }
911 }
912
Yi Tsengc927a062017-05-02 15:02:37 -0700913 public void record(FlowRuleOperations ops) {
914 flowRulesAdd.clear();
915 flowRulesRemove.clear();
916 ops.stages().forEach(stage -> {
917 stage.forEach(op -> {
918 switch (op.type()) {
919 case ADD:
David Glantz0a5779c2021-09-22 14:34:14 -0500920 flowEntries.add(new DefaultFlowEntry(op.rule(), FlowEntry.FlowEntryState.ADDED));
Yi Tsengc927a062017-05-02 15:02:37 -0700921 flowRulesAdd.add(op.rule());
922 break;
923 case REMOVE:
David Glantz0a5779c2021-09-22 14:34:14 -0500924 flowEntries.remove(new DefaultFlowEntry(op.rule(), FlowEntry.FlowEntryState.ADDED));
Yi Tsengc927a062017-05-02 15:02:37 -0700925 flowRulesRemove.add(op.rule());
926 break;
Yi Tsengc29d8822017-10-25 16:19:25 -0700927 case MODIFY:
David Glantz0a5779c2021-09-22 14:34:14 -0500928 flowEntries.add(new DefaultFlowEntry(op.rule(), FlowEntry.FlowEntryState.ADDED));
Yi Tsengc29d8822017-10-25 16:19:25 -0700929 flowRulesModify.add(op.rule());
Yi Tsengc927a062017-05-02 15:02:37 -0700930 default:
931 break;
932 }
933 });
934 });
935 }
936
937 @Override
938 public void apply(FlowRuleOperations ops) {
939 record(ops);
940 ops.callback().onSuccess(ops);
941 }
942 }
943
944 /**
945 * The FlowRuleService for test; always failed for any flow rule operations.
946 */
947 class TestFailedFlowRuleService extends TestFlowRuleService {
948 @Override
949 public void apply(FlowRuleOperations ops) {
950 record(ops);
951 ops.callback().onError(ops);
952 }
953 }
954
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100955 /**
956 * The FlowRuleService for testing non-disruptive reallocation.
957 * It keeps all the FlowRules installed/uninstalled.
958 */
959 class TestFlowRuleServiceNonDisruptive extends FlowRuleServiceAdapter {
960
961 Set<FlowRule> flowRulesAdd = Sets.newHashSet();
962 Set<FlowRule> flowRulesRemove = Sets.newHashSet();
963
964 public void record(FlowRuleOperations ops) {
965 ops.stages().forEach(stage -> {
966 stage.forEach(op -> {
967 switch (op.type()) {
968 case ADD:
969 flowRulesAdd.add(op.rule());
970 break;
971 case REMOVE:
972 flowRulesRemove.add(op.rule());
973 break;
974 default:
975 break;
976 }
977 });
978 });
979 }
980
981 @Override
982 public void apply(FlowRuleOperations ops) {
983 record(ops);
984 ops.callback().onSuccess(ops);
Pier68c025b2018-03-26 17:56:18 -0700985 synchronized (this) {
986 this.notify();
987 }
Antonio Marsico4f68ec92017-03-09 11:16:32 +0100988 }
989 }
990
Yi Tsengc927a062017-05-02 15:02:37 -0700991}