Hyunsun Moon

Make some DHCP options and host discovery configurable

- Added broadcast option
- Made host discovery from DHCP configurable
- Some code cleanups

Change-Id: I42191c2fd17ef309c73a5382730d708686b835cd
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.cordvtn.impl; 16 package org.onosproject.cordvtn.impl;
17 17
18 -import com.google.common.collect.Lists;
19 import com.google.common.collect.Sets; 18 import com.google.common.collect.Sets;
20 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
...@@ -34,6 +33,7 @@ import org.onosproject.cordvtn.api.Instance; ...@@ -34,6 +33,7 @@ import org.onosproject.cordvtn.api.Instance;
34 import org.onosproject.core.ApplicationId; 33 import org.onosproject.core.ApplicationId;
35 import org.onosproject.core.CoreService; 34 import org.onosproject.core.CoreService;
36 import org.onosproject.dhcp.DhcpService; 35 import org.onosproject.dhcp.DhcpService;
36 +import org.onosproject.dhcp.IpAssignment;
37 import org.onosproject.mastership.MastershipService; 37 import org.onosproject.mastership.MastershipService;
38 import org.onosproject.net.ConnectPoint; 38 import org.onosproject.net.ConnectPoint;
39 import org.onosproject.net.DefaultAnnotations; 39 import org.onosproject.net.DefaultAnnotations;
...@@ -70,7 +70,7 @@ import org.onosproject.xosclient.api.XosAccess; ...@@ -70,7 +70,7 @@ import org.onosproject.xosclient.api.XosAccess;
70 import org.onosproject.xosclient.api.XosClientService; 70 import org.onosproject.xosclient.api.XosClientService;
71 import org.slf4j.Logger; 71 import org.slf4j.Logger;
72 72
73 -import java.util.List; 73 +import java.util.Date;
74 import java.util.Map; 74 import java.util.Map;
75 import java.util.Objects; 75 import java.util.Objects;
76 import java.util.Set; 76 import java.util.Set;
...@@ -82,6 +82,8 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -82,6 +82,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
82 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; 82 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
83 import static org.onlab.util.Tools.groupedThreads; 83 import static org.onlab.util.Tools.groupedThreads;
84 import static org.onosproject.cordvtn.api.Instance.*; 84 import static org.onosproject.cordvtn.api.Instance.*;
85 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
86 +import static org.onosproject.xosclient.api.VtnService.NetworkType.MANAGEMENT;
85 import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE; 87 import static org.onosproject.xosclient.api.VtnService.NetworkType.PRIVATE;
86 import static org.slf4j.LoggerFactory.getLogger; 88 import static org.slf4j.LoggerFactory.getLogger;
87 89
...@@ -97,6 +99,7 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv ...@@ -97,6 +99,7 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv
97 private static final String XOS_ACCESS_ERROR = "XOS access is not configured"; 99 private static final String XOS_ACCESS_ERROR = "XOS access is not configured";
98 private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured"; 100 private static final String OPENSTACK_ACCESS_ERROR = "OpenStack access is not configured";
99 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8"); 101 private static final Ip4Address DEFAULT_DNS = Ip4Address.valueOf("8.8.8.8");
102 + private static final int DHCP_INFINITE_LEASE = -1;
100 103
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected CoreService coreService; 105 protected CoreService coreService;
...@@ -273,7 +276,6 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv ...@@ -273,7 +276,6 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv
273 arpProxy.addGateway(service.serviceIp(), privateGatewayMac); 276 arpProxy.addGateway(service.serviceIp(), privateGatewayMac);
274 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance)); 277 arpProxy.sendGratuitousArpForGateway(service.serviceIp(), Sets.newHashSet(instance));
275 } 278 }
276 -
277 if (!instance.isNestedInstance()) { 279 if (!instance.isNestedInstance()) {
278 registerDhcpLease(instance, service); 280 registerDhcpLease(instance, service);
279 } 281 }
...@@ -295,17 +297,25 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv ...@@ -295,17 +297,25 @@ public class CordVtnInstanceManager extends AbstractProvider implements HostProv
295 } 297 }
296 298
297 private void registerDhcpLease(Instance instance, VtnService service) { 299 private void registerDhcpLease(Instance instance, VtnService service) {
298 - List<Ip4Address> options = Lists.newArrayList(); 300 + Ip4Address broadcast = Ip4Address.makeMaskedAddress(
299 - options.add(Ip4Address.makeMaskPrefix(service.subnet().prefixLength())); 301 + instance.ipAddress(),
300 - options.add(service.serviceIp().getIp4Address()); 302 + service.subnet().prefixLength());
301 - options.add(service.serviceIp().getIp4Address()); 303 +
302 - options.add(DEFAULT_DNS); 304 + IpAssignment.Builder ipBuilder = IpAssignment.builder()
305 + .ipAddress(instance.ipAddress())
306 + .leasePeriod(DHCP_INFINITE_LEASE)
307 + .timestamp(new Date())
308 + .subnetMask(Ip4Address.makeMaskPrefix(service.subnet().prefixLength()))
309 + .broadcast(broadcast)
310 + .domainServer(DEFAULT_DNS)
311 + .assignmentStatus(Option_RangeNotEnforced);
312 +
313 + if (service.networkType() != MANAGEMENT) {
314 + ipBuilder = ipBuilder.routerAddress(service.serviceIp().getIp4Address());
315 + }
303 316
304 log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress()); 317 log.debug("Set static DHCP mapping for {} {}", instance.mac(), instance.ipAddress());
305 - dhcpService.setStaticMapping(instance.mac(), 318 + dhcpService.setStaticMapping(instance.mac(), ipBuilder.build());
306 - instance.ipAddress(),
307 - true,
308 - options);
309 } 319 }
310 320
311 private VtnService getVtnService(VtnServiceId serviceId) { 321 private VtnService getVtnService(VtnServiceId serviceId) {
......
...@@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; ...@@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address;
19 import org.onlab.packet.MacAddress; 19 import org.onlab.packet.MacAddress;
20 import org.onosproject.net.HostId; 20 import org.onosproject.net.HostId;
21 21
22 -import java.util.List;
23 import java.util.Map; 22 import java.util.Map;
24 23
25 24
...@@ -58,16 +57,12 @@ public interface DhcpService { ...@@ -58,16 +57,12 @@ public interface DhcpService {
58 57
59 /** 58 /**
60 * Registers a static IP mapping with the DHCP Server. 59 * Registers a static IP mapping with the DHCP Server.
61 - * Supports rangeNotEnforced option
62 * 60 *
63 - * @param macID macID of the client 61 + * @param macAddress mac address to have a given ip assignment
64 - * @param ipAddress IP Address requested for the client 62 + * @param ipRequest ip address and dhcp options
65 - * @param rangeNotEnforced true if rangeNotEnforced was set and the mapping will be eternal
66 - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses if rangeNotEnforced was set
67 * @return true if the mapping was successfully added, false otherwise 63 * @return true if the mapping was successfully added, false otherwise
68 */ 64 */
69 - boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress, boolean rangeNotEnforced, 65 + boolean setStaticMapping(MacAddress macAddress, IpAssignment ipRequest);
70 - List<Ip4Address> addressList);
71 66
72 /** 67 /**
73 * Removes a static IP mapping with the DHCP Server. 68 * Removes a static IP mapping with the DHCP Server.
......
...@@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address; ...@@ -19,7 +19,6 @@ import org.onlab.packet.Ip4Address;
19 import org.onlab.packet.MacAddress; 19 import org.onlab.packet.MacAddress;
20 import org.onosproject.net.HostId; 20 import org.onosproject.net.HostId;
21 21
22 -import java.util.List;
23 import java.util.Map; 22 import java.util.Map;
24 23
25 24
...@@ -41,7 +40,7 @@ public interface DhcpStore { ...@@ -41,7 +40,7 @@ public interface DhcpStore {
41 * 40 *
42 * @param hostId Host ID of the client requesting an IP 41 * @param hostId Host ID of the client requesting an IP
43 * @param requestedIP requested IP address 42 * @param requestedIP requested IP address
44 - * @return IP address assigned to the Mac ID 43 + * @return IP address assigned to the Mac address; null if no available IP
45 */ 44 */
46 Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP); 45 Ip4Address suggestIP(HostId hostId, Ip4Address requestedIP);
47 46
...@@ -50,14 +49,10 @@ public interface DhcpStore { ...@@ -50,14 +49,10 @@ public interface DhcpStore {
50 * Assigns the requested IP to the Mac ID, in response to a DHCP REQUEST message. 49 * Assigns the requested IP to the Mac ID, in response to a DHCP REQUEST message.
51 * 50 *
52 * @param hostId Host Id of the client requesting an IP 51 * @param hostId Host Id of the client requesting an IP
53 - * @param ipAddr IP Address being requested 52 + * @param ipAssignment ip assignment
54 - * @param leaseTime Lease time offered by the server for this mapping
55 - * @param rangeNotEnforced true if rangeNotEnforced was set
56 - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses if rangeNotEnforced was set
57 * @return returns true if the assignment was successful, false otherwise 53 * @return returns true if the assignment was successful, false otherwise
58 */ 54 */
59 - boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced, 55 + boolean assignIP(HostId hostId, IpAssignment ipAssignment);
60 - List<Ip4Address> addressList);
61 56
62 57
63 /** 58 /**
...@@ -92,21 +87,19 @@ public interface DhcpStore { ...@@ -92,21 +87,19 @@ public interface DhcpStore {
92 /** 87 /**
93 * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time. 88 * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time.
94 * 89 *
95 - * @param macID macID of the client 90 + * @param macAddress mac address of the client
96 - * @param ipAddr IP Address requested for the client 91 + * @param ipAssignment ip address and dhcp options requested for the client
97 - * @param rangeNotEnforced true if rangeNotEnforced was set
98 - * @param addressList subnetMask, DHCP/Router/DNS IP Addresses rangeNotEnforced was set
99 * @return true if the mapping was successfully registered, false otherwise 92 * @return true if the mapping was successfully registered, false otherwise
100 */ 93 */
101 - boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean rangeNotEnforced, List<Ip4Address> addressList); 94 + boolean assignStaticIP(MacAddress macAddress, IpAssignment ipAssignment);
102 95
103 /** 96 /**
104 * Removes a static IP mapping associated with the given MAC ID from the DHCP Server. 97 * Removes a static IP mapping associated with the given MAC ID from the DHCP Server.
105 * 98 *
106 - * @param macID macID of the client 99 + * @param macAddress mac address of the client
107 * @return true if the mapping was successfully registered, false otherwise 100 * @return true if the mapping was successfully registered, false otherwise
108 */ 101 */
109 - boolean removeStaticIP(MacAddress macID); 102 + boolean removeStaticIP(MacAddress macAddress);
110 103
111 /** 104 /**
112 * Returns the list of all the available IPs with the server. 105 * Returns the list of all the available IPs with the server.
......
...@@ -27,22 +27,15 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -27,22 +27,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
27 */ 27 */
28 public final class IpAssignment { 28 public final class IpAssignment {
29 29
30 + // TODO make some dhcp options optional
30 private final Ip4Address ipAddress; 31 private final Ip4Address ipAddress;
31 -
32 private final Date timestamp; 32 private final Date timestamp;
33 -
34 private final long leasePeriod; 33 private final long leasePeriod;
35 -
36 private final Ip4Address subnetMask; 34 private final Ip4Address subnetMask;
37 - 35 + private final Ip4Address broadcast;
38 private final Ip4Address dhcpServer; 36 private final Ip4Address dhcpServer;
39 -
40 private final Ip4Address routerAddress; 37 private final Ip4Address routerAddress;
41 -
42 private final Ip4Address domainServer; 38 private final Ip4Address domainServer;
43 -
44 - private final boolean rangeNotEnforced;
45 -
46 private final AssignmentStatus assignmentStatus; 39 private final AssignmentStatus assignmentStatus;
47 40
48 public enum AssignmentStatus { 41 public enum AssignmentStatus {
...@@ -52,8 +45,10 @@ public final class IpAssignment { ...@@ -52,8 +45,10 @@ public final class IpAssignment {
52 Option_Requested, 45 Option_Requested,
53 46
54 /** 47 /**
55 - * IP Assignment has been requested by a OpenStack. 48 + * Static IP Assignment with unregistered IP range.
49 + * This assignment can only be added or removed by set or remove static mapping.
56 */ 50 */
51 + // TODO allow multiple IP ranges and remove this option
57 Option_RangeNotEnforced, 52 Option_RangeNotEnforced,
58 /** 53 /**
59 * IP has been assigned to a host. 54 * IP has been assigned to a host.
...@@ -70,30 +65,34 @@ public final class IpAssignment { ...@@ -70,30 +65,34 @@ public final class IpAssignment {
70 * Constructor for IPAssignment, where the ipAddress, the lease period, the timestamp 65 * Constructor for IPAssignment, where the ipAddress, the lease period, the timestamp
71 * and assignment status is supplied. 66 * and assignment status is supplied.
72 * 67 *
73 - * @param ipAddress 68 + * @param ipAddress ip address to assign
74 - * @param leasePeriod 69 + * @param leasePeriod lease period
75 - * @param timestamp 70 + * @param timestamp time stamp of the assignment
76 - * @param assignmentStatus 71 + * @param assignmentStatus statue of the assignment
77 - * @param subnetMask 72 + * @param subnetMask subnet mask of assigned ip range
78 - * @param dhcpServer 73 + * @param broadcast broadcast address
79 - * @param routerAddress 74 + * @param dhcpServer dhcp server address
80 - * @param domainServer 75 + * @param routerAddress router address
81 - * @param rangeNotEnforced 76 + * @param domainServer domain server address
82 */ 77 */
83 private IpAssignment(Ip4Address ipAddress, 78 private IpAssignment(Ip4Address ipAddress,
84 long leasePeriod, 79 long leasePeriod,
85 Date timestamp, 80 Date timestamp,
86 - AssignmentStatus assignmentStatus, Ip4Address subnetMask, Ip4Address dhcpServer, 81 + AssignmentStatus assignmentStatus,
87 - Ip4Address routerAddress, Ip4Address domainServer, boolean rangeNotEnforced) { 82 + Ip4Address subnetMask,
83 + Ip4Address broadcast,
84 + Ip4Address dhcpServer,
85 + Ip4Address routerAddress,
86 + Ip4Address domainServer) {
88 this.ipAddress = ipAddress; 87 this.ipAddress = ipAddress;
89 this.leasePeriod = leasePeriod; 88 this.leasePeriod = leasePeriod;
90 this.timestamp = timestamp; 89 this.timestamp = timestamp;
91 this.assignmentStatus = assignmentStatus; 90 this.assignmentStatus = assignmentStatus;
92 this.subnetMask = subnetMask; 91 this.subnetMask = subnetMask;
92 + this.broadcast = broadcast;
93 this.dhcpServer = dhcpServer; 93 this.dhcpServer = dhcpServer;
94 this.routerAddress = routerAddress; 94 this.routerAddress = routerAddress;
95 this.domainServer = domainServer; 95 this.domainServer = domainServer;
96 - this.rangeNotEnforced = rangeNotEnforced;
97 } 96 }
98 97
99 /** 98 /**
...@@ -141,26 +140,51 @@ public final class IpAssignment { ...@@ -141,26 +140,51 @@ public final class IpAssignment {
141 return (int) this.leasePeriod * 1000; 140 return (int) this.leasePeriod * 1000;
142 } 141 }
143 142
143 + /**
144 + * Returns subnet mask of the IP assignment.
145 + *
146 + * @return subnet mask
147 + */
144 public Ip4Address subnetMask() { 148 public Ip4Address subnetMask() {
145 return subnetMask; 149 return subnetMask;
146 } 150 }
147 151
152 + /**
153 + * Returns broadcast address of the IP assignment.
154 + *
155 + * @return broadcast address
156 + */
157 + public Ip4Address broadcast() {
158 + return broadcast;
159 + }
160 +
161 + /**
162 + * Returns dhcp server of the IP assignment.
163 + *
164 + * @return dhcp server ip address
165 + */
148 public Ip4Address dhcpServer() { 166 public Ip4Address dhcpServer() {
149 return dhcpServer; 167 return dhcpServer;
150 } 168 }
151 169
170 + /**
171 + * Returns router address of the IP assignment.
172 + *
173 + * @return router ip address
174 + */
152 public Ip4Address routerAddress() { 175 public Ip4Address routerAddress() {
153 return routerAddress; 176 return routerAddress;
154 } 177 }
155 178
179 + /**
180 + * Returns domain server address.
181 + *
182 + * @return domain server ip address
183 + */
156 public Ip4Address domainServer() { 184 public Ip4Address domainServer() {
157 return domainServer; 185 return domainServer;
158 } 186 }
159 187
160 - public boolean rangeNotEnforced() {
161 - return rangeNotEnforced;
162 - }
163 -
164 @Override 188 @Override
165 public String toString() { 189 public String toString() {
166 return MoreObjects.toStringHelper(getClass()) 190 return MoreObjects.toStringHelper(getClass())
...@@ -169,10 +193,10 @@ public final class IpAssignment { ...@@ -169,10 +193,10 @@ public final class IpAssignment {
169 .add("lease", leasePeriod) 193 .add("lease", leasePeriod)
170 .add("assignmentStatus", assignmentStatus) 194 .add("assignmentStatus", assignmentStatus)
171 .add("subnetMask", subnetMask) 195 .add("subnetMask", subnetMask)
196 + .add("broadcast", broadcast)
172 .add("dhcpServer", dhcpServer) 197 .add("dhcpServer", dhcpServer)
173 .add("routerAddress", routerAddress) 198 .add("routerAddress", routerAddress)
174 .add("domainServer", domainServer) 199 .add("domainServer", domainServer)
175 - .add("rangeNotEnforced", rangeNotEnforced)
176 .toString(); 200 .toString();
177 } 201 }
178 202
...@@ -201,25 +225,16 @@ public final class IpAssignment { ...@@ -201,25 +225,16 @@ public final class IpAssignment {
201 public static final class Builder { 225 public static final class Builder {
202 226
203 private Ip4Address ipAddress; 227 private Ip4Address ipAddress;
204 -
205 private Date timeStamp; 228 private Date timeStamp;
206 -
207 private long leasePeriod; 229 private long leasePeriod;
208 -
209 private AssignmentStatus assignmentStatus; 230 private AssignmentStatus assignmentStatus;
210 -
211 private Ip4Address subnetMask; 231 private Ip4Address subnetMask;
212 - 232 + private Ip4Address broadcast;
213 private Ip4Address dhcpServer; 233 private Ip4Address dhcpServer;
214 -
215 - private Ip4Address domainServer;
216 -
217 private Ip4Address routerAddress; 234 private Ip4Address routerAddress;
218 - 235 + private Ip4Address domainServer;
219 - private boolean rangeNotEnforced = false;
220 236
221 private Builder() { 237 private Builder() {
222 -
223 } 238 }
224 239
225 private Builder(IpAssignment ipAssignment) { 240 private Builder(IpAssignment ipAssignment) {
...@@ -227,12 +242,24 @@ public final class IpAssignment { ...@@ -227,12 +242,24 @@ public final class IpAssignment {
227 timeStamp = ipAssignment.timestamp(); 242 timeStamp = ipAssignment.timestamp();
228 leasePeriod = ipAssignment.leasePeriod(); 243 leasePeriod = ipAssignment.leasePeriod();
229 assignmentStatus = ipAssignment.assignmentStatus(); 244 assignmentStatus = ipAssignment.assignmentStatus();
245 + subnetMask = ipAssignment.subnetMask();
246 + broadcast = ipAssignment.broadcast();
247 + dhcpServer = ipAssignment.dhcpServer();
248 + routerAddress = ipAssignment.routerAddress();
249 + domainServer = ipAssignment.domainServer();
230 } 250 }
231 251
232 public IpAssignment build() { 252 public IpAssignment build() {
233 validateInputs(); 253 validateInputs();
234 - return new IpAssignment(ipAddress, leasePeriod, timeStamp, assignmentStatus, subnetMask, 254 + return new IpAssignment(ipAddress,
235 - dhcpServer, routerAddress, domainServer, rangeNotEnforced); 255 + leasePeriod,
256 + timeStamp,
257 + assignmentStatus,
258 + subnetMask,
259 + broadcast,
260 + dhcpServer,
261 + routerAddress,
262 + domainServer);
236 } 263 }
237 264
238 public Builder ipAddress(Ip4Address addr) { 265 public Builder ipAddress(Ip4Address addr) {
...@@ -260,6 +287,11 @@ public final class IpAssignment { ...@@ -260,6 +287,11 @@ public final class IpAssignment {
260 return this; 287 return this;
261 } 288 }
262 289
290 + public Builder broadcast(Ip4Address broadcast) {
291 + this.broadcast = broadcast;
292 + return this;
293 + }
294 +
263 public Builder dhcpServer(Ip4Address dhcpServer) { 295 public Builder dhcpServer(Ip4Address dhcpServer) {
264 this.dhcpServer = dhcpServer; 296 this.dhcpServer = dhcpServer;
265 return this; 297 return this;
...@@ -275,25 +307,12 @@ public final class IpAssignment { ...@@ -275,25 +307,12 @@ public final class IpAssignment {
275 return this; 307 return this;
276 } 308 }
277 309
278 - public Builder rangeNotEnforced(boolean rangeNotEnforced) {
279 - this.rangeNotEnforced = rangeNotEnforced;
280 - return this;
281 - }
282 -
283 -
284 private void validateInputs() { 310 private void validateInputs() {
285 checkNotNull(ipAddress, "IP Address must be specified"); 311 checkNotNull(ipAddress, "IP Address must be specified");
286 checkNotNull(assignmentStatus, "Assignment Status must be specified"); 312 checkNotNull(assignmentStatus, "Assignment Status must be specified");
287 checkNotNull(leasePeriod, "Lease Period must be specified"); 313 checkNotNull(leasePeriod, "Lease Period must be specified");
288 checkNotNull(timeStamp, "Timestamp must be specified"); 314 checkNotNull(timeStamp, "Timestamp must be specified");
289 315
290 - if (rangeNotEnforced) {
291 - checkNotNull(subnetMask, "subnetMask must be specified in case of rangeNotEnforced");
292 - checkNotNull(dhcpServer, "dhcpServer must be specified in case of rangeNotEnforced");
293 - checkNotNull(domainServer, "domainServer must be specified in case of rangeNotEnforced");
294 - checkNotNull(routerAddress, "routerAddress must be specified in case of rangeNotEnforced");
295 - }
296 -
297 switch (assignmentStatus) { 316 switch (assignmentStatus) {
298 case Option_Requested: 317 case Option_Requested:
299 case Option_RangeNotEnforced: 318 case Option_RangeNotEnforced:
......
...@@ -15,13 +15,17 @@ ...@@ -15,13 +15,17 @@
15 */ 15 */
16 package org.onosproject.dhcp.cli; 16 package org.onosproject.dhcp.cli;
17 17
18 -import com.google.common.collect.Lists;
19 import org.apache.karaf.shell.commands.Argument; 18 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command; 19 import org.apache.karaf.shell.commands.Command;
21 import org.onlab.packet.Ip4Address; 20 import org.onlab.packet.Ip4Address;
22 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
23 import org.onosproject.cli.AbstractShellCommand; 22 import org.onosproject.cli.AbstractShellCommand;
24 import org.onosproject.dhcp.DhcpService; 23 import org.onosproject.dhcp.DhcpService;
24 +import org.onosproject.dhcp.IpAssignment;
25 +
26 +import java.util.Date;
27 +
28 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested;
25 29
26 /** 30 /**
27 * Registers a static MAC Address to IP Mapping with the DHCP Server. 31 * Registers a static MAC Address to IP Mapping with the DHCP Server.
...@@ -49,7 +53,15 @@ public class DhcpSetStaticMapping extends AbstractShellCommand { ...@@ -49,7 +53,15 @@ public class DhcpSetStaticMapping extends AbstractShellCommand {
49 try { 53 try {
50 MacAddress macID = MacAddress.valueOf(macAddr); 54 MacAddress macID = MacAddress.valueOf(macAddr);
51 Ip4Address ipAddress = Ip4Address.valueOf(ipAddr); 55 Ip4Address ipAddress = Ip4Address.valueOf(ipAddr);
52 - if (dhcpService.setStaticMapping(macID, ipAddress, false, Lists.newArrayList())) { 56 +
57 + IpAssignment ipAssignment = IpAssignment.builder()
58 + .ipAddress(ipAddress)
59 + .leasePeriod(dhcpService.getLeaseTime())
60 + .timestamp(new Date())
61 + .assignmentStatus(Option_Requested)
62 + .build();
63 +
64 + if (dhcpService.setStaticMapping(macID, ipAssignment)) {
53 print(DHCP_SUCCESS); 65 print(DHCP_SUCCESS);
54 } else { 66 } else {
55 print(DHCP_FAILURE); 67 print(DHCP_FAILURE);
......
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
15 */ 15 */
16 package org.onosproject.dhcp.impl; 16 package org.onosproject.dhcp.impl;
17 17
18 +import com.google.common.base.Strings;
18 import com.google.common.collect.ImmutableSet; 19 import com.google.common.collect.ImmutableSet;
19 -import com.google.common.collect.Lists;
20 import org.apache.felix.scr.annotations.Activate; 20 import org.apache.felix.scr.annotations.Activate;
21 import org.apache.felix.scr.annotations.Component; 21 import org.apache.felix.scr.annotations.Component;
22 import org.apache.felix.scr.annotations.Deactivate; 22 import org.apache.felix.scr.annotations.Deactivate;
23 +import org.apache.felix.scr.annotations.Modified;
24 +import org.apache.felix.scr.annotations.Property;
23 import org.apache.felix.scr.annotations.Reference; 25 import org.apache.felix.scr.annotations.Reference;
24 import org.apache.felix.scr.annotations.ReferenceCardinality; 26 import org.apache.felix.scr.annotations.ReferenceCardinality;
25 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
...@@ -38,6 +40,8 @@ import org.onlab.packet.TpPort; ...@@ -38,6 +40,8 @@ import org.onlab.packet.TpPort;
38 import org.onlab.packet.UDP; 40 import org.onlab.packet.UDP;
39 import org.onlab.packet.VlanId; 41 import org.onlab.packet.VlanId;
40 import org.onlab.util.Timer; 42 import org.onlab.util.Timer;
43 +import org.onlab.util.Tools;
44 +import org.onosproject.cfg.ComponentConfigService;
41 import org.onosproject.core.ApplicationId; 45 import org.onosproject.core.ApplicationId;
42 import org.onosproject.core.CoreService; 46 import org.onosproject.core.CoreService;
43 import org.onosproject.dhcp.DhcpService; 47 import org.onosproject.dhcp.DhcpService;
...@@ -66,19 +70,31 @@ import org.onosproject.net.packet.PacketProcessor; ...@@ -66,19 +70,31 @@ import org.onosproject.net.packet.PacketProcessor;
66 import org.onosproject.net.packet.PacketService; 70 import org.onosproject.net.packet.PacketService;
67 import org.onosproject.net.provider.AbstractProvider; 71 import org.onosproject.net.provider.AbstractProvider;
68 import org.onosproject.net.provider.ProviderId; 72 import org.onosproject.net.provider.ProviderId;
73 +import org.osgi.service.component.ComponentContext;
69 import org.slf4j.Logger; 74 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory; 75 import org.slf4j.LoggerFactory;
71 76
72 import java.nio.ByteBuffer; 77 import java.nio.ByteBuffer;
73 import java.util.ArrayList; 78 import java.util.ArrayList;
74 import java.util.Date; 79 import java.util.Date;
80 +import java.util.Dictionary;
75 import java.util.HashSet; 81 import java.util.HashSet;
76 import java.util.List; 82 import java.util.List;
77 import java.util.Map; 83 import java.util.Map;
78 import java.util.Objects; 84 import java.util.Objects;
85 +import java.util.Optional;
79 import java.util.Set; 86 import java.util.Set;
80 import java.util.concurrent.TimeUnit; 87 import java.util.concurrent.TimeUnit;
88 +
89 +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_DHCPServerIp;
90 +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_MessageType;
91 +import static org.onlab.packet.DHCP.DHCPOptionCode.OptionCode_RequestedIP;
92 +import static org.onlab.packet.DHCPPacketType.DHCPACK;
93 +import static org.onlab.packet.DHCPPacketType.DHCPNAK;
94 +import static org.onlab.packet.DHCPPacketType.DHCPOFFER;
81 import static org.onlab.packet.MacAddress.valueOf; 95 import static org.onlab.packet.MacAddress.valueOf;
96 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
97 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested;
82 import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; 98 import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
83 99
84 /** 100 /**
...@@ -89,6 +105,9 @@ import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FAC ...@@ -89,6 +105,9 @@ import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FAC
89 public class DhcpManager implements DhcpService { 105 public class DhcpManager implements DhcpService {
90 106
91 private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcp", true); 107 private static final ProviderId PID = new ProviderId("of", "org.onosproject.dhcp", true);
108 + private static final String ALLOW_HOST_DISCOVERY = "allowHostDiscovery";
109 + private static final boolean DEFAULT_ALLOW_HOST_DISCOVERY = false;
110 +
92 private final Logger log = LoggerFactory.getLogger(getClass()); 111 private final Logger log = LoggerFactory.getLogger(getClass());
93 112
94 private final InternalConfigListener cfgListener = new InternalConfigListener(); 113 private final InternalConfigListener cfgListener = new InternalConfigListener();
...@@ -120,44 +139,36 @@ public class DhcpManager implements DhcpService { ...@@ -120,44 +139,36 @@ public class DhcpManager implements DhcpService {
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 139 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected HostProviderRegistry hostProviderRegistry; 140 protected HostProviderRegistry hostProviderRegistry;
122 141
123 - protected HostProviderService hostProviderService; 142 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
143 + protected ComponentConfigService componentConfigService;
124 144
125 - private final HostProvider hostProvider = new InternalHostProvider(); 145 + @Property(name = ALLOW_HOST_DISCOVERY, boolValue = DEFAULT_ALLOW_HOST_DISCOVERY,
146 + label = "Allow host discovery from DHCP request")
147 + private boolean allowHostDiscovery = DEFAULT_ALLOW_HOST_DISCOVERY;
126 148
149 + protected HostProviderService hostProviderService;
150 + private final HostProvider hostProvider = new InternalHostProvider();
127 private ApplicationId appId; 151 private ApplicationId appId;
128 152
129 // Hardcoded values are default values. 153 // Hardcoded values are default values.
130 -
131 - private static Ip4Address myIP = Ip4Address.valueOf("10.0.0.2");
132 -
133 - private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f");
134 -
135 /** 154 /**
136 * leaseTime - 10 mins or 600s. 155 * leaseTime - 10 mins or 600s.
137 * renewalTime - 5 mins or 300s. 156 * renewalTime - 5 mins or 300s.
138 * rebindingTime - 6 mins or 360s. 157 * rebindingTime - 6 mins or 360s.
139 */ 158 */
140 -
141 private static int leaseTime = 600; 159 private static int leaseTime = 600;
142 -
143 private static int renewalTime = 300; 160 private static int renewalTime = 300;
144 -
145 private static int rebindingTime = 360; 161 private static int rebindingTime = 360;
146 -
147 private static byte packetTTL = (byte) 127; 162 private static byte packetTTL = (byte) 127;
148 -
149 private static Ip4Address subnetMask = Ip4Address.valueOf("255.0.0.0"); 163 private static Ip4Address subnetMask = Ip4Address.valueOf("255.0.0.0");
150 -
151 private static Ip4Address broadcastAddress = Ip4Address.valueOf("10.255.255.255"); 164 private static Ip4Address broadcastAddress = Ip4Address.valueOf("10.255.255.255");
152 -
153 private static Ip4Address routerAddress = Ip4Address.valueOf("10.0.0.2"); 165 private static Ip4Address routerAddress = Ip4Address.valueOf("10.0.0.2");
154 -
155 private static Ip4Address domainServer = Ip4Address.valueOf("10.0.0.2"); 166 private static Ip4Address domainServer = Ip4Address.valueOf("10.0.0.2");
156 - 167 + private static Ip4Address myIP = Ip4Address.valueOf("10.0.0.2");
168 + private static MacAddress myMAC = valueOf("4f:4f:4f:4f:4f:4f");
157 private static final Ip4Address IP_BROADCAST = Ip4Address.valueOf("255.255.255.255"); 169 private static final Ip4Address IP_BROADCAST = Ip4Address.valueOf("255.255.255.255");
158 170
159 protected Timeout timeout; 171 protected Timeout timeout;
160 -
161 protected static int timerDelay = 2; 172 protected static int timerDelay = 2;
162 173
163 @Activate 174 @Activate
...@@ -165,6 +176,7 @@ public class DhcpManager implements DhcpService { ...@@ -165,6 +176,7 @@ public class DhcpManager implements DhcpService {
165 // start the dhcp server 176 // start the dhcp server
166 appId = coreService.registerApplication("org.onosproject.dhcp"); 177 appId = coreService.registerApplication("org.onosproject.dhcp");
167 178
179 + componentConfigService.registerProperties(getClass());
168 cfgService.addListener(cfgListener); 180 cfgService.addListener(cfgListener);
169 factories.forEach(cfgService::registerConfigFactory); 181 factories.forEach(cfgService::registerConfigFactory);
170 cfgListener.reconfigureNetwork(cfgService.getConfig(appId, DhcpConfig.class)); 182 cfgListener.reconfigureNetwork(cfgService.getConfig(appId, DhcpConfig.class));
...@@ -187,6 +199,19 @@ public class DhcpManager implements DhcpService { ...@@ -187,6 +199,19 @@ public class DhcpManager implements DhcpService {
187 log.info("Stopped"); 199 log.info("Stopped");
188 } 200 }
189 201
202 + @Modified
203 + protected void modified(ComponentContext context) {
204 + Dictionary<?, ?> properties = context.getProperties();
205 +
206 + String updatedConfig = Tools.get(properties, ALLOW_HOST_DISCOVERY);
207 + if (!Strings.isNullOrEmpty(updatedConfig)) {
208 + allowHostDiscovery = Boolean.valueOf(updatedConfig);
209 + log.info("Host discovery is set to {}", updatedConfig);
210 + }
211 +
212 + log.info("Modified");
213 + }
214 +
190 /** 215 /**
191 * Request packet in via PacketService. 216 * Request packet in via PacketService.
192 */ 217 */
...@@ -241,12 +266,10 @@ public class DhcpManager implements DhcpService { ...@@ -241,12 +266,10 @@ public class DhcpManager implements DhcpService {
241 } 266 }
242 267
243 @Override 268 @Override
244 - public boolean setStaticMapping(MacAddress macID, Ip4Address ipAddress, boolean rangeNotEnforced, 269 + public boolean setStaticMapping(MacAddress macAddress, IpAssignment ipAssignment) {
245 - List<Ip4Address> addressList) { 270 + log.debug("setStaticMapping is called with Mac: {} IpAssignment: {}",
246 - log.debug("setStaticMapping is called with Mac: {}, Ip: {} addressList: {}", 271 + macAddress, ipAssignment);
247 - macID.toString(), ipAddress.toString(), addressList.toString()); 272 + return dhcpStore.assignStaticIP(macAddress, ipAssignment);
248 -
249 - return dhcpStore.assignStaticIP(macID, ipAddress, rangeNotEnforced, addressList);
250 } 273 }
251 274
252 @Override 275 @Override
...@@ -271,24 +294,25 @@ public class DhcpManager implements DhcpService { ...@@ -271,24 +294,25 @@ public class DhcpManager implements DhcpService {
271 */ 294 */
272 private Ethernet buildReply(Ethernet packet, Ip4Address ipOffered, byte outgoingMessageType) { 295 private Ethernet buildReply(Ethernet packet, Ip4Address ipOffered, byte outgoingMessageType) {
273 296
274 - Ip4Address subnetMaskReply; 297 + // mandatory options
275 - Ip4Address dhcpServerReply; 298 + // TODO save and get the information below to/from IP assignment
276 - Ip4Address routerAddressReply; 299 + Ip4Address dhcpServerReply = myIP;
277 - Ip4Address domainServerReply; 300 + Ip4Address subnetMaskReply = subnetMask;
278 - IpAssignment ipAssignment; 301 + Ip4Address broadcastReply = broadcastAddress;
302 +
303 + // optional options
304 + Optional<Ip4Address> routerAddressReply = Optional.of(routerAddress);
305 + Optional<Ip4Address> domainServerReply = Optional.of(domainServer);
279 306
280 - ipAssignment = dhcpStore.getIpAssignmentFromAllocationMap(HostId.hostId(packet.getSourceMAC())); 307 + IpAssignment ipAssignment = dhcpStore.getIpAssignmentFromAllocationMap(
308 + HostId.hostId(packet.getSourceMAC()));
281 309
282 - if (ipAssignment != null && ipAssignment.rangeNotEnforced()) { 310 + if (ipAssignment != null &&
311 + ipAssignment.assignmentStatus().equals(Option_RangeNotEnforced)) {
283 subnetMaskReply = ipAssignment.subnetMask(); 312 subnetMaskReply = ipAssignment.subnetMask();
284 - dhcpServerReply = ipAssignment.dhcpServer(); 313 + broadcastReply = ipAssignment.broadcast();
285 - domainServerReply = ipAssignment.domainServer(); 314 + routerAddressReply = Optional.ofNullable(ipAssignment.routerAddress());
286 - routerAddressReply = ipAssignment.routerAddress(); 315 + domainServerReply = Optional.ofNullable(ipAssignment.domainServer());
287 - } else {
288 - subnetMaskReply = subnetMask;
289 - dhcpServerReply = myIP;
290 - routerAddressReply = routerAddress;
291 - domainServerReply = domainServer;
292 } 316 }
293 317
294 // Ethernet Frame. 318 // Ethernet Frame.
...@@ -335,7 +359,7 @@ public class DhcpManager implements DhcpService { ...@@ -335,7 +359,7 @@ public class DhcpManager implements DhcpService {
335 List<DHCPOption> optionList = new ArrayList<>(); 359 List<DHCPOption> optionList = new ArrayList<>();
336 360
337 // DHCP Message Type. 361 // DHCP Message Type.
338 - option.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()); 362 + option.setCode(OptionCode_MessageType.getValue());
339 option.setLength((byte) 1); 363 option.setLength((byte) 1);
340 byte[] optionData = {outgoingMessageType}; 364 byte[] optionData = {outgoingMessageType};
341 option.setData(optionData); 365 option.setData(optionData);
...@@ -343,13 +367,12 @@ public class DhcpManager implements DhcpService { ...@@ -343,13 +367,12 @@ public class DhcpManager implements DhcpService {
343 367
344 // DHCP Server Identifier. 368 // DHCP Server Identifier.
345 option = new DHCPOption(); 369 option = new DHCPOption();
346 - option.setCode(DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()); 370 + option.setCode(OptionCode_DHCPServerIp.getValue());
347 option.setLength((byte) 4); 371 option.setLength((byte) 4);
348 option.setData(dhcpServerReply.toOctets()); 372 option.setData(dhcpServerReply.toOctets());
349 optionList.add(option); 373 optionList.add(option);
350 374
351 if (outgoingMessageType != DHCPPacketType.DHCPNAK.getValue()) { 375 if (outgoingMessageType != DHCPPacketType.DHCPNAK.getValue()) {
352 -
353 // IP Address Lease Time. 376 // IP Address Lease Time.
354 option = new DHCPOption(); 377 option = new DHCPOption();
355 option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue()); 378 option.setCode(DHCP.DHCPOptionCode.OptionCode_LeaseTime.getValue());
...@@ -383,23 +406,27 @@ public class DhcpManager implements DhcpService { ...@@ -383,23 +406,27 @@ public class DhcpManager implements DhcpService {
383 option = new DHCPOption(); 406 option = new DHCPOption();
384 option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue()); 407 option.setCode(DHCP.DHCPOptionCode.OptionCode_BroadcastAddress.getValue());
385 option.setLength((byte) 4); 408 option.setLength((byte) 4);
386 - option.setData(broadcastAddress.toOctets()); 409 + option.setData(broadcastReply.toOctets());
387 optionList.add(option); 410 optionList.add(option);
388 411
389 // Router Address. 412 // Router Address.
413 + if (routerAddressReply.isPresent()) {
390 option = new DHCPOption(); 414 option = new DHCPOption();
391 option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue()); 415 option.setCode(DHCP.DHCPOptionCode.OptionCode_RouterAddress.getValue());
392 option.setLength((byte) 4); 416 option.setLength((byte) 4);
393 - option.setData(routerAddressReply.toOctets()); 417 + option.setData(routerAddressReply.get().toOctets());
394 optionList.add(option); 418 optionList.add(option);
419 + }
395 420
396 // DNS Server Address. 421 // DNS Server Address.
422 + if (domainServerReply.isPresent()) {
397 option = new DHCPOption(); 423 option = new DHCPOption();
398 option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue()); 424 option.setCode(DHCP.DHCPOptionCode.OptionCode_DomainServer.getValue());
399 option.setLength((byte) 4); 425 option.setLength((byte) 4);
400 - option.setData(domainServerReply.toOctets()); 426 + option.setData(domainServerReply.get().toOctets());
401 optionList.add(option); 427 optionList.add(option);
402 } 428 }
429 + }
403 430
404 // End Option. 431 // End Option.
405 option = new DHCPOption(); 432 option = new DHCPOption();
...@@ -439,104 +466,94 @@ public class DhcpManager implements DhcpService { ...@@ -439,104 +466,94 @@ public class DhcpManager implements DhcpService {
439 * @param dhcpPayload the extracted DHCP payload 466 * @param dhcpPayload the extracted DHCP payload
440 */ 467 */
441 private void processDhcpPacket(PacketContext context, DHCP dhcpPayload) { 468 private void processDhcpPacket(PacketContext context, DHCP dhcpPayload) {
469 + if (dhcpPayload == null) {
470 + log.debug("DHCP packet without payload, do nothing");
471 + return;
472 + }
473 +
442 Ethernet packet = context.inPacket().parsed(); 474 Ethernet packet = context.inPacket().parsed();
475 + DHCPPacketType incomingPacketType = null;
443 boolean flagIfRequestedIP = false; 476 boolean flagIfRequestedIP = false;
444 boolean flagIfServerIP = false; 477 boolean flagIfServerIP = false;
445 Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0"); 478 Ip4Address requestedIP = Ip4Address.valueOf("0.0.0.0");
446 Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0"); 479 Ip4Address serverIP = Ip4Address.valueOf("0.0.0.0");
447 480
448 - if (dhcpPayload != null) {
449 -
450 - DHCPPacketType incomingPacketType = DHCPPacketType.getType(0);
451 for (DHCPOption option : dhcpPayload.getOptions()) { 481 for (DHCPOption option : dhcpPayload.getOptions()) {
452 - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_MessageType.getValue()) { 482 + if (option.getCode() == OptionCode_MessageType.getValue()) {
453 byte[] data = option.getData(); 483 byte[] data = option.getData();
454 incomingPacketType = DHCPPacketType.getType(data[0]); 484 incomingPacketType = DHCPPacketType.getType(data[0]);
455 } 485 }
456 - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_RequestedIP.getValue()) { 486 + if (option.getCode() == OptionCode_RequestedIP.getValue()) {
457 byte[] data = option.getData(); 487 byte[] data = option.getData();
458 requestedIP = Ip4Address.valueOf(data); 488 requestedIP = Ip4Address.valueOf(data);
459 flagIfRequestedIP = true; 489 flagIfRequestedIP = true;
460 } 490 }
461 - if (option.getCode() == DHCP.DHCPOptionCode.OptionCode_DHCPServerIp.getValue()) { 491 + if (option.getCode() == OptionCode_DHCPServerIp.getValue()) {
462 byte[] data = option.getData(); 492 byte[] data = option.getData();
463 serverIP = Ip4Address.valueOf(data); 493 serverIP = Ip4Address.valueOf(data);
464 flagIfServerIP = true; 494 flagIfServerIP = true;
465 } 495 }
466 } 496 }
497 +
498 + if (incomingPacketType == null) {
499 + log.debug("No incoming packet type specified, ignore it");
500 + return;
501 + }
502 +
467 DHCPPacketType outgoingPacketType; 503 DHCPPacketType outgoingPacketType;
468 MacAddress clientMac = new MacAddress(dhcpPayload.getClientHardwareAddress()); 504 MacAddress clientMac = new MacAddress(dhcpPayload.getClientHardwareAddress());
469 VlanId vlanId = VlanId.vlanId(packet.getVlanID()); 505 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
470 HostId hostId = HostId.hostId(clientMac, vlanId); 506 HostId hostId = HostId.hostId(clientMac, vlanId);
471 507
472 - if (incomingPacketType.getValue() == DHCPPacketType.DHCPDISCOVER.getValue()) { 508 + switch (incomingPacketType) {
473 - 509 + case DHCPDISCOVER:
474 - outgoingPacketType = DHCPPacketType.DHCPOFFER; 510 + log.trace("DHCP DISCOVER received from {}", hostId);
475 - Ip4Address ipOffered = null; 511 + Ip4Address ipOffered = dhcpStore.suggestIP(hostId, requestedIP);
476 - ipOffered = dhcpStore.suggestIP(hostId, requestedIP);
477 -
478 if (ipOffered != null) { 512 if (ipOffered != null) {
479 - Ethernet ethReply = buildReply(packet, ipOffered, 513 + Ethernet ethReply = buildReply(
480 - (byte) outgoingPacketType.getValue()); 514 + packet,
515 + ipOffered,
516 + (byte) DHCPOFFER.getValue());
481 sendReply(context, ethReply); 517 sendReply(context, ethReply);
482 } 518 }
483 - } else if (incomingPacketType.getValue() == DHCPPacketType.DHCPREQUEST.getValue()) { 519 + break;
520 + case DHCPREQUEST:
521 + log.trace("DHCP REQUEST received from {}", hostId);
522 + if (flagIfServerIP && !myIP.equals(serverIP)) {
523 + return;
524 + }
484 525
485 - if (flagIfServerIP && flagIfRequestedIP) { 526 + if (!flagIfRequestedIP) {
486 - // SELECTING state 527 + // this is renew or rebinding request
528 + int clientIp = dhcpPayload.getClientIPAddress();
529 + requestedIP = Ip4Address.valueOf(clientIp);
530 + }
487 531
532 + IpAssignment ipAssignment = IpAssignment.builder()
533 + .ipAddress(requestedIP)
534 + .leasePeriod(leaseTime)
535 + .timestamp(new Date())
536 + .assignmentStatus(Option_Requested).build();
488 537
489 - if (dhcpStore.getIpAssignmentFromAllocationMap(HostId.hostId(clientMac)) 538 + if (dhcpStore.assignIP(hostId, ipAssignment)) {
490 - .rangeNotEnforced()) { 539 + outgoingPacketType = DHCPACK;
491 - outgoingPacketType = DHCPPacketType.DHCPACK;
492 - Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue());
493 - sendReply(context, ethReply);
494 - } else {
495 - if (myIP.equals(serverIP)) {
496 - if (dhcpStore.assignIP(hostId, requestedIP, leaseTime, false, Lists.newArrayList())) {
497 - outgoingPacketType = DHCPPacketType.DHCPACK;
498 discoverHost(context, requestedIP); 540 discoverHost(context, requestedIP);
499 } else { 541 } else {
500 - outgoingPacketType = DHCPPacketType.DHCPNAK; 542 + outgoingPacketType = DHCPNAK;
501 - }
502 - Ethernet ethReply = buildReply(packet, requestedIP,
503 - (byte) outgoingPacketType.getValue());
504 - sendReply(context, ethReply);
505 - }
506 - }
507 - } else if (flagIfRequestedIP) {
508 - // INIT-REBOOT state
509 - if (dhcpStore.assignIP(hostId, requestedIP, leaseTime, false, Lists.newArrayList())) {
510 - outgoingPacketType = DHCPPacketType.DHCPACK;
511 - Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue());
512 - sendReply(context, ethReply);
513 - discoverHost(context, requestedIP);
514 } 543 }
515 544
516 - } else { 545 + Ethernet ethReply = buildReply(packet, requestedIP, (byte) outgoingPacketType.getValue());
517 - // RENEWING and REBINDING state
518 - int ciaadr = dhcpPayload.getClientIPAddress();
519 - if (ciaadr != 0) {
520 - Ip4Address clientIaddr = Ip4Address.valueOf(ciaadr);
521 - if (dhcpStore.assignIP(hostId, clientIaddr, leaseTime, false, Lists.newArrayList())) {
522 - outgoingPacketType = DHCPPacketType.DHCPACK;
523 - discoverHost(context, clientIaddr);
524 - } else if (packet.getEtherType() == Ethernet.TYPE_IPV4 &&
525 - ((IPv4) packet.getPayload()).getDestinationAddress() == myIP.toInt()) {
526 - outgoingPacketType = DHCPPacketType.DHCPNAK;
527 - } else {
528 - return;
529 - }
530 - Ethernet ethReply = buildReply(packet, clientIaddr, (byte) outgoingPacketType.getValue());
531 sendReply(context, ethReply); 546 sendReply(context, ethReply);
547 + break;
548 + case DHCPRELEASE:
549 + log.trace("DHCP RELEASE received from {}", hostId);
550 + Ip4Address releaseIp = dhcpStore.releaseIP(hostId);
551 + if (releaseIp != null) {
552 + hostProviderService.removeIpFromHost(hostId, releaseIp);
532 } 553 }
533 - } 554 + break;
534 - } else if (incomingPacketType.getValue() == DHCPPacketType.DHCPRELEASE.getValue()) { 555 + default:
535 - Ip4Address ip4Address = dhcpStore.releaseIP(hostId); 556 + break;
536 - if (ip4Address != null) {
537 - hostProviderService.removeIpFromHost(hostId, ip4Address);
538 - }
539 - }
540 } 557 }
541 } 558 }
542 559
...@@ -575,6 +592,11 @@ public class DhcpManager implements DhcpService { ...@@ -575,6 +592,11 @@ public class DhcpManager implements DhcpService {
575 * @param ipAssigned IP Address assigned to the host by DHCP Manager 592 * @param ipAssigned IP Address assigned to the host by DHCP Manager
576 */ 593 */
577 private void discoverHost(PacketContext context, Ip4Address ipAssigned) { 594 private void discoverHost(PacketContext context, Ip4Address ipAssigned) {
595 + if (!allowHostDiscovery) {
596 + // host discovery is not allowed, do nothing
597 + return;
598 + }
599 +
578 Ethernet packet = context.inPacket().parsed(); 600 Ethernet packet = context.inPacket().parsed();
579 MacAddress mac = packet.getSourceMAC(); 601 MacAddress mac = packet.getSourceMAC();
580 VlanId vlanId = VlanId.vlanId(packet.getVlanID()); 602 VlanId vlanId = VlanId.vlanId(packet.getVlanID());
...@@ -585,6 +607,8 @@ public class DhcpManager implements DhcpService { ...@@ -585,6 +607,8 @@ public class DhcpManager implements DhcpService {
585 607
586 HostId hostId = HostId.hostId(mac, vlanId); 608 HostId hostId = HostId.hostId(mac, vlanId);
587 DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips); 609 DefaultHostDescription desc = new DefaultHostDescription(mac, vlanId, hostLocation, ips);
610 +
611 + log.info("Discovered host {}", desc);
588 hostProviderService.hostDetected(hostId, desc, false); 612 hostProviderService.hostDetected(hostId, desc, false);
589 } 613 }
590 614
......
...@@ -39,9 +39,10 @@ import org.slf4j.LoggerFactory; ...@@ -39,9 +39,10 @@ import org.slf4j.LoggerFactory;
39 39
40 import java.util.Date; 40 import java.util.Date;
41 import java.util.Map; 41 import java.util.Map;
42 -import java.util.List;
43 import java.util.HashMap; 42 import java.util.HashMap;
44 -import java.util.Objects; 43 +
44 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Assigned;
45 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
45 46
46 /** 47 /**
47 * Manages the pool of available IP Addresses in the network and 48 * Manages the pool of available IP Addresses in the network and
...@@ -58,18 +59,13 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -58,18 +59,13 @@ public class DistributedDhcpStore implements DhcpStore {
58 protected StorageService storageService; 59 protected StorageService storageService;
59 60
60 private ConsistentMap<HostId, IpAssignment> allocationMap; 61 private ConsistentMap<HostId, IpAssignment> allocationMap;
61 -
62 private DistributedSet<Ip4Address> freeIPPool; 62 private DistributedSet<Ip4Address> freeIPPool;
63 63
64 private static Ip4Address startIPRange; 64 private static Ip4Address startIPRange;
65 -
66 private static Ip4Address endIPRange; 65 private static Ip4Address endIPRange;
67 66
68 // Hardcoded values are default values. 67 // Hardcoded values are default values.
69 -
70 private static int timeoutForPendingAssignments = 60; 68 private static int timeoutForPendingAssignments = 60;
71 - private static final int MAX_RETRIES = 3;
72 - private static final int MAX_BACKOFF = 10;
73 69
74 @Activate 70 @Activate
75 protected void activate() { 71 protected void activate() {
...@@ -109,9 +105,9 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -109,9 +105,9 @@ public class DistributedDhcpStore implements DhcpStore {
109 IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus(); 105 IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus();
110 Ip4Address ipAddr = assignmentInfo.ipAddress(); 106 Ip4Address ipAddr = assignmentInfo.ipAddress();
111 107
112 - if (assignmentInfo.rangeNotEnforced()) { 108 + if (assignmentInfo.assignmentStatus().equals(Option_RangeNotEnforced)) {
113 return assignmentInfo.ipAddress(); 109 return assignmentInfo.ipAddress();
114 - } else if (status == IpAssignment.AssignmentStatus.Option_Assigned || 110 + } else if (status == Option_Assigned ||
115 status == IpAssignment.AssignmentStatus.Option_Requested) { 111 status == IpAssignment.AssignmentStatus.Option_Requested) {
116 // Client has a currently Active Binding. 112 // Client has a currently Active Binding.
117 if (ipWithinRange(ipAddr)) { 113 if (ipWithinRange(ipAddr)) {
...@@ -166,82 +162,65 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -166,82 +162,65 @@ public class DistributedDhcpStore implements DhcpStore {
166 } 162 }
167 163
168 @Override 164 @Override
169 - public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced, 165 + public boolean assignIP(HostId hostId, IpAssignment ipAssignment) {
170 - List<Ip4Address> addressList) { 166 + log.trace("Assign IP Called HostId: {}, ipAssignment: {}",
171 - log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString()); 167 + hostId, ipAssignment);
172 168
173 - Versioned<IpAssignment> currentAssignment = allocationMap.get(hostId);
174 IpAssignment newAssignment = null; 169 IpAssignment newAssignment = null;
175 - if (currentAssignment == null) { 170 + Versioned<IpAssignment> versionedAssignment = allocationMap.get(hostId);
176 - if (rangeNotEnforced) { 171 + Ip4Address requestedIp = ipAssignment.ipAddress();
177 - newAssignment = IpAssignment.builder() 172 +
178 - .ipAddress(ipAddr) 173 + if (versionedAssignment == null) {
179 - .timestamp(new Date()) 174 + // this is new IP assignment of static mapping
180 - .leasePeriod(leaseTime) 175 + // dynamic assignment is done in suggestIP
181 - .rangeNotEnforced(true) 176 + if (ipAssignment.assignmentStatus().equals(Option_RangeNotEnforced)) {
182 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced) 177 + newAssignment = ipAssignment;
183 - .subnetMask((Ip4Address) addressList.toArray()[0]) 178 + } else if (freeIPPool.remove(requestedIp)) {
184 - .dhcpServer((Ip4Address) addressList.toArray()[1]) 179 + newAssignment = IpAssignment.builder(ipAssignment)
185 - .routerAddress((Ip4Address) addressList.toArray()[2]) 180 + .assignmentStatus(Option_Assigned)
186 - .domainServer((Ip4Address) addressList.toArray()[3])
187 - .build();
188 -
189 - } else if (freeIPPool.remove(ipAddr)) {
190 - newAssignment = IpAssignment.builder()
191 - .ipAddress(ipAddr)
192 .timestamp(new Date()) 181 .timestamp(new Date())
193 - .leasePeriod(leaseTime)
194 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
195 .build(); 182 .build();
196 } else { 183 } else {
184 + log.trace("Failed to assign IP for {}", ipAssignment);
197 return false; 185 return false;
198 } 186 }
187 + log.trace("Assigned {}", newAssignment);
199 return allocationMap.putIfAbsent(hostId, newAssignment) == null; 188 return allocationMap.putIfAbsent(hostId, newAssignment) == null;
200 // TODO: handle the case where map changed. 189 // TODO: handle the case where map changed.
201 } else { 190 } else {
202 - IpAssignment existingAssignment = currentAssignment.value(); 191 + // this is lease renew or rebinding
203 - if (Objects.equals(existingAssignment.ipAddress(), ipAddr) && 192 + // update assignment status and time stamp, and keep the others
204 - (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) { 193 + IpAssignment existingAssignment = versionedAssignment.value();
194 + if (!existingAssignment.ipAddress().equals(requestedIp)) {
195 + // return false if existing assignment is not for the
196 + // requested host
197 + log.trace("Failed to assign IP for {}", ipAssignment);
198 + return false;
199 + }
200 +
205 switch (existingAssignment.assignmentStatus()) { 201 switch (existingAssignment.assignmentStatus()) {
206 case Option_RangeNotEnforced: 202 case Option_RangeNotEnforced:
207 - newAssignment = IpAssignment.builder() 203 + newAssignment = IpAssignment.builder(existingAssignment)
208 - .ipAddress(ipAddr)
209 .timestamp(new Date()) 204 .timestamp(new Date())
210 - .leasePeriod(existingAssignment.leasePeriod())
211 - .rangeNotEnforced(true)
212 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced)
213 - .subnetMask(existingAssignment.subnetMask())
214 - .dhcpServer(existingAssignment.dhcpServer())
215 - .routerAddress(existingAssignment.routerAddress())
216 - .domainServer(existingAssignment.domainServer())
217 .build(); 205 .build();
218 break; 206 break;
207 + case Option_Expired:
208 + if (!freeIPPool.remove(requestedIp)) {
209 + // requested IP is expired for this host and reserved to the other host
210 + return false;
211 + }
219 case Option_Assigned: 212 case Option_Assigned:
220 case Option_Requested: 213 case Option_Requested:
221 - newAssignment = IpAssignment.builder() 214 + newAssignment = IpAssignment.builder(existingAssignment)
222 - .ipAddress(ipAddr)
223 - .timestamp(new Date())
224 - .leasePeriod(leaseTime)
225 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
226 - .build();
227 - break;
228 - case Option_Expired:
229 - if (freeIPPool.remove(ipAddr)) {
230 - newAssignment = IpAssignment.builder()
231 - .ipAddress(ipAddr)
232 .timestamp(new Date()) 215 .timestamp(new Date())
233 - .leasePeriod(leaseTime) 216 + .assignmentStatus(Option_Assigned)
234 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
235 .build(); 217 .build();
236 - }
237 break; 218 break;
238 default: 219 default:
239 break; 220 break;
240 } 221 }
241 - return allocationMap.replace(hostId, currentAssignment.version(), newAssignment); 222 + log.trace("Assigned {}", newAssignment);
242 - } else { 223 + return allocationMap.replace(hostId, versionedAssignment.version(), newAssignment);
243 - return false;
244 - }
245 } 224 }
246 } 225 }
247 226
...@@ -273,8 +252,8 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -273,8 +252,8 @@ public class DistributedDhcpStore implements DhcpStore {
273 IpAssignment assignment; 252 IpAssignment assignment;
274 for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { 253 for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) {
275 assignment = entry.getValue().value(); 254 assignment = entry.getValue().value();
276 - if (assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_Assigned 255 + if (assignment.assignmentStatus() == Option_Assigned
277 - || assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_RangeNotEnforced) { 256 + || assignment.assignmentStatus() == Option_RangeNotEnforced) {
278 validMapping.put(entry.getKey(), assignment); 257 validMapping.put(entry.getKey(), assignment);
279 } 258 }
280 } 259 }
...@@ -291,10 +270,9 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -291,10 +270,9 @@ public class DistributedDhcpStore implements DhcpStore {
291 } 270 }
292 271
293 @Override 272 @Override
294 - public boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean rangeNotEnforced, 273 + public boolean assignStaticIP(MacAddress macAddress, IpAssignment ipAssignment) {
295 - List<Ip4Address> addressList) { 274 + HostId host = HostId.hostId(macAddress);
296 - HostId host = HostId.hostId(macID); 275 + return assignIP(host, ipAssignment);
297 - return assignIP(host, ipAddr, -1, rangeNotEnforced, addressList);
298 } 276 }
299 277
300 @Override 278 @Override
...@@ -303,7 +281,7 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -303,7 +281,7 @@ public class DistributedDhcpStore implements DhcpStore {
303 if (allocationMap.containsKey(host)) { 281 if (allocationMap.containsKey(host)) {
304 IpAssignment assignment = allocationMap.get(host).value(); 282 IpAssignment assignment = allocationMap.get(host).value();
305 283
306 - if (assignment.rangeNotEnforced()) { 284 + if (assignment.assignmentStatus().equals(Option_RangeNotEnforced)) {
307 allocationMap.remove(host); 285 allocationMap.remove(host);
308 return true; 286 return true;
309 } 287 }
...@@ -339,11 +317,16 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -339,11 +317,16 @@ public class DistributedDhcpStore implements DhcpStore {
339 nextIP = Ip4Address.valueOf(loopCounter); 317 nextIP = Ip4Address.valueOf(loopCounter);
340 freeIPPool.add(nextIP); 318 freeIPPool.add(nextIP);
341 } 319 }
320 + log.debug("Updated free IP pool {}:{} size:{}", startIP, endIP, freeIPPool.size());
342 } 321 }
343 322
344 @Override 323 @Override
345 public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) { 324 public IpAssignment getIpAssignmentFromAllocationMap(HostId hostId) {
325 + if (allocationMap.get(hostId) != null) {
346 return allocationMap.get(hostId).value(); 326 return allocationMap.get(hostId).value();
327 + } else {
328 + return null;
329 + }
347 } 330 }
348 331
349 /** 332 /**
......
...@@ -18,7 +18,6 @@ package org.onosproject.dhcp.rest; ...@@ -18,7 +18,6 @@ package org.onosproject.dhcp.rest;
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.fasterxml.jackson.databind.node.ArrayNode; 19 import com.fasterxml.jackson.databind.node.ArrayNode;
20 import com.fasterxml.jackson.databind.node.ObjectNode; 20 import com.fasterxml.jackson.databind.node.ObjectNode;
21 -import com.google.common.collect.Lists;
22 import org.onlab.packet.Ip4Address; 21 import org.onlab.packet.Ip4Address;
23 import org.onlab.packet.MacAddress; 22 import org.onlab.packet.MacAddress;
24 import org.onosproject.dhcp.DhcpService; 23 import org.onosproject.dhcp.DhcpService;
...@@ -36,8 +35,11 @@ import javax.ws.rs.core.MediaType; ...@@ -36,8 +35,11 @@ import javax.ws.rs.core.MediaType;
36 import javax.ws.rs.core.Response; 35 import javax.ws.rs.core.Response;
37 import java.io.IOException; 36 import java.io.IOException;
38 import java.io.InputStream; 37 import java.io.InputStream;
38 +import java.util.Date;
39 import java.util.Map; 39 import java.util.Map;
40 40
41 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_Requested;
42 +
41 /** 43 /**
42 * Manage DHCP address assignments. 44 * Manage DHCP address assignments.
43 */ 45 */
...@@ -120,10 +122,15 @@ public class DhcpWebResource extends AbstractWebResource { ...@@ -120,10 +122,15 @@ public class DhcpWebResource extends AbstractWebResource {
120 JsonNode macID = jsonTree.get("mac"); 122 JsonNode macID = jsonTree.get("mac");
121 JsonNode ip = jsonTree.get("ip"); 123 JsonNode ip = jsonTree.get("ip");
122 if (macID != null && ip != null) { 124 if (macID != null && ip != null) {
125 + IpAssignment ipAssignment = IpAssignment.builder()
126 + .ipAddress(Ip4Address.valueOf(ip.asText()))
127 + .leasePeriod(service.getLeaseTime())
128 + .timestamp(new Date())
129 + .assignmentStatus(Option_Requested)
130 + .build();
123 131
124 if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()), 132 if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()),
125 - Ip4Address.valueOf(ip.asText()), 133 + ipAssignment)) {
126 - false, Lists.newArrayList())) {
127 throw new IllegalArgumentException("Static Mapping Failed. " + 134 throw new IllegalArgumentException("Static Mapping Failed. " +
128 "The IP maybe unavailable."); 135 "The IP maybe unavailable.");
129 } 136 }
......
...@@ -28,6 +28,7 @@ import org.onlab.packet.Ip4Address; ...@@ -28,6 +28,7 @@ import org.onlab.packet.Ip4Address;
28 import org.onlab.packet.IpAddress; 28 import org.onlab.packet.IpAddress;
29 import org.onlab.packet.MacAddress; 29 import org.onlab.packet.MacAddress;
30 import org.onlab.packet.UDP; 30 import org.onlab.packet.UDP;
31 +import org.onosproject.cfg.ComponentConfigAdapter;
31 import org.onosproject.core.CoreServiceAdapter; 32 import org.onosproject.core.CoreServiceAdapter;
32 import org.onosproject.dhcp.DhcpStore; 33 import org.onosproject.dhcp.DhcpStore;
33 import org.onosproject.dhcp.IpAssignment; 34 import org.onosproject.dhcp.IpAssignment;
...@@ -93,6 +94,7 @@ public class DhcpManagerTest { ...@@ -93,6 +94,7 @@ public class DhcpManagerTest {
93 hostProviderService = new TestHostProviderService(new TestHostProvider()); 94 hostProviderService = new TestHostProviderService(new TestHostProvider());
94 dhcpXManager.hostProviderService = hostProviderService; 95 dhcpXManager.hostProviderService = hostProviderService;
95 dhcpXManager.hostProviderRegistry = new TestHostRegistry(); 96 dhcpXManager.hostProviderRegistry = new TestHostRegistry();
97 + dhcpXManager.componentConfigService = new TestComponentConfig();
96 dhcpXManager.activate(); 98 dhcpXManager.activate();
97 } 99 }
98 100
...@@ -228,8 +230,7 @@ public class DhcpManagerTest { ...@@ -228,8 +230,7 @@ public class DhcpManagerTest {
228 return Ip4Address.valueOf(EXPECTED_IP); 230 return Ip4Address.valueOf(EXPECTED_IP);
229 } 231 }
230 232
231 - public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean fromOpenStack, 233 + public boolean assignIP(HostId hostId, IpAssignment ipAssignment) {
232 - List<Ip4Address> addressList) {
233 return true; 234 return true;
234 } 235 }
235 236
...@@ -256,8 +257,7 @@ public class DhcpManagerTest { ...@@ -256,8 +257,7 @@ public class DhcpManagerTest {
256 return map; 257 return map;
257 } 258 }
258 259
259 - public boolean assignStaticIP(MacAddress macID, Ip4Address ipAddr, boolean fromOpenStack, 260 + public boolean assignStaticIP(MacAddress macID, IpAssignment ipAssignment) {
260 - List<Ip4Address> addressList) {
261 return true; 261 return true;
262 } 262 }
263 263
...@@ -327,6 +327,13 @@ public class DhcpManagerTest { ...@@ -327,6 +327,13 @@ public class DhcpManagerTest {
327 } 327 }
328 328
329 /** 329 /**
330 + * Mocks the ComponentConfigRegistry.
331 + */
332 + private class TestComponentConfig extends ComponentConfigAdapter {
333 +
334 + }
335 +
336 + /**
330 * Mocks the HostProviderService. 337 * Mocks the HostProviderService.
331 */ 338 */
332 private class TestHostProviderService extends AbstractProviderService<HostProvider> 339 private class TestHostProviderService extends AbstractProviderService<HostProvider>
......
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
9 "router": "10.0.0.1", 9 "router": "10.0.0.1",
10 "domain": "10.0.0.1", 10 "domain": "10.0.0.1",
11 "ttl": "63", 11 "ttl": "63",
12 - "lease": "300", 12 + "lease": 300,
13 "renew": "150", 13 "renew": "150",
14 - "rebind": "200", 14 + "rebind": 200,
15 "delay": "3", 15 "delay": "3",
16 - "timeout": "150", 16 + "timeout": 150,
17 "startip": "10.0.0.110", 17 "startip": "10.0.0.110",
18 "endip": "10.0.0.130" 18 "endip": "10.0.0.130"
19 } 19 }
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.openstacknetworking.switching; 16 package org.onosproject.openstacknetworking.switching;
17 17
18 -import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableMap; 18 import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.Maps; 19 import com.google.common.collect.Maps;
21 import org.apache.felix.scr.annotations.Activate; 20 import org.apache.felix.scr.annotations.Activate;
...@@ -26,9 +25,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -26,9 +25,11 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
26 import org.apache.felix.scr.annotations.Service; 25 import org.apache.felix.scr.annotations.Service;
27 import org.onlab.packet.Ethernet; 26 import org.onlab.packet.Ethernet;
28 import org.onlab.packet.Ip4Address; 27 import org.onlab.packet.Ip4Address;
28 +import org.onlab.packet.IpPrefix;
29 import org.onosproject.core.ApplicationId; 29 import org.onosproject.core.ApplicationId;
30 import org.onosproject.core.CoreService; 30 import org.onosproject.core.CoreService;
31 import org.onosproject.dhcp.DhcpService; 31 import org.onosproject.dhcp.DhcpService;
32 +import org.onosproject.dhcp.IpAssignment;
32 import org.onosproject.event.AbstractEvent; 33 import org.onosproject.event.AbstractEvent;
33 import org.onosproject.net.Device; 34 import org.onosproject.net.Device;
34 import org.onosproject.net.DeviceId; 35 import org.onosproject.net.DeviceId;
...@@ -61,13 +62,18 @@ import org.onosproject.openstacknetworking.OpenstackNetworkingConfig; ...@@ -61,13 +62,18 @@ import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
61 import org.onosproject.openstacknetworking.OpenstackSwitchingService; 62 import org.onosproject.openstacknetworking.OpenstackSwitchingService;
62 import org.slf4j.Logger; 63 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory; 64 import org.slf4j.LoggerFactory;
64 -import java.util.List; 65 +
66 +import java.util.Date;
65 import java.util.Collection; 67 import java.util.Collection;
66 import java.util.Map; 68 import java.util.Map;
67 import java.util.concurrent.ExecutorService; 69 import java.util.concurrent.ExecutorService;
68 import java.util.concurrent.Executors; 70 import java.util.concurrent.Executors;
69 71
70 import static org.onlab.util.Tools.groupedThreads; 72 import static org.onlab.util.Tools.groupedThreads;
73 +import static org.onosproject.dhcp.IpAssignment.AssignmentStatus.Option_RangeNotEnforced;
74 +
75 +import static com.google.common.base.Preconditions.checkArgument;
76 +import static com.google.common.base.Preconditions.checkNotNull;
71 77
72 @Service 78 @Service
73 @Component(immediate = true) 79 @Component(immediate = true)
...@@ -117,8 +123,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -117,8 +123,9 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
117 public static final String PORTNAME = "portName"; 123 public static final String PORTNAME = "portName";
118 private static final String ROUTER_INTERFACE = "network:router_interface"; 124 private static final String ROUTER_INTERFACE = "network:router_interface";
119 public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway"; 125 public static final String DEVICE_OWNER_GATEWAY = "network:router_gateway";
120 - public static final String DNS_SERVER_IP = "8.8.8.8"; 126 + public static final Ip4Address DNS_SERVER_IP = Ip4Address.valueOf("8.8.8.8");
121 private static final String FORWARD_SLASH = "/"; 127 private static final String FORWARD_SLASH = "/";
128 + private static final int DHCP_INFINITE_LEASE = -1;
122 129
123 130
124 private ApplicationId appId; 131 private ApplicationId appId;
...@@ -372,42 +379,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService { ...@@ -372,42 +379,41 @@ public class OpenstackSwitchingManager implements OpenstackSwitchingService {
372 } 379 }
373 380
374 private void registerDhcpInfo(OpenstackPort openstackPort) { 381 private void registerDhcpInfo(OpenstackPort openstackPort) {
375 - Ip4Address ip4Address, subnetMask, gatewayIPAddress, dhcpServer, domainServer; 382 + checkNotNull(openstackPort);
376 - OpenstackSubnet openstackSubnet; 383 + checkArgument(!openstackPort.fixedIps().isEmpty());
377 384
378 - ip4Address = (Ip4Address) openstackPort.fixedIps().values().stream().findFirst().orElse(null); 385 + OpenstackSubnet openstackSubnet = openstackService.subnets().stream()
379 -
380 - openstackSubnet = openstackService.subnets().stream()
381 .filter(n -> n.networkId().equals(openstackPort.networkId())) 386 .filter(n -> n.networkId().equals(openstackPort.networkId()))
382 - .findFirst().get(); 387 + .findFirst().orElse(null);
383 - 388 + if (openstackSubnet == null) {
384 - subnetMask = Ip4Address.valueOf(buildSubnetMask(openstackSubnet.cidr())); 389 + log.warn("Failed to find subnet for {}", openstackPort);
385 - gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp()); 390 + return;
386 - dhcpServer = gatewayIPAddress;
387 - // TODO: supports multiple DNS servers
388 - if (openstackSubnet.dnsNameservers().isEmpty()) {
389 - domainServer = Ip4Address.valueOf(DNS_SERVER_IP);
390 - } else {
391 - domainServer = openstackSubnet.dnsNameservers().get(0);
392 - }
393 - List<Ip4Address> options = ImmutableList.of(subnetMask, dhcpServer, gatewayIPAddress, domainServer);
394 -
395 - dhcpService.setStaticMapping(openstackPort.macAddress(), ip4Address, true, options);
396 } 391 }
397 392
398 - private byte[] buildSubnetMask(String cidr) { 393 + Ip4Address ipAddress = openstackPort.fixedIps().values().stream().findFirst().get();
399 - int prefix; 394 + IpPrefix subnetPrefix = IpPrefix.valueOf(openstackSubnet.cidr());
400 - String[] parts = cidr.split(FORWARD_SLASH); 395 + Ip4Address broadcast = Ip4Address.makeMaskedAddress(
401 - prefix = Integer.parseInt(parts[1]); 396 + ipAddress,
402 - int mask = 0xffffffff << (32 - prefix); 397 + subnetPrefix.prefixLength());
403 - byte[] bytes = new byte[]{(byte) (mask >>> 24),
404 - (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
405 398
406 - return bytes; 399 + // TODO: supports multiple DNS servers
400 + Ip4Address domainServer = openstackSubnet.dnsNameservers().isEmpty() ?
401 + DNS_SERVER_IP : openstackSubnet.dnsNameservers().get(0);
402 +
403 + IpAssignment ipAssignment = IpAssignment.builder()
404 + .ipAddress(ipAddress)
405 + .leasePeriod(DHCP_INFINITE_LEASE)
406 + .timestamp(new Date())
407 + .subnetMask(Ip4Address.makeMaskPrefix(subnetPrefix.prefixLength()))
408 + .broadcast(broadcast)
409 + .domainServer(domainServer)
410 + .assignmentStatus(Option_RangeNotEnforced)
411 + .routerAddress(Ip4Address.valueOf(openstackSubnet.gatewayIp()))
412 + .build();
413 +
414 + dhcpService.setStaticMapping(openstackPort.macAddress(), ipAssignment);
407 } 415 }
408 416
409 -
410 -
411 private class InternalPacketProcessor implements PacketProcessor { 417 private class InternalPacketProcessor implements PacketProcessor {
412 418
413 @Override 419 @Override
......