Index: fedd/federation/ip_addr.py
===================================================================
--- fedd/federation/ip_addr.py	(revision 1fda364d8bff6b17efb638e67e450dd4c90e3206)
+++ fedd/federation/ip_addr.py	(revision 1fda364d8bff6b17efb638e67e450dd4c90e3206)
@@ -0,0 +1,72 @@
+#!/usr/local/bin/python
+
+class ip_addr:
+    def __init__(self, x):
+	if isinstance(x, ip_addr):
+	    self.ival = x.ival
+	elif isinstance(x, int):
+	    self.ival = x
+	elif isinstance(x, str):
+	    self.ival = 0
+	    sh = 24
+	    bytes = x.split(".", 4)
+	    for b in bytes:
+		self.ival |= (int(b) << sh)
+		sh -= 8
+	else:
+	    self.ival = 0
+    
+    def __str__(self):
+	return "%d.%d.%d.%d" % ((self.ival & 0xff000000) >> 24,
+		(self.ival & 0x00ff0000) >> 16, 
+		(self.ival & 0x0000ff00) >> 8,
+		self.ival & 0x000000ff)
+
+    def __add__(self, i):
+	if isinstance(i, int): return ip_addr(self.ival + i)
+	elif isinstance(i, ip_addr): return ip_addr(self.ival + i.ival)
+	else: raise ValueError("IP addrs must operate on IP addrs or ints")
+
+    def __sub__(self, i):
+	if isinstance(i, int): return ip_addr(self.ival - i)
+	elif isinstance(i, ip_addr): return ip_addr(self.ival - i.ival)
+	else: raise ValueError("IP addrs must operate on IP addrs or ints")
+
+    def __and__(self, i):
+	if isinstance(i, int): return ip_addr(self.ival & i)
+	elif isinstance(i, ip_addr): return ip_addr(self.ival & i.ival)
+	else: raise ValueError("IP addrs must operate on IP addrs or ints")
+
+    def __or__(self, i):
+	if isinstance(i, int): return ip_addr(self.ival | i)
+	elif isinstance(i, ip_addr): return ip_addr(self.ival | i.ival)
+	else: raise ValueError("IP addrs must operate on IP addrs or ints")
+
+    def __xor__(self, i):
+	if isinstance(i, int): return ip_addr(self.ival ^ i)
+	elif isinstance(i, ip_addr): return ip_addr(self.ival ^ i.ival)
+	else: raise ValueError("IP addrs must operate on IP addrs or ints")
+
+    def __radd__(self, i):
+	return self.__add__(i)
+
+    def __rsub__(self, i):
+	return self.__sub__(i)
+
+    def __rand__(self, i):
+	return self.__and__(i)
+
+    def __ror__(self, i):
+	return self.__or__(i)
+
+    def __rxor__(self, i):
+	return self.__xor__(i)
+
+    def __int__(self):
+	return self.ival
+
+    def __oct__(self):
+	return oct(self.ival)
+
+    def __hex__(self):
+	return hex(self.ival)
Index: fedd/federation/ip_allocator.py
===================================================================
--- fedd/federation/ip_allocator.py	(revision 1fda364d8bff6b17efb638e67e450dd4c90e3206)
+++ fedd/federation/ip_allocator.py	(revision 1fda364d8bff6b17efb638e67e450dd4c90e3206)
@@ -0,0 +1,87 @@
+#!/usrl/ocal/bin/python
+
+class ip_allocator:
+    def __init__(self, base=0, size=4294967296, min_alloc=256):
+
+	self.base = base
+	self.size = size
+	self.min_alloc = min_alloc
+
+	i = self.min_alloc
+	self.free = { }
+	self.allocated = { }
+	while i < self.size:
+	    self.free[i] = set()
+	    self.allocated[i] = set()
+	    i *= 2
+	self.free[self.size] = set([self.base])
+	self.allocated[self.size] = set()
+
+    def split(self, base, size):
+	return ( base, base + size)
+
+    def make_chunk(self, size):
+	if not self.free[size * 2]:
+	    if size < self.size:
+		if not self.make_chunk(size * 2):
+		    return False
+	    else:
+		return False
+	base = min(self.free[size*2])
+	self.free[size*2].discard(base)
+
+	for b in self.split(base, size):
+	    self.free[size].add(b)
+	return True
+
+    def allocate(self, size):
+	# Make sure size is a power of 2 at least as big as minalloc
+	ns = self.min_alloc
+	while ns < self.size:
+	    if ns == size:
+		break
+	    if ns > size:
+		size = ns
+		break
+	    ns *= 2
+	else:
+	    size = self.size
+
+	if self.free[size] or self.make_chunk(size):
+	    rv = min(self.free[size])
+	    self.free[size].discard(rv)
+	    self.allocated[size].add(rv)
+	    return (rv, size)
+	else:
+	    return None
+
+    def deallocate(self, base, size):
+	if base not in self.allocated[size]:
+	    raise KeyError("Not allocated")
+	if base % (size * 2) == 0:
+	    if base + size in self.free[size]:
+		self.allocated[size].discard(base)
+		self.allocated[size * 2].add(base)
+		self.free[size].discard(base+size)
+		self.deallocate(base, size *2)
+	    else:
+		self.allocated[size].discard(base)
+		self.free[size].add(base)
+	else:
+	    if base - size in self.free[size]:
+		self.allocated[size].discard(base)
+		self.allocated[size * 2].add(base - size)
+		self.free[size].discard(base - size)
+		self.deallocate(base-size, size * 2)
+	    else:
+		self.allocated[size].discard(base)
+		self.free[size].add(base)
+	return True
+
+    def __str__(self):
+	rv = ""
+	i=self.size
+	while i >= self.min_alloc:
+	    rv += "%d: %s\n" % (i, self.free[i])
+	    i /= 2
+	return rv
