blob: d7ecf8ceb367b141c793893c9756acb035f83722 [file] [log] [blame]
samanwita pal18696f62015-07-17 13:15:43 -07001/*
2 * Copyright 2014 Open Networking Laboratory
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 */
samanwita palf66ed8a2015-07-21 15:45:33 -070016package org.onosproject.dhcpserver.impl;
samanwita pal18696f62015-07-17 13:15:43 -070017
samanwita pal775f6192015-07-28 10:10:13 -070018import com.google.common.collect.ImmutableSet;
samanwita pal18696f62015-07-17 13:15:43 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
samanwita palf66ed8a2015-07-21 15:45:33 -070024import org.apache.felix.scr.annotations.Service;
samanwita palb7900e52015-07-30 11:47:14 -070025import org.onlab.packet.ARP;
samanwita pal18696f62015-07-17 13:15:43 -070026import org.onlab.packet.DHCP;
27import org.onlab.packet.DHCPOption;
28import org.onlab.packet.Ethernet;
29import org.onlab.packet.IPv4;
30import org.onlab.packet.Ip4Address;
samanwita pale2983f52015-08-07 11:00:18 -070031import org.onlab.packet.IpAddress;
samanwita pal18696f62015-07-17 13:15:43 -070032import org.onlab.packet.MacAddress;
33import org.onlab.packet.UDP;
samanwita pale2983f52015-08-07 11:00:18 -070034import org.onlab.packet.VlanId;
samanwita pal18696f62015-07-17 13:15:43 -070035import org.onosproject.core.ApplicationId;
36import org.onosproject.core.CoreService;
samanwita palf66ed8a2015-07-21 15:45:33 -070037import org.onosproject.dhcpserver.DHCPService;
38import org.onosproject.dhcpserver.DHCPStore;
samanwita pal982cc0e2015-08-21 11:29:57 -070039import org.onosproject.net.config.ConfigFactory;
40import org.onosproject.net.config.NetworkConfigEvent;
41import org.onosproject.net.config.NetworkConfigListener;
42import org.onosproject.net.config.NetworkConfigRegistry;
43
samanwita pal18696f62015-07-17 13:15:43 -070044import org.onosproject.net.ConnectPoint;
samanwita pale2983f52015-08-07 11:00:18 -070045import org.onosproject.net.Host;
46import org.onosproject.net.HostId;
47import org.onosproject.net.HostLocation;
samanwita pal18696f62015-07-17 13:15:43 -070048import org.onosproject.net.flow.DefaultTrafficSelector;
49import org.onosproject.net.flow.DefaultTrafficTreatment;
50import org.onosproject.net.flow.TrafficSelector;
51import org.onosproject.net.flow.TrafficTreatment;
samanwita pale2983f52015-08-07 11:00:18 -070052import org.onosproject.net.host.DefaultHostDescription;
53import org.onosproject.net.host.HostProvider;
54import org.onosproject.net.host.HostProviderRegistry;
55import org.onosproject.net.host.HostProviderService;
samanwita pal18696f62015-07-17 13:15:43 -070056import org.onosproject.net.packet.DefaultOutboundPacket;
57import org.onosproject.net.packet.PacketContext;
58import org.onosproject.net.packet.PacketPriority;
59import org.onosproject.net.packet.PacketProcessor;
60import org.onosproject.net.packet.PacketService;
samanwita pale2983f52015-08-07 11:00:18 -070061import org.onosproject.net.provider.AbstractProvider;
62import org.onosproject.net.provider.ProviderId;
samanwita pal18696f62015-07-17 13:15:43 -070063import org.slf4j.Logger;
64import org.slf4j.LoggerFactory;
65
66import java.nio.ByteBuffer;
67import java.util.ArrayList;
samanwita pale2983f52015-08-07 11:00:18 -070068import java.util.HashSet;
samanwita pal18696f62015-07-17 13:15:43 -070069import java.util.List;
samanwita palf66ed8a2015-07-21 15:45:33 -070070import java.util.Map;
samanwita pal775f6192015-07-28 10:10:13 -070071import java.util.Set;
samanwita pal18696f62015-07-17 13:15:43 -070072
73import static org.onlab.packet.MacAddress.valueOf;
Thomas Vachuska8f1bd1a2015-08-26 13:28:38 -070074import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
samanwita pal18696f62015-07-17 13:15:43 -070075
76/**
77 * Skeletal ONOS DHCP Server application.
78 */
79@Component(immediate = true)
samanwita palf66ed8a2015-07-21 15:45:33 -070080@Service
81public class DHCPManager implements DHCPService {
samanwita pal18696f62015-07-17 13:15:43 -070082
samanwita pale2983f52015-08-07 11:00:18 -070083 private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcpserver", true);
samanwita pal18696f62015-07-17 13:15:43 -070084 private final Logger log = LoggerFactory.getLogger(getClass());
85
samanwita pal775f6192015-07-28 10:10:13 -070086 private final NetworkConfigListener cfgListener = new InternalConfigListener();
87
88 private final Set<ConfigFactory> factories = ImmutableSet.of(
89 new ConfigFactory<ApplicationId, DHCPConfig>(APP_SUBJECT_FACTORY,
90 DHCPConfig.class,
91 "dhcp") {
92 @Override
93 public DHCPConfig createConfig() {
94 return new DHCPConfig();
95 }
96 },
97 new ConfigFactory<ApplicationId, DHCPStoreConfig>(APP_SUBJECT_FACTORY,
98 DHCPStoreConfig.class,
99 "dhcpstore") {
100 @Override
101 public DHCPStoreConfig createConfig() {
102 return new DHCPStoreConfig();
103 }
104 }
105 );
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected NetworkConfigRegistry cfgService;
108
samanwita pal18696f62015-07-17 13:15:43 -0700109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected PacketService packetService;
111
112 private DHCPPacketProcessor processor = new DHCPPacketProcessor();
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected CoreService coreService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected DHCPStore dhcpStore;
119
samanwita pale2983f52015-08-07 11:00:18 -0700120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected HostProviderRegistry hostProviderRegistry;
122
123 protected HostProviderService hostProviderService;
124
samanwita pal18696f62015-07-17 13:15:43 -0700125 private ApplicationId appId;
126
samanwita pal775f6192015-07-28 10:10:13 -0700127 // Hardcoded values are default values.
samanwita pal18696f62015-07-17 13:15:43 -0700128
samanwita pal775f6192015-07-28 10:10:13 -0700129 private static String myIP = "10.0.0.2";
samanwita pal18696f62015-07-17 13:15:43 -0700130
samanwita pal775f6192015-07-28 10:10:13 -0700131 private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f");
samanwita pal18696f62015-07-17 13:15:43 -0700132
133 /**
134 * leaseTime - 10 mins or 600s.
135 * renewalTime - 5 mins or 300s.
136 * rebindingTime - 6 mins or 360s.
137 */
138
139 private static int leaseTime = 600;
140
141 private static int renewalTime = 300;
142
143 private static int rebindingTime = 360;
144
145 private static byte packetTTL = (byte) 127;
146
147 private static String subnetMask = "255.0.0.0";
148
149 private static String broadcastAddress = "10.255.255.255";
150
samanwita pal792159a2015-07-28 14:07:01 -0700151 private static String routerAddress = "10.0.0.2";
152
153 private static String domainServer = "10.0.0.2";
samanwita pale2983f52015-08-07 11:00:18 -0700154 private final HostProvider hostProvider = new InternalHostProvider();
samanwita pal792159a2015-07-28 14:07:01 -0700155
samanwita pal18696f62015-07-17 13:15:43 -0700156 @Activate
157 protected void activate() {
158 // start the dhcp server
159 appId = coreService.registerApplication("org.onosproject.dhcpserver");
160
samanwita pal775f6192015-07-28 10:10:13 -0700161 cfgService.addListener(cfgListener);
162 factories.forEach(cfgService::registerConfigFactory);
samanwita pale2983f52015-08-07 11:00:18 -0700163 hostProviderService = hostProviderRegistry.register(hostProvider);
samanwita palb7900e52015-07-30 11:47:14 -0700164 packetService.addProcessor(processor, PacketProcessor.observer(1));
samanwita pal18696f62015-07-17 13:15:43 -0700165 requestPackets();
166 log.info("Started");
167 }
168
169 @Deactivate
170 protected void deactivate() {
samanwita pal775f6192015-07-28 10:10:13 -0700171 cfgService.removeListener(cfgListener);
172 factories.forEach(cfgService::unregisterConfigFactory);
samanwita pal18696f62015-07-17 13:15:43 -0700173 packetService.removeProcessor(processor);
samanwita pale2983f52015-08-07 11:00:18 -0700174 hostProviderRegistry.unregister(hostProvider);
175 hostProviderService = null;
samanwita palb7900e52015-07-30 11:47:14 -0700176 cancelPackets();
samanwita pal18696f62015-07-17 13:15:43 -0700177 log.info("Stopped");
178 }
179
180 /**
181 * Request packet in via PacketService.
182 */
183 private void requestPackets() {
184
185 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
186 .matchEthType(Ethernet.TYPE_IPV4)
187 .matchIPProtocol(IPv4.PROTOCOL_UDP)
188 .matchUdpDst(UDP.DHCP_SERVER_PORT)
189 .matchUdpSrc(UDP.DHCP_CLIENT_PORT);
samanwita palb7900e52015-07-30 11:47:14 -0700190 packetService.requestPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
samanwita pal18696f62015-07-17 13:15:43 -0700191
samanwita palb7900e52015-07-30 11:47:14 -0700192 selectorServer = DefaultTrafficSelector.builder()
193 .matchEthType(Ethernet.TYPE_ARP);
194 packetService.requestPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
195 }
196
197 /**
198 * Cancel requested packets in via packet service.
199 */
200 private void cancelPackets() {
201 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
202 .matchEthType(Ethernet.TYPE_IPV4)
203 .matchIPProtocol(IPv4.PROTOCOL_UDP)
204 .matchUdpDst(UDP.DHCP_SERVER_PORT)
205 .matchUdpSrc(UDP.DHCP_CLIENT_PORT);
206 packetService.cancelPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
207
208 selectorServer = DefaultTrafficSelector.builder()
209 .matchEthType(Ethernet.TYPE_ARP);
210 packetService.cancelPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
samanwita pal18696f62015-07-17 13:15:43 -0700211 }
212
samanwita palf66ed8a2015-07-21 15:45:33 -0700213 @Override
214 public Map<MacAddress, Ip4Address> listMapping() {
215
216 return dhcpStore.listMapping();
217 }
218
219 @Override
220 public int getLeaseTime() {
221 return leaseTime;
222 }
223
224 @Override
225 public int getRenewalTime() {
226 return renewalTime;
227 }
228
229 @Override
230 public int getRebindingTime() {
231 return rebindingTime;
232 }
233
234 @Override
235 public boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress) {
236 return dhcpStore.assignStaticIP(macID, ipAddress);
237 }
238
239 @Override
240 public boolean removeStaticMapping(MacAddress macID) {
241 return dhcpStore.removeStaticIP(macID);
242 }
243
244 @Override
245 public Iterable<Ip4Address> getAvailableIPs() {
246 return dhcpStore.getAvailableIPs();
247 }
248
samanwita pal18696f62015-07-17 13:15:43 -0700249 private class DHCPPacketProcessor implements PacketProcessor {
250
251 /**
252 * Builds the DHCP Reply packet.
253 *
254 * @param packet the incoming Ethernet frame
255 * @param ipOffered the IP offered by the DHCP Server
256 * @param outgoingMessageType the message type of the outgoing packet
257 * @return the Ethernet reply frame
258 */
259 private Ethernet buildReply(Ethernet packet, String ipOffered, byte outgoingMessageType) {
samanwita pal775f6192015-07-28 10:10:13 -0700260 Ip4Address myIPAddress = Ip4Address.valueOf(myIP);
samanwita pal18696f62015-07-17 13:15:43 -0700261 Ip4Address ipAddress;
262
263 // Ethernet Frame.
264 Ethernet ethReply = new Ethernet();
samanwita pal775f6192015-07-28 10:10:13 -0700265 ethReply.setSourceMACAddress(myMAC);
samanwita pal18696f62015-07-17 13:15:43 -0700266 ethReply.setDestinationMACAddress(packet.getSourceMAC());
267 ethReply.setEtherType(Ethernet.TYPE_IPV4);
268 ethReply.setVlanID(packet.getVlanID());
269
270 // IP Packet
271 IPv4 ipv4Packet = (IPv4) packet.getPayload();
272 IPv4 ipv4Reply = new IPv4();
273 ipv4Reply.setSourceAddress(myIPAddress.toInt());
274 ipAddress = Ip4Address.valueOf(ipOffered);
275 ipv4Reply.setDestinationAddress(ipAddress.toInt());
276 ipv4Reply.setTtl(packetTTL);
277
278 // UDP Datagram.
279 UDP udpPacket = (UDP) ipv4Packet.getPayload();
280 UDP udpReply = new UDP();
281 udpReply.setSourcePort((byte) UDP.DHCP_SERVER_PORT);
282 udpReply.setDestinationPort((byte) UDP.DHCP_CLIENT_PORT);
283
284 // DHCP Payload.
285 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
286 DHCP dhcpReply = new DHCP();
287 dhcpReply.setOpCode(DHCP.OPCODE_REPLY);
288
289 ipAddress = Ip4Address.valueOf(ipOffered);
290 dhcpReply.setYourIPAddress(ipAddress.toInt());
291 dhcpReply.setServerIPAddress(myIPAddress.toInt());
292
293 dhcpReply.setTransactionId(dhcpPacket.getTransactionId());
294 dhcpReply.setClientHardwareAddress(dhcpPacket.getClientHardwareAddress());
295 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
296 dhcpReply.setHardwareAddressLength((byte) 6);
297
298 // DHCP Options.
299 DHCPOption option = new DHCPOption();
300 List<DHCPOption> optionList = new ArrayList<>();
301
302 // DHCP Message Type.
303 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
304 option.setLength((byte) 1);
305 byte[] optionData = {outgoingMessageType};
306 option.setData(optionData);
307 optionList.add(option);
308
309 // DHCP Server Identifier.
310 option = new DHCPOption();
311 option.setCode(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue());
312 option.setLength((byte) 4);
313 option.setData(myIPAddress.toOctets());
314 optionList.add(option);
315
316 // IP Address Lease Time.
317 option = new DHCPOption();
318 option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue());
319 option.setLength((byte) 4);
320 option.setData(ByteBuffer.allocate(4).putInt(leaseTime).array());
321 optionList.add(option);
322
323 // IP Address Renewal Time.
324 option = new DHCPOption();
325 option.setCode(DHCP.DHCPOptionCode.OptionCode_RenewalTime.getValue());
326 option.setLength((byte) 4);
327 option.setData(ByteBuffer.allocate(4).putInt(renewalTime).array());
328 optionList.add(option);
329
330 // IP Address Rebinding Time.
331 option = new DHCPOption();
332 option.setCode(DHCP.DHCPOptionCode.OPtionCode_RebindingTime.getValue());
333 option.setLength((byte) 4);
334 option.setData(ByteBuffer.allocate(4).putInt(rebindingTime).array());
335 optionList.add(option);
336
337 // Subnet Mask.
338 option = new DHCPOption();
339 option.setCode(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue());
340 option.setLength((byte) 4);
341 ipAddress = Ip4Address.valueOf(subnetMask);
342 option.setData(ipAddress.toOctets());
343 optionList.add(option);
344
345 // Broadcast Address.
346 option = new DHCPOption();
347 option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue());
348 option.setLength((byte) 4);
349 ipAddress = Ip4Address.valueOf(broadcastAddress);
350 option.setData(ipAddress.toOctets());
351 optionList.add(option);
352
353 // Router Address.
354 option = new DHCPOption();
355 option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue());
356 option.setLength((byte) 4);
samanwita pal792159a2015-07-28 14:07:01 -0700357 ipAddress = Ip4Address.valueOf(routerAddress);
358 option.setData(ipAddress.toOctets());
samanwita pal18696f62015-07-17 13:15:43 -0700359 optionList.add(option);
360
361 // DNS Server Address.
362 option = new DHCPOption();
363 option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue());
364 option.setLength((byte) 4);
samanwita pal792159a2015-07-28 14:07:01 -0700365 ipAddress = Ip4Address.valueOf(domainServer);
366 option.setData(ipAddress.toOctets());
samanwita pal18696f62015-07-17 13:15:43 -0700367 optionList.add(option);
368
369 // End Option.
370 option = new DHCPOption();
371 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
372 option.setLength((byte) 1);
373 optionList.add(option);
374
375 dhcpReply.setOptions(optionList);
376
377 udpReply.setPayload(dhcpReply);
378 ipv4Reply.setPayload(udpReply);
379 ethReply.setPayload(ipv4Reply);
380
381 return ethReply;
382 }
383
384 /**
385 * Sends the Ethernet reply frame via the Packet Service.
386 *
387 * @param context the context of the incoming frame
388 * @param reply the Ethernet reply frame
389 */
390 private void sendReply(PacketContext context, Ethernet reply) {
391 if (reply != null) {
392 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
393 ConnectPoint sourcePoint = context.inPacket().receivedFrom();
394 builder.setOutput(sourcePoint.port());
395
396 packetService.emit(new DefaultOutboundPacket(sourcePoint.deviceId(),
397 builder.build(), ByteBuffer.wrap(reply.serialize())));
398 }
399 }
400
401 /**
402 * Processes the DHCP Payload and initiates a reply to the client.
403 *
404 * @param context context of the incoming message
405 * @param dhcpPayload the extracted DHCP payload
406 */
407 private void processDHCPPacket(PacketContext context, DHCP dhcpPayload) {
408
409 Ethernet packet = context.inPacket().parsed();
410 boolean flagIfRequestedIP = false;
411 boolean flagIfServerIP = false;
412 Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0");
413 Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0");
414
415 if (dhcpPayload != null) {
416
417 // TODO Convert this to enum value.
418 byte incomingPacketType = 0;
419 for (DHCPOption option : dhcpPayload.getOptions()) {
420 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()) {
421 byte[] data = option.getData();
422 incomingPacketType = data[0];
423 }
424 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue()) {
425 byte[] data = option.getData();
426 requestedIP = Ip4Address.valueOf(data);
427 flagIfRequestedIP = true;
428 }
429 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()) {
430 byte[] data = option.getData();
431 serverIP = Ip4Address.valueOf(data);
432 flagIfServerIP = true;
433 }
434 }
435
436 String ipOffered = "";
437 DHCP.DHCPMessageType outgoingPacketType;
438 MacAddress clientMAC = new MacAddress(dhcpPayload.getClientHardwareAddress());
439
440 if (incomingPacketType == DHCP.DHCPMessageType.MessageType_Discover.getValue()) {
441
442 outgoingPacketType = DHCP.DHCPMessageType.MessageType_Offer;
samanwita palf09c09e2015-07-22 16:06:42 -0700443 ipOffered = dhcpStore.suggestIP(clientMAC, requestedIP).toString();
samanwita pal18696f62015-07-17 13:15:43 -0700444
445 Ethernet ethReply = buildReply(packet, ipOffered, outgoingPacketType.getValue());
446 sendReply(context, ethReply);
447
448 } else if (incomingPacketType == DHCP.DHCPMessageType.MessageType_Request.getValue()) {
449
450 outgoingPacketType = DHCP.DHCPMessageType.MessageType_ACK;
451
452 if (flagIfServerIP && flagIfRequestedIP) {
453 // SELECTING state
samanwita pal775f6192015-07-28 10:10:13 -0700454 if (myIP.equals(serverIP.toString()) &&
samanwita pal18696f62015-07-17 13:15:43 -0700455 dhcpStore.assignIP(clientMAC, requestedIP, leaseTime)) {
456
457 Ethernet ethReply = buildReply(packet, requestedIP.toString(),
458 outgoingPacketType.getValue());
459 sendReply(context, ethReply);
samanwita pale2983f52015-08-07 11:00:18 -0700460 discoverHost(context, requestedIP);
samanwita pal18696f62015-07-17 13:15:43 -0700461 }
462 } else if (flagIfRequestedIP) {
463 // INIT-REBOOT state
464 if (dhcpStore.assignIP(clientMAC, requestedIP, leaseTime)) {
465 Ethernet ethReply = buildReply(packet, requestedIP.toString(),
466 outgoingPacketType.getValue());
467 sendReply(context, ethReply);
samanwita pale2983f52015-08-07 11:00:18 -0700468 discoverHost(context, requestedIP);
samanwita pal18696f62015-07-17 13:15:43 -0700469 }
470 } else {
471 // RENEWING and REBINDING state
472 int ciaadr = dhcpPayload.getClientIPAddress();
473 if (ciaadr != 0) {
474 Ip4Address clientIaddr = Ip4Address.valueOf(ciaadr);
475 if (dhcpStore.assignIP(clientMAC, clientIaddr, leaseTime)) {
476 Ethernet ethReply = buildReply(packet, clientIaddr.toString(),
477 outgoingPacketType.getValue());
478 sendReply(context, ethReply);
samanwita pale2983f52015-08-07 11:00:18 -0700479 discoverHost(context, clientIaddr);
samanwita pal18696f62015-07-17 13:15:43 -0700480 }
481 }
482 }
483 } else if (incomingPacketType == DHCP.DHCPMessageType.MessageType_Release.getValue()) {
484
485 dhcpStore.releaseIP(clientMAC);
486 }
487 }
488 }
489
samanwita palb7900e52015-07-30 11:47:14 -0700490 /**
491 * Processes the ARP Payload and initiates a reply to the client.
492 *
493 * @param context context of the incoming message
494 * @param packet the ethernet payload
495 */
496 private void processARPPacket(PacketContext context, Ethernet packet) {
497
498 ARP arpPacket = (ARP) packet.getPayload();
499
500 ARP arpReply = (ARP) arpPacket.clone();
501 arpReply.setOpCode(ARP.OP_REPLY);
502
503 arpReply.setTargetProtocolAddress(arpPacket.getSenderProtocolAddress());
504 arpReply.setTargetHardwareAddress(arpPacket.getSenderHardwareAddress());
505 arpReply.setSenderProtocolAddress(arpPacket.getTargetProtocolAddress());
506 arpReply.setSenderHardwareAddress(myMAC.toBytes());
507
508 // Ethernet Frame.
509 Ethernet ethReply = new Ethernet();
510 ethReply.setSourceMACAddress(myMAC);
511 ethReply.setDestinationMACAddress(packet.getSourceMAC());
512 ethReply.setEtherType(Ethernet.TYPE_ARP);
513 ethReply.setVlanID(packet.getVlanID());
514
515 ethReply.setPayload(arpReply);
516 sendReply(context, ethReply);
517 }
518
samanwita pale2983f52015-08-07 11:00:18 -0700519 /**
520 * Integrates hosts learned through DHCP into topology.
521 * @param context context of the incoming message
522 * @param ipAssigned IP Address assigned to the host by DHCP Manager
523 */
524 private void discoverHost(PacketContext context, Ip4Address ipAssigned) {
525 Ethernet packet = context.inPacket().parsed();
526 MacAddress mac = packet.getSourceMAC();
527 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
528 HostLocation hostLocation = new HostLocation(context.inPacket().receivedFrom(), 0);
529
530 Set<IpAddress> ips = new HashSet<>();
531 ips.add(ipAssigned);
532
533 HostId hostId = HostId.hostId(mac, vlanId);
534 DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips);
535 hostProviderService.hostDetected(hostId, desc);
536 }
537
samanwita palb7900e52015-07-30 11:47:14 -0700538
samanwita pal18696f62015-07-17 13:15:43 -0700539 @Override
540 public void process(PacketContext context) {
541
samanwita pal18696f62015-07-17 13:15:43 -0700542 Ethernet packet = context.inPacket().parsed();
543 if (packet == null) {
544 return;
545 }
546
547 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
548 IPv4 ipv4Packet = (IPv4) packet.getPayload();
549
550 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
551 UDP udpPacket = (UDP) ipv4Packet.getPayload();
552
553 if (udpPacket.getDestinationPort() == UDP.DHCP_SERVER_PORT &&
554 udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT) {
555 // This is meant for the dhcp server so process the packet here.
556
557 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
558 processDHCPPacket(context, dhcpPayload);
559 }
560 }
samanwita palb7900e52015-07-30 11:47:14 -0700561 } else if (packet.getEtherType() == Ethernet.TYPE_ARP) {
562 ARP arpPacket = (ARP) packet.getPayload();
563
564 if ((arpPacket.getOpCode() == ARP.OP_REQUEST) &&
565 (Ip4Address.valueOf(arpPacket.getTargetProtocolAddress()).toString().equals(myIP))) {
566
567 processARPPacket(context, packet);
568
569 }
samanwita pal18696f62015-07-17 13:15:43 -0700570 }
571 }
572 }
samanwita pal775f6192015-07-28 10:10:13 -0700573
574 private class InternalConfigListener implements NetworkConfigListener {
575
576 /**
577 * Reconfigures the DHCP Server according to the configuration parameters passed.
578 *
579 * @param cfg configuration object
580 */
581 private void reconfigureNetwork(DHCPConfig cfg) {
582
583 if (cfg.ip() != null) {
584 myIP = cfg.ip();
585 }
586 if (cfg.mac() != null) {
587 myMAC = MacAddress.valueOf(cfg.mac());
588 }
589 if (cfg.subnetMask() != null) {
590 subnetMask = cfg.subnetMask();
591 }
592 if (cfg.broadcastAddress() != null) {
593 broadcastAddress = cfg.broadcastAddress();
594 }
samanwita pal792159a2015-07-28 14:07:01 -0700595 if (cfg.routerAddress() != null) {
596 routerAddress = cfg.routerAddress();
597 }
598 if (cfg.domainServer() != null) {
599 domainServer = cfg.domainServer();
600 }
samanwita pal775f6192015-07-28 10:10:13 -0700601 if (cfg.ttl() != null) {
602 packetTTL = Byte.valueOf(cfg.ttl());
603 }
604 if (cfg.leaseTime() != null) {
605 leaseTime = Integer.valueOf(cfg.leaseTime());
606 }
607 if (cfg.renewTime() != null) {
608 renewalTime = Integer.valueOf(cfg.renewTime());
609 }
610 if (cfg.rebindTime() != null) {
611 rebindingTime = Integer.valueOf(cfg.rebindTime());
612 }
613 }
614
615 /**
616 * Reconfigures the DHCP Store according to the configuration parameters passed.
617 *
618 * @param cfg configuration object
619 */
620 private void reconfigureStore(DHCPStoreConfig cfg) {
621
622 if (cfg.defaultTimeout() != null) {
623 dhcpStore.setDefaultTimeoutForPurge(Integer.valueOf(cfg.defaultTimeout()));
624 }
625 if (cfg.timerDelay() != null) {
626 dhcpStore.setTimerDelay(Integer.valueOf(cfg.defaultTimeout()));
627 }
628 if ((cfg.startIP() != null) && (cfg.endIP() != null)) {
samanwita palb7900e52015-07-30 11:47:14 -0700629 dhcpStore.populateIPPoolfromRange(Ip4Address.valueOf(cfg.startIP()),
630 Ip4Address.valueOf(cfg.endIP()));
samanwita pal775f6192015-07-28 10:10:13 -0700631 }
632 }
633
634 @Override
635 public void event(NetworkConfigEvent event) {
636
637 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
638 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
639 if (event.configClass().equals(DHCPConfig.class)) {
640 DHCPConfig cfg = cfgService.getConfig(appId, DHCPConfig.class);
641 reconfigureNetwork(cfg);
642 log.info("Reconfigured Manager");
643 }
644 if (event.configClass().equals(DHCPStoreConfig.class)) {
645 DHCPStoreConfig cfg = cfgService.getConfig(appId, DHCPStoreConfig.class);
646 reconfigureStore(cfg);
647 log.info("Reconfigured Store");
648 }
samanwita pal775f6192015-07-28 10:10:13 -0700649 }
samanwita pal775f6192015-07-28 10:10:13 -0700650 }
651 }
samanwita pale2983f52015-08-07 11:00:18 -0700652
653 private class InternalHostProvider extends AbstractProvider implements HostProvider {
654
655 /**
656 * Creates a provider with the supplier identifier.
657 */
658 protected InternalHostProvider() {
659 super(PID);
660 }
661
662 @Override
663 public void triggerProbe(Host host) {
664 // nothing to do
665 }
666 }
samanwita pal18696f62015-07-17 13:15:43 -0700667}