ONOS-2888 Bug fix to avaoid DHCP Server assigning two hosts the same IP
Change-Id: I75dd4bdca43b9b3a0194d9742d84e088eeddac4e
diff --git a/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java b/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java
index 1637cf7..c9fade9 100644
--- a/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java
+++ b/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java
@@ -68,11 +68,18 @@
void releaseIP(HostId hostId);
/**
+ * Returns a collection of all the MacAddress to IPAddress mapping assigned to the hosts.
+ *
+ * @return the collection of the mappings
+ */
+ Map<HostId, IpAssignment> listAssignedMapping();
+
+ /**
* Returns a collection of all the MacAddress to IPAddress mapping.
*
* @return the collection of the mappings
*/
- Map<HostId, IpAssignment> listMapping();
+ Map<HostId, IpAssignment> listAllMapping();
/**
* Assigns the requested IP to the MAC ID (if available) for an indefinite period of time.
diff --git a/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java b/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
index e3a4f43..345d5ad 100644
--- a/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
+++ b/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
@@ -221,7 +221,7 @@
@Override
public Map<HostId, IpAssignment> listMapping() {
- return dhcpStore.listMapping();
+ return dhcpStore.listAssignedMapping();
}
@Override
@@ -658,7 +658,7 @@
IpAssignment ipAssignment;
Date dateNow = new Date();
- Map<HostId, IpAssignment> ipAssignmentMap = dhcpStore.listMapping();
+ Map<HostId, IpAssignment> ipAssignmentMap = dhcpStore.listAllMapping();
for (Map.Entry<HostId, IpAssignment> entry: ipAssignmentMap.entrySet()) {
ipAssignment = entry.getValue();
@@ -667,6 +667,7 @@
(ipAssignment.leasePeriod() > 0) && (timeLapsed > (ipAssignment.leasePeriodMs()))) {
dhcpStore.releaseIP(entry.getKey());
+ // TODO remove only the IP from the host entry when the API is in place.
hostProviderService.hostVanished(entry.getKey());
}
}
diff --git a/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java b/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
index 96013b6..dbdadb3 100644
--- a/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
+++ b/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
@@ -40,6 +40,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
/**
* Manages the pool of available IP Addresses in the network and
@@ -107,7 +108,7 @@
if (status == IpAssignment.AssignmentStatus.Option_Assigned ||
status == IpAssignment.AssignmentStatus.Option_Requested) {
// Client has a currently Active Binding.
- if ((ipAddr.toInt() > startIPRange.toInt()) && (ipAddr.toInt() < endIPRange.toInt())) {
+ if (ipWithinRange(ipAddr)) {
return ipAddr;
}
@@ -126,8 +127,6 @@
}
}
}
- return assignmentInfo.ipAddress();
-
} else if (requestedIP.toInt() != 0) {
// Client has requested an IP.
if (freeIPPool.contains(requestedIP)) {
@@ -166,17 +165,36 @@
IpAssignment assignmentInfo;
if (allocationMap.containsKey(hostId)) {
assignmentInfo = allocationMap.get(hostId).value();
- if ((assignmentInfo.ipAddress().toInt() == ipAddr.toInt()) &&
- (ipAddr.toInt() >= startIPRange.toInt()) && (ipAddr.toInt() <= endIPRange.toInt())) {
+ IpAssignment.AssignmentStatus status = assignmentInfo.assignmentStatus();
- assignmentInfo = IpAssignment.builder()
- .ipAddress(ipAddr)
- .timestamp(new Date())
- .leasePeriod(leaseTime)
- .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
- .build();
- allocationMap.put(hostId, assignmentInfo);
- return true;
+ if (Objects.equals(assignmentInfo.ipAddress(), ipAddr) && ipWithinRange(ipAddr)) {
+
+ if (status == IpAssignment.AssignmentStatus.Option_Assigned ||
+ status == IpAssignment.AssignmentStatus.Option_Requested) {
+ // Client has a currently active binding with the server.
+ assignmentInfo = IpAssignment.builder()
+ .ipAddress(ipAddr)
+ .timestamp(new Date())
+ .leasePeriod(leaseTime)
+ .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
+ .build();
+ allocationMap.put(hostId, assignmentInfo);
+ return true;
+ } else if (status == IpAssignment.AssignmentStatus.Option_Expired) {
+ // Client has an expired binding with the server.
+ if (freeIPPool.contains(ipAddr)) {
+ assignmentInfo = IpAssignment.builder()
+ .ipAddress(ipAddr)
+ .timestamp(new Date())
+ .leasePeriod(leaseTime)
+ .assignmentStatus(IpAssignment.AssignmentStatus.Option_Assigned)
+ .build();
+ if (freeIPPool.remove(ipAddr)) {
+ allocationMap.put(hostId, assignmentInfo);
+ return true;
+ }
+ }
+ }
}
} else if (freeIPPool.contains(ipAddr)) {
assignmentInfo = IpAssignment.builder()
@@ -201,7 +219,7 @@
.build();
Ip4Address freeIP = newAssignment.ipAddress();
allocationMap.put(hostId, newAssignment);
- if ((freeIP.toInt() > startIPRange.toInt()) && (freeIP.toInt() < endIPRange.toInt())) {
+ if (ipWithinRange(freeIP)) {
freeIPPool.add(freeIP);
}
}
@@ -213,17 +231,26 @@
}
@Override
- public Map<HostId, IpAssignment> listMapping() {
+ public Map<HostId, IpAssignment> listAssignedMapping() {
- Map<HostId, IpAssignment> allMapping = new HashMap<>();
+ Map<HostId, IpAssignment> validMapping = new HashMap<>();
+ IpAssignment assignment;
for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) {
- IpAssignment assignment = entry.getValue().value();
+ assignment = entry.getValue().value();
if (assignment.assignmentStatus() == IpAssignment.AssignmentStatus.Option_Assigned) {
- allMapping.put(entry.getKey(), assignment);
+ validMapping.put(entry.getKey(), assignment);
}
}
- return allMapping;
+ return validMapping;
+ }
+ @Override
+ public Map<HostId, IpAssignment> listAllMapping() {
+ Map<HostId, IpAssignment> validMapping = new HashMap<>();
+ for (Map.Entry<HostId, Versioned<IpAssignment>> entry: allocationMap.entrySet()) {
+ validMapping.put(entry.getKey(), entry.getValue().value());
+ }
+ return validMapping;
}
@Override
@@ -240,7 +267,7 @@
Ip4Address freeIP = assignment.ipAddress();
if (assignment.leasePeriod() < 0) {
allocationMap.remove(host);
- if ((freeIP.toInt() > startIPRange.toInt()) && (freeIP.toInt() < endIPRange.toInt())) {
+ if (ipWithinRange(freeIP)) {
freeIPPool.add(freeIP);
}
return true;
@@ -257,9 +284,10 @@
@Override
public void populateIPPoolfromRange(Ip4Address startIP, Ip4Address endIP) {
// Clear all entries from previous range.
+ allocationMap.clear();
+ freeIPPool.clear();
startIPRange = startIP;
endIPRange = endIP;
- freeIPPool.clear();
int lastIP = endIP.toInt();
Ip4Address nextIP;
@@ -282,4 +310,17 @@
}
return null;
}
+
+ /**
+ * Returns true if the given ip is within the range of available IPs.
+ *
+ * @param ip given ip address
+ * @return true if within range, false otherwise
+ */
+ private boolean ipWithinRange(Ip4Address ip) {
+ if ((ip.toInt() >= startIPRange.toInt()) && (ip.toInt() <= endIPRange.toInt())) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java b/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
index 85c9d5c..682ab91 100644
--- a/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
+++ b/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
@@ -237,7 +237,11 @@
public void releaseIP(HostId hostId) {
}
- public Map<HostId, IpAssignment> listMapping() {
+ public Map<HostId, IpAssignment> listAssignedMapping() {
+ return listAllMapping();
+ }
+
+ public Map<HostId, IpAssignment> listAllMapping() {
Map<HostId, IpAssignment> map = new HashMap<>();
IpAssignment assignment = IpAssignment.builder()
.ipAddress(Ip4Address.valueOf(EXPECTED_IP))