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