Committed by
Gerrit Code Review
Fixes deadlock in dhcp ip assignment logic caused by nesting calls to distributed primitives.
Change-Id: I25acd37cbf3800ad260c672c99e9f630435f0f88
Showing
1 changed file
with
20 additions
and
27 deletions
| ... | @@ -25,13 +25,11 @@ import org.apache.felix.scr.annotations.Service; | ... | @@ -25,13 +25,11 @@ 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; | ||
| 29 | import org.onosproject.dhcp.DhcpStore; | 28 | import org.onosproject.dhcp.DhcpStore; |
| 30 | import org.onosproject.dhcp.IpAssignment; | 29 | import org.onosproject.dhcp.IpAssignment; |
| 31 | import org.onosproject.net.HostId; | 30 | import org.onosproject.net.HostId; |
| 32 | import org.onosproject.store.serializers.KryoNamespaces; | 31 | import org.onosproject.store.serializers.KryoNamespaces; |
| 33 | import org.onosproject.store.service.ConsistentMap; | 32 | import org.onosproject.store.service.ConsistentMap; |
| 34 | -import org.onosproject.store.service.ConsistentMapException; | ||
| 35 | import org.onosproject.store.service.DistributedSet; | 33 | import org.onosproject.store.service.DistributedSet; |
| 36 | import org.onosproject.store.service.Serializer; | 34 | import org.onosproject.store.service.Serializer; |
| 37 | import org.onosproject.store.service.StorageService; | 35 | import org.onosproject.store.service.StorageService; |
| ... | @@ -44,7 +42,6 @@ import java.util.Map; | ... | @@ -44,7 +42,6 @@ import java.util.Map; |
| 44 | import java.util.List; | 42 | import java.util.List; |
| 45 | import java.util.HashMap; | 43 | import java.util.HashMap; |
| 46 | import java.util.Objects; | 44 | import java.util.Objects; |
| 47 | -import java.util.concurrent.atomic.AtomicBoolean; | ||
| 48 | 45 | ||
| 49 | /** | 46 | /** |
| 50 | * Manages the pool of available IP Addresses in the network and | 47 | * Manages the pool of available IP Addresses in the network and |
| ... | @@ -172,15 +169,11 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -172,15 +169,11 @@ public class DistributedDhcpStore implements DhcpStore { |
| 172 | List<Ip4Address> addressList) { | 169 | List<Ip4Address> addressList) { |
| 173 | log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString()); | 170 | log.debug("Assign IP Called w/ Ip4Address: {}, HostId: {}", ipAddr.toString(), hostId.mac().toString()); |
| 174 | 171 | ||
| 175 | - AtomicBoolean assigned = Tools.retryable(() -> { | 172 | + Versioned<IpAssignment> currentAssignment = allocationMap.get(hostId); |
| 176 | - AtomicBoolean result = new AtomicBoolean(false); | 173 | + IpAssignment newAssignment = null; |
| 177 | - allocationMap.compute( | 174 | + if (currentAssignment == null) { |
| 178 | - hostId, | ||
| 179 | - (h, existingAssignment) -> { | ||
| 180 | - IpAssignment assignment = existingAssignment; | ||
| 181 | - if (existingAssignment == null) { | ||
| 182 | if (rangeNotEnforced) { | 175 | if (rangeNotEnforced) { |
| 183 | - assignment = IpAssignment.builder() | 176 | + newAssignment = IpAssignment.builder() |
| 184 | .ipAddress(ipAddr) | 177 | .ipAddress(ipAddr) |
| 185 | .timestamp(new Date()) | 178 | .timestamp(new Date()) |
| 186 | .leasePeriod(leaseTime) | 179 | .leasePeriod(leaseTime) |
| ... | @@ -191,21 +184,26 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -191,21 +184,26 @@ public class DistributedDhcpStore implements DhcpStore { |
| 191 | .routerAddress((Ip4Address) addressList.toArray()[2]) | 184 | .routerAddress((Ip4Address) addressList.toArray()[2]) |
| 192 | .domainServer((Ip4Address) addressList.toArray()[3]) | 185 | .domainServer((Ip4Address) addressList.toArray()[3]) |
| 193 | .build(); | 186 | .build(); |
| 194 | - result.set(true); | 187 | + |
| 195 | } else if (freeIPPool.remove(ipAddr)) { | 188 | } else if (freeIPPool.remove(ipAddr)) { |
| 196 | - assignment = IpAssignment.builder() | 189 | + newAssignment = IpAssignment.builder() |
| 197 | .ipAddress(ipAddr) | 190 | .ipAddress(ipAddr) |
| 198 | .timestamp(new Date()) | 191 | .timestamp(new Date()) |
| 199 | .leasePeriod(leaseTime) | 192 | .leasePeriod(leaseTime) |
| 200 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | 193 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) |
| 201 | .build(); | 194 | .build(); |
| 202 | - result.set(true); | 195 | + } else { |
| 196 | + return false; | ||
| 203 | } | 197 | } |
| 204 | - } else if (Objects.equals(existingAssignment.ipAddress(), ipAddr) && | 198 | + return allocationMap.putIfAbsent(hostId, newAssignment) == null; |
| 199 | + // TODO: handle the case where map changed. | ||
| 200 | + } else { | ||
| 201 | + IpAssignment existingAssignment = currentAssignment.value(); | ||
| 202 | + if (Objects.equals(existingAssignment.ipAddress(), ipAddr) && | ||
| 205 | (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) { | 203 | (existingAssignment.rangeNotEnforced() || ipWithinRange(ipAddr))) { |
| 206 | switch (existingAssignment.assignmentStatus()) { | 204 | switch (existingAssignment.assignmentStatus()) { |
| 207 | case Option_RangeNotEnforced: | 205 | case Option_RangeNotEnforced: |
| 208 | - assignment = IpAssignment.builder() | 206 | + newAssignment = IpAssignment.builder() |
| 209 | .ipAddress(ipAddr) | 207 | .ipAddress(ipAddr) |
| 210 | .timestamp(new Date()) | 208 | .timestamp(new Date()) |
| 211 | .leasePeriod(existingAssignment.leasePeriod()) | 209 | .leasePeriod(existingAssignment.leasePeriod()) |
| ... | @@ -216,39 +214,34 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -216,39 +214,34 @@ public class DistributedDhcpStore implements DhcpStore { |
| 216 | .routerAddress(existingAssignment.routerAddress()) | 214 | .routerAddress(existingAssignment.routerAddress()) |
| 217 | .domainServer(existingAssignment.domainServer()) | 215 | .domainServer(existingAssignment.domainServer()) |
| 218 | .build(); | 216 | .build(); |
| 219 | - result.set(true); | ||
| 220 | break; | 217 | break; |
| 221 | case Option_Assigned: | 218 | case Option_Assigned: |
| 222 | case Option_Requested: | 219 | case Option_Requested: |
| 223 | - assignment = IpAssignment.builder() | 220 | + newAssignment = IpAssignment.builder() |
| 224 | .ipAddress(ipAddr) | 221 | .ipAddress(ipAddr) |
| 225 | .timestamp(new Date()) | 222 | .timestamp(new Date()) |
| 226 | .leasePeriod(leaseTime) | 223 | .leasePeriod(leaseTime) |
| 227 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | 224 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) |
| 228 | .build(); | 225 | .build(); |
| 229 | - result.set(true); | ||
| 230 | break; | 226 | break; |
| 231 | case Option_Expired: | 227 | case Option_Expired: |
| 232 | if (freeIPPool.remove(ipAddr)) { | 228 | if (freeIPPool.remove(ipAddr)) { |
| 233 | - assignment = IpAssignment.builder() | 229 | + newAssignment = IpAssignment.builder() |
| 234 | .ipAddress(ipAddr) | 230 | .ipAddress(ipAddr) |
| 235 | .timestamp(new Date()) | 231 | .timestamp(new Date()) |
| 236 | .leasePeriod(leaseTime) | 232 | .leasePeriod(leaseTime) |
| 237 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | 233 | .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) |
| 238 | .build(); | 234 | .build(); |
| 239 | - result.set(true); | ||
| 240 | } | 235 | } |
| 241 | break; | 236 | break; |
| 242 | default: | 237 | default: |
| 243 | break; | 238 | break; |
| 244 | } | 239 | } |
| 240 | + return allocationMap.replace(hostId, currentAssignment.version(), newAssignment); | ||
| 241 | + } else { | ||
| 242 | + return false; | ||
| 243 | + } | ||
| 245 | } | 244 | } |
| 246 | - return assignment; | ||
| 247 | - }); | ||
| 248 | - return result; | ||
| 249 | - }, ConsistentMapException.class, MAX_RETRIES, MAX_BACKOFF).get(); | ||
| 250 | - | ||
| 251 | - return assigned.get(); | ||
| 252 | } | 245 | } |
| 253 | 246 | ||
| 254 | @Override | 247 | @Override | ... | ... |
-
Please register or login to post a comment