blob: a93ac8df4300135e11f4506bf2f439bc2b6457c5 [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;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +053058import org.onosproject.net.flowobjective.DefaultForwardingObjective;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070059import org.onosproject.net.flowobjective.FilteringObjective;
60import org.onosproject.net.flowobjective.FlowObjectiveService;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +053061import org.onosproject.net.flowobjective.ForwardingObjective;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070062import org.onosproject.net.host.HostService;
63import org.onosproject.net.meter.MeterId;
64import org.onosproject.net.provider.ProviderId;
65import org.onosproject.store.service.TestStorageService;
Gustavo Silva29fb20e2022-05-26 09:59:54 -030066import org.opencord.olt.AccessDevicePort;
67import org.opencord.olt.DiscoveredSubscriber;
68import org.opencord.olt.OltPortStatus;
69import org.opencord.olt.ServiceKey;
70import org.opencord.olt.FlowOperation;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +053071import org.opencord.olt.impl.fttb.FttbUtils;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070072import org.opencord.sadis.BaseInformationService;
73import org.opencord.sadis.SadisService;
74import org.opencord.sadis.SubscriberAndDeviceInformation;
75import org.opencord.sadis.UniTagInformation;
76
77import java.util.Arrays;
78import java.util.HashSet;
79import java.util.LinkedList;
80import java.util.List;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +053081import java.util.Map;
82import java.util.Optional;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070083import java.util.Set;
Andrea Campanella40d2b342022-02-04 18:13:37 +010084import java.util.concurrent.TimeUnit;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070085
86import static org.mockito.Matchers.any;
87import static org.mockito.Matchers.argThat;
88import static org.mockito.Matchers.eq;
89import static org.mockito.Mockito.doReturn;
90import static org.mockito.Mockito.never;
91import static org.mockito.Mockito.spy;
92import static org.mockito.Mockito.times;
93import static org.mockito.Mockito.verify;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +053094import static org.mockito.Mockito.when;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -070095import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Gustavo Silva29fb20e2022-05-26 09:59:54 -030096import static org.opencord.olt.OltFlowsStatus.ERROR;
97import static org.opencord.olt.OltFlowsStatus.NONE;
98import static org.opencord.olt.OltFlowsStatus.ADDED;
99import static org.opencord.olt.OltFlowsStatus.PENDING_ADD;
100import static org.opencord.olt.OltFlowsStatus.PENDING_REMOVE;
101import static org.opencord.olt.OltFlowsStatus.REMOVED;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700102import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_BP_ID_DEFAULT;
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800103import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_MCAST_SERVICE_NAME;
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530104import static org.opencord.olt.impl.OsgiPropertyConstants.DEFAULT_MCAST_SERVICE_NAME_DEFAULT;
105import static org.opencord.olt.impl.OsgiPropertyConstants.DOWNSTREAM_OLT;
106import static org.opencord.olt.impl.OsgiPropertyConstants.DOWNSTREAM_ONU;
107import static org.opencord.olt.impl.OsgiPropertyConstants.UPSTREAM_OLT;
108import static org.opencord.olt.impl.OsgiPropertyConstants.UPSTREAM_ONU;
109import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_DIRECTION;
110import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_DOWNSTREAM;
111import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_UPSTREAM;
112import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_SERVICE_NAME;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700113
114public class OltFlowServiceTest extends OltTestHelpers {
115
Andrea Campanella40d2b342022-02-04 18:13:37 +0100116 public static final String PORT_1 = "port-1";
117 public static final String PORT_2 = "port-2";
118 public static final String PORT_3 = "port-3";
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800119 private OltFlowService component;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700120 private OltFlowService oltFlowService;
Andrea Campanella34ce61a2022-04-28 18:55:46 +0200121
122 private DeviceService deviceService;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700123 OltFlowService.InternalFlowListener internalFlowListener;
124 private final ApplicationId testAppId = new DefaultApplicationId(1, "org.opencord.olt.test");
125 private final short eapolDefaultVlan = 4091;
126
127 private final DeviceId deviceId = DeviceId.deviceId("test-device");
128 private final Device testDevice = new DefaultDevice(ProviderId.NONE, deviceId, Device.Type.OLT,
129 "testManufacturer", "1.0", "1.0", "SN", new ChassisId(1));
130 Port nniPort = new OltPort(testDevice, true, PortNumber.portNumber(1048576),
131 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
132 Port nniPortDisabled = new OltPort(testDevice, false, PortNumber.portNumber(1048576),
133 DefaultAnnotations.builder().set(PORT_NAME, "nni-1").build());
134 Port uniUpdateEnabled = new OltPort(testDevice, true, PortNumber.portNumber(16),
135 DefaultAnnotations.builder().set(PORT_NAME, "uni-1").build());
136
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530137 private final UniTagInformation dpuMgmtUti = new UniTagInformation.Builder()
138 .setPonCTag(VlanId.vlanId("6"))
139 .setPonSTag(VlanId.vlanId("60"))
140 .setUsPonCTagPriority(1)
141 .setUsPonSTagPriority(2)
142 .setTechnologyProfileId(64)
143 .setUpstreamBandwidthProfile("usBp")
144 .setUpstreamOltBandwidthProfile("usOltBp")
145 .setServiceName(FttbUtils.FTTB_SERVICE_DPU_MGMT_TRAFFIC)
146 .setIsDhcpRequired(true)
147 .setEnableMacLearning(true)
148 .build();
149
150 private final UniTagInformation ancpUti = new UniTagInformation.Builder()
151 .setPonCTag(VlanId.vlanId("4"))
152 .setPonSTag(VlanId.vlanId("40"))
153 .setUsPonCTagPriority(3)
154 .setUsPonSTagPriority(4)
155 .setTechnologyProfileId(64)
156 .setUpstreamBandwidthProfile("usBp")
157 .setUpstreamOltBandwidthProfile("usOltBp")
158 .setServiceName(FttbUtils.FTTB_SERVICE_DPU_ANCP_TRAFFIC)
159 .setIsDhcpRequired(false)
160 .build();
161
162 private final UniTagInformation fttbSubscriberUti = new UniTagInformation.Builder()
163 .setPonCTag(VlanId.vlanId("8"))
164 .setPonSTag(VlanId.vlanId("80"))
165 .setTechnologyProfileId(64)
166 .setUpstreamBandwidthProfile("usBp")
167 .setUpstreamOltBandwidthProfile("usOltBp")
168 .setServiceName(FttbUtils.FTTB_SERVICE_SUBSCRIBER_TRAFFIC)
169 .setIsDhcpRequired(false)
170 .build();
171
172
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700173 @Before
174 public void setUp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800175 component = new OltFlowService();
176 component.cfgService = new ComponentConfigAdapter();
177 component.sadisService = Mockito.mock(SadisService.class);
178 component.coreService = Mockito.spy(new CoreServiceAdapter());
179 component.oltMeterService = Mockito.mock(OltMeterService.class);
180 component.flowObjectiveService = Mockito.mock(FlowObjectiveService.class);
181 component.hostService = Mockito.mock(HostService.class);
182 component.flowRuleService = Mockito.mock(FlowRuleService.class);
183 component.storageService = new TestStorageService();
184 component.oltDeviceService = Mockito.mock(OltDeviceService.class);
185 component.appId = testAppId;
186 component.deviceService = Mockito.mock(DeviceService.class);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700187
188 doReturn(Mockito.mock(BaseInformationService.class))
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800189 .when(component.sadisService).getSubscriberInfoService();
190 doReturn(testAppId).when(component.coreService).registerApplication("org.opencord.olt");
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530191 doReturn(testDevice).when(component.deviceService).getDevice(testDevice.id());
192 when(component.sadisService.getSubscriberInfoService().get(testDevice.serialNumber())).
193 thenReturn(Mockito.mock(SubscriberAndDeviceInformation.class));
194 when(component.oltDeviceService.getNniPort(testDevice)).thenReturn(Optional.of(nniPort));
195
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800196 component.activate(null);
197 component.bindSadisService(component.sadisService);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700198
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800199 internalFlowListener = spy(component.internalFlowListener);
200
201 oltFlowService = spy(component);
Andrea Campanella34ce61a2022-04-28 18:55:46 +0200202 deviceService = Mockito.mock(DeviceService.class);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700203 }
204
205 @After
206 public void tearDown() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800207 component.deactivate(null);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700208 }
209
210 @Test
211 public void testUpdateConnectPointStatus() {
212
213 DeviceId deviceId = DeviceId.deviceId("test-device");
214 ProviderId pid = new ProviderId("of", "foo");
215 Device device =
216 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
217 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100218 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700219 Port port2 = new DefaultPort(device, PortNumber.portNumber(2), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100220 DefaultAnnotations.builder().set(PORT_NAME, PORT_2).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700221 Port port3 = new DefaultPort(device, PortNumber.portNumber(3), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100222 DefaultAnnotations.builder().set(PORT_NAME, PORT_3).build());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700223
224 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
225 ServiceKey sk2 = new ServiceKey(new AccessDevicePort(port2), new UniTagInformation());
226 ServiceKey sk3 = new ServiceKey(new AccessDevicePort(port3), new UniTagInformation());
227
228 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800229 component.cpStatus = component.storageService.
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700230 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
Andrea Campanella87241ae2022-03-11 11:20:24 +0100231 OltPortStatus cp1Status = new OltPortStatus(PENDING_ADD, NONE, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800232 component.cpStatus.put(sk1, cp1Status);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700233
234 //check that we only update the provided value
Andrea Campanella87241ae2022-03-11 11:20:24 +0100235 component.updateConnectPointStatus(sk1, ADDED, null, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800236 OltPortStatus updated = component.cpStatus.get(sk1);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700237 Assert.assertEquals(ADDED, updated.defaultEapolStatus);
238 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
239 Assert.assertEquals(NONE, updated.dhcpStatus);
240
241 // check that it creates an entry if it does not exist
Andrea Campanella87241ae2022-03-11 11:20:24 +0100242 component.updateConnectPointStatus(sk2, PENDING_ADD, NONE, NONE, NONE, NONE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800243 Assert.assertNotNull(component.cpStatus.get(sk2));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700244
245 // check that if we create a new entry with null values they're converted to NONE
Andrea Campanella87241ae2022-03-11 11:20:24 +0100246 component.updateConnectPointStatus(sk3, null, null, null, null, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800247 updated = component.cpStatus.get(sk3);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700248 Assert.assertEquals(NONE, updated.defaultEapolStatus);
249 Assert.assertEquals(NONE, updated.subscriberFlowsStatus);
250 Assert.assertEquals(NONE, updated.dhcpStatus);
251 }
252
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800253 /**
254 * If the flow status is PENDING_REMOVE or ERROR and there is no
255 * previous state in the map that don't update it.
256 * In case of a device disconnection we immediately wipe out the status,
257 * but then flows might update the cpStatus map. That result
258 */
259 @Test
260 public void doNotUpdateConnectPointStatus() {
261 DeviceId deviceId = DeviceId.deviceId("test-device");
262 ProviderId pid = new ProviderId("of", "foo");
263 Device device =
264 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
265 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100266 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800267
268 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), new UniTagInformation());
269
270 // cpStatus map for the test
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800271 component.cpStatus = component.storageService.
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800272 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
273
274 // check that an entry is not created if the only status is pending remove
Andrea Campanella87241ae2022-03-11 11:20:24 +0100275 component.updateConnectPointStatus(sk1, null, null, null, PENDING_REMOVE, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800276 OltPortStatus entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800277 Assert.assertNull(entry);
278
279 // check that an entry is not created if the only status is ERROR
Andrea Campanella87241ae2022-03-11 11:20:24 +0100280 component.updateConnectPointStatus(sk1, null, null, null, ERROR, null);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800281 entry = component.cpStatus.get(sk1);
Matteo Scandolo2542e5d2021-12-01 16:53:41 -0800282 Assert.assertNull(entry);
283 }
284
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700285 @Test
286 public void testHasDefaultEapol() {
287 DeviceId deviceId = DeviceId.deviceId("test-device");
288 ProviderId pid = new ProviderId("of", "foo");
289
290 Device device =
291 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
292
293 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
294 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
295 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800296 component.defaultEapolUniTag);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700297
298 Port port17 = new DefaultPort(device, PortNumber.portNumber(17), true,
299 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
300
301 OltPortStatus portStatusAdded = new OltPortStatus(
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300302 ADDED,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700303 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000304 null,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100305 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700306 null
307 );
308
309 OltPortStatus portStatusRemoved = new OltPortStatus(
310 REMOVED,
311 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000312 null,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100313 null,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700314 null
315 );
316
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800317 component.cpStatus.put(skWithStatus, portStatusAdded);
318 Assert.assertTrue(component.hasDefaultEapol(port));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700319
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800320 component.cpStatus.put(skWithStatus, portStatusRemoved);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700321
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800322 Assert.assertFalse(component.hasDefaultEapol(port17));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700323 }
324
325 @Test
326 public void testHasSubscriberFlows() {
327 // TODO test with multiple services
328 DeviceId deviceId = DeviceId.deviceId("test-device");
329 ProviderId pid = new ProviderId("of", "foo");
330
331 Device device =
332 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
333
334 Port port = new DefaultPort(device, PortNumber.portNumber(16), true,
335 DefaultAnnotations.builder().set(PORT_NAME, "name-1").build());
336
337 UniTagInformation uti = new UniTagInformation.Builder().setServiceName("test").build();
338 ServiceKey skWithStatus = new ServiceKey(new AccessDevicePort(port),
339 uti);
340
341 OltPortStatus withDefaultEapol = new OltPortStatus(
342 ADDED,
343 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000344 NONE,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100345 NONE,
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700346 NONE
347 );
348
349 OltPortStatus withDhcp = new OltPortStatus(
350 REMOVED,
351 NONE,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100352 NONE,
yasin sapli0823c932022-01-26 11:26:09 +0000353 ADDED,
354 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700355 );
356
357 OltPortStatus withSubFlow = new OltPortStatus(
358 REMOVED,
359 ADDED,
yasin sapli0823c932022-01-26 11:26:09 +0000360 ADDED,
Andrea Campanella87241ae2022-03-11 11:20:24 +0100361 ADDED,
yasin sapli0823c932022-01-26 11:26:09 +0000362 NONE
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700363 );
364
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800365 component.cpStatus.put(skWithStatus, withDefaultEapol);
366 Assert.assertFalse(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700367
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800368 component.cpStatus.put(skWithStatus, withDhcp);
369 Assert.assertTrue(component.hasDhcpFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700370
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800371 component.cpStatus.put(skWithStatus, withSubFlow);
372 Assert.assertTrue(component.hasSubscriberFlows(port, uti));
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700373 }
374
375 @Test
376 public void testHandleBasicPortFlowsNoEapol() throws Exception {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800377 component.enableEapol = false;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700378 // create empty service for testing
379 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
380 UniTagInformation empty = new UniTagInformation.Builder().build();
381 uniTagInformationList.add(empty);
382
383 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
384 si.setUniTagList(uniTagInformationList);
385
386 final DiscoveredSubscriber addedSub =
387 new DiscoveredSubscriber(testDevice,
388 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
389 false, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800390 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700391 // if eapol is not enabled there's nothing we need to do,
392 // so make sure we don't even call sadis
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800393 verify(component.subsService, never()).get(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700394 }
395
396 @Test
397 public void testHandleBasicPortFlowsWithEapolNoMeter() throws Exception {
398 // create empty service for testing
399 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
400 UniTagInformation empty = new UniTagInformation.Builder().build();
401 uniTagInformationList.add(empty);
402 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
403 si.setUniTagList(uniTagInformationList);
404 final DiscoveredSubscriber addedSub =
405 new DiscoveredSubscriber(testDevice,
406 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
407 false, si);
408 // whether the meter is pending or not is up to the createMeter method to handle
409 // we just don't proceed with the subscriber till it's ready
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800410 doReturn(false).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700411 .createMeter(addedSub.device.id(), DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800412 boolean res = component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700413
414 Assert.assertFalse(res);
415
416 // we do not create flows
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800417 verify(component.flowObjectiveService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700418 .filter(eq(addedSub.device.id()), any());
419 }
420
421 @Test
422 public void testHandleBasicPortFlowsWithEapolAddedMeter() throws Exception {
423 // create empty service for testing
424 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
425 UniTagInformation empty = new UniTagInformation.Builder().build();
426 uniTagInformationList.add(empty);
427 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
428 si.setUniTagList(uniTagInformationList);
429 final DiscoveredSubscriber addedSub =
430 new DiscoveredSubscriber(testDevice,
431 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
432 false, si);
433 // this is the happy case, we have the meter so we check that the default EAPOL flow
434 // is installed
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800435 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700436 .createMeter(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800437 doReturn(true).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700438 .hasMeterByBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800439 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700440 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
441
442 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
443 .permit()
444 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
445 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
446 .fromApp(testAppId)
447 .withPriority(10000)
448 .withMeta(
449 DefaultTrafficTreatment.builder()
450 .meter(MeterId.meterId(1))
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530451 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(
Harsh Awasthi498b5c62022-03-21 23:19:46 +0530452 VlanId.NONE,
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800453 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700454 .setOutput(PortNumber.CONTROLLER)
455 .pushVlan()
456 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
457 )
458 .add();
459
460
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800461 component.handleBasicPortFlows(addedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700462
463 // we check for an existing meter (present)
464 // FIXME understand why the above test invokes this call and this one doesn't
465// verify(oltFlowService.oltMeterService, times(1))
466// .hasMeterByBandwidthProfile(eq(addedSub.device.id()), eq(DEFAULT_BP_ID_DEFAULT));
467
468 // the meter exist, no need to check for PENDING or to create it
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800469 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700470 .hasPendingMeterByBandwidthProfile(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800471 verify(component.oltMeterService, never())
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700472 .createMeterForBp(eq(deviceId), eq(DEFAULT_BP_ID_DEFAULT));
473
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800474 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700475 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
476 }
477
478 @Test
479 public void testHandleBasicPortFlowsRemovedSub() throws Exception {
480 // create empty service for testing
481 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
482 UniTagInformation empty = new UniTagInformation.Builder().build();
483 uniTagInformationList.add(empty);
484 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
485 si.setUniTagList(uniTagInformationList);
486 final DiscoveredSubscriber removedSub =
487 new DiscoveredSubscriber(testDevice,
488 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
489 false, si);
490 // we are testing that when a port goes down we remove the default EAPOL flow
491
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800492 doReturn(MeterId.meterId(1)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700493 .getMeterIdForBandwidthProfile(deviceId, DEFAULT_BP_ID_DEFAULT);
494
495 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
496 .deny()
497 .withKey(Criteria.matchInPort(uniUpdateEnabled.number()))
498 .addCondition(Criteria.matchEthType(EthType.EtherType.EAPOL.ethType()))
499 .fromApp(testAppId)
500 .withPriority(10000)
501 .withMeta(
502 DefaultTrafficTreatment.builder()
503 .meter(MeterId.meterId(1))
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530504 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(
Harsh Awasthi498b5c62022-03-21 23:19:46 +0530505 VlanId.NONE,
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800506 component.defaultTechProfileId, MeterId.meterId(1)), 0)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700507 .setOutput(PortNumber.CONTROLLER)
508 .pushVlan()
509 .setVlanId(VlanId.vlanId(eapolDefaultVlan)).build()
510 )
511 .add();
512
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800513 component.handleBasicPortFlows(removedSub, DEFAULT_BP_ID_DEFAULT, DEFAULT_BP_ID_DEFAULT);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700514
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800515 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700516 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
517 }
518
519 @Test
520 public void testHandleNniFlowsOnlyLldp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800521 component.enableDhcpOnNni = false;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300522 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700523
524 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
525 .permit()
526 .withKey(Criteria.matchInPort(nniPort.number()))
527 .addCondition(Criteria.matchEthType(EthType.EtherType.LLDP.ethType()))
528 .fromApp(testAppId)
529 .withPriority(10000)
530 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
531 .add();
532
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800533 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700534 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800535 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700536 .filter(eq(deviceId), any());
537 }
538
539 @Test
540 public void testHandleNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800541 component.enableDhcpOnNni = true;
542 component.enableDhcpV4 = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300543 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700544
545 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
546 .permit()
547 .withKey(Criteria.matchInPort(nniPort.number()))
548 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
549 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
550 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
551 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
552 .fromApp(testAppId)
553 .withPriority(10000)
554 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
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
566 public void testRemoveNniFlowsDhcpV4() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800567 component.enableDhcpOnNni = true;
568 component.enableDhcpV4 = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300569 component.handleNniFlows(testDevice, nniPortDisabled, FlowOperation.REMOVE);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700570
571 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
572 .deny()
573 .withKey(Criteria.matchInPort(nniPort.number()))
574 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
575 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
576 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
577 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
578 .fromApp(testAppId)
579 .withPriority(10000)
580 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
581 .add();
582
583 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800584 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700585 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
586 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800587 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700588 .filter(eq(deviceId), any());
589 }
590
591 @Test
592 public void testHandleNniFlowsDhcpV6() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800593 component.enableDhcpOnNni = true;
594 component.enableDhcpV4 = false;
595 component.enableDhcpV6 = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300596 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700597
598 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
599 .permit()
600 .withKey(Criteria.matchInPort(nniPort.number()))
601 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV6.ethType()))
602 .addCondition(Criteria.matchIPProtocol(IPv6.PROTOCOL_UDP))
603 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(546)))
604 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(547)))
605 .fromApp(testAppId)
606 .withPriority(10000)
607 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
608 .add();
609
610 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800611 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700612 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
613 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800614 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700615 .filter(eq(deviceId), any());
616 }
617
618 @Test
619 public void testHandleNniFlowsIgmp() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800620 component.enableDhcpOnNni = false;
621 component.enableIgmpOnNni = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300622 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700623
624 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
625 .permit()
626 .withKey(Criteria.matchInPort(nniPort.number()))
627 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
628 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_IGMP))
629 .fromApp(testAppId)
630 .withPriority(10000)
631 .add();
632
633 // invoked with the correct DHCP filtering objective
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800634 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700635 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
636 // invoked only twice, LLDP and DHCP
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800637 verify(component.flowObjectiveService, times(2))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700638 .filter(eq(deviceId), any());
639 }
640
641 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000642 public void testHandleNniFlowsPppoe() {
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530643 component.enableDhcpOnNni = false;
yasin sapli0823c932022-01-26 11:26:09 +0000644 component.enablePppoeOnNni = true;
645 component.enablePppoe = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300646 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
yasin sapli0823c932022-01-26 11:26:09 +0000647
648 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
649 .permit()
650 .withKey(Criteria.matchInPort(nniPort.number()))
651 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
652 .fromApp(testAppId)
653 .withPriority(10000)
654 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
655 .add();
656
657 // invoked with the correct Pppoe filtering objective
658 verify(component.flowObjectiveService, times(1))
659 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
660 // invoked only twice, LLDP and DHCP
661 verify(component.flowObjectiveService, times(2))
662 .filter(eq(deviceId), any());
663 }
664
665 @Test
666 public void testRemoveNniFlowsPppoe() {
Harsh Awasthic1e4bf52022-02-09 14:14:14 +0530667 component.enableDhcpOnNni = false;
yasin sapli0823c932022-01-26 11:26:09 +0000668 component.enablePppoeOnNni = true;
669 component.enablePppoe = true;
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300670 component.handleNniFlows(testDevice, nniPortDisabled, FlowOperation.REMOVE);
yasin sapli0823c932022-01-26 11:26:09 +0000671
672 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
673 .deny()
674 .withKey(Criteria.matchInPort(nniPort.number()))
675 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
676 .fromApp(testAppId)
677 .withPriority(10000)
678 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
679 .add();
680
681 // invoked with the correct Pppoe filtering objective
682 verify(component.flowObjectiveService, times(1))
683 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
684 // invoked only twice, LLDP and DHCP
685 verify(component.flowObjectiveService, times(2))
686 .filter(eq(deviceId), any());
687 }
688
689 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700690 public void testMacAddressNotRequired() {
691 // create a single service that doesn't require mac address
692 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
693 UniTagInformation hsia = new UniTagInformation.Builder()
694 .setEnableMacLearning(false)
695 .build();
696 uniTagInformationList.add(hsia);
697 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
698 si.setUniTagList(uniTagInformationList);
699
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800700 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700701 // we return true as we don't care wether it's available or not
702 Assert.assertTrue(isMacAvailable);
703 }
704
705 @Test
706 public void testIsMacAddressAvailableViaMacLearning() {
707
708 // create a single service that requires macLearning to be enabled
709 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
710 VlanId hsiaCtag = VlanId.vlanId((short) 11);
711 UniTagInformation hsia = new UniTagInformation.Builder()
712 .setPonCTag(hsiaCtag)
713 .setEnableMacLearning(true).build();
714 uniTagInformationList.add(hsia);
715
716 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
717 si.setUniTagList(uniTagInformationList);
718
719 // with no hosts discovered, return false
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800720 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700721 Assert.assertFalse(isMacAvailable);
722
723 // with a discovered host, return true
724 Host fakeHost = new DefaultHost(ProviderId.NONE, HostId.hostId(MacAddress.NONE), MacAddress.ZERO,
725 hsiaCtag, HostLocation.NONE, new HashSet<>(), DefaultAnnotations.builder().build());
726 Set<Host> hosts = new HashSet<>(Arrays.asList(fakeHost));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800727 doReturn(hosts).when(component.hostService).getConnectedHosts((ConnectPoint) any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700728
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800729 isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700730 Assert.assertTrue(isMacAvailable);
731 }
732
733 @Test
734 public void testIsMacAddressAvailableViaConfiguration() {
735 // create a single service that has a macAddress configured
736 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
737 UniTagInformation hsia = new UniTagInformation.Builder()
738 .setConfiguredMacAddress("2e:0a:00:01:00:00")
739 .build();
740 uniTagInformationList.add(hsia);
741 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
742 si.setUniTagList(uniTagInformationList);
743
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800744 boolean isMacAvailable = component.isMacAddressAvailable(testDevice.id(), uniUpdateEnabled, si);
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700745 Assert.assertTrue(isMacAvailable);
746 }
747
748 @Test
749 public void testHandleSubscriberDhcpFlowsAdd() {
750
751 String usBp = "usBp";
752 String usOltBp = "usOltBp";
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800753 component.enableDhcpV4 = true;
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700754
755 // create two services, one requires DHCP the other doesn't
756 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
757 VlanId hsiaCtag = VlanId.vlanId((short) 11);
758 UniTagInformation hsia = new UniTagInformation.Builder()
759 .setPonCTag(hsiaCtag)
760 .setTechnologyProfileId(64)
761 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
762 .setUpstreamBandwidthProfile(usBp)
763 .setUpstreamOltBandwidthProfile(usOltBp)
764 .setIsDhcpRequired(true).build();
765 UniTagInformation mc = new UniTagInformation.Builder()
766 .setIsDhcpRequired(false).build();
767 uniTagInformationList.add(hsia);
768 uniTagInformationList.add(mc);
769
770 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
771 si.setUniTagList(uniTagInformationList);
772
773 final DiscoveredSubscriber addedSub =
774 new DiscoveredSubscriber(testDevice,
775 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
776 false, si);
777
778 // return meter IDs
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800779 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700780 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800781 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700782 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
783
784 // TODO improve the matches on the filter
785 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
786 .permit()
787 .withKey(Criteria.matchInPort(addedSub.port.number()))
788 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
789 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
790 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
791 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
792 .fromApp(testAppId)
793 .withPriority(10000)
794 .add();
795
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800796 component.handleSubscriberDhcpFlows(addedSub.device.id(), addedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300797 FlowOperation.ADD, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800798 verify(component.flowObjectiveService, times(1))
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700799 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
800 }
801
802 @Test
yasin sapli0823c932022-01-26 11:26:09 +0000803 public void testHandleSubscriberPppoeFlowsAdd() {
804
805 String usBp = "usBp";
806 String usOltBp = "usOltBp";
807 component.enablePppoe = true;
808
809 // create two services, one requires Pppoe the other doesn't
810 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
811 VlanId hsiaCtag = VlanId.vlanId((short) 11);
812 UniTagInformation hsia = new UniTagInformation.Builder()
813 .setPonCTag(hsiaCtag)
814 .setTechnologyProfileId(64)
815 .setUniTagMatch(VlanId.vlanId(VlanId.NO_VID))
816 .setUpstreamBandwidthProfile(usBp)
817 .setUpstreamOltBandwidthProfile(usOltBp)
818 .setIsPppoeRequired(true).build();
819 UniTagInformation mc = new UniTagInformation.Builder()
820 .setIsPppoeRequired(false).build();
821 uniTagInformationList.add(hsia);
822 uniTagInformationList.add(mc);
823
824 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
825 si.setUniTagList(uniTagInformationList);
826
827 final DiscoveredSubscriber addedSub =
828 new DiscoveredSubscriber(testDevice,
829 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
830 false, si);
831
832 // return meter IDs
833 doReturn(MeterId.meterId(2)).when(component.oltMeterService)
834 .getMeterIdForBandwidthProfile(addedSub.device.id(), usBp);
835 doReturn(MeterId.meterId(3)).when(component.oltMeterService)
836 .getMeterIdForBandwidthProfile(addedSub.device.id(), usOltBp);
837
838 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
839 .permit()
840 .withKey(Criteria.matchInPort(addedSub.port.number()))
841 .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
842 .fromApp(testAppId)
843 .withPriority(10000)
844 .add();
845
846 component.handleSubscriberPppoeFlows(addedSub.device.id(), addedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300847 FlowOperation.ADD, si);
yasin sapli0823c932022-01-26 11:26:09 +0000848 verify(component.flowObjectiveService, times(1))
849 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
850 }
851
852 @Test
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700853 public void testInternalFlowListenerNotMaster() {
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800854 doReturn(false).when(component.oltDeviceService).isLocalLeader(any());
Matteo Scandoloaa2adde2021-09-13 12:45:32 -0700855
856 FlowRule flowRule = DefaultFlowRule.builder()
857 .forDevice(DeviceId.deviceId("foo"))
858 .fromApp(testAppId)
859 .makePermanent()
860 .withPriority(1000)
861 .build();
862 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
863 flowRule);
864
865 internalFlowListener.event(event);
866
867 // if we're not master of the device, we should not update
868 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
869 }
870
871 @Test
872 public void testInternalFlowListenerDifferentApp() {
873 ApplicationId someAppId = new DefaultApplicationId(1, "org.opencord.olt.not-test");
874 FlowRule flowRule = DefaultFlowRule.builder()
875 .forDevice(DeviceId.deviceId("foo"))
876 .fromApp(someAppId)
877 .makePermanent()
878 .withPriority(1000)
879 .build();
880 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED,
881 flowRule);
882
883 internalFlowListener.event(event);
884
885 // if we're not master of the device, we should not update
886 verify(internalFlowListener, never()).updateCpStatus(any(), any(), any());
887 }
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800888
889 @Test
890 public void testRemoveSubscriberFlows() {
891 // test that if we have EAPOL we wait till the tagged flow is removed
892 // before installing the default one
893
894 // setup
895 component.enableEapol = true;
896
897 // mock data
898 DeviceId deviceId = DeviceId.deviceId("test-device");
899 ProviderId pid = new ProviderId("of", "foo");
900 Device device =
901 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
902 Port port = new DefaultPort(device, PortNumber.portNumber(1), true,
Andrea Campanella40d2b342022-02-04 18:13:37 +0100903 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800904
905 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
906 UniTagInformation hsia = new UniTagInformation.Builder()
907 .setUpstreamBandwidthProfile("usbp")
908 .setDownstreamBandwidthProfile("dsbp")
909 .setPonCTag(VlanId.vlanId((short) 900)).build();
910 uniTagInformationList.add(hsia);
911 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
912 si.setUniTagList(uniTagInformationList);
913
914 DiscoveredSubscriber sub = new DiscoveredSubscriber(
915 device, port, DiscoveredSubscriber.Status.REMOVED, true, si);
916
917 // first test that when we remove the EAPOL flow we return false so that the
918 // subscriber is not removed from the queue
Andrea Campanella34ce61a2022-04-28 18:55:46 +0200919 doReturn(null).when(deviceService).getPort(any());
Andrea Campanella87241ae2022-03-11 11:20:24 +0100920 doReturn(true).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any(), eq(true));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800921 boolean res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
922 verify(oltFlowService, times(1))
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300923 .handleSubscriberDhcpFlows(deviceId, port, FlowOperation.REMOVE, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800924 verify(oltFlowService, times(1))
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300925 .handleSubscriberEapolFlows(sub, FlowOperation.REMOVE, si);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800926 verify(oltFlowService, times(1))
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300927 .handleSubscriberDataFlows(device, port, FlowOperation.REMOVE,
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800928 si, DEFAULT_MCAST_SERVICE_NAME);
929 verify(oltFlowService, times(1))
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300930 .handleSubscriberIgmpFlows(sub, FlowOperation.REMOVE);
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800931 verify(oltFlowService, never())
932 .handleEapolFlow(any(), any(), any(),
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300933 eq(FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800934 Assert.assertFalse(res);
935
936 // then test that if the tagged EAPOL is not there we install the default EAPOL
937 // and return true so we remove the subscriber from the queue
Andrea Campanella87241ae2022-03-11 11:20:24 +0100938 doReturn(false).when(oltFlowService).areSubscriberFlowsPendingRemoval(any(), any(), eq(true));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800939 doReturn(port).when(oltFlowService.deviceService).getPort(deviceId, port.number());
940 res = oltFlowService.removeSubscriberFlows(sub, DEFAULT_BP_ID_DEFAULT, DEFAULT_MCAST_SERVICE_NAME);
941 verify(oltFlowService, times(1))
942 .handleEapolFlow(any(), any(), any(),
Gustavo Silva29fb20e2022-05-26 09:59:54 -0300943 eq(FlowOperation.ADD), eq(VlanId.vlanId(OltFlowService.EAPOL_DEFAULT_VLAN)));
Matteo Scandolo97449bb2021-12-09 15:33:46 -0800944 Assert.assertTrue(res);
945 }
Andrea Campanella40d2b342022-02-04 18:13:37 +0100946
947 @Test
948 public void testRemovedFlowEvent() throws InterruptedException {
949 // test that we update the status in case of REMOVED flow even with non
950 // existing port in the onos device manager
951
952 DeviceId deviceId = DeviceId.deviceId("test-device");
953 ProviderId pid = new ProviderId("of", "foo");
954 Device device =
955 new DefaultDevice(pid, deviceId, Device.Type.OLT, "", "", "", "", null);
956
957 Port port1 = new DefaultPort(device, PortNumber.portNumber(1), true,
958 DefaultAnnotations.builder().set(PORT_NAME, PORT_1).build());
959 // create empty service for testing
960 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
961 UniTagInformation vlanUniTag = new UniTagInformation.Builder().setPonCTag(VlanId.vlanId((short) 60))
962 .build();
963 uniTagInformationList.add(vlanUniTag);
964 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
965 si.setUniTagList(uniTagInformationList);
966 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(port1), vlanUniTag);
967
968 TrafficSelector selector = DefaultTrafficSelector.builder()
969 .matchInPort(port1.number())
970 .matchVlanId(VlanId.vlanId((short) 60))
971 .build();
972
973 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
974 .immediate()
975 .setOutput(port1.number())
976 .build();
977
978 FlowRule flowRule = DefaultFlowRule.builder()
979 .makePermanent()
980 .withPriority(1000)
981 .forTable(0)
982 .forDevice(deviceId)
983 .fromApp(testAppId)
984 .withSelector(selector)
985 .withTreatment(treatment)
986 .build();
987
988 // cpStatus map for the test
989 component.cpStatus = component.storageService.
990 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
Andrea Campanella87241ae2022-03-11 11:20:24 +0100991 OltPortStatus cp1Status = new OltPortStatus(NONE, NONE, PENDING_REMOVE, NONE, NONE);
Andrea Campanella40d2b342022-02-04 18:13:37 +0100992 component.cpStatus.put(sk1, cp1Status);
993
994 FlowRuleEvent event = new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVED, flowRule);
995 doReturn(true).when(component.oltDeviceService).isLocalLeader(any());
996 doReturn(device).when(component.deviceService).getDevice(deviceId);
997 doReturn(si).when(component.subsService).get(PORT_1);
998
999 oltFlowService.internalFlowListener.event(event);
1000
1001 //Some time to finish the operation
1002 TimeUnit.MILLISECONDS.sleep(200);
1003
1004 OltPortStatus status = component.cpStatus.get(sk1);
1005 Assert.assertEquals(REMOVED, status.subscriberFlowsStatus);
1006 }
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301007
1008 @Test
1009 public void testHandleNniFlowsDhcpV4WithNniDhcpTrapVid() {
1010 component.enableDhcpOnNni = true;
1011 component.enableDhcpV4 = true;
1012
1013 SubscriberAndDeviceInformation testOltFttbSadis = new SubscriberAndDeviceInformation();
1014 testOltFttbSadis.setNniDhcpTrapVid(VlanId.vlanId("60"));
1015
1016 when(component.sadisService.getSubscriberInfoService().get(testDevice.serialNumber())).
1017 thenReturn(testOltFttbSadis);
1018
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001019 component.handleNniFlows(testDevice, nniPort, FlowOperation.ADD);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301020
1021 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
1022 .permit()
1023 .withKey(Criteria.matchInPort(nniPort.number()))
1024 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
1025 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
1026 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(67)))
1027 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(68)))
1028 .addCondition(Criteria.matchVlanId(testOltFttbSadis.nniDhcpTrapVid()))
1029 .fromApp(testAppId)
1030 .withPriority(10000)
1031 .withMeta(DefaultTrafficTreatment.builder().setOutput(PortNumber.CONTROLLER).build())
1032 .add();
1033
1034 // invoked with the correct DHCP filtering objective
1035 verify(component.flowObjectiveService, times(1))
1036 .filter(eq(deviceId), argThat(new FilteringObjectiveMatcher(expectedFilter)));
1037 // invoked only twice, LLDP and DHCP
1038 verify(component.flowObjectiveService, times(2))
1039 .filter(eq(deviceId), any());
1040 }
1041
1042 @Test
1043 public void testHandleFttbSubscriberDhcpFlowsAdd() {
1044 component.enableDhcpV4 = true;
1045
1046 // add two services, one requires DHCP the other doesn't
1047 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1048
1049 UniTagInformation mc = new UniTagInformation.Builder()
1050 .setIsDhcpRequired(false).build();
1051 uniTagInformationList.add(dpuMgmtUti);
1052 uniTagInformationList.add(mc);
1053
1054 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1055 si.setUniTagList(uniTagInformationList);
1056
1057 final DiscoveredSubscriber addedSub =
1058 new DiscoveredSubscriber(testDevice,
1059 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
1060 false, si);
1061
1062 // return meter IDs
1063 MeterId usBpMeterId = MeterId.meterId(2);
1064 MeterId usOltBpMeterId = MeterId.meterId(3);
1065
1066 doReturn(usBpMeterId).when(component.oltMeterService)
1067 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1068 doReturn(usOltBpMeterId).when(component.oltMeterService)
1069 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1070
1071 TrafficTreatment expectedTreatment = DefaultTrafficTreatment.builder()
1072 .setVlanId(dpuMgmtUti.getPonSTag())
1073 .setVlanPcp((byte) dpuMgmtUti.getUsPonSTagPriority())
1074 .setOutput(PortNumber.CONTROLLER)
1075 .meter(usBpMeterId)
Andrea Campanella7ef88992022-05-17 12:38:00 +02001076 //TODO why tests use this one and not the other method ?
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301077 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(VlanId.NONE,
1078 dpuMgmtUti.getTechnologyProfileId(), usOltBpMeterId), 0L).build();
1079
1080 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
1081 .permit()
1082 .withKey(Criteria.matchInPort(addedSub.port.number()))
1083 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
1084 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
1085 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
1086 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
1087 .addCondition(Criteria.matchVlanId(dpuMgmtUti.getPonCTag()))
1088 .addCondition(Criteria.matchVlanPcp((byte) dpuMgmtUti.getUsPonCTagPriority()))
1089 .fromApp(testAppId)
1090 .withPriority(10000)
1091 .withMeta(expectedTreatment)
1092 .add();
1093
1094 component.handleSubscriberDhcpFlows(addedSub.device.id(), addedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001095 FlowOperation.ADD, si);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301096 verify(component.flowObjectiveService, times(1))
1097 .filter(eq(addedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
1098 }
1099
1100 @Test
1101 public void testRemoveFttbSubscriberDhcpFlows() {
1102 component.enableDhcpV4 = true;
1103
1104 // Mocking the get call, to mark the SubscriberKey as already added.
1105 component.cpStatus = Mockito.mock(Map.class);
1106 doReturn(new OltPortStatus(null, null, null, ADDED, null))
1107 .when(component.cpStatus).get(Mockito.any());
1108
1109 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1110 uniTagInformationList.add(dpuMgmtUti);
1111
1112 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1113 si.setUniTagList(uniTagInformationList);
1114
1115 final DiscoveredSubscriber removedSub =
1116 new DiscoveredSubscriber(testDevice,
1117 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
1118 false, si);
1119
1120 // return meter IDs
1121 MeterId usBpMeterId = MeterId.meterId(2);
1122 MeterId usOltBpMeterId = MeterId.meterId(3);
1123
1124 doReturn(usBpMeterId).when(component.oltMeterService)
1125 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1126 doReturn(usOltBpMeterId).when(component.oltMeterService)
1127 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1128
1129 TrafficTreatment expectedTreatment = DefaultTrafficTreatment.builder()
1130 .setVlanId(dpuMgmtUti.getPonSTag())
1131 .setVlanPcp((byte) dpuMgmtUti.getUsPonSTagPriority())
1132 .setOutput(PortNumber.CONTROLLER)
1133 .meter(usBpMeterId)
1134 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(VlanId.NONE,
1135 dpuMgmtUti.getTechnologyProfileId(), usOltBpMeterId), 0L).build();
1136
1137 FilteringObjective expectedFilter = DefaultFilteringObjective.builder()
1138 .deny()
1139 .withKey(Criteria.matchInPort(removedSub.port.number()))
1140 .addCondition(Criteria.matchEthType(EthType.EtherType.IPV4.ethType()))
1141 .addCondition(Criteria.matchIPProtocol(IPv4.PROTOCOL_UDP))
1142 .addCondition(Criteria.matchUdpSrc(TpPort.tpPort(68)))
1143 .addCondition(Criteria.matchUdpDst(TpPort.tpPort(67)))
1144 .addCondition(Criteria.matchVlanId(dpuMgmtUti.getPonCTag()))
1145 .addCondition(Criteria.matchVlanPcp((byte) dpuMgmtUti.getUsPonCTagPriority()))
1146 .fromApp(testAppId)
1147 .withPriority(10000)
1148 .withMeta(expectedTreatment)
1149 .add();
1150
1151 component.handleSubscriberDhcpFlows(removedSub.device.id(), removedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001152 FlowOperation.REMOVE, si);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301153 verify(component.flowObjectiveService, times(1))
1154 .filter(eq(removedSub.device.id()), argThat(new FilteringObjectiveMatcher(expectedFilter)));
1155 }
1156
1157 @Test
1158 public void testHandleFttbMacSwitchingFlowsAdd() {
1159 component.enableDhcpV4 = true;
1160
1161 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1162
1163 uniTagInformationList.add(dpuMgmtUti);
1164 uniTagInformationList.add(ancpUti);
1165
1166 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1167 si.setUniTagList(uniTagInformationList);
1168
1169 final DiscoveredSubscriber addedSub =
1170 new DiscoveredSubscriber(testDevice,
1171 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
1172 false, si);
1173
1174 // return meter IDs
1175 MeterId usBpMeterId = MeterId.meterId(1);
1176 MeterId usOltBpMeterId = MeterId.meterId(1);
1177
1178 MeterId dsBpMeterId = MeterId.meterId(2);
1179 MeterId dsOltBpMeterId = MeterId.meterId(2);
1180
1181 MacAddress mac = MacAddress.valueOf("0A:00:27:00:00:09");
1182 Host host = Mockito.mock(Host.class);
1183 doReturn(mac).when(host).mac();
1184 doReturn(dpuMgmtUti.getPonSTag()).when(host).vlan();
1185
1186 doReturn(new HashSet<>(Arrays.asList(host))).when(component.hostService)
1187 .getConnectedHosts(new ConnectPoint(addedSub.device.id(), addedSub.port.number()));
1188
1189 doReturn(usBpMeterId).when(component.oltMeterService)
1190 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1191 doReturn(usOltBpMeterId).when(component.oltMeterService)
1192 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1193
1194 doReturn(dsBpMeterId).when(component.oltMeterService)
1195 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getDownstreamBandwidthProfile());
1196 doReturn(dsOltBpMeterId).when(component.oltMeterService)
1197 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getDownstreamOltBandwidthProfile());
1198
1199 String[] directions = {FTTB_FLOW_UPSTREAM, FTTB_FLOW_DOWNSTREAM};
1200 for (UniTagInformation uti : uniTagInformationList) {
1201 for (String direction : directions) {
1202 TrafficTreatment.Builder expectedTreatment = DefaultTrafficTreatment.builder();
1203 TrafficSelector.Builder expectedSelectorBuilder = DefaultTrafficSelector.builder();
1204
1205 DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
1206 annotationBuilder.set(FTTB_FLOW_DIRECTION, direction);
1207 annotationBuilder.set(FTTB_SERVICE_NAME, uti.getServiceName());
1208
1209 switch (direction) {
1210 case FTTB_FLOW_UPSTREAM:
1211 expectedSelectorBuilder
1212 .matchInPort(addedSub.port.number())
1213 .matchVlanId(uti.getPonCTag())
1214 .matchVlanPcp((byte) uti.getUsPonCTagPriority())
1215 .matchEthSrc(mac);
1216
1217 expectedTreatment.setVlanId(uti.getPonSTag())
1218 .setVlanPcp((byte) uti.getUsPonSTagPriority())
1219 .setOutput(nniPort.number())
1220 .meter(usBpMeterId)
1221 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.NONE,
1222 uti.getTechnologyProfileId(), nniPort.number()), 0L).build();
1223
1224 annotationBuilder.set(UPSTREAM_ONU, usBpMeterId.toString());
1225 annotationBuilder.set(UPSTREAM_OLT, usOltBpMeterId.toString());
1226 break;
1227
1228 case FTTB_FLOW_DOWNSTREAM:
1229 expectedSelectorBuilder
1230 .matchInPort(nniPort.number())
1231 .matchVlanId(uti.getPonSTag())
1232 .matchEthDst(mac);
1233
1234 expectedTreatment.setVlanId(uti.getPonCTag())
1235 .setOutput(addedSub.port.number())
1236 .meter(dsBpMeterId)
1237 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.NONE,
1238 uti.getTechnologyProfileId(), addedSub.port.number()), 0L).build();
1239
1240 annotationBuilder.set(DOWNSTREAM_ONU, dsBpMeterId.toString());
1241 annotationBuilder.set(DOWNSTREAM_OLT, dsOltBpMeterId.toString());
1242 break;
1243
1244 default:
1245 return;
1246 }
1247
1248 ForwardingObjective expected = DefaultForwardingObjective.builder()
1249 .withFlag(ForwardingObjective.Flag.VERSATILE)
1250 .withPriority(1000)
1251 .makePermanent()
1252 .withSelector(expectedSelectorBuilder.build())
1253 .withAnnotations(annotationBuilder.build())
1254 .fromApp(testAppId)
1255 .withTreatment(expectedTreatment.build())
1256 .add();
1257
1258 component.handleSubscriberDataFlows(addedSub.device, addedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001259 FlowOperation.ADD, si, DEFAULT_MCAST_SERVICE_NAME_DEFAULT);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301260 verify(component.flowObjectiveService, times(1))
1261 .forward(eq(addedSub.device.id()), eq(expected));
1262 }
1263 }
1264 }
1265
1266 @Test
1267 public void testRemoveFttbMacSwitchingFlows() {
1268 component.enableDhcpV4 = true;
1269 component.cpStatus = Mockito.mock(Map.class);
1270 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1271
1272 uniTagInformationList.add(dpuMgmtUti);
1273 uniTagInformationList.add(ancpUti);
1274
1275 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1276 si.setUniTagList(uniTagInformationList);
1277
1278 final DiscoveredSubscriber removedSub =
1279 new DiscoveredSubscriber(testDevice,
1280 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
1281 false, si);
1282
1283
1284 ServiceKey sk1 = new ServiceKey(new AccessDevicePort(removedSub.port), dpuMgmtUti);
1285 ServiceKey sk2 = new ServiceKey(new AccessDevicePort(removedSub.port), ancpUti);
1286
1287 component.cpStatus = component.storageService.
1288 <ServiceKey, OltPortStatus>consistentMapBuilder().build().asJavaMap();
1289 OltPortStatus cp1Status = new OltPortStatus(NONE, NONE, PENDING_ADD, NONE, NONE);
1290 OltPortStatus cp2Status = new OltPortStatus(NONE, NONE, PENDING_ADD, NONE, NONE);
1291 component.cpStatus.put(sk1, cp1Status);
1292 component.cpStatus.put(sk2, cp2Status);
1293
1294 // return meter IDs
1295 MeterId usBpMeterId = MeterId.meterId(1);
1296 MeterId usOltBpMeterId = MeterId.meterId(1);
1297
1298 MeterId dsBpMeterId = MeterId.meterId(2);
1299 MeterId dsOltBpMeterId = MeterId.meterId(2);
1300
1301 MacAddress mac = MacAddress.valueOf("0A:00:27:00:00:09");
1302 Host host = Mockito.mock(Host.class);
1303 doReturn(mac).when(host).mac();
1304 doReturn(dpuMgmtUti.getPonSTag()).when(host).vlan();
1305
1306 doReturn(new HashSet<>(Arrays.asList(host))).when(component.hostService)
1307 .getConnectedHosts(new ConnectPoint(removedSub.device.id(), removedSub.port.number()));
1308
1309 doReturn(usBpMeterId).when(component.oltMeterService)
1310 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1311 doReturn(usOltBpMeterId).when(component.oltMeterService)
1312 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1313
1314 doReturn(dsBpMeterId).when(component.oltMeterService)
1315 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getDownstreamBandwidthProfile());
1316 doReturn(dsOltBpMeterId).when(component.oltMeterService)
1317 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getDownstreamOltBandwidthProfile());
1318
1319 String[] directions = {FTTB_FLOW_UPSTREAM, FTTB_FLOW_DOWNSTREAM};
1320 for (UniTagInformation uti : uniTagInformationList) {
1321 for (String direction : directions) {
1322 TrafficTreatment.Builder expectedTreatment = DefaultTrafficTreatment.builder();
1323 TrafficSelector.Builder expectedSelectorBuilder = DefaultTrafficSelector.builder();
1324
1325 DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
1326 annotationBuilder.set(FTTB_FLOW_DIRECTION, direction);
1327 annotationBuilder.set(FTTB_SERVICE_NAME, uti.getServiceName());
1328
1329 switch (direction) {
1330 case FTTB_FLOW_UPSTREAM:
1331 expectedSelectorBuilder
1332 .matchInPort(removedSub.port.number())
1333 .matchVlanId(uti.getPonCTag())
1334 .matchVlanPcp((byte) uti.getUsPonCTagPriority())
1335 .matchEthSrc(mac);
1336
1337 expectedTreatment.setVlanId(uti.getPonSTag())
1338 .setVlanPcp((byte) uti.getUsPonSTagPriority())
1339 .setOutput(nniPort.number())
1340 .meter(usBpMeterId)
1341 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.NONE,
1342 uti.getTechnologyProfileId(), nniPort.number()), 0L).build();
1343
1344 annotationBuilder.set(UPSTREAM_ONU, usBpMeterId.toString());
1345 annotationBuilder.set(UPSTREAM_OLT, usOltBpMeterId.toString());
1346 break;
1347
1348 case FTTB_FLOW_DOWNSTREAM:
1349 expectedSelectorBuilder
1350 .matchInPort(nniPort.number())
1351 .matchVlanId(uti.getPonSTag())
1352 .matchEthDst(mac);
1353
1354 expectedTreatment.setVlanId(uti.getPonCTag())
1355 .setOutput(removedSub.port.number())
1356 .meter(dsBpMeterId)
1357 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.NONE,
1358 uti.getTechnologyProfileId(), removedSub.port.number()), 0L).build();
1359
1360 annotationBuilder.set(DOWNSTREAM_ONU, dsBpMeterId.toString());
1361 annotationBuilder.set(DOWNSTREAM_OLT, dsOltBpMeterId.toString());
1362 break;
1363
1364 default:
1365 return;
1366 }
1367
1368 ForwardingObjective expected = DefaultForwardingObjective.builder()
1369 .withFlag(ForwardingObjective.Flag.VERSATILE)
1370 .withPriority(1000)
1371 .makePermanent()
1372 .withSelector(expectedSelectorBuilder.build())
1373 .withAnnotations(annotationBuilder.build())
1374 .fromApp(testAppId)
1375 .withTreatment(expectedTreatment.build())
1376 .remove();
1377
1378 component.handleSubscriberDataFlows(removedSub.device, removedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001379 FlowOperation.REMOVE, si, DEFAULT_MCAST_SERVICE_NAME_DEFAULT);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301380 verify(component.flowObjectiveService, times(1))
1381 .forward(eq(removedSub.device.id()), eq(expected));
1382 }
1383 }
1384 }
1385
1386 @Test
1387 public void testHandleFttbSubscriberFlowsAdd() {
1388 component.enableDhcpV4 = true;
1389
1390 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1391 uniTagInformationList.add(fttbSubscriberUti);
1392
1393 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1394 si.setUniTagList(uniTagInformationList);
1395
1396 final DiscoveredSubscriber addedSub =
1397 new DiscoveredSubscriber(testDevice,
1398 uniUpdateEnabled, DiscoveredSubscriber.Status.ADDED,
1399 false, si);
1400
1401 // return meter IDs
1402 MeterId usBpMeterId = MeterId.meterId(1);
1403 MeterId usOltBpMeterId = MeterId.meterId(1);
1404
1405 MeterId dsBpMeterId = MeterId.meterId(2);
1406 MeterId dsOltBpMeterId = MeterId.meterId(2);
1407
1408 doReturn(usBpMeterId).when(component.oltMeterService)
1409 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1410 doReturn(usOltBpMeterId).when(component.oltMeterService)
1411 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1412
1413 doReturn(dsBpMeterId).when(component.oltMeterService)
1414 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getDownstreamBandwidthProfile());
1415 doReturn(dsOltBpMeterId).when(component.oltMeterService)
1416 .getMeterIdForBandwidthProfile(addedSub.device.id(), dpuMgmtUti.getDownstreamOltBandwidthProfile());
1417
1418 String[] directions = {FTTB_FLOW_UPSTREAM, FTTB_FLOW_DOWNSTREAM};
1419 for (UniTagInformation uti : uniTagInformationList) {
1420 for (String direction : directions) {
1421 TrafficTreatment.Builder expectedTreatment = DefaultTrafficTreatment.builder();
1422 TrafficSelector.Builder expectedSelectorBuilder = DefaultTrafficSelector.builder();
1423
1424 DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
1425 annotationBuilder.set(FTTB_FLOW_DIRECTION, direction);
1426 annotationBuilder.set(FTTB_SERVICE_NAME, uti.getServiceName());
1427
1428 switch (direction) {
1429 case FTTB_FLOW_UPSTREAM:
1430 expectedSelectorBuilder
1431 .matchInPort(addedSub.port.number())
1432 .matchVlanId(uti.getPonCTag());
1433
1434 expectedTreatment.setVlanId(uti.getPonSTag())
1435 .setOutput(nniPort.number())
1436 .meter(usBpMeterId)
1437 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.ANY,
1438 uti.getTechnologyProfileId(), nniPort.number()), 0L).build();
1439
1440 annotationBuilder.set(UPSTREAM_ONU, usBpMeterId.toString());
1441 annotationBuilder.set(UPSTREAM_OLT, usOltBpMeterId.toString());
1442 break;
1443
1444 case FTTB_FLOW_DOWNSTREAM:
1445 expectedSelectorBuilder
1446 .matchInPort(nniPort.number())
amit.ghosh4f0910e2022-06-20 15:53:21 +02001447 .matchMetadata(uti.getPonSTag().toShort())
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301448 .matchVlanId(uti.getPonSTag());
1449
1450 expectedTreatment.setVlanId(uti.getPonCTag())
1451 .setOutput(addedSub.port.number())
1452 .meter(dsBpMeterId)
1453 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.ANY,
1454 uti.getTechnologyProfileId(), addedSub.port.number()), 0L).build();
1455
1456 annotationBuilder.set(DOWNSTREAM_ONU, dsBpMeterId.toString());
1457 annotationBuilder.set(DOWNSTREAM_OLT, dsOltBpMeterId.toString());
1458 break;
1459
1460 default:
1461 return;
1462 }
1463
1464 ForwardingObjective expected = DefaultForwardingObjective.builder()
1465 .withFlag(ForwardingObjective.Flag.VERSATILE)
1466 .withPriority(1000)
1467 .makePermanent()
1468 .withSelector(expectedSelectorBuilder.build())
1469 .withAnnotations(annotationBuilder.build())
1470 .fromApp(testAppId)
1471 .withTreatment(expectedTreatment.build())
1472 .add();
1473
1474 component.handleSubscriberDataFlows(addedSub.device, addedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001475 FlowOperation.ADD, si, DEFAULT_MCAST_SERVICE_NAME_DEFAULT);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301476 verify(component.flowObjectiveService, times(1))
1477 .forward(eq(addedSub.device.id()), eq(expected));
1478 }
1479 }
1480 }
1481
1482 @Test
1483 public void testRemoveFttbSubscriberFlows() {
1484 component.enableDhcpV4 = true;
1485
1486 OltPortStatus oltPortStatus1 = new OltPortStatus(null, null, ADDED,
1487 null, null);
1488 // Mocking the get call, to mark the SubscriberKey as already added.
1489 component.cpStatus = Mockito.mock(Map.class);
1490 when(component.cpStatus.get(Mockito.any())).thenReturn(oltPortStatus1);
1491
1492 List<UniTagInformation> uniTagInformationList = new LinkedList<>();
1493
1494 uniTagInformationList.add(fttbSubscriberUti);
1495
1496 SubscriberAndDeviceInformation si = new SubscriberAndDeviceInformation();
1497 si.setUniTagList(uniTagInformationList);
1498
1499 final DiscoveredSubscriber removedSub =
1500 new DiscoveredSubscriber(testDevice,
1501 uniUpdateEnabled, DiscoveredSubscriber.Status.REMOVED,
1502 false, si);
1503
1504 // return meter IDs
1505 MeterId usBpMeterId = MeterId.meterId(1);
1506 MeterId usOltBpMeterId = MeterId.meterId(1);
1507
1508 MeterId dsBpMeterId = MeterId.meterId(2);
1509 MeterId dsOltBpMeterId = MeterId.meterId(2);
1510
1511 doReturn(usBpMeterId).when(component.oltMeterService)
1512 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamBandwidthProfile());
1513 doReturn(usOltBpMeterId).when(component.oltMeterService)
1514 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getUpstreamOltBandwidthProfile());
1515
1516 doReturn(dsBpMeterId).when(component.oltMeterService)
1517 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getDownstreamBandwidthProfile());
1518 doReturn(dsOltBpMeterId).when(component.oltMeterService)
1519 .getMeterIdForBandwidthProfile(removedSub.device.id(), dpuMgmtUti.getDownstreamOltBandwidthProfile());
1520
1521 String[] directions = {FTTB_FLOW_UPSTREAM, FTTB_FLOW_DOWNSTREAM};
1522 for (UniTagInformation uti : uniTagInformationList) {
1523 for (String direction : directions) {
1524 TrafficTreatment.Builder expectedTreatment = DefaultTrafficTreatment.builder();
1525 TrafficSelector.Builder expectedSelectorBuilder = DefaultTrafficSelector.builder();
1526
1527 DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
1528 annotationBuilder.set(FTTB_FLOW_DIRECTION, direction);
1529 annotationBuilder.set(FTTB_SERVICE_NAME, uti.getServiceName());
1530
1531 switch (direction) {
1532 case FTTB_FLOW_UPSTREAM:
1533 expectedSelectorBuilder
1534 .matchInPort(removedSub.port.number())
1535 .matchVlanId(uti.getPonCTag());
1536
1537 expectedTreatment.setVlanId(uti.getPonSTag())
1538 .setOutput(nniPort.number())
1539 .meter(usBpMeterId)
1540 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.ANY,
1541 uti.getTechnologyProfileId(), nniPort.number()), 0L).build();
1542
1543 annotationBuilder.set(UPSTREAM_ONU, usBpMeterId.toString());
1544 annotationBuilder.set(UPSTREAM_OLT, usOltBpMeterId.toString());
1545 break;
1546
1547 case FTTB_FLOW_DOWNSTREAM:
1548 expectedSelectorBuilder
1549 .matchInPort(nniPort.number())
amit.ghosh4f0910e2022-06-20 15:53:21 +02001550 .matchMetadata(uti.getPonSTag().toShort())
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301551 .matchVlanId(uti.getPonSTag());
1552
1553 expectedTreatment.setVlanId(uti.getPonCTag())
1554 .setOutput(removedSub.port.number())
1555 .meter(dsBpMeterId)
1556 .writeMetadata(OltFlowServiceUtils.createMetadata(VlanId.ANY,
1557 uti.getTechnologyProfileId(), removedSub.port.number()), 0L).build();
1558
1559 annotationBuilder.set(DOWNSTREAM_ONU, dsBpMeterId.toString());
1560 annotationBuilder.set(DOWNSTREAM_OLT, dsOltBpMeterId.toString());
1561 break;
1562
1563 default:
1564 return;
1565 }
1566
1567 ForwardingObjective expected = DefaultForwardingObjective.builder()
1568 .withFlag(ForwardingObjective.Flag.VERSATILE)
1569 .withPriority(1000)
1570 .makePermanent()
1571 .withSelector(expectedSelectorBuilder.build())
1572 .withAnnotations(annotationBuilder.build())
1573 .fromApp(testAppId)
1574 .withTreatment(expectedTreatment.build())
1575 .remove();
1576
1577 component.handleSubscriberDataFlows(removedSub.device, removedSub.port,
Gustavo Silva29fb20e2022-05-26 09:59:54 -03001578 FlowOperation.REMOVE, si, DEFAULT_MCAST_SERVICE_NAME_DEFAULT);
Harsh Awasthic1e4bf52022-02-09 14:14:14 +05301579 verify(component.flowObjectiveService, times(1))
1580 .forward(eq(removedSub.device.id()), eq(expected));
1581 }
1582 }
1583 }
amit.ghosh4f0910e2022-06-20 15:53:21 +02001584}