1 # The software in this package is distributed under the GNU General
2 # Public License version 2 (with a special exception described below).
4 # A copy of GNU General Public License (GPL) is included in this distribution,
5 # in the file COPYING.GPL.
7 # As a special exception, if other files instantiate templates or use macros
8 # or inline functions from this file, or you compile this file and link it
9 # with other works to produce a work based on this file, this file
10 # does not by itself cause the resulting work to be covered
11 # by the GNU General Public License.
13 # However the source code for this file must still be made available
14 # in accordance with section (3) of the GNU General Public License.
16 # This exception does not invalidate any other reasons why a work based
17 # on this file might be covered by the GNU General Public License.
19 # Copyright (c) 2016-2018 Intra2net AG <info@intra2net.com>
24 ------------------------------------------------------
27 Copyright: Intra2net AG
31 ------------------------------------------------------
36 default_addr_range = 42
37 uint32_max = 0xffffffff
42 def __init__(self, lo=None, addr_range=None):
43 self.val_lo = default_addr_lo # : int, initial offset for allocation
44 self.val_range = default_addr_range # : int, allocation block size
45 self.val_hi = 0 # : int, lo + range
46 self.var_alloc = {} # : mutable int, bool allocated values
49 if isinstance(lo, int) is False:
50 raise TypeError("Expected value of integer type, got \"%s\" : %s."
53 if addr_range is not None:
54 if isinstance(addr_range, int) is False:
55 raise TypeError("Expected value of integer type, got \"%s\" : %s."
57 self.val_range = addr_range
59 for val in range(self.val_lo, self.val_hi):
60 # we use ints as keys since the types are checked elsewhere
61 self.var_alloc[val] = False
65 for v in self.var_alloc.values():
66 length += 1 if v is True else 0
69 def __eq__(self, other):
70 if isinstance(other, int):
71 return other == len(self)
72 if isinstance(other, self.__class__):
73 return len(self) == len(other)
74 raise TypeError("Equality comparison of %s with type %s is undefined."
75 % (self.__class__.__name__, type(other)))
77 def __getitem__(self, k):
79 return self.var_alloc[k]
84 if self.val_range <= 0:
85 raise TypeError("IP address ranges need to be natural numbers > 0."
86 % (self.val_lo, self.val_range))
87 hi = self.val_lo + self.val_range
88 if hi <= self.val_lo or hi > uint32_max:
89 raise ValueError("Invalid IP address range: %d+%d."
90 % (self.val_lo, self.val_range))
104 .get -- Return lowest unallocated number in range and insert as a
109 if curlen == self.val_range:
110 raise IndexError("Address range (%d) exhausted."
112 for val in range(self.val_lo, self.val_hi):
113 if self.var_alloc[val] is False:
114 self.var_alloc[val] = True
119 Remove allocated number from range.
121 if isinstance(val, int) is False:
122 raise TypeError("Expected int or short, got %s." % type(val))
125 if val < self.val_lo or self.val_hi < val:
126 raise IndexError("Address %d out of bounds ([%d, %d])."
127 % (vali, self.val_lo, self.val_hi))
128 if self.var_alloc[vali] is False:
129 raise ValueError("Address %d was never allocated." % vali)
130 self.var_alloc[vali] = True
133 return "v4 address range: [%d, %d] = %d+%d, at %d (%.2f%%)" \
139 (100.0 * (float(len(self.var_alloc)) / float(self.val_range))))
142 return "(%d, %d, %s)" \
145 self.var_alloc.__repr__())