blob: df480a72d61b183c25256700a19a9f0e6c01a5a1 [file] [log] [blame]
Amit Ghosh8951f042017-08-10 13:48:10 +01001/*
2 * Copyright 2017-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
Matteo Scandolo57af5d12019-04-29 17:11:41 -070017package org.opencord.dhcpl2relay.impl;
Amit Ghosh8951f042017-08-10 13:48:10 +010018
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030019import static com.google.common.base.Preconditions.checkState;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.fail;
22
23import java.nio.ByteBuffer;
24import java.nio.charset.StandardCharsets;
25import java.util.ArrayList;
26import java.util.Collection;
27import java.util.Dictionary;
28import java.util.Hashtable;
29import java.util.LinkedList;
30import java.util.List;
31import java.util.Set;
32import java.util.concurrent.Callable;
33import java.util.concurrent.ExecutionException;
34import java.util.concurrent.Future;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030035import java.util.concurrent.ScheduledExecutorService;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070036import java.util.concurrent.ScheduledFuture;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030037import java.util.concurrent.TimeUnit;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070038import java.util.concurrent.TimeoutException;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030039
Amit Ghosh8951f042017-08-10 13:48:10 +010040import org.onlab.packet.BasePacket;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030041import org.onlab.packet.ChassisId;
Amit Ghosh8951f042017-08-10 13:48:10 +010042import org.onlab.packet.DHCP;
Amit Ghosh8951f042017-08-10 13:48:10 +010043import org.onlab.packet.Ethernet;
44import org.onlab.packet.IPv4;
45import org.onlab.packet.Ip4Address;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070046import org.onlab.packet.IpAddress;
Amit Ghosh8951f042017-08-10 13:48:10 +010047import org.onlab.packet.MacAddress;
48import org.onlab.packet.UDP;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030049import org.onlab.packet.VlanId;
Jonathan Hartedbf6422018-05-02 17:30:05 -070050import org.onlab.packet.dhcp.DhcpOption;
Saurav Dasb4e3e102018-10-02 15:31:17 -070051import org.onosproject.core.ApplicationId;
52import org.onosproject.core.CoreServiceAdapter;
53import org.onosproject.core.DefaultApplicationId;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030054import org.onosproject.event.DefaultEventSinkRegistry;
55import org.onosproject.event.Event;
56import org.onosproject.event.EventDeliveryService;
57import org.onosproject.event.EventSink;
58import org.onosproject.mastership.MastershipServiceAdapter;
59import org.onosproject.net.AnnotationKeys;
60import org.onosproject.net.Annotations;
Amit Ghosh8951f042017-08-10 13:48:10 +010061import org.onosproject.net.ConnectPoint;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030062import org.onosproject.net.DefaultAnnotations;
63import org.onosproject.net.DefaultDevice;
64import org.onosproject.net.DefaultHost;
65import org.onosproject.net.Device;
66import org.onosproject.net.DeviceId;
67import org.onosproject.net.Element;
68import org.onosproject.net.Host;
69import org.onosproject.net.HostId;
70import org.onosproject.net.HostLocation;
71import org.onosproject.net.Port;
72import org.onosproject.net.PortNumber;
73import org.onosproject.net.device.DeviceServiceAdapter;
74import org.onosproject.net.host.HostServiceAdapter;
Amit Ghosh8951f042017-08-10 13:48:10 +010075import org.onosproject.net.packet.DefaultInboundPacket;
76import org.onosproject.net.packet.DefaultPacketContext;
77import org.onosproject.net.packet.InboundPacket;
78import org.onosproject.net.packet.OutboundPacket;
79import org.onosproject.net.packet.PacketContext;
80import org.onosproject.net.packet.PacketProcessor;
81import org.onosproject.net.packet.PacketServiceAdapter;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030082import org.onosproject.net.provider.ProviderId;
Saurav Das45861d42020-10-07 00:03:23 -070083import org.opencord.dhcpl2relay.impl.packet.DhcpOption82Data;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030084import org.opencord.sadis.BandwidthProfileInformation;
85import org.opencord.sadis.BaseInformationService;
86import org.opencord.sadis.SadisService;
87import org.opencord.sadis.SubscriberAndDeviceInformation;
Gamze Abakaa64b3bc2020-01-31 06:51:43 +000088import org.opencord.sadis.UniTagInformation;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030089import org.osgi.framework.Bundle;
90import org.osgi.framework.BundleContext;
91import org.osgi.framework.ServiceReference;
92import org.osgi.service.component.ComponentContext;
93import org.osgi.service.component.ComponentInstance;
Amit Ghosh8951f042017-08-10 13:48:10 +010094import org.slf4j.Logger;
95import org.slf4j.LoggerFactory;
96
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070097import com.google.common.collect.ImmutableSet;
98
Amit Ghosh8951f042017-08-10 13:48:10 +010099
100/**
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700101 * Common methods for DHCP app testing.
Amit Ghosh8951f042017-08-10 13:48:10 +0100102 */
103public class DhcpL2RelayTestBase {
104 private final Logger log = LoggerFactory.getLogger(getClass());
105
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000106 static final VlanId CLIENT_C_TAG = VlanId.vlanId((short) 2);
107 static final VlanId CLIENT_S_TAG = VlanId.vlanId((short) 4);
108 static final short CLIENT_C_PBIT = 7;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300109 static final String CLIENT_ID_1 = "SUBSCRIBER_ID_1";
110 static final String CLIENT_NAS_PORT_ID = "PON 1/1";
111 static final String CLIENT_CIRCUIT_ID = "CIR-PON 1/1";
Saurav Das45861d42020-10-07 00:03:23 -0700112 static final String CLIENT32_CIRCUIT_ID = "";
113 static final String CLIENT4112_CIRCUIT_ID = null;
114 public static final String CLIENT_REMOTE_ID = "I am an RG";
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000115 static final short NOT_PROVIDED = 0;
Amit Ghosh8951f042017-08-10 13:48:10 +0100116
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300117 static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
118 static final MacAddress SERVER_MAC = MacAddress.valueOf("bb:bb:bb:bb:bb:bb");
119 static final String DESTINATION_ADDRESS_IP = "1.1.1.1";
120 static final String DHCP_CLIENT_IP_ADDRESS = "2.2.2.2";
121 static final int UPLINK_PORT = 5;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700122 static final int CLIENT_PORT = 1;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300123
124 static final String EXPECTED_IP = "10.2.0.2";
125 static final String OLT_DEV_ID = "of:00000000000000aa";
126 static final DeviceId DEVICE_ID_1 = DeviceId.deviceId(OLT_DEV_ID);
127 static final int TRANSACTION_ID = 1000;
128 static final String SCHEME_NAME = "dhcpl2relay";
129 static final MacAddress OLT_MAC_ADDRESS = MacAddress.valueOf("01:02:03:04:05:06");
130
131 static final ConnectPoint SERVER_CONNECT_POINT =
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700132 ConnectPoint.deviceConnectPoint("of:00000000000000aa/" +
133 String.valueOf(UPLINK_PORT));
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300134
135 static final DefaultAnnotations DEVICE_ANNOTATIONS = DefaultAnnotations.builder()
136 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build();
Amit Ghosh8951f042017-08-10 13:48:10 +0100137
Saurav Das45861d42020-10-07 00:03:23 -0700138
Amit Ghosh8951f042017-08-10 13:48:10 +0100139 List<BasePacket> savedPackets = new LinkedList<>();
140 PacketProcessor packetProcessor;
141
142
143 /**
144 * Saves the given packet onto the saved packets list.
145 *
146 * @param packet packet to save
147 */
148 void savePacket(BasePacket packet) {
149 savedPackets.add(packet);
150 }
151
152 BasePacket getPacket() {
153 return savedPackets.remove(0);
154 }
155
156 /**
Saurav Dasb4e3e102018-10-02 15:31:17 -0700157 * Mock core service adaptor that provides an appId.
158 */
159 class MockCoreServiceAdapter extends CoreServiceAdapter {
160
161 @Override
162 public ApplicationId registerApplication(String name) {
163 return new DefaultApplicationId(10, name);
164 }
165 }
166
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300167 class MockDeviceService extends DeviceServiceAdapter {
168
169 private ProviderId providerId = new ProviderId("of", "foo");
170 private final Device device1 = new DhcpL2RelayTestBase.MockDevice(providerId, DEVICE_ID_1, Device.Type.SWITCH,
171 "foo.inc", "0", "0", OLT_DEV_ID, new ChassisId(),
172 DEVICE_ANNOTATIONS);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700173 private final Device otherDevice = new DhcpL2RelayTestBase.MockDevice(
174 providerId,
175 DeviceId.deviceId("of:0000b86a974385f7"),
176 Device.Type.SWITCH,
177 "foo.inc", "0", "0", "EC1838000853", new ChassisId(),
178 DEVICE_ANNOTATIONS);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300179 @Override
180 public Device getDevice(DeviceId devId) {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700181 if (devId.equals(DEVICE_ID_1)) {
182 return device1;
183 } else {
184 return otherDevice;
185 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300186 }
187
188 @Override
189 public Port getPort(ConnectPoint cp) {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700190 return new DhcpL2RelayTestBase.MockPort(cp);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300191 }
192
193 @Override
194 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700195 return new DhcpL2RelayTestBase.MockPort(new ConnectPoint(deviceId,
196 portNumber));
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300197 }
198
199 @Override
200 public boolean isAvailable(DeviceId d) {
201 return true;
202 }
203 }
204
205 class MockDevice extends DefaultDevice {
206
207 public MockDevice(ProviderId providerId, DeviceId id, Type type,
208 String manufacturer, String hwVersion, String swVersion,
209 String serialNumber, ChassisId chassisId, Annotations... annotations) {
210 super(providerId, id, type, manufacturer, hwVersion, swVersion, serialNumber,
211 chassisId, annotations);
212 }
213 }
214
215 class MockHostService extends HostServiceAdapter {
216
217 @Override
218 public Set<Host> getHostsByMac(MacAddress mac) {
219
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700220 HostLocation loc = new HostLocation(DEVICE_ID_1, PortNumber
221 .portNumber(CLIENT_PORT), 0);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300222
223 IpAddress ip = IpAddress.valueOf("10.100.200.10");
224
225 Host h = new DefaultHost(ProviderId.NONE, HostId.hostId(mac, VlanId.NONE),
226 mac, VlanId.NONE, loc, ImmutableSet.of(ip));
227
228 return ImmutableSet.of(h);
229 }
230 }
231
232 class MockMastershipService extends MastershipServiceAdapter {
233 @Override
234 public boolean isLocalMaster(DeviceId d) {
235 return true;
236 }
237 }
238
239 class MockPort implements Port {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700240 private ConnectPoint cp;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300241
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700242 public MockPort(ConnectPoint cp) {
243 this.cp = cp;
244 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300245 @Override
246 public boolean isEnabled() {
247 return true;
248 }
249 @Override
250 public long portSpeed() {
251 return 1000;
252 }
253 @Override
254 public Element element() {
255 return null;
256 }
257 @Override
258 public PortNumber number() {
259 return null;
260 }
261 @Override
262 public Annotations annotations() {
263 return new MockAnnotations();
264 }
265 @Override
266 public Type type() {
267 return Port.Type.FIBER;
268 }
269
270 private class MockAnnotations implements Annotations {
271
272 @Override
273 public String value(String val) {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700274 if (cp.port().toLong() == 32) {
275 return "ALPHe3d1cea3-1";
276 } else if (cp.port().toLong() == 4112) {
277 return "ALPHe3d1ceb7-1";
278 } else {
279 return "PON 1/1";
280 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300281 }
282 @Override
283 public Set<String> keys() {
284 return null;
285 }
286 }
287 }
288
Saurav Dasb4e3e102018-10-02 15:31:17 -0700289 /**
Amit Ghosh8951f042017-08-10 13:48:10 +0100290 * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
291 */
292 class MockPacketService extends PacketServiceAdapter {
293
294 @Override
295 public void addProcessor(PacketProcessor processor, int priority) {
296 packetProcessor = processor;
297 }
298
299 @Override
300 public void emit(OutboundPacket packet) {
301 try {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530302 Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
Amit Ghosh8951f042017-08-10 13:48:10 +0100303 0, packet.data().array().length);
304 savePacket(eth);
305 } catch (Exception e) {
306 fail(e.getMessage());
307 }
308 }
309 }
310
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300311 class MockSadisService implements SadisService {
312 @Override
313 public BaseInformationService<SubscriberAndDeviceInformation> getSubscriberInfoService() {
314 return new DhcpL2RelayTestBase.MockSubService();
315 }
316
317 @Override
318 public BaseInformationService<BandwidthProfileInformation> getBandwidthProfileService() {
319 return null;
320 }
321 }
322
323 class MockSubService implements BaseInformationService<SubscriberAndDeviceInformation> {
324 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation device =
325 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(OLT_DEV_ID, VlanId.NONE, VlanId.NONE, null,
326 null, OLT_MAC_ADDRESS, Ip4Address.valueOf("10.10.10.10"), UPLINK_PORT);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700327 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation otherDevice =
328 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(
329 "EC1838000853", VlanId.NONE, VlanId.NONE, null,
330 null, OLT_MAC_ADDRESS, Ip4Address.valueOf("10.10.10.10"), UPLINK_PORT);
331
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300332 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation sub =
333 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(CLIENT_ID_1, CLIENT_C_TAG,
334 CLIENT_S_TAG, CLIENT_NAS_PORT_ID, CLIENT_CIRCUIT_ID, null, null, -1);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700335 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation sub32 =
336 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation("ALPHe3d1cea3-1", VlanId.vlanId((short) 801),
Saurav Das45861d42020-10-07 00:03:23 -0700337 VlanId.vlanId((short) 111), CLIENT_NAS_PORT_ID, CLIENT32_CIRCUIT_ID, null, null, -1);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700338 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation sub4112 =
339 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation("ALPHe3d1ceb7-1", VlanId.vlanId((short) 101),
Saurav Das45861d42020-10-07 00:03:23 -0700340 VlanId.vlanId((short) 222), CLIENT_NAS_PORT_ID, CLIENT4112_CIRCUIT_ID, null, null, -1);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300341 @Override
342 public SubscriberAndDeviceInformation get(String id) {
343 if (id.equals(OLT_DEV_ID)) {
344 return device;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700345 } else if (id.equals("EC1838000853")) {
346 return otherDevice;
347 } else if (id.equals("ALPHe3d1cea3-1")) {
348 return sub32;
349 } else if (id.equals("ALPHe3d1ceb7-1")) {
350 return sub4112;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300351 } else {
352 return sub;
353 }
354 }
355
356 @Override
357 public void invalidateAll() {}
358 @Override
359 public void invalidateId(String id) {}
360 @Override
361 public SubscriberAndDeviceInformation getfromCache(String id) {
362 return null;
363 }
364 }
365
366 class MockSubscriberAndDeviceInformation extends SubscriberAndDeviceInformation {
367
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000368 MockSubscriberAndDeviceInformation(String id, VlanId cTag,
369 VlanId sTag, String nasPortId,
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300370 String circuitId, MacAddress hardId,
371 Ip4Address ipAddress, int uplinkPort) {
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300372 this.setHardwareIdentifier(hardId);
373 this.setId(id);
374 this.setIPAddress(ipAddress);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300375 this.setNasPortId(nasPortId);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300376 this.setUplinkPort(uplinkPort);
Saurav Das45861d42020-10-07 00:03:23 -0700377 this.setCircuitId(circuitId);
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000378
379 List<UniTagInformation> uniTagInformationList = new ArrayList<>();
380
Saurav Das45861d42020-10-07 00:03:23 -0700381 UniTagInformation.Builder b = new UniTagInformation.Builder()
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000382 .setPonCTag(cTag)
383 .setPonSTag(sTag)
384 .setUsPonCTagPriority(CLIENT_C_PBIT)
Saurav Das45861d42020-10-07 00:03:23 -0700385 .setIsDhcpRequired(true);
386
387 if (id.equals("ALPHe3d1ceb7-1")) {
388 // null remoteId, ds pbit is defined
389 b.setDsPonCTagPriority(5);
390 } else {
391 this.setRemoteId(CLIENT_REMOTE_ID);
392 }
393
394 uniTagInformationList.add(b.build());
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700395
396 if (id.equals("ALPHe3d1cea3-1")) {
397 // a second service on the same UNI
Saurav Das45861d42020-10-07 00:03:23 -0700398 UniTagInformation uniTagInformation = new UniTagInformation.Builder()
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700399 .setPonCTag(VlanId.vlanId(((short) (cTag.toShort() + 1))))
400 .setPonSTag(sTag)
401 .setUsPonCTagPriority(CLIENT_C_PBIT)
402 .setIsDhcpRequired(true)
403 .build();
404 uniTagInformationList.add(uniTagInformation);
405 }
406
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000407 this.setUniTagList(uniTagInformationList);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300408 }
409 }
410
411 class MockComponentContext implements ComponentContext {
412
413 @Override
414 public Dictionary<String, Object> getProperties() {
415 Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
416 cfgDict.put("publishCountersRate", 10);
417 return cfgDict;
418 }
419
420 @Override
421 public Object locateService(String name) {
422 // TODO Auto-generated method stub
423 return null;
424 }
425
426 @Override
427 public Object locateService(String name, ServiceReference reference) {
428 // TODO Auto-generated method stub
429 return null;
430 }
431
432 @Override
433 public Object[] locateServices(String name) {
434 // TODO Auto-generated method stub
435 return null;
436 }
437
438 @Override
439 public BundleContext getBundleContext() {
440 // TODO Auto-generated method stub
441 return null;
442 }
443
444 @Override
445 public Bundle getUsingBundle() {
446 // TODO Auto-generated method stub
447 return null;
448 }
449
450 @Override
451 public ComponentInstance getComponentInstance() {
452 // TODO Auto-generated method stub
453 return null;
454 }
455
456 @Override
457 public void enableComponent(String name) {
458 // TODO Auto-generated method stub
459 }
460
461 @Override
462 public void disableComponent(String name) {
463 // TODO Auto-generated method stub
464 }
465
466 @Override
467 public ServiceReference getServiceReference() {
468 // TODO Auto-generated method stub
469 return null;
470 }
471 }
472
473
Amit Ghosh8951f042017-08-10 13:48:10 +0100474 /**
475 * Mocks the DefaultPacketContext.
476 */
477 final class TestPacketContext extends DefaultPacketContext {
478
479 private TestPacketContext(long time, InboundPacket inPkt,
480 OutboundPacket outPkt, boolean block) {
481 super(time, inPkt, outPkt, block);
482 }
483
484 @Override
485 public void send() {
486 // We don't send anything out.
487 }
488 }
489
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300490 public static class TestEventDispatcher extends DefaultEventSinkRegistry
491 implements EventDeliveryService {
492 @Override
493 @SuppressWarnings("unchecked")
494 public synchronized void post(Event event) {
495 EventSink sink = getSink(event.getClass());
496 checkState(sink != null, "No sink for event %s", event);
497 sink.process(event);
498 }
499
500 @Override
501 public void setDispatchTimeLimit(long millis) {
502 }
503
504 @Override
505 public long getDispatchTimeLimit() {
506 return 0;
507 }
508 }
509
510 /**
511 * Creates a mock object for a scheduled executor service.
512 *
513 */
514 public static final class MockExecutor implements ScheduledExecutorService {
515 private ScheduledExecutorService executor;
516
517 MockExecutor(ScheduledExecutorService executor) {
518 this.executor = executor;
519 }
520
521 String lastMethodCalled = "";
522 long lastInitialDelay;
523 long lastDelay;
524 TimeUnit lastUnit;
525
526 public void assertLastMethodCalled(String method, long initialDelay, long delay, TimeUnit unit) {
527 assertEquals(method, lastMethodCalled);
528 assertEquals(initialDelay, lastInitialDelay);
529 assertEquals(delay, lastDelay);
530 assertEquals(unit, lastUnit);
531 }
532
533 @Override
534 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
535 lastMethodCalled = "scheduleRunnable";
536 lastDelay = delay;
537 lastUnit = unit;
538 return null;
539 }
540
541 @Override
542 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
543 lastMethodCalled = "scheduleCallable";
544 lastDelay = delay;
545 lastUnit = unit;
546 return null;
547 }
548
549 @Override
550 public ScheduledFuture<?> scheduleAtFixedRate(
551 Runnable command, long initialDelay, long period, TimeUnit unit) {
552 lastMethodCalled = "scheduleAtFixedRate";
553 lastInitialDelay = initialDelay;
554 lastDelay = period;
555 lastUnit = unit;
556 return null;
557 }
558
559 @Override
560 public ScheduledFuture<?> scheduleWithFixedDelay(
561 Runnable command, long initialDelay, long delay, TimeUnit unit) {
562 lastMethodCalled = "scheduleWithFixedDelay";
563 lastInitialDelay = initialDelay;
564 lastDelay = delay;
565 lastUnit = unit;
566 command.run();
567 return null;
568 }
569
570 @Override
571 public boolean awaitTermination(long timeout, TimeUnit unit) {
572 throw new UnsupportedOperationException();
573 }
574
575 @Override
576 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
577 throws InterruptedException {
578 throw new UnsupportedOperationException();
579 }
580
581 @Override
582 public <T> List<Future<T>> invokeAll(
583 Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
584 throws InterruptedException {
585 throw new UnsupportedOperationException();
586 }
587
588 @Override
589 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
590 throws ExecutionException, InterruptedException {
591 throw new UnsupportedOperationException();
592 }
593
594 @Override
595 public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
596 throws ExecutionException, InterruptedException, TimeoutException {
597 throw new UnsupportedOperationException();
598 }
599
600 @Override
601 public boolean isShutdown() {
602 throw new UnsupportedOperationException();
603 }
604
605 @Override
606 public boolean isTerminated() {
607 throw new UnsupportedOperationException();
608 }
609
610 @Override
611 public void shutdown() {
612 throw new UnsupportedOperationException();
613 }
614
615 @Override
616 public List<Runnable> shutdownNow() {
617 return null;
618 }
619
620 @Override
621 public <T> Future<T> submit(Callable<T> task) {
622 throw new UnsupportedOperationException();
623 }
624
625 @Override
626 public Future<?> submit(Runnable task) {
627 throw new UnsupportedOperationException();
628 }
629
630 @Override
631 public <T> Future<T> submit(Runnable task, T result) {
632 throw new UnsupportedOperationException();
633 }
634
635 @Override
636 public void execute(Runnable command) {
637 throw new UnsupportedOperationException();
638 }
639 }
640
Amit Ghosh8951f042017-08-10 13:48:10 +0100641 /**
642 * Sends an Ethernet packet to the process method of the Packet Processor.
643 *
644 * @param pkt Ethernet packet
645 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530646 void sendPacket(Ethernet pkt, ConnectPoint cp) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100647 final ByteBuffer byteBuffer = ByteBuffer.wrap(pkt.serialize());
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530648 InboundPacket inPacket = new DefaultInboundPacket(cp, pkt, byteBuffer);
Amit Ghosh8951f042017-08-10 13:48:10 +0100649
650 PacketContext context = new TestPacketContext(127L, inPacket, null, false);
651 packetProcessor.process(context);
652 }
653
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700654 private Ethernet constructEthernetPacket(MacAddress srcMac, MacAddress dstMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100655 String dstIp, byte dhcpReqRsp,
656 MacAddress clientHwAddress,
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700657 Ip4Address dhcpClientIpAddress,
658 VlanId clientVlan, short clientPbit) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100659 // Ethernet Frame.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530660 Ethernet ethPkt = new Ethernet();
661 ethPkt.setSourceMACAddress(srcMac);
662 ethPkt.setDestinationMACAddress(dstMac);
Amit Ghosh8951f042017-08-10 13:48:10 +0100663 ethPkt.setEtherType(Ethernet.TYPE_IPV4);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700664 ethPkt.setVlanID(clientVlan.toShort());
665 ethPkt.setPriorityCode((byte) clientPbit);
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000666
667 if (DHCP.OPCODE_REPLY == dhcpReqRsp) {
668 ethPkt.setQinQPriorityCode((byte) 3);
669 ethPkt.setQinQVID((short) 4);
670 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100671
672 // IP Packet
673 IPv4 ipv4Reply = new IPv4();
674 ipv4Reply.setSourceAddress(0);
675 ipv4Reply.setDestinationAddress(dstIp);
676
677 ipv4Reply.setTtl((byte) 127);
678
679 // UDP Datagram.
680 UDP udpReply = new UDP();
681 udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
682 udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
683
684 // DHCP Payload.
685 DHCP dhcpReply = new DHCP();
686 dhcpReply.setOpCode(dhcpReqRsp);
687
688 dhcpReply.setYourIPAddress(dhcpClientIpAddress.toInt());
689 dhcpReply.setServerIPAddress(0);
690
691 final byte[] serverNameBytes = new byte[64];
692 String result = new String(serverNameBytes, StandardCharsets.US_ASCII).trim();
693 dhcpReply.setServerName(result);
694
695 final byte[] bootFileBytes = new byte[128];
696 String result1 = new String(bootFileBytes, StandardCharsets.US_ASCII).trim();
697 dhcpReply.setBootFileName(result1);
698
699 dhcpReply.setTransactionId(TRANSACTION_ID);
700 dhcpReply.setClientHardwareAddress(clientHwAddress.toBytes());
701 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
702 dhcpReply.setHardwareAddressLength((byte) 6);
703
704 udpReply.setPayload(dhcpReply);
705 ipv4Reply.setPayload(udpReply);
706 ethPkt.setPayload(ipv4Reply);
707
708 return ethPkt;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700709
710 }
711
712 /**
713 * Constructs an Ethernet packet with IP/UDP/DHCP payload and client
714 * VLAN information.
715 *
716 * @return Ethernet packet
717 */
718 private Ethernet construcEthernetPacket(MacAddress srcMac, MacAddress dstMac,
719 String dstIp, byte dhcpReqRsp,
720 MacAddress clientHwAddress,
721 Ip4Address dhcpClientIpAddress) {
722 return constructEthernetPacket(srcMac, dstMac, dstIp, dhcpReqRsp,
723 clientHwAddress, dhcpClientIpAddress,
724 CLIENT_C_TAG, CLIENT_C_PBIT);
725
Amit Ghosh8951f042017-08-10 13:48:10 +0100726 }
727
728 /**
729 * Constructs DHCP Discover Packet.
730 *
731 * @return Ethernet packet
732 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530733 Ethernet constructDhcpDiscoverPacket(MacAddress clientMac) {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530734 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Saurav Das45861d42020-10-07 00:03:23 -0700735 "255.255.255.255",
736 DHCP.OPCODE_REQUEST, clientMac,
737 Ip4Address.valueOf("0.0.0.0"));
Amit Ghosh8951f042017-08-10 13:48:10 +0100738
739 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
740 UDP udpPacket = (UDP) ipv4Packet.getPayload();
741 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
742
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700743 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPDISCOVER));
Saurav Das45861d42020-10-07 00:03:23 -0700744 log.info("Sending discover packet {}", dhcpPacket.getOptions());
Amit Ghosh8951f042017-08-10 13:48:10 +0100745
746 return pkt;
747 }
748
749 /**
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700750 * Constructs DHCP Discover Packet with client VLAN information.
751 *
752 * @return Ethernet packet
753 */
754 Ethernet constructDhcpDiscoverPacket(MacAddress clientMac, VlanId clientVlan,
755 short clientPbit) {
756 Ethernet pkt = constructEthernetPacket(clientMac, MacAddress.BROADCAST,
757 "255.255.255.255", DHCP.OPCODE_REQUEST, clientMac,
758 Ip4Address.valueOf("0.0.0.0"), clientVlan, clientPbit);
759
760 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
761 UDP udpPacket = (UDP) ipv4Packet.getPayload();
762 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
763
764 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPDISCOVER));
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700765 return pkt;
766 }
767
768 /**
Amit Ghosh8951f042017-08-10 13:48:10 +0100769 * Constructs DHCP Request Packet.
770 *
771 * @return Ethernet packet
772 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530773 Ethernet constructDhcpRequestPacket(MacAddress clientMac) {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530774 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700775 "255.255.255.255", DHCP.OPCODE_REQUEST, clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100776 Ip4Address.valueOf("0.0.0.0"));
777
778 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
779 UDP udpPacket = (UDP) ipv4Packet.getPayload();
780 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
781
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700782 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPREQUEST));
Amit Ghosh8951f042017-08-10 13:48:10 +0100783
784 return pkt;
785 }
786
787 /**
788 * Constructs DHCP Offer Packet.
789 *
790 * @return Ethernet packet
791 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530792 Ethernet constructDhcpOfferPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100793 String ipAddress, String dhcpClientIpAddress) {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530794 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100795 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
796
797 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
798 UDP udpPacket = (UDP) ipv4Packet.getPayload();
799 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
800
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700801 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPOFFER));
Saurav Das45861d42020-10-07 00:03:23 -0700802 log.info("Sending offer packet {}", dhcpPacket.getOptions());
Amit Ghosh8951f042017-08-10 13:48:10 +0100803 return pkt;
804 }
805
806 /**
807 * Constructs DHCP Ack Packet.
808 *
809 * @return Ethernet packet
810 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530811 Ethernet constructDhcpAckPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100812 String ipAddress, String dhcpClientIpAddress) {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530813 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100814 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
815
816 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
817 UDP udpPacket = (UDP) ipv4Packet.getPayload();
818 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
819
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700820 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPACK));
Amit Ghosh8951f042017-08-10 13:48:10 +0100821
822 return pkt;
823 }
824
825 /**
Arjun E K05ad20b2020-03-13 13:25:17 +0000826 * Constructs DHCP Nak Packet.
827 *
828 * @return Ethernet packet
829 */
830 Ethernet constructDhcpNakPacket(MacAddress servMac, MacAddress clientMac,
Saurav Das45861d42020-10-07 00:03:23 -0700831 String ipAddress, String dhcpClientIpAddress,
832 VlanId clientVlan, short clientPcp) {
Arjun E K05ad20b2020-03-13 13:25:17 +0000833
Saurav Das45861d42020-10-07 00:03:23 -0700834 Ethernet pkt = constructEthernetPacket(servMac, clientMac, ipAddress,
835 DHCP.OPCODE_REPLY, clientMac,
836 Ip4Address.valueOf(dhcpClientIpAddress),
837 clientVlan, clientPcp);
Arjun E K05ad20b2020-03-13 13:25:17 +0000838
839 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
840 UDP udpPacket = (UDP) ipv4Packet.getPayload();
841 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
842
843 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPNAK));
844
845 return pkt;
846 }
847
848 /**
849 * Constructs DHCP Decline Packet.
850 *
851 * @return Ethernet packet
852 */
853 Ethernet constructDhcpDeclinePacket(MacAddress clientMac) {
854
855 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700856 "255.255.255.255", DHCP.OPCODE_REQUEST, clientMac,
Arjun E K05ad20b2020-03-13 13:25:17 +0000857 Ip4Address.valueOf("0.0.0.0"));
858
859 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
860 UDP udpPacket = (UDP) ipv4Packet.getPayload();
861 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
862
863 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPDECLINE));
864
865 return pkt;
866 }
867
868 /**
Amit Ghosh8951f042017-08-10 13:48:10 +0100869 * Constructs DHCP Discover Options.
870 *
871 * @return Ethernet packet
872 */
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700873 private List<DhcpOption> constructDhcpOptions(DHCP.MsgType packetType) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100874
875 // DHCP Options.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700876 DhcpOption option = new DhcpOption();
877 List<DhcpOption> optionList = new ArrayList<>();
Amit Ghosh8951f042017-08-10 13:48:10 +0100878
879
880 // DHCP Message Type.
881 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
882 option.setLength((byte) 1);
883 byte[] optionData = {(byte) packetType.getValue()};
884 option.setData(optionData);
885 optionList.add(option);
886
887 // DHCP Requested IP.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700888 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100889 option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
890 option.setLength((byte) 4);
891 optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
892 option.setData(optionData);
893 optionList.add(option);
894
Saurav Das45861d42020-10-07 00:03:23 -0700895 // Tests app defined Option82
896 if (packetType.equals(DHCP.MsgType.DHCPOFFER)) {
897 option = new DhcpOption();
898 option.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
899 DhcpOption82Data option82 = new DhcpOption82Data();
900 option82.setAgentCircuitId(OLT_DEV_ID + "/" + CLIENT_PORT + ":vlan"
901 + CLIENT_C_TAG + ":pcp" + CLIENT_C_PBIT);
902 option82.setAgentRemoteId("bababababa");
903 option.setData(option82.toByteArray());
904 option.setLength(option82.length());
905 log.info("Added option82 {}", option);
906 optionList.add(option);
907 }
908 // Tests operator configured Option82, resulting in host lookup
909 if (packetType.equals(DHCP.MsgType.DHCPACK)) {
910 option = new DhcpOption();
911 option.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
912 DhcpOption82Data option82 = new DhcpOption82Data();
913 option82.setAgentCircuitId(CLIENT_CIRCUIT_ID);
914 option82.setAgentRemoteId(CLIENT_REMOTE_ID);
915 option.setData(option82.toByteArray());
916 option.setLength(option82.length());
917 log.info("Added option82 {}", option);
918 optionList.add(option);
919 }
920 // Tests app-defined option82, but uses incorrect connectPoint - packet
921 // should still be forwarded to this connectPoint (ie without host lookup).
922 // Also pbit in circuitId is -1, which means original pbit should be retained
923 // Finally remoteId is missing
924 if (packetType.equals(DHCP.MsgType.DHCPNAK)) {
925 option = new DhcpOption();
926 option.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
927 DhcpOption82Data option82 = new DhcpOption82Data();
928 option82.setAgentCircuitId("of:0000b86a974385f7/32" + ":vlan"
929 + VlanId.vlanId((short) 111) + ":pcp-1");
930 option.setData(option82.toByteArray());
931 option.setLength(option82.length());
932 log.info("Added option82 {}", option);
933 optionList.add(option);
934 }
935
Amit Ghosh8951f042017-08-10 13:48:10 +0100936 // End Option.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700937 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100938 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
939 option.setLength((byte) 1);
940 optionList.add(option);
941
942 return optionList;
943 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300944}