def link_config(network, interface, link_options, devname=None, interface_two=None): """ Convenience method for configuring a link, :param network: network to configure link for :param interface: interface to configure :param core.emulator.emudata.LinkOptions link_options: data to configure link with :param str devname: device name, default is None :param interface_two: other interface associated, default is None :return: nothing """ config = { "netif": interface, "bw": link_options.bandwidth, "delay": link_options.delay, "loss": link_options.per, "duplicate": link_options.dup, "jitter": link_options.jitter, "netif2": interface_two, } # hacky check here, because physical and emane nodes do not conform to the same linkconfig interface if not nodeutils.is_node(network, [NodeTypes.EMANE, NodeTypes.PHYSICAL]): config["devname"] = devname network.linkconfig(**config)
def waitfordevicenode(self): """ Check for presence of a node device - tap device may not appear right away waits. :return: nothing """ logging.debug("waiting for device node: %s", self.name) def nodedevexists(): args = [constants.IP_BIN, "link", "show", self.name] return self.node.cmd(args) count = 0 while True: result = self.waitfor(nodedevexists) if result: break # check if this is an EMANE interface; if so, continue # waiting if EMANE is still running # TODO: remove emane code should_retry = count < 5 is_emane_node = nodeutils.is_node(self.net, NodeTypes.EMANE) is_emane_running = self.node.session.emane.emanerunning(self.node) if all([should_retry, is_emane_node, is_emane_running]): count += 1 else: raise RuntimeError("node device failed to exist")
def add_virtual_host(self, physical_host, node): if not isinstance(node, CoreNodeBase): raise TypeError("invalid node type: %s" % node) # create virtual host element host_id = "%s/%s" % (physical_host.get("id"), node.name) host_element = etree.SubElement(physical_host, "testHost", id=host_id, name=node.name) # add host type add_type(host_element, "virtual") for netif in node.netifs(): emane_element = None if nodeutils.is_node(netif.net, NodeTypes.EMANE): emane_element = add_emane_interface(host_element, netif) parent_element = host_element if emane_element is not None: parent_element = emane_element for address in netif.addrlist: address_type = get_address_type(address) add_address(parent_element, address_type, address, netif.name)
def ptpcheck(ifc): """ Helper to detect whether interface is connected to a notional point-to-point link. """ if nodeutils.is_node(ifc.net, NodeTypes.PEER_TO_PEER): return " ipv6 ospf6 network point-to-point\n" return ""
def sendobjs(self): """ Session has already started, and the SDT3D GUI later connects. Send all node and link objects for display. Otherwise, nodes and links will only be drawn when they have been updated (e.g. moved). :return: nothing """ nets = [] with self.session._nodes_lock: for node_id in self.session.nodes: node = self.session.nodes[node_id] if isinstance(node, CoreNetworkBase): nets.append(node) if not isinstance(node, NodeBase): continue (x, y, z) = node.getposition() if x is None or y is None: continue self.updatenode( node.id, MessageFlags.ADD.value, x, y, z, node.name, node.type, node.icon, ) for nodenum in sorted(self.remotes.keys()): r = self.remotes[nodenum] x, y, z = r.pos self.updatenode(nodenum, MessageFlags.ADD.value, x, y, z, r.name, r.type, r.icon) for net in nets: all_links = net.all_link_data(flags=MessageFlags.ADD.value) for link_data in all_links: is_wireless = nodeutils.is_node( net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)) wireless_link = link_data.message_type == LinkTypes.WIRELESS.value if is_wireless and link_data.node1_id == net.id: continue self.updatelink( link_data.node1_id, link_data.node2_id, MessageFlags.ADD.value, wireless_link, ) for n1num in sorted(self.remotes.keys()): r = self.remotes[n1num] for n2num, wireless_link in r.links: self.updatelink(n1num, n2num, MessageFlags.ADD.value, wireless_link)
def setup(self): """ Populate self._objs with EmaneNodes; perform distributed setup; associate models with EmaneNodes from self.config. Returns Emane.(SUCCESS, NOT_NEEDED, NOT_READY) in order to delay session instantiation. """ logging.debug("emane setup") # TODO: drive this from the session object with self.session._nodes_lock: for node_id in self.session.nodes: node = self.session.nodes[node_id] if nodeutils.is_node(node, NodeTypes.EMANE): logging.debug("adding emane node: id(%s) name(%s)", node.id, node.name) self.add_node(node) if not self._emane_nodes: logging.debug("no emane nodes in session") return EmaneManager.NOT_NEEDED # control network bridge required for EMANE 0.9.2 # - needs to be configured before checkdistributed() for distributed # - needs to exist when eventservice binds to it (initeventservice) if self.session.master: otadev = self.get_config("otamanagerdevice") netidx = self.session.get_control_net_index(otadev) logging.debug("emane ota manager device: index(%s) otadev(%s)", netidx, otadev) if netidx < 0: logging.error("EMANE cannot start, check core config. invalid OTA device provided: %s", otadev) return EmaneManager.NOT_READY ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False) self.distributedctrlnet(ctrlnet) eventdev = self.get_config("eventservicedevice") logging.debug("emane event service device: eventdev(%s)", eventdev) if eventdev != otadev: netidx = self.session.get_control_net_index(eventdev) logging.debug("emane event service device index: %s", netidx) if netidx < 0: logging.error("EMANE cannot start, check core config. invalid event service device: %s", eventdev) return EmaneManager.NOT_READY ctrlnet = self.session.add_remove_control_net(net_index=netidx, remove=False, conf_required=False) self.distributedctrlnet(ctrlnet) if self.checkdistributed(): # we are slave, but haven't received a platformid yet platform_id_start = "platform_id_start" default_values = self.emane_config.default_values() value = self.get_config(platform_id_start) if value == default_values[platform_id_start]: return EmaneManager.NOT_READY self.check_node_models() return EmaneManager.SUCCESS
def rj45check(ifc): """ Helper to detect whether interface is connected an external RJ45 link. """ if ifc.net: for peerifc in ifc.net.netifs(): if peerifc == ifc: continue if nodeutils.is_node(peerifc, NodeTypes.RJ45): return True return False
def newnetif(self, net=None, addrlist=None, hwaddr=None, ifindex=None, ifname=None): """ Create a new network interface. :param core.nodes.base.CoreNetworkBase net: network to associate with :param list addrlist: addresses to add on the interface :param core.nodes.ipaddress.MacAddress hwaddr: hardware address to set for interface :param int ifindex: index of interface to create :param str ifname: name for interface :return: interface index :rtype: int """ if not addrlist: addrlist = [] with self.lock: # TODO: see if you can move this to emane specific code if nodeutils.is_node(net, NodeTypes.EMANE): ifindex = self.newtuntap(ifindex=ifindex, ifname=ifname, net=net) # TUN/TAP is not ready for addressing yet; the device may # take some time to appear, and installing it into a # namespace after it has been bound removes addressing; # save addresses with the interface now self.attachnet(ifindex, net) netif = self.netif(ifindex) netif.sethwaddr(hwaddr) for address in utils.make_tuple(addrlist): netif.addaddr(address) return ifindex else: ifindex = self.newveth(ifindex=ifindex, ifname=ifname, net=net) if net is not None: self.attachnet(ifindex, net) if hwaddr: self.sethwaddr(ifindex, hwaddr) for address in utils.make_tuple(addrlist): self.addaddr(ifindex, address) self.ifup(ifindex) return ifindex
def generatequaggaifcconfig(cls, node, ifc): cfg = cls.mtucheck(ifc) # Uncomment the following line to use Address Family Translation for IPv4 cfg += " ipv6 ospf6 instance-id 65\n" if ifc.net is not None and nodeutils.is_node( ifc.net, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): return (cfg + """\ ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 6 ipv6 ospf6 retransmit-interval 5 ipv6 ospf6 network manet-designated-router ipv6 ospf6 diffhellos ipv6 ospf6 adjacencyconnectivity uniconnected ipv6 ospf6 lsafullness mincostlsa """) else: return cfg
def GetSession(self, request, context): logging.debug("get session: %s", request) session = self.get_session(request.session_id, context) links = [] nodes = [] for _id in session.nodes: node = session.nodes[_id] if not isinstance(node.id, int): continue node_type = nodeutils.get_node_type(node.__class__).value model = getattr(node, "type", None) position = core_pb2.Position(x=node.position.x, y=node.position.y, z=node.position.z) services = getattr(node, "services", []) if services is None: services = [] services = [x.name for x in services] emane_model = None if nodeutils.is_node(node, NodeTypes.EMANE): emane_model = node.model.name node_proto = core_pb2.Node(id=node.id, name=node.name, emane=emane_model, model=model, type=node_type, position=position, services=services) nodes.append(node_proto) node_links = get_links(session, node) links.extend(node_links) session_proto = core_pb2.Session(state=session.state, nodes=nodes, links=links) return core_pb2.GetSessionResponse(session=session_proto)
def wlancheck(self, nodenum): """ Helper returns True if a node number corresponds to a WlanNode or EmaneNode. :param int nodenum: node id to check :return: True if node is wlan or emane, False otherwise :rtype: bool """ if nodenum in self.remotes: node_type = self.remotes[nodenum].type if node_type in ("wlan", "emane"): return True else: try: n = self.session.get_node(nodenum) except CoreError: return False if nodeutils.is_node(n, (NodeTypes.WIRELESS_LAN, NodeTypes.EMANE)): return True return False
def write_nodes(self): self.networks = etree.SubElement(self.scenario, "networks") self.devices = etree.SubElement(self.scenario, "devices") links = [] for node_id in self.session.nodes: node = self.session.nodes[node_id] # network node is_network_or_rj45 = isinstance(node, (core.nodes.base.CoreNetworkBase, core.nodes.physical.Rj45Node)) is_controlnet = nodeutils.is_node(node, NodeTypes.CONTROL_NET) if is_network_or_rj45 and not is_controlnet: self.write_network(node) # device node elif isinstance(node, core.nodes.base.CoreNodeBase): self.write_device(node) # add known links links.extend(node.all_link_data(0)) return links
def create_interface_element(self, element_name, node_id, interface_id, mac, ip4, ip4_mask, ip6, ip6_mask): interface = etree.Element(element_name) node = self.session.get_node(node_id) interface_name = None if not isinstance(node, CoreNetworkBase): node_interface = node.netif(interface_id) interface_name = node_interface.name # check if emane interface if nodeutils.is_node(node_interface.net, NodeTypes.EMANE): nem = node_interface.net.getnemid(node_interface) add_attribute(interface, "nem", nem) add_attribute(interface, "id", interface_id) add_attribute(interface, "name", interface_name) add_attribute(interface, "mac", mac) add_attribute(interface, "ip4", ip4) add_attribute(interface, "ip4_mask", ip4_mask) add_attribute(interface, "ip6", ip6) add_attribute(interface, "ip6_mask", ip6_mask) return interface
def GetNode(self, request, context): logging.debug("get node: %s", request) session = self.get_session(request.session_id, context) node = self.get_node(session, request.node_id, context) interfaces = [] for interface_id in node._netif: interface = node._netif[interface_id] net_id = None if interface.net: net_id = interface.net.id interface_proto = core_pb2.Interface(id=interface_id, netid=net_id, name=interface.name, mac=str(interface.hwaddr), mtu=interface.mtu, flowid=interface.flow_id) interfaces.append(interface_proto) emane_model = None if nodeutils.is_node(node, NodeTypes.EMANE): emane_model = node.model.name services = [x.name for x in getattr(node, "services", [])] position = core_pb2.Position(x=node.position.x, y=node.position.y, z=node.position.z) node_type = nodeutils.get_node_type(node.__class__).value node = core_pb2.Node(id=node.id, name=node.name, type=node_type, emane=emane_model, model=node.type, position=position, services=services) return core_pb2.GetNodeResponse(node=node, interfaces=interfaces)
def generate_config(cls, node, filename): if filename == cls.configs[0]: transport_commands = [] for interface in node.netifs(sort=True): network_node = node.session.get_node(interface.net.id) if nodeutils.is_node(network_node, NodeTypes.EMANE): config = node.session.emane.get_configs( network_node.id, network_node.model.name) if config and emanexml.is_external(config): nem_id = network_node.getnemid(interface) command = ( "emanetransportd -r -l 0 -d ../transportdaemon%s.xml" % nem_id) transport_commands.append(command) transport_commands = "\n".join(transport_commands) return """ emanegentransportxml -o ../ ../platform%s.xml %s """ % ( node.id, transport_commands, ) else: raise ValueError
def addnettunnel(self, node_id): """ Add network tunnel between node and broker. :param int node_id: node id of network to add tunnel to :return: list of gre taps :rtype: list """ try: net = self.session.get_node(node_id) logging.info("adding net tunnel for: id(%s) %s", node_id, net) except KeyError: raise KeyError("network node %s not found" % node_id) # add other nets here that do not require tunnels if nodeutils.is_node(net, NodeTypes.EMANE_NET): logging.warning("emane network does not require a tunnel") return None server_interface = getattr(net, "serverintf", None) if nodeutils.is_node( net, NodeTypes.CONTROL_NET) and server_interface is not None: logging.warning( "control networks with server interfaces do not need a tunnel") return None servers = self.getserversbynode(node_id) if len(servers) < 2: logging.warning("not enough servers to create a tunnel: %s", servers) return None hosts = [] for server in servers: if server.host is None: continue logging.info("adding server host for net tunnel: %s", server.host) hosts.append(server.host) if len(hosts) == 0: for session_client in self.session_clients: # get IP address from API message sender (master) if session_client.client_address != "": address = session_client.client_address[0] logging.info("adding session_client host: %s", address) hosts.append(address) r = [] for host in hosts: if self.myip: # we are the remote emulation server myip = self.myip else: # we are the session master myip = host key = self.tunnelkey(node_id, IpAddress.to_int(myip)) if key in self.tunnels.keys(): logging.info( "tunnel already exists, returning existing tunnel: %s", key) gt = self.tunnels[key] r.append(gt) continue logging.info("adding tunnel for net %s to %s with key %s", node_id, host, key) gt = GreTap(node=None, name=None, session=self.session, remoteip=host, key=key) self.tunnels[key] = gt r.append(gt) # attaching to net will later allow gt to be destroyed # during net.shutdown() net.attach(gt) return r