diff --git a/daemon/core/emulator/session.py b/daemon/core/emulator/session.py index 1445cb8f..e864ec8b 100644 --- a/daemon/core/emulator/session.py +++ b/daemon/core/emulator/session.py @@ -153,7 +153,7 @@ class Session(object): self.services.default_services = { "mdr": ("zebra", "OSPFv3MDR", "IPForward"), "PC": ("DefaultRoute",), - "prouter": ("zebra", "OSPFv2", "OSPFv3", "IPForward"), + "prouter": (), "router": ("zebra", "OSPFv2", "OSPFv3", "IPForward"), "host": ("DefaultRoute", "SSH"), } @@ -192,32 +192,33 @@ class Session(object): for name in self.servers: server = self.servers[name] - host = server.host - key = self.tunnelkey(node_id, IpAddress.to_int(host)) + self.create_gre_tunnel(node, server) - # local to server - logging.info( - "local tunnel node(%s) to remote(%s) key(%s)", node.name, host, key - ) - local_tap = GreTap(session=self, remoteip=host, key=key) - local_tap.net_client.create_interface(node.brname, local_tap.localname) + def create_gre_tunnel(self, node, server): + host = server.host + key = self.tunnelkey(node.id, IpAddress.to_int(host)) + tunnel = self.tunnels.get(key) + if tunnel is not None: + return tunnel - # server to local - logging.info( - "remote tunnel node(%s) to local(%s) key(%s)", - node.name, - self.address, - key, - ) - remote_tap = GreTap( - session=self, remoteip=self.address, key=key, server=server - ) - remote_tap.net_client.create_interface( - node.brname, remote_tap.localname - ) + # local to server + logging.info( + "local tunnel node(%s) to remote(%s) key(%s)", node.name, host, key + ) + local_tap = GreTap(session=self, remoteip=host, key=key) + local_tap.net_client.create_interface(node.brname, local_tap.localname) - # save tunnels for shutdown - self.tunnels[key] = (local_tap, remote_tap) + # server to local + logging.info( + "remote tunnel node(%s) to local(%s) key(%s)", node.name, self.address, key + ) + remote_tap = GreTap(session=self, remoteip=self.address, key=key, server=server) + remote_tap.net_client.create_interface(node.brname, remote_tap.localname) + + # save tunnels for shutdown + tunnel = (local_tap, remote_tap) + self.tunnels[key] = tunnel + return tunnel def tunnelkey(self, n1_id, n2_id): """ diff --git a/daemon/core/nodes/physical.py b/daemon/core/nodes/physical.py index 93e04c5e..ecbcf368 100644 --- a/daemon/core/nodes/physical.py +++ b/daemon/core/nodes/physical.py @@ -9,15 +9,19 @@ import threading from core import utils from core.constants import MOUNT_BIN, UMOUNT_BIN from core.emulator.enumerations import NodeTypes -from core.errors import CoreCommandError +from core.errors import CoreCommandError, CoreError from core.nodes.base import CoreNodeBase from core.nodes.interface import CoreInterface from core.nodes.network import CoreNetwork, GreTap class PhysicalNode(CoreNodeBase): - def __init__(self, session, _id=None, name=None, nodedir=None, start=True): - CoreNodeBase.__init__(self, session, _id, name, start=start) + def __init__( + self, session, _id=None, name=None, nodedir=None, start=True, server=None + ): + CoreNodeBase.__init__(self, session, _id, name, start, server) + if not self.server: + raise CoreError("physical nodes must be assigned to a remote server") self.nodedir = nodedir self.up = start self.lock = threading.RLock() @@ -86,7 +90,6 @@ class PhysicalNode(CoreNodeBase): def adoptnetif(self, netif, ifindex, hwaddr, addrlist): """ - The broker builds a GreTap tunnel device to this physical node. When a link message is received linking this node to another part of the emulation, no new interface is created; instead, adopt the GreTap netif as the node interface. @@ -157,26 +160,21 @@ class PhysicalNode(CoreNodeBase): if ifindex is None: ifindex = self.newifindex() - if self.up: - # this is reached when this node is linked to a network node - # tunnel to net not built yet, so build it now and adopt it - gt = self.session.broker.addnettunnel(net.id) - if gt is None or len(gt) != 1: - raise ValueError( - "error building tunnel from adding a new network interface: %s" % gt - ) - gt = gt[0] - net.detach(gt) - self.adoptnetif(gt, ifindex, hwaddr, addrlist) - return ifindex - - # this is reached when configuring services (self.up=False) if ifname is None: ifname = "gt%d" % ifindex - netif = GreTap(node=self, name=ifname, session=self.session, start=False) - self.adoptnetif(netif, ifindex, hwaddr, addrlist) - return ifindex + if self.up: + # this is reached when this node is linked to a network node + # tunnel to net not built yet, so build it now and adopt it + _, remote_tap = self.session.create_gre_tunnel(net, self.server) + # net.detach(remote_tap) + self.adoptnetif(remote_tap, ifindex, hwaddr, addrlist) + return ifindex + else: + # this is reached when configuring services (self.up=False) + netif = GreTap(node=self, name=ifname, session=self.session, start=False) + self.adoptnetif(netif, ifindex, hwaddr, addrlist) + return ifindex def privatedir(self, path): if path[0] != "/": @@ -223,6 +221,9 @@ class PhysicalNode(CoreNodeBase): os.chmod(node_file.name, mode) logging.info("created nodefile: '%s'; mode: 0%o", node_file.name, mode) + def node_net_cmd(self, args, wait=True): + return self.net_cmd(args, wait=wait) + class Rj45Node(CoreNodeBase, CoreInterface): """ diff --git a/gui/nodes.tcl b/gui/nodes.tcl index 00e52c5d..c8645f03 100644 --- a/gui/nodes.tcl +++ b/gui/nodes.tcl @@ -19,7 +19,7 @@ array set g_node_types_default { 4 {mdr mdr.gif mdr.gif {zebra OSPFv3MDR IPForward} \ netns {built-in type for wireless routers}} 5 {prouter router_green.gif router_green.gif \ - {zebra OSPFv2 OSPFv3 IPForward} \ + {} \ physical {built-in type for physical nodes}} }