samanwita pal

ONOS-2888 Bug fix to avaoid DHCP Server assigning two hosts the same IP

Change-Id: I75dd4bdca43b9b3a0194d9742d84e088eeddac4e
...@@ -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,9 +165,13 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -166,9 +165,13 @@ 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())) { 169 +
170 + if (Objects.equals(assignmentInfo.ipAddress(), ipAddr) && ipWithinRange(ipAddr)) {
171 171
172 + if (status == IpAssignment.AssignmentStatus.Option_Assigned ||
173 + status == IpAssignment.AssignmentStatus.Option_Requested) {
174 + // Client has a currently active binding with the server.
172 assignmentInfo = IpAssignment.builder() 175 assignmentInfo = IpAssignment.builder()
173 .ipAddress(ipAddr) 176 .ipAddress(ipAddr)
174 .timestamp(new Date()) 177 .timestamp(new Date())
...@@ -177,6 +180,21 @@ public class DistributedDhcpStore implements DhcpStore { ...@@ -177,6 +180,21 @@ public class DistributedDhcpStore implements DhcpStore {
177 .build(); 180 .build();
178 allocationMap.put(hostId, assignmentInfo); 181 allocationMap.put(hostId, assignmentInfo);
179 return true; 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))
......