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);
......
...@@ -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
......