simplified logic for picking next subnet, avoiding trying to optimize too early

This commit is contained in:
Blake Harnden 2019-11-25 11:31:40 -08:00
parent 27a37c77fc
commit 1290dae4f8
2 changed files with 39 additions and 63 deletions

View file

@ -45,7 +45,6 @@ class CoreClient:
self.node_ids = [] self.node_ids = []
self.app = app self.app = app
self.master = app.master self.master = app.master
self.interface_helper = None
self.services = {} self.services = {}
self.default_services = {} self.default_services = {}
self.emane_models = [] self.emane_models = []
@ -493,8 +492,6 @@ class CoreClient:
if node_id == node_id: if node_id == node_id:
del self.emane_model_configs[key] del self.emane_model_configs[key]
deleted_cidrs = set()
keep_cidrs = set()
for edge in canvas_node.edges: for edge in canvas_node.edges:
if edge in edges: if edge in edges:
continue continue
@ -502,29 +499,7 @@ class CoreClient:
if edge.token not in self.links: if edge.token not in self.links:
logging.error("unknown edge: %s", edge.token) logging.error("unknown edge: %s", edge.token)
del self.links[edge.token] del self.links[edge.token]
other_id = edge.src
other_interface = edge.src_interface
interface = edge.dst_interface
if canvas_node.id == edge.src:
other_id = edge.dst
other_interface = edge.dst_interface
interface = edge.src_interface
other_node = self.app.canvas.nodes.get(other_id)
if not other_node:
continue
if other_interface:
cidr = self.interfaces_manager.get_cidr(other_interface)
deleted_cidrs.add(cidr)
else:
cidr = self.interfaces_manager.find_subnet(other_node)
if cidr:
keep_cidrs.add(cidr)
else:
cidr = self.interfaces_manager.get_cidr(interface)
deleted_cidrs.add(cidr)
deleted_cidrs = deleted_cidrs - keep_cidrs
for cidr in deleted_cidrs:
self.interfaces_manager.deleted_cidr(cidr)
self.deleted_nodes.sort() self.deleted_nodes.sort()
def create_interface(self, canvas_node): def create_interface(self, canvas_node):

View file

@ -11,39 +11,40 @@ def random_mac():
class InterfaceManager: class InterfaceManager:
def __init__(self, app, cidr="10.0.0.0/24"): def __init__(self, app, address="10.0.0.0", mask=24):
self.app = app self.app = app
self.default = cidr self.mask = mask
self.cidr = IPNetwork(cidr) self.base_prefix = max(self.mask - 8, 0)
self.deleted = [] self.subnets = IPNetwork(f"{address}/{self.base_prefix}")
self.current = None self.current_subnet = None
def reset(self):
self.cidr = IPNetwork(self.default)
self.deleted.clear()
self.current = None
def get_ips(self, node_id):
ip4 = self.current[node_id]
ip6 = ip4.ipv6()
return str(ip4), str(ip6), self.current.prefixlen
def next_subnet(self): def next_subnet(self):
if self.deleted: # define currently used subnets
return self.deleted.pop(0) used_subnets = set()
else: for link in self.app.core.links.values():
if self.current: if link.HasField("interface_one"):
self.cidr = self.cidr.next() subnet = self.get_subnet(link.interface_one)
return self.cidr used_subnets.add(subnet)
if link.HasField("interface_two"):
subnet = self.get_subnet(link.interface_two)
used_subnets.add(subnet)
def deleted_cidr(self, cidr): # find next available subnet
logging.info("deleted cidr: %s", cidr) for i in self.subnets.subnet(self.mask):
if cidr not in self.deleted: if i not in used_subnets:
self.deleted.append(cidr) return i
self.deleted.sort()
def reset(self):
self.current_subnet = None
def get_ips(self, node_id):
ip4 = self.current_subnet[node_id]
ip6 = ip4.ipv6()
prefix = self.current_subnet.prefixlen
return str(ip4), str(ip6), prefix
@classmethod @classmethod
def get_cidr(cls, interface): def get_subnet(cls, interface):
return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr
def determine_subnet(self, canvas_src_node, canvas_dst_node): def determine_subnet(self, canvas_src_node, canvas_dst_node):
@ -52,19 +53,19 @@ class InterfaceManager:
is_src_container = NodeUtils.is_container_node(src_node.type) is_src_container = NodeUtils.is_container_node(src_node.type)
is_dst_container = NodeUtils.is_container_node(dst_node.type) is_dst_container = NodeUtils.is_container_node(dst_node.type)
if is_src_container and is_dst_container: if is_src_container and is_dst_container:
self.current = self.next_subnet() self.current_subnet = self.next_subnet()
elif is_src_container and not is_dst_container: elif is_src_container and not is_dst_container:
cidr = self.find_subnet(canvas_dst_node, visited={src_node.id}) subnet = self.find_subnet(canvas_dst_node, visited={src_node.id})
if cidr: if subnet:
self.current = cidr self.current_subnet = subnet
else: else:
self.current = self.next_subnet() self.current_subnet = self.next_subnet()
elif not is_src_container and is_dst_container: elif not is_src_container and is_dst_container:
cidr = self.find_subnet(canvas_src_node, visited={dst_node.id}) subnet = self.find_subnet(canvas_src_node, visited={dst_node.id})
if cidr: if subnet:
self.current = cidr self.current_subnet = subnet
else: else:
self.current = self.next_subnet() self.current_subnet = self.next_subnet()
else: else:
logging.info("ignoring subnet change for link between network nodes") logging.info("ignoring subnet change for link between network nodes")
@ -87,7 +88,7 @@ class InterfaceManager:
continue continue
visited.add(check_node.core_node.id) visited.add(check_node.core_node.id)
if interface: if interface:
cidr = self.get_cidr(interface) cidr = self.get_subnet(interface)
else: else:
cidr = self.find_subnet(check_node, visited) cidr = self.find_subnet(check_node, visited)
if cidr: if cidr: