blob: 85854abad502a9d4c25c7b1a0e9709be2f70ea3c [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;
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
Amit Ghosh8951f042017-08-10 13:48:10 +010097
98/**
99 * Common methods for AAA app testing.
100 */
101public class DhcpL2RelayTestBase {
102 private final Logger log = LoggerFactory.getLogger(getClass());
103
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000104 static final VlanId CLIENT_C_TAG = VlanId.vlanId((short) 2);
105 static final VlanId CLIENT_S_TAG = VlanId.vlanId((short) 4);
106 static final short CLIENT_C_PBIT = 7;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300107 static final String CLIENT_ID_1 = "SUBSCRIBER_ID_1";
108 static final String CLIENT_NAS_PORT_ID = "PON 1/1";
109 static final String CLIENT_CIRCUIT_ID = "CIR-PON 1/1";
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000110 static final short NOT_PROVIDED = 0;
Amit Ghosh8951f042017-08-10 13:48:10 +0100111
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300112 static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
113 static final MacAddress SERVER_MAC = MacAddress.valueOf("bb:bb:bb:bb:bb:bb");
114 static final String DESTINATION_ADDRESS_IP = "1.1.1.1";
115 static final String DHCP_CLIENT_IP_ADDRESS = "2.2.2.2";
116 static final int UPLINK_PORT = 5;
117
118 static final String EXPECTED_IP = "10.2.0.2";
119 static final String OLT_DEV_ID = "of:00000000000000aa";
120 static final DeviceId DEVICE_ID_1 = DeviceId.deviceId(OLT_DEV_ID);
121 static final int TRANSACTION_ID = 1000;
122 static final String SCHEME_NAME = "dhcpl2relay";
123 static final MacAddress OLT_MAC_ADDRESS = MacAddress.valueOf("01:02:03:04:05:06");
124
125 static final ConnectPoint SERVER_CONNECT_POINT =
126 ConnectPoint.deviceConnectPoint("of:00000000000000aa/5");
127
128 static final DefaultAnnotations DEVICE_ANNOTATIONS = DefaultAnnotations.builder()
129 .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build();
Amit Ghosh8951f042017-08-10 13:48:10 +0100130
131 List<BasePacket> savedPackets = new LinkedList<>();
132 PacketProcessor packetProcessor;
133
134
135 /**
136 * Saves the given packet onto the saved packets list.
137 *
138 * @param packet packet to save
139 */
140 void savePacket(BasePacket packet) {
141 savedPackets.add(packet);
142 }
143
144 BasePacket getPacket() {
145 return savedPackets.remove(0);
146 }
147
148 /**
Saurav Dasb4e3e102018-10-02 15:31:17 -0700149 * Mock core service adaptor that provides an appId.
150 */
151 class MockCoreServiceAdapter extends CoreServiceAdapter {
152
153 @Override
154 public ApplicationId registerApplication(String name) {
155 return new DefaultApplicationId(10, name);
156 }
157 }
158
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300159 class MockDeviceService extends DeviceServiceAdapter {
160
161 private ProviderId providerId = new ProviderId("of", "foo");
162 private final Device device1 = new DhcpL2RelayTestBase.MockDevice(providerId, DEVICE_ID_1, Device.Type.SWITCH,
163 "foo.inc", "0", "0", OLT_DEV_ID, new ChassisId(),
164 DEVICE_ANNOTATIONS);
165
166 @Override
167 public Device getDevice(DeviceId devId) {
168 return device1;
169
170 }
171
172 @Override
173 public Port getPort(ConnectPoint cp) {
174 return new DhcpL2RelayTestBase.MockPort();
175 }
176
177 @Override
178 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
179 return new DhcpL2RelayTestBase.MockPort();
180 }
181
182 @Override
183 public boolean isAvailable(DeviceId d) {
184 return true;
185 }
186 }
187
188 class MockDevice extends DefaultDevice {
189
190 public MockDevice(ProviderId providerId, DeviceId id, Type type,
191 String manufacturer, String hwVersion, String swVersion,
192 String serialNumber, ChassisId chassisId, Annotations... annotations) {
193 super(providerId, id, type, manufacturer, hwVersion, swVersion, serialNumber,
194 chassisId, annotations);
195 }
196 }
197
198 class MockHostService extends HostServiceAdapter {
199
200 @Override
201 public Set<Host> getHostsByMac(MacAddress mac) {
202
203 HostLocation loc = new HostLocation(DEVICE_ID_1, PortNumber.portNumber(22), 0);
204
205 IpAddress ip = IpAddress.valueOf("10.100.200.10");
206
207 Host h = new DefaultHost(ProviderId.NONE, HostId.hostId(mac, VlanId.NONE),
208 mac, VlanId.NONE, loc, ImmutableSet.of(ip));
209
210 return ImmutableSet.of(h);
211 }
212 }
213
214 class MockMastershipService extends MastershipServiceAdapter {
215 @Override
216 public boolean isLocalMaster(DeviceId d) {
217 return true;
218 }
219 }
220
221 class MockPort implements Port {
222
223 @Override
224 public boolean isEnabled() {
225 return true;
226 }
227 @Override
228 public long portSpeed() {
229 return 1000;
230 }
231 @Override
232 public Element element() {
233 return null;
234 }
235 @Override
236 public PortNumber number() {
237 return null;
238 }
239 @Override
240 public Annotations annotations() {
241 return new MockAnnotations();
242 }
243 @Override
244 public Type type() {
245 return Port.Type.FIBER;
246 }
247
248 private class MockAnnotations implements Annotations {
249
250 @Override
251 public String value(String val) {
252 return "PON 1/1";
253 }
254 @Override
255 public Set<String> keys() {
256 return null;
257 }
258 }
259 }
260
Saurav Dasb4e3e102018-10-02 15:31:17 -0700261 /**
Amit Ghosh8951f042017-08-10 13:48:10 +0100262 * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
263 */
264 class MockPacketService extends PacketServiceAdapter {
265
266 @Override
267 public void addProcessor(PacketProcessor processor, int priority) {
268 packetProcessor = processor;
269 }
270
271 @Override
272 public void emit(OutboundPacket packet) {
273 try {
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530274 Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
Amit Ghosh8951f042017-08-10 13:48:10 +0100275 0, packet.data().array().length);
276 savePacket(eth);
277 } catch (Exception e) {
278 fail(e.getMessage());
279 }
280 }
281 }
282
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300283 class MockSadisService implements SadisService {
284 @Override
285 public BaseInformationService<SubscriberAndDeviceInformation> getSubscriberInfoService() {
286 return new DhcpL2RelayTestBase.MockSubService();
287 }
288
289 @Override
290 public BaseInformationService<BandwidthProfileInformation> getBandwidthProfileService() {
291 return null;
292 }
293 }
294
295 class MockSubService implements BaseInformationService<SubscriberAndDeviceInformation> {
296 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation device =
297 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(OLT_DEV_ID, VlanId.NONE, VlanId.NONE, null,
298 null, OLT_MAC_ADDRESS, Ip4Address.valueOf("10.10.10.10"), UPLINK_PORT);
299 DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation sub =
300 new DhcpL2RelayTestBase.MockSubscriberAndDeviceInformation(CLIENT_ID_1, CLIENT_C_TAG,
301 CLIENT_S_TAG, CLIENT_NAS_PORT_ID, CLIENT_CIRCUIT_ID, null, null, -1);
302 @Override
303 public SubscriberAndDeviceInformation get(String id) {
304 if (id.equals(OLT_DEV_ID)) {
305 return device;
306 } else {
307 return sub;
308 }
309 }
310
311 @Override
312 public void invalidateAll() {}
313 @Override
314 public void invalidateId(String id) {}
315 @Override
316 public SubscriberAndDeviceInformation getfromCache(String id) {
317 return null;
318 }
319 }
320
321 class MockSubscriberAndDeviceInformation extends SubscriberAndDeviceInformation {
322
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000323 MockSubscriberAndDeviceInformation(String id, VlanId cTag,
324 VlanId sTag, String nasPortId,
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300325 String circuitId, MacAddress hardId,
326 Ip4Address ipAddress, int uplinkPort) {
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300327 this.setHardwareIdentifier(hardId);
328 this.setId(id);
329 this.setIPAddress(ipAddress);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300330 this.setNasPortId(nasPortId);
331 this.setCircuitId(circuitId);
332 this.setUplinkPort(uplinkPort);
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000333
334 List<UniTagInformation> uniTagInformationList = new ArrayList<>();
335
336 UniTagInformation uniTagInformation = new UniTagInformation.Builder()
337 .setPonCTag(cTag)
338 .setPonSTag(sTag)
339 .setUsPonCTagPriority(CLIENT_C_PBIT)
340 .setIsDhcpRequired(true)
341 .build();
342 uniTagInformationList.add(uniTagInformation);
343 this.setUniTagList(uniTagInformationList);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300344 }
345 }
346
347 class MockComponentContext implements ComponentContext {
348
349 @Override
350 public Dictionary<String, Object> getProperties() {
351 Dictionary<String, Object> cfgDict = new Hashtable<String, Object>();
352 cfgDict.put("publishCountersRate", 10);
353 return cfgDict;
354 }
355
356 @Override
357 public Object locateService(String name) {
358 // TODO Auto-generated method stub
359 return null;
360 }
361
362 @Override
363 public Object locateService(String name, ServiceReference reference) {
364 // TODO Auto-generated method stub
365 return null;
366 }
367
368 @Override
369 public Object[] locateServices(String name) {
370 // TODO Auto-generated method stub
371 return null;
372 }
373
374 @Override
375 public BundleContext getBundleContext() {
376 // TODO Auto-generated method stub
377 return null;
378 }
379
380 @Override
381 public Bundle getUsingBundle() {
382 // TODO Auto-generated method stub
383 return null;
384 }
385
386 @Override
387 public ComponentInstance getComponentInstance() {
388 // TODO Auto-generated method stub
389 return null;
390 }
391
392 @Override
393 public void enableComponent(String name) {
394 // TODO Auto-generated method stub
395 }
396
397 @Override
398 public void disableComponent(String name) {
399 // TODO Auto-generated method stub
400 }
401
402 @Override
403 public ServiceReference getServiceReference() {
404 // TODO Auto-generated method stub
405 return null;
406 }
407 }
408
409
Amit Ghosh8951f042017-08-10 13:48:10 +0100410 /**
411 * Mocks the DefaultPacketContext.
412 */
413 final class TestPacketContext extends DefaultPacketContext {
414
415 private TestPacketContext(long time, InboundPacket inPkt,
416 OutboundPacket outPkt, boolean block) {
417 super(time, inPkt, outPkt, block);
418 }
419
420 @Override
421 public void send() {
422 // We don't send anything out.
423 }
424 }
425
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300426 public static class TestEventDispatcher extends DefaultEventSinkRegistry
427 implements EventDeliveryService {
428 @Override
429 @SuppressWarnings("unchecked")
430 public synchronized void post(Event event) {
431 EventSink sink = getSink(event.getClass());
432 checkState(sink != null, "No sink for event %s", event);
433 sink.process(event);
434 }
435
436 @Override
437 public void setDispatchTimeLimit(long millis) {
438 }
439
440 @Override
441 public long getDispatchTimeLimit() {
442 return 0;
443 }
444 }
445
446 /**
447 * Creates a mock object for a scheduled executor service.
448 *
449 */
450 public static final class MockExecutor implements ScheduledExecutorService {
451 private ScheduledExecutorService executor;
452
453 MockExecutor(ScheduledExecutorService executor) {
454 this.executor = executor;
455 }
456
457 String lastMethodCalled = "";
458 long lastInitialDelay;
459 long lastDelay;
460 TimeUnit lastUnit;
461
462 public void assertLastMethodCalled(String method, long initialDelay, long delay, TimeUnit unit) {
463 assertEquals(method, lastMethodCalled);
464 assertEquals(initialDelay, lastInitialDelay);
465 assertEquals(delay, lastDelay);
466 assertEquals(unit, lastUnit);
467 }
468
469 @Override
470 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
471 lastMethodCalled = "scheduleRunnable";
472 lastDelay = delay;
473 lastUnit = unit;
474 return null;
475 }
476
477 @Override
478 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
479 lastMethodCalled = "scheduleCallable";
480 lastDelay = delay;
481 lastUnit = unit;
482 return null;
483 }
484
485 @Override
486 public ScheduledFuture<?> scheduleAtFixedRate(
487 Runnable command, long initialDelay, long period, TimeUnit unit) {
488 lastMethodCalled = "scheduleAtFixedRate";
489 lastInitialDelay = initialDelay;
490 lastDelay = period;
491 lastUnit = unit;
492 return null;
493 }
494
495 @Override
496 public ScheduledFuture<?> scheduleWithFixedDelay(
497 Runnable command, long initialDelay, long delay, TimeUnit unit) {
498 lastMethodCalled = "scheduleWithFixedDelay";
499 lastInitialDelay = initialDelay;
500 lastDelay = delay;
501 lastUnit = unit;
502 command.run();
503 return null;
504 }
505
506 @Override
507 public boolean awaitTermination(long timeout, TimeUnit unit) {
508 throw new UnsupportedOperationException();
509 }
510
511 @Override
512 public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
513 throws InterruptedException {
514 throw new UnsupportedOperationException();
515 }
516
517 @Override
518 public <T> List<Future<T>> invokeAll(
519 Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
520 throws InterruptedException {
521 throw new UnsupportedOperationException();
522 }
523
524 @Override
525 public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
526 throws ExecutionException, InterruptedException {
527 throw new UnsupportedOperationException();
528 }
529
530 @Override
531 public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
532 throws ExecutionException, InterruptedException, TimeoutException {
533 throw new UnsupportedOperationException();
534 }
535
536 @Override
537 public boolean isShutdown() {
538 throw new UnsupportedOperationException();
539 }
540
541 @Override
542 public boolean isTerminated() {
543 throw new UnsupportedOperationException();
544 }
545
546 @Override
547 public void shutdown() {
548 throw new UnsupportedOperationException();
549 }
550
551 @Override
552 public List<Runnable> shutdownNow() {
553 return null;
554 }
555
556 @Override
557 public <T> Future<T> submit(Callable<T> task) {
558 throw new UnsupportedOperationException();
559 }
560
561 @Override
562 public Future<?> submit(Runnable task) {
563 throw new UnsupportedOperationException();
564 }
565
566 @Override
567 public <T> Future<T> submit(Runnable task, T result) {
568 throw new UnsupportedOperationException();
569 }
570
571 @Override
572 public void execute(Runnable command) {
573 throw new UnsupportedOperationException();
574 }
575 }
576
Amit Ghosh8951f042017-08-10 13:48:10 +0100577 /**
578 * Sends an Ethernet packet to the process method of the Packet Processor.
579 *
580 * @param pkt Ethernet packet
581 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530582 void sendPacket(Ethernet pkt, ConnectPoint cp) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100583 final ByteBuffer byteBuffer = ByteBuffer.wrap(pkt.serialize());
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530584 InboundPacket inPacket = new DefaultInboundPacket(cp, pkt, byteBuffer);
Amit Ghosh8951f042017-08-10 13:48:10 +0100585
586 PacketContext context = new TestPacketContext(127L, inPacket, null, false);
587 packetProcessor.process(context);
588 }
589
590 /**
591 * Constructs an Ethernet packet with IP/UDP/DHCP payload.
592 *
593 * @return Ethernet packet
594 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530595 private Ethernet construcEthernetPacket(MacAddress srcMac, MacAddress dstMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100596 String dstIp, byte dhcpReqRsp,
597 MacAddress clientHwAddress,
598 Ip4Address dhcpClientIpAddress) {
599 // Ethernet Frame.
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530600 Ethernet ethPkt = new Ethernet();
601 ethPkt.setSourceMACAddress(srcMac);
602 ethPkt.setDestinationMACAddress(dstMac);
Amit Ghosh8951f042017-08-10 13:48:10 +0100603 ethPkt.setEtherType(Ethernet.TYPE_IPV4);
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000604 ethPkt.setVlanID(CLIENT_C_TAG.toShort());
605 ethPkt.setPriorityCode((byte) CLIENT_C_PBIT);
606
607 if (DHCP.OPCODE_REPLY == dhcpReqRsp) {
608 ethPkt.setQinQPriorityCode((byte) 3);
609 ethPkt.setQinQVID((short) 4);
610 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100611
612 // IP Packet
613 IPv4 ipv4Reply = new IPv4();
614 ipv4Reply.setSourceAddress(0);
615 ipv4Reply.setDestinationAddress(dstIp);
616
617 ipv4Reply.setTtl((byte) 127);
618
619 // UDP Datagram.
620 UDP udpReply = new UDP();
621 udpReply.setSourcePort((byte) UDP.DHCP_CLIENT_PORT);
622 udpReply.setDestinationPort((byte) UDP.DHCP_SERVER_PORT);
623
624 // DHCP Payload.
625 DHCP dhcpReply = new DHCP();
626 dhcpReply.setOpCode(dhcpReqRsp);
627
628 dhcpReply.setYourIPAddress(dhcpClientIpAddress.toInt());
629 dhcpReply.setServerIPAddress(0);
630
631 final byte[] serverNameBytes = new byte[64];
632 String result = new String(serverNameBytes, StandardCharsets.US_ASCII).trim();
633 dhcpReply.setServerName(result);
634
635 final byte[] bootFileBytes = new byte[128];
636 String result1 = new String(bootFileBytes, StandardCharsets.US_ASCII).trim();
637 dhcpReply.setBootFileName(result1);
638
639 dhcpReply.setTransactionId(TRANSACTION_ID);
640 dhcpReply.setClientHardwareAddress(clientHwAddress.toBytes());
641 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
642 dhcpReply.setHardwareAddressLength((byte) 6);
643
644 udpReply.setPayload(dhcpReply);
645 ipv4Reply.setPayload(udpReply);
646 ethPkt.setPayload(ipv4Reply);
647
648 return ethPkt;
649 }
650
651 /**
652 * Constructs DHCP Discover Packet.
653 *
654 * @return Ethernet packet
655 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530656 Ethernet constructDhcpDiscoverPacket(MacAddress clientMac) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100657
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530658 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Amit Ghosh8951f042017-08-10 13:48:10 +0100659 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
660 Ip4Address.valueOf("0.0.0.0"));
661
662 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
663 UDP udpPacket = (UDP) ipv4Packet.getPayload();
664 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
665
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700666 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPDISCOVER));
Amit Ghosh8951f042017-08-10 13:48:10 +0100667
668 return pkt;
669 }
670
671 /**
672 * Constructs DHCP Request Packet.
673 *
674 * @return Ethernet packet
675 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530676 Ethernet constructDhcpRequestPacket(MacAddress clientMac) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100677
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530678 Ethernet pkt = construcEthernetPacket(clientMac, MacAddress.BROADCAST,
Amit Ghosh8951f042017-08-10 13:48:10 +0100679 "255.255.255.255", DHCP.OPCODE_REQUEST, MacAddress.NONE,
680 Ip4Address.valueOf("0.0.0.0"));
681
682 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
683 UDP udpPacket = (UDP) ipv4Packet.getPayload();
684 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
685
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700686 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPREQUEST));
Amit Ghosh8951f042017-08-10 13:48:10 +0100687
688 return pkt;
689 }
690
691 /**
692 * Constructs DHCP Offer Packet.
693 *
694 * @return Ethernet packet
695 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530696 Ethernet constructDhcpOfferPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100697 String ipAddress, String dhcpClientIpAddress) {
698
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530699 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100700 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
701
702 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
703 UDP udpPacket = (UDP) ipv4Packet.getPayload();
704 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
705
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700706 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPOFFER));
Amit Ghosh8951f042017-08-10 13:48:10 +0100707
708 return pkt;
709 }
710
711 /**
712 * Constructs DHCP Ack Packet.
713 *
714 * @return Ethernet packet
715 */
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530716 Ethernet constructDhcpAckPacket(MacAddress servMac, MacAddress clientMac,
Amit Ghosh8951f042017-08-10 13:48:10 +0100717 String ipAddress, String dhcpClientIpAddress) {
718
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530719 Ethernet pkt = construcEthernetPacket(servMac, clientMac, ipAddress, DHCP.OPCODE_REPLY,
Amit Ghosh8951f042017-08-10 13:48:10 +0100720 clientMac, Ip4Address.valueOf(dhcpClientIpAddress));
721
722 IPv4 ipv4Packet = (IPv4) pkt.getPayload();
723 UDP udpPacket = (UDP) ipv4Packet.getPayload();
724 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
725
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700726 dhcpPacket.setOptions(constructDhcpOptions(DHCP.MsgType.DHCPACK));
Amit Ghosh8951f042017-08-10 13:48:10 +0100727
728 return pkt;
729 }
730
731 /**
732 * Constructs DHCP Discover Options.
733 *
734 * @return Ethernet packet
735 */
Carmelo Casconede1e6e32019-07-15 19:39:08 -0700736 private List<DhcpOption> constructDhcpOptions(DHCP.MsgType packetType) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100737
738 // DHCP Options.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700739 DhcpOption option = new DhcpOption();
740 List<DhcpOption> optionList = new ArrayList<>();
Amit Ghosh8951f042017-08-10 13:48:10 +0100741
742
743 // DHCP Message Type.
744 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
745 option.setLength((byte) 1);
746 byte[] optionData = {(byte) packetType.getValue()};
747 option.setData(optionData);
748 optionList.add(option);
749
750 // DHCP Requested IP.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700751 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100752 option.setCode(DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue());
753 option.setLength((byte) 4);
754 optionData = Ip4Address.valueOf(EXPECTED_IP).toOctets();
755 option.setData(optionData);
756 optionList.add(option);
757
758 // End Option.
Jonathan Hartedbf6422018-05-02 17:30:05 -0700759 option = new DhcpOption();
Amit Ghosh8951f042017-08-10 13:48:10 +0100760 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
761 option.setLength((byte) 1);
762 optionList.add(option);
763
764 return optionList;
765 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300766}