blob: 811baac2d39cf57140565d0174740b9487118ef1 [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 Milkeyd9bbde82016-06-09 11:35:00 -070018import 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;
26
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 Milkeyd9bbde82016-06-09 11:35:00 -070073import 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;
78import com.google.common.util.concurrent.MoreExecutors;
Thomas Vachuska27bee092015-06-23 19:03:10 -070079
Naoki Shiota399a0b32015-11-15 20:36:13 -060080import static org.easymock.EasyMock.createMock;
81import static org.easymock.EasyMock.expect;
82import static org.easymock.EasyMock.replay;
Naoki Shiota399a0b32015-11-15 20:36:13 -060083import static org.junit.Assert.assertEquals;
Ray Milkeycd6ab182016-02-03 11:13:09 -080084import static org.junit.Assert.assertFalse;
85import static org.junit.Assert.assertNotNull;
86import static org.junit.Assert.assertNull;
Naoki Shiota399a0b32015-11-15 20:36:13 -060087import static org.junit.Assert.assertTrue;
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080088import static org.onlab.junit.TestTools.assertAfter;
Naoki Shiota399a0b32015-11-15 20:36:13 -060089import static org.onosproject.provider.lldp.impl.LldpLinkProvider.DEFAULT_RULES;
Naoki Shiota399a0b32015-11-15 20:36:13 -060090
alshabib0ed6a202014-10-19 12:42:57 -070091
Jonathan Hartb35540a2015-11-17 09:30:56 -080092public class LldpLinkProviderTest {
alshabib0ed6a202014-10-19 12:42:57 -070093
94 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
95 private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
HIGUCHI Yuta9a9edf82015-10-21 11:23:20 -070096 private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
Thomas Vachuskab5f6f522016-03-01 13:52:10 -080097 private static final int EVENT_MS = 500;
alshabib0ed6a202014-10-19 12:42:57 -070098
99 private static Port pd1;
100 private static Port pd2;
101 private static Port pd3;
102 private static Port pd4;
103
Jonathan Hartb35540a2015-11-17 09:30:56 -0800104 private final LldpLinkProvider provider = new LldpLinkProvider();
Ray Milkeycd6ab182016-02-03 11:13:09 -0800105 private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter();
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700106 private final TestLinkService linkService = new TestLinkService();
alshabib0ed6a202014-10-19 12:42:57 -0700107 private final TestPacketService packetService = new TestPacketService();
108 private final TestDeviceService deviceService = new TestDeviceService();
109 private final TestMasterShipService masterService = new TestMasterShipService();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600110 private final TestNetworkConfigRegistry configRegistry = new TestNetworkConfigRegistry();
alshabib0ed6a202014-10-19 12:42:57 -0700111
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800112 private CoreService coreService;
Ray Milkeycd6ab182016-02-03 11:13:09 -0800113 private LinkProviderServiceAdapter providerService;
alshabib0ed6a202014-10-19 12:42:57 -0700114
115 private PacketProcessor testProcessor;
116 private DeviceListener deviceListener;
Naoki Shiota399a0b32015-11-15 20:36:13 -0600117 private NetworkConfigListener configListener;
alshabib0ed6a202014-10-19 12:42:57 -0700118
Thomas Vachuska02aeb032015-01-06 22:36:30 -0800119 private ApplicationId appId =
120 new DefaultApplicationId(100, "org.onosproject.provider.lldp");
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800121
Naoki Shiota399a0b32015-11-15 20:36:13 -0600122 private TestSuppressionConfig cfg;
123
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800124 private Set<DeviceId> deviceBlacklist;
125
126 private Set<ConnectPoint> portBlacklist;
127
alshabib0ed6a202014-10-19 12:42:57 -0700128 @Before
129 public void setUp() {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800130 deviceBlacklist = new HashSet<>();
131 portBlacklist = new HashSet<>();
Naoki Shiota399a0b32015-11-15 20:36:13 -0600132 cfg = new TestSuppressionConfig();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800133 coreService = createMock(CoreService.class);
134 expect(coreService.registerApplication(appId.name()))
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800135 .andReturn(appId).anyTimes();
Pavlin Radoslavovd36a74b2015-01-09 11:59:07 -0800136 replay(coreService);
137
Thomas Vachuska6519e6f2015-03-11 02:29:31 -0700138 provider.cfgService = new ComponentConfigAdapter();
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() {
Ayaka Koshibe12c8c082015-12-08 12:48:46 -0800655 ONOSLLDP lldp = ONOSLLDP.onosLLDP(deviceService.getDevice(DID1).id().toString(),
656 device.chassisId(),
657 (int) pd1.number().toLong());
alshabib0ed6a202014-10-19 12:42:57 -0700658
659 Ethernet ethPacket = new Ethernet();
660 ethPacket.setEtherType(Ethernet.TYPE_LLDP);
Jonathan Hart7838c512016-06-07 15:18:22 -0700661 ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
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
792 private final class TestMasterShipService implements MastershipService {
793
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
Madan Jampanic6e574f2015-05-29 13:41:52 -0700805 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
806 return null;
alshabib0ed6a202014-10-19 12:42:57 -0700807 }
808
809 @Override
810 public NodeId getMasterFor(DeviceId deviceId) {
811 return null;
812 }
813
814 @Override
815 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
816 return null;
817 }
818
819 @Override
alshabib0ed6a202014-10-19 12:42:57 -0700820 public void addListener(MastershipListener listener) {
821
822 }
823
824 @Override
825 public void removeListener(MastershipListener listener) {
826
827 }
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700828
829 @Override
Ayaka Koshibeabedb092014-10-20 17:01:31 -0700830 public RoleInfo getNodesFor(DeviceId deviceId) {
831 return new RoleInfo(new NodeId("foo"), Collections.<NodeId>emptyList());
Yuta HIGUCHI376d7502014-10-19 15:57:52 -0700832 }
alshabib0ed6a202014-10-19 12:42:57 -0700833 }
834
835
Thomas Vachuskae4ebac92015-09-10 11:39:05 -0700836 private class TestLinkService extends LinkServiceAdapter {
837 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600838
839 private final class TestNetworkConfigRegistry
Thomas Vachuskab5f6f522016-03-01 13:52:10 -0800840 extends NetworkConfigRegistryAdapter {
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800841 @SuppressWarnings("unchecked")
Naoki Shiota399a0b32015-11-15 20:36:13 -0600842 @Override
HIGUCHI Yutad9fe3a32015-11-24 18:52:25 -0800843 public <S, C extends Config<S>> C getConfig(S subj, Class<C> configClass) {
844 if (configClass == SuppressionConfig.class) {
845 return (C) cfg;
846 } else if (configClass == LinkDiscoveryFromDevice.class) {
847 return (C) new LinkDiscoveryFromDevice() {
848 @Override
849 public boolean enabled() {
850 return !deviceBlacklist.contains(subj);
851 }
852 };
853 } else if (configClass == LinkDiscoveryFromPort.class) {
854 return (C) new LinkDiscoveryFromPort() {
855 @Override
856 public boolean enabled() {
857 return !portBlacklist.contains(subj);
858 }
859 };
860 } else {
861 return null;
862 }
Naoki Shiota399a0b32015-11-15 20:36:13 -0600863 }
864
865 @Override
866 public void addListener(NetworkConfigListener listener) {
867 configListener = listener;
868 }
869 }
870
871 private final class TestSuppressionConfig extends SuppressionConfig {
Naoki Shiota399a0b32015-11-15 20:36:13 -0600872 private Set<Device.Type> deviceTypes = new HashSet<>(DEFAULT_RULES.getSuppressedDeviceType());
873 private Map<String, String> annotation = new HashMap<>(DEFAULT_RULES.getSuppressedAnnotation());
874
875 @Override
Naoki Shiota399a0b32015-11-15 20:36:13 -0600876 public Set<Device.Type> deviceTypes() {
877 return ImmutableSet.copyOf(deviceTypes);
878 }
879
880 @Override
881 public SuppressionConfig deviceTypes(Set<Device.Type> deviceTypes) {
882 this.deviceTypes = ImmutableSet.copyOf(deviceTypes);
883 return this;
884 }
885
886 @Override
887 public Map<String, String> annotation() {
888 return ImmutableMap.copyOf(annotation);
889 }
890
891 @Override
892 public SuppressionConfig annotation(Map<String, String> annotation) {
893 this.annotation = ImmutableMap.copyOf(annotation);
894 return this;
895 }
896 }
alshabib0ed6a202014-10-19 12:42:57 -0700897}