blob: 412e9371c70b263fb2ea9c89a337dcb0e7942a1d [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 */
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070016package org.onosproject.vpls;
17
18import com.google.common.collect.HashMultimap;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.ImmutableSetMultimap;
Luca Prete092e8952016-10-26 16:25:56 +020021import com.google.common.collect.Maps;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070022import 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;
Luca Prete092e8952016-10-26 16:25:56 +020044import org.onosproject.net.EncapsulationType;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070045import org.onosproject.net.Host;
46import org.onosproject.net.HostId;
47import org.onosproject.net.HostLocation;
48import org.onosproject.net.PortNumber;
49import org.onosproject.net.host.HostService;
50import org.onosproject.net.host.HostServiceAdapter;
51import org.onosproject.net.provider.ProviderId;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070052
53import java.util.Collection;
Luca Prete092e8952016-10-26 16:25:56 +020054import java.util.HashMap;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070055import java.util.Map;
56import java.util.Set;
57import java.util.stream.Collectors;
58
59import static junit.framework.TestCase.assertEquals;
60
61/**
62 * Tests the the {@link VplsNeighbourHandler} class.
63 */
64public class VplsNeighbourHandlerTest {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070065
Luca Prete092e8952016-10-26 16:25:56 +020066 private static final String IFACES_NOT_EXPECTED =
67 "The interfaces reached by the packet are not equal to the " +
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010068 "interfaces expected.";
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070069
Luca Prete092e8952016-10-26 16:25:56 +020070 private static final DeviceId DID1 = getDeviceId(1);
71 private static final DeviceId DID2 = getDeviceId(2);
72 private static final DeviceId DID3 = getDeviceId(3);
73 private static final DeviceId DID4 = getDeviceId(4);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010074 private static final DeviceId DID5 = getDeviceId(5);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070075
Luca Prete092e8952016-10-26 16:25:56 +020076 private static final PortNumber P1 = PortNumber.portNumber(1);
77 private static final PortNumber P2 = PortNumber.portNumber(2);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010078 private static final PortNumber P3 = PortNumber.portNumber(3);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070079
Luca Prete092e8952016-10-26 16:25:56 +020080 private static final ConnectPoint OF1P1 = new ConnectPoint(DID1, P1);
81 private static final ConnectPoint OF2P1 = new ConnectPoint(DID2, P1);
82 private static final ConnectPoint OF3P1 = new ConnectPoint(DID3, P1);
83 private static final ConnectPoint OF4P1 = new ConnectPoint(DID4, P1);
84 private static final ConnectPoint OF4P2 = new ConnectPoint(DID4, P2);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010085 private static final ConnectPoint OF4P3 = new ConnectPoint(DID4, P3);
86 private static final ConnectPoint OF5P1 = new ConnectPoint(DID5, P1);
87 private static final ConnectPoint OF5P2 = new ConnectPoint(DID5, P2);
88 private static final ConnectPoint OF5P3 = new ConnectPoint(DID5, P3);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070089
Luca Prete092e8952016-10-26 16:25:56 +020090 private static final String VPLS1 = "vpls1";
91 private static final String VPLS2 = "vpls2";
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010092 private static final String VPLS3 = "vpls3";
93 private static final String VPLS4 = "vpls4";
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -070094
Luca Prete092e8952016-10-26 16:25:56 +020095 private static final VlanId VLAN100 = VlanId.vlanId("100");
96 private static final VlanId VLAN200 = VlanId.vlanId("200");
97 private static final VlanId VLAN300 = VlanId.vlanId("300");
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +010098 private static final VlanId VLAN400 = VlanId.vlanId("400");
99 private static final VlanId VLAN_NONE = VlanId.NONE;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700100
Luca Prete092e8952016-10-26 16:25:56 +0200101 private static final Interface V100H1 =
102 new Interface("v100h1", OF1P1, null, null, VLAN100);
103 private static final Interface V100H2 =
104 new Interface("v100h2", OF4P1, null, null, VLAN100);
105 private static final Interface V200H1 =
106 new Interface("v200h1", OF4P2, null, null, VLAN200);
107 private static final Interface V200H2 =
108 new Interface("v200h2", OF2P1, null, null, VLAN200);
109 private static final Interface V300H1 =
110 new Interface("v300h1", OF3P1, null, null, VLAN300);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100111 private static final Interface V400H1 =
112 new Interface("v400h1", OF5P1, null, null, VLAN400);
113 private static final Interface VNONEH1 =
114 new Interface("vNoneh1", OF5P2, null, null, VLAN_NONE);
115 private static final Interface VNONEH2 =
116 new Interface("vNoneh2", OF5P3, null, null, VLAN_NONE);
117 private static final Interface VNONEH3 =
118 new Interface("vNoneh3", OF4P3, null, null, VLAN_NONE);
Luca Prete092e8952016-10-26 16:25:56 +0200119
120 private static final MacAddress MAC1 = MacAddress.valueOf("00:00:00:00:00:01");
121 private static final MacAddress MAC2 = MacAddress.valueOf("00:00:00:00:00:02");
122 private static final MacAddress MAC3 = MacAddress.valueOf("00:00:00:00:00:03");
123 private static final MacAddress MAC4 = MacAddress.valueOf("00:00:00:00:00:04");
124 private static final MacAddress MAC5 = MacAddress.valueOf("00:00:00:00:00:05");
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100125 private static final MacAddress MAC6 = MacAddress.valueOf("00:00:00:00:00:06");
126 private static final MacAddress MAC7 = MacAddress.valueOf("00:00:00:00:00:07");
127 private static final MacAddress MAC8 = MacAddress.valueOf("00:00:00:00:00:08");
128 private static final MacAddress MAC9 = MacAddress.valueOf("00:00:00:00:00:09");
Luca Prete092e8952016-10-26 16:25:56 +0200129
130 private static final ProviderId PID = new ProviderId("of", "foo");
131
132 private final Host v100Host1 = makeHost(MAC1, VLAN100, OF1P1);
133 private final Host v100Host2 = makeHost(MAC2, VLAN100, OF4P1);
134 private final Host v200Host1 = makeHost(MAC3, VLAN200, OF4P2);
135 private final Host v200Host2 = makeHost(MAC5, VLAN200, OF2P1);
136 private final Host v300Host1 = makeHost(MAC4, VLAN300, OF3P1);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100137 private final Host v400Host1 = makeHost(MAC6, VLAN400, OF5P1);
138 private final Host vNoneHost1 = makeHost(MAC7, VLAN_NONE, OF5P2);
139 private final Host vNoneHost2 = makeHost(MAC8, VLAN_NONE, OF5P3);
140 private final Host vNoneHost3 = makeHost(MAC9, VLAN_NONE, OF4P3);
Luca Prete092e8952016-10-26 16:25:56 +0200141
142 private final Set<Host> availableHosts = ImmutableSet.of(v100Host1,
143 v100Host2,
144 v200Host1,
145 v300Host1,
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100146 v200Host2,
147 v400Host1,
148 vNoneHost1,
149 vNoneHost2,
150 vNoneHost3);
Luca Prete092e8952016-10-26 16:25:56 +0200151
152 private final Set<Interface> availableInterfaces =
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100153 ImmutableSet.of(V100H1, V100H2, V200H1, V200H2, V300H1,
154 V400H1, VNONEH1, VNONEH2, VNONEH3);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700155
156 private VplsNeighbourHandler vplsNeighbourHandler;
157
158 private HostService hostService;
159
160 /**
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100161 * Sets up 4 VPLS.
Luca Prete092e8952016-10-26 16:25:56 +0200162 * VPLS 1 contains 3 hosts: v100h1, v200h1 and v300h1
163 * VPLS 2 contains 2 hosts: v100h2, v200h2
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100164 * VPLS 3 contains 2 hosts: vNoneh1, vNoneh2
165 * VPLS 4 contains 2 hosts: v400h1, vNoneh3
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700166 */
167 @Before
168 public void setUp() {
169 vplsNeighbourHandler = new VplsNeighbourHandler();
Luca Prete092e8952016-10-26 16:25:56 +0200170 SetMultimap<String, Interface> ifacesByVpls =
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700171 HashMultimap.create();
Luca Prete092e8952016-10-26 16:25:56 +0200172 ifacesByVpls.put(VPLS1, V100H1);
173 ifacesByVpls.put(VPLS1, V200H1);
174 ifacesByVpls.put(VPLS1, V300H1);
175 ifacesByVpls.put(VPLS2, V100H2);
176 ifacesByVpls.put(VPLS2, V200H2);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100177 ifacesByVpls.put(VPLS3, VNONEH1);
178 ifacesByVpls.put(VPLS3, VNONEH2);
179 ifacesByVpls.put(VPLS4, V400H1);
180 ifacesByVpls.put(VPLS4, VNONEH3);
Luca Prete092e8952016-10-26 16:25:56 +0200181 HashMap<String, EncapsulationType> encap = Maps.newHashMap();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700182 vplsNeighbourHandler.vplsConfigService =
Luca Prete092e8952016-10-26 16:25:56 +0200183 new TestVplsConfigService(ifacesByVpls, encap);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700184 vplsNeighbourHandler.interfaceService =
185 new TestInterfaceService();
186 vplsNeighbourHandler.neighbourService =
187 new TestNeighbourService();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700188 hostService = new TestHostService();
189 }
190
191 @After
192 public void tearDown() {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700193 }
194
195 /**
Luca Prete092e8952016-10-26 16:25:56 +0200196 * Sends request messages to all hosts in VPLS 1.
197 * Request messages should be received from other hosts in VPLS 1.
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700198 */
199 @Test
Luca Prete092e8952016-10-26 16:25:56 +0200200 public void vpls1RequestMessage() {
201 // Request messages from v100h1 (VPLS 1) should be received by v200h1 and v300h1
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700202 TestMessageContext requestMessage =
Luca Prete092e8952016-10-26 16:25:56 +0200203 makeBroadcastRequestContext(v100Host1);
204 Set<Interface> expectInterfaces = ImmutableSet.of(V200H1, V300H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700205 vplsNeighbourHandler.handleRequest(requestMessage);
Luca Prete092e8952016-10-26 16:25:56 +0200206 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700207
Luca Prete092e8952016-10-26 16:25:56 +0200208 // Request messages from v200h1 (VPLS 1) should be received by v100h1 and v300h1
209 requestMessage = makeBroadcastRequestContext(v200Host1);
210 expectInterfaces = ImmutableSet.of(V100H1, V300H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700211 vplsNeighbourHandler.handleRequest(requestMessage);
Luca Prete092e8952016-10-26 16:25:56 +0200212 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700213
Luca Prete092e8952016-10-26 16:25:56 +0200214 // Request from v300h1 (VPLS 1) should be received by v100h1 and v200h1
215 requestMessage = makeBroadcastRequestContext(v300Host1);
216 expectInterfaces = ImmutableSet.of(V100H1, V200H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700217 vplsNeighbourHandler.handleRequest(requestMessage);
Luca Prete092e8952016-10-26 16:25:56 +0200218 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700219 }
220
221 /**
Luca Prete092e8952016-10-26 16:25:56 +0200222 * Sends request messages to all hosts in VPLS 2.
223 * Request messages should be received from other hosts in VPLS 2.
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700224 */
225 @Test
Luca Prete092e8952016-10-26 16:25:56 +0200226 public void vpls2RequestMessage() {
227 // Request messages from v100h2 (VPLS 2) should be received by v200h2
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700228 TestMessageContext requestMessage =
Luca Prete092e8952016-10-26 16:25:56 +0200229 makeBroadcastRequestContext(v100Host2);
230 Set<Interface> expectInterfaces = ImmutableSet.of(V200H2);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700231 vplsNeighbourHandler.handleRequest(requestMessage);
Luca Prete092e8952016-10-26 16:25:56 +0200232 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700233
Luca Prete092e8952016-10-26 16:25:56 +0200234 // Request messages from v200h2 (VPLS 2) should be received by v100h2
235 requestMessage = makeBroadcastRequestContext(v200Host2);
236 expectInterfaces = ImmutableSet.of(V100H2);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700237 vplsNeighbourHandler.handleRequest(requestMessage);
Luca Prete092e8952016-10-26 16:25:56 +0200238 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700239 }
240
241 /**
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100242 * Tests correct connection between untagged interfaces.
243 *
244 * Sends request messages to all hosts in VPLS 3.
245 * Request messages should be received from other hosts in VPLS 3.
246 */
247 @Test
248 public void vpls3RequestMessage() {
249 // Request messages from vNoneHost1 (VPLS 3) should be received by vNoneHost2
250 TestMessageContext requestMessage =
251 makeBroadcastRequestContext(vNoneHost1);
252 Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH2);
253 vplsNeighbourHandler.handleRequest(requestMessage);
254 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
255
256 // Request messages from vNoneh2 (VPLS 3) should be received by vNoneh1
257 requestMessage = makeBroadcastRequestContext(vNoneHost2);
258 expectInterfaces = ImmutableSet.of(VNONEH1);
259 vplsNeighbourHandler.handleRequest(requestMessage);
260 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
261 }
262
263 /**
264 * Tests correct connection between tagged and untagged interfaces.
265 *
266 * Sends request messages to all hosts in VPLS 4.
267 * Request messages should be received from other hosts in VPLS 4.
268 */
269 @Test
270 public void vpls4RequestMessage() {
271 // Request messages from v400Host1 (VPLS 4) should be received by vNoneHost3
272 TestMessageContext requestMessage =
273 makeBroadcastRequestContext(v400Host1);
274 Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH3);
275 vplsNeighbourHandler.handleRequest(requestMessage);
276 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
277
278 // Request messages from vNoneHost3 (VPLS 4) should be received by v400Host1
279 requestMessage = makeBroadcastRequestContext(vNoneHost3);
280 expectInterfaces = ImmutableSet.of(V400H1);
281 vplsNeighbourHandler.handleRequest(requestMessage);
282 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, requestMessage.forwardResults);
283 }
284
285 /**
Luca Prete092e8952016-10-26 16:25:56 +0200286 * Sends reply messages to hosts in VPLS 1.
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700287 * Reply messages should be received by the host with MAC address equal to
288 * the dstMac of the message context.
289 */
290 @Test
Luca Prete092e8952016-10-26 16:25:56 +0200291 public void vpls1ReplyMessage() {
292 // Reply messages from v100h1 (VPLS 1) should be received by v200h1
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700293 TestMessageContext replyMessage =
Luca Prete092e8952016-10-26 16:25:56 +0200294 makeReplyContext(v100Host1, v200Host1);
295 Set<Interface> expectInterfaces = ImmutableSet.of(V200H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700296 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200297 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700298
Luca Prete092e8952016-10-26 16:25:56 +0200299 // Reply messages from v200h1 (VPLS 1) should be received by v300h1
300 replyMessage = makeReplyContext(v200Host1, v300Host1);
301 expectInterfaces = ImmutableSet.of(V300H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700302 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200303 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700304
Luca Prete092e8952016-10-26 16:25:56 +0200305 // Reply messages from v300h1 (VPLS 1) should be received by v100h1
306 replyMessage = makeReplyContext(v300Host1, v100Host1);
307 expectInterfaces = ImmutableSet.of(V100H1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700308 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200309 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700310 }
311
312 /**
Luca Prete092e8952016-10-26 16:25:56 +0200313 * Sends reply messages to hosts in VPLS 2.
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700314 * Reply messages should be received by the host with MAC address equal to
315 * the dstMac of the message context.
316 */
317 @Test
Luca Prete092e8952016-10-26 16:25:56 +0200318 public void vpls2ReplyMessage() {
319 // Reply messages from v100h2 (VPLS 2) should be received by v200h2
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700320 TestMessageContext replyMessage =
Luca Prete092e8952016-10-26 16:25:56 +0200321 makeReplyContext(v100Host2, v200Host2);
322 Set<Interface> expectInterfaces = ImmutableSet.of(V200H2);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700323 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200324 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700325
Luca Prete092e8952016-10-26 16:25:56 +0200326 // Reply messages from v200h2 (VPLS 2) should be received by v100h2
327 replyMessage = makeReplyContext(v200Host2, v100Host2);
328 expectInterfaces = ImmutableSet.of(V100H2);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700329 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200330 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700331 }
332
333 /**
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100334 * Sends reply messages to hosts in VPLS 3.
335 * Reply messages should be received by the host with MAC address equal to
336 * the dstMac of the message context.
337 */
338 @Test
339 public void vpls3ReplyMessage() {
340 // Reply messages from vNoneh1 (VPLS 3) should be received by vNoneh2
341 TestMessageContext replyMessage =
342 makeReplyContext(vNoneHost1, vNoneHost2);
343 Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH2);
344 vplsNeighbourHandler.handleReply(replyMessage, hostService);
345 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
346
347 // Reply messages from vNoneh2 (VPLS 3) should be received by vNoneh1
348 replyMessage = makeReplyContext(vNoneHost2, vNoneHost1);
349 expectInterfaces = ImmutableSet.of(VNONEH1);
350 vplsNeighbourHandler.handleReply(replyMessage, hostService);
351 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
352 }
353
354 /**
355 * Sends reply messages to hosts in VPLS 4.
356 * Reply messages should be received by the host with MAC address equal to
357 * the dstMac of the message context.
358 */
359 @Test
360 public void vpls4ReplyMessage() {
361 // Reply messages from v400h1 (VPLS 4) should be received by vNoneh3
362 TestMessageContext replyMessage =
363 makeReplyContext(v400Host1, vNoneHost3);
364 Set<Interface> expectInterfaces = ImmutableSet.of(VNONEH3);
365 vplsNeighbourHandler.handleReply(replyMessage, hostService);
366 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
367
368 // Reply messages from vNoneh3 (VPLS 4) should be received by v400h1
369 replyMessage = makeReplyContext(vNoneHost3, v400Host1);
370 expectInterfaces = ImmutableSet.of(V400H1);
371 vplsNeighbourHandler.handleReply(replyMessage, hostService);
372 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
373 }
374
375 /**
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700376 * Sends wrong reply messages to hosts.
377 * The source and the destination MAC addresses are not set on any host of the VPLS.
Luca Prete092e8952016-10-26 16:25:56 +0200378 * The reply messages will not be received by any hosts.
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700379 */
380 @Test
Luca Prete092e8952016-10-26 16:25:56 +0200381 public void wrongReplyMessage() {
382 // Reply message from v100h1 (VPLS 1) to v100h2 (VPLS 2).
383 // Forward results should be empty
384 TestMessageContext replyMessage = makeReplyContext(v100Host1, v100Host2);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700385 Set<Interface> expectInterfaces = ImmutableSet.of();
386 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200387 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700388
Luca Prete092e8952016-10-26 16:25:56 +0200389 // Reply message from v200h2 (VPLS 2) to v300h1 (VPLS 1).
390 // Forward results should be empty
391 replyMessage = makeReplyContext(v200Host2, v300Host1);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700392 expectInterfaces = ImmutableSet.of();
393 vplsNeighbourHandler.handleReply(replyMessage, hostService);
Luca Prete092e8952016-10-26 16:25:56 +0200394 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100395
396 // Reply message from vNoneh1 (VPLS 3) to v400h1 (VPLS 4).
397 // Forward results should be empty
398 replyMessage = makeReplyContext(vNoneHost1, v400Host1);
399 expectInterfaces = ImmutableSet.of();
400 vplsNeighbourHandler.handleReply(replyMessage, hostService);
401 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
402
403 // Reply message from vNoneh3 (VPLS 4) to vNoneH2 (VPLS 3).
404 // Forward results should be empty
405 replyMessage = makeReplyContext(vNoneHost3, vNoneHost2);
406 expectInterfaces = ImmutableSet.of();
407 vplsNeighbourHandler.handleReply(replyMessage, hostService);
408 assertEquals(IFACES_NOT_EXPECTED, expectInterfaces, replyMessage.forwardResults);
Luca Prete092e8952016-10-26 16:25:56 +0200409 }
410
411 /**
412 * Returns the device Id of the ith device.
413 *
414 * @param i the device to get the Id of
415 * @return the device Id
416 */
417 private static DeviceId getDeviceId(int i) {
418 return DeviceId.deviceId("" + i);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700419 }
420
421 private Host makeHost(MacAddress mac, VlanId vlan, ConnectPoint cp) {
Luca Prete092e8952016-10-26 16:25:56 +0200422 return new DefaultHost(PID,
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700423 HostId.hostId(mac, vlan),
424 mac,
425 vlan,
426 new HostLocation(cp, 0),
427 Sets.newHashSet());
428 }
429
430 private TestMessageContext makeBroadcastRequestContext(Host host) {
431 return new TestMessageContext(host.location(),
432 host.mac(),
433 MacAddress.BROADCAST,
434 host.vlan(),
435 NeighbourMessageType.REQUEST);
436 }
437
438 private TestMessageContext makeReplyContext(Host src, Host dst) {
439 return new TestMessageContext(src.location(),
440 src.mac(),
441 dst.mac(),
442 src.vlan(),
443 NeighbourMessageType.REPLY);
444 }
445
446 private class TestMessageContext implements NeighbourMessageContext {
447
448
449 private final NeighbourMessageType type;
450 private final MacAddress srcMac;
451 private final MacAddress dstMac;
452 private final ConnectPoint inPort;
453 private final VlanId vlanId;
454
455 public Set<Interface> forwardResults;
456
457 /**
458 * Creates new neighbour message context for test.
459 *
460 * @param inPort the input port
461 * @param srcMac the source Mac
462 * @param dstMac the destination Mac
463 * @param vlanId the VLAN Id
464 * @param type the message context type
465 */
466 public TestMessageContext(
467 ConnectPoint inPort,
468 MacAddress srcMac,
469 MacAddress dstMac,
470 VlanId vlanId,
471 NeighbourMessageType type) {
472
473 this.inPort = inPort;
474 this.srcMac = srcMac;
475 this.dstMac = dstMac;
476 this.vlanId = vlanId;
477 this.type = type;
478
479 this.forwardResults = Sets.newHashSet();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700480 }
Luca Prete092e8952016-10-26 16:25:56 +0200481
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700482 @Override
483 public ConnectPoint inPort() {
484 return inPort;
485 }
486
487 @Override
488 public NeighbourMessageType type() {
489 return type;
490 }
491
492 @Override
493 public VlanId vlan() {
494 return vlanId;
495 }
496
497 @Override
498 public MacAddress srcMac() {
499 return srcMac;
500 }
501
502 @Override
503 public MacAddress dstMac() {
504 return dstMac;
505 }
506
507 @Override
508 public IpAddress target() {
509 return null;
510 }
511
512 @Override
513 public IpAddress sender() {
514 return null;
515 }
516
517 @Override
518 public void forward(ConnectPoint outPort) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700519 }
520
521 @Override
522 public void forward(Interface outIntf) {
523 forwardResults.add(outIntf);
524 }
525
526 @Override
527 public void reply(MacAddress targetMac) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700528 }
529
530 @Override
531 public void flood() {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700532 }
533
534 @Override
535 public void drop() {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700536 }
537
538 @Override
539 public Ethernet packet() {
540 return null;
541 }
542
543 @Override
544 public NeighbourProtocol protocol() {
545 return null;
546 }
547 }
548
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100549 private class TestVplsConfigService extends VplsConfigServiceAdapter {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700550
Luca Prete092e8952016-10-26 16:25:56 +0200551 private final SetMultimap<String, Interface> ifacesByVplsName;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700552
Luca Prete092e8952016-10-26 16:25:56 +0200553 public TestVplsConfigService(SetMultimap<String, Interface> ifacesByVplsName,
554 HashMap<String, EncapsulationType> encapByVplsName) {
555 this.ifacesByVplsName = ifacesByVplsName;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700556 }
557
558 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200559 public void addVpls(String vplsName, Set<String> ifaceNames, String encap) {
560 if (!ifacesByVplsName.containsKey(vplsName)) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700561 ifaceNames.forEach(ifaceName -> {
Luca Prete092e8952016-10-26 16:25:56 +0200562 availableInterfaces.forEach(iface -> {
563 if (iface.name().equals(ifaceName)) {
564 ifacesByVplsName.put(vplsName, iface);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700565 }
566 });
567 });
568 }
569 }
570
571 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200572 public void removeVpls(String vplsName) {
573 if (ifacesByVplsName.containsKey(vplsName)) {
574 ifacesByVplsName.removeAll(vplsName);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700575 }
576 }
577
578 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200579 public void addIface(String vplsName, String ifaceName) {
580 availableInterfaces.forEach(intf -> {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700581 if (intf.name().equals(ifaceName)) {
Luca Prete092e8952016-10-26 16:25:56 +0200582 ifacesByVplsName.put(vplsName, intf);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700583 }
584 });
585 }
586
587 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200588 public void removeIface(String ifaceName) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700589 SetMultimap<String, Interface> toBeRemoved = HashMultimap.create();
Luca Prete092e8952016-10-26 16:25:56 +0200590 ifacesByVplsName.entries().forEach(e -> {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700591 if (e.getValue().name().equals(ifaceName)) {
592 toBeRemoved.put(e.getKey(), e.getValue());
593 }
594 });
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700595 toBeRemoved.entries()
Luca Prete092e8952016-10-26 16:25:56 +0200596 .forEach(e -> ifacesByVplsName.remove(e.getKey(),
597 e.getValue()));
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700598 }
599
600 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200601 public void cleanVplsConfig() {
602 ifacesByVplsName.clear();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700603 }
604
605 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200606 public Set<Interface> allIfaces() {
607 return ImmutableSet.copyOf(ifacesByVplsName.values());
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700608 }
609
610 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200611 public Set<Interface> ifaces(String name) {
612 return ifacesByVplsName.get(name)
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700613 .stream()
614 .collect(Collectors.toSet());
615 }
616
617 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200618 public Set<String> vplsNames() {
619 return ifacesByVplsName.keySet();
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700620 }
621
622 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200623 public SetMultimap<String, Interface> ifacesByVplsName() {
624 return ImmutableSetMultimap.copyOf(ifacesByVplsName);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700625 }
626
627 @Override
Luca Prete092e8952016-10-26 16:25:56 +0200628 public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
629 ConnectPoint connectPoint) {
630 String vplsName =
631 ifacesByVplsName.entries().stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700632 .filter(e -> e.getValue().connectPoint().equals(connectPoint))
633 .filter(e -> e.getValue().vlan().equals(vlan))
Carolina Fernandezb1cef5c2016-11-22 19:18:40 +0100634 .map(Map.Entry::getKey)
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700635 .findFirst()
636 .orElse(null);
637 SetMultimap<String, Interface> result = HashMultimap.create();
Luca Prete092e8952016-10-26 16:25:56 +0200638 if (vplsName != null &&
639 ifacesByVplsName.containsKey(vplsName)) {
640 ifacesByVplsName.get(vplsName)
641 .forEach(intf -> result.put(vplsName, intf));
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700642 return result;
643 }
644 return null;
645 }
646 }
647
648 class TestHostService extends HostServiceAdapter {
649 @Override
650 public Set<Host> getHostsByMac(MacAddress mac) {
651 return availableHosts.stream()
652 .filter(host -> host.mac().equals(mac))
653 .collect(Collectors.toSet());
654 }
655
656 @Override
657 public Iterable<Host> getHosts() {
658 return availableHosts;
659 }
660
661 @Override
662 public Set<Host> getHostsByVlan(VlanId vlanId) {
663 return availableHosts.stream()
664 .filter(host -> host.vlan().equals(vlanId))
665 .collect(Collectors.toSet());
666 }
667
668 @Override
669 public int getHostCount() {
670 return availableHosts.size();
671 }
672
673 @Override
674 public Host getHost(HostId hostId) {
675 return availableHosts.stream()
676 .filter(host -> host.id().equals(hostId))
677 .findFirst()
678 .orElse(null);
679 }
680 }
681
682 private class TestNeighbourService implements NeighbourResolutionService {
683 private SetMultimap<ConnectPoint, NeighbourHandlerRegistration> handlerRegs;
684
685 public TestNeighbourService() {
686 handlerRegs = HashMultimap.create();
687 }
688
689 @Override
690 public void registerNeighbourHandler(ConnectPoint connectPoint,
691 NeighbourMessageHandler handler,
692 ApplicationId appId) {
693 Interface intf =
694 new Interface(null, connectPoint, null, null, null);
695
696 NeighbourHandlerRegistration reg =
697 new HandlerRegistration(handler, intf, appId);
698
699 handlerRegs.put(connectPoint, reg);
700 }
701
702 @Override
703 public void registerNeighbourHandler(Interface intf,
704 NeighbourMessageHandler handler,
705 ApplicationId appId) {
706 NeighbourHandlerRegistration reg =
707 new HandlerRegistration(handler, intf, appId);
708 handlerRegs.put(intf.connectPoint(), reg);
709 }
710
711 @Override
712 public void unregisterNeighbourHandler(ConnectPoint connectPoint,
713 NeighbourMessageHandler handler,
714 ApplicationId appId) {
715 handlerRegs.removeAll(connectPoint);
716 }
717
718 @Override
719 public void unregisterNeighbourHandler(Interface intf,
720 NeighbourMessageHandler handler,
721 ApplicationId appId) {
722 handlerRegs.removeAll(intf.connectPoint());
723 }
724
725 @Override
726 public void unregisterNeighbourHandlers(ApplicationId appId) {
727 handlerRegs.clear();
728 }
729
730 @Override
731 public Map<ConnectPoint, Collection<NeighbourHandlerRegistration>> getHandlerRegistrations() {
732 return handlerRegs.asMap();
733 }
734
735 private class HandlerRegistration implements NeighbourHandlerRegistration {
736 private final Interface intf;
737 private final NeighbourMessageHandler handler;
738 private final ApplicationId appId;
739
740 /**
741 * Creates a new registration handler.
742 *
743 * @param handler the neighbour message handler
744 * @param intf the interface
745 */
746 public HandlerRegistration(NeighbourMessageHandler handler,
747 Interface intf,
748 ApplicationId appId) {
749 this.intf = intf;
750 this.handler = handler;
751 this.appId = appId;
752 }
753
754 @Override
755 public Interface intf() {
756 return intf;
757 }
758
759 @Override
760 public NeighbourMessageHandler handler() {
761 return handler;
762 }
763
764 @Override
765 public ApplicationId appId() {
766 return appId;
767 }
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700768 }
769 }
770
771 class TestInterfaceService implements InterfaceService {
772
773 @Override
774 public void addListener(InterfaceListener listener) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700775 }
776
777 @Override
778 public void removeListener(InterfaceListener listener) {
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700779 }
780
781 @Override
782 public Set<Interface> getInterfaces() {
Luca Prete092e8952016-10-26 16:25:56 +0200783 return availableInterfaces;
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700784 }
785
786 @Override
787 public Interface getInterfaceByName(ConnectPoint connectPoint,
788 String name) {
Luca Prete092e8952016-10-26 16:25:56 +0200789 return availableInterfaces.stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700790 .filter(intf -> intf.name().equals(name))
791 .findFirst()
792 .orElse(null);
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700793 }
794
795 @Override
796 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
Luca Prete092e8952016-10-26 16:25:56 +0200797 return availableInterfaces.stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700798 .filter(intf -> intf.connectPoint().equals(port))
799 .collect(Collectors.toSet());
800 }
801
802 @Override
803 public Set<Interface> getInterfacesByIp(IpAddress ip) {
Luca Prete092e8952016-10-26 16:25:56 +0200804 return availableInterfaces.stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700805 .filter(intf -> intf.ipAddressesList().contains(ip))
806 .collect(Collectors.toSet());
807 }
808
809 @Override
810 public Set<Interface> getInterfacesByVlan(VlanId vlan) {
Luca Prete092e8952016-10-26 16:25:56 +0200811 return availableInterfaces.stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700812 .filter(intf -> intf.vlan().equals(vlan))
813 .collect(Collectors.toSet());
814 }
815
816 @Override
817 public Interface getMatchingInterface(IpAddress ip) {
Luca Prete092e8952016-10-26 16:25:56 +0200818 return availableInterfaces.stream()
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700819 .filter(intf -> intf.ipAddressesList().contains(ip))
820 .findFirst()
821 .orElse(null);
822 }
Charles Chanb3b09cd2017-03-14 12:53:46 -0700823
824 @Override
825 public Set<Interface> getMatchingInterfaces(IpAddress ip) {
826 return availableInterfaces.stream()
827 .filter(intf -> intf.ipAddressesList().contains(ip))
828 .collect(Collectors.toSet());
829 }
Yong-hwan Kimfbf653c2016-09-21 10:05:22 -0700830 }
831}