blob: baa880d68ff7926471a5776e2ddce11145bed90d [file] [log] [blame]
Matteo Scandoloaa2adde2021-09-13 12:45:32 -07001/*
2 * Copyright 2021-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.opencord.olt.impl;
18
19import org.junit.After;
20import org.junit.Assert;
21import org.junit.Before;
22import org.junit.Test;
23import org.mockito.Mockito;
24import org.onlab.packet.ChassisId;
25import org.onlab.packet.EthType;
26import org.onlab.packet.IPv4;
27import org.onlab.packet.IPv6;
28import org.onlab.packet.MacAddress;
29import org.onlab.packet.TpPort;
30import org.onlab.packet.VlanId;
31import org.onosproject.cfg.ComponentConfigAdapter;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreServiceAdapter;
34import org.onosproject.core.DefaultApplicationId;
35import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.DefaultAnnotations;
37import org.onosproject.net.DefaultDevice;
38import org.onosproject.net.DefaultHost;
39import org.onosproject.net.DefaultPort;
40import org.onosproject.net.Device;
41import org.onosproject.net.DeviceId;
42import org.onosproject.net.Host;
43import org.onosproject.net.HostId;
44import org.onosproject.net.HostLocation;
45import org.onosproject.net.Port;
46import org.onosproject.net.PortNumber;
Matteo Scandolo97449bb2021-12-09 15:33:46 -080047import org.onosproject.net.device.DeviceService;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070048import org.onosproject.net.flow.DefaultFlowRule;
Andrea Campanella40d2b342022-02-04 18:13:37 +010049import org.onosproject.net.flow.DefaultTrafficSelector;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070050import org.onosproject.net.flow.DefaultTrafficTreatment;
51import org.onosproject.net.flow.FlowRule;
52import org.onosproject.net.flow.FlowRuleEvent;
53import org.onosproject.net.flow.FlowRuleService;
Andrea Campanella40d2b342022-02-04 18:13:37 +010054import org.onosproject.net.flow.TrafficSelector;
55import org.onosproject.net.flow.TrafficTreatment;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070056import org.onosproject.net.flow.criteria.Criteria;
57import org.onosproject.net.flowobjective.DefaultFilteringObjective;
58import org.onosproject.net.flowobjective.FilteringObjective;
59import org.onosproject.net.flowobjective.FlowObjectiveService;
60import org.onosproject.net.host.HostService;
61import org.onosproject.net.meter.MeterId;
62import org.onosproject.net.provider.ProviderId;
63import org.onosproject.store.service.TestStorageService;
64import org.opencord.sadis.BaseInformationService;
65import org.opencord.sadis.SadisService;
66import org.opencord.sadis.SubscriberAndDeviceInformation;
67import org.opencord.sadis.UniTagInformation;
68
69import java.util.Arrays;
70import java.util.HashSet;
71import java.util.LinkedList;
72import java.util.List;
73import java.util.Set;
Andrea Campanella40d2b342022-02-04 18:13:37 +010074import java.util.concurrent.TimeUnit;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070075
76import static org.mockito.Matchers.any;
77import static org.mockito.Matchers.argThat;
78import static org.mockito.Matchers.eq;
79import static org.mockito.Mockito.doReturn;
80import static org.mockito.Mockito.never;
81import static org.mockito.Mockito.spy;
82import static org.mockito.Mockito.times;
83import static org.mockito.Mockito.verify;
84import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Matteo Scandolo2542e5d2021-12-01 16:53:41 -080085import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.ERROR;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070086import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.NONE;
87import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.ADDED;
88import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.PENDING_ADD;
Matteo Scandolo2542e5d2021-12-01 16:53:41 -080089import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.PENDING_REMOVE;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070090import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.REMOVED;
91import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_BP_ID_DEFAULT;
Matteo Scandolo97449bb2021-12-09 15:33:46 -080092import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_MCAST_SERVICE_NAME;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070093
94public class OltFlowServiceTest extends OltTestHelpers {
95
Andrea Campanella40d2b342022-02-04 18:13:37 +010096 public static final String PORT_1 = "port-1";
97 public static final String PORT_2 = "port-2";
98 public static final String PORT_3 = "port-3";
Matteo Scandolo97449bb2021-12-09 15:33:46 -080099 private OltFlowService component;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700100 private OltFlowService oltFlowService;
101 OltFlowService.InternalFlowListener internalFlowListener;
102 private final ApplicationId testAppId = new DefaultApplicationId(1, "org.opencord.olt.test");
103 private final short eapolDefaultVlan = 4091;
104
105 private final DeviceId deviceId = DeviceId.deviceId("test-device");
106 private final Device testDevice = new DefaultDevice(ProviderId.NONE, deviceId, Device.Type.OLT,
107 "testManufacturer", "1.0", "1.0", "SN", new ChassisId(1));
108 Port nniPort = new OltPort(testDevice, true, PortNumber.portNumber(1048576),
109 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
110 Port nniPortDisabled = new OltPort(testDevice, false, PortNumber.portNumber(1048576),
111 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
112 Port uniUpdateEnabled = new OltPort(testDevice, true, PortNumber.portNumber(16),
113 DefaultAnnotations.builder().set(PORT_NAME, "uni-1").build());
114
115 @Before
116 public void setUp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800117 component = new OltFlowService();
118 component.cfgService = new ComponentConfigAdapter();
119 component.sadisService = Mockito.mock(SadisService.class);
120 component.coreService = Mockito.spy(new CoreServiceAdapter());
121 component.oltMeterService = Mockito.mock(OltMeterService.class);
122 component.flowObjectiveService = Mockito.mock(FlowObjectiveService.class);
123 component.hostService = Mockito.mock(HostService.class);
124 component.flowRuleService = Mockito.mock(FlowRuleService.class);
125 component.storageService = new TestStorageService();
126 component.oltDeviceService = Mockito.mock(OltDeviceService.class);
127 component.appId = testAppId;
128 component.deviceService = Mockito.mock(DeviceService.class);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700129
130 doReturn(Mockito.mock(BaseInformationService.class))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800131 .when(component.sadisService).getSubscriberInfoService();
132 doReturn(testAppId).when(component.coreService).registerApplication("org.opencord.olt");
133 component.activate(null);
134 component.bindSadisService(component.sadisService);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700135
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800136 internalFlowListener = spy(component.internalFlowListener);
137
138 oltFlowService = spy(component);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700139 }
140
141 @After
142 public void tearDown() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800143 component.deactivate(null);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700144 }
145
146 @Test
147 public void testUpdateConnectPointStatus() {
148
149 DeviceId deviceId = DeviceId.deviceId("test-device");
150 ProviderId pid = new ProviderId("of", "foo");
151 Device device =
152 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
153 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100154 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700155 Port port2 = new DefaultPort(device, PortNumber.portNumber(2), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100156 DefaultAnnotations.builder().set(PORT_NAME, PORT_2).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700157 Port port3 = new DefaultPort(device, PortNumber.portNumber(3), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100158 DefaultAnnotations.builder().set(PORT_NAME, PORT_3).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700159
160 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
161 ServiceKey sk2 = new ServiceKey(new AccessDevicePort(port2), new UniTagInformation());
162 ServiceKey sk3 = new ServiceKey(new AccessDevicePort(port3), new UniTagInformation());
163
164 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800165 component.cpStatus = component.storageService.
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700166 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
Andrea Campanella87241ae2022-03-11 11:20:24 +0100167 OltPortStatus cp1Status = new OltPortStatus(PENDING_ADD, NONE, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800168 component.cpStatus.put(sk1, cp1Status);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700169
170 //check that we only update the provided value
Andrea Campanella87241ae2022-03-11 11:20:24 +0100171 component.updateConnectPointStatus(sk1, ADDED, null, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800172 OltPortStatus updated = component.cpStatus.get(sk1);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700173 Assert.assertEquals(ADDED, updated.defaultEapolStatus);
174 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
175 Assert.assertEquals(NONE, updated.dhcpStatus);
176
177 // check that it creates an entry if it does not exist
Andrea Campanella87241ae2022-03-11 11:20:24 +0100178 component.updateConnectPointStatus(sk2, PENDING_ADD, NONE, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800179 Assert.assertNotNull(component.cpStatus.get(sk2));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700180
181 // check that if we create a new entry with null values they're converted to NONE
Andrea Campanella87241ae2022-03-11 11:20:24 +0100182 component.updateConnectPointStatus(sk3, null, null, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800183 updated = component.cpStatus.get(sk3);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700184 Assert.assertEquals(NONE, updated.defaultEapolStatus);
185 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
186 Assert.assertEquals(NONE, updated.dhcpStatus);
187 }
188
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800189 /**
190 * If the flow status is PENDING_REMOVE or ERROR and there is no
191 * previous state in the map that don't update it.
192 * In case of a device disconnection we immediately wipe out the status,
193 * but then flows might update the cpStatus map. That result
194 */
195 @Test
196 public void doNotUpdateConnectPointStatus() {
197 DeviceId deviceId = DeviceId.deviceId("test-device");
198 ProviderId pid = new ProviderId("of", "foo");
199 Device device =
200 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
201 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100202 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800203
204 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
205
206 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800207 component.cpStatus = component.storageService.
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800208 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
209
210 // check that an entry is not created if the only status is pending remove
Andrea Campanella87241ae2022-03-11 11:20:24 +0100211 component.updateConnectPointStatus(sk1, null, null, null, PENDING_REMOVE, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800212 OltPortStatus entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800213 Assert.assertNull(entry);
214
215 // check that an entry is not created if the only status is ERROR
Andrea Campanella87241ae2022-03-11 11:20:24 +0100216 component.updateConnectPointStatus(sk1, null, null, null, ERROR, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800217 entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800218 Assert.assertNull(entry);
219 }
220
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700221 @Test
222 public void testHasDefaultEapol() {
223 DeviceId deviceId = DeviceId.deviceId("test-device");
224 ProviderId pid = new ProviderId("of", "foo");
225
226 Device device =
227 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
228
229 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
230 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
231 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800232 component.defaultEapolUniTag);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700233
234 Port port17 = new DefaultPort(device, PortNumber.portNumber(17), true,
235 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
236
237 OltPortStatus portStatusAdded = new OltPortStatus(
238 OltFlowService.OltFlowsStatus.ADDED,
239 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000240 null,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100241 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700242 null
243 );
244
245 OltPortStatus portStatusRemoved = new OltPortStatus(
246 REMOVED,
247 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000248 null,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100249 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700250 null
251 );
252
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800253 component.cpStatus.put(skWithStatus, portStatusAdded);
254 Assert.assertTrue(component.hasDefaultEapol(port));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700255
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800256 component.cpStatus.put(skWithStatus, portStatusRemoved);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700257
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800258 Assert.assertFalse(component.hasDefaultEapol(port17));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700259 }
260
261 @Test
262 public void testHasSubscriberFlows() {
263 // TODO test with multiple services
264 DeviceId deviceId = DeviceId.deviceId("test-device");
265 ProviderId pid = new ProviderId("of", "foo");
266
267 Device device =
268 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
269
270 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
271 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
272
273 UniTagInformation uti = new UniTagInformation.Builder().setServiceName("test").build();
274 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
275 uti);
276
277 OltPortStatus withDefaultEapol = new OltPortStatus(
278 ADDED,
279 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000280 NONE,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100281 NONE,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700282 NONE
283 );
284
285 OltPortStatus withDhcp = new OltPortStatus(
286 REMOVED,
287 NONE,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100288 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000289 ADDED,
290 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700291 );
292
293 OltPortStatus withSubFlow = new OltPortStatus(
294 REMOVED,
295 ADDED,
yasin sapli0823c932022-01-26 11:26:09 +0000296 ADDED,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100297 ADDED,
yasin sapli0823c932022-01-26 11:26:09 +0000298 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700299 );
300
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800301 component.cpStatus.put(skWithStatus, withDefaultEapol);
302 Assert.assertFalse(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700303
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800304 component.cpStatus.put(skWithStatus, withDhcp);
305 Assert.assertTrue(component.hasDhcpFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700306
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800307 component.cpStatus.put(skWithStatus, withSubFlow);
308 Assert.assertTrue(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700309 }
310
311 @Test
312 public void testHandleBasicPortFlowsNoEapol() throws Exception {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800313 component.enableEapol = false;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700314 // create empty service for testing
315 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
316 UniTagInformation empty = new UniTagInformation.Builder().build();
317 uniTagInformationList.add(empty);
318
319 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
320 si.setUniTagList(uniTagInformationList);
321
322 final DiscoveredSubscriber addedSub =
323 new DiscoveredSubscriber(testDevice,
324 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
325 false, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800326 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700327 // if eapol is not enabled there's nothing we need to do,
328 // so make sure we don't even call sadis
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800329 verify(component.subsService, never()).get(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700330 }
331
332 @Test
333 public void testHandleBasicPortFlowsWithEapolNoMeter() throws Exception {
334 // create empty service for testing
335 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
336 UniTagInformation empty = new UniTagInformation.Builder().build();
337 uniTagInformationList.add(empty);
338 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
339 si.setUniTagList(uniTagInformationList);
340 final DiscoveredSubscriber addedSub =
341 new DiscoveredSubscriber(testDevice,
342 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
343 false, si);
344 // whether the meter is pending or not is up to the createMeter method to handle
345 // we just don't proceed with the subscriber till it's ready
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800346 doReturn(false).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700347 .createMeter(addedSub.device.id(), DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800348 boolean res = component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700349
350 Assert.assertFalse(res);
351
352 // we do not create flows
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800353 verify(component.flowObjectiveService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700354 .filter(eq(addedSub.device.id()), any());
355 }
356
357 @Test
358 public void testHandleBasicPortFlowsWithEapolAddedMeter() throws Exception {
359 // create empty service for testing
360 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
361 UniTagInformation empty = new UniTagInformation.Builder().build();
362 uniTagInformationList.add(empty);
363 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
364 si.setUniTagList(uniTagInformationList);
365 final DiscoveredSubscriber addedSub =
366 new DiscoveredSubscriber(testDevice,
367 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
368 false, si);
369 // this is the happy case, we have the meter so we check that the default EAPOL flow
370 // is installed
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800371 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700372 .createMeter(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800373 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700374 .hasMeterByBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800375 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700376 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
377
378 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
379 .permit()
380 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
381 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
382 .fromApp(testAppId)
383 .withPriority(10000)
384 .withMeta(
385 DefaultTrafficTreatment.builder()
386 .meter(MeterId.meterId(1))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800387 .writeMetadata(component.createTechProfValueForWriteMetadata(
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700388 VlanId.vlanId(eapolDefaultVlan),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800389 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700390 .setOutput(PortNumber.CONTROLLER)
391 .pushVlan()
392 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
393 )
394 .add();
395
396
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800397 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700398
399 // we check for an existing meter (present)
400 // FIXME understand why the above test invokes this call and this one doesn't
401// verify(oltFlowService.oltMeterService, times(1))
402// .hasMeterByBandwidthProfile(eq(addedSub.device.id()), eq(DEFAULT_BP_ID_DEFAULT));
403
404 // the meter exist, no need to check for PENDING or to create it
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800405 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700406 .hasPendingMeterByBandwidthProfile(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800407 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700408 .createMeterForBp(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
409
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800410 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700411 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
412 }
413
414 @Test
415 public void testHandleBasicPortFlowsRemovedSub() throws Exception {
416 // create empty service for testing
417 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
418 UniTagInformation empty = new UniTagInformation.Builder().build();
419 uniTagInformationList.add(empty);
420 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
421 si.setUniTagList(uniTagInformationList);
422 final DiscoveredSubscriber removedSub =
423 new DiscoveredSubscriber(testDevice,
424 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
425 false, si);
426 // we are testing that when a port goes down we remove the default EAPOL flow
427
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800428 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700429 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
430
431 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
432 .deny()
433 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
434 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
435 .fromApp(testAppId)
436 .withPriority(10000)
437 .withMeta(
438 DefaultTrafficTreatment.builder()
439 .meter(MeterId.meterId(1))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800440 .writeMetadata(component.createTechProfValueForWriteMetadata(
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700441 VlanId.vlanId(eapolDefaultVlan),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800442 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700443 .setOutput(PortNumber.CONTROLLER)
444 .pushVlan()
445 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
446 )
447 .add();
448
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800449 component.handleBasicPortFlows(removedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700450
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800451 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700452 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
453 }
454
455 @Test
456 public void testHandleNniFlowsOnlyLldp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800457 component.enableDhcpOnNni = false;
458 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700459
460 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
461 .permit()
462 .withKey(Criteria.matchInPort(nniPort.number()))
463 .addCondition(Criteria.matchEthType(EthType.EtherType.LLDP.ethType()))
464 .fromApp(testAppId)
465 .withPriority(10000)
466 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
467 .add();
468
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800469 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700470 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800471 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700472 .filter(eq(deviceId), any());
473 }
474
475 @Test
476 public void testHandleNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800477 component.enableDhcpOnNni = true;
478 component.enableDhcpV4 = true;
479 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700480
481 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
482 .permit()
483 .withKey(Criteria.matchInPort(nniPort.number()))
484 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
485 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
486 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
487 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
488 .fromApp(testAppId)
489 .withPriority(10000)
490 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
491 .add();
492
493 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800494 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700495 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
496 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800497 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700498 .filter(eq(deviceId), any());
499 }
500
501 @Test
502 public void testRemoveNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800503 component.enableDhcpOnNni = true;
504 component.enableDhcpV4 = true;
505 component.handleNniFlows(testDevice, nniPortDisabled, OltFlowService.FlowOperation.REMOVE);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700506
507 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
508 .deny()
509 .withKey(Criteria.matchInPort(nniPort.number()))
510 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
511 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
512 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
513 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
514 .fromApp(testAppId)
515 .withPriority(10000)
516 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
517 .add();
518
519 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800520 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700521 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
522 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800523 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700524 .filter(eq(deviceId), any());
525 }
526
527 @Test
528 public void testHandleNniFlowsDhcpV6() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800529 component.enableDhcpOnNni = true;
530 component.enableDhcpV4 = false;
531 component.enableDhcpV6 = true;
532 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700533
534 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
535 .permit()
536 .withKey(Criteria.matchInPort(nniPort.number()))
537 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV6.ethType()))
538 .addCondition(Criteria.matchIPProtocol(IPv6.PROTOCOL_UDP))
539 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(546)))
540 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(547)))
541 .fromApp(testAppId)
542 .withPriority(10000)
543 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
544 .add();
545
546 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800547 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700548 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
549 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800550 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700551 .filter(eq(deviceId), any());
552 }
553
554 @Test
555 public void testHandleNniFlowsIgmp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800556 component.enableDhcpOnNni = false;
557 component.enableIgmpOnNni = true;
558 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700559
560 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
561 .permit()
562 .withKey(Criteria.matchInPort(nniPort.number()))
563 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
564 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
565 .fromApp(testAppId)
566 .withPriority(10000)
567 .add();
568
569 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800570 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700571 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
572 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800573 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700574 .filter(eq(deviceId), any());
575 }
576
577 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000578 public void testHandleNniFlowsPppoe() {
579 component.enablePppoeOnNni = true;
580 component.enablePppoe = true;
581 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
582
583 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
584 .permit()
585 .withKey(Criteria.matchInPort(nniPort.number()))
586 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
587 .fromApp(testAppId)
588 .withPriority(10000)
589 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
590 .add();
591
592 // invoked with the correct Pppoe filtering objective
593 verify(component.flowObjectiveService, times(1))
594 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
595 // invoked only twice, LLDP and DHCP
596 verify(component.flowObjectiveService, times(2))
597 .filter(eq(deviceId), any());
598 }
599
600 @Test
601 public void testRemoveNniFlowsPppoe() {
602 component.enablePppoeOnNni = true;
603 component.enablePppoe = true;
604 component.handleNniFlows(testDevice, nniPortDisabled, OltFlowService.FlowOperation.REMOVE);
605
606 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
607 .deny()
608 .withKey(Criteria.matchInPort(nniPort.number()))
609 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
610 .fromApp(testAppId)
611 .withPriority(10000)
612 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
613 .add();
614
615 // invoked with the correct Pppoe filtering objective
616 verify(component.flowObjectiveService, times(1))
617 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
618 // invoked only twice, LLDP and DHCP
619 verify(component.flowObjectiveService, times(2))
620 .filter(eq(deviceId), any());
621 }
622
623 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700624 public void testMacAddressNotRequired() {
625 // create a single service that doesn't require mac address
626 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
627 UniTagInformation hsia = new UniTagInformation.Builder()
628 .setEnableMacLearning(false)
629 .build();
630 uniTagInformationList.add(hsia);
631 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
632 si.setUniTagList(uniTagInformationList);
633
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800634 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700635 // we return true as we don't care wether it's available or not
636 Assert.assertTrue(isMacAvailable);
637 }
638
639 @Test
640 public void testIsMacAddressAvailableViaMacLearning() {
641
642 // create a single service that requires macLearning to be enabled
643 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
644 VlanId hsiaCtag = VlanId.vlanId((short) 11);
645 UniTagInformation hsia = new UniTagInformation.Builder()
646 .setPonCTag(hsiaCtag)
647 .setEnableMacLearning(true).build();
648 uniTagInformationList.add(hsia);
649
650 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
651 si.setUniTagList(uniTagInformationList);
652
653 // with no hosts discovered, return false
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800654 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700655 Assert.assertFalse(isMacAvailable);
656
657 // with a discovered host, return true
658 Host fakeHost = new DefaultHost(ProviderId.NONE, HostId.hostId(MacAddress.NONE), MacAddress.ZERO,
659 hsiaCtag, HostLocation.NONE, new HashSet<>(), DefaultAnnotations.builder().build());
660 Set<Host> hosts = new HashSet<>(Arrays.asList(fakeHost));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800661 doReturn(hosts).when(component.hostService).getConnectedHosts((ConnectPoint) any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700662
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800663 isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700664 Assert.assertTrue(isMacAvailable);
665 }
666
667 @Test
668 public void testIsMacAddressAvailableViaConfiguration() {
669 // create a single service that has a macAddress configured
670 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
671 UniTagInformation hsia = new UniTagInformation.Builder()
672 .setConfiguredMacAddress("2e:0a:00:01:00:00")
673 .build();
674 uniTagInformationList.add(hsia);
675 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
676 si.setUniTagList(uniTagInformationList);
677
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800678 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700679 Assert.assertTrue(isMacAvailable);
680 }
681
682 @Test
683 public void testHandleSubscriberDhcpFlowsAdd() {
684
685 String usBp = "usBp";
686 String usOltBp = "usOltBp";
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800687 component.enableDhcpV4 = true;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700688
689 // create two services, one requires DHCP the other doesn't
690 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
691 VlanId hsiaCtag = VlanId.vlanId((short) 11);
692 UniTagInformation hsia = new UniTagInformation.Builder()
693 .setPonCTag(hsiaCtag)
694 .setTechnologyProfileId(64)
695 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
696 .setUpstreamBandwidthProfile(usBp)
697 .setUpstreamOltBandwidthProfile(usOltBp)
698 .setIsDhcpRequired(true).build();
699 UniTagInformation mc = new UniTagInformation.Builder()
700 .setIsDhcpRequired(false).build();
701 uniTagInformationList.add(hsia);
702 uniTagInformationList.add(mc);
703
704 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
705 si.setUniTagList(uniTagInformationList);
706
707 final DiscoveredSubscriber addedSub =
708 new DiscoveredSubscriber(testDevice,
709 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
710 false, si);
711
712 // return meter IDs
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800713 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700714 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800715 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700716 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
717
718 // TODO improve the matches on the filter
719 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
720 .permit()
721 .withKey(Criteria.matchInPort(addedSub.port.number()))
722 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
723 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
724 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
725 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
726 .fromApp(testAppId)
727 .withPriority(10000)
728 .add();
729
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800730 component.handleSubscriberDhcpFlows(addedSub.device.id(), addedSub.port,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700731 OltFlowService.FlowOperation.ADD, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800732 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700733 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
734 }
735
736 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000737 public void testHandleSubscriberPppoeFlowsAdd() {
738
739 String usBp = "usBp";
740 String usOltBp = "usOltBp";
741 component.enablePppoe = true;
742
743 // create two services, one requires Pppoe the other doesn't
744 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
745 VlanId hsiaCtag = VlanId.vlanId((short) 11);
746 UniTagInformation hsia = new UniTagInformation.Builder()
747 .setPonCTag(hsiaCtag)
748 .setTechnologyProfileId(64)
749 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
750 .setUpstreamBandwidthProfile(usBp)
751 .setUpstreamOltBandwidthProfile(usOltBp)
752 .setIsPppoeRequired(true).build();
753 UniTagInformation mc = new UniTagInformation.Builder()
754 .setIsPppoeRequired(false).build();
755 uniTagInformationList.add(hsia);
756 uniTagInformationList.add(mc);
757
758 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
759 si.setUniTagList(uniTagInformationList);
760
761 final DiscoveredSubscriber addedSub =
762 new DiscoveredSubscriber(testDevice,
763 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
764 false, si);
765
766 // return meter IDs
767 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
768 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
769 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
770 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
771
772 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
773 .permit()
774 .withKey(Criteria.matchInPort(addedSub.port.number()))
775 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
776 .fromApp(testAppId)
777 .withPriority(10000)
778 .add();
779
780 component.handleSubscriberPppoeFlows(addedSub.device.id(), addedSub.port,
781 OltFlowService.FlowOperation.ADD, si);
782 verify(component.flowObjectiveService, times(1))
783 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
784 }
785
786 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700787 public void testInternalFlowListenerNotMaster() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800788 doReturn(false).when(component.oltDeviceService).isLocalLeader(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700789
790 FlowRule flowRule = DefaultFlowRule.builder()
791 .forDevice(DeviceId.deviceId("foo"))
792 .fromApp(testAppId)
793 .makePermanent()
794 .withPriority(1000)
795 .build();
796 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
797 flowRule);
798
799 internalFlowListener.event(event);
800
801 // if we're not master of the device, we should not update
802 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
803 }
804
805 @Test
806 public void testInternalFlowListenerDifferentApp() {
807 ApplicationId someAppId = new DefaultApplicationId(1, "org.opencord.olt.not-test");
808 FlowRule flowRule = DefaultFlowRule.builder()
809 .forDevice(DeviceId.deviceId("foo"))
810 .fromApp(someAppId)
811 .makePermanent()
812 .withPriority(1000)
813 .build();
814 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
815 flowRule);
816
817 internalFlowListener.event(event);
818
819 // if we're not master of the device, we should not update
820 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
821 }
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800822
823 @Test
824 public void testRemoveSubscriberFlows() {
825 // test that if we have EAPOL we wait till the tagged flow is removed
826 // before installing the default one
827
828 // setup
829 component.enableEapol = true;
830
831 // mock data
832 DeviceId deviceId = DeviceId.deviceId("test-device");
833 ProviderId pid = new ProviderId("of", "foo");
834 Device device =
835 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
836 Port port = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100837 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800838
839 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
840 UniTagInformation hsia = new UniTagInformation.Builder()
841 .setUpstreamBandwidthProfile("usbp")
842 .setDownstreamBandwidthProfile("dsbp")
843 .setPonCTag(VlanId.vlanId((short) 900)).build();
844 uniTagInformationList.add(hsia);
845 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
846 si.setUniTagList(uniTagInformationList);
847
848 DiscoveredSubscriber sub = new DiscoveredSubscriber(
849 device, port, DiscoveredSubscriber.Status.REMOVED, true, si);
850
851 // first test that when we remove the EAPOL flow we return false so that the
852 // subscriber is not removed from the queue
Andrea Campanella87241ae2022-03-11 11:20:24 +0100853 doReturn(true).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any(), eq(true));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800854 boolean res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
855 verify(oltFlowService, times(1))
856 .handleSubscriberDhcpFlows(deviceId, port, OltFlowService.FlowOperation.REMOVE, si);
857 verify(oltFlowService, times(1))
858 .handleSubscriberEapolFlows(sub, OltFlowService.FlowOperation.REMOVE, si);
859 verify(oltFlowService, times(1))
860 .handleSubscriberDataFlows(device, port, OltFlowService.FlowOperation.REMOVE,
861 si, DEFAULT_MCAST_SERVICE_NAME);
862 verify(oltFlowService, times(1))
863 .handleSubscriberIgmpFlows(sub, OltFlowService.FlowOperation.REMOVE);
864 verify(oltFlowService, never())
865 .handleEapolFlow(any(), any(), any(),
866 eq(OltFlowService.FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
867 Assert.assertFalse(res);
868
869 // then test that if the tagged EAPOL is not there we install the default EAPOL
870 // and return true so we remove the subscriber from the queue
Andrea Campanella87241ae2022-03-11 11:20:24 +0100871 doReturn(false).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any(), eq(true));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800872 doReturn(port).when(oltFlowService.deviceService).getPort(deviceId, port.number());
873 res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
874 verify(oltFlowService, times(1))
875 .handleEapolFlow(any(), any(), any(),
876 eq(OltFlowService.FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
877 Assert.assertTrue(res);
878 }
Andrea Campanella40d2b342022-02-04 18:13:37 +0100879
880 @Test
881 public void testRemovedFlowEvent() throws InterruptedException {
882 // test that we update the status in case of REMOVED flow even with non
883 // existing port in the onos device manager
884
885 DeviceId deviceId = DeviceId.deviceId("test-device");
886 ProviderId pid = new ProviderId("of", "foo");
887 Device device =
888 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
889
890 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
891 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
892 // create empty service for testing
893 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
894 UniTagInformation vlanUniTag = new UniTagInformation.Builder().setPonCTag(VlanId.vlanId((short) 60))
895 .build();
896 uniTagInformationList.add(vlanUniTag);
897 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
898 si.setUniTagList(uniTagInformationList);
899 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), vlanUniTag);
900
901 TrafficSelector selector = DefaultTrafficSelector.builder()
902 .matchInPort(port1.number())
903 .matchVlanId(VlanId.vlanId((short) 60))
904 .build();
905
906 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
907 .immediate()
908 .setOutput(port1.number())
909 .build();
910
911 FlowRule flowRule = DefaultFlowRule.builder()
912 .makePermanent()
913 .withPriority(1000)
914 .forTable(0)
915 .forDevice(deviceId)
916 .fromApp(testAppId)
917 .withSelector(selector)
918 .withTreatment(treatment)
919 .build();
920
921 // cpStatus map for the test
922 component.cpStatus = component.storageService.
923 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
Andrea Campanella87241ae2022-03-11 11:20:24 +0100924 OltPortStatus cp1Status = new OltPortStatus(NONE, NONE, PENDING_REMOVE, NONE, NONE);
Andrea Campanella40d2b342022-02-04 18:13:37 +0100925 component.cpStatus.put(sk1, cp1Status);
926
927 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVED, flowRule);
928 doReturn(true).when(component.oltDeviceService).isLocalLeader(any());
929 doReturn(device).when(component.deviceService).getDevice(deviceId);
930 doReturn(si).when(component.subsService).get(PORT_1);
931
932 oltFlowService.internalFlowListener.event(event);
933
934 //Some time to finish the operation
935 TimeUnit.MILLISECONDS.sleep(200);
936
937 OltPortStatus status = component.cpStatus.get(sk1);
938 Assert.assertEquals(REMOVED, status.subscriberFlowsStatus);
939 }
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700940}