Hyunsun Moon
Committed by Gerrit Code Review

ONOS-3549 Fixed NPE during renew for rangeNotEnforced IP

Added renew case for IP assigned with rangeNotEnforced option.
Addresses ONOS-3549

Change-Id: I6cb43f662332f0d461889d32659f1252ea436102
...@@ -25,11 +25,13 @@ import org.apache.felix.scr.annotations.Service; ...@@ -25,11 +25,13 @@ import org.apache.felix.scr.annotations.Service;
25 import org.onlab.packet.Ip4Address; 25 import org.onlab.packet.Ip4Address;
26 import org.onlab.packet.MacAddress; 26 import org.onlab.packet.MacAddress;
27 import org.onlab.util.KryoNamespace; 27 import org.onlab.util.KryoNamespace;
28 +import org.onlab.util.Tools;
28 import org.onosproject.dhcp.DhcpStore; 29 import org.onosproject.dhcp.DhcpStore;
29 import org.onosproject.dhcp.IpAssignment; 30 import org.onosproject.dhcp.IpAssignment;
30 import org.onosproject.net.HostId; 31 import org.onosproject.net.HostId;
31 import org.onosproject.store.serializers.KryoNamespaces; 32 import org.onosproject.store.serializers.KryoNamespaces;
32 import org.onosproject.store.service.ConsistentMap; 33 import org.onosproject.store.service.ConsistentMap;
34 +import org.onosproject.store.service.ConsistentMapException;
33 import org.onosproject.store.service.DistributedSet; 35 import org.onosproject.store.service.DistributedSet;
34 import org.onosproject.store.service.Serializer; 36 import org.onosproject.store.service.Serializer;
35 import org.onosproject.store.service.StorageService; 37 import org.onosproject.store.service.StorageService;
...@@ -42,6 +44,7 @@ import java.util.Map; ...@@ -42,6 +44,7 @@ import java.util.Map;
42 import java.util.List; 44 import java.util.List;
43 import java.util.HashMap; 45 import java.util.HashMap;
44 import java.util.Objects; 46 import java.util.Objects;
47 +import java.util.concurrent.atomic.AtomicBoolean;
45 48
46 /** 49 /**
47 * Manages the pool of available IP Addresses in the network and 50 * Manages the pool of available IP Addresses in the network and
...@@ -68,6 +71,8 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -68,6 +71,8 @@ public class DistributedDhcpStore implements DhcpStore {
68 // Hardcoded values are default values. 71 // Hardcoded values are default values.
69 72
70 private static int timeoutForPendingAssignments = 60; 73 private static int timeoutForPendingAssignments = 60;
74 + private static final int MAX_RETRIES = 3;
75 + private static final int MAX_BACKOFF = 10;
71 76
72 @Activate 77 @Activate
73 protected void activate() { 78 protected void activate() {
...@@ -165,72 +170,85 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -165,72 +170,85 @@ public class DistributedDhcpStore implements DhcpStore {
165 @Override 170 @Override
166 public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced, 171 public boolean assignIP(HostId hostId, Ip4Address ipAddr, int leaseTime, boolean rangeNotEnforced,
167 List<Ip4Address> addressList) { 172 List<Ip4Address> addressList) {
168 -
169 - IpAssignment assignmentInfo;
170 -
171 log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString()); 173 log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString());
172 174
173 - if (allocationMap.containsKey(hostId)) { 175 + AtomicBoolean assigned = Tools.retryable(() -> {
174 - 176 + AtomicBoolean result = new AtomicBoolean(false);
175 - assignmentInfo = allocationMap.get(hostId).value(); 177 + allocationMap.compute(
176 - IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus(); 178 + hostId,
177 - 179 + (h, existingAssignment) -> {
178 - if (Objects.equals(assignmentInfo.ipAddress(), ipAddr) && ipWithinRange(ipAddr)) { 180 + IpAssignment assignment = existingAssignment;
179 - 181 + if (existingAssignment == null) {
180 - if (status == IpAssignment.AssignmentStatus.Option_Assigned || 182 + if (rangeNotEnforced) {
181 - status == IpAssignment.AssignmentStatus.Option_Requested) { 183 + assignment = IpAssignment.builder()
182 - // Client has a currently active binding with the server.
183 - assignmentInfo = IpAssignment.builder()
184 .ipAddress(ipAddr) 184 .ipAddress(ipAddr)
185 .timestamp(new Date()) 185 .timestamp(new Date())
186 .leasePeriod(leaseTime) 186 .leasePeriod(leaseTime)
187 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) 187 + .rangeNotEnforced(true)
188 + .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced)
189 + .subnetMask((Ip4Address) addressList.toArray()[0])
190 + .dhcpServer((Ip4Address) addressList.toArray()[1])
191 + .routerAddress((Ip4Address) addressList.toArray()[2])
192 + .domainServer((Ip4Address) addressList.toArray()[3])
188 .build(); 193 .build();
189 - allocationMap.put(hostId, assignmentInfo); 194 + result.set(true);
190 - return true; 195 + } else if (freeIPPool.remove(ipAddr)) {
191 - } else if (status == IpAssignment.AssignmentStatus.Option_Expired) { 196 + assignment = IpAssignment.builder()
192 - // Client has an expired binding with the server.
193 - if (freeIPPool.contains(ipAddr)) {
194 - assignmentInfo = IpAssignment.builder()
195 .ipAddress(ipAddr) 197 .ipAddress(ipAddr)
196 .timestamp(new Date()) 198 .timestamp(new Date())
197 .leasePeriod(leaseTime) 199 .leasePeriod(leaseTime)
198 .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) 200 .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
199 .build(); 201 .build();
200 - if (freeIPPool.remove(ipAddr)) { 202 + result.set(true);
201 - allocationMap.put(hostId, assignmentInfo);
202 - return true;
203 - }
204 } 203 }
205 - } 204 + } else if (Objects.equals(existingAssignment.ipAddress(), ipAddr) &&
206 - } 205 + (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) {
207 - } else if (freeIPPool.contains(ipAddr)) { 206 + switch (existingAssignment.assignmentStatus()) {
208 - assignmentInfo = IpAssignment.builder() 207 + case Option_RangeNotEnforced:
208 + assignment = IpAssignment.builder()
209 + .ipAddress(ipAddr)
210 + .timestamp(new Date())
211 + .leasePeriod(leaseTime)
212 + .rangeNotEnforced(true)
213 + .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced)
214 + .subnetMask(existingAssignment.subnetMask())
215 + .dhcpServer(existingAssignment.dhcpServer())
216 + .routerAddress(existingAssignment.routerAddress())
217 + .domainServer(existingAssignment.domainServer())
218 + .build();
219 + result.set(true);
220 + break;
221 + case Option_Assigned:
222 + case Option_Requested:
223 + assignment = IpAssignment.builder()
209 .ipAddress(ipAddr) 224 .ipAddress(ipAddr)
210 .timestamp(new Date()) 225 .timestamp(new Date())
211 .leasePeriod(leaseTime) 226 .leasePeriod(leaseTime)
212 .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) 227 .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
213 .build(); 228 .build();
229 + result.set(true);
230 + break;
231 + case Option_Expired:
214 if (freeIPPool.remove(ipAddr)) { 232 if (freeIPPool.remove(ipAddr)) {
215 - allocationMap.put(hostId, assignmentInfo); 233 + assignment = IpAssignment.builder()
216 - return true;
217 - }
218 - } else if (rangeNotEnforced) {
219 - assignmentInfo = IpAssignment.builder()
220 .ipAddress(ipAddr) 234 .ipAddress(ipAddr)
221 .timestamp(new Date()) 235 .timestamp(new Date())
222 .leasePeriod(leaseTime) 236 .leasePeriod(leaseTime)
223 - .rangeNotEnforced(true) 237 + .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
224 - .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced)
225 - .subnetMask((Ip4Address) addressList.toArray()[0])
226 - .dhcpServer((Ip4Address) addressList.toArray()[1])
227 - .routerAddress((Ip4Address) addressList.toArray()[2])
228 - .domainServer((Ip4Address) addressList.toArray()[3])
229 .build(); 238 .build();
230 - allocationMap.put(hostId, assignmentInfo); 239 + result.set(true);
231 - return true;
232 } 240 }
233 - return false; 241 + break;
242 + default:
243 + break;
244 + }
245 + }
246 + return assignment;
247 + });
248 + return result;
249 + }, ConsistentMapException.class, MAX_RETRIES, MAX_BACKOFF).get();
250 +
251 + return assigned.get();
234 } 252 }
235 253
236 @Override 254 @Override
......