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
Showing
1 changed file
with
81 additions
and
63 deletions
| ... | @@ -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. | 184 | + .ipAddress(ipAddr) |
| 183 | - assignmentInfo = IpAssignment.builder() | 185 | + .timestamp(new Date()) |
| 184 | - .ipAddress(ipAddr) | 186 | + .leasePeriod(leaseTime) |
| 185 | - .timestamp(new Date()) | 187 | + .rangeNotEnforced(true) |
| 186 | - .leasePeriod(leaseTime) | 188 | + .assignmentStatus(IpAssignment.AssignmentStatus.Option_RangeNotEnforced) |
| 187 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | 189 | + .subnetMask((Ip4Address) addressList.toArray()[0]) |
| 188 | - .build(); | 190 | + .dhcpServer((Ip4Address) addressList.toArray()[1]) |
| 189 | - allocationMap.put(hostId, assignmentInfo); | 191 | + .routerAddress((Ip4Address) addressList.toArray()[2]) |
| 190 | - return true; | 192 | + .domainServer((Ip4Address) addressList.toArray()[3]) |
| 191 | - } else if (status == IpAssignment.AssignmentStatus.Option_Expired) { | 193 | + .build(); |
| 192 | - // Client has an expired binding with the server. | 194 | + result.set(true); |
| 193 | - if (freeIPPool.contains(ipAddr)) { | 195 | + } else if (freeIPPool.remove(ipAddr)) { |
| 194 | - assignmentInfo = IpAssignment.builder() | 196 | + assignment = 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); | 203 | + } |
| 202 | - return true; | 204 | + } else if (Objects.equals(existingAssignment.ipAddress(), ipAddr) && |
| 205 | + (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) { | ||
| 206 | + switch (existingAssignment.assignmentStatus()) { | ||
| 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() | ||
| 224 | + .ipAddress(ipAddr) | ||
| 225 | + .timestamp(new Date()) | ||
| 226 | + .leasePeriod(leaseTime) | ||
| 227 | + .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
| 228 | + .build(); | ||
| 229 | + result.set(true); | ||
| 230 | + break; | ||
| 231 | + case Option_Expired: | ||
| 232 | + if (freeIPPool.remove(ipAddr)) { | ||
| 233 | + assignment = IpAssignment.builder() | ||
| 234 | + .ipAddress(ipAddr) | ||
| 235 | + .timestamp(new Date()) | ||
| 236 | + .leasePeriod(leaseTime) | ||
| 237 | + .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
| 238 | + .build(); | ||
| 239 | + result.set(true); | ||
| 240 | + } | ||
| 241 | + break; | ||
| 242 | + default: | ||
| 243 | + break; | ||
| 244 | + } | ||
| 203 | } | 245 | } |
| 204 | - } | 246 | + return assignment; |
| 205 | - } | 247 | + }); |
| 206 | - } | 248 | + return result; |
| 207 | - } else if (freeIPPool.contains(ipAddr)) { | 249 | + }, ConsistentMapException.class, MAX_RETRIES, MAX_BACKOFF).get(); |
| 208 | - assignmentInfo = IpAssignment.builder() | 250 | + |
| 209 | - .ipAddress(ipAddr) | 251 | + return assigned.get(); |
| 210 | - .timestamp(new Date()) | ||
| 211 | - .leasePeriod(leaseTime) | ||
| 212 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
| 213 | - .build(); | ||
| 214 | - if (freeIPPool.remove(ipAddr)) { | ||
| 215 | - allocationMap.put(hostId, assignmentInfo); | ||
| 216 | - return true; | ||
| 217 | - } | ||
| 218 | - } else if (rangeNotEnforced) { | ||
| 219 | - assignmentInfo = IpAssignment.builder() | ||
| 220 | - .ipAddress(ipAddr) | ||
| 221 | - .timestamp(new Date()) | ||
| 222 | - .leasePeriod(leaseTime) | ||
| 223 | - .rangeNotEnforced(true) | ||
| 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(); | ||
| 230 | - allocationMap.put(hostId, assignmentInfo); | ||
| 231 | - return true; | ||
| 232 | - } | ||
| 233 | - return false; | ||
| 234 | } | 252 | } |
| 235 | 253 | ||
| 236 | @Override | 254 | @Override | ... | ... |
-
Please register or login to post a comment