blob: 90e34151adc3d224f012bb6f3006ca12ce49954d [file] [log] [blame]
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -07001/*
2 * Copyright 2016-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.vpls;
18
19import com.google.common.collect.HashMultimap;
20import com.google.common.collect.ImmutableSet;
21import com.google.common.collect.ImmutableSetMultimap;
22import com.google.common.collect.SetMultimap;
23import com.google.common.collect.Sets;
24import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
27import org.onlab.packet.Ethernet;
28import org.onlab.packet.IpAddress;
29import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
31import org.onosproject.core.ApplicationId;
32import org.onosproject.incubator.net.intf.Interface;
33import org.onosproject.incubator.net.intf.InterfaceListener;
34import org.onosproject.incubator.net.intf.InterfaceService;
35import org.onosproject.incubator.net.neighbour.NeighbourHandlerRegistration;
36import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
37import org.onosproject.incubator.net.neighbour.NeighbourMessageHandler;
38import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
39import org.onosproject.incubator.net.neighbour.NeighbourProtocol;
40import org.onosproject.incubator.net.neighbour.NeighbourResolutionService;
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.host.HostService;
49import org.onosproject.net.host.HostServiceAdapter;
50import org.onosproject.net.provider.ProviderId;
51import org.onosproject.vpls.config.VplsConfigurationService;
52
53import java.util.Collection;
54import java.util.Map;
55import java.util.Set;
56import java.util.stream.Collectors;
57
58import static junit.framework.TestCase.assertEquals;
59
60/**
61 * Tests the the {@link VplsNeighbourHandler} class.
62 */
63public class VplsNeighbourHandlerTest {
64 private final ConnectPoint of1p1 =
65 new ConnectPoint(DeviceId.deviceId("of:1"),
66 PortNumber.portNumber(1));
67 private final ConnectPoint of4p1 =
68 new ConnectPoint(DeviceId.deviceId("of:4"),
69 PortNumber.portNumber(1));
70 private final ConnectPoint of3p1 =
71 new ConnectPoint(DeviceId.deviceId("of:3"),
72 PortNumber.portNumber(1));
73 private final ConnectPoint of4p2 =
74 new ConnectPoint(DeviceId.deviceId("of:4"),
75 PortNumber.portNumber(2));
76 private final ConnectPoint of2p1 =
77 new ConnectPoint(DeviceId.deviceId("of:2"),
78 PortNumber.portNumber(1));
79
80 private final VlanId vlan100 = VlanId.vlanId("100");
81 private final VlanId vlan200 = VlanId.vlanId("200");
82 private final VlanId vlan300 = VlanId.vlanId("300");
83
84 private final Interface v100h1 =
85 new Interface("v100h1", of1p1, null, null, vlan100);
86 private final Interface v100h2 =
87 new Interface("v100h2", of4p1, null, null, vlan100);
88 private final Interface v200h1 =
89 new Interface("v200h1", of4p2, null, null, vlan200);
90 private final Interface v300h1 =
91 new Interface("v300h1", of3p1, null, null, vlan300);
92 private final Interface v200h2 =
93 new Interface("v200h2", of2p1, null, null, vlan200);
94
95 private final MacAddress mac1 = MacAddress.valueOf("00:00:00:00:00:01");
96 private final MacAddress mac2 = MacAddress.valueOf("00:00:00:00:00:02");
97 private final MacAddress mac3 = MacAddress.valueOf("00:00:00:00:00:03");
98 private final MacAddress mac4 = MacAddress.valueOf("00:00:00:00:00:04");
99 private final MacAddress mac5 = MacAddress.valueOf("00:00:00:00:00:05");
100
101 private final ProviderId pid = new ProviderId("of", "foo");
102
103 private final Host v100host1 = makeHost(mac1, vlan100, of1p1);
104 private final Host v100host2 = makeHost(mac2, vlan100, of4p1);
105 private final Host v200host1 = makeHost(mac3, vlan200, of4p2);
106 private final Host v300host1 = makeHost(mac4, vlan300, of3p1);
107 private final Host v200host2 = makeHost(mac5, vlan200, of2p1);
108
109 private final Set<Host> availableHosts = ImmutableSet.of(v100host1,
110 v100host2,
111 v200host1,
112 v300host1,
113 v200host2);
114
115 private final Set<Interface> avaliableInterfaces =
116 ImmutableSet.of(v100h1, v100h2, v200h1, v200h2, v300h1);
117
118 private VplsNeighbourHandler vplsNeighbourHandler;
119
120 private HostService hostService;
121
122 /**
123 * Sets up 2 VPLS which contain 2 networks and 5 hosts.
124 * net1 contains 3 hosts: v100h1, v200h1 and v300h1
125 * net2 contains 2 hosts: v100h2, v200h2
126 */
127 @Before
128 public void setUp() {
129 vplsNeighbourHandler = new VplsNeighbourHandler();
130 SetMultimap<String, Interface> vplsNetworks =
131 HashMultimap.create();
132 vplsNetworks.put("net1", v100h1);
133 vplsNetworks.put("net1", v200h1);
134 vplsNetworks.put("net1", v300h1);
135 vplsNetworks.put("net2", v100h2);
136 vplsNetworks.put("net2", v200h2);
137 vplsNeighbourHandler.vplsConfigService =
138 new TestVplsConfigService(vplsNetworks);
139 vplsNeighbourHandler.interfaceService =
140 new TestInterfaceService();
141 vplsNeighbourHandler.neighbourService =
142 new TestNeighbourService();
143
144 hostService = new TestHostService();
145 }
146
147 @After
148 public void tearDown() {
149
150 }
151
152 /**
153 * Sends request messages to all hosts in VPLS net1.
154 * Request messages should be received from other hosts in net1.
155 */
156 @Test
157 public void testNet1RequestMessage() {
158 // Request from v100h1 (net1)
159 // Should be received by v200h1 and v300h1
160 TestMessageContext requestMessage =
161 makeBroadcastRequestContext(v100host1);
162 Set<Interface> expectInterfaces = ImmutableSet.of(v200h1, v300h1);
163 vplsNeighbourHandler.handleRequest(requestMessage);
164 assertEquals(expectInterfaces, requestMessage.forwardResults);
165
166 // Request from v200h1 (net1)
167 // Should be received by v100h1 and v300h1
168 requestMessage = makeBroadcastRequestContext(v200host1);
169 expectInterfaces = ImmutableSet.of(v100h1, v300h1);
170 vplsNeighbourHandler.handleRequest(requestMessage);
171 assertEquals(expectInterfaces, requestMessage.forwardResults);
172
173 // Request from v300h1 (net1)
174 // Should be received by v100h1 and v200h1
175 requestMessage = makeBroadcastRequestContext(v300host1);
176 expectInterfaces = ImmutableSet.of(v100h1, v200h1);
177 vplsNeighbourHandler.handleRequest(requestMessage);
178 assertEquals(expectInterfaces, requestMessage.forwardResults);
179 }
180
181 /**
182 * Sends request messages to all hosts in VPLS net2.
183 * Request messages should be received from other hosts in net2.
184 */
185 @Test
186 public void testNet2RequestMessage() {
187 // Request from v100h2
188 // Should be received by v200h2
189 TestMessageContext requestMessage =
190 makeBroadcastRequestContext(v100host2);
191 Set<Interface> expectInterfaces = ImmutableSet.of(v200h2);
192 vplsNeighbourHandler.handleRequest(requestMessage);
193 assertEquals(expectInterfaces, requestMessage.forwardResults);
194
195 // Request from v200h2
196 // Should be received by v100h2
197 requestMessage = makeBroadcastRequestContext(v200host2);
198 expectInterfaces = ImmutableSet.of(v100h2);
199 vplsNeighbourHandler.handleRequest(requestMessage);
200 assertEquals(expectInterfaces, requestMessage.forwardResults);
201 }
202
203 /**
204 * Sends reply messages to hosts in VPLS net1.
205 * Reply messages should be received by the host with MAC address equal to
206 * the dstMac of the message context.
207 */
208 @Test
209 public void testNet1ReplyMessage() {
210 // Response from v100h1 (net1) to v200h1 (net1)
211 // Should be received by v200h1
212 TestMessageContext replyMessage =
213 makeReplyContext(v100host1, v200host1);
214 Set<Interface> expectInterfaces = ImmutableSet.of(v200h1);
215 vplsNeighbourHandler.handleReply(replyMessage, hostService);
216 assertEquals(expectInterfaces, replyMessage.forwardResults);
217
218 // Response from v200h1 (net1) to v300h1 (net1)
219 // Should be received by v300h1
220 replyMessage = makeReplyContext(v200host1, v300host1);
221 expectInterfaces = ImmutableSet.of(v300h1);
222 vplsNeighbourHandler.handleReply(replyMessage, hostService);
223 assertEquals(expectInterfaces, replyMessage.forwardResults);
224
225 // Response from v300h1 (net1) to v100h1 (net1)
226 // Should be received by v100h1
227 replyMessage = makeReplyContext(v300host1, v100host1);
228 expectInterfaces = ImmutableSet.of(v100h1);
229 vplsNeighbourHandler.handleReply(replyMessage, hostService);
230 assertEquals(expectInterfaces, replyMessage.forwardResults);
231 }
232
233 /**
234 * Sends reply messages to hosts in VPLS net2.
235 * Reply messages should be received by the host with MAC address equal to
236 * the dstMac of the message context.
237 */
238 @Test
239 public void testNet2ReplyMessage() {
240 // Response from v100h2 (net2) to v200h2 (net2)
241 // Should be received by v200h2
242 TestMessageContext replyMessage =
243 makeReplyContext(v100host2, v200host2);
244 Set<Interface> expectInterfaces = ImmutableSet.of(v200h2);
245 vplsNeighbourHandler.handleReply(replyMessage, hostService);
246 assertEquals(expectInterfaces, replyMessage.forwardResults);
247
248 // Response from v200h2 (net2) to v100h2 (net2)
249 // Should be received by v100h2
250 replyMessage = makeReplyContext(v200host2, v100host2);
251 expectInterfaces = ImmutableSet.of(v100h2);
252 vplsNeighbourHandler.handleReply(replyMessage, hostService);
253 assertEquals(expectInterfaces, replyMessage.forwardResults);
254 }
255
256 /**
257 * Sends wrong reply messages to hosts.
258 * The source and the destination MAC addresses are not set on any host of the VPLS.
259 * The reply messages won't be received by any hosts.
260 */
261 @Test
262 public void testWrongReplyMessage() {
263 // Response from v100h1 (net1) to v100h2 (net2)
264 // forward results should be empty
265 TestMessageContext replyMessage = makeReplyContext(v100host1, v100host2);
266 Set<Interface> expectInterfaces = ImmutableSet.of();
267 vplsNeighbourHandler.handleReply(replyMessage, hostService);
268 assertEquals(expectInterfaces, replyMessage.forwardResults);
269
270 // Response from v200h2 (net2) to v300h1 (net1)
271 // forward results should be empty
272 replyMessage = makeReplyContext(v200host2, v300host1);
273 expectInterfaces = ImmutableSet.of();
274 vplsNeighbourHandler.handleReply(replyMessage, hostService);
275 assertEquals(expectInterfaces, replyMessage.forwardResults);
276 }
277
278 private Host makeHost(MacAddress mac, VlanId vlan, ConnectPoint cp) {
279 return new DefaultHost(pid,
280 HostId.hostId(mac, vlan),
281 mac,
282 vlan,
283 new HostLocation(cp, 0),
284 Sets.newHashSet());
285 }
286
287 private TestMessageContext makeBroadcastRequestContext(Host host) {
288 return new TestMessageContext(host.location(),
289 host.mac(),
290 MacAddress.BROADCAST,
291 host.vlan(),
292 NeighbourMessageType.REQUEST);
293 }
294
295 private TestMessageContext makeReplyContext(Host src, Host dst) {
296 return new TestMessageContext(src.location(),
297 src.mac(),
298 dst.mac(),
299 src.vlan(),
300 NeighbourMessageType.REPLY);
301 }
302
303 private class TestMessageContext implements NeighbourMessageContext {
304
305
306 private final NeighbourMessageType type;
307 private final MacAddress srcMac;
308 private final MacAddress dstMac;
309 private final ConnectPoint inPort;
310 private final VlanId vlanId;
311
312 public Set<Interface> forwardResults;
313
314 /**
315 * Creates new neighbour message context for test.
316 *
317 * @param inPort the input port
318 * @param srcMac the source Mac
319 * @param dstMac the destination Mac
320 * @param vlanId the VLAN Id
321 * @param type the message context type
322 */
323 public TestMessageContext(
324 ConnectPoint inPort,
325 MacAddress srcMac,
326 MacAddress dstMac,
327 VlanId vlanId,
328 NeighbourMessageType type) {
329
330 this.inPort = inPort;
331 this.srcMac = srcMac;
332 this.dstMac = dstMac;
333 this.vlanId = vlanId;
334 this.type = type;
335
336 this.forwardResults = Sets.newHashSet();
337
338 }
339 @Override
340 public ConnectPoint inPort() {
341 return inPort;
342 }
343
344 @Override
345 public NeighbourMessageType type() {
346 return type;
347 }
348
349 @Override
350 public VlanId vlan() {
351 return vlanId;
352 }
353
354 @Override
355 public MacAddress srcMac() {
356 return srcMac;
357 }
358
359 @Override
360 public MacAddress dstMac() {
361 return dstMac;
362 }
363
364 @Override
365 public IpAddress target() {
366 return null;
367 }
368
369 @Override
370 public IpAddress sender() {
371 return null;
372 }
373
374 @Override
375 public void forward(ConnectPoint outPort) {
376
377 }
378
379 @Override
380 public void forward(Interface outIntf) {
381 forwardResults.add(outIntf);
382 }
383
384 @Override
385 public void reply(MacAddress targetMac) {
386
387 }
388
389 @Override
390 public void flood() {
391
392 }
393
394 @Override
395 public void drop() {
396
397 }
398
399 @Override
400 public Ethernet packet() {
401 return null;
402 }
403
404 @Override
405 public NeighbourProtocol protocol() {
406 return null;
407 }
408 }
409
410 private class TestVplsConfigService implements VplsConfigurationService {
411
412 private final SetMultimap<String, Interface> vplsNetworks;
413
414 public TestVplsConfigService(SetMultimap<String, Interface> networks) {
415 this.vplsNetworks = networks;
416 }
417
418 @Override
419 public void addVpls(String name, Set<String> ifaceNames) {
420 if (!vplsNetworks.containsKey(name)) {
421 ifaceNames.forEach(ifaceName -> {
422 avaliableInterfaces.forEach(intf -> {
423 if (intf.name().equals(ifaceName)) {
424 vplsNetworks.put(name, intf);
425 }
426 });
427 });
428 }
429 }
430
431 @Override
432 public void removeVpls(String name) {
433 if (vplsNetworks.containsKey(name)) {
434 vplsNetworks.removeAll(name);
435 }
436 }
437
438 @Override
439 public void addInterfaceToVpls(String name, String ifaceName) {
440 avaliableInterfaces.forEach(intf -> {
441 if (intf.name().equals(ifaceName)) {
442 vplsNetworks.put(name, intf);
443 }
444 });
445 }
446
447 @Override
448 public void removeInterfaceFromVpls(String ifaceName) {
449 SetMultimap<String, Interface> toBeRemoved = HashMultimap.create();
450 vplsNetworks.entries().forEach(e -> {
451 if (e.getValue().name().equals(ifaceName)) {
452 toBeRemoved.put(e.getKey(), e.getValue());
453 }
454 });
455
456 toBeRemoved.entries()
457 .forEach(e -> vplsNetworks.remove(e.getKey(),
458 e.getValue()));
459 }
460
461 @Override
462 public void cleanVpls() {
463 vplsNetworks.clear();
464 }
465
466 @Override
467 public Set<String> getVplsAffectedByApi() {
468 return null;
469 }
470
471 @Override
472 public Set<Interface> getAllInterfaces() {
473 return ImmutableSet.copyOf(vplsNetworks.values());
474 }
475
476 @Override
477 public Set<Interface> getVplsInterfaces(String name) {
478 return vplsNetworks.get(name)
479 .stream()
480 .collect(Collectors.toSet());
481 }
482
483 @Override
484 public Set<String> getAllVpls() {
485 return vplsNetworks.keySet();
486 }
487
488 @Override
489 public Set<String> getOldVpls() {
490 return null;
491 }
492
493 @Override
494 public SetMultimap<String, Interface> getVplsNetworks() {
495 return ImmutableSetMultimap.copyOf(vplsNetworks);
496 }
497
498 @Override
499 public SetMultimap<String, Interface> getVplsNetwork(VlanId vlan,
500 ConnectPoint connectPoint) {
501 String vplsNetworkName =
502 vplsNetworks.entries().stream()
503 .filter(e -> e.getValue().connectPoint().equals(connectPoint))
504 .filter(e -> e.getValue().vlan().equals(vlan))
505 .map(e -> e.getKey())
506 .findFirst()
507 .orElse(null);
508 SetMultimap<String, Interface> result = HashMultimap.create();
509 if (vplsNetworkName != null &&
510 vplsNetworks.containsKey(vplsNetworkName)) {
511 vplsNetworks.get(vplsNetworkName)
512 .forEach(intf -> result.put(vplsNetworkName, intf));
513 return result;
514 }
515 return null;
516 }
517 }
518
519 class TestHostService extends HostServiceAdapter {
520 @Override
521 public Set<Host> getHostsByMac(MacAddress mac) {
522 return availableHosts.stream()
523 .filter(host -> host.mac().equals(mac))
524 .collect(Collectors.toSet());
525 }
526
527 @Override
528 public Iterable<Host> getHosts() {
529 return availableHosts;
530 }
531
532 @Override
533 public Set<Host> getHostsByVlan(VlanId vlanId) {
534 return availableHosts.stream()
535 .filter(host -> host.vlan().equals(vlanId))
536 .collect(Collectors.toSet());
537 }
538
539 @Override
540 public int getHostCount() {
541 return availableHosts.size();
542 }
543
544 @Override
545 public Host getHost(HostId hostId) {
546 return availableHosts.stream()
547 .filter(host -> host.id().equals(hostId))
548 .findFirst()
549 .orElse(null);
550 }
551 }
552
553 private class TestNeighbourService implements NeighbourResolutionService {
554 private SetMultimap<ConnectPoint, NeighbourHandlerRegistration> handlerRegs;
555
556 public TestNeighbourService() {
557 handlerRegs = HashMultimap.create();
558 }
559
560 @Override
561 public void registerNeighbourHandler(ConnectPoint connectPoint,
562 NeighbourMessageHandler handler,
563 ApplicationId appId) {
564 Interface intf =
565 new Interface(null, connectPoint, null, null, null);
566
567 NeighbourHandlerRegistration reg =
568 new HandlerRegistration(handler, intf, appId);
569
570 handlerRegs.put(connectPoint, reg);
571 }
572
573 @Override
574 public void registerNeighbourHandler(Interface intf,
575 NeighbourMessageHandler handler,
576 ApplicationId appId) {
577 NeighbourHandlerRegistration reg =
578 new HandlerRegistration(handler, intf, appId);
579 handlerRegs.put(intf.connectPoint(), reg);
580 }
581
582 @Override
583 public void unregisterNeighbourHandler(ConnectPoint connectPoint,
584 NeighbourMessageHandler handler,
585 ApplicationId appId) {
586 handlerRegs.removeAll(connectPoint);
587 }
588
589 @Override
590 public void unregisterNeighbourHandler(Interface intf,
591 NeighbourMessageHandler handler,
592 ApplicationId appId) {
593 handlerRegs.removeAll(intf.connectPoint());
594 }
595
596 @Override
597 public void unregisterNeighbourHandlers(ApplicationId appId) {
598 handlerRegs.clear();
599 }
600
601 @Override
602 public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
603 return handlerRegs.asMap();
604 }
605
606 private class HandlerRegistration implements NeighbourHandlerRegistration {
607 private final Interface intf;
608 private final NeighbourMessageHandler handler;
609 private final ApplicationId appId;
610
611 /**
612 * Creates a new registration handler.
613 *
614 * @param handler the neighbour message handler
615 * @param intf the interface
616 */
617 public HandlerRegistration(NeighbourMessageHandler handler,
618 Interface intf,
619 ApplicationId appId) {
620 this.intf = intf;
621 this.handler = handler;
622 this.appId = appId;
623 }
624
625 @Override
626 public Interface intf() {
627 return intf;
628 }
629
630 @Override
631 public NeighbourMessageHandler handler() {
632 return handler;
633 }
634
635 @Override
636 public ApplicationId appId() {
637 return appId;
638 }
639
640 }
641 }
642
643 class TestInterfaceService implements InterfaceService {
644
645 @Override
646 public void addListener(InterfaceListener listener) {
647
648 }
649
650 @Override
651 public void removeListener(InterfaceListener listener) {
652
653 }
654
655 @Override
656 public Set<Interface> getInterfaces() {
657 return avaliableInterfaces;
658 }
659
660 @Override
661 public Interface getInterfaceByName(ConnectPoint connectPoint,
662 String name) {
663 return avaliableInterfaces.stream()
664 .filter(intf -> intf.name().equals(name))
665 .findFirst()
666 .orElse(null);
667
668 }
669
670 @Override
671 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
672 return avaliableInterfaces.stream()
673 .filter(intf -> intf.connectPoint().equals(port))
674 .collect(Collectors.toSet());
675 }
676
677 @Override
678 public Set<Interface> getInterfacesByIp(IpAddress ip) {
679 return avaliableInterfaces.stream()
680 .filter(intf -> intf.ipAddressesList().contains(ip))
681 .collect(Collectors.toSet());
682 }
683
684 @Override
685 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
686 return avaliableInterfaces.stream()
687 .filter(intf -> intf.vlan().equals(vlan))
688 .collect(Collectors.toSet());
689 }
690
691 @Override
692 public Interface getMatchingInterface(IpAddress ip) {
693 return avaliableInterfaces.stream()
694 .filter(intf -> intf.ipAddressesList().contains(ip))
695 .findFirst()
696 .orElse(null);
697 }
698 }
699}