Merge pull request #360 from coreemu/enhancement/coretk-global-ip6

updates for coretk to default to assigning global ip6 addresses
This commit is contained in:
bharnden 2020-01-28 11:30:33 -08:00 committed by GitHub
commit 7cc52f13d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 80 additions and 46 deletions

View file

@ -803,18 +803,26 @@ class CoreClient:
def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface: def create_interface(self, canvas_node: CanvasNode) -> core_pb2.Interface:
node = canvas_node.core_node node = canvas_node.core_node
ip4, ip6, prefix = self.interfaces_manager.get_ips(node.id) ip4, ip6 = self.interfaces_manager.get_ips(node.id)
ip4_mask = self.interfaces_manager.ip4_mask
ip6_mask = self.interfaces_manager.ip6_mask
interface_id = len(canvas_node.interfaces) interface_id = len(canvas_node.interfaces)
name = f"eth{interface_id}" name = f"eth{interface_id}"
interface = core_pb2.Interface( interface = core_pb2.Interface(
id=interface_id, name=name, ip4=ip4, ip4mask=prefix, ip6=ip6, ip6mask=prefix id=interface_id,
name=name,
ip4=ip4,
ip4mask=ip4_mask,
ip6=ip6,
ip6mask=ip6_mask,
) )
canvas_node.interfaces.append(interface) canvas_node.interfaces.append(interface)
logging.debug( logging.debug(
"create node(%s) interface IPv4: %s, name: %s", "create node(%s) interface(%s) IPv4(%s) IPv6(%s)",
node.name, node.name,
interface.ip4,
interface.name, interface.name,
interface.ip4,
interface.ip6,
) )
return interface return interface
@ -829,7 +837,7 @@ class CoreClient:
dst_node = canvas_dst_node.core_node dst_node = canvas_dst_node.core_node
# determine subnet # determine subnet
self.interfaces_manager.determine_subnet(canvas_src_node, canvas_dst_node) self.interfaces_manager.determine_subnets(canvas_src_node, canvas_dst_node)
src_interface = None src_interface = None
if NodeUtils.is_container_node(src_node.type): if NodeUtils.is_container_node(src_node.type):

View file

