From 4ffa02a6eeaf8c5daacb10d8f52fc15782af84ab Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Mon, 16 Feb 2015 04:03:03 +0100 Subject: [PATCH] Cleaning up ns-3 multi-host examples --- examples/ns3/multi_host/case_a.py | 93 ----- examples/ns3/multi_host/case_b.py | 79 ---- examples/ns3/multi_host/case_c.py | 70 ---- examples/ns3/multi_host/code/agent.c | 9 +- examples/ns3/multi_host/code/transmitter.c | 6 +- examples/ns3/multi_host/distributed.py | 82 ++++ examples/ns3/multi_host/experiment.py | 379 ------------------ .../multi_host/experiment_interconnected.py | 47 --- ...experiment_interconnected_ns3_planetlab.py | 96 ----- .../experiment_interconnected_ns3ns3.py | 65 --- examples/ns3/multi_host/hybrid.py | 99 +++++ examples/ns3/multi_host/parallel.py | 85 ++++ examples/ns3/multi_host/topology.py | 286 +++++++++++++ src/nepi/resources/linux/ns3/ns3simulation.py | 21 + 14 files changed, 577 insertions(+), 840 deletions(-) delete mode 100644 examples/ns3/multi_host/case_a.py delete mode 100644 examples/ns3/multi_host/case_b.py delete mode 100644 examples/ns3/multi_host/case_c.py create mode 100644 examples/ns3/multi_host/distributed.py delete mode 100644 examples/ns3/multi_host/experiment.py delete mode 100644 examples/ns3/multi_host/experiment_interconnected.py delete mode 100644 examples/ns3/multi_host/experiment_interconnected_ns3_planetlab.py delete mode 100644 examples/ns3/multi_host/experiment_interconnected_ns3ns3.py create mode 100644 examples/ns3/multi_host/hybrid.py create mode 100644 examples/ns3/multi_host/parallel.py create mode 100644 examples/ns3/multi_host/topology.py diff --git a/examples/ns3/multi_host/case_a.py b/examples/ns3/multi_host/case_a.py deleted file mode 100644 index 9c342267..00000000 --- a/examples/ns3/multi_host/case_a.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -import os -from experiment imptort Experiment -from nepi.execution.ec import ExperimentController -from nepi.execution.resource import ResourceState, ResourceManager - -# Experiment parameters -experiment_id = "case_a" -agent = "10.0.1.1" -netblock = "10.0.1.0" -prefix = "24" -# number of nodes to test -parameters = [3] - -# list of hosts for running the experiment on -node_info = [ - {"hostname":"onelab4.warsaw.rd.tp.pl", - "username":"inria_nepi", - "identity": "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])}] - -# tunning -os.environ["NEPI_NTHREADS"] = "1" -ResourceManager._reschedule_delay = "0s" - -# == Experimentation setup ==================================================== -def main(): - # Prepare the ExperimentController - ec = ExperimentController(exp_id = experiment_id) - - # run experimentation as long as there is something to do - while len(parameters) > 0: - # Collection of application being processed - jobs = list() - - # Collection of experiments launched - xps = list() - - # Push a job on each node in the cluster - for node in node_info: - # Stop if nothing else to do - if len(parameters) == 0: - break - - # Determine what network size to test - nb_nodes = parameters.pop(0) - - # Create the simulated network - xp = Experiment(ec, node, nb_nodes, False) - xp.build_topology(netblock, prefix, agent) - - # Remember the experiments just created - xps.append(xp) - - # Remember the applications to be executed - jobs += xp.apps - - # Let's run the experiment - ec.deploy() - ec.wait_finished(jobs) - - # Check if everything went well for each experiment - for xp in xps: - # and see the output - stdout = ec.trace(xp.apps[0], "stdout") - print "[", stdout, "]" - # check if one transmitter failed (if everything goes well, all trasmitters - # must have stopped properly) (ignore the agent) - for app in xp.apps[1:len(xp.apps)]: - if ec.state(app, hr=False) != ResourceState.STOPPED: - raise Exception("Crashed at size %d" % xp.nb_nodes) - # et voila - ec.shutdown() - -main() diff --git a/examples/ns3/multi_host/case_b.py b/examples/ns3/multi_host/case_b.py deleted file mode 100644 index b44c8992..00000000 --- a/examples/ns3/multi_host/case_b.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -import os -from experiment_interconnected_ns3_ns3 import ExperimentInterconnectedNs3Ns3 -from nepi.execution.ec import ExperimentController -from nepi.execution.resource import ResourceManager - -# Experiment parameters -experiment_id = "case_b" -agent = ["10.0.2.1", "10.0.1.1"] -netblock = ["10.0.1.0", "10.0.2.0"] -prefix = ["24", "24"] -nb_nodes = [1, 1] -# list of hosts for running the experiment on -node_info = [ - {"hostname":"onelab4.warsaw.rd.tp.pl", - "username":"inria_nepi", - "identity": "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])}, - {"hostname":"planet2.servers.ua.pt", - "username":"inria_nepi", - "identity": "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])} - ] - -# tunning -os.environ["NEPI_NTHREADS"] = "1" -ResourceManager._reschedule_delay = "0s" - -# == Experimentation setup ==================================================== -def main(): - # Prepare the ExperimentController - ec = ExperimentController(exp_id = experiment_id) - - # Create the simulated network - # - # On the first machine - xp1 = ExperimentInterconnectedNs3Ns3(ec, node_info[0], nb_nodes[0]) - xp1.build_topology(netblock = netblock[0], prefix = prefix[0], target = agent[0]) - # - # On the second machine - xp2 = ExperimentInterconnectedNs3Ns3(ec, node_info[1], nb_nodes[1]) - xp2.build_topology(netblock = netblock[1], prefix = prefix[1], target = agent[1]) - - # interconnect the two experiments - xp1.interconnect(xp2) - - # Let's run the experiment - ec.deploy() - ec.wait_finished( xp1.apps[1:len(xp1.apps)] + xp2.apps[1:len(xp2.apps)] ) - - - # and see the output - stdout = ec.trace(xp1.apps[0], "stdout") - print "1[", stdout, "]" - - stdout = ec.trace(xp2.apps[0], "stdout") - print "2[", stdout, "]" - - # et voila - ec.shutdown() - -main() diff --git a/examples/ns3/multi_host/case_c.py b/examples/ns3/multi_host/case_c.py deleted file mode 100644 index bd36cf77..00000000 --- a/examples/ns3/multi_host/case_c.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -import os -from experiment_interconnected_ns3_planetlab import ExperimentInterconnectedNs3Planetlab -from nepi.execution.ec import ExperimentController -from nepi.execution.resource import ResourceManager - -# Experiment parameters -experiment_id = "case_c" -agent = None -netblock = "192.168.3.0" -prefix = "25" -nb_nodes = 1 - -node_info = { - "hostname":"onelab4.warsaw.rd.tp.pl", - "username":"inria_nepi", - "identity": "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME']) - } - - -# tunning -os.environ["NEPI_NTHREADS"] = "1" -ResourceManager._reschedule_delay = "0s" - -# == Experimentation setup ==================================================== -def main(): - # Prepare the ExperimentController - ec = ExperimentController(exp_id = experiment_id) - - # Create the simulated network - xp = ExperimentInterconnectedNs3Planetlab(ec, node_info, nb_nodes) - xp.build_topology(netblock = netblock, prefix = prefix, target = agent) - - # Create Planetlab application - app = xp.add_planetlab_client(xp.ip_ap) - - # Interconnect Planetlab and ns3 - xp.interconnect("192.168.3.128", "25") - - # Let's run the experiment - ec.deploy() - ec.wait_finished([app]) - - # and see the output - stdout = ec.trace(xp.apps[0], "stdout") - print "[", stdout, "]" - - # et voila - ec.shutdown() - -main() diff --git a/examples/ns3/multi_host/code/agent.c b/examples/ns3/multi_host/code/agent.c index 460401c2..2a82fe7f 100644 --- a/examples/ns3/multi_host/code/agent.c +++ b/examples/ns3/multi_host/code/agent.c @@ -13,12 +13,6 @@ int main(int argc, char**argv) socklen_t len; char mesg[1000]; - printf("DEBUT\n"); - if (argc != 2) - { - fprintf(stderr, "usage: %s \n", argv[0]); - exit(1); - } sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd < 0){ @@ -29,7 +23,7 @@ int main(int argc, char**argv) bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); - servaddr.sin_port = htons(atoi(argv[1])); + servaddr.sin_port = htons(45005); if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0){ perror("bind"); exit(2); @@ -49,5 +43,4 @@ int main(int argc, char**argv) mesg[n] = 0; printf("[%s]\n",mesg); } - printf("FIN\n"); } diff --git a/examples/ns3/multi_host/code/transmitter.c b/examples/ns3/multi_host/code/transmitter.c index 52bb3b2d..10fe57e8 100644 --- a/examples/ns3/multi_host/code/transmitter.c +++ b/examples/ns3/multi_host/code/transmitter.c @@ -16,9 +16,9 @@ int main(int argc, char**argv) struct sockaddr_in servaddr,cliaddr; char * sendline = "coucou"; - if (argc != 3) + if (argc != 2) { - fprintf(stderr, "usage: %s \n", argv[0]); + fprintf(stderr, "usage: %s \n", argv[0]); exit(1); } @@ -31,7 +31,7 @@ int main(int argc, char**argv) bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr=inet_addr(argv[1]); - servaddr.sin_port=htons(atoi(argv[2])); + servaddr.sin_port=htons(45005); int i; for(i = 0; i < 10; i++){ diff --git a/examples/ns3/multi_host/distributed.py b/examples/ns3/multi_host/distributed.py new file mode 100644 index 00000000..c1a5a8b0 --- /dev/null +++ b/examples/ns3/multi_host/distributed.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2015 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Damien Saucez +# Alina Quereilhac +# + +# +# Note: To run this experiment you need to have a PlanetLab account. +# +# This experiment consists of a simulated wireless sensor network (ns-3) +# with one fixed access point (AP), running an agent application, and several +# mobile stations that run a transmitter application to send messages to +# the AP. +# +# The experiment uses 2 networks like the one described above, running in 2 +# independent ns-3 instances in remote hosts, and transparently connected +# through a UDP tunnel. + +# +# command line: +# +# PYTHONPATH=$PYTHONPATH:src python examples/ns3/multi_host/ditributed.py +# + +import os + +from nepi.execution.ec import ExperimentController +from nepi.execution.resource import ResourceState, ResourceManager + +from topology import * + +# tunning +os.environ["NEPI_NTHREADS"] = "1" +ResourceManager._reschedule_delay = "0s" + +# list of hosts for running the experiment on +hostname1 = "onelab4.warsaw.rd.tp.pl" +hostname2 = "planet2.servers.ua.pt" + +(username, pl_user, pl_password, ssh_key, node_count) = get_options() + +ec = ExperimentController(exp_id="distributed") + +host1, simu1 = add_host_simu(ec, hostname1, username, pl_user, pl_password, + ssh_key) + +ap1, agent1 = build_ns3_topology(ec, simu1, node_count, network="10.1.0.0", + prefixlen="24", agent_ip="10.1.0.1") + +host2, simu2 = add_host_simu(ec, hostname2, username, pl_user, pl_password, ssh_key) +ap2, agent2 = build_ns3_topology(ec, simu2, node_count, network="10.2.0.0", prefixlen="24", agent_ip="10.1.0.1") + +fddev1 = add_fdnet_device(ec, ap1, "10.0.0.1", "30") +fddev2 = add_fdnet_device(ec, ap2, "10.0.0.2", "30") + +connect_with_udp_tunnel(ec, fddev1, fddev2) + +ec.deploy() + +ec.wait_finished([simu1, simu2]) + +stdout = ec.trace(agent1, "stdout") +print " Agent says:" +print stdout + +ec.shutdown() + diff --git a/examples/ns3/multi_host/experiment.py b/examples/ns3/multi_host/experiment.py deleted file mode 100644 index 34da12f2..00000000 --- a/examples/ns3/multi_host/experiment.py +++ /dev/null @@ -1,379 +0,0 @@ -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -import ipaddr -from random import randint -from nepi.execution.ec import ExperimentController -from nepi.execution.resource import ResourceState, ResourceAction - -# ######################################################## -class Experiment(object): - # ec : ExperimentController - # node: planetlab::Node - def __init__(self, ec, node_info, nb_nodes, real_time = True): - print "Experiement %s %s" % (node_info, nb_nodes) - - # remember the ExperimentController the experiment is associated to - self.ec = ec - - # define the physical machine to run the experiment on - self.add_node(node_info) - - # number of simulated nodes moving in the - self.nb_nodes = nb_nodes - - # fix the geographical boundaries of the network - self.bounds_width = self.bounds_height = 100 - - # fix the speed at which mobile nodes can move - self.speed = 1 - - # collection of simulated node (their GID) in the simulator - # nsnodes[0] is always the GID of the simulated node containing the - # access point - self.nsnodes = list() - - # collection of application (their GID) running in the simulator - # apps[0] is always the GID of the agent application running on the - # access point - self.apps = list() - - # prepare the ns-3 simulator to use for the experiment - self.add_simulator(real_time) - - # for sanity check - self.topology_built = False - - def add_node(self, node_info): - """ - Define the physical machine on which run the experiment - """ - if node_info["hostname"] == "localhost": - self.node = self.ec.register_resource("linux::Node") - self.ec.set(self.node, "hostname", "localhost") - else: - self.node = self.ec.register_resource("planetlab::Node") - self.ec.set(self.node, "hostname", node_info["hostname"]) - self.ec.set(self.node, "username", node_info["username"]) - self.ec.set(self.node, "identity", node_info["identity"]) - self.ec.set(self.node, "cleanProcesses", True) - self.ec.set(self.node, "cleanExperiment", True) - - return self.node - - def add_simulator(self, real_time): - """ - Add a ns-3 simulator on the node used for the experiment - """ - # creat the ns-3 simulator instance - self.simu = self.ec.register_resource("linux::ns3::Simulation") - self.ec.set (self.simu, "StopTime", "200s") - # - # run it in realtime mode if asked - if real_time: - self.ec.set(self.simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl") - # - # log additional information - self.ec.set(self.simu, "checksumEnabled", True) - self.ec.set(self.simu, "verbose", True) - self.ec.set(self.simu, "enableDump", True) - self.ec.register_connection(self.simu, self.node) - - return self.simu - - # == ns-3 simulation helper functions ===================================== - def add_nsnode(self): - """ - Create a ns-3 node and add it to the simulator - """ - # create a ns-3 node - nsnode = self.ec.register_resource("ns3::Node") - # enable its network stack - self.ec.set(nsnode, "enableStack", True) - self.ec.register_connection(nsnode, self.simu) - - return nsnode - - def add_wifi_channel(self): - """ - Create the WiFi channel on which all nodes will be connected - """ - # create a channel - channel = self.ec.register_resource("ns3::YansWifiChannel") - - # specify the delay model - delay = self.ec.register_resource("ns3::ConstantSpeedPropagationDelayModel") - self.ec.register_connection(channel, delay) - - # specify a loss model - loss = self.ec.register_resource("ns3::LogDistancePropagationLossModel") - self.ec.register_connection(channel, loss) - - return channel - - def add_wifi_device(self, node, ip, prefix, access_point = False): - """ - Add and configure the WiFi interface on a simulated node - """ - - # create the WiFi network interface - dev = self.ec.register_resource("ns3::WifiNetDevice") - - # specify the network layer parameters - self.ec.set(dev, "ip", ip) - self.ec.set(dev, "prefix", prefix) - self.ec.register_connection(node, dev) - - # specify the MAC layer parameters - # - # can be in access point mode or not - if access_point: - mac = self.ec.register_resource("ns3::ApWifiMac") - else: - mac = self.ec.register_resource("ns3::StaWifiMac") - # the MAC is IEEE 802.11a - self.ec.set(mac, "Standard", "WIFI_PHY_STANDARD_80211a") - self.ec.register_connection(dev, mac) - - # specify the physical layer parameters - phy = self.ec.register_resource("ns3::YansWifiPhy") - # - # it physical layer is IEEE802.11a - self.ec.set(phy, "Standard", "WIFI_PHY_STANDARD_80211a") - self.ec.register_connection(dev, phy) - # - # specify an error model for transmissions - error = self.ec.register_resource("ns3::NistErrorRateModel") - self.ec.register_connection(phy, error) - - # specify the Wifi manager to be assocated with the interface - manager = self.ec.register_resource("ns3::ArfWifiManager") - self.ec.register_connection(dev, manager) - - return dev, phy - - def add_random_mobility(self, node, x, y, z, speed, bounds_width, bounds_height): - """ - Create a mobility model for node with random movements - """ - position = "%d:%d:%d" % (x, y, z) - bounds = "0|%d|0|%d" % (bounds_width, bounds_height) - speed = "ns3::UniformRandomVariable[Min=%d|Max=%s]" % (speed, speed) - pause = "ns3::ConstantRandomVariable[Constant=1.0]" - - mobility = self.ec.register_resource("ns3::RandomDirection2dMobilityModel") - self.ec.set(mobility, "Position", position) - self.ec.set(mobility, "Bounds", bounds) - self.ec.set(mobility, "Speed", speed) - self.ec.set(mobility, "Pause", pause) - self.ec.register_connection(node, mobility) - - return mobility - - def add_constant_mobility(self, node, x, y, z): - """ - Create a mobility model for node with a constant position - """ - mobility = self.ec.register_resource("ns3::ConstantPositionMobilityModel") - position = "%d:%d:%d" % (x, y, z) - self.ec.set(mobility, "Position", position) - self.ec.register_connection(node, mobility) - - return mobility - - def create_simulated_node(self, ip, prefix, channel, access_point, x, y): - """ - Create a simulated node connected on a WiFi channel - """ - # Create the ns node that will run the application - nsnode = self.add_nsnode() - - # Add a WiFi interface to the node - dev, phy = self.add_wifi_device(nsnode, ip, prefix, access_point) - # - # Connect the access point to the WiFi network - self.ec.register_connection(channel, phy) - - # Specify that the node mobility - # - # access point is not mobile - if access_point: - mobility = self.add_constant_mobility(nsnode, x, y, 0) - # other nodes have random mobility pattern - else: - mobility = self.add_random_mobility(nsnode, x, y, 0, self.speed, self.bounds_width, self.bounds_height) - - return nsnode - - def add_route(self, nsnode, netblock, prefix, nexthop): - """ - add a route on ns-3 node nsnode for netblock/prefix via nexthop - """ - route = self.ec.register_resource("ns3::Route") - self.ec.set(route, "network", netblock) - self.ec.set(route, "prefix", prefix) - self.ec.set(route, "nexthop", nexthop) - self.ec.register_connection(route, nsnode) - print "route %s/%s via %s added on nsnode %s (%s)" % (netblock, prefix, nexthop, nsnode, self) - - return route - - def add_vroute(self, dev, netblock, prefix, nexthop): - """ - Add a route on Planetlab node for netblock/prefix via nexthop - """ - route = self.ec.register_resource("planetlab::Vroute") - self.ec.set(route, "network", netblock) - self.ec.set(route, "prefix", prefix) - self.ec.set(route, "nexthop", nexthop) - self.ec.register_connection(route, dev) - print "Vroute %s/%s via %s added on nsnode %s (%s)" % (netblock, prefix, nexthop, dev, self) - - return route - - def add_agent(self, nsnode): - """ - Add a agent application - """ - # Create a DCE application running the agent code - app = self.ec.register_resource("linux::ns3::dce::Application") - self.ec.set(app, "sources", "code/agent.c") - self.ec.set(app "build", "gcc -fPIC -pie -rdynamic ${SRC}/agent.c -o ${BIN_DCE}/agent") - self.ec.set(app, "binary", "agent") - self.ec.set(app, "arguments", "45005") - self.ec.set(app, "stackSize", 1<<20) - self.ec.set(app, "StartTime", "10s") - self.ec.set(app, "StopTime", "200s") - - # Associate the application with the simulated node - self.ec.register_connection(app, nsnode) - - # Make the application start only once the simulated node is started - self.ec.register_condition(app, ResourceAction.START, - nsnode, ResourceState.STARTED, time="5s") - - return app - - def add_transmitter(self, nsnode): - """ - Add a transmitter application - """ - # Create a DCE application running the transmitter code - app = self.ec.register_resource("linux::ns3::dce::Application") - self.ec.set(app, "sources", "code/transmitter.c") - self.ec.set(app, "build", "gcc -fPIC -pie -rdynamic ${SRC}/transmitter.c -o ${BIN_DCE}/transmitter") - self.ec.set(app, "binary", "transmitter") - self.ec.set(app, "arguments", "%s;45005" % target) - self.ec.set(app, "stackSize", 1<<20) - self.ec.set(app, "StartTime", "10s") - self.ec.set(app, "StopTime", "200s") - - # Associate the application with the simulated node - self.ec.register_connection(app, nsnode) - # - # Make the application start only once the simulated node and the serer are started - self.ec.register_condition(app, ResourceAction.START, - [nsnode, self.apps[0]], ResourceState.STARTED, time="10s") - - return app - - def add_planetlab_transmitter(self, target): - """ - Add a planetlab transmitter application - """ - - # Create an application running the transmitter code - app = self.ec.register_resource("linux::Application") - self.ec.set(app, "sources", "code/transmitter.c") - self.ec.set(app, "build", "make ${SRC}/transmitter") - self.ec.set(app, "command", "${SRC}/transmitter %s 45005" % target) - - # Associate the application with the Planetlab node - self.ec.register_connection(app, self.node) - - # Make the application start only once the simulated agent and the node are started - self.ec.register_condition(app, ResourceAction.START, - [self.apps[0], self.node], ResourceState.STARTED, time="10s") - - return app - - # == Topology construction ================================================ - def build_topology(self, netblock, prefix, target): - """ - Builds a topology composed of one fixed access point and nb_nodes - mobile nodes - """ - - # Rember network parameters - self.netblock = netblock - self.prefix = prefix - - # Create the WiFi network via which nodes are connected - chan = self.add_wifi_channel() - - # == Access point - # Geographical position of the access point - x=50 - y=0 - - # the IP address of the access point is the first in the prefix - self.ip_ap = str(ipaddr.IPv4Address(self.netblock) + 1) - print "IP AP: %s " % (self.ip_ap) - - # Create the ns node that will run the access point - nsnode = self.create_simulated_node(self.ip_ap, self.prefix, chan, True, x, y) - - # add the node in the collection of simulated nodes - self.nsnodes.append(nsnode) - - # Run a agent application on the access point - agent = self.add_agent(nsnode) - - # add the agent application in the collection of applications - self.apps.append(agent) - - # Add nb_nodes mobile nodes in the WiFi network - for i in range(1, self.nb_nodes + 1): - # pic a random initial location - x = randint(0, self.bounds_width) - y = randint(0, self.bounds_height) - - # define the appropriate IP address of the node (sequential IP in what remains after the access point IP) - ip = str(ipaddr.IPv4Address(self.ip_ap) + i) - - print "IP mobile: " , ip - - # Create the ns node that will run the mobile node - nsnode = self.create_simulated_node(ip, self.prefix, chan, False, x, y) - # - # add the node in the collection of simulated nodes - self.nsnodes.append(nsnode) - - if target: - # Run a transmitter application on the mobile node - transmitter = self.add_transmitter(nsnode) - - # add the trasmitter application in the collection of applications - self.apps.append(transmitter) - - # Add a default route via the access point - self.add_route(nsnode, "0.0.0.0", "0", self.ip_ap) - - # for sanity check - self.topology_built = True diff --git a/examples/ns3/multi_host/experiment_interconnected.py b/examples/ns3/multi_host/experiment_interconnected.py deleted file mode 100644 index f95bd771..00000000 --- a/examples/ns3/multi_host/experiment_interconnected.py +++ /dev/null @@ -1,47 +0,0 @@ -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -from experiment import Experiment - -class ExperimentInterconnected(Experiment): - def __init__(self, ec, node, nb_nodes, real_time = True): - super(ExperimentInterconnected, self).__init__(ec, node, nb_nodes, real_time) - self.interconnected = False - self.fddev = None - - def add_fdnetdevice(self, ip, prefix, nsnode = None): - # Sanity check - # - # only one FD device allowed - if self.fddev: - raise Exception("A FD device is already setup") - - # Attach the FD device to the access point by default - if not nsnode: - nsnode = self.nsnodes[0] - - # Create the FD device - self.fddev = self.ec.register_resource("ns3::FdNetDevice") - self.ec.set(self.fddev, "ip", ip) - self.ec.set(self.fddev, "prefix", prefix) - - # attach it to the simulated node - self.ec.register_connection(nsnode, self.fddev) - - return self.fddev diff --git a/examples/ns3/multi_host/experiment_interconnected_ns3_planetlab.py b/examples/ns3/multi_host/experiment_interconnected_ns3_planetlab.py deleted file mode 100644 index 01f8bcd5..00000000 --- a/examples/ns3/multi_host/experiment_interconnected_ns3_planetlab.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -import ipaddr -from experiment_interconnected import ExperimentInterconnected - -class ExperimentInterconnectedNs3Planetlab(ExperimentInterconnected): - def add_tap_device(self, node, ip, prefix, pointopoint): - """ - Add a point-to-point tap device on the planetlab node. This tap device - is used to exchange traffic with the simulated network - """ - # Create the tap device - dev = self.ec.register_resource("planetlab::Tap") - - # Define the local network associated with the TAP device - self.ec.set(dev, "ip", ip) - self.ec.set(dev, "prefix", prefix) - - # Define the other side of the tap (the simulated network device) - self.ec.set(dev, "pointopoint", pointopoint) - - # Associate the TAP device with the Planetlab node - self.ec.register_connection(node, dev) - - return dev - - def connect_with_tuntap(self, tap): - """ - Connect the simulated network with the Planetlab node via the TAP of - the Planetlab node and the FD device of the simulated network - """ - # Create the link - crosslink = self.ec.register_resource("planetlab::ns3::TunTapFdLink") - - # Associate it with the Planetlab tap device on one side - self.ec.register_connection(crosslink, tap) - # - # Associate it with the simulated network FD device on the other side - self.ec.register_connection(crosslink, self.fddev) - - return crosslink - - def interconnect(self, netblock_pl, prefix_pl): - """ - Interconnect a simulated network with a Planetlab network via a tap device - """ - # sanity checks - # - # topology must be setup - if not self.topology_built: - raise Exception("Topology not setup on ", self) - # - # experiment cannot be interconnected to another experiment - if self.interconnected: - raise Exception("Experiment already interconnected on ", self) - - - ip_simulated = str(ipaddr.IPv4Address(netblock_pl) + 1) - ip_pl = str(ipaddr.IPv4Address(ip_simulated) + 1) - - # Add a TAP interface on the Planetlab machine to connect the real - # application with the simulated network - tap = self.add_tap_device(self.node, ip_pl, prefix_pl, ip_simulated) - - # Add an FD device on the simulator to connect to the real - self.add_fdnetdevice(ip_simulated, prefix_pl) - - # Connect both Planetlab and simulated network via the tap device - self.connect_with_tuntap(tap) - - # Route traffic for the Planetlab node to the Planetlab machine - self.add_route(self.nsnodes[0], netblock_pl, prefix_pl, self.ip_ap) - - # Route traffic for the simulated node to the simulator - self.add_vroute(tap, self.netblock, self.prefix, ip_simulated) - - # Sanity check - self.interconnected = True - diff --git a/examples/ns3/multi_host/experiment_interconnected_ns3ns3.py b/examples/ns3/multi_host/experiment_interconnected_ns3ns3.py deleted file mode 100644 index ab2a8a2c..00000000 --- a/examples/ns3/multi_host/experiment_interconnected_ns3ns3.py +++ /dev/null @@ -1,65 +0,0 @@ -# -# NEPI, a framework to manage network experiments -# Copyright (C) 2013 INRIA -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation; -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Author: Damien Saucez -# Alina Quereilhac - -from experiment_interconnected import ExperimentInterconnected - -class ExperimentInterconnectedNs3Ns3(ExperimentInterconnected): - def connect_with_udp_tunnel(self, xp_remote): - # Connect the two experiments via a UDP tunnel direcly on the FD devices - tunnel = self.ec.register_resource("planetlab::ns3::FdUdpTunnel") - self.ec.register_connection(tunnel, self.fddev) - self.ec.register_connection(tunnel, xp_remote.fddev) - - return tunnel - - def interconnect(self, xp_remote): - """ - Interconnect two ns3 simulations via a UDP tunnel - """ - # sanity checks - # - # topology must be setup - if not self.topology_built: - raise Exception("Topology not setup on ", self) - if not xp_remote.topology_built: - raise Exception("Topology not setup on ", xp_remote ) - # - # experiment cannot be interconnected to another experiment - if self.interconnected: - raise Exception("Experiment already interconnected on ", self) - if xp_remote.interconnected: - raise Exception("Experiment already interconnected on ", xp_remote) - - # IP for the AP of the two experiments - # XXX DSA: ugly - ip = ["10.0.0.1", "10.0.0.2"] - - # add an FD device on both local and remote experiments - self.add_fdnetdevice(ip[0], "30") - xp_remote.add_fdnetdevice(ip[1], "30") - - # Connect the two experiments via a UDP tunnel direcly on the FD devices - self.connect_with_udp_tunnel(xp_remote) - - # Add a route to the remote network on each experiment, via the FD device - self.add_route(self.nsnodes[0], xp_remote.netblock, xp_remote.prefix, ip[1]) - xp_remote.add_route(xp_remote.nsnodes[0], self.netblock, self.prefix, ip[0]) - - # Sanity check - self.interconnected = True diff --git a/examples/ns3/multi_host/hybrid.py b/examples/ns3/multi_host/hybrid.py new file mode 100644 index 00000000..0b364789 --- /dev/null +++ b/examples/ns3/multi_host/hybrid.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2015 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Damien Saucez +# Alina Quereilhac +# + +# +# Note that to run this experiment you need to have a PlanetLab account. +# +# This experiment consists of a simulated wireless sensor network (ns-3) +# with one fixed access point (AP), running an agent application, and several +# mobile stations that run a transmitter application to send messages to +# the AP. +# +# One of the transmitter applications runs outside the simulation, on +# the host, and sends messages to the AP through the FdNetDevice/TAP +# link. +# + +# +# command line: +# +# PYTHONPATH=$PYTHONPATH:src python examples/ns3/multi_host/hybrid.py +# + +import os + +from nepi.execution.ec import ExperimentController +from nepi.execution.resource import ResourceState, ResourceManager + +from topology import * + +# tunning +os.environ["NEPI_NTHREADS"] = "1" +ResourceManager._reschedule_delay = "0s" + +# list of hosts for running the experiment on +hostname1 = "onelab4.warsaw.rd.tp.pl" +hostname2 = "planet2.servers.ua.pt" + +(username, pl_user, pl_password, ssh_key, node_count) = get_options() + +ec = ExperimentController(exp_id="hybrid") + +host, simu = add_host_simu(ec, hostname1, username, pl_user, pl_password, + ssh_key) + +ap, agent = build_ns3_topology(ec, simu, node_count, network="192.168.3.0", + prefixlen="25", agent_ip="192.168.3.1") + +fddev = add_fdnet_device(ec, ap, "192.168.3.129", "25") + +tap = ec.register_resource("planetlab::Tap") +ec.set(tap, "ip", "192.168.3.130") +ec.set(tap, "prefix", "25") +ec.set(tap, "pointopoint", "192.168.3.129") +ec.register_connection(host, tap) + +connect_with_virtual_link(ec, tap, fddev) + +add_ns3_route(ec, ap, network="192.168.3.128", prefixlen="25", nexthop="192.168.3.1") +add_planetlab_route(ec, tap, network="192.168.3.0", prefixlen="25", nexthop="192.168.3.129") + +transmitter = ec.register_resource("linux::Application") +ec.set(transmitter, "sources", "code/transmitter.c") +ec.set(transmitter, "build", "gcc ${SRC}/transmitter.c -o ${BIN}/transmitter") +ec.set(transmitter, "command", "${BIN}/transmitter 192.168.3.1") +ec.register_connection(transmitter, host) + +ec.deploy() + +ec.wait_finished([simu, transmitter]) + +stdout = ec.trace(agent, "stdout") +print " Agent says: " +print stdout + +stdout = ec.trace(transmitter, "stdout") +print " Live transmitter output: " +print stdout + +ec.shutdown() + + diff --git a/examples/ns3/multi_host/parallel.py b/examples/ns3/multi_host/parallel.py new file mode 100644 index 00000000..a0be0a9a --- /dev/null +++ b/examples/ns3/multi_host/parallel.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2015 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Damien Saucez +# Alina Quereilhac +# + +# +# Note: To run this experiment you need to have a PlanetLab account. +# +# This experiment consists of a simulated wireless sensor network (ns-3) +# with one fixed access point (AP), running an agent application, and several +# mobile stations that run a transmitter application to send messages to +# the AP. +# +# The same experiment described above is run in parallel with different +# number of mobile stations in 2 PlanetLab hosts. +# + +# +# command line: +# +# PYTHONPATH=$PYTHONPATH:src python examples/ns3/multi_host/parallel.py +# + +import os + +from topology import * + +from nepi.execution.ec import ExperimentController +from nepi.execution.resource import ResourceState, ResourceManager + +# tunning +os.environ["NEPI_NTHREADS"] = "1" +ResourceManager._reschedule_delay = "0s" + +# list of hosts for running the experiment on +hostname1 = "onelab4.warsaw.rd.tp.pl" +hostname2 = "planet2.servers.ua.pt" + +(username, pl_user, pl_password, ssh_key, node_count) = get_options() + +ec = ExperimentController(exp_id="parallel") +counts = [node_count, 10] +hosts = [hostname1, hostname2] + +simulations = [] +agents = [] + +for hostname in hosts: + host, simu = add_host_simu(ec, hostname, username, pl_user, pl_password, + ssh_key) + simulations.append(simu) + + node_count = counts.pop() + ap, agent = build_ns3_topology(ec, simu, node_count, network="10.1.0.0", + prefixlen="24", agent_ip="10.1.0.1") + agents.append(agent) + +ec.deploy() + +ec.wait_finished(simulations) + +for agent in agents: + stdout = ec.trace(agent, "stdout") + print " Agent says:" + print stdout + +ec.shutdown() + + diff --git a/examples/ns3/multi_host/topology.py b/examples/ns3/multi_host/topology.py new file mode 100644 index 00000000..70dbbbf5 --- /dev/null +++ b/examples/ns3/multi_host/topology.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2015 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation; +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# Author: Damien Saucez +# Alina Quereilhac +# + +import ipaddr +from optparse import OptionParser +import os +from random import randint + +# list of hosts for running the experiment on +hostname1 = "onelab4.warsaw.rd.tp.pl" +hostname2 = "planet2.servers.ua.pt" + +def get_options(): + # PlanetLab credentials + pl_slice = os.environ.get("PL_SLICE") + pl_user = os.environ.get("PL_USER") + pl_password = os.environ.get("PL_PASS") + pl_ssh_key = os.environ.get("PL_SSHKEY") + + usage = ("usage: %prog -s -u -p " + "-k -n ") + + parser = OptionParser(usage = usage) + parser.add_option("-s", "--pl-slice", dest="pl_slice", + help="PlanetLab slicename", default=pl_slice, type="str") + parser.add_option("-u", "--pl-user", dest="pl_user", + help="PlanetLab web username", default=pl_user, type="str") + parser.add_option("-p", "--pl-password", dest="pl_password", + help="PlanetLab web password", default=pl_password, type="str") + parser.add_option("-k", "--pl-ssh-key", dest="pl_ssh_key", + help="Path to private SSH key associated with the PL account", + default=pl_ssh_key, type="str") + parser.add_option("-n", "--node-count", dest="node_count", + help="Number of nodes in the wireless network", + default = 4, type="int") + + (options, args) = parser.parse_args() + + return (options.pl_slice, options.pl_user, options.pl_password, + options.pl_ssh_key, options.node_count) + +# == add host and simu ======================================================= +def add_host_simu(ec, hostname, username, pl_user, pl_password, ssh_key): + host = ec.register_resource("planetlab::Node") + ec.set(host, "hostname", hostname) + + if username: + ec.set(host, "username", username) + + if pl_user: + ec.set(host, "pluser", pl_user) + + if pl_password: + ec.set(host, "plpassword", pl_password) + + if ssh_key: + ec.set(host, "identity", ssh_key) + + ec.set(host, "cleanProcesses", True) + ec.set(host, "cleanExperiment", True) + + simu = ec.register_resource("linux::ns3::Simulation") + ec.set(simu, "simulatorImplementationType", "ns3::RealtimeSimulatorImpl") + ec.set(simu, "checksumEnabled", True) + ec.set(simu, "verbose", True) + ec.set(simu, "enableDump", True) + ec.set (simu, "StopTime", "200s") + ec.register_connection(simu, host) + + return host, simu + +# == build topology ========================================================= + +def add_ns3_wifi_device(ec, ns3_node, ip, prefixlen, ap_mode): + # create the WiFi network interface + dev = ec.register_resource("ns3::WifiNetDevice") + + # specify the network layer parameters + ec.set(dev, "ip", ip) + ec.set(dev, "prefix", prefixlen) + ec.register_connection(ns3_node, dev) + + # specify the MAC layer parameters + # + # can be in access point mode or not + if ap_mode: + mac = ec.register_resource("ns3::ApWifiMac") + else: + mac = ec.register_resource("ns3::StaWifiMac") + + # the MAC is IEEE 802.11a + ec.set(mac, "Standard", "WIFI_PHY_STANDARD_80211a") + ec.register_connection(dev, mac) + + # specify the physical layer parameters + phy = ec.register_resource("ns3::YansWifiPhy") + # + # it physical layer is IEEE802.11a + ec.set(phy, "Standard", "WIFI_PHY_STANDARD_80211a") + ec.register_connection(dev, phy) + # + # specify an error model for transmissions + error = ec.register_resource("ns3::NistErrorRateModel") + ec.register_connection(phy, error) + + # specify the Wifi manager to be assocated with the interface + manager = ec.register_resource("ns3::ArfWifiManager") + ec.register_connection(dev, manager) + + return dev, phy + +def add_ns3_wifi_channel(ec): + channel = ec.register_resource("ns3::YansWifiChannel") + + delay = ec.register_resource("ns3::ConstantSpeedPropagationDelayModel") + ec.register_connection(channel, delay) + + loss = ec.register_resource("ns3::LogDistancePropagationLossModel") + ec.register_connection(channel, loss) + + return channel + +# == Add random mobility +def add_ns3_random_mobility(ec, ns3_node): + speed = 1 + bounds_width = 100 + bounds_height = 100 + x = randint(0, bounds_width) + y = randint(0, bounds_height) + z = 0 + + position = "%d:%d:%d" % (x, y, z) + bounds = "0|%d|0|%d" % (bounds_width, bounds_height) + speed = "ns3::UniformRandomVariable[Min=%d|Max=%s]" % (speed, speed) + pause = "ns3::ConstantRandomVariable[Constant=1.0]" + + mobility = ec.register_resource("ns3::RandomDirection2dMobilityModel") + ec.set(mobility, "Position", position) + ec.set(mobility, "Bounds", bounds) + ec.set(mobility, "Speed", speed) + ec.set(mobility, "Pause", pause) + ec.register_connection(ns3_node, mobility) + + return mobility + +# == Add constant mobility +def add_ns3_constant_mobility(ec, ns3_node): + mobility = ec.register_resource("ns3::ConstantPositionMobilityModel") + position = "%d:%d:%d" % (0, 50, 0) + ec.set(mobility, "Position", position) + ec.register_connection(ns3_node, mobility) + + return mobility + +# == add ns-3 node +def add_ns3_node(ec, simu, ip, prefixlen, channel, ap_mode=False): + ns3_node = ec.register_resource("ns3::Node") + ec.set(ns3_node, "enableStack", True) + ec.register_connection(ns3_node, simu) + + dev, phy = add_ns3_wifi_device(ec, ns3_node, ip, prefixlen, ap_mode) + ec.register_connection(channel, phy) + + if not ap_mode: + add_ns3_random_mobility(ec, ns3_node) + else: + add_ns3_constant_mobility(ec, ns3_node) + + return ns3_node + +# == add DCE agent +def add_dce_agent(ec, ns3_node): + agent = ec.register_resource("linux::ns3::dce::Application") + ec.set(agent, "sources", "code/agent.c") + ec.set(agent, "build", "gcc -fPIC -pie -rdynamic ${SRC}/agent.c -o ${BIN_DCE}/agent") + ec.set(agent, "binary", "agent") + ec.set(agent, "stackSize", 1<<20) + ec.set(agent, "StartTime", "10s") + ec.set(agent, "StopTime", "200s") + + ec.register_connection(agent, ns3_node) + + return agent + +# == add DCE transmitter +def add_dce_transmitter(ec, ns3_node, target): + transmitter = ec.register_resource("linux::ns3::dce::Application") + ec.set(transmitter, "sources", "code/transmitter.c") + ec.set(transmitter, "build", "gcc -fPIC -pie -rdynamic ${SRC}/transmitter.c -o ${BIN_DCE}/transmitter") + ec.set(transmitter, "binary", "transmitter") + ec.set(transmitter, "arguments", target) + ec.set(transmitter, "stackSize", 1<<20) + ec.set(transmitter, "StartTime", "10s") + ec.set(transmitter, "StopTime", "200s") + + ec.register_connection(transmitter, ns3_node) + + return transmitter + +# == Add ns-3 route +def add_ns3_route(ec, ns3_node, network, prefixlen, nexthop): + route = ec.register_resource("ns3::Route") + ec.set(route, "network", network) + ec.set(route, "prefix", prefixlen) + ec.set(route, "nexthop", nexthop) + ec.register_connection(route, ns3_node) + + return route + +# = build ns3 topology ======================================================= +def build_ns3_topology(ec, simu, node_count, network, prefixlen, agent_ip): + channel = add_ns3_wifi_channel(ec) + + net = ipaddr.IPv4Network("%s/%s" % (network, prefixlen)) + itr = net.iterhosts() + + ap_ip = itr.next().exploded + ap = add_ns3_node(ec, simu, ap_ip, prefixlen, channel, ap_mode=True) + + agent = None + if ap_ip == agent_ip: + agent = add_dce_agent(ec, ap) + + for i in range(0, node_count): + ip = itr.next().exploded + sensor = add_ns3_node(ec, simu, ip, prefixlen, channel, ap_mode=False) + transmitter = add_dce_transmitter(ec, sensor, ap_ip) + add_ns3_route(ec, sensor, network="0.0.0.0", prefixlen="0", nexthop=ap_ip) + + return ap, agent + + +# == add FdNetDevice ========================================================= +def add_fdnet_device(ec, ap, ip, prefixlen): + fddev = ec.register_resource("ns3::FdNetDevice") + ec.set(fddev, "ip", ip) + ec.set(fddev, "prefix", prefixlen) + ec.register_connection(ap, fddev) + + return fddev + +# == connect with UDP tunnel ================================================= +def connect_with_udp_tunnel(ec, fddev1, fddev2): + tunnel = ec.register_resource("planetlab::ns3::FdUdpTunnel") + ec.register_connection(tunnel, fddev1) + ec.register_connection(tunnel, fddev2) + + return tunnel + +# == connect with virtual link =============================================== +def connect_with_virtual_link(ec, tap, fddev): + link = ec.register_resource("planetlab::ns3::TunTapFdLink") + ec.register_connection(link, tap) + ec.register_connection(link, fddev) + + return link + +# == Add planet lab route ==================================================== + +def add_planetlab_route(ec, dev, network, prefixlen, nexthop): + route = ec.register_resource("planetlab::Vroute") + ec.set(route, "network", network) + ec.set(route, "prefix", prefixlen) + ec.set(route, "nexthop", nexthop) + ec.register_connection(route, dev) + + return route + diff --git a/src/nepi/resources/linux/ns3/ns3simulation.py b/src/nepi/resources/linux/ns3/ns3simulation.py index c39c1a32..f6be9753 100644 --- a/src/nepi/resources/linux/ns3/ns3simulation.py +++ b/src/nepi/resources/linux/ns3/ns3simulation.py @@ -335,6 +335,27 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): super(LinuxApplication, self).do_release() + @property + def state(self): + super(LinuxApplication, self).state + + if self._state == ResourceState.STARTED: + try: + is_finished = self.invoke(SIMULATOR_UUID, "isFinished") + + if is_finished: + self.set_stopped() + except: + msg = "Simulator failed. Can not retrieve state" + out = "" + + import traceback + err = traceback.format_exc() + self.error(msg, out, err) + self.do_fail() + + return self._state + @property def enable_dce(self): if self._enable_dce is None: -- 2.43.0