blob: 8f0556c6c73991501b3c542b5110debfeae1bafe [file] [log] [blame]
Luca Prete9c2ee072016-02-16 11:00:44 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Luca Prete9c2ee072016-02-16 11:00:44 -08003 *
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 */
16package org.onosproject.vpls;
17
Ray Milkey6e968eb2016-06-29 09:37:27 -070018import java.util.Collections;
19import java.util.List;
Luca Pretec21c6e62016-09-22 14:52:21 -070020import java.util.Map;
Ray Milkey6e968eb2016-06-29 09:37:27 -070021import java.util.Set;
22import java.util.concurrent.atomic.AtomicLong;
23import java.util.stream.Collectors;
24
Yi Tseng28767f02016-09-13 04:27:20 -070025import com.google.common.collect.Lists;
Luca Pretec21c6e62016-09-22 14:52:21 -070026import com.google.common.collect.Maps;
Ray Milkey6e968eb2016-06-29 09:37:27 -070027import org.junit.After;
Luca Prete9c2ee072016-02-16 11:00:44 -080028import org.junit.Before;
Luca Prete9c2ee072016-02-16 11:00:44 -080029import org.junit.Test;
30import org.onlab.packet.Ip4Address;
31import org.onlab.packet.MacAddress;
32import org.onlab.packet.VlanId;
33import org.onosproject.TestApplicationId;
34import org.onosproject.app.ApplicationService;
35import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
37import org.onosproject.core.IdGenerator;
38import org.onosproject.incubator.net.intf.Interface;
Luca Pretea8854822016-04-26 16:30:55 -070039import org.onosproject.incubator.net.intf.InterfaceListener;
Luca Prete9c2ee072016-02-16 11:00:44 -080040import org.onosproject.incubator.net.intf.InterfaceService;
41import org.onosproject.net.ConnectPoint;
42import org.onosproject.net.DefaultHost;
43import org.onosproject.net.DeviceId;
44import org.onosproject.net.Host;
45import org.onosproject.net.HostId;
46import org.onosproject.net.HostLocation;
47import org.onosproject.net.PortNumber;
48import org.onosproject.net.flow.DefaultTrafficSelector;
49import org.onosproject.net.flow.DefaultTrafficTreatment;
50import org.onosproject.net.flow.TrafficSelector;
51import org.onosproject.net.flow.TrafficTreatment;
52import org.onosproject.net.host.HostEvent;
53import org.onosproject.net.host.HostListener;
54import org.onosproject.net.host.HostService;
55import org.onosproject.net.host.HostServiceAdapter;
56import org.onosproject.net.intent.Intent;
57import org.onosproject.net.intent.IntentService;
58import org.onosproject.net.intent.IntentServiceAdapter;
59import org.onosproject.net.intent.IntentUtils;
60import org.onosproject.net.intent.Key;
61import org.onosproject.net.intent.MultiPointToSinglePointIntent;
62import org.onosproject.net.intent.SinglePointToMultiPointIntent;
63import org.onosproject.net.provider.ProviderId;
64import org.onosproject.routing.IntentSynchronizationAdminService;
65import org.onosproject.routing.IntentSynchronizationService;
66
Ray Milkey6e968eb2016-06-29 09:37:27 -070067import com.google.common.collect.Sets;
Luca Prete9c2ee072016-02-16 11:00:44 -080068
69import static java.lang.String.format;
Ray Milkey6e968eb2016-06-29 09:37:27 -070070import static org.easymock.EasyMock.anyObject;
71import static org.easymock.EasyMock.createMock;
72import static org.easymock.EasyMock.expect;
Luca Pretea8854822016-04-26 16:30:55 -070073import static org.easymock.EasyMock.expectLastCall;
Ray Milkey6e968eb2016-06-29 09:37:27 -070074import static org.easymock.EasyMock.replay;
Luca Prete9c2ee072016-02-16 11:00:44 -080075import static org.junit.Assert.assertEquals;
76import static org.junit.Assert.assertTrue;
77
78/**
79 * Tests for the {@link Vpls} class.
80 */
81public class VplsTest {
82
83 private static final int NUM_DEVICES = 7;
84
85 private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
86 private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
87 private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
88 private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
89 private static final MacAddress MAC5 = MacAddress.valueOf("00:00:00:00:00:05");
90 private static final MacAddress MAC6 = MacAddress.valueOf("00:00:00:00:00:06");
91 private static final MacAddress MAC7 = MacAddress.valueOf("00:00:00:00:00:07");
92
93 private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
94 private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
95
96 private static final PortNumber P1 = PortNumber.portNumber(1);
97
98 private static final VlanId VLAN1 = VlanId.vlanId((short) 1);
99 private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
100
101 private static final int PRIORITY_OFFSET = 1000;
102 private static final String PREFIX_BROADCAST = "brc";
103 private static final String PREFIX_UNICAST = "uni";
104
105 private static final DeviceId DID1 = getDeviceId(1);
106 private static final DeviceId DID2 = getDeviceId(2);
107 private static final DeviceId DID3 = getDeviceId(3);
108 private static final DeviceId DID4 = getDeviceId(4);
109 private static final DeviceId DID5 = getDeviceId(5);
110 private static final DeviceId DID6 = getDeviceId(6);
111
112 private static final ConnectPoint C1 = new ConnectPoint(DID1, P1);
113 private static final ConnectPoint C2 = new ConnectPoint(DID2, P1);
114 private static final ConnectPoint C3 = new ConnectPoint(DID3, P1);
115 private static final ConnectPoint C4 = new ConnectPoint(DID4, P1);
116 private static final ConnectPoint C5 = new ConnectPoint(DID5, P1);
117 private static final ConnectPoint C6 = new ConnectPoint(DID6, P1);
118
119 private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
120 private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
121 private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
122 private static final HostId HID4 = HostId.hostId(MAC4, VLAN2);
123 private static final HostId HID5 = HostId.hostId(MAC5, VLAN2);
124 private static final HostId HID6 = HostId.hostId(MAC6, VLAN2);
125 private static final HostId HID7 = HostId.hostId(MAC7, VlanId.NONE);
126
127 private ApplicationService applicationService;
128 private CoreService coreService;
129 private HostListener hostListener;
130 private Set<Host> hostsAvailable;
131 private HostService hostService;
132 private IntentService intentService;
133 private InterfaceService interfaceService;
134 private Vpls vpls;
135
136 private static final String APP_NAME = "org.onosproject.vpls";
137 private static final ApplicationId APPID = TestApplicationId.create(APP_NAME);
138
139 private static final ProviderId PID = new ProviderId("of", "foo");
140
Ray Milkey6e968eb2016-06-29 09:37:27 -0700141 private static IdGenerator idGenerator;
Luca Prete9c2ee072016-02-16 11:00:44 -0800142
143 @Before
144 public void setUp() throws Exception {
Ray Milkey6e968eb2016-06-29 09:37:27 -0700145 idGenerator = new TestIdGenerator();
146 Intent.bindIdGenerator(idGenerator);
147
Luca Prete9c2ee072016-02-16 11:00:44 -0800148 applicationService = createMock(ApplicationService.class);
149
150 coreService = createMock(CoreService.class);
151 expect(coreService.registerApplication(APP_NAME))
152 .andReturn(APPID);
153 replay(coreService);
154
155 hostsAvailable = Sets.newHashSet();
156 hostService = new TestHostService(hostsAvailable);
157
158 intentService = new TestIntentService();
159
160 TestIntentSynchronizer intentSynchronizer =
161 new TestIntentSynchronizer(intentService);
162
163 interfaceService = createMock(InterfaceService.class);
Luca Pretea8854822016-04-26 16:30:55 -0700164 interfaceService.addListener(anyObject(InterfaceListener.class));
165 expectLastCall().anyTimes();
Luca Prete9c2ee072016-02-16 11:00:44 -0800166 addIntfConfig();
167
168 vpls = new Vpls();
169 vpls.applicationService = applicationService;
170 vpls.coreService = coreService;
171 vpls.hostService = hostService;
172 vpls.intentService = intentService;
173 vpls.interfaceService = interfaceService;
174 vpls.intentSynchronizer = intentSynchronizer;
Yi Tseng28767f02016-09-13 04:27:20 -0700175
Luca Prete9c2ee072016-02-16 11:00:44 -0800176 }
177
Ray Milkey6e968eb2016-06-29 09:37:27 -0700178 @After
179 public void tearDown() {
180 Intent.unbindIdGenerator(idGenerator);
181 }
182
Luca Prete9c2ee072016-02-16 11:00:44 -0800183 /**
184 * Creates the interface configuration. On devices 1, 2 and 3 is configured
185 * an interface on port 1 with vlan 1. On devices 4, 5 and 6 is configured
186 * an interface on port 1 with vlan 2. On device 5 no interfaces are
187 * configured.
188 */
189 private void addIntfConfig() {
190 Set<Interface> interfaces = Sets.newHashSet();
Luca Pretea8854822016-04-26 16:30:55 -0700191 Set<Interface> vlanOneSet = Sets.newHashSet();
192 Set<Interface> vlanTwoSet = Sets.newHashSet();
Luca Prete9c2ee072016-02-16 11:00:44 -0800193
194 for (int i = 1; i <= NUM_DEVICES - 1; i++) {
195 ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
196
197 Interface intf =
Luca Pretea8854822016-04-26 16:30:55 -0700198 new Interface("intfOne", cp, Collections.emptyList(), null,
199 VlanId.NONE);
Luca Prete9c2ee072016-02-16 11:00:44 -0800200
201 if (i <= 3) {
Luca Pretea8854822016-04-26 16:30:55 -0700202 intf = new Interface("intfTwo", cp, Collections.emptyList(),
203 null, VLAN1);
Luca Prete9c2ee072016-02-16 11:00:44 -0800204 interfaces.add(intf);
205 vlanOneSet.add(intf);
206 } else if (i > 3 && i <= 6) {
Luca Pretea8854822016-04-26 16:30:55 -0700207 intf = new Interface("intfThree", cp, Collections.emptyList(),
208 null, VLAN2);
Luca Prete9c2ee072016-02-16 11:00:44 -0800209 interfaces.add(intf);
210 vlanTwoSet.add(intf);
211 }
212 expect(interfaceService.getInterfacesByPort(cp))
213 .andReturn(Sets.newHashSet(intf)).anyTimes();
214 }
215 expect(interfaceService.getInterfacesByVlan(VLAN1))
216 .andReturn(vlanOneSet).anyTimes();
217 expect(interfaceService.getInterfacesByVlan(VLAN2))
218 .andReturn(vlanTwoSet).anyTimes();
219 expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
220
221 replay(interfaceService);
222 }
223
224 /**
225 * Checks the case in which six ports are configured with VLANs but no
226 * hosts are registered by the HostService. The first three ports have an
227 * interface configured on VLAN1, the other three on VLAN2. The number of
228 * intents expected is six: three for VLAN1, three for VLAN2. three sp2mp
229 * intents, three mp2sp intents.
230 */
231 @Test
232 public void testActivateNoHosts() {
233 vpls.activate();
234
Yi Tseng28767f02016-09-13 04:27:20 -0700235 List<Intent> expectedIntents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800236 expectedIntents.addAll(generateVlanOneBrc());
237 expectedIntents.addAll(generateVlanTwoBrc());
238
239 checkIntents(expectedIntents);
240 }
241
242 /**
243 * Checks the case in which six ports are configured with VLANs and four
244 * hosts are registered by the HostService. The first three ports have an
245 * interface configured on VLAN1, the other three on VLAN2. The number of
246 * intents expected is twelve: six for VLAN1, six for VLAN2. six sp2mp
247 * intents, six mp2sp intents. For VLAN1 IPs are added to demonstrate it
248 * doesn't influence the number of intents created.
249 */
250 @Test
251 public void testFourInterfacesConfiguredHostsPresent() {
252 Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1),
253 Collections.singleton(IP1));
254 Host h2 = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(2),
255 Collections.singleton(IP2));
256 Host h3 = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(3),
257 Collections.EMPTY_SET);
258 Host h4 = new DefaultHost(PID, HID4, MAC4, VLAN2, getLocation(4),
259 Collections.EMPTY_SET);
260 Host h5 = new DefaultHost(PID, HID5, MAC5, VLAN2, getLocation(5),
261 Collections.EMPTY_SET);
262 Host h6 = new DefaultHost(PID, HID6, MAC6, VLAN2, getLocation(6),
263 Collections.EMPTY_SET);
264 hostsAvailable.addAll(Sets.newHashSet(h1, h2, h3, h4, h5, h6));
265
266 vpls.activate();
267
Yi Tseng28767f02016-09-13 04:27:20 -0700268 List<Intent> expectedIntents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800269 expectedIntents.addAll(generateVlanOneBrc());
270 expectedIntents.addAll(generateVlanOneUni());
271 expectedIntents.addAll(generateVlanTwoBrc());
272 expectedIntents.addAll(generateVlanTwoUni());
273
274 checkIntents(expectedIntents);
275 }
276
277 /**
278 * Checks the case in which six ports are configured with VLANs and
279 * initially no hosts are registered by the HostService. The first three
280 * ports have an interface configured on VLAN1, the other three have an
281 * interface configured on VLAN2. When the module starts up, three hosts -
282 * on device one, two and three - port 1 (both on VLAN1), are registered by
283 * the HostService and events are sent to the application. sp2mp intents
284 * are created for all interfaces configured and mp2sp intents are created
285 * only for the hosts attached.
286 * The number of intents expected is nine: six for VLAN1, three for VLAN2.
287 * Six sp2mp intents, three mp2sp intents. IPs are added on the first two
288 * hosts only to demonstrate it doesn't influence the number of intents
289 * created.
290 * An additional host is added on device seven, port one to demonstrate
291 * that, even if it's on the same VLAN of other interfaces configured in
292 * the system, it doesn't let the application generate intents, since it's
293 * not connected to the interface configured.
294 */
295 @Test
296 public void testFourInterfacesThreeHostEventsSameVlan() {
297 vpls.activate();
298
299 Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1),
300 Collections.singleton(IP1));
301 Host h2 = new DefaultHost(PID, HID2, MAC2, VLAN1, getLocation(2),
302 Collections.singleton(IP2));
303 Host h3 = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(3),
304 Collections.EMPTY_SET);
305 Host h7 = new DefaultHost(PID, HID7, MAC7, VLAN1, getLocation(7),
306 Collections.EMPTY_SET);
307 hostsAvailable.addAll(Sets.newHashSet(h1, h2, h3, h7));
308
309 hostsAvailable.forEach(host ->
310 hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host)));
311
Yi Tseng28767f02016-09-13 04:27:20 -0700312 List<Intent> expectedIntents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800313 expectedIntents.addAll(generateVlanOneBrc());
314 expectedIntents.addAll(generateVlanOneUni());
315 expectedIntents.addAll(generateVlanTwoBrc());
316
317 checkIntents(expectedIntents);
318 }
319
320 /**
321 * Checks the case in which six ports are configured with VLANs and
322 * initially no hosts are registered by the HostService. The first three
323 * ports have an interface configured on VLAN1, the other three have an
324 * interface configured on VLAN2. When the module starts up, two hosts -
325 * on device one and four - port 1 (VLAN 1 and VLAN 2), are registered by
326 * the HostService and events are sent to the application. sp2mp intents
327 * are created for all interfaces configured and no mp2sp intents are created
328 * at all, since the minimum number of hosts needed on the same vlan to
329 * create mp2sp intents is 2.
330 * The number of intents expected is six: three for VLAN1, three for VLAN2.
331 * six sp2mp intents, zero mp2sp intents. IPs are added on the first host
332 * only to demonstrate it doesn't influence the number of intents created.
333 */
334 @Test
335 public void testFourInterfacesTwoHostEventsDifferentVlan() {
336 vpls.activate();
337
338 Host h1 = new DefaultHost(PID, HID1, MAC1, VLAN1, getLocation(1),
339 Collections.singleton(IP1));
340 Host h4 = new DefaultHost(PID, HID4, MAC4, VLAN2, getLocation(4),
341 Collections.EMPTY_SET);
342 hostsAvailable.addAll(Sets.newHashSet(h1, h4));
343
344 hostsAvailable.forEach(host -> {
345 hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host));
346 });
347
Yi Tseng28767f02016-09-13 04:27:20 -0700348 List<Intent> expectedIntents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800349 expectedIntents.addAll(generateVlanOneBrc());
350 expectedIntents.addAll(generateVlanTwoBrc());
351
352 checkIntents(expectedIntents);
353 }
354
355 /**
356 * Checks both that the number of intents in submitted in the intent
357 * framework it's equal to the number of intents expected and that all
358 * intents are equivalent.
359 *
360 * @param intents the list of intents expected
361 */
362 private void checkIntents(List<Intent> intents) {
363 assertEquals(intents.size(), intentService.getIntentCount());
364
365 for (Intent intentOne : intents) {
366 boolean found = false;
367 for (Intent intentTwo : intentService.getIntents()) {
368 if (intentOne.key().equals(intentTwo.key())) {
369 found = true;
370 assertTrue(format("Comparing %s and %s", intentOne, intentTwo),
371 IntentUtils.intentsAreEqual(intentOne, intentTwo));
372 break;
373 }
374 }
375 assertTrue(found);
376 }
377 }
378
379 /**
380 * Generates the list of the expected sp2mp intents for VLAN 1.
381 *
382 * @return the list of expected sp2mp intents for VLAN 1
383 */
384 private List<SinglePointToMultiPointIntent> generateVlanOneBrc() {
385 Key key = null;
386
Yi Tseng28767f02016-09-13 04:27:20 -0700387 List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800388
389 // Building sp2mp intent for H1 - VLAN1
390 key = Key.of((PREFIX_BROADCAST + "-" + DID1 + "-" + P1 + "-" + VLAN1),
391 APPID);
392 intents.add(buildBrcIntent(key, C1, Sets.newHashSet(C2, C3), VLAN1));
393
394 // Building sp2mp intent for H2 - VLAN1
395 key = Key.of((PREFIX_BROADCAST + "-" + DID2 + "-" + P1 + "-" + VLAN1),
396 APPID);
397 intents.add(buildBrcIntent(key, C2, Sets.newHashSet(C1, C3), VLAN1));
398
399 // Building sp2mp intent for H3 - VLAN1
400 key = Key.of((PREFIX_BROADCAST + "-" + DID3 + "-" + P1 + "-" + VLAN1),
401 APPID);
402 intents.add(buildBrcIntent(key, C3, Sets.newHashSet(C1, C2), VLAN1));
403
404 return intents;
405 }
406
407 /**
408 * Generates the list of the expected mp2sp intents for VLAN 1.
409 *
410 * @return the list of expected mp2sp intents for VLAN 1
411 */
412 private List<MultiPointToSinglePointIntent> generateVlanOneUni() {
413 Key key = null;
414
Yi Tseng28767f02016-09-13 04:27:20 -0700415 List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800416
417 // Building mp2sp intent for H1 - VLAN1
418 key = Key.of((PREFIX_UNICAST + "-" + DID1 + "-" + P1 + "-" + VLAN1),
419 APPID);
420 intents.add(buildUniIntent(key, Sets.newHashSet(C2, C3), C1, VLAN1, MAC1));
421
422 // Building mp2sp intent for H2 - VLAN1
423 key = Key.of((PREFIX_UNICAST + "-" + DID2 + "-" + P1 + "-" + VLAN1),
424 APPID);
425 intents.add(buildUniIntent(key, Sets.newHashSet(C1, C3), C2, VLAN1, MAC2));
426
427 // Building mp2sp intent for H3 - VLAN1
428 key = Key.of((PREFIX_UNICAST + "-" + DID3 + "-" + P1 + "-" + VLAN1),
429 APPID);
430 intents.add(buildUniIntent(key, Sets.newHashSet(C1, C2), C3, VLAN1, MAC3));
431
432 return intents;
433 }
434
435 /**
436 * Generates the list of the expected sp2mp intents for VLAN 2.
437 *
438 * @return the list of expected sp2mp intents for VLAN 2
439 */
440 private List<SinglePointToMultiPointIntent> generateVlanTwoBrc() {
441 Key key = null;
442
Yi Tseng28767f02016-09-13 04:27:20 -0700443 List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800444
445 // Building sp2mp intent for H4 - VLAN2
446 key = Key.of((PREFIX_BROADCAST + "-" + DID4 + "-" + P1 + "-" + VLAN2),
447 APPID);
448 intents.add(buildBrcIntent(key, C4, Sets.newHashSet(C5, C6), VLAN2));
449
450 // Building sp2mp intent for H5 - VLAN2
451 key = Key.of((PREFIX_BROADCAST + "-" + DID5 + "-" + P1 + "-" + VLAN2),
452 APPID);
453 intents.add(buildBrcIntent(key, C5, Sets.newHashSet(C4, C6), VLAN2));
454
455 // Building sp2mp intent for H6 - VLAN2
456 key = Key.of((PREFIX_BROADCAST + "-" + DID6 + "-" + P1 + "-" + VLAN2),
457 APPID);
458 intents.add(buildBrcIntent(key, C6, Sets.newHashSet(C4, C5), VLAN2));
459
460 return intents;
461 }
462
463 /**
464 * Generates the list of the expected mp2sp intents for VLAN 2.
465 *
466 * @return the list of expected mp2sp intents for VLAN 2
467 */
468 private List<MultiPointToSinglePointIntent> generateVlanTwoUni() {
469 Key key = null;
470
Yi Tseng28767f02016-09-13 04:27:20 -0700471 List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();
Luca Prete9c2ee072016-02-16 11:00:44 -0800472
473 // Building mp2sp intent for H4 - VLAN2
474 key = Key.of((PREFIX_UNICAST + "-" + DID4 + "-" + P1 + "-" + VLAN2),
475 APPID);
476 intents.add(buildUniIntent(key, Sets.newHashSet(C5, C6), C4, VLAN2, MAC4));
477
478 // Building mp2sp intent for H5 - VLAN2
479 key = Key.of((PREFIX_UNICAST + "-" + DID5 + "-" + P1 + "-" + VLAN2),
480 APPID);
481 intents.add(buildUniIntent(key, Sets.newHashSet(C4, C6), C5, VLAN2, MAC5));
482
483 // Building mp2sp intent for H6 - VLAN2
484 key = Key.of((PREFIX_UNICAST + "-" + DID6 + "-" + P1 + "-" + VLAN2),
485 APPID);
486 intents.add(buildUniIntent(key, Sets.newHashSet(C4, C5), C6, VLAN2, MAC6));
487
488 return intents;
489 }
490
491 /**
492 * Builds a Single Point to Multi Point intent.
493 *
494 * @param key The intent key
495 * @param src The source Connect Point
496 * @param dsts The destination Connect Points
497 * @return Single Point to Multi Point intent generated.
498 */
499 private SinglePointToMultiPointIntent buildBrcIntent(Key key,
500 ConnectPoint src,
501 Set<ConnectPoint> dsts,
502 VlanId vlanId) {
503 SinglePointToMultiPointIntent intent;
504
505 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
506
507 TrafficSelector selector = DefaultTrafficSelector.builder()
508 .matchEthDst(MacAddress.BROADCAST)
509 .matchVlanId(vlanId)
510 .build();
511
512 intent = SinglePointToMultiPointIntent.builder()
513 .appId(APPID)
514 .key(key)
515 .selector(selector)
516 .treatment(treatment)
517 .ingressPoint(src)
518 .egressPoints(dsts)
519 .priority(PRIORITY_OFFSET)
520 .build();
521 return intent;
522 }
523
524 /**
525 * Builds a Multi Point to Single Point intent.
526 *
527 * @param key The intent key
528 * @param srcs The source Connect Points
529 * @param dst The destination Connect Point
530 * @return Multi Point to Single Point intent generated.
531 */
532 private MultiPointToSinglePointIntent buildUniIntent(Key key,
533 Set<ConnectPoint> srcs,
534 ConnectPoint dst,
535 VlanId vlanId,
536 MacAddress mac) {
537 MultiPointToSinglePointIntent intent;
538
539 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
540
541 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
542 .matchEthDst(mac)
543 .matchVlanId(vlanId);
544
545 TrafficSelector selector = builder.build();
546
547 intent = MultiPointToSinglePointIntent.builder()
548 .appId(APPID)
549 .key(key)
550 .selector(selector)
551 .treatment(treatment)
552 .ingressPoints(srcs)
553 .egressPoint(dst)
554 .priority(PRIORITY_OFFSET)
555 .build();
556 return intent;
557 }
558
559 /**
560 * Returns the device ID of the ith device.
561 *
562 * @param i device to get the ID of
563 * @return the device ID
564 */
565 private static DeviceId getDeviceId(int i) {
566 return DeviceId.deviceId("" + i);
567 }
568
569 private static HostLocation getLocation(int i) {
570 return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
571 }
572
573 /**
574 * Represents a fake IntentService class that easily allows to store and
575 * retrieve intents without implementing the IntentService logic.
576 */
577 private class TestIntentService extends IntentServiceAdapter {
578
Luca Pretec21c6e62016-09-22 14:52:21 -0700579 private Map<Key, Intent> intents;
Luca Prete9c2ee072016-02-16 11:00:44 -0800580
581 public TestIntentService() {
Luca Pretec21c6e62016-09-22 14:52:21 -0700582 intents = Maps.newHashMap();
Luca Prete9c2ee072016-02-16 11:00:44 -0800583 }
584
585 @Override
586 public void submit(Intent intent) {
Luca Pretec21c6e62016-09-22 14:52:21 -0700587 intents.put(intent.key(), intent);
Luca Prete9c2ee072016-02-16 11:00:44 -0800588 }
589
590 @Override
591 public long getIntentCount() {
592 return intents.size();
593 }
594
595 @Override
596 public Iterable<Intent> getIntents() {
Luca Pretec21c6e62016-09-22 14:52:21 -0700597 return intents.values();
Luca Prete9c2ee072016-02-16 11:00:44 -0800598 }
599
600 @Override
601 public Intent getIntent(Key intentKey) {
Luca Pretec21c6e62016-09-22 14:52:21 -0700602 for (Intent intent : intents.values()) {
Luca Prete9c2ee072016-02-16 11:00:44 -0800603 if (intent.key().equals(intentKey)) {
604 return intent;
605 }
606 }
607 return null;
608 }
609 }
610
611 /**
612 * Represents a fake HostService class which allows to add hosts manually
613 * in each test, when needed.
614 */
615 private class TestHostService extends HostServiceAdapter {
616
617 private Set<Host> hosts;
618
619 public TestHostService(Set<Host> hosts) {
620 this.hosts = hosts;
621 }
622
623 @Override
624 public void addListener(HostListener listener) {
625 VplsTest.this.hostListener = listener;
626 }
627
628 @Override
629 public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
630 return hosts.stream()
631 .filter(h -> h.location().elementId().equals(connectPoint.elementId())
632 && h.location().port().equals(connectPoint.port()))
633 .collect(Collectors.toSet());
634 }
635
636 }
637
638 private static class TestIdGenerator implements IdGenerator {
639
640 private final AtomicLong id = new AtomicLong(0);
641
642 @Override
643 public long getNewId() {
644 return id.getAndIncrement();
645 }
646
647 }
648
649 /**
650 * Test IntentSynchronizer that passes all intents straight through to the
651 * intent service.
652 */
653 private class TestIntentSynchronizer implements IntentSynchronizationService,
654 IntentSynchronizationAdminService {
655
656 private final IntentService intentService;
657
658 /**
659 * Creates a new test intent synchronizer.
660 *
661 * @param intentService intent service
662 */
663 public TestIntentSynchronizer(IntentService intentService) {
664 this.intentService = intentService;
665 }
666
667 @Override
668 public void submit(Intent intent) {
669 intentService.submit(intent);
670 }
671
672 @Override
673 public void withdraw(Intent intent) {
674 intentService.withdraw(intent);
675 }
676
677 @Override
678 public void modifyPrimary(boolean isPrimary) {
Luca Prete9c2ee072016-02-16 11:00:44 -0800679 }
680
681 @Override
682 public void removeIntents() {
Luca Prete2705d662016-04-29 15:30:23 -0700683 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800684
Luca Prete2705d662016-04-29 15:30:23 -0700685 @Override
686 public void removeIntentsByAppId(ApplicationId applicationId) {
Luca Prete9c2ee072016-02-16 11:00:44 -0800687 }
688 }
689
690}