|
@@ -80,6 +80,10 @@ class PcapAddressOperations():
|
|
|
:return: the newly created local IP addresses
|
|
|
"""
|
|
|
|
|
|
+ # add more unused local ips to the pool, if needed
|
|
|
+ if len(self.unused_local_ips) < 10:
|
|
|
+ self.expand_unused_local_ips()
|
|
|
+
|
|
|
unused_local_ips = self.unused_local_ips
|
|
|
uncertain_local_ips = self.uncertain_local_ips
|
|
|
count_certain = min(count, len(unused_local_ips))
|
|
@@ -183,21 +187,73 @@ class PcapAddressOperations():
|
|
|
elif (not str(ip) == "255.255.255.255") and (not ip.is_localhost()) and (not ip.is_multicast()) and (not ip.is_reserved()) and (not ip.is_zero_conf()):
|
|
|
external_ips.add(ip)
|
|
|
|
|
|
- min_local_ip, max_local_ip = min(local_ips), max(local_ips)
|
|
|
-
|
|
|
# save the certain unused local IPs of the network
|
|
|
- unused_local_ips = set()
|
|
|
- for i in range(min_local_ip.to_int() + 1, max_local_ip.to_int()):
|
|
|
- ip = IPAddress.from_int(i)
|
|
|
- if not ip in local_ips:
|
|
|
- unused_local_ips.add(ip)
|
|
|
+ # to do that, divide the unused local Addressspace into chunks of (chunks_size) Addresses
|
|
|
+ # initally only the first chunk will be used, but more chunks can be added to the pool of unused_local_ips if needed
|
|
|
+ self.min_local_ip, self.max_local_ip = min(local_ips), max(local_ips)
|
|
|
+ local_ip_range = (self.max_local_ip.to_int() - 1) - (self.min_local_ip.to_int() + 1) # boundaries are inclusive
|
|
|
+
|
|
|
+ # chunk size can be adjusted if needed
|
|
|
+ self.chunk_size = 200
|
|
|
+
|
|
|
+ self.current_chunk = 1
|
|
|
+ if local_ip_range < self.chunk_size:
|
|
|
+ # there are not more than chunk_size unused IP Addresses to begin with
|
|
|
+ self.chunks = 0
|
|
|
+ self.chunk_remainder = local_ip_range
|
|
|
+ else:
|
|
|
+ # determine how many chunks of (chunk_size) Addresses there are and the save the remainder
|
|
|
+ self.chunks = local_ip_range // self.chunk_size
|
|
|
+ self.chunk_remainder = local_ip_range % self.chunk_size
|
|
|
+
|
|
|
+ # add the first chunk of IP Addresses
|
|
|
+ self.unused_local_ips = set()
|
|
|
+ self.expand_unused_local_ips()
|
|
|
|
|
|
# save the gathered information for efficient later use
|
|
|
self.external_ips = frozenset(external_ips)
|
|
|
self.remaining_external_ips = external_ips
|
|
|
- self.min_local_ip, self.max_local_ip = min_local_ip, max_local_ip
|
|
|
- self.max_uncertain_local_ip = max_local_ip
|
|
|
+ self.max_uncertain_local_ip = self.max_local_ip
|
|
|
self.local_ips = frozenset(local_ips)
|
|
|
self.remaining_local_ips = local_ips
|
|
|
- self.unused_local_ips = unused_local_ips
|
|
|
- self.uncertain_local_ips = set()
|
|
|
+ self.uncertain_local_ips = set()
|
|
|
+
|
|
|
+ def expand_unused_local_ips(self):
|
|
|
+ """
|
|
|
+ expands the set of unused_local_ips by one chunk_size
|
|
|
+ to illustrate this algorithm: suppose we have a chunksize of 100 and an Address space of 1 to 1000 (1 and 1000 are unused too), we then have 10 chunks
|
|
|
+ every time this method is called, one chunk (100 Addresses) is added, each chunk starts at the base_address + the number of its chunk
|
|
|
+ then, every chunk_amounth'th Address is added. Therefore for 10 chunks, every 10th address is added
|
|
|
+ For the above example for the first, second and last call, we get the following IPs, respectively:
|
|
|
+ first Call: 1+0, 1+10, 1+20, 1+30, ..., 1+990
|
|
|
+ second Call: 2+0, 2+10, 2+20, 2+30, ..., 2+990
|
|
|
+ ten'th Call: 10+0, 10+10, 10+20, 10+30, ..., 10+990
|
|
|
+
|
|
|
+ :return: False if there are no more available unusd local IP Addresses, True otherwise
|
|
|
+ """
|
|
|
+
|
|
|
+ if self.current_chunk == self.chunks+1:
|
|
|
+ # all chunks are used up, therefore add the remainder
|
|
|
+ remainder_base_addr = self.min_local_ip.to_int() + self.chunks*self.chunk_size + 1
|
|
|
+ for i in range(0,self.chunk_remainder):
|
|
|
+ ip = IPAddress.from_int(remainder_base_addr + i)
|
|
|
+ self.unused_local_ips.add(ip)
|
|
|
+
|
|
|
+ self.current_chunk = self.current_chunk + 1
|
|
|
+ return True
|
|
|
+
|
|
|
+ elif self.current_chunk <= self.chunks:
|
|
|
+ # add another chunk
|
|
|
+ # choose IPs from the whole address space, that is available
|
|
|
+ base_address = self.min_local_ip.to_int() + self.current_chunk
|
|
|
+
|
|
|
+ for i in range(0,self.chunk_size):
|
|
|
+ ip = IPAddress.from_int(base_address + i*self.chunks)
|
|
|
+ self.unused_local_ips.add(ip)
|
|
|
+
|
|
|
+ self.current_chunk = self.current_chunk + 1
|
|
|
+ return True
|
|
|
+
|
|
|
+ else:
|
|
|
+ # no free IPs remaining
|
|
|
+ return False
|