Committed by
Gerrit Code Review
ONOS-2888 Bug fix to avaoid DHCP Server assigning two hosts the same IP
Change-Id: I75dd4bdca43b9b3a0194d9742d84e088eeddac4e
Showing
4 changed files
with
78 additions
and
25 deletions
| ... | @@ -68,11 +68,18 @@ public interface DhcpStore { | ... | @@ -68,11 +68,18 @@ public interface DhcpStore { |
| 68 | void releaseIP(HostId hostId); | 68 | void releaseIP(HostId hostId); |
| 69 | 69 | ||
| 70 | /** | 70 | /** |
| 71 | + * Returns a collection of all the MacAddress to IPAddress mapping assigned to the hosts. | ||
| 72 | + * | ||
| 73 | + * @return the collection of the mappings | ||
| 74 | + */ | ||
| 75 | + Map<HostId, IpAssignment> listAssignedMapping(); | ||
| 76 | + | ||
| 77 | + /** | ||
| 71 | * Returns a collection of all the MacAddress to IPAddress mapping. | 78 | * Returns a collection of all the MacAddress to IPAddress mapping. |
| 72 | * | 79 | * |
| 73 | * @return the collection of the mappings | 80 | * @return the collection of the mappings |
| 74 | */ | 81 | */ |
| 75 | - Map<HostId, IpAssignment> listMapping(); | 82 | + Map<HostId, IpAssignment> listAllMapping(); |
| 76 | 83 | ||
| 77 | /** | 84 | /** |
| 78 | * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time. | 85 | * Assigns the requested IP to the MAC ID (if available) for an indefinite period of time. | ... | ... |
| ... | @@ -221,7 +221,7 @@ public class DhcpManager implements DhcpService { | ... | @@ -221,7 +221,7 @@ public class DhcpManager implements DhcpService { |
| 221 | 221 | ||
| 222 | @Override | 222 | @Override |
| 223 | public Map<HostId, IpAssignment> listMapping() { | 223 | public Map<HostId, IpAssignment> listMapping() { |
| 224 | - return dhcpStore.listMapping(); | 224 | + return dhcpStore.listAssignedMapping(); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | @Override | 227 | @Override |
| ... | @@ -658,7 +658,7 @@ public class DhcpManager implements DhcpService { | ... | @@ -658,7 +658,7 @@ public class DhcpManager implements DhcpService { |
| 658 | IpAssignment ipAssignment; | 658 | IpAssignment ipAssignment; |
| 659 | Date dateNow = new Date(); | 659 | Date dateNow = new Date(); |
| 660 | 660 | ||
| 661 | - Map<HostId, IpAssignment> ipAssignmentMap = dhcpStore.listMapping(); | 661 | + Map<HostId, IpAssignment> ipAssignmentMap = dhcpStore.listAllMapping(); |
| 662 | for (Map.Entry<HostId, IpAssignment> entry: ipAssignmentMap.entrySet()) { | 662 | for (Map.Entry<HostId, IpAssignment> entry: ipAssignmentMap.entrySet()) { |
| 663 | ipAssignment = entry.getValue(); | 663 | ipAssignment = entry.getValue(); |
| 664 | 664 | ||
| ... | @@ -667,6 +667,7 @@ public class DhcpManager implements DhcpService { | ... | @@ -667,6 +667,7 @@ public class DhcpManager implements DhcpService { |
| 667 | (ipAssignment.leasePeriod() > 0) && (timeLapsed > (ipAssignment.leasePeriodMs()))) { | 667 | (ipAssignment.leasePeriod() > 0) && (timeLapsed > (ipAssignment.leasePeriodMs()))) { |
| 668 | 668 | ||
| 669 | dhcpStore.releaseIP(entry.getKey()); | 669 | dhcpStore.releaseIP(entry.getKey()); |
| 670 | + // TODO remove only the IP from the host entry when the API is in place. | ||
| 670 | hostProviderService.hostVanished(entry.getKey()); | 671 | hostProviderService.hostVanished(entry.getKey()); |
| 671 | } | 672 | } |
| 672 | } | 673 | } | ... | ... |
| ... | @@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory; | ... | @@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory; |
| 40 | import java.util.Date; | 40 | import java.util.Date; |
| 41 | import java.util.HashMap; | 41 | import java.util.HashMap; |
| 42 | import java.util.Map; | 42 | import java.util.Map; |
| 43 | +import java.util.Objects; | ||
| 43 | 44 | ||
| 44 | /** | 45 | /** |
| 45 | * Manages the pool of available IP Addresses in the network and | 46 | * Manages the pool of available IP Addresses in the network and |
| ... | @@ -107,7 +108,7 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -107,7 +108,7 @@ public class DistributedDhcpStore implements DhcpStore { |
| 107 | if (status == IpAssignment.AssignmentStatus.Option_Assigned || | 108 | if (status == IpAssignment.AssignmentStatus.Option_Assigned || |
| 108 | status == IpAssignment.AssignmentStatus.Option_Requested) { | 109 | status == IpAssignment.AssignmentStatus.Option_Requested) { |
| 109 | // Client has a currently Active Binding. | 110 | // Client has a currently Active Binding. |
| 110 | - if ((ipAddr.toInt() > startIPRange.toInt()) && (ipAddr.toInt() < endIPRange.toInt())) { | 111 | + if (ipWithinRange(ipAddr)) { |
| 111 | return ipAddr; | 112 | return ipAddr; |
| 112 | } | 113 | } |
| 113 | 114 | ||
| ... | @@ -126,8 +127,6 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -126,8 +127,6 @@ public class DistributedDhcpStore implements DhcpStore { |
| 126 | } | 127 | } |
| 127 | } | 128 | } |
| 128 | } | 129 | } |
| 129 | - return assignmentInfo.ipAddress(); | ||
| 130 | - | ||
| 131 | } else if (requestedIP.toInt() != 0) { | 130 | } else if (requestedIP.toInt() != 0) { |
| 132 | // Client has requested an IP. | 131 | // Client has requested an IP. |
| 133 | if (freeIPPool.contains(requestedIP)) { | 132 | if (freeIPPool.contains(requestedIP)) { |
| ... | @@ -166,17 +165,36 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -166,17 +165,36 @@ public class DistributedDhcpStore implements DhcpStore { |
| 166 | IpAssignment assignmentInfo; | 165 | IpAssignment assignmentInfo; |
| 167 | if (allocationMap.containsKey(hostId)) { | 166 | if (allocationMap.containsKey(hostId)) { |
| 168 | assignmentInfo = allocationMap.get(hostId).value(); | 167 | assignmentInfo = allocationMap.get(hostId).value(); |
| 169 | - if ((assignmentInfo.ipAddress().toInt() == ipAddr.toInt()) && | 168 | + IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus(); |
| 170 | - (ipAddr.toInt() >= startIPRange.toInt()) && (ipAddr.toInt() <= endIPRange.toInt())) { | ||
| 171 | 169 | ||
| 172 | - assignmentInfo = IpAssignment.builder() | 170 | + if (Objects.equals(assignmentInfo.ipAddress(), ipAddr) && ipWithinRange(ipAddr)) { |
| 173 | - .ipAddress(ipAddr) | 171 | + |
| 174 | - .timestamp(new Date()) | 172 | + if (status == IpAssignment.AssignmentStatus.Option_Assigned || |
| 175 | - .leasePeriod(leaseTime) | 173 | + status == IpAssignment.AssignmentStatus.Option_Requested) { |
| 176 | - .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | 174 | + // Client has a currently active binding with the server. |
| 177 | - .build(); | 175 | + assignmentInfo = IpAssignment.builder() |
| 178 | - allocationMap.put(hostId, assignmentInfo); | 176 | + .ipAddress(ipAddr) |
| 179 | - return true; | 177 | + .timestamp(new Date()) |
| 178 | + .leasePeriod(leaseTime) | ||
| 179 | + .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
| 180 | + .build(); | ||
| 181 | + allocationMap.put(hostId, assignmentInfo); | ||
| 182 | + return true; | ||
| 183 | + } else if (status == IpAssignment.AssignmentStatus.Option_Expired) { | ||
| 184 | + // Client has an expired binding with the server. | ||
| 185 | + if (freeIPPool.contains(ipAddr)) { | ||
| 186 | + assignmentInfo = IpAssignment.builder() | ||
| 187 | + .ipAddress(ipAddr) | ||
| 188 | + .timestamp(new Date()) | ||
| 189 | + .leasePeriod(leaseTime) | ||
| 190 | + .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned) | ||
| 191 | + .build(); | ||
| 192 | + if (freeIPPool.remove(ipAddr)) { | ||
| 193 | + allocationMap.put(hostId, assignmentInfo); | ||
| 194 | + return true; | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | + } | ||
| 180 | } | 198 | } |
| 181 | } else if (freeIPPool.contains(ipAddr)) { | 199 | } else if (freeIPPool.contains(ipAddr)) { |
| 182 | assignmentInfo = IpAssignment.builder() | 200 | assignmentInfo = IpAssignment.builder() |
| ... | @@ -201,7 +219,7 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -201,7 +219,7 @@ public class DistributedDhcpStore implements DhcpStore { |
| 201 | .build(); | 219 | .build(); |
| 202 | Ip4Address freeIP = newAssignment.ipAddress(); | 220 | Ip4Address freeIP = newAssignment.ipAddress(); |
| 203 | allocationMap.put(hostId, newAssignment); | 221 | allocationMap.put(hostId, newAssignment); |
| 204 | - if ((freeIP.toInt() > startIPRange.toInt()) && (freeIP.toInt() < endIPRange.toInt())) { | 222 | + if (ipWithinRange(freeIP)) { |
| 205 | freeIPPool.add(freeIP); | 223 | freeIPPool.add(freeIP); |
| 206 | } | 224 | } |
| 207 | } | 225 | } |
| ... | @@ -213,17 +231,26 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -213,17 +231,26 @@ public class DistributedDhcpStore implements DhcpStore { |
| 213 | } | 231 | } |
| 214 | 232 | ||
| 215 | @Override | 233 | @Override |
| 216 | - public Map<HostId, IpAssignment> listMapping() { | 234 | + public Map<HostId, IpAssignment> listAssignedMapping() { |
| 217 | 235 | ||
| 218 | - Map<HostId, IpAssignment> allMapping = new HashMap<>(); | 236 | + Map<HostId, IpAssignment> validMapping = new HashMap<>(); |
| 237 | + IpAssignment assignment; | ||
| 219 | for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { | 238 | for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { |
| 220 | - IpAssignment assignment = entry.getValue().value(); | 239 | + assignment = entry.getValue().value(); |
| 221 | if (assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_Assigned) { | 240 | if (assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_Assigned) { |
| 222 | - allMapping.put(entry.getKey(), assignment); | 241 | + validMapping.put(entry.getKey(), assignment); |
| 223 | } | 242 | } |
| 224 | } | 243 | } |
| 225 | - return allMapping; | 244 | + return validMapping; |
| 245 | + } | ||
| 226 | 246 | ||
| 247 | + @Override | ||
| 248 | + public Map<HostId, IpAssignment> listAllMapping() { | ||
| 249 | + Map<HostId, IpAssignment> validMapping = new HashMap<>(); | ||
| 250 | + for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) { | ||
| 251 | + validMapping.put(entry.getKey(), entry.getValue().value()); | ||
| 252 | + } | ||
| 253 | + return validMapping; | ||
| 227 | } | 254 | } |
| 228 | 255 | ||
| 229 | @Override | 256 | @Override |
| ... | @@ -240,7 +267,7 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -240,7 +267,7 @@ public class DistributedDhcpStore implements DhcpStore { |
| 240 | Ip4Address freeIP = assignment.ipAddress(); | 267 | Ip4Address freeIP = assignment.ipAddress(); |
| 241 | if (assignment.leasePeriod() < 0) { | 268 | if (assignment.leasePeriod() < 0) { |
| 242 | allocationMap.remove(host); | 269 | allocationMap.remove(host); |
| 243 | - if ((freeIP.toInt() > startIPRange.toInt()) && (freeIP.toInt() < endIPRange.toInt())) { | 270 | + if (ipWithinRange(freeIP)) { |
| 244 | freeIPPool.add(freeIP); | 271 | freeIPPool.add(freeIP); |
| 245 | } | 272 | } |
| 246 | return true; | 273 | return true; |
| ... | @@ -257,9 +284,10 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -257,9 +284,10 @@ public class DistributedDhcpStore implements DhcpStore { |
| 257 | @Override | 284 | @Override |
| 258 | public void populateIPPoolfromRange(Ip4Address startIP, Ip4Address endIP) { | 285 | public void populateIPPoolfromRange(Ip4Address startIP, Ip4Address endIP) { |
| 259 | // Clear all entries from previous range. | 286 | // Clear all entries from previous range. |
| 287 | + allocationMap.clear(); | ||
| 288 | + freeIPPool.clear(); | ||
| 260 | startIPRange = startIP; | 289 | startIPRange = startIP; |
| 261 | endIPRange = endIP; | 290 | endIPRange = endIP; |
| 262 | - freeIPPool.clear(); | ||
| 263 | 291 | ||
| 264 | int lastIP = endIP.toInt(); | 292 | int lastIP = endIP.toInt(); |
| 265 | Ip4Address nextIP; | 293 | Ip4Address nextIP; |
| ... | @@ -282,4 +310,17 @@ public class DistributedDhcpStore implements DhcpStore { | ... | @@ -282,4 +310,17 @@ public class DistributedDhcpStore implements DhcpStore { |
| 282 | } | 310 | } |
| 283 | return null; | 311 | return null; |
| 284 | } | 312 | } |
| 313 | + | ||
| 314 | + /** | ||
| 315 | + * Returns true if the given ip is within the range of available IPs. | ||
| 316 | + * | ||
| 317 | + * @param ip given ip address | ||
| 318 | + * @return true if within range, false otherwise | ||
| 319 | + */ | ||
| 320 | + private boolean ipWithinRange(Ip4Address ip) { | ||
| 321 | + if ((ip.toInt() >= startIPRange.toInt()) && (ip.toInt() <= endIPRange.toInt())) { | ||
| 322 | + return true; | ||
| 323 | + } | ||
| 324 | + return false; | ||
| 325 | + } | ||
| 285 | } | 326 | } | ... | ... |
| ... | @@ -237,7 +237,11 @@ public class DhcpManagerTest { | ... | @@ -237,7 +237,11 @@ public class DhcpManagerTest { |
| 237 | public void releaseIP(HostId hostId) { | 237 | public void releaseIP(HostId hostId) { |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | - public Map<HostId, IpAssignment> listMapping() { | 240 | + public Map<HostId, IpAssignment> listAssignedMapping() { |
| 241 | + return listAllMapping(); | ||
| 242 | + } | ||
| 243 | + | ||
| 244 | + public Map<HostId, IpAssignment> listAllMapping() { | ||
| 241 | Map<HostId, IpAssignment> map = new HashMap<>(); | 245 | Map<HostId, IpAssignment> map = new HashMap<>(); |
| 242 | IpAssignment assignment = IpAssignment.builder() | 246 | IpAssignment assignment = IpAssignment.builder() |
| 243 | .ipAddress(Ip4Address.valueOf(EXPECTED_IP)) | 247 | .ipAddress(Ip4Address.valueOf(EXPECTED_IP)) | ... | ... |
-
Please register or login to post a comment