blob: 8e53c9af6a1756136435894886b175ded1255c36 [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
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 Milkeyeb130702018-06-21 15:19:33 -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;
23import com.google.common.util.concurrent.MoreExecutors;
alshabib0ed6a202014-10-19 12:42:57 -070024import org.junit.After;
25import org.junit.Before;
26import org.junit.Test;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080027import org.onlab.packet.ChassisId;
28import org.onlab.packet.Ethernet;
Charles Chan928ff8b2017-05-04 12:22:54 -070029import org.onlab.packet.MacAddress;
Jonathan Hart3cfce8e2015-01-14 16:43:27 -080030import org.onlab.packet.ONOSLLDP;
Thomas Vachuska6519e6f2015-03-11 02:29:31 -070031import org.onosproject.cfg.ComponentConfigAdapter;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -070032import org.onosproject.cluster.ClusterMetadataServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.cluster.NodeId;
34import org.onosproject.cluster.RoleInfo;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -080035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
37import org.onosproject.core.DefaultApplicationId;
Ray Milkeyeb130702018-06-21 15:19:33 -070038import org.onosproject.mastership.MastershipServiceAdapter;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070039import org.onosproject.net.Annotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.ConnectPoint;
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070041import org.onosproject.net.DefaultAnnotations;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.DefaultDevice;
43import org.onosproject.net.DefaultPort;
44import org.onosproject.net.Device;
45import org.onosproject.net.DeviceId;
46import org.onosproject.net.MastershipRole;
47import org.onosproject.net.Port;
48import org.onosproject.net.PortNumber;
Naoki Shiota399a0b32015-11-15 20:36:13 -060049import org.onosproject.net.config.Config;
Naoki Shiota399a0b32015-11-15 20:36:13 -060050import org.onosproject.net.config.NetworkConfigEvent;
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -080051import org.onosproject.net.config.NetworkConfigEvent.Type;
Naoki Shiota399a0b32015-11-15 20:36:13 -060052import org.onosproject.net.config.NetworkConfigListener;
53import org.onosproject.net.config.NetworkConfigRegistryAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080054import org.onosproject.net.device.DeviceEvent;
55import org.onosproject.net.device.DeviceListener;
56import org.onosproject.net.device.DeviceServiceAdapter;
57import org.onosproject.net.flow.TrafficTreatment;
Ray Milkeycd6ab182016-02-03 11:13:09 -080058import org.onosproject.net.link.LinkProviderRegistryAdapter;
59import org.onosproject.net.link.LinkProviderServiceAdapter;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -070060import org.onosproject.net.link.LinkServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080061import org.onosproject.net.packet.DefaultInboundPacket;
62import org.onosproject.net.packet.InboundPacket;
63import org.onosproject.net.packet.OutboundPacket;
64import org.onosproject.net.packet.PacketContext;
65import org.onosproject.net.packet.PacketProcessor;
Thomas Vachuska27bee092015-06-23 19:03:10 -070066import org.onosproject.net.packet.PacketServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080067import org.onosproject.net.provider.ProviderId;
Ray Milkey957390e2016-02-09 10:02:46 -080068import org.onosproject.provider.lldpcommon.LinkDiscovery;
alshabib0ed6a202014-10-19 12:42:57 -070069
Ray Milkeyeb130702018-06-21 15:19:33 -070070import java.nio.ByteBuffer;
71import java.util.Collections;
72import java.util.HashMap;
73import java.util.HashSet;
74import java.util.List;
75import java.util.Map;
76import java.util.Set;
77import java.util.concurrent.CompletableFuture;
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();
Thomas Vachuska1c23d042018-10-17 10:05:19 -0700138 provider.enabled = false;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800139 provider.coreService = coreService;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600140 provider.cfgRegistry = configRegistry;
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800141
alshabib0ed6a202014-10-19 12:42:57 -0700142 provider.deviceService = deviceService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700143 provider.linkService = linkService;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800144 provider.packetService = packetService;
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700145 provider.providerRegistry = linkRegistry;
alshabib0ed6a202014-10-19 12:42:57 -0700146 provider.masterService = masterService;
Ayaka Koshibe07e9d412016-05-20 13:37:16 -0700147 provider.clusterMetadataService = new ClusterMetadataServiceAdapter();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800148
Saurav Dasc313c402015-02-27 10:09:47 -0800149 provider.activate(null);
Ray Milkeycd6ab182016-02-03 11:13:09 -0800150
Ray Milkeyd9bbde82016-06-09 11:35:00 -0700151 provider.eventExecutor = MoreExecutors.newDirectExecutorService();
152
Ray Milkeycd6ab182016-02-03 11:13:09 -0800153 providerService = linkRegistry.registeredProvider();
alshabib0ed6a202014-10-19 12:42:57 -0700154 }
155
156 @Test
157 public void basics() {
158 assertNotNull("registration expected", providerService);
159 assertEquals("incorrect provider", provider, providerService.provider());
160 }
161
162 @Test
163 public void switchAdd() {
164 DeviceEvent de = deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1);
165 deviceListener.event(de);
166
167 assertFalse("Device not added", provider.discoverers.isEmpty());
168 }
169
170 @Test
171 public void switchRemove() {
172 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
173 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
174
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700175 final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
176 if (linkDiscovery != null) {
177 // If LinkDiscovery helper is there after DEVICE_REMOVED,
178 // it should be stopped
179 assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
180 }
alshabib0ed6a202014-10-19 12:42:57 -0700181 assertTrue("Device is not gone.", vanishedDpid(DID1));
182 }
183
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700184 /**
185 * Checks that links on a reconfigured switch are properly removed.
186 */
187 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800188 public void switchSuppressedByAnnotation() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600189
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700190 // add device to stub DeviceService
191 deviceService.putDevice(device(DID3));
192 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
193
194 assertFalse("Device not added", provider.discoverers.isEmpty());
195
196 // update device in stub DeviceService with suppression config
197 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800198 .set(LldpLinkProvider.NO_LLDP, "true")
199 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700200 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
201
Naoki Shiota399a0b32015-11-15 20:36:13 -0600202 // discovery on device is expected to be gone or stopped
203 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
204 if (linkDiscovery != null) {
205 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
206 }
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700207 }
208
alshabib0ed6a202014-10-19 12:42:57 -0700209 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800210 public void switchSuppressByBlacklist() {
211 // add device in stub DeviceService
212 deviceService.putDevice(device(DID3));
213 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
214
215 // add deviveId to device blacklist
216 deviceBlacklist.add(DID3);
217 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
218 DID3,
219 LinkDiscoveryFromDevice.class));
220
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800221 assertAfter(EVENT_MS, () -> {
222 // discovery helper for device is expected to be gone or stopped
223 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
224 if (linkDiscovery != null) {
225 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
226 }
227 });
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800228 }
229
230 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700231 public void portUp() {
232 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
233 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
234
235 assertTrue("Port not added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700236 provider.discoverers.get(DID1).containsPort(3L));
alshabib0ed6a202014-10-19 12:42:57 -0700237 }
238
239 @Test
240 public void portDown() {
241
242 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
243 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
244
alshabib0ed6a202014-10-19 12:42:57 -0700245 assertFalse("Port added to discoverer",
Sho SHIMIZUc14b2a22015-05-05 18:15:13 -0700246 provider.discoverers.get(DID1).containsPort(1L));
247 assertTrue("Port is not gone.", vanishedPort(1L));
alshabib0ed6a202014-10-19 12:42:57 -0700248 }
249
250 @Test
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700251 public void portRemoved() {
252 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
253 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
254 deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));
255
256 assertTrue("Port is not gone.", vanishedPort(3L));
257 assertFalse("Port was not removed from discoverer",
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800258 provider.discoverers.get(DID1).containsPort(3L));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700259 }
260
261 /**
262 * Checks that discovery on reconfigured switch are properly restarted.
263 */
264 @Test
Naoki Shiota399a0b32015-11-15 20:36:13 -0600265 public void portSuppressedByDeviceAnnotationConfig() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700266
267 /// When Device is configured with suppression:ON, Port also is same
268
269 // add device in stub DeviceService with suppression configured
270 deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800271 .set(LldpLinkProvider.NO_LLDP, "true")
272 .build()));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700273 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
274
275 // non-suppressed port added to suppressed device
276 final long portno3 = 3L;
277 deviceService.putPorts(DID3, port(DID3, portno3, true));
278 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
279
280 // discovery on device is expected to be stopped
281 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
282 if (linkDiscovery != null) {
283 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
284 }
285
286 /// When Device is reconfigured without suppression:OFF,
287 /// Port should be included for discovery
288
289 // update device in stub DeviceService without suppression configured
290 deviceService.putDevice(device(DID3));
291 // update the Port in stub DeviceService. (Port has reference to Device)
292 deviceService.putPorts(DID3, port(DID3, portno3, true));
293 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
294
295 // discovery should come back on
296 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
297 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
298 }
299
300 /**
Naoki Shiota399a0b32015-11-15 20:36:13 -0600301 * Checks that discovery on reconfigured switch are properly restarted.
302 */
303 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800304 public void portSuppressedByParentDeviceIdBlacklist() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600305
306 /// When Device is configured without suppression:OFF,
307 /// Port should be included for discovery
308
309 // add device in stub DeviceService without suppression configured
310 deviceService.putDevice(device(DID3));
311 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
312
313 // non-suppressed port added to suppressed device
314 final long portno3 = 3L;
315 deviceService.putPorts(DID3, port(DID3, portno3, true));
316 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
317
318 // discovery should succeed
319 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
320 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
321
322 // add suppression rule for "deviceId: "of:0000000000000003""
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800323 deviceBlacklist.add(DID3);
324 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
325 DID3,
326 LinkDiscoveryFromDevice.class));
327
Naoki Shiota399a0b32015-11-15 20:36:13 -0600328
329 /// When Device is reconfigured with suppression:ON, Port also is same
330
331 // update device in stub DeviceService with suppression configured
332 deviceService.putDevice(device(DID3));
333 // update the Port in stub DeviceService. (Port has reference to Device)
334 deviceService.putPorts(DID3, port(DID3, portno3, true));
335 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
336
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800337 // discovery helper for device is expected to be gone or stopped
Naoki Shiota399a0b32015-11-15 20:36:13 -0600338 LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
339 if (linkDiscovery != null) {
340 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
341 }
342 }
343
344 /**
345 * Checks that discovery on reconfigured switch are properly restarted.
346 */
347 @Test
348 public void portSuppressedByDeviceTypeConfig() {
349
350 /// When Device is configured without suppression:OFF,
351 /// Port should be included for discovery
352
353 // add device in stub DeviceService without suppression configured
354 deviceService.putDevice(device(DID1, Device.Type.SWITCH));
355 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
356
357 // non-suppressed port added to suppressed device
358 final long portno3 = 3L;
359 deviceService.putPorts(DID1, port(DID1, portno3, true));
360 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, portno3, true)));
361
362 // add device in stub DeviceService with suppression configured
363 deviceService.putDevice(device(DID2, Device.Type.ROADM));
364 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
365
366 // non-suppressed port added to suppressed device
367 final long portno4 = 4L;
368 deviceService.putPorts(DID2, port(DID2, portno4, true));
369 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, portno4, true)));
370
371 // discovery should succeed for this device
372 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID1).isStopped());
373 assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID1).containsPort(portno3));
374
375 // discovery on device is expected to be stopped for this device
376 LinkDiscovery linkDiscovery = provider.discoverers.get(DID2);
377 if (linkDiscovery != null) {
378 assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
379 }
380 }
381
382 /**
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700383 * Checks that discovery on reconfigured port are properly restarted.
384 */
385 @Test
386 public void portSuppressedByPortConfig() {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600387
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700388 // add device in stub DeviceService without suppression configured
389 deviceService.putDevice(device(DID3));
390 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
391
392 // suppressed port added to non-suppressed device
393 final long portno3 = 3L;
394 final Port port3 = port(DID3, portno3, true,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800395 DefaultAnnotations.builder()
396 .set(LldpLinkProvider.NO_LLDP, "true")
397 .build());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700398 deviceService.putPorts(DID3, port3);
399 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
400
401 // discovery helper should be there turned on
402 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
403 assertFalse("Discoverer should not contain the port there",
404 provider.discoverers.get(DID3).containsPort(portno3));
405 }
406
407 @Test
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800408 public void portSuppressedByPortBlacklist() {
409
410 // add device in stub DeviceService without suppression configured
411 deviceService.putDevice(device(DID3));
412 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
413
414 final long portno3 = 3L;
415 final Port port3 = port(DID3, portno3, true);
416
417 final ConnectPoint cpDid3no3 = new ConnectPoint(DID3, PortNumber.portNumber(portno3));
418 portBlacklist.add(cpDid3no3);
419
420 // suppressed port added to non-suppressed device
421 deviceService.putPorts(DID3, port3);
422 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
423
424 configListener.event(new NetworkConfigEvent(Type.CONFIG_ADDED,
425 cpDid3no3,
426 LinkDiscoveryFromPort.class));
427
428 // discovery helper should be there turned on
429 assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
430 // but port is not a discovery target
431 assertFalse("Discoverer should not contain the port there",
432 provider.discoverers.get(DID3).containsPort(portno3));
433 }
434
435 @Test
alshabib0ed6a202014-10-19 12:42:57 -0700436 public void portUnknown() {
437 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700438 // Note: DID3 hasn't been added to TestDeviceService, but only port is added
439 deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));
alshabib0ed6a202014-10-19 12:42:57 -0700440
441
alshabibdfc7afb2014-10-21 20:13:27 -0700442 assertNull("DeviceId exists",
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700443 provider.discoverers.get(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700444 }
445
446 @Test
447 public void unknownPktCtx() {
448
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700449 // Note: DID3 hasn't been added to TestDeviceService
450 PacketContext pktCtx = new TestPacketContext(device(DID3));
alshabib0ed6a202014-10-19 12:42:57 -0700451
452 testProcessor.process(pktCtx);
453 assertFalse("Context should still be free", pktCtx.isHandled());
454 }
455
456 @Test
457 public void knownPktCtx() {
458 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
459 deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID2));
460 PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
461
462
463 testProcessor.process(pktCtx);
464
465 assertTrue("Link not detected", detectedLink(DID1, DID2));
466
467 }
468
469
470 @After
471 public void tearDown() {
472 provider.deactivate();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800473 provider.coreService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700474 provider.providerRegistry = null;
475 provider.deviceService = null;
Marc De Leenheer8b3e80b2015-03-06 14:27:03 -0800476 provider.packetService = null;
alshabib0ed6a202014-10-19 12:42:57 -0700477 }
478
479 private DeviceEvent deviceEvent(DeviceEvent.Type type, DeviceId did) {
480 return new DeviceEvent(type, deviceService.getDevice(did));
481
482 }
483
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700484 private DefaultDevice device(DeviceId did) {
485 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800486 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700487 }
488
Naoki Shiota399a0b32015-11-15 20:36:13 -0600489 private DefaultDevice device(DeviceId did, Device.Type type) {
490 return new DefaultDevice(ProviderId.NONE, did, type,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800491 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
Naoki Shiota399a0b32015-11-15 20:36:13 -0600492 }
493
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700494 private DefaultDevice device(DeviceId did, Annotations annotations) {
495 return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800496 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700497 }
498
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800499 @SuppressWarnings(value = {"unused"})
alshabib0ed6a202014-10-19 12:42:57 -0700500 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800501 return new DeviceEvent(type, deviceService.getDevice(did),
502 deviceService.getPort(did, port));
alshabib0ed6a202014-10-19 12:42:57 -0700503 }
504
505 private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, Port port) {
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800506 return new DeviceEvent(type, deviceService.getDevice(did), port);
alshabib0ed6a202014-10-19 12:42:57 -0700507 }
508
509 private Port port(DeviceId did, long port, boolean enabled) {
510 return new DefaultPort(deviceService.getDevice(did),
511 PortNumber.portNumber(port), enabled);
512 }
513
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700514 private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
515 return new DefaultPort(deviceService.getDevice(did),
516 PortNumber.portNumber(port), enabled, annotations);
517 }
alshabib0ed6a202014-10-19 12:42:57 -0700518
519 private boolean vanishedDpid(DeviceId... dids) {
520 for (int i = 0; i < dids.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800521 if (!providerService.vanishedDpid().contains(dids[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700522 return false;
523 }
524 }
525 return true;
526 }
527
528 private boolean vanishedPort(Long... ports) {
529 for (int i = 0; i < ports.length; i++) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800530 if (!providerService.vanishedPort().contains(ports[i])) {
alshabib0ed6a202014-10-19 12:42:57 -0700531 return false;
532 }
533 }
534 return true;
535 }
536
537 private boolean detectedLink(DeviceId src, DeviceId dst) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800538 for (DeviceId key : providerService.discoveredLinks().keySet()) {
alshabib0ed6a202014-10-19 12:42:57 -0700539 if (key.equals(src)) {
Ray Milkeycd6ab182016-02-03 11:13:09 -0800540 return providerService.discoveredLinks().get(src).equals(dst);
alshabib0ed6a202014-10-19 12:42:57 -0700541 }
542 }
543 return false;
544 }
545
Naoki Shiota399a0b32015-11-15 20:36:13 -0600546 @Test
547 public void addDeviceTypeRule() {
548 Device.Type deviceType1 = Device.Type.ROADM;
549 Device.Type deviceType2 = Device.Type.SWITCH;
550
551 Set<Device.Type> deviceTypes = new HashSet<>();
552 deviceTypes.add(deviceType1);
553
554 cfg.deviceTypes(deviceTypes);
555
556 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
557
558 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
559 assertFalse(provider.rules().getSuppressedDeviceType().contains(deviceType2));
560 }
561
562 @Test
563 public void updateDeviceTypeRule() {
564 Device.Type deviceType1 = Device.Type.ROADM;
565 Device.Type deviceType2 = Device.Type.SWITCH;
566 Set<Device.Type> deviceTypes = new HashSet<>();
567
568 deviceTypes.add(deviceType1);
569 cfg.deviceTypes(deviceTypes);
570
571 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
572
573 deviceTypes.add(deviceType2);
574 cfg.deviceTypes(deviceTypes);
575
576 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
577
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800578 assertAfter(EVENT_MS, () -> {
579 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType1));
580 assertTrue(provider.rules().getSuppressedDeviceType().contains(deviceType2));
581 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600582 }
583
584 @Test
585 public void addAnnotationRule() {
586 final String key1 = "key1", key2 = "key2";
587 final String value1 = "value1";
588
589 Map<String, String> annotation = new HashMap<>();
590 annotation.put(key1, value1);
591
592 cfg.annotation(annotation);
593
594 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
595
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800596 assertAfter(EVENT_MS, () -> {
597 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
598 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
599 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
600 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600601 }
602
603 @Test
604 public void updateAnnotationRule() {
605 final String key1 = "key1", key2 = "key2";
606 final String value1 = "value1", value2 = "value2";
607 Map<String, String> annotation = new HashMap<>();
608
609 annotation.put(key1, value1);
610 cfg.annotation(annotation);
611
612 configEvent(NetworkConfigEvent.Type.CONFIG_ADDED);
613
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800614 assertAfter(EVENT_MS, () -> {
615 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
616 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
617 assertFalse(provider.rules().getSuppressedAnnotation().containsKey(key2));
618 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600619
620 annotation.put(key2, value2);
621 cfg.annotation(annotation);
622
623 configEvent(NetworkConfigEvent.Type.CONFIG_UPDATED);
624
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800625 assertAfter(EVENT_MS, () -> {
626 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key1));
627 assertEquals(value1, provider.rules().getSuppressedAnnotation().get(key1));
628 assertTrue(provider.rules().getSuppressedAnnotation().containsKey(key2));
629 assertEquals(value2, provider.rules().getSuppressedAnnotation().get(key2));
630 });
Naoki Shiota399a0b32015-11-15 20:36:13 -0600631 }
632
633 private void configEvent(NetworkConfigEvent.Type evType) {
634 configListener.event(new NetworkConfigEvent(evType,
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800635 appId,
636 SuppressionConfig.class));
Naoki Shiota399a0b32015-11-15 20:36:13 -0600637 }
638
alshabib0ed6a202014-10-19 12:42:57 -0700639 private class TestPacketContext implements PacketContext {
640
641 protected Device device;
642 protected boolean blocked = false;
643
644 public TestPacketContext(Device dev) {
645 device = dev;
646 }
647
648 @Override
649 public long time() {
650 return 0;
651 }
652
653 @Override
654 public InboundPacket inPacket() {
Samuel Jero31e16f52018-09-21 10:34:28 -0400655 ONOSLLDP lldp = ONOSLLDP.onosSecureLLDP(deviceService.getDevice(DID1).id().toString(),
656 device.chassisId(),
657 (int) pd1.number().toLong(), "", "test");
alshabib0ed6a202014-10-19 12:42:57 -0700658
659 Ethernet ethPacket = new Ethernet();
660 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Charles Chan928ff8b2017-05-04 12:22:54 -0700661 ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
alshabib0ed6a202014-10-19 12:42:57 -0700662 ethPacket.setPayload(lldp);
663 ethPacket.setPad(true);
664
alshabib0ed6a202014-10-19 12:42:57 -0700665 ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
666
667 ConnectPoint cp = new ConnectPoint(device.id(), pd3.number());
668
669 return new DefaultInboundPacket(cp, ethPacket,
670 ByteBuffer.wrap(ethPacket.serialize()));
671
672 }
673
674 @Override
675 public OutboundPacket outPacket() {
676 return null;
677 }
678
679 @Override
680 public TrafficTreatment.Builder treatmentBuilder() {
681 return null;
682 }
683
684 @Override
685 public void send() {
686
687 }
688
689 @Override
690 public boolean block() {
691 blocked = true;
692 return blocked;
693 }
694
695 @Override
696 public boolean isHandled() {
697 return blocked;
698 }
699
700 }
701
Thomas Vachuska27bee092015-06-23 19:03:10 -0700702 private class TestPacketService extends PacketServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700703 @Override
704 public void addProcessor(PacketProcessor processor, int priority) {
705 testProcessor = processor;
706 }
alshabib0ed6a202014-10-19 12:42:57 -0700707 }
708
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800709 private class TestDeviceService extends DeviceServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700710
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700711 private final Map<DeviceId, Device> devices = new HashMap<>();
alshabib0ed6a202014-10-19 12:42:57 -0700712 private final ArrayListMultimap<DeviceId, Port> ports =
713 ArrayListMultimap.create();
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800714
alshabib0ed6a202014-10-19 12:42:57 -0700715 public TestDeviceService() {
716 Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
717 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
718 Device d2 = new DefaultDevice(ProviderId.NONE, DID2, Device.Type.SWITCH,
719 "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
720 devices.put(DID1, d1);
721 devices.put(DID2, d2);
alshabib0ed6a202014-10-19 12:42:57 -0700722 pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
723 pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
724 pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
725 pd4 = new DefaultPort(d2, PortNumber.portNumber(2), true);
726
727 ports.putAll(DID1, Lists.newArrayList(pd1, pd2));
728 ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
alshabib0ed6a202014-10-19 12:42:57 -0700729 }
730
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700731 private void putDevice(Device device) {
732 DeviceId deviceId = device.id();
733 devices.put(deviceId, device);
734 }
735
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800736 private void putPorts(DeviceId did, Port... ports) {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700737 this.ports.putAll(did, Lists.newArrayList(ports));
738 }
739
alshabib0ed6a202014-10-19 12:42:57 -0700740 @Override
741 public int getDeviceCount() {
742 return devices.values().size();
743 }
744
745 @Override
746 public Iterable<Device> getDevices() {
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -0700747 return ImmutableList.copyOf(devices.values());
alshabib0ed6a202014-10-19 12:42:57 -0700748 }
749
750 @Override
751 public Device getDevice(DeviceId deviceId) {
752 return devices.get(deviceId);
753 }
754
755 @Override
756 public MastershipRole getRole(DeviceId deviceId) {
757 return MastershipRole.MASTER;
758 }
759
760 @Override
761 public List<Port> getPorts(DeviceId deviceId) {
762 return ports.get(deviceId);
763 }
764
765 @Override
766 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
767 for (Port p : ports.get(deviceId)) {
768 if (p.number().equals(portNumber)) {
769 return p;
770 }
771 }
772 return null;
773 }
774
775 @Override
776 public boolean isAvailable(DeviceId deviceId) {
777 return true;
778 }
779
780 @Override
781 public void addListener(DeviceListener listener) {
782 deviceListener = listener;
783
784 }
785
786 @Override
787 public void removeListener(DeviceListener listener) {
788
789 }
790 }
791
Ray Milkeyeb130702018-06-21 15:19:33 -0700792 private final class TestMasterShipService extends MastershipServiceAdapter {
alshabib0ed6a202014-10-19 12:42:57 -0700793
794 @Override
795 public MastershipRole getLocalRole(DeviceId deviceId) {
796 return MastershipRole.MASTER;
797 }
798
799 @Override
Madan Jampanide003d92015-05-11 17:14:20 -0700800 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
801 return CompletableFuture.completedFuture(null);
alshabib0ed6a202014-10-19 12:42:57 -0700802 }
803
804 @Override
Ayaka Koshibeabedb092014-10-20 17:01:31 -0700805 public RoleInfo getNodesFor(DeviceId deviceId) {
806 return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700807 }
alshabib0ed6a202014-10-19 12:42:57 -0700808 }
809
810
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700811 private class TestLinkService extends LinkServiceAdapter {
812 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600813
814 private final class TestNetworkConfigRegistry
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800815 extends NetworkConfigRegistryAdapter {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800816 @SuppressWarnings("unchecked")
Naoki Shiota399a0b32015-11-15 20:36:13 -0600817 @Override
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800818 public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
819 if (configClass == SuppressionConfig.class) {
820 return (C) cfg;
821 } else if (configClass == LinkDiscoveryFromDevice.class) {
822 return (C) new LinkDiscoveryFromDevice() {
823 @Override
824 public boolean enabled() {
825 return !deviceBlacklist.contains(subj);
826 }
827 };
828 } else if (configClass == LinkDiscoveryFromPort.class) {
829 return (C) new LinkDiscoveryFromPort() {
830 @Override
831 public boolean enabled() {
832 return !portBlacklist.contains(subj);
833 }
834 };
835 } else {
836 return null;
837 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600838 }
839
840 @Override
841 public void addListener(NetworkConfigListener listener) {
842 configListener = listener;
843 }
844 }
845
846 private final class TestSuppressionConfig extends SuppressionConfig {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600847 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
848 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());
849
850 @Override
Naoki Shiota399a0b32015-11-15 20:36:13 -0600851 public Set<Device.Type> deviceTypes() {
852 return ImmutableSet.copyOf(deviceTypes);
853 }
854
855 @Override
856 public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
857 this.deviceTypes = ImmutableSet.copyOf(deviceTypes);
858 return this;
859 }
860
861 @Override
862 public Map<String, String> annotation() {
863 return ImmutableMap.copyOf(annotation);
864 }
865
866 @Override
867 public SuppressionConfig annotation(Map<String, String> annotation) {
868 this.annotation = ImmutableMap.copyOf(annotation);
869 return this;
870 }
871 }
alshabib0ed6a202014-10-19 12:42:57 -0700872}