def test_xml_emane_node_config(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): # create nodes options = NodeOptions(model="mdr", x=50, y=50) node1 = session.add_node(CoreNode, options=options) iface1_data = ip_prefixes.create_iface(node1) node2 = session.add_node(CoreNode, options=options) iface2_data = ip_prefixes.create_iface(node2) # create emane node options = NodeOptions(model=None, emane=EmaneRfPipeModel.name) emane_node = session.add_node(EmaneNet, options=options) # create links session.add_link(node1.id, emane_node.id, iface1_data) session.add_link(node2.id, emane_node.id, iface2_data) # set node specific config datarate = "101" session.emane.set_config(node1.id, EmaneRfPipeModel.name, {"datarate": datarate}) # instantiate session session.instantiate() # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(Path(file_path)) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2.id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(emane_node.id, EmaneNet) # load saved xml session.open_xml(Path(file_path), start=True) # verify nodes have been recreated assert session.get_node(node1.id, CoreNode) assert session.get_node(node2.id, CoreNode) assert session.get_node(emane_node.id, EmaneNet) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.links() assert len(links) == 2 config = session.emane.get_config(node1.id, EmaneRfPipeModel.name) assert config["datarate"] == datarate
def test_wired_ping(self, session: Session, net_type: Type[NodeBase], ip_prefixes: IpPrefixes): """ Test ptp node network. :param session: session for test :param core.enumerations.NodeTypes net_type: type of net node to create :param ip_prefixes: generates ip addresses for nodes """ # create net node net_node = session.add_node(net_type) # create nodes node_one = session.add_node(CoreNode) node_two = session.add_node(CoreNode) # link nodes to net node for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, net_node.id, interface_one=interface) # instantiate session session.instantiate() # ping n2 from n1 and assert success status = ping(node_one, node_two, ip_prefixes) assert not status
def test_vnode_client(self, request, session: Session, ip_prefixes: IpPrefixes): """ Test vnode client methods. :param request: pytest request :param session: session for test :param ip_prefixes: generates ip addresses for nodes """ # create ptp ptp_node = session.add_node(PtpNet) # create nodes node_one = session.add_node(CoreNode) node_two = session.add_node(CoreNode) # link nodes to ptp net for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, ptp_node.id, interface_one=interface) # get node client for testing client = node_one.client # instantiate session session.instantiate() # check we are connected assert client.connected() # validate command if not request.config.getoption("mock"): assert client.check_cmd("echo hello") == "hello"
def test_wlan_ping(self, session: Session, ip_prefixes: IpPrefixes): """ Test basic wlan network. :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ # create wlan wlan_node = session.add_node(WlanNode) session.mobility.set_model(wlan_node, BasicRangeModel) # create nodes options = NodeOptions(model="mdr") options.set_position(0, 0) node_one = session.add_node(CoreNode, options=options) node_two = session.add_node(CoreNode, options=options) # link nodes for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, wlan_node.id, interface_one=interface) # instantiate session session.instantiate() # ping n2 from n1 and assert success status = ping(node_one, node_two, ip_prefixes) assert not status
def test_xml_ptp( self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes ): """ Test xml client methods for a ptp network. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create ptp ptp_node = session.add_node(PtpNet) # create nodes node1 = session.add_node(CoreNode) node2 = session.add_node(CoreNode) # link nodes to ptp net for node in [node1, node2]: iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, ptp_node.id, iface1_data=iface_data) # instantiate session session.instantiate() # get ids for nodes node1_id = node1.id node2_id = node2.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, CoreNode)
def test_network_to_network(self, session: Session, tmpdir: TemporaryFile): """ Test xml generation when dealing with network to network nodes. :param session: session for test :param tmpdir: tmpdir to create data in """ # create nodes switch_one = session.add_node(SwitchNode) switch_two = session.add_node(SwitchNode) # link nodes session.add_link(switch_one.id, switch_two.id) # instantiate session session.instantiate() # get ids for nodes n1_id = switch_one.id n2_id = switch_two.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(n1_id, SwitchNode) with pytest.raises(CoreError): assert not session.get_node(n2_id, SwitchNode) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated switch_one = session.get_node(n1_id, SwitchNode) switch_two = session.get_node(n2_id, SwitchNode) assert switch_one assert switch_two assert len(switch_one.all_link_data() + switch_two.all_link_data()) == 1
def test_mobility(self, session: Session, ip_prefixes: IpPrefixes): """ Test basic wlan network. :param core.emulator.coreemu.EmuSession session: session for test :param ip_prefixes: generates ip addresses for nodes """ # create wlan wlan_node = session.add_node(WlanNode) session.mobility.set_model(wlan_node, BasicRangeModel) # create nodes options = NodeOptions(model="mdr") options.set_position(0, 0) node_one = session.add_node(CoreNode, options=options) node_two = session.add_node(CoreNode, options=options) # link nodes for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, wlan_node.id, interface_one=interface) # configure mobility script for session config = { "file": _MOBILITY_FILE, "refresh_ms": "50", "loop": "1", "autostart": "0.0", "map": "", "script_start": "", "script_pause": "", "script_stop": "", } session.mobility.set_model(wlan_node, Ns2ScriptedMobility, config) # add handler for receiving node updates event = threading.Event() def node_update(_): event.set() session.node_handlers.append(node_update) # instantiate session session.instantiate() # validate we receive a node message for updating its location assert event.wait(5)
def create_ptp_network(session: Session, ip_prefixes: IpPrefixes) -> Tuple[CoreNode, CoreNode]: # create nodes node1 = session.add_node(CoreNode) node2 = session.add_node(CoreNode) # link nodes to net node iface1_data = ip_prefixes.create_iface(node1) iface2_data = ip_prefixes.create_iface(node2) session.add_link(node1.id, node2.id, iface1_data, iface2_data) # instantiate session session.instantiate() return node1, node2
def test_remote_node(self, session: Session): # given server_name = "core2" host = "127.0.0.1" # when session.distributed.add_server(server_name, host) options = NodeOptions(server=server_name) node = session.add_node(CoreNode, options=options) session.instantiate() # then assert node.server is not None assert node.server.name == server_name assert node.server.host == host
def create_ptp_network( session: Session, ip_prefixes: IpPrefixes ) -> Tuple[CoreNode, CoreNode]: # create nodes node_one = session.add_node(CoreNode) node_two = session.add_node(CoreNode) # link nodes to net node interface_one = ip_prefixes.create_interface(node_one) interface_two = ip_prefixes.create_interface(node_two) session.add_link(node_one.id, node_two.id, interface_one, interface_two) # instantiate session session.instantiate() return node_one, node_two
def test_models(self, session: Session, model: Type[EmaneModel], ip_prefixes: IpPrefixes): """ Test emane models within a basic network. :param core.emulator.coreemu.EmuSession session: session for test :param model: emane model to test :param ip_prefixes: generates ip addresses for nodes """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) emane_network = session.add_node(EmaneNet, options=options) session.emane.set_model(emane_network, model) # configure tdma if model == EmaneTdmaModel: session.emane.set_model_config( emane_network.id, EmaneTdmaModel.name, { "schedule": os.path.join(_DIR, "../../examples/tdma/schedule.xml") }, ) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, emane_network.id, iface1_data=iface_data) # instantiate session session.instantiate() # ping node2 from node1 and assert success status = ping(node1, node2, ip_prefixes, count=5) assert not status
def test_netif(self, session: Session, ip_prefixes: IpPrefixes): """ Test netif methods. :param session: session for test :param ip_prefixes: generates ip addresses for nodes """ # create ptp ptp_node = session.add_node(PtpNet) # create nodes node_one = session.add_node(CoreNode) node_two = session.add_node(CoreNode) # link nodes to ptp net for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, ptp_node.id, interface_one=interface) # instantiate session session.instantiate() # check link data gets generated assert ptp_node.all_link_data(MessageFlags.ADD) # check common nets exist between linked nodes assert node_one.commonnets(node_two) assert node_two.commonnets(node_one) # check we can retrieve netif index assert node_one.ifname(0) assert node_two.ifname(0) # check interface parameters interface = node_one.netif(0) interface.setparam("test", 1) assert interface.getparam("test") == 1 assert interface.getparams() # delete netif and test that if no longer exists node_one.delnetif(0) assert not node_one.netif(0)
def test_iface(self, session: Session, ip_prefixes: IpPrefixes): """ Test interface methods. :param session: session for test :param ip_prefixes: generates ip addresses for nodes """ # create ptp ptp_node = session.add_node(PtpNet) # create nodes node1 = session.add_node(CoreNode) node2 = session.add_node(CoreNode) # link nodes to ptp net for node in [node1, node2]: iface = ip_prefixes.create_iface(node) session.add_link(node.id, ptp_node.id, iface1_data=iface) # instantiate session session.instantiate() # check link data gets generated assert ptp_node.links(MessageFlags.ADD) # check common nets exist between linked nodes assert node1.commonnets(node2) assert node2.commonnets(node1) # check we can retrieve interface id assert 0 in node1.ifaces assert 0 in node2.ifaces # check interface parameters iface = node1.get_iface(0) iface.setparam("test", 1) assert iface.getparam("test") == 1 assert iface.getparams() # delete interface and test that if no longer exists node1.delete_iface(0) assert 0 not in node1.ifaces
def test_two_emane_interfaces(self, session: Session): """ Test nodes running multiple emane interfaces. :param core.emulator.coreemu.EmuSession session: session for test """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) options.emane = EmaneIeee80211abgModel.name emane_net1 = session.add_node(EmaneNet, options=options) options.emane = EmaneRfPipeModel.name emane_net2 = session.add_node(EmaneNet, options=options) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) # create interfaces ip_prefix1 = IpPrefixes("10.0.0.0/24") ip_prefix2 = IpPrefixes("10.0.1.0/24") for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefix1.create_iface(node) session.add_link(node.id, emane_net1.id, iface1_data=iface_data) iface_data = ip_prefix2.create_iface(node) session.add_link(node.id, emane_net2.id, iface1_data=iface_data) # instantiate session session.instantiate() # ping node2 from node1 on both interfaces and check success status = ping(node1, node2, ip_prefix1, count=5) assert not status status = ping(node1, node2, ip_prefix2, count=5) assert not status
class Experiment(object): """ Experiment object to organize tests. """ def __init__(self, opt, start): """ Initialize with opt and start time. """ self.session = None # node list self.nodes = [] # WLAN network self.net = None self.verbose = opt.verbose # dict from OptionParser self.opt = opt self.start = start self.numping = opt.numping self.numiperf = opt.numiperf self.nummgen = opt.nummgen self.logbegin() def info(self, msg): """ Utility method for writing output to stdout. """ print(msg) sys.stdout.flush() self.log(msg) def warn(self, msg): """ Utility method for writing output to stderr. """ sys.stderr.write(msg) sys.stderr.flush() self.log(msg) def logbegin(self): """ Start logging. """ self.logfp = None if not self.opt.logfile: return self.logfp = open(self.opt.logfile, "w") self.log("%s begin: %s\n" % (sys.argv[0], self.start.ctime())) self.log("%s args: %s\n" % (sys.argv[0], sys.argv[1:])) (sysname, rel, ver, machine, nodename) = os.uname() self.log("%s %s %s %s on %s" % (sysname, rel, ver, machine, nodename)) def logend(self): """ End logging. """ if not self.logfp: return end = datetime.datetime.now() self.log("%s end: %s (%s)\n" % \ (sys.argv[0], end.ctime(), end - self.start)) self.logfp.flush() self.logfp.close() self.logfp = None def log(self, msg): """ Write to the log file, if any. """ if not self.logfp: return self.logfp.write(msg) def reset(self): """ Prepare for another experiment run. """ if self.session: self.session.shutdown() del self.session self.session = None self.nodes = [] self.net = None def createbridgedsession(self, numnodes, verbose=False): """ Build a topology consisting of the given number of LxcNodes connected to a WLAN. """ # IP subnet prefix = ipaddress.Ipv4Prefix("10.0.0.0/16") self.session = Session(1) # emulated network self.net = self.session.create_node(cls=core.nodes.network.WlanNode, name="wlan1") prev = None for i in range(1, numnodes + 1): addr = "%s/%s" % (prefix.addr(i), 32) tmp = self.session.create_node(cls=core.nodes.base.CoreNode, _id=i, name="n%d" % i) tmp.newnetif(self.net, [addr]) self.nodes.append(tmp) self.session.services.add_services(tmp, "router", "IPForward") self.session.services.boot_services(tmp) self.staticroutes(i, prefix, numnodes) # link each node in a chain, with the previous node if prev: self.net.link(prev.netif(0), tmp.netif(0)) prev = tmp def createemanesession(self, numnodes, verbose=False, cls=None, values=None): """ Build a topology consisting of the given number of LxcNodes connected to an EMANE WLAN. """ prefix = ipaddress.Ipv4Prefix("10.0.0.0/16") self.session = Session(2) self.session.node_count = str(numnodes + 1) self.session.master = True self.session.location.setrefgeo(47.57917, -122.13232, 2.00000) self.session.location.refscale = 150.0 self.session.emane.loadmodels() self.net = self.session.create_node(cls=EmaneNode, _id=numnodes + 1, name="wlan1") self.net.verbose = verbose # self.session.emane.addobj(self.net) for i in range(1, numnodes + 1): addr = "%s/%s" % (prefix.addr(i), 32) tmp = self.session.create_node(cls=core.nodes.base.CoreNode, _id=i, name="n%d" % i) # tmp.setposition(i * 20, 50, None) tmp.setposition(50, 50, None) tmp.newnetif(self.net, [addr]) self.nodes.append(tmp) self.session.services.add_services(tmp, "router", "IPForward") if values is None: values = cls.getdefaultvalues() self.session.emane.setconfig(self.net.id, cls.name, values) self.session.instantiate() self.info("waiting %s sec (TAP bring-up)" % 2) time.sleep(2) for i in range(1, numnodes + 1): tmp = self.nodes[i - 1] self.session.services.boot_services(tmp) self.staticroutes(i, prefix, numnodes) def setnodes(self): """ Set the sender and receiver nodes for use in this experiment, along with the address of the receiver to be used. """ self.firstnode = self.nodes[0] self.lastnode = self.nodes[-1] self.lastaddr = self.lastnode.netif(0).addrlist[0].split("/")[0] def staticroutes(self, i, prefix, numnodes): """ Add static routes on node number i to the other nodes in the chain. """ routecmd = ["/sbin/ip", "route", "add"] node = self.nodes[i - 1] neigh_left = "" neigh_right = "" # add direct interface routes first if i > 1: neigh_left = "%s" % prefix.addr(i - 1) cmd = routecmd + [neigh_left, "dev", node.netif(0).name] (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) if i < numnodes: neigh_right = "%s" % prefix.addr(i + 1) cmd = routecmd + [neigh_right, "dev", node.netif(0).name] (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add interface route: %s" % cmd) # add static routes to all other nodes via left/right neighbors for j in range(1, numnodes + 1): if abs(j - i) < 2: continue addr = "%s" % prefix.addr(j) if j < i: gw = neigh_left else: gw = neigh_right cmd = routecmd + [addr, "via", gw] (status, result) = node.cmd_output(cmd) if status != 0: self.warn("failed to add route: %s" % cmd) def setpathloss(self, numnodes): """ Send EMANE pathloss events to connect all NEMs in a chain. """ if self.session.emane.version < self.session.emane.EMANE091: service = emaneeventservice.EventService() e = emaneeventpathloss.EventPathloss(1) old = True else: if self.session.emane.version == self.session.emane.EMANE091: dev = "lo" else: dev = self.session.obj("ctrlnet").brname service = EventService(eventchannel=("224.1.2.8", 45703, dev), otachannel=None) old = False for i in range(1, numnodes + 1): rxnem = i # inform rxnem that it can hear node to the left with 10dB noise txnem = rxnem - 1 if txnem > 0: if old: e.set(0, txnem, 10.0, 10.0) service.publish(emaneeventpathloss.EVENT_ID, emaneeventservice.PLATFORMID_ANY, rxnem, emaneeventservice.COMPONENTID_ANY, e.export()) else: e = PathlossEvent() e.append(txnem, forward=10.0, reverse=10.0) service.publish(rxnem, e) # inform rxnem that it can hear node to the right with 10dB noise txnem = rxnem + 1 if txnem > numnodes: continue if old: e.set(0, txnem, 10.0, 10.0) service.publish(emaneeventpathloss.EVENT_ID, emaneeventservice.PLATFORMID_ANY, rxnem, emaneeventservice.COMPONENTID_ANY, e.export()) else: e = PathlossEvent() e.append(txnem, forward=10.0, reverse=10.0) service.publish(rxnem, e) def setneteffects(self, bw=None, delay=None): """ Set link effects for all interfaces attached to the network node. """ if not self.net: self.warn("failed to set effects: no network node") return for netif in self.net.netifs(): self.net.linkconfig(netif, bw=bw, delay=delay) def runalltests(self, title=""): """ Convenience helper to run all defined experiment tests. If tests are run multiple times, this returns the average of those runs. """ duration = self.opt.duration rate = self.opt.rate if len(title) > 0: self.info("----- running %s tests (duration=%s, rate=%s) -----" % \ (title, duration, rate)) (latency, mdev, throughput, cpu, loss) = (0, 0, 0, 0, 0) self.info("number of runs: ping=%d, iperf=%d, mgen=%d" % \ (self.numping, self.numiperf, self.nummgen)) if self.numping > 0: (latency, mdev) = self.pingtest(count=self.numping) if self.numiperf > 0: throughputs = [] for i in range(1, self.numiperf + 1): throughput = self.iperftest(time=duration) if self.numiperf > 1: throughputs += throughput # iperf is very CPU intensive time.sleep(1) if self.numiperf > 1: throughput = sum(throughputs) / len(throughputs) self.info("throughputs=%s" % ["%.2f" % v for v in throughputs]) if self.nummgen > 0: cpus = [] losses = [] for i in range(1, self.nummgen + 1): (cpu, loss) = self.cputest(time=duration, rate=rate) if self.nummgen > 1: cpus += cpu, losses += loss, if self.nummgen > 1: cpu = sum(cpus) / len(cpus) loss = sum(losses) / len(losses) self.info("cpus=%s" % ["%.2f" % v for v in cpus]) self.info("losses=%s" % ["%.2f" % v for v in losses]) return latency, mdev, throughput, cpu, loss def pingtest(self, count=50): """ Ping through a chain of nodes and report the average latency. """ p = PingCmd(node=self.firstnode, verbose=self.verbose, addr=self.lastaddr, count=count, interval=0.1).run() (latency, mdev) = p self.info("latency (ms): %.03f, %.03f" % (latency, mdev)) return p def iperftest(self, time=10): """ Run iperf through a chain of nodes and report the maximum throughput. """ bps = IperfCmd(node=self.lastnode, client_node=self.firstnode, verbose=False, addr=self.lastaddr, time=time).run() self.info("throughput (bps): %s" % bps) return bps def cputest(self, time=10, rate=512): """ Run MGEN through a chain of nodes and report the CPU usage and percent of lost packets. Rate is in kbps. """ if self.verbose: self.info("%s initial test ping (max 1 second)..." % \ self.firstnode.name) (status, result) = self.firstnode.cmd_output( ["ping", "-q", "-c", "1", "-w", "1", self.lastaddr]) if status != 0: self.warn("initial ping from %s to %s failed! result:\n%s" % \ (self.firstnode.name, self.lastaddr, result)) return 0.0, 0.0 lines = readstat() cpustart = getcputimes(lines[0]) loss = MgenCmd(node=self.lastnode, client_node=self.firstnode, verbose=False, addr=self.lastaddr, time=time, rate=rate).run() lines = readstat() cpuend = getcputimes(lines[0]) percent = calculatecpu(cpustart, cpuend) self.info("CPU usage (%%): %.02f, %.02f loss" % (percent, loss)) return percent, loss
def test_xml_emane( self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes ): """ Test xml client methods for emane. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create emane node for networking the core nodes session.set_location(47.57917, -122.13232, 2.00000, 1.0) options = NodeOptions() options.set_position(80, 50) emane_network = session.add_node(EmaneNet, options=options) config_key = "txpower" config_value = "10" session.emane.set_model( emane_network, EmaneIeee80211abgModel, {config_key: config_value} ) # create nodes options = NodeOptions(model="mdr") options.set_position(150, 150) node1 = session.add_node(CoreNode, options=options) options.set_position(300, 150) node2 = session.add_node(CoreNode, options=options) for i, node in enumerate([node1, node2]): node.setposition(x=150 * (i + 1), y=150) iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, emane_network.id, iface1_data=iface_data) # instantiate session session.instantiate() # get ids for nodes emane_id = emane_network.id node1_id = node1.id node2_id = node2.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # retrieve configuration we set originally value = str( session.emane.get_config(config_key, emane_id, EmaneIeee80211abgModel.name) ) # verify nodes and configuration were restored assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, CoreNode) assert session.get_node(emane_id, EmaneNet) assert value == config_value
def test_link_options_bidirectional(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): """ Test xml client methods for a ptp network. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create nodes node1 = session.add_node(CoreNode) iface1_data = ip_prefixes.create_iface(node1) node2 = session.add_node(CoreNode) iface2_data = ip_prefixes.create_iface(node2) # create link options1 = LinkOptions() options1.unidirectional = 1 options1.bandwidth = 5000 options1.delay = 10 options1.loss = 10.5 options1.dup = 5 options1.jitter = 5 options1.buffer = 50 session.add_link(node1.id, node2.id, iface1_data, iface2_data, options1) options2 = LinkOptions() options2.unidirectional = 1 options2.bandwidth = 10000 options2.delay = 20 options2.loss = 10 options2.dup = 10 options2.jitter = 10 options2.buffer = 100 session.update_link(node2.id, node1.id, iface2_data.id, iface1_data.id, options2) # instantiate session session.instantiate() # get ids for nodes node1_id = node1.id node2_id = node2.id # save xml xml_file = tmpdir.join("session.xml") file_path = Path(xml_file.strpath) session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, CoreNode) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.links() assert len(links) == 2 link1 = links[0] link2 = links[1] assert options1.bandwidth == link1.options.bandwidth assert options1.delay == link1.options.delay assert options1.loss == link1.options.loss assert options1.dup == link1.options.dup assert options1.jitter == link1.options.jitter assert options1.buffer == link1.options.buffer assert options2.bandwidth == link2.options.bandwidth assert options2.delay == link2.options.delay assert options2.loss == link2.options.loss assert options2.dup == link2.options.dup assert options2.jitter == link2.options.jitter assert options2.buffer == link2.options.buffer
def test_xml_mobility(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): """ Test xml client methods for mobility. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create wlan wlan_node = session.add_node(WlanNode) session.mobility.set_model(wlan_node, BasicRangeModel, {"test": "1"}) # create nodes options = NodeOptions(model="mdr") options.set_position(0, 0) node1 = session.add_node(CoreNode, options=options) node2 = session.add_node(CoreNode, options=options) # link nodes for node in [node1, node2]: iface_data = ip_prefixes.create_iface(node) session.add_link(node.id, wlan_node.id, iface1_data=iface_data) # instantiate session session.instantiate() # get ids for nodes wlan_id = wlan_node.id node1_id = node1.id node2_id = node2.id # save xml xml_file = tmpdir.join("session.xml") file_path = Path(xml_file.strpath) session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # retrieve configuration we set originally value = str( session.mobility.get_config("test", wlan_id, BasicRangeModel.name)) # verify nodes and configuration were restored assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, CoreNode) assert session.get_node(wlan_id, WlanNode) assert value == "1"
def test_xml_ptp_services(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): """ Test xml client methods for a ptp neetwork. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create ptp ptp_node = session.add_node(PtpNet) # create nodes options = NodeOptions(model="host") node_one = session.add_node(CoreNode, options=options) node_two = session.add_node(CoreNode) # link nodes to ptp net for node in [node_one, node_two]: interface = ip_prefixes.create_interface(node) session.add_link(node.id, ptp_node.id, interface_one=interface) # set custom values for node service session.services.set_service(node_one.id, SshService.name) service_file = SshService.configs[0] file_data = "# test" session.services.set_service_file(node_one.id, SshService.name, service_file, file_data) # instantiate session session.instantiate() # get ids for nodes n1_id = node_one.id n2_id = node_two.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(n1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(n2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # retrieve custom service service = session.services.get_service(node_one.id, SshService.name) # verify nodes have been recreated assert session.get_node(n1_id, CoreNode) assert session.get_node(n2_id, CoreNode) assert service.config_data.get(service_file) == file_data
def main(): usagestr = "usage: %prog [-h] [options] [args]" parser = optparse.OptionParser(usage=usagestr) parser.set_defaults(numnodes=5, slave=None) parser.add_option("-n", "--numnodes", dest="numnodes", type=int, help="number of nodes") parser.add_option("-s", "--slave-server", dest="slave", type=str, help="slave server IP address") def usage(msg=None, err=0): sys.stdout.write("\n") if msg: sys.stdout.write(msg + "\n\n") parser.print_help() sys.exit(err) # parse command line options (options, args) = parser.parse_args() if options.numnodes < 1: usage("invalid number of nodes: %s" % options.numnodes) if not options.slave: usage("slave server IP address (-s) is a required argument") for a in args: sys.stderr.write("ignoring command line argument: '%s'\n" % a) start = datetime.datetime.now() prefix = ipaddress.Ipv4Prefix("10.83.0.0/16") session = Session(1) server = globals().get("server") if server is not None: server.addsession(session) # distributed setup - connect to slave server slaveport = options.slave.split(":") slave = slaveport[0] if len(slaveport) > 1: port = int(slaveport[1]) else: port = CORE_API_PORT print("connecting to slave at %s:%d" % (slave, port)) session.broker.addserver(slave, slave, port) session.broker.setupserver(slave) session.set_state(EventTypes.CONFIGURATION_STATE) tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.CONFIGURATION_STATE.value) session.broker.handlerawmsg(coreapi.CoreEventMessage.pack(0, tlvdata)) switch = session.create_node(cls=core.nodes.network.SwitchNode, name="switch") switch.setposition(x=80, y=50) num_local = options.numnodes / 2 num_remote = options.numnodes / 2 + options.numnodes % 2 print("creating %d (%d local / %d remote) nodes with addresses from %s" % (options.numnodes, num_local, num_remote, prefix)) for i in range(1, num_local + 1): node = session.create_node(cls=core.nodes.base.CoreNode, name="n%d" % i, _id=i) node.newnetif(switch, ["%s/%s" % (prefix.addr(i), prefix.prefixlen)]) node.cmd( [constants.SYSCTL_BIN, "net.ipv4.icmp_echo_ignore_broadcasts=0"]) node.setposition(x=150 * i, y=150) n.append(node) flags = MessageFlags.ADD.value session.broker.handlerawmsg(switch.tonodemsg(flags=flags)) # create remote nodes via API for i in range(num_local + 1, options.numnodes + 1): node = core.nodes.base.CoreNode(session=session, _id=i, name="n%d" % i, start=False) node.setposition(x=150 * i, y=150) node.server = slave n.append(node) node_data = node.data(flags) node_message = dataconversion.convert_node(node_data) session.broker.handlerawmsg(node_message) # create remote links via API for i in range(num_local + 1, options.numnodes + 1): tlvdata = coreapi.CoreLinkTlv.pack(LinkTlvs.N1_NUMBER.value, switch.id) tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.N2_NUMBER.value, i) tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.TYPE.value, LinkTypes.WIRED.value) tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_NUMBER.value, 0) tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_IP4.value, prefix.addr(i)) tlvdata += coreapi.CoreLinkTlv.pack(LinkTlvs.INTERFACE2_IP4_MASK.value, prefix.prefixlen) msg = coreapi.CoreLinkMessage.pack(flags, tlvdata) session.broker.handlerawmsg(msg) session.instantiate() tlvdata = coreapi.CoreEventTlv.pack(EventTlvs.TYPE.value, EventTypes.INSTANTIATION_STATE.value) msg = coreapi.CoreEventMessage.pack(0, tlvdata) session.broker.handlerawmsg(msg) # start a shell on node 1 n[1].client.term("bash") print("elapsed time: %s" % (datetime.datetime.now() - start)) print("To stop this session, use the 'core-cleanup' script on this server") print("and on the remote slave server.")
def test_link_options_bidirectional(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): """ Test xml client methods for a ptp network. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create nodes node_one = session.add_node(CoreNode) interface_one = ip_prefixes.create_interface(node_one) node_two = session.add_node(CoreNode) interface_two = ip_prefixes.create_interface(node_two) # create link link_options_one = LinkOptions() link_options_one.unidirectional = 1 link_options_one.bandwidth = 5000 link_options_one.delay = 10 link_options_one.per = 10.5 link_options_one.dup = 5 link_options_one.jitter = 5 session.add_link(node_one.id, node_two.id, interface_one, interface_two, link_options_one) link_options_two = LinkOptions() link_options_two.unidirectional = 1 link_options_two.bandwidth = 10000 link_options_two.delay = 20 link_options_two.per = 10 link_options_two.dup = 10 link_options_two.jitter = 10 session.update_link( node_two.id, node_one.id, interface_two.id, interface_one.id, link_options_two, ) # instantiate session session.instantiate() # get ids for nodes n1_id = node_one.id n2_id = node_two.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(n1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(n2_id, CoreNode) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(n1_id, CoreNode) assert session.get_node(n2_id, CoreNode) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.all_link_data() assert len(links) == 2 link_one = links[0] link_two = links[1] assert link_options_one.bandwidth == link_one.bandwidth assert link_options_one.delay == link_one.delay assert link_options_one.per == link_one.per assert link_options_one.dup == link_one.dup assert link_options_one.jitter == link_one.jitter assert link_options_two.bandwidth == link_two.bandwidth assert link_options_two.delay == link_two.delay assert link_options_two.per == link_two.per assert link_options_two.dup == link_two.dup assert link_options_two.jitter == link_two.jitter
def test_link_options(self, session: Session, tmpdir: TemporaryFile, ip_prefixes: IpPrefixes): """ Test xml client methods for a ptp network. :param session: session for test :param tmpdir: tmpdir to create data in :param ip_prefixes: generates ip addresses for nodes """ # create nodes node1 = session.add_node(CoreNode) iface1_data = ip_prefixes.create_iface(node1) switch = session.add_node(SwitchNode) # create link options = LinkOptions() options.loss = 10.5 options.bandwidth = 50000 options.jitter = 10 options.delay = 30 options.dup = 5 session.add_link(node1.id, switch.id, iface1_data, options=options) # instantiate session session.instantiate() # get ids for nodes node1_id = node1.id node2_id = switch.id # save xml xml_file = tmpdir.join("session.xml") file_path = xml_file.strpath session.save_xml(file_path) # verify xml file was created and can be parsed assert xml_file.isfile() assert ElementTree.parse(file_path) # stop current session, clearing data session.shutdown() # verify nodes have been removed from session with pytest.raises(CoreError): assert not session.get_node(node1_id, CoreNode) with pytest.raises(CoreError): assert not session.get_node(node2_id, SwitchNode) # load saved xml session.open_xml(file_path, start=True) # verify nodes have been recreated assert session.get_node(node1_id, CoreNode) assert session.get_node(node2_id, SwitchNode) links = [] for node_id in session.nodes: node = session.nodes[node_id] links += node.links() link = links[0] assert options.loss == link.options.loss assert options.bandwidth == link.options.bandwidth assert options.jitter == link.options.jitter assert options.delay == link.options.delay assert options.dup == link.options.dup