blob: fb1bf67a8683dde4dbde6a96b98d21d15fdca3ee [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.lldp.impl;
alshabib0ed6a202014-10-19 12:42:57 -070017
Jonathan Hart7838c512016-06-07 15:18:22 -070018import com.google.common.collect.ArrayListMultimap;
19import com.google.common.collect.ImmutableList;
20import com.google.common.collect.ImmutableMap;
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Lists;
alshabib0ed6a202014-10-19 12:42:57 -070023import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080026import org.onlab.packet.ChassisId;
27import org.onlab.packet.Ethernet;
28import org.onlab.packet.ONOSLLDP;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070029import org.onosproject.cfg.ComponentConfigAdapter;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -070030import org.onosproject.cluster.ClusterMetadataServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.cluster.NodeId;
32import org.onosproject.cluster.RoleInfo;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080033import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.core.DefaultApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.mastership.MastershipListener;
37import org.onosproject.mastership.MastershipService;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070038import org.onosproject.net.Annotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.ConnectPoint;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070040import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080041import org.onosproject.net.DefaultDevice;
42import org.onosproject.net.DefaultPort;
43import org.onosproject.net.Device;
44import org.onosproject.net.DeviceId;
45import org.onosproject.net.MastershipRole;
46import org.onosproject.net.Port;
47import org.onosproject.net.PortNumber;
Naoki Shiota399a0b32015-11-15 20:36:13 -060048import org.onosproject.net.config.Config;
Naoki Shiota399a0b32015-11-15 20:36:13 -060049import org.onosproject.net.config.NetworkConfigEvent;
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -080050import org.onosproject.net.config.NetworkConfigEvent.Type;
Naoki Shiota399a0b32015-11-15 20:36:13 -060051import org.onosproject.net.config.NetworkConfigListener;
52import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080053import org.onosproject.net.device.DeviceEvent;
54import org.onosproject.net.device.DeviceListener;
55import org.onosproject.net.device.DeviceServiceAdapter;
56import org.onosproject.net.flow.TrafficTreatment;
Ray Milkeycd6ab182016-02-03 11:13:09 -080057import org.onosproject.net.link.LinkProviderRegistryAdapter;
58import org.onosproject.net.link.LinkProviderServiceAdapter;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070059import org.onosproject.net.link.LinkServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080060import org.onosproject.net.packet.DefaultInboundPacket;
61import org.onosproject.net.packet.InboundPacket;
62import org.onosproject.net.packet.OutboundPacket;
63import org.onosproject.net.packet.PacketContext;
64import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska27bee092015-06-23 19:03:10 -070065import org.onosproject.net.packet.PacketServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080066import org.onosproject.net.provider.ProviderId;
Ray Milkey957390e2016-02-09 10:02:46 -080067import org.onosproject.provider.lldpcommon.LinkDiscovery;
alshabib0ed6a202014-10-19 12:42:57 -070068
Jonathan Hart7838c512016-06-07 15:18:22 -070069import java.nio.ByteBuffer;
70import java.util.Collections;
71import java.util.HashMap;
72import java.util.HashSet;
73import java.util.List;
74import java.util.Map;
75import java.util.Set;
76import java.util.concurrent.CompletableFuture;
Thomas Vachuska27bee092015-06-23 19:03:10 -070077
Naoki Shiota399a0b32015-11-15 20:36:13 -060078import static org.easymock.EasyMock.createMock;
79import static org.easymock.EasyMock.expect;
80import static org.easymock.EasyMock.replay;
Naoki Shiota399a0b32015-11-15 20:36:13 -060081import static org.junit.Assert.assertEquals;
Ray Milkeycd6ab182016-02-03 11:13:09 -080082import static org.junit.Assert.assertFalse;
83import static org.junit.Assert.assertNotNull;
84import static org.junit.Assert.assertNull;
Naoki Shiota399a0b32015-11-15 20:36:13 -060085import static org.junit.Assert.assertTrue;
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080086import static org.onlab.junit.TestTools.assertAfter;
Naoki Shiota399a0b32015-11-15 20:36:13 -060087import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;
Naoki Shiota399a0b32015-11-15 20:36:13 -060088
alshabib0ed6a202014-10-19 12:42:57 -070089
Jonathan Hartb35540a2015-11-17 09:30:56 -080090public class LldpLinkProviderTest {
alshabib0ed6a202014-10-19 12:42:57 -070091
92 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
93 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070094 private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080095 private static final int EVENT_MS = 500;
alshabib0ed6a202014-10-19 12:42:57 -070096
97 private static Port pd1;
98 private static Port pd2;
99 private static Port pd3;
100 private static Port pd4;
101
Jonathan Hartb35540a2015-11-17 09:30:56 -0800102 private final LldpLinkProvider provider = new LldpLinkProvider();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800103 private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter();
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700104 private final TestLinkService linkService = new TestLinkService();
alshabib0ed6a202014-10-19 12:42:57 -0700105 private final TestPacketService packetService = new TestPacketService();
106 private final TestDeviceService deviceService = new TestDeviceService();
107 private final TestMasterShipService masterService = new TestMasterShipService();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600108 private final TestNetworkConfigRegistry configRegistry = new TestNetworkConfigRegistry();
alshabib0ed6a202014-10-19 12:42:57 -0700109
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800110 private CoreService coreService;
Ray Milkeycd6ab182016-02-03 11:13:09 -0800111 private LinkProviderServiceAdapter providerService;
alshabib0ed6a202014-10-19 12:42:57 -0700112
113 private PacketProcessor testProcessor;
114 private DeviceListener deviceListener;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600115 private NetworkConfigListener configListener;
alshabib0ed6a202014-10-19 12:42:57 -0700116
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800117 private ApplicationId appId =
118 new DefaultApplicationId(100, "org.onosproject.provider.lldp");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800119
Naoki Shiota399a0b32015-11-15 20:36:13 -0600120 private TestSuppressionConfig cfg;
121
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800122 private Set<DeviceId> deviceBlacklist;
123
124 private Set<ConnectPoint> portBlacklist;
125
alshabib0ed6a202014-10-19 12:42:57 -0700126 @Before
127 public void setUp() {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800128 deviceBlacklist = new HashSet<>();
129 portBlacklist = new HashSet<>();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600130 cfg = new TestSuppressionConfig();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800131 coreService = createMock(CoreService.class);
132 expect(coreService.registerApplication(appId.name()))
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800133 .andReturn(appId).anyTimes();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800134 replay(coreService);
135
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700136 provider.cfgService = new ComponentConfigAdapter();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800137 provider.coreService = coreService;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600138 provider.cfgRegistry = configRegistry;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800139
alshabib0ed6a202014-10-19 12:42:57 -0700140 provider.deviceService = deviceService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700141 provider.linkService = linkService;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800142 provider.packetService = packetService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700143 provider.providerRegistry = linkRegistry;
alshabib0ed6a202014-10-19 12:42:57 -0700144 provider.masterService = masterService;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -0700145 provider.clusterMetadataService = new ClusterMetadataServiceAdapter();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800146
Saurav Dasc313c402015-02-27 10:09:47 -0800147 provider.activate(null);
Ray Milkeycd6ab182016-02-03 11:13:09 -0800148
149 providerService = linkRegistry.registeredProvider();
alshabib0ed6a202014-10-19 12:42:57 -0700150 }
151
152 @Test
153 public void basics() {
154 assertNotNull("registration expected", providerService);
155 assertEquals("incorrect provider", provider, providerService.provider());
156 }
157
158 @Test
159 public void switchAdd() {
160 DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1);
161 deviceListener.event(de);
162
163 assertFalse("Device not added", provider.discoverers.isEmpty());
164 }
165
166 @Test
167 public void switchRemove() {
168 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
169 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
170
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700171 final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
172 if (linkDiscovery != null) {
173 // If LinkDiscovery helper is there after DEVICE_REMOVED,
174 // it should be stopped
175 assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
176 }
alshabib0ed6a202014-10-19 12:42:57 -0700177 assertTrue("Device is not gone.", vanishedDpid(DID1));
178 }
179
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700180 /**
181 * Checks that links on a reconfigured switch are properly removed.
182 */
183 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800184 public void switchSuppressedByAnnotation() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600185
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700186 // add device to stub DeviceService
187 deviceService.putDevice(device(DID3));
188 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
189
190 assertFalse("Device not added", provider.discoverers.isEmpty());
191
192 // update device in stub DeviceService with suppression config
193 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800194 .set(LldpLinkProvider.NO_LLDP, "true")
195 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700196 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
197
Naoki Shiota399a0b32015-11-15 20:36:13 -0600198 // discovery on device is expected to be gone or stopped
199 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
200 if (linkDiscovery != null) {
201 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
202 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700203 }
204
alshabib0ed6a202014-10-19 12:42:57 -0700205 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800206 public void switchSuppressByBlacklist() {
207 // add device in stub DeviceService
208 deviceService.putDevice(device(DID3));
209 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
210
211 // add deviveId to device blacklist
212 deviceBlacklist.add(DID3);
213 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
214 DID3,
215 LinkDiscoveryFromDevice.class));
216
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800217 assertAfter(EVENT_MS, () -> {
218 // discovery helper for device is expected to be gone or stopped
219 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
220 if (linkDiscovery != null) {
221 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
222 }
223 });
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800224 }
225
226 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700227 public void portUp() {
228 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
229 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
230
231 assertTrue("Port not added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700232 provider.discoverers.get(DID1).containsPort(3L));
alshabib0ed6a202014-10-19 12:42:57 -0700233 }
234
235 @Test
236 public void portDown() {
237
238 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
239 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
240
alshabib0ed6a202014-10-19 12:42:57 -0700241 assertFalse("Port added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700242 provider.discoverers.get(DID1).containsPort(1L));
243 assertTrue("Port is not gone.", vanishedPort(1L));
alshabib0ed6a202014-10-19 12:42:57 -0700244 }
245
246 @Test
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700247 public void portRemoved() {
248 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
249 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
250 deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));
251
252 assertTrue("Port is not gone.", vanishedPort(3L));
253 assertFalse("Port was not removed from discoverer",
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800254 provider.discoverers.get(DID1).containsPort(3L));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700255 }
256
257 /**
258 * Checks that discovery on reconfigured switch are properly restarted.
259 */
260 @Test
Naoki Shiota399a0b32015-11-15 20:36:13 -0600261 public void portSuppressedByDeviceAnnotationConfig() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700262
263 /// When Device is configured with suppression:ON, Port also is same
264
265 // add device in stub DeviceService with suppression configured
266 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800267 .set(LldpLinkProvider.NO_LLDP, "true")
268 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700269 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
270
271 // non-suppressed port added to suppressed device
272 final long portno3 = 3L;
273 deviceService.putPorts(DID3, port(DID3, portno3, true));
274 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
275
276 // discovery on device is expected to be stopped
277 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
278 if (linkDiscovery != null) {
279 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
280 }
281
282 /// When Device is reconfigured without suppression:OFF,
283 /// Port should be included for discovery
284
285 // update device in stub DeviceService without suppression configured
286 deviceService.putDevice(device(DID3));
287 // update the Port in stub DeviceService. (Port has reference to Device)
288 deviceService.putPorts(DID3, port(DID3, portno3, true));
289 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
290
291 // discovery should come back on
292 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
293 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
294 }
295
296 /**
Naoki Shiota399a0b32015-11-15 20:36:13 -0600297 * Checks that discovery on reconfigured switch are properly restarted.
298 */
299 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800300 public void portSuppressedByParentDeviceIdBlacklist() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600301
302 /// When Device is configured without suppression:OFF,
303 /// Port should be included for discovery
304
305 // add device in stub DeviceService without suppression configured
306 deviceService.putDevice(device(DID3));
307 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
308
309 // non-suppressed port added to suppressed device
310 final long portno3 = 3L;
311 deviceService.putPorts(DID3, port(DID3, portno3, true));
312 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
313
314 // discovery should succeed
315 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
316 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
317
318 // add suppression rule for "deviceId: "of:0000000000000003""
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800319 deviceBlacklist.add(DID3);
320 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
321 DID3,
322 LinkDiscoveryFromDevice.class));
323
Naoki Shiota399a0b32015-11-15 20:36:13 -0600324
325 /// When Device is reconfigured with suppression:ON, Port also is same
326
327 // update device in stub DeviceService with suppression configured
328 deviceService.putDevice(device(DID3));
329 // update the Port in stub DeviceService. (Port has reference to Device)
330 deviceService.putPorts(DID3, port(DID3, portno3, true));
331 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
332
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800333 // discovery helper for device is expected to be gone or stopped
Naoki Shiota399a0b32015-11-15 20:36:13 -0600334 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
335 if (linkDiscovery != null) {
336 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
337 }
338 }
339
340 /**
341 * Checks that discovery on reconfigured switch are properly restarted.
342 */
343 @Test
344 public void portSuppressedByDeviceTypeConfig() {
345
346 /// When Device is configured without suppression:OFF,
347 /// Port should be included for discovery
348
349 // add device in stub DeviceService without suppression configured
350 deviceService.putDevice(device(DID1, Device.Type.SWITCH));
351 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
352
353 // non-suppressed port added to suppressed device
354 final long portno3 = 3L;
355 deviceService.putPorts(DID1, port(DID1, portno3, true));
356 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, portno3, true)));
357
358 // add device in stub DeviceService with suppression configured
359 deviceService.putDevice(device(DID2, Device.Type.ROADM));
360 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
361
362 // non-suppressed port added to suppressed device
363 final long portno4 = 4L;
364 deviceService.putPorts(DID2, port(DID2, portno4, true));
365 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, portno4, true)));
366
367 // discovery should succeed for this device
368 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID1).isStopped());
369 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID1).containsPort(portno3));
370
371 // discovery on device is expected to be stopped for this device
372 LinkDiscovery linkDiscovery = provider.discoverers.get(DID2);
373 if (linkDiscovery != null) {
374 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
375 }
376 }
377
378 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700379 * Checks that discovery on reconfigured port are properly restarted.
380 */
381 @Test
382 public void portSuppressedByPortConfig() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600383
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700384 // add device in stub DeviceService without suppression configured
385 deviceService.putDevice(device(DID3));
386 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
387
388 // suppressed port added to non-suppressed device
389 final long portno3 = 3L;
390 final Port port3 = port(DID3, portno3, true,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800391 DefaultAnnotations.builder()
392 .set(LldpLinkProvider.NO_LLDP, "true")
393 .build());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700394 deviceService.putPorts(DID3, port3);
395 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
396
397 // discovery helper should be there turned on
398 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
399 assertFalse("Discoverer should not contain the port there",
400 provider.discoverers.get(DID3).containsPort(portno3));
401 }
402
403 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800404 public void portSuppressedByPortBlacklist() {
405
406 // add device in stub DeviceService without suppression configured
407 deviceService.putDevice(device(DID3));
408 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
409
410 final long portno3 = 3L;
411 final Port port3 = port(DID3, portno3, true);
412
413 final ConnectPoint cpDid3no3 = new ConnectPoint(DID3, PortNumber.portNumber(portno3));
414 portBlacklist.add(cpDid3no3);
415
416 // suppressed port added to non-suppressed device
417 deviceService.putPorts(DID3, port3);
418 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
419
420 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
421 cpDid3no3,
422 LinkDiscoveryFromPort.class));
423
424 // discovery helper should be there turned on
425 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
426 // but port is not a discovery target
427 assertFalse("Discoverer should not contain the port there",
428 provider.discoverers.get(DID3).containsPort(portno3));
429 }
430
431 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700432 public void portUnknown() {
433 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700434 // Note: DID3 hasn't been added to TestDeviceService, but only port is added
435 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));
alshabib0ed6a202014-10-19 12:42:57 -0700436
437
alshabibdfc7afb2014-10-21 20:13:27 -0700438 assertNull("DeviceId exists",
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700439 provider.discoverers.get(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700440 }
441
442 @Test
443 public void unknownPktCtx() {
444
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700445 // Note: DID3 hasn't been added to TestDeviceService
446 PacketContext pktCtx = new TestPacketContext(device(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700447
448 testProcessor.process(pktCtx);
449 assertFalse("Context should still be free", pktCtx.isHandled());
450 }
451
452 @Test
453 public void knownPktCtx() {
454 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
455 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
456 PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
457
458
459 testProcessor.process(pktCtx);
460
461 assertTrue("Link not detected", detectedLink(DID1, DID2));
462
463 }
464
465
466 @After
467 public void tearDown() {
468 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800469 provider.coreService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700470 provider.providerRegistry = null;
471 provider.deviceService = null;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800472 provider.packetService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700473 }
474
475 private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) {
476 return new DeviceEvent(type, deviceService.getDevice(did));
477
478 }
479
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700480 private DefaultDevice device(DeviceId did) {
481 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800482 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700483 }
484
Naoki Shiota399a0b32015-11-15 20:36:13 -0600485 private DefaultDevice device(DeviceId did, Device.Type type) {
486 return new DefaultDevice(ProviderId.NONE, did, type,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800487 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
Naoki Shiota399a0b32015-11-15 20:36:13 -0600488 }
489
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700490 private DefaultDevice device(DeviceId did, Annotations annotations) {
491 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800492 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700493 }
494
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800495 @SuppressWarnings(value = {"unused"})
alshabib0ed6a202014-10-19 12:42:57 -0700496 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800497 return new DeviceEvent(type, deviceService.getDevice(did),
498 deviceService.getPort(did, port));
alshabib0ed6a202014-10-19 12:42:57 -0700499 }
500
501 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800502 return new DeviceEvent(type, deviceService.getDevice(did), port);
alshabib0ed6a202014-10-19 12:42:57 -0700503 }
504
505 private Port port(DeviceId did, long port, boolean enabled) {
506 return new DefaultPort(deviceService.getDevice(did),
507 PortNumber.portNumber(port), enabled);
508 }
509
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700510 private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
511 return new DefaultPort(deviceService.getDevice(did),
512 PortNumber.portNumber(port), enabled, annotations);
513 }
alshabib0ed6a202014-10-19 12:42:57 -0700514
515 private boolean vanishedDpid(DeviceId... dids) {
516 for (int i = 0; i < dids.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800517 if (!providerService.vanishedDpid().contains(dids[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700518 return false;
519 }
520 }
521 return true;
522 }
523
524 private boolean vanishedPort(Long... ports) {
525 for (int i = 0; i < ports.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800526 if (!providerService.vanishedPort().contains(ports[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700527 return false;
528 }
529 }
530 return true;
531 }
532
533 private boolean detectedLink(DeviceId src, DeviceId dst) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800534 for (DeviceId key : providerService.discoveredLinks().keySet()) {
alshabib0ed6a202014-10-19 12:42:57 -0700535 if (key.equals(src)) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800536 return providerService.discoveredLinks().get(src).equals(dst);
alshabib0ed6a202014-10-19 12:42:57 -0700537 }
538 }
539 return false;
540 }
541
Naoki Shiota399a0b32015-11-15 20:36:13 -0600542 @Test
543 public void addDeviceTypeRule() {
544 Device.Type deviceType1 = Device.Type.ROADM;
545 Device.Type deviceType2 = Device.Type.SWITCH;
546
547 Set<Device.Type> deviceTypes = new HashSet<>();
548 deviceTypes.add(deviceType1);
549
550 cfg.deviceTypes(deviceTypes);
551
552 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
553
554 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
555 assertFalse(provider.rules().getSuppressedDeviceType().contains(deviceType2));
556 }
557
558 @Test
559 public void updateDeviceTypeRule() {
560 Device.Type deviceType1 = Device.Type.ROADM;
561 Device.Type deviceType2 = Device.Type.SWITCH;
562 Set<Device.Type> deviceTypes = new HashSet<>();
563
564 deviceTypes.add(deviceType1);
565 cfg.deviceTypes(deviceTypes);
566
567 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
568
569 deviceTypes.add(deviceType2);
570 cfg.deviceTypes(deviceTypes);
571
572 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
573
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800574 assertAfter(EVENT_MS, () -> {
575 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
576 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType2));
577 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600578 }
579
580 @Test
581 public void addAnnotationRule() {
582 final String key1 = "key1", key2 = "key2";
583 final String value1 = "value1";
584
585 Map<String, String> annotation = new HashMap<>();
586 annotation.put(key1, value1);
587
588 cfg.annotation(annotation);
589
590 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
591
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800592 assertAfter(EVENT_MS, () -> {
593 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
594 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
595 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
596 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600597 }
598
599 @Test
600 public void updateAnnotationRule() {
601 final String key1 = "key1", key2 = "key2";
602 final String value1 = "value1", value2 = "value2";
603 Map<String, String> annotation = new HashMap<>();
604
605 annotation.put(key1, value1);
606 cfg.annotation(annotation);
607
608 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
609
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800610 assertAfter(EVENT_MS, () -> {
611 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
612 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
613 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
614 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600615
616 annotation.put(key2, value2);
617 cfg.annotation(annotation);
618
619 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
620
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800621 assertAfter(EVENT_MS, () -> {
622 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
623 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
624 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key2));
625 assertEquals(value2, provider.rules().getSuppressedAnnotation().get(key2));
626 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600627 }
628
629 private void configEvent(NetworkConfigEvent.Type evType) {
630 configListener.event(new NetworkConfigEvent(evType,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800631 appId,
632 SuppressionConfig.class));
Naoki Shiota399a0b32015-11-15 20:36:13 -0600633 }
634
alshabib0ed6a202014-10-19 12:42:57 -0700635 private class TestPacketContext implements PacketContext {
636
637 protected Device device;
638 protected boolean blocked = false;
639
640 public TestPacketContext(Device dev) {
641 device = dev;
642 }
643
644 @Override
645 public long time() {
646 return 0;
647 }
648
649 @Override
650 public InboundPacket inPacket() {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800651 ONOSLLDP lldp = ONOSLLDP.onosLLDP(deviceService.getDevice(DID1).id().toString(),
652 device.chassisId(),
653 (int) pd1.number().toLong());
alshabib0ed6a202014-10-19 12:42:57 -0700654
655 Ethernet ethPacket = new Ethernet();
656 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Jonathan Hart7838c512016-06-07 15:18:22 -0700657 ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
alshabib0ed6a202014-10-19 12:42:57 -0700658 ethPacket.setPayload(lldp);
659 ethPacket.setPad(true);
660
alshabib0ed6a202014-10-19 12:42:57 -0700661 ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
662
663 ConnectPoint cp = new ConnectPoint(device.id(), pd3.number());
664
665 return new DefaultInboundPacket(cp, ethPacket,
666 ByteBuffer.wrap(ethPacket.serialize()));
667
668 }
669
670 @Override
671 public OutboundPacket outPacket() {
672 return null;
673 }
674
675 @Override
676 public TrafficTreatment.Builder treatmentBuilder() {
677 return null;
678 }
679
680 @Override
681 public void send() {
682
683 }
684
685 @Override
686 public boolean block() {
687 blocked = true;
688 return blocked;
689 }
690
691 @Override
692 public boolean isHandled() {
693 return blocked;
694 }
695
696 }
697
Thomas Vachuska27bee092015-06-23 19:03:10 -0700698 private class TestPacketService extends PacketServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700699 @Override
700 public void addProcessor(PacketProcessor processor, int priority) {
701 testProcessor = processor;
702 }
alshabib0ed6a202014-10-19 12:42:57 -0700703 }
704
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800705 private class TestDeviceService extends DeviceServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700706
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700707 private final Map<DeviceId, Device> devices = new HashMap<>();
alshabib0ed6a202014-10-19 12:42:57 -0700708 private final ArrayListMultimap<DeviceId, Port> ports =
709 ArrayListMultimap.create();
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800710
alshabib0ed6a202014-10-19 12:42:57 -0700711 public TestDeviceService() {
712 Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
713 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
714 Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH,
715 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
716 devices.put(DID1, d1);
717 devices.put(DID2, d2);
alshabib0ed6a202014-10-19 12:42:57 -0700718 pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
719 pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
720 pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
721 pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true);
722
723 ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
724 ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
alshabib0ed6a202014-10-19 12:42:57 -0700725 }
726
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700727 private void putDevice(Device device) {
728 DeviceId deviceId = device.id();
729 devices.put(deviceId, device);
730 }
731
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800732 private void putPorts(DeviceId did, Port... ports) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700733 this.ports.putAll(did, Lists.newArrayList(ports));
734 }
735
alshabib0ed6a202014-10-19 12:42:57 -0700736 @Override
737 public int getDeviceCount() {
738 return devices.values().size();
739 }
740
741 @Override
742 public Iterable<Device> getDevices() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700743 return ImmutableList.copyOf(devices.values());
alshabib0ed6a202014-10-19 12:42:57 -0700744 }
745
746 @Override
747 public Device getDevice(DeviceId deviceId) {
748 return devices.get(deviceId);
749 }
750
751 @Override
752 public MastershipRole getRole(DeviceId deviceId) {
753 return MastershipRole.MASTER;
754 }
755
756 @Override
757 public List<Port> getPorts(DeviceId deviceId) {
758 return ports.get(deviceId);
759 }
760
761 @Override
762 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
763 for (Port p : ports.get(deviceId)) {
764 if (p.number().equals(portNumber)) {
765 return p;
766 }
767 }
768 return null;
769 }
770
771 @Override
772 public boolean isAvailable(DeviceId deviceId) {
773 return true;
774 }
775
776 @Override
777 public void addListener(DeviceListener listener) {
778 deviceListener = listener;
779
780 }
781
782 @Override
783 public void removeListener(DeviceListener listener) {
784
785 }
786 }
787
788 private final class TestMasterShipService implements MastershipService {
789
790 @Override
791 public MastershipRole getLocalRole(DeviceId deviceId) {
792 return MastershipRole.MASTER;
793 }
794
795 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700796 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
797 return CompletableFuture.completedFuture(null);
alshabib0ed6a202014-10-19 12:42:57 -0700798 }
799
800 @Override
Madan Jampanic6e574f2015-05-29 13:41:52 -0700801 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
802 return null;
alshabib0ed6a202014-10-19 12:42:57 -0700803 }
804
805 @Override
806 public NodeId getMasterFor(DeviceId deviceId) {
807 return null;
808 }
809
810 @Override
811 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
812 return null;
813 }
814
815 @Override
alshabib0ed6a202014-10-19 12:42:57 -0700816 public void addListener(MastershipListener listener) {
817
818 }
819
820 @Override
821 public void removeListener(MastershipListener listener) {
822
823 }
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700824
825 @Override
Ayaka Koshibeabedb092014-10-20 17:01:31 -0700826 public RoleInfo getNodesFor(DeviceId deviceId) {
827 return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700828 }
alshabib0ed6a202014-10-19 12:42:57 -0700829 }
830
831
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700832 private class TestLinkService extends LinkServiceAdapter {
833 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600834
835 private final class TestNetworkConfigRegistry
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800836 extends NetworkConfigRegistryAdapter {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800837 @SuppressWarnings("unchecked")
Naoki Shiota399a0b32015-11-15 20:36:13 -0600838 @Override
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800839 public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
840 if (configClass == SuppressionConfig.class) {
841 return (C) cfg;
842 } else if (configClass == LinkDiscoveryFromDevice.class) {
843 return (C) new LinkDiscoveryFromDevice() {
844 @Override
845 public boolean enabled() {
846 return !deviceBlacklist.contains(subj);
847 }
848 };
849 } else if (configClass == LinkDiscoveryFromPort.class) {
850 return (C) new LinkDiscoveryFromPort() {
851 @Override
852 public boolean enabled() {
853 return !portBlacklist.contains(subj);
854 }
855 };
856 } else {
857 return null;
858 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600859 }
860
861 @Override
862 public void addListener(NetworkConfigListener listener) {
863 configListener = listener;
864 }
865 }
866
867 private final class TestSuppressionConfig extends SuppressionConfig {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600868 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
869 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());
870
871 @Override
Naoki Shiota399a0b32015-11-15 20:36:13 -0600872 public Set<Device.Type> deviceTypes() {
873 return ImmutableSet.copyOf(deviceTypes);
874 }
875
876 @Override
877 public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
878 this.deviceTypes = ImmutableSet.copyOf(deviceTypes);
879 return this;
880 }
881
882 @Override
883 public Map<String, String> annotation() {
884 return ImmutableMap.copyOf(annotation);
885 }
886
887 @Override
888 public SuppressionConfig annotation(Map<String, String> annotation) {
889 this.annotation = ImmutableMap.copyOf(annotation);
890 return this;
891 }
892 }
alshabib0ed6a202014-10-19 12:42:57 -0700893}