@ -16,45 +16,71 @@ def random_mac():
return ("{:02x}" * 6).format(*[random.randrange(256) for _ in range(6)]) return ("{:02x}" * 6).format(*[random.randrange(256) for _ in range(6)])
class InterfaceManager: class Subnets:
def __init__(self, app: "Application", address: str = "10.0.0.0", mask: int = 24): def __init__(self, ip4: IPNetwork, ip6: IPNetwork) -> None:
self.app = app self.ip4 = ip4
self.mask = mask self.ip6 = ip6
self.base_prefix = max(self.mask - 8, 0)
self.subnets = IPNetwork(f"{address}/{self.base_prefix}")
self.current_subnet = None
def next_subnet(self) -> IPNetwork: def __eq__(self, other: "Subnets") -> bool:
return (self.ip4, self.ip6) == (other.ip4, other.ip6)
def __hash__(self) -> int:
return hash((self.ip4, self.ip6))
def next(self) -> "Subnets":
return Subnets(self.ip4.next(), self.ip6.next())
class InterfaceManager:
def __init__(
self,
app: "Application",
ip4: str = "10.0.0.0",
ip4_mask: int = 24,
ip6: str = "2001::",
ip6_mask=64,
) -> None:
self.app = app
self.ip4_mask = ip4_mask
self.ip6_mask = ip6_mask
self.ip4_subnets = IPNetwork(f"{ip4}/{ip4_mask}")
self.ip6_subnets = IPNetwork(f"{ip6}/{ip6_mask}")
self.current_subnets = None
def next_subnets(self) -> Subnets:
# define currently used subnets # define currently used subnets
used_subnets = set() used_subnets = set()
for edge in self.app.core.links.values(): for edge in self.app.core.links.values():
link = edge.link link = edge.link
subnets = None
if link.HasField("interface_one"): if link.HasField("interface_one"):
subnet = self.get_subnet(link.interface_one) subnets = self.get_subnets(link.interface_one)
used_subnets.add(subnet)
if link.HasField("interface_two"): if link.HasField("interface_two"):
subnet = self.get_subnet(link.interface_two) subnets = self.get_subnets(link.interface_two)
used_subnets.add(subnet) if subnets:
used_subnets.add(subnets)
# find next available subnet # find next available subnets
for i in self.subnets.subnet(self.mask): subnets = Subnets(self.ip4_subnets, self.ip6_subnets)
if i not in used_subnets: while subnets in used_subnets:
return i subnets = subnets.next()
return subnets
def reset(self): def reset(self):
self.current_subnet = None self.current_subnets = None
def get_ips(self, node_id: int) -> [str, str, int]: def get_ips(self, node_id: int) -> [str, str]:
ip4 = self.current_subnet[node_id] ip4 = self.current_subnets.ip4[node_id]
ip6 = ip4.ipv6() ip6 = self.current_subnets.ip6[node_id]
prefix = self.current_subnet.prefixlen return str(ip4), str(ip6)
return str(ip4), str(ip6), prefix
@classmethod @classmethod
def get_subnet(cls, interface: "core_pb2.Interface") -> IPNetwork: def get_subnets(cls, interface: "core_pb2.Interface") -> Subnets:
return IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr ip4_subnet = IPNetwork(f"{interface.ip4}/{interface.ip4mask}").cidr
ip6_subnet = IPNetwork(f"{interface.ip6}/{interface.ip6mask}").cidr
return Subnets(ip4_subnet, ip6_subnet)
def determine_subnet( def determine_subnets(
self, canvas_src_node: "CanvasNode", canvas_dst_node: "CanvasNode" self, canvas_src_node: "CanvasNode", canvas_dst_node: "CanvasNode"
): ):
src_node = canvas_src_node.core_node src_node = canvas_src_node.core_node
@ -62,28 +88,28 @@ 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_subnet = self.next_subnet() self.current_subnets = self.next_subnets()
elif is_src_container and not is_dst_container: elif is_src_container and not is_dst_container:
subnet = self.find_subnet(canvas_dst_node, visited={src_node.id}) subnets = self.find_subnets(canvas_dst_node, visited={src_node.id})
if subnet: if subnets:
self.current_subnet = subnet self.current_subnets = subnets
else: else:
self.current_subnet = self.next_subnet() self.current_subnets = self.next_subnets()
elif not is_src_container and is_dst_container: elif not is_src_container and is_dst_container:
subnet = self.find_subnet(canvas_src_node, visited={dst_node.id}) subnets = self.find_subnets(canvas_src_node, visited={dst_node.id})
if subnet: if subnets:
self.current_subnet = subnet self.current_subnets = subnets
else: else:
self.current_subnet = self.next_subnet() self.current_subnets = self.next_subnets()
else: else:
logging.info("ignoring subnet change for link between network nodes") logging.info("ignoring subnet change for link between network nodes")
def find_subnet( def find_subnets(
self, canvas_node: "CanvasNode", visited: Set[int] = None self, canvas_node: "CanvasNode", visited: Set[int] = None
) -> Union[IPNetwork, None]: ) -> Union[IPNetwork, None]:
logging.info("finding subnet for node: %s", canvas_node.core_node.name) logging.info("finding subnet for node: %s", canvas_node.core_node.name)
canvas = self.app.canvas canvas = self.app.canvas
cidr = None subnets = None
if not visited: if not visited:
visited = set() visited = set()
visited.add(canvas_node.core_node.id) visited.add(canvas_node.core_node.id)
@ -99,10 +125,10 @@ 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_subnet(interface) subnets = self.get_subnets(interface)
else: else:
cidr = self.find_subnet(check_node, visited) subnets = self.find_subnets(check_node, visited)
if cidr: if subnets:
logging.info("found subnet: %s", cidr) logging.info("found subnets: %s", subnets)
break break
return cidr return subnets