blob: 99cc731955835ff68e11f5922794de80fe24f36b [file] [log] [blame]
samanwita palf28207b2015-09-04 10:41:56 -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 */
16package org.onosproject.dhcp.impl;
17
18import com.google.common.collect.ImmutableSet;
19import 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;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.packet.ARP;
26import org.onlab.packet.DHCP;
27import org.onlab.packet.DHCPOption;
samanwita pal8969cbe2015-09-04 13:31:30 -070028import org.onlab.packet.DHCPPacketType;
samanwita palf28207b2015-09-04 10:41:56 -070029import org.onlab.packet.Ethernet;
30import org.onlab.packet.IPv4;
31import org.onlab.packet.Ip4Address;
32import org.onlab.packet.IpAddress;
33import org.onlab.packet.MacAddress;
34import org.onlab.packet.TpPort;
35import org.onlab.packet.UDP;
36import org.onlab.packet.VlanId;
37import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -070039import org.onosproject.dhcp.DhcpService;
40import org.onosproject.dhcp.DhcpStore;
41import org.onosproject.dhcp.IpAssignment;
samanwita palf28207b2015-09-04 10:41:56 -070042import org.onosproject.net.config.ConfigFactory;
43import org.onosproject.net.config.NetworkConfigEvent;
44import org.onosproject.net.config.NetworkConfigListener;
45import org.onosproject.net.config.NetworkConfigRegistry;
46
47import org.onosproject.net.ConnectPoint;
48import org.onosproject.net.Host;
49import org.onosproject.net.HostId;
50import org.onosproject.net.HostLocation;
51import org.onosproject.net.flow.DefaultTrafficSelector;
52import org.onosproject.net.flow.DefaultTrafficTreatment;
53import org.onosproject.net.flow.TrafficSelector;
54import org.onosproject.net.flow.TrafficTreatment;
55import org.onosproject.net.host.DefaultHostDescription;
56import org.onosproject.net.host.HostProvider;
57import org.onosproject.net.host.HostProviderRegistry;
58import org.onosproject.net.host.HostProviderService;
59import org.onosproject.net.packet.DefaultOutboundPacket;
60import org.onosproject.net.packet.PacketContext;
61import org.onosproject.net.packet.PacketPriority;
62import org.onosproject.net.packet.PacketProcessor;
63import org.onosproject.net.packet.PacketService;
64import org.onosproject.net.provider.AbstractProvider;
65import org.onosproject.net.provider.ProviderId;
66import org.slf4j.Logger;
67import org.slf4j.LoggerFactory;
68
69import java.nio.ByteBuffer;
70import java.util.ArrayList;
71import java.util.HashSet;
72import java.util.List;
73import java.util.Map;
74import java.util.Set;
75
76import static org.onlab.packet.MacAddress.valueOf;
77import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
78
79/**
80 * Skeletal ONOS DHCP Server application.
81 */
82@Component(immediate = true)
83@Service
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -070084public class DhcpManager implements DhcpService {
samanwita palf28207b2015-09-04 10:41:56 -070085
86 private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcp", true);
87 private final Logger log = LoggerFactory.getLogger(getClass());
88
Thomas Vachuska00090442015-09-11 18:08:04 -070089 private final InternalConfigListener cfgListener = new InternalConfigListener();
samanwita palf28207b2015-09-04 10:41:56 -070090
91 private final Set<ConfigFactory> factories = ImmutableSet.of(
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -070092 new ConfigFactory<ApplicationId, DhcpConfig>(APP_SUBJECT_FACTORY,
93 DhcpConfig.class,
samanwita palf28207b2015-09-04 10:41:56 -070094 "dhcp") {
95 @Override
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -070096 public DhcpConfig createConfig() {
97 return new DhcpConfig();
samanwita palf28207b2015-09-04 10:41:56 -070098 }
99 },
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700100 new ConfigFactory<ApplicationId, DhcpStoreConfig>(APP_SUBJECT_FACTORY,
101 DhcpStoreConfig.class,
samanwita palf28207b2015-09-04 10:41:56 -0700102 "dhcpstore") {
103 @Override
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700104 public DhcpStoreConfig createConfig() {
105 return new DhcpStoreConfig();
samanwita palf28207b2015-09-04 10:41:56 -0700106 }
107 }
108 );
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected NetworkConfigRegistry cfgService;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected PacketService packetService;
114
115 private DHCPPacketProcessor processor = new DHCPPacketProcessor();
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected CoreService coreService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700121 protected DhcpStore dhcpStore;
samanwita palf28207b2015-09-04 10:41:56 -0700122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected HostProviderRegistry hostProviderRegistry;
125
126 protected HostProviderService hostProviderService;
127
128 private ApplicationId appId;
129
130 // Hardcoded values are default values.
131
132 private static String myIP = "10.0.0.2";
133
134 private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f");
135
136 /**
137 * leaseTime - 10 mins or 600s.
138 * renewalTime - 5 mins or 300s.
139 * rebindingTime - 6 mins or 360s.
140 */
141
142 private static int leaseTime = 600;
143
144 private static int renewalTime = 300;
145
146 private static int rebindingTime = 360;
147
148 private static byte packetTTL = (byte) 127;
149
150 private static String subnetMask = "255.0.0.0";
151
152 private static String broadcastAddress = "10.255.255.255";
153
154 private static String routerAddress = "10.0.0.2";
155
156 private static String domainServer = "10.0.0.2";
157 private final HostProvider hostProvider = new InternalHostProvider();
158
159 @Activate
160 protected void activate() {
161 // start the dhcp server
162 appId = coreService.registerApplication("org.onosproject.dhcp");
163
164 cfgService.addListener(cfgListener);
165 factories.forEach(cfgService::registerConfigFactory);
Thomas Vachuska00090442015-09-11 18:08:04 -0700166 cfgListener.reconfigureNetwork(cfgService.getConfig(appId, DhcpConfig.class));
167 cfgListener.reconfigureStore(cfgService.getConfig(appId, DhcpStoreConfig.class));
168
samanwita palf28207b2015-09-04 10:41:56 -0700169 hostProviderService = hostProviderRegistry.register(hostProvider);
Thomas Vachuska00090442015-09-11 18:08:04 -0700170 packetService.addProcessor(processor, PacketProcessor.director(1));
samanwita palf28207b2015-09-04 10:41:56 -0700171 requestPackets();
172 log.info("Started");
173 }
174
175 @Deactivate
176 protected void deactivate() {
177 cfgService.removeListener(cfgListener);
178 factories.forEach(cfgService::unregisterConfigFactory);
179 packetService.removeProcessor(processor);
180 hostProviderRegistry.unregister(hostProvider);
181 hostProviderService = null;
182 cancelPackets();
183 log.info("Stopped");
184 }
185
186 /**
187 * Request packet in via PacketService.
188 */
189 private void requestPackets() {
190
191 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
192 .matchEthType(Ethernet.TYPE_IPV4)
193 .matchIPProtocol(IPv4.PROTOCOL_UDP)
194 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
195 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
196 packetService.requestPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
197
198 selectorServer = DefaultTrafficSelector.builder()
199 .matchEthType(Ethernet.TYPE_ARP);
200 packetService.requestPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
201 }
202
203 /**
204 * Cancel requested packets in via packet service.
205 */
206 private void cancelPackets() {
207 TrafficSelector.Builder selectorServer = DefaultTrafficSelector.builder()
208 .matchEthType(Ethernet.TYPE_IPV4)
209 .matchIPProtocol(IPv4.PROTOCOL_UDP)
210 .matchUdpDst(TpPort.tpPort(UDP.DHCP_SERVER_PORT))
211 .matchUdpSrc(TpPort.tpPort(UDP.DHCP_CLIENT_PORT));
212 packetService.cancelPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
213
214 selectorServer = DefaultTrafficSelector.builder()
215 .matchEthType(Ethernet.TYPE_ARP);
216 packetService.cancelPackets(selectorServer.build(), PacketPriority.CONTROL, appId);
217 }
218
219 @Override
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700220 public Map<MacAddress, IpAssignment> listMapping() {
samanwita palf28207b2015-09-04 10:41:56 -0700221 return dhcpStore.listMapping();
222 }
223
224 @Override
225 public int getLeaseTime() {
226 return leaseTime;
227 }
228
229 @Override
230 public int getRenewalTime() {
231 return renewalTime;
232 }
233
234 @Override
235 public int getRebindingTime() {
236 return rebindingTime;
237 }
238
239 @Override
240 public boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress) {
241 return dhcpStore.assignStaticIP(macID, ipAddress);
242 }
243
244 @Override
245 public boolean removeStaticMapping(MacAddress macID) {
246 return dhcpStore.removeStaticIP(macID);
247 }
248
249 @Override
250 public Iterable<Ip4Address> getAvailableIPs() {
251 return dhcpStore.getAvailableIPs();
252 }
253
254 private class DHCPPacketProcessor implements PacketProcessor {
255
256 /**
257 * Builds the DHCP Reply packet.
258 *
259 * @param packet the incoming Ethernet frame
260 * @param ipOffered the IP offered by the DHCP Server
261 * @param outgoingMessageType the message type of the outgoing packet
262 * @return the Ethernet reply frame
263 */
264 private Ethernet buildReply(Ethernet packet, String ipOffered, byte outgoingMessageType) {
265 Ip4Address myIPAddress = Ip4Address.valueOf(myIP);
266 Ip4Address ipAddress;
267
268 // Ethernet Frame.
269 Ethernet ethReply = new Ethernet();
270 ethReply.setSourceMACAddress(myMAC);
271 ethReply.setDestinationMACAddress(packet.getSourceMAC());
272 ethReply.setEtherType(Ethernet.TYPE_IPV4);
273 ethReply.setVlanID(packet.getVlanID());
274
275 // IP Packet
276 IPv4 ipv4Packet = (IPv4) packet.getPayload();
277 IPv4 ipv4Reply = new IPv4();
278 ipv4Reply.setSourceAddress(myIPAddress.toInt());
279 ipAddress = Ip4Address.valueOf(ipOffered);
280 ipv4Reply.setDestinationAddress(ipAddress.toInt());
281 ipv4Reply.setTtl(packetTTL);
282
283 // UDP Datagram.
284 UDP udpPacket = (UDP) ipv4Packet.getPayload();
285 UDP udpReply = new UDP();
286 udpReply.setSourcePort((byte) UDP.DHCP_SERVER_PORT);
287 udpReply.setDestinationPort((byte) UDP.DHCP_CLIENT_PORT);
288
289 // DHCP Payload.
290 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
291 DHCP dhcpReply = new DHCP();
292 dhcpReply.setOpCode(DHCP.OPCODE_REPLY);
293
294 ipAddress = Ip4Address.valueOf(ipOffered);
295 dhcpReply.setYourIPAddress(ipAddress.toInt());
296 dhcpReply.setServerIPAddress(myIPAddress.toInt());
297
298 dhcpReply.setTransactionId(dhcpPacket.getTransactionId());
299 dhcpReply.setClientHardwareAddress(dhcpPacket.getClientHardwareAddress());
300 dhcpReply.setHardwareType(DHCP.HWTYPE_ETHERNET);
301 dhcpReply.setHardwareAddressLength((byte) 6);
302
303 // DHCP Options.
304 DHCPOption option = new DHCPOption();
305 List<DHCPOption> optionList = new ArrayList<>();
306
307 // DHCP Message Type.
308 option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
309 option.setLength((byte) 1);
310 byte[] optionData = {outgoingMessageType};
311 option.setData(optionData);
312 optionList.add(option);
313
314 // DHCP Server Identifier.
315 option = new DHCPOption();
316 option.setCode(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue());
317 option.setLength((byte) 4);
318 option.setData(myIPAddress.toOctets());
319 optionList.add(option);
320
321 // IP Address Lease Time.
322 option = new DHCPOption();
323 option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue());
324 option.setLength((byte) 4);
325 option.setData(ByteBuffer.allocate(4).putInt(leaseTime).array());
326 optionList.add(option);
327
328 // IP Address Renewal Time.
329 option = new DHCPOption();
330 option.setCode(DHCP.DHCPOptionCode.OptionCode_RenewalTime.getValue());
331 option.setLength((byte) 4);
332 option.setData(ByteBuffer.allocate(4).putInt(renewalTime).array());
333 optionList.add(option);
334
335 // IP Address Rebinding Time.
336 option = new DHCPOption();
337 option.setCode(DHCP.DHCPOptionCode.OPtionCode_RebindingTime.getValue());
338 option.setLength((byte) 4);
339 option.setData(ByteBuffer.allocate(4).putInt(rebindingTime).array());
340 optionList.add(option);
341
342 // Subnet Mask.
343 option = new DHCPOption();
344 option.setCode(DHCP.DHCPOptionCode.OptionCode_SubnetMask.getValue());
345 option.setLength((byte) 4);
346 ipAddress = Ip4Address.valueOf(subnetMask);
347 option.setData(ipAddress.toOctets());
348 optionList.add(option);
349
350 // Broadcast Address.
351 option = new DHCPOption();
352 option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue());
353 option.setLength((byte) 4);
354 ipAddress = Ip4Address.valueOf(broadcastAddress);
355 option.setData(ipAddress.toOctets());
356 optionList.add(option);
357
358 // Router Address.
359 option = new DHCPOption();
360 option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue());
361 option.setLength((byte) 4);
362 ipAddress = Ip4Address.valueOf(routerAddress);
363 option.setData(ipAddress.toOctets());
364 optionList.add(option);
365
366 // DNS Server Address.
367 option = new DHCPOption();
368 option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue());
369 option.setLength((byte) 4);
370 ipAddress = Ip4Address.valueOf(domainServer);
371 option.setData(ipAddress.toOctets());
372 optionList.add(option);
373
374 // End Option.
375 option = new DHCPOption();
376 option.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
377 option.setLength((byte) 1);
378 optionList.add(option);
379
380 dhcpReply.setOptions(optionList);
381
382 udpReply.setPayload(dhcpReply);
383 ipv4Reply.setPayload(udpReply);
384 ethReply.setPayload(ipv4Reply);
385
386 return ethReply;
387 }
388
389 /**
390 * Sends the Ethernet reply frame via the Packet Service.
391 *
392 * @param context the context of the incoming frame
393 * @param reply the Ethernet reply frame
394 */
395 private void sendReply(PacketContext context, Ethernet reply) {
396 if (reply != null) {
397 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
398 ConnectPoint sourcePoint = context.inPacket().receivedFrom();
399 builder.setOutput(sourcePoint.port());
Thomas Vachuska00090442015-09-11 18:08:04 -0700400 context.block();
samanwita palf28207b2015-09-04 10:41:56 -0700401 packetService.emit(new DefaultOutboundPacket(sourcePoint.deviceId(),
samanwita pal8969cbe2015-09-04 13:31:30 -0700402 builder.build(), ByteBuffer.wrap(reply.serialize())));
samanwita palf28207b2015-09-04 10:41:56 -0700403 }
404 }
405
406 /**
407 * Processes the DHCP Payload and initiates a reply to the client.
408 *
409 * @param context context of the incoming message
410 * @param dhcpPayload the extracted DHCP payload
411 */
412 private void processDHCPPacket(PacketContext context, DHCP dhcpPayload) {
samanwita palf28207b2015-09-04 10:41:56 -0700413 Ethernet packet = context.inPacket().parsed();
414 boolean flagIfRequestedIP = false;
415 boolean flagIfServerIP = false;
416 Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0");
417 Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0");
418
419 if (dhcpPayload != null) {
420
421 // TODO Convert this to enum value.
422 byte incomingPacketType = 0;
423 for (DHCPOption option : dhcpPayload.getOptions()) {
424 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()) {
425 byte[] data = option.getData();
426 incomingPacketType = data[0];
427 }
428 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue()) {
429 byte[] data = option.getData();
430 requestedIP = Ip4Address.valueOf(data);
431 flagIfRequestedIP = true;
432 }
433 if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()) {
434 byte[] data = option.getData();
435 serverIP = Ip4Address.valueOf(data);
436 flagIfServerIP = true;
437 }
438 }
439
440 String ipOffered = "";
samanwita pal8969cbe2015-09-04 13:31:30 -0700441 DHCPPacketType outgoingPacketType;
samanwita palf28207b2015-09-04 10:41:56 -0700442 MacAddress clientMAC = new MacAddress(dhcpPayload.getClientHardwareAddress());
443
samanwita pal8969cbe2015-09-04 13:31:30 -0700444 if (incomingPacketType == DHCPPacketType.DHCPDISCOVER.getValue()) {
samanwita palf28207b2015-09-04 10:41:56 -0700445
samanwita pal8969cbe2015-09-04 13:31:30 -0700446 outgoingPacketType = DHCPPacketType.DHCPOFFER;
samanwita palf28207b2015-09-04 10:41:56 -0700447 ipOffered = dhcpStore.suggestIP(clientMAC, requestedIP).toString();
448
samanwita pal8969cbe2015-09-04 13:31:30 -0700449 Ethernet ethReply = buildReply(packet, ipOffered, (byte) outgoingPacketType.getValue());
samanwita palf28207b2015-09-04 10:41:56 -0700450 sendReply(context, ethReply);
451
samanwita pal8969cbe2015-09-04 13:31:30 -0700452 } else if (incomingPacketType == DHCPPacketType.DHCPREQUEST.getValue()) {
samanwita palf28207b2015-09-04 10:41:56 -0700453
samanwita pal8969cbe2015-09-04 13:31:30 -0700454 outgoingPacketType = DHCPPacketType.DHCPACK;
samanwita palf28207b2015-09-04 10:41:56 -0700455
456 if (flagIfServerIP && flagIfRequestedIP) {
457 // SELECTING state
458 if (myIP.equals(serverIP.toString()) &&
459 dhcpStore.assignIP(clientMAC, requestedIP, leaseTime)) {
460
461 Ethernet ethReply = buildReply(packet, requestedIP.toString(),
samanwita pal8969cbe2015-09-04 13:31:30 -0700462 (byte) outgoingPacketType.getValue());
samanwita palf28207b2015-09-04 10:41:56 -0700463 sendReply(context, ethReply);
464 discoverHost(context, requestedIP);
465 }
466 } else if (flagIfRequestedIP) {
467 // INIT-REBOOT state
468 if (dhcpStore.assignIP(clientMAC, requestedIP, leaseTime)) {
469 Ethernet ethReply = buildReply(packet, requestedIP.toString(),
samanwita pal8969cbe2015-09-04 13:31:30 -0700470 (byte) outgoingPacketType.getValue());
samanwita palf28207b2015-09-04 10:41:56 -0700471 sendReply(context, ethReply);
472 discoverHost(context, requestedIP);
473 }
474 } else {
475 // RENEWING and REBINDING state
476 int ciaadr = dhcpPayload.getClientIPAddress();
477 if (ciaadr != 0) {
478 Ip4Address clientIaddr = Ip4Address.valueOf(ciaadr);
479 if (dhcpStore.assignIP(clientMAC, clientIaddr, leaseTime)) {
480 Ethernet ethReply = buildReply(packet, clientIaddr.toString(),
samanwita pal8969cbe2015-09-04 13:31:30 -0700481 (byte) outgoingPacketType.getValue());
samanwita palf28207b2015-09-04 10:41:56 -0700482 sendReply(context, ethReply);
483 discoverHost(context, clientIaddr);
484 }
485 }
486 }
samanwita pal8969cbe2015-09-04 13:31:30 -0700487 } else if (incomingPacketType == DHCPPacketType.DHCPRELEASE.getValue()) {
samanwita palf28207b2015-09-04 10:41:56 -0700488 dhcpStore.releaseIP(clientMAC);
489 }
490 }
491 }
492
493 /**
494 * Processes the ARP Payload and initiates a reply to the client.
495 *
496 * @param context context of the incoming message
497 * @param packet the ethernet payload
498 */
499 private void processARPPacket(PacketContext context, Ethernet packet) {
500
501 ARP arpPacket = (ARP) packet.getPayload();
502
503 ARP arpReply = (ARP) arpPacket.clone();
504 arpReply.setOpCode(ARP.OP_REPLY);
505
506 arpReply.setTargetProtocolAddress(arpPacket.getSenderProtocolAddress());
507 arpReply.setTargetHardwareAddress(arpPacket.getSenderHardwareAddress());
508 arpReply.setSenderProtocolAddress(arpPacket.getTargetProtocolAddress());
509 arpReply.setSenderHardwareAddress(myMAC.toBytes());
510
511 // Ethernet Frame.
512 Ethernet ethReply = new Ethernet();
513 ethReply.setSourceMACAddress(myMAC);
514 ethReply.setDestinationMACAddress(packet.getSourceMAC());
515 ethReply.setEtherType(Ethernet.TYPE_ARP);
516 ethReply.setVlanID(packet.getVlanID());
517
518 ethReply.setPayload(arpReply);
519 sendReply(context, ethReply);
520 }
521
522 /**
523 * Integrates hosts learned through DHCP into topology.
524 * @param context context of the incoming message
525 * @param ipAssigned IP Address assigned to the host by DHCP Manager
526 */
527 private void discoverHost(PacketContext context, Ip4Address ipAssigned) {
528 Ethernet packet = context.inPacket().parsed();
529 MacAddress mac = packet.getSourceMAC();
530 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
531 HostLocation hostLocation = new HostLocation(context.inPacket().receivedFrom(), 0);
532
533 Set<IpAddress> ips = new HashSet<>();
534 ips.add(ipAssigned);
535
536 HostId hostId = HostId.hostId(mac, vlanId);
537 DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips);
538 hostProviderService.hostDetected(hostId, desc);
539 }
540
541
542 @Override
543 public void process(PacketContext context) {
samanwita palf28207b2015-09-04 10:41:56 -0700544 Ethernet packet = context.inPacket().parsed();
545 if (packet == null) {
546 return;
547 }
548
549 if (packet.getEtherType() == Ethernet.TYPE_IPV4) {
550 IPv4 ipv4Packet = (IPv4) packet.getPayload();
551
552 if (ipv4Packet.getProtocol() == IPv4.PROTOCOL_UDP) {
553 UDP udpPacket = (UDP) ipv4Packet.getPayload();
554
555 if (udpPacket.getDestinationPort() == UDP.DHCP_SERVER_PORT &&
556 udpPacket.getSourcePort() == UDP.DHCP_CLIENT_PORT) {
557 // This is meant for the dhcp server so process the packet here.
558
559 DHCP dhcpPayload = (DHCP) udpPacket.getPayload();
560 processDHCPPacket(context, dhcpPayload);
561 }
562 }
563 } else if (packet.getEtherType() == Ethernet.TYPE_ARP) {
564 ARP arpPacket = (ARP) packet.getPayload();
565
566 if ((arpPacket.getOpCode() == ARP.OP_REQUEST) &&
567 (Ip4Address.valueOf(arpPacket.getTargetProtocolAddress()).toString().equals(myIP))) {
568
569 processARPPacket(context, packet);
570
571 }
572 }
573 }
574 }
575
576 private class InternalConfigListener implements NetworkConfigListener {
577
578 /**
579 * Reconfigures the DHCP Server according to the configuration parameters passed.
580 *
581 * @param cfg configuration object
582 */
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700583 private void reconfigureNetwork(DhcpConfig cfg) {
Thomas Vachuska00090442015-09-11 18:08:04 -0700584 if (cfg == null) {
585 return;
586 }
samanwita palf28207b2015-09-04 10:41:56 -0700587 if (cfg.ip() != null) {
588 myIP = cfg.ip();
589 }
590 if (cfg.mac() != null) {
591 myMAC = MacAddress.valueOf(cfg.mac());
592 }
593 if (cfg.subnetMask() != null) {
594 subnetMask = cfg.subnetMask();
595 }
596 if (cfg.broadcastAddress() != null) {
597 broadcastAddress = cfg.broadcastAddress();
598 }
599 if (cfg.routerAddress() != null) {
600 routerAddress = cfg.routerAddress();
601 }
602 if (cfg.domainServer() != null) {
603 domainServer = cfg.domainServer();
604 }
605 if (cfg.ttl() != null) {
606 packetTTL = Byte.valueOf(cfg.ttl());
607 }
608 if (cfg.leaseTime() != null) {
609 leaseTime = Integer.valueOf(cfg.leaseTime());
610 }
611 if (cfg.renewTime() != null) {
612 renewalTime = Integer.valueOf(cfg.renewTime());
613 }
614 if (cfg.rebindTime() != null) {
615 rebindingTime = Integer.valueOf(cfg.rebindTime());
616 }
617 }
618
619 /**
620 * Reconfigures the DHCP Store according to the configuration parameters passed.
621 *
622 * @param cfg configuration object
623 */
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700624 private void reconfigureStore(DhcpStoreConfig cfg) {
Thomas Vachuska00090442015-09-11 18:08:04 -0700625 if (cfg == null) {
626 return;
627 }
samanwita palf28207b2015-09-04 10:41:56 -0700628
629 if (cfg.defaultTimeout() != null) {
630 dhcpStore.setDefaultTimeoutForPurge(Integer.valueOf(cfg.defaultTimeout()));
631 }
632 if (cfg.timerDelay() != null) {
633 dhcpStore.setTimerDelay(Integer.valueOf(cfg.defaultTimeout()));
634 }
635 if ((cfg.startIP() != null) && (cfg.endIP() != null)) {
636 dhcpStore.populateIPPoolfromRange(Ip4Address.valueOf(cfg.startIP()),
samanwita pal8969cbe2015-09-04 13:31:30 -0700637 Ip4Address.valueOf(cfg.endIP()));
samanwita palf28207b2015-09-04 10:41:56 -0700638 }
639 }
640
641 @Override
642 public void event(NetworkConfigEvent event) {
643
644 if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
645 event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) {
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700646 if (event.configClass().equals(DhcpConfig.class)) {
647 DhcpConfig cfg = cfgService.getConfig(appId, DhcpConfig.class);
samanwita palf28207b2015-09-04 10:41:56 -0700648 reconfigureNetwork(cfg);
649 log.info("Reconfigured Manager");
650 }
Thomas Vachuskaa1da42e2015-09-09 00:45:22 -0700651 if (event.configClass().equals(DhcpStoreConfig.class)) {
652 DhcpStoreConfig cfg = cfgService.getConfig(appId, DhcpStoreConfig.class);
samanwita palf28207b2015-09-04 10:41:56 -0700653 reconfigureStore(cfg);
654 log.info("Reconfigured Store");
655 }
656 }
657 }
658 }
659
660 private class InternalHostProvider extends AbstractProvider implements HostProvider {
661
662 /**
663 * Creates a provider with the supplier identifier.
664 */
665 protected InternalHostProvider() {
666 super(PID);
667 }
668
669 @Override
670 public void triggerProbe(Host host) {
671 // nothing to do
672 }
673 }
674}