blob: b9118790fdd5b91f2216dd7267b9e7808c3d92d5 [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
Ray Milkeycd6ab182016-02-03 11:13:09 -080018import java.nio.ByteBuffer;
19import java.util.Collections;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.List;
23import java.util.Map;
24import java.util.Set;
25import java.util.concurrent.CompletableFuture;
Ayaka Koshibe12c8c082015-12-08 12:48:46 -080026
alshabib0ed6a202014-10-19 12:42:57 -070027import org.junit.After;
28import org.junit.Before;
29import org.junit.Test;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080030import org.onlab.packet.ChassisId;
31import org.onlab.packet.Ethernet;
32import org.onlab.packet.ONOSLLDP;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070033import org.onosproject.cfg.ComponentConfigAdapter;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -070034import org.onosproject.cluster.ClusterMetadataServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.cluster.NodeId;
36import org.onosproject.cluster.RoleInfo;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080037import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
39import org.onosproject.core.DefaultApplicationId;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.mastership.MastershipListener;
41import org.onosproject.mastership.MastershipService;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070042import org.onosproject.net.Annotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080043import org.onosproject.net.ConnectPoint;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070044import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.DefaultDevice;
46import org.onosproject.net.DefaultPort;
47import org.onosproject.net.Device;
48import org.onosproject.net.DeviceId;
49import org.onosproject.net.MastershipRole;
50import org.onosproject.net.Port;
51import org.onosproject.net.PortNumber;
Naoki Shiota399a0b32015-11-15 20:36:13 -060052import org.onosproject.net.config.Config;
Naoki Shiota399a0b32015-11-15 20:36:13 -060053import org.onosproject.net.config.NetworkConfigEvent;
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -080054import org.onosproject.net.config.NetworkConfigEvent.Type;
Naoki Shiota399a0b32015-11-15 20:36:13 -060055import org.onosproject.net.config.NetworkConfigListener;
56import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080057import org.onosproject.net.device.DeviceEvent;
58import org.onosproject.net.device.DeviceListener;
59import org.onosproject.net.device.DeviceServiceAdapter;
60import org.onosproject.net.flow.TrafficTreatment;
Ray Milkeycd6ab182016-02-03 11:13:09 -080061import org.onosproject.net.link.LinkProviderRegistryAdapter;
62import org.onosproject.net.link.LinkProviderServiceAdapter;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070063import org.onosproject.net.link.LinkServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080064import org.onosproject.net.packet.DefaultInboundPacket;
65import org.onosproject.net.packet.InboundPacket;
66import org.onosproject.net.packet.OutboundPacket;
67import org.onosproject.net.packet.PacketContext;
68import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska27bee092015-06-23 19:03:10 -070069import org.onosproject.net.packet.PacketServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080070import org.onosproject.net.provider.ProviderId;
Ray Milkey957390e2016-02-09 10:02:46 -080071import org.onosproject.provider.lldpcommon.LinkDiscovery;
alshabib0ed6a202014-10-19 12:42:57 -070072
Ray Milkeycd6ab182016-02-03 11:13:09 -080073import com.google.common.collect.ArrayListMultimap;
74import com.google.common.collect.ImmutableList;
75import com.google.common.collect.ImmutableMap;
76import com.google.common.collect.ImmutableSet;
77import com.google.common.collect.Lists;
Thomas Vachuska27bee092015-06-23 19:03:10 -070078
Naoki Shiota399a0b32015-11-15 20:36:13 -060079import static org.easymock.EasyMock.createMock;
80import static org.easymock.EasyMock.expect;
81import static org.easymock.EasyMock.replay;
Naoki Shiota399a0b32015-11-15 20:36:13 -060082import static org.junit.Assert.assertEquals;
Ray Milkeycd6ab182016-02-03 11:13:09 -080083import static org.junit.Assert.assertFalse;
84import static org.junit.Assert.assertNotNull;
85import static org.junit.Assert.assertNull;
Naoki Shiota399a0b32015-11-15 20:36:13 -060086import static org.junit.Assert.assertTrue;
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080087import static org.onlab.junit.TestTools.assertAfter;
Naoki Shiota399a0b32015-11-15 20:36:13 -060088import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;
Naoki Shiota399a0b32015-11-15 20:36:13 -060089
alshabib0ed6a202014-10-19 12:42:57 -070090
Jonathan Hartb35540a2015-11-17 09:30:56 -080091public class LldpLinkProviderTest {
alshabib0ed6a202014-10-19 12:42:57 -070092
93 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
94 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070095 private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080096 private static final int EVENT_MS = 500;
alshabib0ed6a202014-10-19 12:42:57 -070097
98 private static Port pd1;
99 private static Port pd2;
100 private static Port pd3;
101 private static Port pd4;
102
Jonathan Hartb35540a2015-11-17 09:30:56 -0800103 private final LldpLinkProvider provider = new LldpLinkProvider();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800104 private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter();
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700105 private final TestLinkService linkService = new TestLinkService();
alshabib0ed6a202014-10-19 12:42:57 -0700106 private final TestPacketService packetService = new TestPacketService();
107 private final TestDeviceService deviceService = new TestDeviceService();
108 private final TestMasterShipService masterService = new TestMasterShipService();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600109 private final TestNetworkConfigRegistry configRegistry = new TestNetworkConfigRegistry();
alshabib0ed6a202014-10-19 12:42:57 -0700110
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800111 private CoreService coreService;
Ray Milkeycd6ab182016-02-03 11:13:09 -0800112 private LinkProviderServiceAdapter providerService;
alshabib0ed6a202014-10-19 12:42:57 -0700113
114 private PacketProcessor testProcessor;
115 private DeviceListener deviceListener;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600116 private NetworkConfigListener configListener;
alshabib0ed6a202014-10-19 12:42:57 -0700117
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800118 private ApplicationId appId =
119 new DefaultApplicationId(100, "org.onosproject.provider.lldp");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800120
Naoki Shiota399a0b32015-11-15 20:36:13 -0600121 private TestSuppressionConfig cfg;
122
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800123 private Set<DeviceId> deviceBlacklist;
124
125 private Set<ConnectPoint> portBlacklist;
126
alshabib0ed6a202014-10-19 12:42:57 -0700127 @Before
128 public void setUp() {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800129 deviceBlacklist = new HashSet<>();
130 portBlacklist = new HashSet<>();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600131 cfg = new TestSuppressionConfig();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800132 coreService = createMock(CoreService.class);
133 expect(coreService.registerApplication(appId.name()))
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800134 .andReturn(appId).anyTimes();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800135 replay(coreService);
136
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700137 provider.cfgService = new ComponentConfigAdapter();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800138 provider.coreService = coreService;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600139 provider.cfgRegistry = configRegistry;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800140
alshabib0ed6a202014-10-19 12:42:57 -0700141 provider.deviceService = deviceService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700142 provider.linkService = linkService;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800143 provider.packetService = packetService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700144 provider.providerRegistry = linkRegistry;
alshabib0ed6a202014-10-19 12:42:57 -0700145 provider.masterService = masterService;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -0700146 provider.clusterMetadataService = new ClusterMetadataServiceAdapter();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800147
Saurav Dasc313c402015-02-27 10:09:47 -0800148 provider.activate(null);
Ray Milkeycd6ab182016-02-03 11:13:09 -0800149
150 providerService = linkRegistry.registeredProvider();
alshabib0ed6a202014-10-19 12:42:57 -0700151 }
152
153 @Test
154 public void basics() {
155 assertNotNull("registration expected", providerService);
156 assertEquals("incorrect provider", provider, providerService.provider());
157 }
158
159 @Test
160 public void switchAdd() {
161 DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1);
162 deviceListener.event(de);
163
164 assertFalse("Device not added", provider.discoverers.isEmpty());
165 }
166
167 @Test
168 public void switchRemove() {
169 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
170 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
171
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700172 final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
173 if (linkDiscovery != null) {
174 // If LinkDiscovery helper is there after DEVICE_REMOVED,
175 // it should be stopped
176 assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
177 }
alshabib0ed6a202014-10-19 12:42:57 -0700178 assertTrue("Device is not gone.", vanishedDpid(DID1));
179 }
180
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700181 /**
182 * Checks that links on a reconfigured switch are properly removed.
183 */
184 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800185 public void switchSuppressedByAnnotation() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600186
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700187 // add device to stub DeviceService
188 deviceService.putDevice(device(DID3));
189 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
190
191 assertFalse("Device not added", provider.discoverers.isEmpty());
192
193 // update device in stub DeviceService with suppression config
194 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800195 .set(LldpLinkProvider.NO_LLDP, "true")
196 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700197 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
198
Naoki Shiota399a0b32015-11-15 20:36:13 -0600199 // discovery on device is expected to be gone or stopped
200 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
201 if (linkDiscovery != null) {
202 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
203 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700204 }
205
alshabib0ed6a202014-10-19 12:42:57 -0700206 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800207 public void switchSuppressByBlacklist() {
208 // add device in stub DeviceService
209 deviceService.putDevice(device(DID3));
210 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
211
212 // add deviveId to device blacklist
213 deviceBlacklist.add(DID3);
214 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
215 DID3,
216 LinkDiscoveryFromDevice.class));
217
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800218 assertAfter(EVENT_MS, () -> {
219 // discovery helper for device is expected to be gone or stopped
220 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
221 if (linkDiscovery != null) {
222 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
223 }
224 });
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800225 }
226
227 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700228 public void portUp() {
229 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
230 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
231
232 assertTrue("Port not added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700233 provider.discoverers.get(DID1).containsPort(3L));
alshabib0ed6a202014-10-19 12:42:57 -0700234 }
235
236 @Test
237 public void portDown() {
238
239 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
240 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
241
alshabib0ed6a202014-10-19 12:42:57 -0700242 assertFalse("Port added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700243 provider.discoverers.get(DID1).containsPort(1L));
244 assertTrue("Port is not gone.", vanishedPort(1L));
alshabib0ed6a202014-10-19 12:42:57 -0700245 }
246
247 @Test
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700248 public void portRemoved() {
249 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
250 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
251 deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));
252
253 assertTrue("Port is not gone.", vanishedPort(3L));
254 assertFalse("Port was not removed from discoverer",
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800255 provider.discoverers.get(DID1).containsPort(3L));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700256 }
257
258 /**
259 * Checks that discovery on reconfigured switch are properly restarted.
260 */
261 @Test
Naoki Shiota399a0b32015-11-15 20:36:13 -0600262 public void portSuppressedByDeviceAnnotationConfig() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700263
264 /// When Device is configured with suppression:ON, Port also is same
265
266 // add device in stub DeviceService with suppression configured
267 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800268 .set(LldpLinkProvider.NO_LLDP, "true")
269 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700270 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
271
272 // non-suppressed port added to suppressed device
273 final long portno3 = 3L;
274 deviceService.putPorts(DID3, port(DID3, portno3, true));
275 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
276
277 // discovery on device is expected to be stopped
278 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
279 if (linkDiscovery != null) {
280 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
281 }
282
283 /// When Device is reconfigured without suppression:OFF,
284 /// Port should be included for discovery
285
286 // update device in stub DeviceService without suppression configured
287 deviceService.putDevice(device(DID3));
288 // update the Port in stub DeviceService. (Port has reference to Device)
289 deviceService.putPorts(DID3, port(DID3, portno3, true));
290 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
291
292 // discovery should come back on
293 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
294 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
295 }
296
297 /**
Naoki Shiota399a0b32015-11-15 20:36:13 -0600298 * Checks that discovery on reconfigured switch are properly restarted.
299 */
300 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800301 public void portSuppressedByParentDeviceIdBlacklist() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600302
303 /// When Device is configured without suppression:OFF,
304 /// Port should be included for discovery
305
306 // add device in stub DeviceService without suppression configured
307 deviceService.putDevice(device(DID3));
308 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
309
310 // non-suppressed port added to suppressed device
311 final long portno3 = 3L;
312 deviceService.putPorts(DID3, port(DID3, portno3, true));
313 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
314
315 // discovery should succeed
316 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
317 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
318
319 // add suppression rule for "deviceId: "of:0000000000000003""
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800320 deviceBlacklist.add(DID3);
321 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
322 DID3,
323 LinkDiscoveryFromDevice.class));
324
Naoki Shiota399a0b32015-11-15 20:36:13 -0600325
326 /// When Device is reconfigured with suppression:ON, Port also is same
327
328 // update device in stub DeviceService with suppression configured
329 deviceService.putDevice(device(DID3));
330 // update the Port in stub DeviceService. (Port has reference to Device)
331 deviceService.putPorts(DID3, port(DID3, portno3, true));
332 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
333
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800334 // discovery helper for device is expected to be gone or stopped
Naoki Shiota399a0b32015-11-15 20:36:13 -0600335 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
336 if (linkDiscovery != null) {
337 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
338 }
339 }
340
341 /**
342 * Checks that discovery on reconfigured switch are properly restarted.
343 */
344 @Test
345 public void portSuppressedByDeviceTypeConfig() {
346
347 /// When Device is configured without suppression:OFF,
348 /// Port should be included for discovery
349
350 // add device in stub DeviceService without suppression configured
351 deviceService.putDevice(device(DID1, Device.Type.SWITCH));
352 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
353
354 // non-suppressed port added to suppressed device
355 final long portno3 = 3L;
356 deviceService.putPorts(DID1, port(DID1, portno3, true));
357 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, portno3, true)));
358
359 // add device in stub DeviceService with suppression configured
360 deviceService.putDevice(device(DID2, Device.Type.ROADM));
361 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
362
363 // non-suppressed port added to suppressed device
364 final long portno4 = 4L;
365 deviceService.putPorts(DID2, port(DID2, portno4, true));
366 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, portno4, true)));
367
368 // discovery should succeed for this device
369 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID1).isStopped());
370 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID1).containsPort(portno3));
371
372 // discovery on device is expected to be stopped for this device
373 LinkDiscovery linkDiscovery = provider.discoverers.get(DID2);
374 if (linkDiscovery != null) {
375 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
376 }
377 }
378
379 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700380 * Checks that discovery on reconfigured port are properly restarted.
381 */
382 @Test
383 public void portSuppressedByPortConfig() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600384
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700385 // add device in stub DeviceService without suppression configured
386 deviceService.putDevice(device(DID3));
387 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
388
389 // suppressed port added to non-suppressed device
390 final long portno3 = 3L;
391 final Port port3 = port(DID3, portno3, true,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800392 DefaultAnnotations.builder()
393 .set(LldpLinkProvider.NO_LLDP, "true")
394 .build());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700395 deviceService.putPorts(DID3, port3);
396 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
397
398 // discovery helper should be there turned on
399 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
400 assertFalse("Discoverer should not contain the port there",
401 provider.discoverers.get(DID3).containsPort(portno3));
402 }
403
404 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800405 public void portSuppressedByPortBlacklist() {
406
407 // add device in stub DeviceService without suppression configured
408 deviceService.putDevice(device(DID3));
409 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
410
411 final long portno3 = 3L;
412 final Port port3 = port(DID3, portno3, true);
413
414 final ConnectPoint cpDid3no3 = new ConnectPoint(DID3, PortNumber.portNumber(portno3));
415 portBlacklist.add(cpDid3no3);
416
417 // suppressed port added to non-suppressed device
418 deviceService.putPorts(DID3, port3);
419 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
420
421 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
422 cpDid3no3,
423 LinkDiscoveryFromPort.class));
424
425 // discovery helper should be there turned on
426 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
427 // but port is not a discovery target
428 assertFalse("Discoverer should not contain the port there",
429 provider.discoverers.get(DID3).containsPort(portno3));
430 }
431
432 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700433 public void portUnknown() {
434 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700435 // Note: DID3 hasn't been added to TestDeviceService, but only port is added
436 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));
alshabib0ed6a202014-10-19 12:42:57 -0700437
438
alshabibdfc7afb2014-10-21 20:13:27 -0700439 assertNull("DeviceId exists",
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700440 provider.discoverers.get(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700441 }
442
443 @Test
444 public void unknownPktCtx() {
445
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700446 // Note: DID3 hasn't been added to TestDeviceService
447 PacketContext pktCtx = new TestPacketContext(device(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700448
449 testProcessor.process(pktCtx);
450 assertFalse("Context should still be free", pktCtx.isHandled());
451 }
452
453 @Test
454 public void knownPktCtx() {
455 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
456 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
457 PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
458
459
460 testProcessor.process(pktCtx);
461
462 assertTrue("Link not detected", detectedLink(DID1, DID2));
463
464 }
465
466
467 @After
468 public void tearDown() {
469 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800470 provider.coreService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700471 provider.providerRegistry = null;
472 provider.deviceService = null;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800473 provider.packetService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700474 }
475
476 private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) {
477 return new DeviceEvent(type, deviceService.getDevice(did));
478
479 }
480
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700481 private DefaultDevice device(DeviceId did) {
482 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800483 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700484 }
485
Naoki Shiota399a0b32015-11-15 20:36:13 -0600486 private DefaultDevice device(DeviceId did, Device.Type type) {
487 return new DefaultDevice(ProviderId.NONE, did, type,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800488 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
Naoki Shiota399a0b32015-11-15 20:36:13 -0600489 }
490
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700491 private DefaultDevice device(DeviceId did, Annotations annotations) {
492 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800493 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700494 }
495
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800496 @SuppressWarnings(value = {"unused"})
alshabib0ed6a202014-10-19 12:42:57 -0700497 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800498 return new DeviceEvent(type, deviceService.getDevice(did),
499 deviceService.getPort(did, port));
alshabib0ed6a202014-10-19 12:42:57 -0700500 }
501
502 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800503 return new DeviceEvent(type, deviceService.getDevice(did), port);
alshabib0ed6a202014-10-19 12:42:57 -0700504 }
505
506 private Port port(DeviceId did, long port, boolean enabled) {
507 return new DefaultPort(deviceService.getDevice(did),
508 PortNumber.portNumber(port), enabled);
509 }
510
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700511 private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
512 return new DefaultPort(deviceService.getDevice(did),
513 PortNumber.portNumber(port), enabled, annotations);
514 }
alshabib0ed6a202014-10-19 12:42:57 -0700515
516 private boolean vanishedDpid(DeviceId... dids) {
517 for (int i = 0; i < dids.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800518 if (!providerService.vanishedDpid().contains(dids[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700519 return false;
520 }
521 }
522 return true;
523 }
524
525 private boolean vanishedPort(Long... ports) {
526 for (int i = 0; i < ports.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800527 if (!providerService.vanishedPort().contains(ports[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700528 return false;
529 }
530 }
531 return true;
532 }
533
534 private boolean detectedLink(DeviceId src, DeviceId dst) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800535 for (DeviceId key : providerService.discoveredLinks().keySet()) {
alshabib0ed6a202014-10-19 12:42:57 -0700536 if (key.equals(src)) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800537 return providerService.discoveredLinks().get(src).equals(dst);
alshabib0ed6a202014-10-19 12:42:57 -0700538 }
539 }
540 return false;
541 }
542
Naoki Shiota399a0b32015-11-15 20:36:13 -0600543 @Test
544 public void addDeviceTypeRule() {
545 Device.Type deviceType1 = Device.Type.ROADM;
546 Device.Type deviceType2 = Device.Type.SWITCH;
547
548 Set<Device.Type> deviceTypes = new HashSet<>();
549 deviceTypes.add(deviceType1);
550
551 cfg.deviceTypes(deviceTypes);
552
553 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
554
555 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
556 assertFalse(provider.rules().getSuppressedDeviceType().contains(deviceType2));
557 }
558
559 @Test
560 public void updateDeviceTypeRule() {
561 Device.Type deviceType1 = Device.Type.ROADM;
562 Device.Type deviceType2 = Device.Type.SWITCH;
563 Set<Device.Type> deviceTypes = new HashSet<>();
564
565 deviceTypes.add(deviceType1);
566 cfg.deviceTypes(deviceTypes);
567
568 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
569
570 deviceTypes.add(deviceType2);
571 cfg.deviceTypes(deviceTypes);
572
573 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
574
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800575 assertAfter(EVENT_MS, () -> {
576 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
577 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType2));
578 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600579 }
580
581 @Test
582 public void addAnnotationRule() {
583 final String key1 = "key1", key2 = "key2";
584 final String value1 = "value1";
585
586 Map<String, String> annotation = new HashMap<>();
587 annotation.put(key1, value1);
588
589 cfg.annotation(annotation);
590
591 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
592
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800593 assertAfter(EVENT_MS, () -> {
594 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
595 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
596 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
597 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600598 }
599
600 @Test
601 public void updateAnnotationRule() {
602 final String key1 = "key1", key2 = "key2";
603 final String value1 = "value1", value2 = "value2";
604 Map<String, String> annotation = new HashMap<>();
605
606 annotation.put(key1, value1);
607 cfg.annotation(annotation);
608
609 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
610
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800611 assertAfter(EVENT_MS, () -> {
612 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
613 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
614 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
615 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600616
617 annotation.put(key2, value2);
618 cfg.annotation(annotation);
619
620 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
621
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800622 assertAfter(EVENT_MS, () -> {
623 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
624 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
625 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key2));
626 assertEquals(value2, provider.rules().getSuppressedAnnotation().get(key2));
627 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600628 }
629
630 private void configEvent(NetworkConfigEvent.Type evType) {
631 configListener.event(new NetworkConfigEvent(evType,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800632 appId,
633 SuppressionConfig.class));
Naoki Shiota399a0b32015-11-15 20:36:13 -0600634 }
635
alshabib0ed6a202014-10-19 12:42:57 -0700636 private class TestPacketContext implements PacketContext {
637
638 protected Device device;
639 protected boolean blocked = false;
640
641 public TestPacketContext(Device dev) {
642 device = dev;
643 }
644
645 @Override
646 public long time() {
647 return 0;
648 }
649
650 @Override
651 public InboundPacket inPacket() {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800652 ONOSLLDP lldp = ONOSLLDP.onosLLDP(deviceService.getDevice(DID1).id().toString(),
653 device.chassisId(),
654 (int) pd1.number().toLong());
alshabib0ed6a202014-10-19 12:42:57 -0700655
656 Ethernet ethPacket = new Ethernet();
657 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
658 ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_NICIRA);
659 ethPacket.setPayload(lldp);
660 ethPacket.setPad(true);
661
alshabib0ed6a202014-10-19 12:42:57 -0700662 ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
663
664 ConnectPoint cp = new ConnectPoint(device.id(), pd3.number());
665
666 return new DefaultInboundPacket(cp, ethPacket,
667 ByteBuffer.wrap(ethPacket.serialize()));
668
669 }
670
671 @Override
672 public OutboundPacket outPacket() {
673 return null;
674 }
675
676 @Override
677 public TrafficTreatment.Builder treatmentBuilder() {
678 return null;
679 }
680
681 @Override
682 public void send() {
683
684 }
685
686 @Override
687 public boolean block() {
688 blocked = true;
689 return blocked;
690 }
691
692 @Override
693 public boolean isHandled() {
694 return blocked;
695 }
696
697 }
698
Thomas Vachuska27bee092015-06-23 19:03:10 -0700699 private class TestPacketService extends PacketServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700700 @Override
701 public void addProcessor(PacketProcessor processor, int priority) {
702 testProcessor = processor;
703 }
alshabib0ed6a202014-10-19 12:42:57 -0700704 }
705
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800706 private class TestDeviceService extends DeviceServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700707
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700708 private final Map<DeviceId, Device> devices = new HashMap<>();
alshabib0ed6a202014-10-19 12:42:57 -0700709 private final ArrayListMultimap<DeviceId, Port> ports =
710 ArrayListMultimap.create();
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800711
alshabib0ed6a202014-10-19 12:42:57 -0700712 public TestDeviceService() {
713 Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
714 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
715 Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH,
716 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
717 devices.put(DID1, d1);
718 devices.put(DID2, d2);
alshabib0ed6a202014-10-19 12:42:57 -0700719 pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
720 pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
721 pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
722 pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true);
723
724 ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
725 ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
alshabib0ed6a202014-10-19 12:42:57 -0700726 }
727
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700728 private void putDevice(Device device) {
729 DeviceId deviceId = device.id();
730 devices.put(deviceId, device);
731 }
732
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800733 private void putPorts(DeviceId did, Port... ports) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700734 this.ports.putAll(did, Lists.newArrayList(ports));
735 }
736
alshabib0ed6a202014-10-19 12:42:57 -0700737 @Override
738 public int getDeviceCount() {
739 return devices.values().size();
740 }
741
742 @Override
743 public Iterable<Device> getDevices() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700744 return ImmutableList.copyOf(devices.values());
alshabib0ed6a202014-10-19 12:42:57 -0700745 }
746
747 @Override
748 public Device getDevice(DeviceId deviceId) {
749 return devices.get(deviceId);
750 }
751
752 @Override
753 public MastershipRole getRole(DeviceId deviceId) {
754 return MastershipRole.MASTER;
755 }
756
757 @Override
758 public List<Port> getPorts(DeviceId deviceId) {
759 return ports.get(deviceId);
760 }
761
762 @Override
763 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
764 for (Port p : ports.get(deviceId)) {
765 if (p.number().equals(portNumber)) {
766 return p;
767 }
768 }
769 return null;
770 }
771
772 @Override
773 public boolean isAvailable(DeviceId deviceId) {
774 return true;
775 }
776
777 @Override
778 public void addListener(DeviceListener listener) {
779 deviceListener = listener;
780
781 }
782
783 @Override
784 public void removeListener(DeviceListener listener) {
785
786 }
787 }
788
789 private final class TestMasterShipService implements MastershipService {
790
791 @Override
792 public MastershipRole getLocalRole(DeviceId deviceId) {
793 return MastershipRole.MASTER;
794 }
795
796 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700797 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
798 return CompletableFuture.completedFuture(null);
alshabib0ed6a202014-10-19 12:42:57 -0700799 }
800
801 @Override
Madan Jampanic6e574f2015-05-29 13:41:52 -0700802 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
803 return null;
alshabib0ed6a202014-10-19 12:42:57 -0700804 }
805
806 @Override
807 public NodeId getMasterFor(DeviceId deviceId) {
808 return null;
809 }
810
811 @Override
812 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
813 return null;
814 }
815
816 @Override
alshabib0ed6a202014-10-19 12:42:57 -0700817 public void addListener(MastershipListener listener) {
818
819 }
820
821 @Override
822 public void removeListener(MastershipListener listener) {
823
824 }
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700825
826 @Override
Ayaka Koshibeabedb092014-10-20 17:01:31 -0700827 public RoleInfo getNodesFor(DeviceId deviceId) {
828 return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700829 }
alshabib0ed6a202014-10-19 12:42:57 -0700830 }
831
832
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700833 private class TestLinkService extends LinkServiceAdapter {
834 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600835
836 private final class TestNetworkConfigRegistry
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800837 extends NetworkConfigRegistryAdapter {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800838 @SuppressWarnings("unchecked")
Naoki Shiota399a0b32015-11-15 20:36:13 -0600839 @Override
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800840 public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
841 if (configClass == SuppressionConfig.class) {
842 return (C) cfg;
843 } else if (configClass == LinkDiscoveryFromDevice.class) {
844 return (C) new LinkDiscoveryFromDevice() {
845 @Override
846 public boolean enabled() {
847 return !deviceBlacklist.contains(subj);
848 }
849 };
850 } else if (configClass == LinkDiscoveryFromPort.class) {
851 return (C) new LinkDiscoveryFromPort() {
852 @Override
853 public boolean enabled() {
854 return !portBlacklist.contains(subj);
855 }
856 };
857 } else {
858 return null;
859 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600860 }
861
862 @Override
863 public void addListener(NetworkConfigListener listener) {
864 configListener = listener;
865 }
866 }
867
868 private final class TestSuppressionConfig extends SuppressionConfig {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600869 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
870 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());
871
872 @Override
Naoki Shiota399a0b32015-11-15 20:36:13 -0600873 public Set<Device.Type> deviceTypes() {
874 return ImmutableSet.copyOf(deviceTypes);
875 }
876
877 @Override
878 public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
879 this.deviceTypes = ImmutableSet.copyOf(deviceTypes);
880 return this;
881 }
882
883 @Override
884 public Map<String, String> annotation() {
885 return ImmutableMap.copyOf(annotation);
886 }
887
888 @Override
889 public SuppressionConfig annotation(Map<String, String> annotation) {
890 this.annotation = ImmutableMap.copyOf(annotation);
891 return this;
892 }
893 }
alshabib0ed6a202014-10-19 12:42:57 -0700894}