blob: 2f0f82eeaef11d596e9cab1333469dc3537fce69 [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;
49import org.onosproject.net.flow.DefaultTrafficTreatment;
50import org.onosproject.net.flow.FlowRule;
51import org.onosproject.net.flow.FlowRuleEvent;
52import org.onosproject.net.flow.FlowRuleService;
53import org.onosproject.net.flow.criteria.Criteria;
54import org.onosproject.net.flowobjective.DefaultFilteringObjective;
55import org.onosproject.net.flowobjective.FilteringObjective;
56import org.onosproject.net.flowobjective.FlowObjectiveService;
57import org.onosproject.net.host.HostService;
58import org.onosproject.net.meter.MeterId;
59import org.onosproject.net.provider.ProviderId;
60import org.onosproject.store.service.TestStorageService;
61import org.opencord.sadis.BaseInformationService;
62import org.opencord.sadis.SadisService;
63import org.opencord.sadis.SubscriberAndDeviceInformation;
64import org.opencord.sadis.UniTagInformation;
65
66import java.util.Arrays;
67import java.util.HashSet;
68import java.util.LinkedList;
69import java.util.List;
70import java.util.Set;
71
72import static org.mockito.Matchers.any;
73import static org.mockito.Matchers.argThat;
74import static org.mockito.Matchers.eq;
75import static org.mockito.Mockito.doReturn;
76import static org.mockito.Mockito.never;
77import static org.mockito.Mockito.spy;
78import static org.mockito.Mockito.times;
79import static org.mockito.Mockito.verify;
80import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Matteo Scandolo2542e5d2021-12-01 16:53:41 -080081import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.ERROR;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070082import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.NONE;
83import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.ADDED;
84import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.PENDING_ADD;
Matteo Scandolo2542e5d2021-12-01 16:53:41 -080085import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.PENDING_REMOVE;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070086import static org.opencord.olt.impl.OltFlowService.OltFlowsStatus.REMOVED;
87import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_BP_ID_DEFAULT;
Matteo Scandolo97449bb2021-12-09 15:33:46 -080088import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_MCAST_SERVICE_NAME;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070089
90public class OltFlowServiceTest extends OltTestHelpers {
91
Matteo Scandolo97449bb2021-12-09 15:33:46 -080092 private OltFlowService component;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070093 private OltFlowService oltFlowService;
94 OltFlowService.InternalFlowListener internalFlowListener;
95 private final ApplicationId testAppId = new DefaultApplicationId(1, "org.opencord.olt.test");
96 private final short eapolDefaultVlan = 4091;
97
98 private final DeviceId deviceId = DeviceId.deviceId("test-device");
99 private final Device testDevice = new DefaultDevice(ProviderId.NONE, deviceId, Device.Type.OLT,
100 "testManufacturer", "1.0", "1.0", "SN", new ChassisId(1));
101 Port nniPort = new OltPort(testDevice, true, PortNumber.portNumber(1048576),
102 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
103 Port nniPortDisabled = new OltPort(testDevice, false, PortNumber.portNumber(1048576),
104 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
105 Port uniUpdateEnabled = new OltPort(testDevice, true, PortNumber.portNumber(16),
106 DefaultAnnotations.builder().set(PORT_NAME, "uni-1").build());
107
108 @Before
109 public void setUp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800110 component = new OltFlowService();
111 component.cfgService = new ComponentConfigAdapter();
112 component.sadisService = Mockito.mock(SadisService.class);
113 component.coreService = Mockito.spy(new CoreServiceAdapter());
114 component.oltMeterService = Mockito.mock(OltMeterService.class);
115 component.flowObjectiveService = Mockito.mock(FlowObjectiveService.class);
116 component.hostService = Mockito.mock(HostService.class);
117 component.flowRuleService = Mockito.mock(FlowRuleService.class);
118 component.storageService = new TestStorageService();
119 component.oltDeviceService = Mockito.mock(OltDeviceService.class);
120 component.appId = testAppId;
121 component.deviceService = Mockito.mock(DeviceService.class);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700122
123 doReturn(Mockito.mock(BaseInformationService.class))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800124 .when(component.sadisService).getSubscriberInfoService();
125 doReturn(testAppId).when(component.coreService).registerApplication("org.opencord.olt");
126 component.activate(null);
127 component.bindSadisService(component.sadisService);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700128
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800129 internalFlowListener = spy(component.internalFlowListener);
130
131 oltFlowService = spy(component);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700132 }
133
134 @After
135 public void tearDown() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800136 component.deactivate(null);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700137 }
138
139 @Test
140 public void testUpdateConnectPointStatus() {
141
142 DeviceId deviceId = DeviceId.deviceId("test-device");
143 ProviderId pid = new ProviderId("of", "foo");
144 Device device =
145 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
146 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
147 DefaultAnnotations.builder().set(PORT_NAME, "port-1").build());
148 Port port2 = new DefaultPort(device, PortNumber.portNumber(2), true,
149 DefaultAnnotations.builder().set(PORT_NAME, "port-2").build());
150 Port port3 = new DefaultPort(device, PortNumber.portNumber(3), true,
151 DefaultAnnotations.builder().set(PORT_NAME, "port-3").build());
152
153 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
154 ServiceKey sk2 = new ServiceKey(new AccessDevicePort(port2), new UniTagInformation());
155 ServiceKey sk3 = new ServiceKey(new AccessDevicePort(port3), new UniTagInformation());
156
157 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800158 component.cpStatus = component.storageService.
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700159 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
yasin sapli0823c932022-01-26 11:26:09 +0000160 OltPortStatus cp1Status = new OltPortStatus(PENDING_ADD, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800161 component.cpStatus.put(sk1, cp1Status);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700162
163 //check that we only update the provided value
yasin sapli0823c932022-01-26 11:26:09 +0000164 component.updateConnectPointStatus(sk1, ADDED, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800165 OltPortStatus updated = component.cpStatus.get(sk1);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700166 Assert.assertEquals(ADDED, updated.defaultEapolStatus);
167 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
168 Assert.assertEquals(NONE, updated.dhcpStatus);
169
170 // check that it creates an entry if it does not exist
yasin sapli0823c932022-01-26 11:26:09 +0000171 component.updateConnectPointStatus(sk2, PENDING_ADD, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800172 Assert.assertNotNull(component.cpStatus.get(sk2));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700173
174 // check that if we create a new entry with null values they're converted to NONE
yasin sapli0823c932022-01-26 11:26:09 +0000175 component.updateConnectPointStatus(sk3, null, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800176 updated = component.cpStatus.get(sk3);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700177 Assert.assertEquals(NONE, updated.defaultEapolStatus);
178 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
179 Assert.assertEquals(NONE, updated.dhcpStatus);
180 }
181
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800182 /**
183 * If the flow status is PENDING_REMOVE or ERROR and there is no
184 * previous state in the map that don't update it.
185 * In case of a device disconnection we immediately wipe out the status,
186 * but then flows might update the cpStatus map. That result
187 */
188 @Test
189 public void doNotUpdateConnectPointStatus() {
190 DeviceId deviceId = DeviceId.deviceId("test-device");
191 ProviderId pid = new ProviderId("of", "foo");
192 Device device =
193 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
194 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
195 DefaultAnnotations.builder().set(PORT_NAME, "port-1").build());
196
197 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
198
199 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800200 component.cpStatus = component.storageService.
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800201 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
202
203 // check that an entry is not created if the only status is pending remove
yasin sapli0823c932022-01-26 11:26:09 +0000204 component.updateConnectPointStatus(sk1, null, null, PENDING_REMOVE, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800205 OltPortStatus entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800206 Assert.assertNull(entry);
207
208 // check that an entry is not created if the only status is ERROR
yasin sapli0823c932022-01-26 11:26:09 +0000209 component.updateConnectPointStatus(sk1, null, null, ERROR, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800210 entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800211 Assert.assertNull(entry);
212 }
213
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700214 @Test
215 public void testHasDefaultEapol() {
216 DeviceId deviceId = DeviceId.deviceId("test-device");
217 ProviderId pid = new ProviderId("of", "foo");
218
219 Device device =
220 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
221
222 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
223 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
224 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800225 component.defaultEapolUniTag);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700226
227 Port port17 = new DefaultPort(device, PortNumber.portNumber(17), true,
228 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
229
230 OltPortStatus portStatusAdded = new OltPortStatus(
231 OltFlowService.OltFlowsStatus.ADDED,
232 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000233 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700234 null
235 );
236
237 OltPortStatus portStatusRemoved = new OltPortStatus(
238 REMOVED,
239 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000240 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700241 null
242 );
243
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800244 component.cpStatus.put(skWithStatus, portStatusAdded);
245 Assert.assertTrue(component.hasDefaultEapol(port));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700246
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800247 component.cpStatus.put(skWithStatus, portStatusRemoved);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700248
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800249 Assert.assertFalse(component.hasDefaultEapol(port17));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700250 }
251
252 @Test
253 public void testHasSubscriberFlows() {
254 // TODO test with multiple services
255 DeviceId deviceId = DeviceId.deviceId("test-device");
256 ProviderId pid = new ProviderId("of", "foo");
257
258 Device device =
259 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
260
261 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
262 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
263
264 UniTagInformation uti = new UniTagInformation.Builder().setServiceName("test").build();
265 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
266 uti);
267
268 OltPortStatus withDefaultEapol = new OltPortStatus(
269 ADDED,
270 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000271 NONE,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700272 NONE
273 );
274
275 OltPortStatus withDhcp = new OltPortStatus(
276 REMOVED,
277 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000278 ADDED,
279 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700280 );
281
282 OltPortStatus withSubFlow = new OltPortStatus(
283 REMOVED,
284 ADDED,
yasin sapli0823c932022-01-26 11:26:09 +0000285 ADDED,
286 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700287 );
288
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800289 component.cpStatus.put(skWithStatus, withDefaultEapol);
290 Assert.assertFalse(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700291
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800292 component.cpStatus.put(skWithStatus, withDhcp);
293 Assert.assertTrue(component.hasDhcpFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700294
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800295 component.cpStatus.put(skWithStatus, withSubFlow);
296 Assert.assertTrue(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700297 }
298
299 @Test
300 public void testHandleBasicPortFlowsNoEapol() throws Exception {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800301 component.enableEapol = false;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700302 // create empty service for testing
303 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
304 UniTagInformation empty = new UniTagInformation.Builder().build();
305 uniTagInformationList.add(empty);
306
307 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
308 si.setUniTagList(uniTagInformationList);
309
310 final DiscoveredSubscriber addedSub =
311 new DiscoveredSubscriber(testDevice,
312 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
313 false, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800314 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700315 // if eapol is not enabled there's nothing we need to do,
316 // so make sure we don't even call sadis
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800317 verify(component.subsService, never()).get(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700318 }
319
320 @Test
321 public void testHandleBasicPortFlowsWithEapolNoMeter() throws Exception {
322 // create empty service for testing
323 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
324 UniTagInformation empty = new UniTagInformation.Builder().build();
325 uniTagInformationList.add(empty);
326 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
327 si.setUniTagList(uniTagInformationList);
328 final DiscoveredSubscriber addedSub =
329 new DiscoveredSubscriber(testDevice,
330 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
331 false, si);
332 // whether the meter is pending or not is up to the createMeter method to handle
333 // we just don't proceed with the subscriber till it's ready
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800334 doReturn(false).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700335 .createMeter(addedSub.device.id(), DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800336 boolean res = component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700337
338 Assert.assertFalse(res);
339
340 // we do not create flows
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800341 verify(component.flowObjectiveService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700342 .filter(eq(addedSub.device.id()), any());
343 }
344
345 @Test
346 public void testHandleBasicPortFlowsWithEapolAddedMeter() throws Exception {
347 // create empty service for testing
348 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
349 UniTagInformation empty = new UniTagInformation.Builder().build();
350 uniTagInformationList.add(empty);
351 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
352 si.setUniTagList(uniTagInformationList);
353 final DiscoveredSubscriber addedSub =
354 new DiscoveredSubscriber(testDevice,
355 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
356 false, si);
357 // this is the happy case, we have the meter so we check that the default EAPOL flow
358 // is installed
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800359 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700360 .createMeter(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800361 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700362 .hasMeterByBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800363 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700364 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
365
366 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
367 .permit()
368 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
369 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
370 .fromApp(testAppId)
371 .withPriority(10000)
372 .withMeta(
373 DefaultTrafficTreatment.builder()
374 .meter(MeterId.meterId(1))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800375 .writeMetadata(component.createTechProfValueForWriteMetadata(
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700376 VlanId.vlanId(eapolDefaultVlan),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800377 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700378 .setOutput(PortNumber.CONTROLLER)
379 .pushVlan()
380 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
381 )
382 .add();
383
384
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800385 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700386
387 // we check for an existing meter (present)
388 // FIXME understand why the above test invokes this call and this one doesn't
389// verify(oltFlowService.oltMeterService, times(1))
390// .hasMeterByBandwidthProfile(eq(addedSub.device.id()), eq(DEFAULT_BP_ID_DEFAULT));
391
392 // the meter exist, no need to check for PENDING or to create it
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800393 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700394 .hasPendingMeterByBandwidthProfile(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800395 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700396 .createMeterForBp(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
397
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800398 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700399 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
400 }
401
402 @Test
403 public void testHandleBasicPortFlowsRemovedSub() throws Exception {
404 // create empty service for testing
405 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
406 UniTagInformation empty = new UniTagInformation.Builder().build();
407 uniTagInformationList.add(empty);
408 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
409 si.setUniTagList(uniTagInformationList);
410 final DiscoveredSubscriber removedSub =
411 new DiscoveredSubscriber(testDevice,
412 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
413 false, si);
414 // we are testing that when a port goes down we remove the default EAPOL flow
415
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800416 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700417 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
418
419 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
420 .deny()
421 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
422 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
423 .fromApp(testAppId)
424 .withPriority(10000)
425 .withMeta(
426 DefaultTrafficTreatment.builder()
427 .meter(MeterId.meterId(1))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800428 .writeMetadata(component.createTechProfValueForWriteMetadata(
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700429 VlanId.vlanId(eapolDefaultVlan),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800430 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700431 .setOutput(PortNumber.CONTROLLER)
432 .pushVlan()
433 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
434 )
435 .add();
436
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800437 component.handleBasicPortFlows(removedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700438
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800439 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700440 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
441 }
442
443 @Test
444 public void testHandleNniFlowsOnlyLldp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800445 component.enableDhcpOnNni = false;
446 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700447
448 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
449 .permit()
450 .withKey(Criteria.matchInPort(nniPort.number()))
451 .addCondition(Criteria.matchEthType(EthType.EtherType.LLDP.ethType()))
452 .fromApp(testAppId)
453 .withPriority(10000)
454 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
455 .add();
456
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800457 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700458 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800459 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700460 .filter(eq(deviceId), any());
461 }
462
463 @Test
464 public void testHandleNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800465 component.enableDhcpOnNni = true;
466 component.enableDhcpV4 = true;
467 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700468
469 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
470 .permit()
471 .withKey(Criteria.matchInPort(nniPort.number()))
472 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
473 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
474 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
475 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
476 .fromApp(testAppId)
477 .withPriority(10000)
478 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
479 .add();
480
481 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800482 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700483 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
484 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800485 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700486 .filter(eq(deviceId), any());
487 }
488
489 @Test
490 public void testRemoveNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800491 component.enableDhcpOnNni = true;
492 component.enableDhcpV4 = true;
493 component.handleNniFlows(testDevice, nniPortDisabled, OltFlowService.FlowOperation.REMOVE);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700494
495 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
496 .deny()
497 .withKey(Criteria.matchInPort(nniPort.number()))
498 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
499 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
500 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
501 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
502 .fromApp(testAppId)
503 .withPriority(10000)
504 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
505 .add();
506
507 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800508 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700509 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
510 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800511 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700512 .filter(eq(deviceId), any());
513 }
514
515 @Test
516 public void testHandleNniFlowsDhcpV6() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800517 component.enableDhcpOnNni = true;
518 component.enableDhcpV4 = false;
519 component.enableDhcpV6 = true;
520 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700521
522 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
523 .permit()
524 .withKey(Criteria.matchInPort(nniPort.number()))
525 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV6.ethType()))
526 .addCondition(Criteria.matchIPProtocol(IPv6.PROTOCOL_UDP))
527 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(546)))
528 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(547)))
529 .fromApp(testAppId)
530 .withPriority(10000)
531 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
532 .add();
533
534 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800535 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700536 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
537 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800538 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700539 .filter(eq(deviceId), any());
540 }
541
542 @Test
543 public void testHandleNniFlowsIgmp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800544 component.enableDhcpOnNni = false;
545 component.enableIgmpOnNni = true;
546 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700547
548 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
549 .permit()
550 .withKey(Criteria.matchInPort(nniPort.number()))
551 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
552 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
553 .fromApp(testAppId)
554 .withPriority(10000)
555 .add();
556
557 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800558 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700559 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
560 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800561 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700562 .filter(eq(deviceId), any());
563 }
564
565 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000566 public void testHandleNniFlowsPppoe() {
567 component.enablePppoeOnNni = true;
568 component.enablePppoe = true;
569 component.handleNniFlows(testDevice, nniPort, OltFlowService.FlowOperation.ADD);
570
571 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
572 .permit()
573 .withKey(Criteria.matchInPort(nniPort.number()))
574 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
575 .fromApp(testAppId)
576 .withPriority(10000)
577 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
578 .add();
579
580 // invoked with the correct Pppoe filtering objective
581 verify(component.flowObjectiveService, times(1))
582 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
583 // invoked only twice, LLDP and DHCP
584 verify(component.flowObjectiveService, times(2))
585 .filter(eq(deviceId), any());
586 }
587
588 @Test
589 public void testRemoveNniFlowsPppoe() {
590 component.enablePppoeOnNni = true;
591 component.enablePppoe = true;
592 component.handleNniFlows(testDevice, nniPortDisabled, OltFlowService.FlowOperation.REMOVE);
593
594 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
595 .deny()
596 .withKey(Criteria.matchInPort(nniPort.number()))
597 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
598 .fromApp(testAppId)
599 .withPriority(10000)
600 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
601 .add();
602
603 // invoked with the correct Pppoe filtering objective
604 verify(component.flowObjectiveService, times(1))
605 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
606 // invoked only twice, LLDP and DHCP
607 verify(component.flowObjectiveService, times(2))
608 .filter(eq(deviceId), any());
609 }
610
611 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700612 public void testMacAddressNotRequired() {
613 // create a single service that doesn't require mac address
614 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
615 UniTagInformation hsia = new UniTagInformation.Builder()
616 .setEnableMacLearning(false)
617 .build();
618 uniTagInformationList.add(hsia);
619 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
620 si.setUniTagList(uniTagInformationList);
621
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800622 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700623 // we return true as we don't care wether it's available or not
624 Assert.assertTrue(isMacAvailable);
625 }
626
627 @Test
628 public void testIsMacAddressAvailableViaMacLearning() {
629
630 // create a single service that requires macLearning to be enabled
631 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
632 VlanId hsiaCtag = VlanId.vlanId((short) 11);
633 UniTagInformation hsia = new UniTagInformation.Builder()
634 .setPonCTag(hsiaCtag)
635 .setEnableMacLearning(true).build();
636 uniTagInformationList.add(hsia);
637
638 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
639 si.setUniTagList(uniTagInformationList);
640
641 // with no hosts discovered, return false
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800642 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700643 Assert.assertFalse(isMacAvailable);
644
645 // with a discovered host, return true
646 Host fakeHost = new DefaultHost(ProviderId.NONE, HostId.hostId(MacAddress.NONE), MacAddress.ZERO,
647 hsiaCtag, HostLocation.NONE, new HashSet<>(), DefaultAnnotations.builder().build());
648 Set<Host> hosts = new HashSet<>(Arrays.asList(fakeHost));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800649 doReturn(hosts).when(component.hostService).getConnectedHosts((ConnectPoint) any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700650
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800651 isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700652 Assert.assertTrue(isMacAvailable);
653 }
654
655 @Test
656 public void testIsMacAddressAvailableViaConfiguration() {
657 // create a single service that has a macAddress configured
658 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
659 UniTagInformation hsia = new UniTagInformation.Builder()
660 .setConfiguredMacAddress("2e:0a:00:01:00:00")
661 .build();
662 uniTagInformationList.add(hsia);
663 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
664 si.setUniTagList(uniTagInformationList);
665
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800666 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700667 Assert.assertTrue(isMacAvailable);
668 }
669
670 @Test
671 public void testHandleSubscriberDhcpFlowsAdd() {
672
673 String usBp = "usBp";
674 String usOltBp = "usOltBp";
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800675 component.enableDhcpV4 = true;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700676
677 // create two services, one requires DHCP the other doesn't
678 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
679 VlanId hsiaCtag = VlanId.vlanId((short) 11);
680 UniTagInformation hsia = new UniTagInformation.Builder()
681 .setPonCTag(hsiaCtag)
682 .setTechnologyProfileId(64)
683 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
684 .setUpstreamBandwidthProfile(usBp)
685 .setUpstreamOltBandwidthProfile(usOltBp)
686 .setIsDhcpRequired(true).build();
687 UniTagInformation mc = new UniTagInformation.Builder()
688 .setIsDhcpRequired(false).build();
689 uniTagInformationList.add(hsia);
690 uniTagInformationList.add(mc);
691
692 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
693 si.setUniTagList(uniTagInformationList);
694
695 final DiscoveredSubscriber addedSub =
696 new DiscoveredSubscriber(testDevice,
697 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
698 false, si);
699
700 // return meter IDs
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800701 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700702 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800703 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700704 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
705
706 // TODO improve the matches on the filter
707 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
708 .permit()
709 .withKey(Criteria.matchInPort(addedSub.port.number()))
710 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
711 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
712 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
713 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
714 .fromApp(testAppId)
715 .withPriority(10000)
716 .add();
717
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800718 component.handleSubscriberDhcpFlows(addedSub.device.id(), addedSub.port,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700719 OltFlowService.FlowOperation.ADD, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800720 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700721 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
722 }
723
724 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000725 public void testHandleSubscriberPppoeFlowsAdd() {
726
727 String usBp = "usBp";
728 String usOltBp = "usOltBp";
729 component.enablePppoe = true;
730
731 // create two services, one requires Pppoe the other doesn't
732 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
733 VlanId hsiaCtag = VlanId.vlanId((short) 11);
734 UniTagInformation hsia = new UniTagInformation.Builder()
735 .setPonCTag(hsiaCtag)
736 .setTechnologyProfileId(64)
737 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
738 .setUpstreamBandwidthProfile(usBp)
739 .setUpstreamOltBandwidthProfile(usOltBp)
740 .setIsPppoeRequired(true).build();
741 UniTagInformation mc = new UniTagInformation.Builder()
742 .setIsPppoeRequired(false).build();
743 uniTagInformationList.add(hsia);
744 uniTagInformationList.add(mc);
745
746 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
747 si.setUniTagList(uniTagInformationList);
748
749 final DiscoveredSubscriber addedSub =
750 new DiscoveredSubscriber(testDevice,
751 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
752 false, si);
753
754 // return meter IDs
755 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
756 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
757 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
758 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
759
760 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
761 .permit()
762 .withKey(Criteria.matchInPort(addedSub.port.number()))
763 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
764 .fromApp(testAppId)
765 .withPriority(10000)
766 .add();
767
768 component.handleSubscriberPppoeFlows(addedSub.device.id(), addedSub.port,
769 OltFlowService.FlowOperation.ADD, si);
770 verify(component.flowObjectiveService, times(1))
771 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
772 }
773
774 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700775 public void testInternalFlowListenerNotMaster() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800776 doReturn(false).when(component.oltDeviceService).isLocalLeader(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700777
778 FlowRule flowRule = DefaultFlowRule.builder()
779 .forDevice(DeviceId.deviceId("foo"))
780 .fromApp(testAppId)
781 .makePermanent()
782 .withPriority(1000)
783 .build();
784 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
785 flowRule);
786
787 internalFlowListener.event(event);
788
789 // if we're not master of the device, we should not update
790 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
791 }
792
793 @Test
794 public void testInternalFlowListenerDifferentApp() {
795 ApplicationId someAppId = new DefaultApplicationId(1, "org.opencord.olt.not-test");
796 FlowRule flowRule = DefaultFlowRule.builder()
797 .forDevice(DeviceId.deviceId("foo"))
798 .fromApp(someAppId)
799 .makePermanent()
800 .withPriority(1000)
801 .build();
802 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
803 flowRule);
804
805 internalFlowListener.event(event);
806
807 // if we're not master of the device, we should not update
808 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
809 }
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800810
811 @Test
812 public void testRemoveSubscriberFlows() {
813 // test that if we have EAPOL we wait till the tagged flow is removed
814 // before installing the default one
815
816 // setup
817 component.enableEapol = true;
818
819 // mock data
820 DeviceId deviceId = DeviceId.deviceId("test-device");
821 ProviderId pid = new ProviderId("of", "foo");
822 Device device =
823 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
824 Port port = new DefaultPort(device, PortNumber.portNumber(1), true,
825 DefaultAnnotations.builder().set(PORT_NAME, "port-1").build());
826
827 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
828 UniTagInformation hsia = new UniTagInformation.Builder()
829 .setUpstreamBandwidthProfile("usbp")
830 .setDownstreamBandwidthProfile("dsbp")
831 .setPonCTag(VlanId.vlanId((short) 900)).build();
832 uniTagInformationList.add(hsia);
833 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
834 si.setUniTagList(uniTagInformationList);
835
836 DiscoveredSubscriber sub = new DiscoveredSubscriber(
837 device, port, DiscoveredSubscriber.Status.REMOVED, true, si);
838
839 // first test that when we remove the EAPOL flow we return false so that the
840 // subscriber is not removed from the queue
841 doReturn(true).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any());
842 boolean res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
843 verify(oltFlowService, times(1))
844 .handleSubscriberDhcpFlows(deviceId, port, OltFlowService.FlowOperation.REMOVE, si);
845 verify(oltFlowService, times(1))
846 .handleSubscriberEapolFlows(sub, OltFlowService.FlowOperation.REMOVE, si);
847 verify(oltFlowService, times(1))
848 .handleSubscriberDataFlows(device, port, OltFlowService.FlowOperation.REMOVE,
849 si, DEFAULT_MCAST_SERVICE_NAME);
850 verify(oltFlowService, times(1))
851 .handleSubscriberIgmpFlows(sub, OltFlowService.FlowOperation.REMOVE);
852 verify(oltFlowService, never())
853 .handleEapolFlow(any(), any(), any(),
854 eq(OltFlowService.FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
855 Assert.assertFalse(res);
856
857 // then test that if the tagged EAPOL is not there we install the default EAPOL
858 // and return true so we remove the subscriber from the queue
859 doReturn(false).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any());
860 doReturn(port).when(oltFlowService.deviceService).getPort(deviceId, port.number());
861 res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
862 verify(oltFlowService, times(1))
863 .handleEapolFlow(any(), any(), any(),
864 eq(OltFlowService.FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
865 Assert.assertTrue(res);
866 }
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700867}