blob: bae3575fc1962f7822e4a25debd998b5d394dd46 [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;
35import java.util.concurrent.ScheduledFuture;
36import java.util.concurrent.ScheduledExecutorService;
37import java.util.concurrent.TimeoutException;
38import java.util.concurrent.TimeUnit;
39
40import com.google.common.collect.ImmutableSet;
Amit Ghosh8951f042017-08-10 13:48:10 +010041import org.onlab.packet.BasePacket;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030042import org.onlab.packet.ChassisId;
Amit Ghosh8951f042017-08-10 13:48:10 +010043import org.onlab.packet.DHCP;
Amit Ghosh8951f042017-08-10 13:48:10 +010044import org.onlab.packet.Ethernet;
45import org.onlab.packet.IPv4;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030046import org.onlab.packet.IpAddress;
Amit Ghosh8951f042017-08-10 13:48:10 +010047import org.onlab.packet.Ip4Address;
48import org.onlab.packet.MacAddress;
49import org.onlab.packet.UDP;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030050import org.onlab.packet.VlanId;
Jonathan Hartedbf6422018-05-02 17:30:05 -070051import org.onlab.packet.dhcp.DhcpOption;
Saurav Dasb4e3e102018-10-02 15:31:17 -070052import org.onosproject.core.ApplicationId;
53import org.onosproject.core.CoreServiceAdapter;
54import org.onosproject.core.DefaultApplicationId;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030055import org.onosproject.event.DefaultEventSinkRegistry;
56import org.onosproject.event.Event;
57import org.onosproject.event.EventDeliveryService;
58import org.onosproject.event.EventSink;
59import org.onosproject.mastership.MastershipServiceAdapter;
60import org.onosproject.net.AnnotationKeys;
61import org.onosproject.net.Annotations;
Amit Ghosh8951f042017-08-10 13:48:10 +010062import org.onosproject.net.ConnectPoint;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030063import org.onosproject.net.DefaultAnnotations;
64import org.onosproject.net.DefaultDevice;
65import org.onosproject.net.DefaultHost;
66import org.onosproject.net.Device;
67import org.onosproject.net.DeviceId;
68import org.onosproject.net.Element;
69import org.onosproject.net.Host;
70import org.onosproject.net.HostId;
71import org.onosproject.net.HostLocation;
72import org.onosproject.net.Port;
73import org.onosproject.net.PortNumber;
74import org.onosproject.net.device.DeviceServiceAdapter;
75import org.onosproject.net.host.HostServiceAdapter;
Amit Ghosh8951f042017-08-10 13:48:10 +010076import org.onosproject.net.packet.DefaultInboundPacket;
77import org.onosproject.net.packet.DefaultPacketContext;
78import org.onosproject.net.packet.InboundPacket;
79import org.onosproject.net.packet.OutboundPacket;
80import org.onosproject.net.packet.PacketContext;
81import org.onosproject.net.packet.PacketProcessor;
82import org.onosproject.net.packet.PacketServiceAdapter;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030083import org.onosproject.net.provider.ProviderId;
84import org.opencord.sadis.BandwidthProfileInformation;
85import org.opencord.sadis.BaseInformationService;
86import org.opencord.sadis.SadisService;
87import org.opencord.sadis.SubscriberAndDeviceInformation;
88import org.osgi.framework.Bundle;
89import org.osgi.framework.BundleContext;
90import org.osgi.framework.ServiceReference;
91import org.osgi.service.component.ComponentContext;
92import org.osgi.service.component.ComponentInstance;
Amit Ghosh8951f042017-08-10 13:48:10 +010093import org.slf4j.Logger;
94import org.slf4j.LoggerFactory;
95
Amit Ghosh8951f042017-08-10 13:48:10 +010096
97/**
98 * Common methods for AAA app testing.
99 */
100public class DhcpL2RelayTestBase {
101 private final Logger log = LoggerFactory.getLogger(getClass());
102
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300103 static final VlanId CLIENT_C_TAG = VlanId.vlanId((short) 999);
104 static final VlanId CLIENT_S_TAG = VlanId.vlanId((short) 111);
105 static final String CLIENT_ID_1 = "SUBSCRIBER_ID_1";
106 static final String CLIENT_NAS_PORT_ID = "PON 1/1";
107 static final String CLIENT_CIRCUIT_ID = "CIR-PON 1/1";
Amit Ghosh8951f042017-08-10 13:48:10 +0100108
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300109 static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
110 static final MacAddress SERVER_MAC = MacAddress.valueOf("bb:bb:bb:bb:bb:bb");
111 static final String DESTINATION_ADDRESS_IP = "1.1.1.1";
112 static final String DHCP_CLIENT_IP_ADDRESS = "2.2.2.2";
113 static final int UPLINK_PORT = 5;
114
115 static final String EXPECTED_IP = "10.2.0.2";
116 static final String OLT_DEV_ID = "of:00000000000000aa";
117 static final DeviceId DEVICE_ID_1 = DeviceId.deviceId(OLT_DEV_ID);
118 static final int TRANSACTION_ID = 1000;
119 static final String SCHEME_NAME = "dhcpl2relay";
120 static final MacAddress OLT_MAC_ADDRESS = MacAddress.valueOf("01:02:03:04:05:06");
121
122 static final ConnectPoint SERVER_CONNECT_POINT =
123 ConnectPoint.deviceConnectPoint("of:00000000000000aa/5");
124
125 static final DefaultAnnotations DEVICE_ANNOTATIONS = DefaultAnnotations.builder()
126 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build();
Amit Ghosh8951f042017-08-10 13:48:10 +0100127
128 List<BasePacket> savedPackets = new LinkedList<>();
129 PacketProcessor packetProcessor;
130
131
132 /**
133 * Saves the given packet onto the saved packets list.
134 *
135 * @param packet packet to save
136 */
137 void savePacket(BasePacket packet) {
138 savedPackets.add(packet);
139 }
140
141 BasePacket getPacket() {
142 return savedPackets.remove(0);
143 }
144
145 /**
Saurav Dasb4e3e102018-10-02 15:31:17 -0700146 * Mock core service adaptor that provides an appId.
147 */
148 class MockCoreServiceAdapter extends CoreServiceAdapter {
149
150 @Override
151 public ApplicationId registerApplication(String name) {
152 return new DefaultApplicationId(10, name);
153 }
154 }
155
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300156 class MockDeviceService extends DeviceServiceAdapter {
157
158 private ProviderId providerId = new ProviderId("of", "foo");
159 private final Device device1 = new DhcpL2RelayTestBase.MockDevice(providerId, DEVICE_ID_1, Device.Type.SWITCH,
160 "foo.inc", "0", "0", OLT_DEV_ID, new ChassisId(),
161 DEVICE_ANNOTATIONS);
162
163 @Override
164 public Device getDevice(DeviceId devId) {
165 return device1;
166
167 }
168
169 @Override
170 public Port getPort(ConnectPoint cp) {
171 return new DhcpL2RelayTestBase.MockPort();
172 }
173
174 @Override
175 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
176 return new DhcpL2RelayTestBase.MockPort();
177 }
178
179 @Override
180 public boolean isAvailable(DeviceId d) {
181 return true;
182 }
183 }
184
185 class MockDevice extends DefaultDevice {
186
187 public MockDevice(ProviderId providerId, DeviceId id, Type type,
188 String manufacturer, String hwVersion, String swVersion,
189 String serialNumber, ChassisId chassisId, Annotations... annotations) {
190 super(providerId, id, type, manufacturer, hwVersion, swVersion, serialNumber,
191 chassisId, annotations);
192 }
193 }
194
195 class MockHostService extends HostServiceAdapter {
196
197 @Override
198 public Set<Host> getHostsByMac(MacAddress mac) {
199
200 HostLocation loc = new HostLocation(DEVICE_ID_1, PortNumber.portNumber(22), 0);
201
202 IpAddress ip = IpAddress.valueOf("10.100.200.10");
203
204 Host h = new DefaultHost(ProviderId.NONE, HostId.hostId(mac, VlanId.NONE),
205 mac, VlanId.NONE, loc, ImmutableSet.of(ip));
206
207 return ImmutableSet.of(h);
208 }
209 }
210
211 class MockMastershipService extends MastershipServiceAdapter {
212 @Override
213 public boolean isLocalMaster(DeviceId d) {
214 return true;
215 }
216 }
217
218 class MockPort implements Port {
219
220 @Override
221 public boolean isEnabled() {
222 return true;
223 }
224 @Override
225 public long portSpeed() {
226 return 1000;
227 }
228 @Override
229 public Element element() {
230 return null;
231 }
232 @Override
233 public PortNumber number() {
234 return null;
235 }
236 @Override
237 public Annotations annotations() {
238 return new MockAnnotations();
239 }
240 @Override
241 public Type type() {
242 return Port.Type.FIBER;
243 }
244
245 private class MockAnnotations implements Annotations {
246
247 @Override
248 public String value(String val) {
249 return "PON 1/1";
250 }
251 @Override
252 public Set<String> keys() {
253 return null;
254 }
255 }
256 }
257
Saurav Dasb4e3e102018-10-02 15:31:17 -0700258 /**
Amit Ghosh8951f042017-08-10 13:48:10 +0100259 * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
260 */
261 class MockPacketService extends PacketServiceAdapter {
262
263 @Override
264 public void addProcessor(PacketProcessor processor, int priority) {
265 packetProcessor = processor;
266 }
267
268 @Override
269 public void emit(OutboundPacket packet) {
270 try {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530271 Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
Amit Ghosh8951f042017-08-10 13:48:10 +0100272 0, packet.data().array().length);
273 savePacket(eth);
274 } catch (Exception e) {
275 fail(e.getMessage());
276 }
277 }
278 }
279
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300280 class MockSadisService implements SadisService {
281 @Override
282 public BaseInformationService<SubscriberAndDeviceInformation> getSubscriberInfoService() {
283 return new DhcpL2RelayTestBase.MockSubService();
284 }
285
286 @Override
287 public BaseInformationService<BandwidthProfileInformation> getBandwidthProfileService() {
288 return null;
289 }
290 }
291
292 class MockSubService implements BaseInformationService<SubscriberAndDeviceInformation> {
293 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation device =
294 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(OLT_DEV_ID, VlanId.NONE, VlanId.NONE, null,
295 null, OLT_MAC_ADDRESS, Ip4Address.valueOf("10.10.10.10"), UPLINK_PORT);
296 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation sub =
297 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(CLIENT_ID_1, CLIENT_C_TAG,
298 CLIENT_S_TAG, CLIENT_NAS_PORT_ID, CLIENT_CIRCUIT_ID, null, null, -1);
299 @Override
300 public SubscriberAndDeviceInformation get(String id) {
301 if (id.equals(OLT_DEV_ID)) {
302 return device;
303 } else {
304 return sub;
305 }
306 }
307
308 @Override
309 public void invalidateAll() {}
310 @Override
311 public void invalidateId(String id) {}
312 @Override
313 public SubscriberAndDeviceInformation getfromCache(String id) {
314 return null;
315 }
316 }
317
318 class MockSubscriberAndDeviceInformation extends SubscriberAndDeviceInformation {
319
320 MockSubscriberAndDeviceInformation(String id, VlanId ctag,
321 VlanId stag, String nasPortId,
322 String circuitId, MacAddress hardId,
323 Ip4Address ipAddress, int uplinkPort) {
324 this.setCTag(ctag);
325 this.setHardwareIdentifier(hardId);
326 this.setId(id);
327 this.setIPAddress(ipAddress);
328 this.setSTag(stag);
329 this.setNasPortId(nasPortId);
330 this.setCircuitId(circuitId);
331 this.setUplinkPort(uplinkPort);
332 }
333 }
334
335 class MockComponentContext implements ComponentContext {
336
337 @Override
338 public Dictionary<String, Object> getProperties() {
339 Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
340 cfgDict.put("publishCountersRate", 10);
341 return cfgDict;
342 }
343
344 @Override
345 public Object locateService(String name) {
346 // TODO Auto-generated method stub
347 return null;
348 }
349
350 @Override
351 public Object locateService(String name, ServiceReference reference) {
352 // TODO Auto-generated method stub
353 return null;
354 }
355
356 @Override
357 public Object[] locateServices(String name) {
358 // TODO Auto-generated method stub
359 return null;
360 }
361
362 @Override
363 public BundleContext getBundleContext() {
364 // TODO Auto-generated method stub
365 return null;
366 }
367
368 @Override
369 public Bundle getUsingBundle() {
370 // TODO Auto-generated method stub
371 return null;
372 }
373
374 @Override
375 public ComponentInstance getComponentInstance() {
376 // TODO Auto-generated method stub
377 return null;
378 }
379
380 @Override
381 public void enableComponent(String name) {
382 // TODO Auto-generated method stub
383 }
384
385 @Override
386 public void disableComponent(String name) {
387 // TODO Auto-generated method stub
388 }
389
390 @Override
391 public ServiceReference getServiceReference() {
392 // TODO Auto-generated method stub
393 return null;
394 }
395 }
396
397
Amit Ghosh8951f042017-08-10 13:48:10 +0100398 /**
399 * Mocks the DefaultPacketContext.
400 */
401 final class TestPacketContext extends DefaultPacketContext {
402
403 private TestPacketContext(long time, InboundPacket inPkt,
404 OutboundPacket outPkt, boolean block) {
405 super(time, inPkt, outPkt, block);
406 }
407
408 @Override
409 public void send() {
410 // We don't send anything out.
411 }
412 }
413
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300414 public static class TestEventDispatcher extends DefaultEventSinkRegistry
415 implements EventDeliveryService {
416 @Override
417 @SuppressWarnings("unchecked")
418 public synchronized void post(Event event) {
419 EventSink sink = getSink(event.getClass());
420 checkState(sink != null, "No sink for event %s", event);
421 sink.process(event);
422 }
423
424 @Override
425 public void setDispatchTimeLimit(long millis) {
426 }
427
428 @Override
429 public long getDispatchTimeLimit() {
430 return 0;
431 }
432 }
433
434 /**
435 * Creates a mock object for a scheduled executor service.
436 *
437 */
438 public static final class MockExecutor implements ScheduledExecutorService {
439 private ScheduledExecutorService executor;
440
441 MockExecutor(ScheduledExecutorService executor) {
442 this.executor = executor;
443 }
444
445 String lastMethodCalled = "";
446 long lastInitialDelay;
447 long lastDelay;
448 TimeUnit lastUnit;
449
450 public void assertLastMethodCalled(String method, long initialDelay, long delay, TimeUnit unit) {
451 assertEquals(method, lastMethodCalled);
452 assertEquals(initialDelay, lastInitialDelay);
453 assertEquals(delay, lastDelay);
454 assertEquals(unit, lastUnit);
455 }
456
457 @Override
458 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
459 lastMethodCalled = "scheduleRunnable";
460 lastDelay = delay;
461 lastUnit = unit;
462 return null;
463 }
464
465 @Override
466 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
467 lastMethodCalled = "scheduleCallable";
468 lastDelay = delay;
469 lastUnit = unit;
470 return null;
471 }
472
473 @Override
474 public ScheduledFuture<?> scheduleAtFixedRate(
475 Runnable command, long initialDelay, long period, TimeUnit unit) {
476 lastMethodCalled = "scheduleAtFixedRate";
477 lastInitialDelay = initialDelay;
478 lastDelay = period;
479 lastUnit = unit;
480 return null;
481 }
482
483 @Override
484 public ScheduledFuture<?> scheduleWithFixedDelay(
485 Runnable command, long initialDelay, long delay, TimeUnit unit) {
486 lastMethodCalled = "scheduleWithFixedDelay";
487 lastInitialDelay = initialDelay;
488 lastDelay = delay;
489 lastUnit = unit;
490 command.run();
491 return null;
492 }
493
494 @Override
495 public boolean awaitTermination(long timeout, TimeUnit unit) {
496 throw new UnsupportedOperationException();
497 }
498
499 @Override
500 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
501 throws InterruptedException {
502 throw new UnsupportedOperationException();
503 }
504
505 @Override
506 public <T> List<Future<T>> invokeAll(
507 Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
508 throws InterruptedException {
509 throw new UnsupportedOperationException();
510 }
511
512 @Override
513 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
514 throws ExecutionException, InterruptedException {
515 throw new UnsupportedOperationException();
516 }
517
518 @Override
519 public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
520 throws ExecutionException, InterruptedException, TimeoutException {
521 throw new UnsupportedOperationException();
522 }
523
524 @Override
525 public boolean isShutdown() {
526 throw new UnsupportedOperationException();
527 }
528
529 @Override
530 public boolean isTerminated() {
531 throw new UnsupportedOperationException();
532 }
533
534 @Override
535 public void shutdown() {
536 throw new UnsupportedOperationException();
537 }
538
539 @Override
540 public List<Runnable> shutdownNow() {
541 return null;
542 }
543
544 @Override
545 public <T> Future<T> submit(Callable<T> task) {
546 throw new UnsupportedOperationException();
547 }
548
549 @Override
550 public Future<?> submit(Runnable task) {
551 throw new UnsupportedOperationException();
552 }
553
554 @Override
555 public <T> Future<T> submit(Runnable task, T result) {
556 throw new UnsupportedOperationException();
557 }
558
559 @Override
560 public void execute(Runnable command) {
561 throw new UnsupportedOperationException();
562 }
563 }
564
Amit Ghosh8951f042017-08-10 13:48:10 +0100565 /**
566 * Sends an Ethernet packet to the process method of the Packet Processor.
567 *
568 * @param pkt Ethernet packet
569 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530570 void sendPacket(Ethernet pkt, ConnectPoint cp) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100571 final ByteBuffer byteBuffer = ByteBuffer.wrap(pkt.serialize());
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530572 InboundPacket inPacket = new DefaultInboundPacket(cp, pkt, byteBuffer);
Amit Ghosh8951f042017-08-10 13:48:10 +0100573
574 PacketContext context = new TestPacketContext(127L, inPacket, null, false);
575 packetProcessor.process(context);
576 }
577
578 /**
579 * Constructs an Ethernet packet with IP/UDP/DHCP payload.
580 *
581 * @return Ethernet packet
582 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530583 private Ethernet construcEthernetPacket(MacAddress srcMac, MacAddress dstMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100584 String dstIp, byte dhcpReqRsp,
585 MacAddress clientHwAddress,
586 Ip4Address dhcpClientIpAddress) {
587 // Ethernet Frame.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530588 Ethernet ethPkt = new Ethernet();
589 ethPkt.setSourceMACAddress(srcMac);
590 ethPkt.setDestinationMACAddress(dstMac);
Amit Ghosh8951f042017-08-10 13:48:10 +0100591 ethPkt.setEtherType(Ethernet.TYPE_IPV4);
592 ethPkt.setVlanID((short) 2);
593 ethPkt.setPriorityCode((byte) 6);
594
595 // IP Packet
596 IPv4 ipv4Reply = new IPv4();
597 ipv4Reply.setSourceAddress(0);
598 ipv4Reply.setDestinationAddress(dstIp);
599
600 ipv4Reply.setTtl((byte) 127);
601
602 // UDP Datagram.
603 UDP udpReply = new UDP();
604 udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
605 udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
606
607 // DHCP Payload.
608 DHCP dhcpReply = new DHCP();
609 dhcpReply.setOpCode(dhcpReqRsp);
610
611 dhcpReply.setYourIPAddress(dhcpClientIpAddress.toInt());
612 dhcpReply.setServerIPAddress(0);
613
614 final byte[] serverNameBytes = new byte[64];
615 String result = new String(serverNameBytes, StandardCharsets.US_ASCII).trim();
616 dhcpReply.setServerName(result);
617
618 final byte[] bootFileBytes = new byte[128];
619 String result1 = new String(bootFileBytes, StandardCharsets.US_ASCII).trim();
620 dhcpReply.setBootFileName(result1);
621
622 dhcpReply.setTransactionId(TRANSACTION_ID);
623 dhcpReply.setClientHardwareAddress(clientHwAddress.toBytes());
624 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
625 dhcpReply.setHardwareAddressLength((byte) 6);
626
627 udpReply.setPayload(dhcpReply);
628 ipv4Reply.setPayload(udpReply);
629 ethPkt.setPayload(ipv4Reply);
630
631 return ethPkt;
632 }
633
634 /**
635 * Constructs DHCP Discover Packet.
636 *
637 * @return Ethernet packet
638 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530639 Ethernet constructDhcpDiscoverPacket(MacAddress clientMac) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100640
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530641 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Amit Ghosh8951f042017-08-10 13:48:10 +0100642 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
643 Ip4Address.valueOf("0.0.0.0"));
644
645 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
646 UDP udpPacket = (UDP) ipv4Packet.getPayload();
647 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
648
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700649 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPDISCOVER));
Amit Ghosh8951f042017-08-10 13:48:10 +0100650
651 return pkt;
652 }
653
654 /**
655 * Constructs DHCP Request Packet.
656 *
657 * @return Ethernet packet
658 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530659 Ethernet constructDhcpRequestPacket(MacAddress clientMac) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100660
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530661 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Amit Ghosh8951f042017-08-10 13:48:10 +0100662 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
663 Ip4Address.valueOf("0.0.0.0"));
664
665 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
666 UDP udpPacket = (UDP) ipv4Packet.getPayload();
667 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
668
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700669 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPREQUEST));
Amit Ghosh8951f042017-08-10 13:48:10 +0100670
671 return pkt;
672 }
673
674 /**
675 * Constructs DHCP Offer Packet.
676 *
677 * @return Ethernet packet
678 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530679 Ethernet constructDhcpOfferPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100680 String ipAddress, String dhcpClientIpAddress) {
681
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530682 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100683 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
684
685 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
686 UDP udpPacket = (UDP) ipv4Packet.getPayload();
687 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
688
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700689 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPOFFER));
Amit Ghosh8951f042017-08-10 13:48:10 +0100690
691 return pkt;
692 }
693
694 /**
695 * Constructs DHCP Ack Packet.
696 *
697 * @return Ethernet packet
698 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530699 Ethernet constructDhcpAckPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100700 String ipAddress, String dhcpClientIpAddress) {
701
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530702 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100703 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
704
705 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
706 UDP udpPacket = (UDP) ipv4Packet.getPayload();
707 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
708
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700709 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPACK));
Amit Ghosh8951f042017-08-10 13:48:10 +0100710
711 return pkt;
712 }
713
714 /**
715 * Constructs DHCP Discover Options.
716 *
717 * @return Ethernet packet
718 */
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700719 private List<DhcpOption> constructDhcpOptions(DHCP.MsgType packetType) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100720
721 // DHCP Options.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700722 DhcpOption option = new DhcpOption();
723 List<DhcpOption> optionList = new ArrayList<>();
Amit Ghosh8951f042017-08-10 13:48:10 +0100724
725
726 // DHCP Message Type.
727 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
728 option.setLength((byte) 1);
729 byte[] optionData = {(byte) packetType.getValue()};
730 option.setData(optionData);
731 optionList.add(option);
732
733 // DHCP Requested IP.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700734 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100735 option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
736 option.setLength((byte) 4);
737 optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
738 option.setData(optionData);
739 optionList.add(option);
740
741 // End Option.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700742 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100743 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
744 option.setLength((byte) 1);
745 optionList.add(option);
746
747 return optionList;
748 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300749}