From e0447bc7e91d169d6d88498981421572d939b6fb Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Fri, 21 Feb 2014 14:58:47 +0100 Subject: [PATCH] Adding compilation of DCE sources --- src/nepi/resources/linux/node.py | 41 +++-- src/nepi/resources/linux/ns3/ns3simulation.py | 155 +++++++++++++----- src/nepi/resources/ns3/ns3node.py | 42 +++++ src/nepi/resources/ns3/ns3wrapper.py | 9 +- test/resources/linux/ns3/ns3simulation.py | 66 +++++++- 5 files changed, 255 insertions(+), 58 deletions(-) diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index f9c016a8..8ad69f32 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -353,14 +353,14 @@ class LinuxNode(ResourceManager): if self.get("cleanExperiment"): self.clean_experiment() - # Create shared directory structure - self.mkdir(self.lib_dir) - self.mkdir(self.bin_dir) - self.mkdir(self.src_dir) - self.mkdir(self.share_dir) + # Create shared directory structure and node home directory + paths = [self.lib_dir, + self.bin_dir, + self.src_dir, + self.share_dir, + self.node_home] - # Create experiment node home directory - self.mkdir(self.node_home) + self.mkdir(paths) super(LinuxNode, self).do_provision() @@ -787,14 +787,31 @@ class LinuxNode(ResourceManager): return (out, err), proc - def mkdir(self, path, clean = False): + def mkdir(self, paths, clean = False): + """ Paths is either a single remote directory path to create, + or a list of directories to create. + """ if clean: - self.rmdir(path) + self.rmdir(paths) + + if isinstance(paths, str): + paths = [paths] - return self.execute("mkdir -p %s" % path, with_lock = True) + cmd = " ; ".join(map(lambda path: "mkdir -p %s" % path, paths)) - def rmdir(self, path): - return self.execute("rm -rf %s" % path, with_lock = True) + return self.execute(cmd, with_lock = True) + + def rmdir(self, paths): + """ Paths is either a single remote directory path to delete, + or a list of directories to delete. + """ + + if isinstance(paths, str): + paths = [paths] + + cmd = " ; ".join(map(lambda path: "rm -rf %s" % path, paths)) + + return self.execute(cmd, with_lock = True) def run_and_wait(self, command, home, shfile = "cmd.sh", diff --git a/src/nepi/resources/linux/ns3/ns3simulation.py b/src/nepi/resources/linux/ns3/ns3simulation.py index 9ce8291c..5745f543 100644 --- a/src/nepi/resources/linux/ns3/ns3simulation.py +++ b/src/nepi/resources/linux/ns3/ns3simulation.py @@ -74,7 +74,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): build_mode = Attribute("buildMode", "Mode used to build ns-3 with waf. One if: debug, release, oprimized ", - default = "release", + default = "optimized", allowed = ["debug", "release", "optimized"], type = Types.Enumerate, flags = Flags.Design) @@ -84,6 +84,12 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): default = "ns-3.19", flags = Flags.Design) + enable_dce = Attribute("enableDCE", + "Install DCE source code", + default = False, + type = Types.Bool, + flags = Flags.Design) + pybindgen_version = Attribute("pybindgenVersion", "Version of pybindgen to install from bazar repo", default = "834", @@ -104,6 +110,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): cls._register_attribute(ns3_version) cls._register_attribute(pybindgen_version) cls._register_attribute(populate_routing_tables) + cls._register_attribute(enable_dce) def __init__(self, ec, guid): LinuxApplication.__init__(self, ec, guid) @@ -111,7 +118,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): self._client = None self._home = "ns3-simu-%s" % self.guid - self._socket_name = "ns3simu-%s" % os.urandom(8).encode('hex') + self._socket_name = "ns3-%s.sock" % os.urandom(4).encode('hex') @property def socket_name(self): @@ -121,6 +128,11 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): def remote_socket(self): return os.path.join(self.run_home, self.socket_name) + @property + def ns3_build_home(self): + return os.path.join(self.node.bin_dir, "ns-3", self.get("ns3Version"), + self.get("buildMode"), "build") + def trace(self, name, attr = TraceAttr.ALL, block = 512, offset = 0): self._client.flush() return LinuxApplication.trace(self, name, attr, block, offset) @@ -195,7 +207,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): sched_type = self.get("schedulerType") stype = self.create("StringValue", sched_type) self.invoke(GLOBAL_VALUE_UUID, "Bind", "SchedulerType", btrue) - + def do_deploy(self): if not self.node or self.node.state < ResourceState.READY: self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.node.state ) @@ -282,9 +294,11 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): @property def _start_command(self): command = [] - command.append("PYTHONPATH=$PYTHONPATH:${SRC}/ns3wrapper/") - command.append("python ${SRC}/ns3wrapper/ns3server.py -S %s" % self.remote_socket ) + command.append("PYTHONPATH=$PYTHONPATH:${SRC}/ns3wrapper/") + + command.append("python ${SRC}/ns3wrapper/ns3server.py -S %s" % \ + os.path.basename(self.remote_socket) ) ns_log = self.get("nsLog") if ns_log: @@ -318,50 +332,70 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): # on the remote sources directory. Else we clone ns-3 from the official repo. source = self.get("sources") if not source: - copy_ns3_cmd = "hg clone %(ns3_repo)s/%(ns3_version)s ${SRC}/ns-3/%(ns3_version)s" \ - % ({ + clone_ns3_cmd = "hg clone %(ns3_repo)s/%(ns3_version)s ${SRC}/ns-3/%(ns3_version)s" \ + % { 'ns3_version': self.get("ns3Version"), 'ns3_repo': self.ns3_repo, - }) + } else: if source.find(".tar.gz") > -1: - copy_ns3_cmd = ( + clone_ns3_cmd = ( "tar xzf ${SRC}/ns-3/%(basename)s " " --strip-components=1 -C ${SRC}/ns-3/%(ns3_version)s " - ) % ({ + ) % { 'basename': os.path.basename(source), 'ns3_version': self.get("ns3Version"), - }) + } elif source.find(".tar") > -1: - copy_ns3_cmd = ( + clone_ns3_cmd = ( "tar xf ${SRC}/ns-3/%(basename)s " " --strip-components=1 -C ${SRC}/ns-3/%(ns3_version)s " - ) % ({ + ) % { 'basename': os.path.basename(source), 'ns3_version': self.get("ns3Version"), - }) + } elif source.find(".zip") > -1: basename = os.path.basename(source) bare_basename = basename.replace(".zip", "") \ .replace(".tar", "") \ .replace(".tar.gz", "") - copy_ns3_cmd = ( + clone_ns3_cmd = ( "unzip ${SRC}/ns-3/%(basename)s && " "mv ${SRC}/ns-3/%(bare_basename)s ${SRC}/ns-3/%(ns3_version)s " - ) % ({ + ) % { 'bare_basename': basename_name, 'basename': basename, 'ns3_version': self.get("ns3Version"), - }) + } + + clone_dce_cmd = " echo 'DCE will not be built' " + if self.get("enableDCE"): + clone_dce_cmd = ( + # DCE installation + # Test if dce is alredy installed + " ( " + " ( " + " ( test -d ${SRC}/dce/ns-3-dce ) " + " && echo 'dce binaries found, nothing to do'" + " ) " + " ) " + " || " + # Get dce source code + " ( " + " mkdir -p ${SRC}/dce && " + " hg clone http://code.nsnam.org/ns-3-dce ${SRC}/dce/ns-3-dce" + " ) " + ) return ( - # Test if ns-3 is alredy installed + # NS3 installation + "( " " ( " - " (( " - " ( test -d ${SRC}/ns-3/%(ns3_version)s ) || " - " ( test -d ${NS3BINDINGS:='None'} && test -d ${NS3LIBRARIES:='None'}) " - " ) && echo 'binaries found, nothing to do' )" + # Test if ns-3 is alredy installed + " ((( test -d ${SRC}/ns-3/%(ns3_version)s ) || " + " ( test -d ${NS3BINDINGS:='None'} && test -d ${NS3LIBRARIES:='None'})) " + " && echo 'ns-3 binaries found, nothing to do' )" " ) " " || " # If not, install ns-3 and its dependencies @@ -401,51 +435,88 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): # Get ns-3 source code " ( " " mkdir -p ${SRC}/ns-3/%(ns3_version)s && " - " %(copy_ns3_cmd)s " + " %(clone_ns3_cmd)s " " ) " " ) " - ) % ({ + ") " + " && " + "( " + " %(clone_dce_cmd)s " + ") " + ) % { 'ns3_version': self.get("ns3Version"), 'pybindgen_version': self.get("pybindgenVersion"), 'pygccxml_version': self.pygccxml_version, - 'copy_ns3_cmd': copy_ns3_cmd, - }) + 'clone_ns3_cmd': clone_ns3_cmd, + 'clone_dce_cmd': clone_dce_cmd, + } @property def _install(self): + install_dce_cmd = " echo 'DCE will not be installed' " + if self.get("enableDCE"): + install_dce_cmd = ( + " ( " + " ((test -d %(ns3_build_home)s/bin_dce ) && " + " echo 'dce binaries found, nothing to do' )" + " ) " + " ||" + " ( " + # If not, copy ns-3 build to bin + " cd ${SRC}/dce/ns-3-dce && " + " ./waf configure --enable-opt --with-pybindgen=${SRC}/pybindgen/%(pybindgen_version)s " + " --prefix=%(ns3_build_home)s --with-ns3=%(ns3_build_home)s && " + " ./waf build && " + " ./waf install " + " )" + ) % { + 'ns3_version': self.get("ns3Version"), + 'pybindgen_version': self.get("pybindgenVersion"), + 'ns3_build_home': self.ns3_build_home, + 'build_mode': self.get("buildMode"), + } + return ( - # Test if ns-3 is alredy cloned + # Test if ns-3 is alredy installed + "(" " ( " - " ( ( (test -d ${BIN}/ns-3/%(ns3_version)s/%(build_mode)s/build ) || " + " ( ( (test -d %(ns3_build_home)s/lib ) || " " (test -d ${NS3BINDINGS:='None'} && test -d ${NS3LIBRARIES:='None'}) ) && " " echo 'binaries found, nothing to do' )" " ) " " ||" " ( " # If not, copy ns-3 build to bin + " mkdir -p %(ns3_build_home)s && " " cd ${SRC}/ns-3/%(ns3_version)s && " - " ./waf configure -d %(build_mode)s --with-pybindgen=${SRC}/pybindgen/%(pybindgen_version)s && " - " ./waf && " - " mkdir -p ${BIN}/ns-3/%(ns3_version)s/%(build_mode)s && " - " mv ${SRC}/ns-3/%(ns3_version)s/build ${BIN}/ns-3/%(ns3_version)s/%(build_mode)s/build " + " ./waf configure -d %(build_mode)s --with-pybindgen=${SRC}/pybindgen/%(pybindgen_version)s " + " --prefix=%(ns3_build_home)s --includedir=%(ns3_build_home)s && " + " ./waf build && " + " ./waf install && " + " mv %(ns3_build_home)s/lib/python* %(ns3_build_home)s/lib/python " " )" - ) % ({ + ") " + " && " + "( " + " %(install_dce_cmd)s " + ") " + ) % { 'ns3_version': self.get("ns3Version"), 'pybindgen_version': self.get("pybindgenVersion"), 'build_mode': self.get("buildMode"), - }) + 'ns3_build_home': self.ns3_build_home, + 'install_dce_cmd': install_dce_cmd + } @property def _environment(self): env = [] - env.append("NS3BINDINGS=${NS3BINDINGS:=${BIN}/ns-3/%(ns3_version)s/%(build_mode)s/build/bindings/python/}" % ({ - 'ns3_version': self.get("ns3Version"), - 'build_mode': self.get("buildMode") - })) - env.append("NS3LIBRARIES=${NS3LIBRARIES:=${BIN}/ns-3/%(ns3_version)s/%(build_mode)s/build/}" % ({ - 'ns3_version': self.get("ns3Version"), - 'build_mode': self.get("buildMode") - })) + env.append("PYTHONPATH=$PYTHONPATH:${NS3BINDINGS:=%(ns3_build_home)s/lib/python/site-packages}" % { + 'ns3_build_home': self.ns3_build_home + }) + env.append("LD_LIBRARY_PATH=${NS3LIBRARIES:=%(ns3_build_home)s/lib/}" % { + 'ns3_build_home': self.ns3_build_home + }) return " ".join(env) diff --git a/src/nepi/resources/ns3/ns3node.py b/src/nepi/resources/ns3/ns3node.py index 0d6f6917..491cd917 100644 --- a/src/nepi/resources/ns3/ns3node.py +++ b/src/nepi/resources/ns3/ns3node.py @@ -17,6 +17,7 @@ # # Author: Alina Quereilhac +from nepi.execution.attribute import Attribute, Flags, Types from nepi.execution.resource import clsinit_copy from nepi.resources.ns3.ns3base import NS3Base @@ -24,6 +25,16 @@ from nepi.resources.ns3.ns3base import NS3Base class NS3BaseNode(NS3Base): _rtype = "abstract::ns3::Node" + @classmethod + def _register_attributes(cls): + enable_dce = Attribute("enableDCE", + "This node will run in DCE emulation mode ", + default = False, + type = Types.Bool, + flags = Flags.Design) + + cls._register_attribute(enable_dce) + @property def simulation(self): from nepi.resources.ns3.ns3simulation import NS3Simulation @@ -82,6 +93,9 @@ class NS3BaseNode(NS3Base): uuid_packet_socket_factory = self.simulation.create("PacketSocketFactory") self.simulation.invoke(self.uuid, "AggregateObject", uuid_packet_socket_factory) + if self.get("enableDCE") == True: + self._add_dce() + def _connect_object(self): ipv4 = self.ipv4 if ipv4: @@ -91,4 +105,32 @@ class NS3BaseNode(NS3Base): if mobility: self.simulation.invoke(self.uuid, "AggregateObject", mobility.uuid) + def _add_dce(self): + # TODO: All these component types should be configurable somewhere + """ + manager_uuid = self.simulation.create("ns3::TaskManager") + m_schedulerFactory.SetTypeId ("ns3::RrTaskScheduler"); + m_managerFactory.SetTypeId ("ns3::DceManager"); + m_networkStackFactory.SetTypeId ("ns3::Ns3SocketFdFactory"); + m_delayFactory.SetTypeId ("ns3::RandomProcessDelayModel"); + + Ptr taskManager = m_taskManagerFactory.Create (); + Ptr scheduler = m_schedulerFactory.Create (); + Ptr loader = m_loaderFactory.Create (); + Ptr networkStack = m_networkStackFactory.Create (); + Ptr delay = m_delayFactory.Create (); + + taskManager->SetScheduler (scheduler); + taskManager->SetDelayModel (delay); + manager->SetAttribute ("FirstPid", UintegerValue (g_firstPid.GetInteger (0, 0xffff))); + Ptr node = *i; + node->AggregateObject (taskManager); + node->AggregateObject (loader); + node->AggregateObject (manager); + node->AggregateObject (networkStack); + node->AggregateObject (CreateObject ()); + manager->AggregateObject (CreateObject ()); + manager->SetVirtualPath (GetVirtualPath ()); + """ + pass diff --git a/src/nepi/resources/ns3/ns3wrapper.py b/src/nepi/resources/ns3/ns3wrapper.py index b7ed1926..d06371f3 100644 --- a/src/nepi/resources/ns3/ns3wrapper.py +++ b/src/nepi/resources/ns3/ns3wrapper.py @@ -30,11 +30,10 @@ CONFIG_UUID = "singleton::Config" GLOBAL_VALUE_UUID = "singleton::GlobalValue" IPV4_GLOBAL_ROUTING_HELPER_UUID = "singleton::Ipv4GlobalRoutingHelper" -def load_ns3_module(): +def load_ns3_libraries(): import ctypes import re - bindings = os.environ.get("NS3BINDINGS") libdir = os.environ.get("NS3LIBRARIES") # Load the ns-3 modules shared libraries @@ -62,9 +61,13 @@ def load_ns3_module(): # to prevent infinit loop if initial_size == len(libs): raise RuntimeError("Imposible to load shared libraries %s" % str(libs)) - initial_size = list(libs) + initial_size = len(libs) + +def load_ns3_module(): + load_ns3_libraries() # import the python bindings for the ns-3 modules + bindings = os.environ.get("NS3BINDINGS") if bindings: sys.path.append(bindings) diff --git a/test/resources/linux/ns3/ns3simulation.py b/test/resources/linux/ns3/ns3simulation.py index e632bcfb..19f2b32e 100644 --- a/test/resources/linux/ns3/ns3simulation.py +++ b/test/resources/linux/ns3/ns3simulation.py @@ -153,6 +153,7 @@ class LinuxNS3ClientTest(unittest.TestCase): ec.set(node, "hostname", "localhost") simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) ec.register_connection(simu, node) nsnode1 = add_ns3_node(ec, simu) @@ -198,6 +199,7 @@ class LinuxNS3ClientTest(unittest.TestCase): #ec.set(node, "cleanHome", True) simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) ec.register_connection(simu, node) nsnode1 = add_ns3_node(ec, simu) @@ -243,6 +245,7 @@ class LinuxNS3ClientTest(unittest.TestCase): #ec.set(node, "cleanHome", True) simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) ec.register_connection(simu, node) nsnode1 = add_ns3_node(ec, simu) @@ -288,6 +291,7 @@ class LinuxNS3ClientTest(unittest.TestCase): #ec.set(node, "cleanHome", True) simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) sources = os.path.join(os.path.dirname(os.path.realpath(__file__)), "ns-3.18-user.tar.gz") ec.set(simu, "sources", sources) @@ -444,6 +448,7 @@ class LinuxNS3ClientTest(unittest.TestCase): #ec.set(node, "cleanHome", True) simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) ec.register_connection(simu, node) nsnode1 = add_ns3_node(ec, simu) @@ -681,7 +686,7 @@ class LinuxNS3ClientTest(unittest.TestCase): """ - ec = ExperimentController(exp_id = "test-ns3-auto-routes") + ec = ExperimentController(exp_id = "test-ns3-dce") node = ec.register_resource("LinuxNode") ec.set(node, "hostname", self.fedora_host) @@ -757,6 +762,65 @@ class LinuxNS3ClientTest(unittest.TestCase): ec.shutdown() + def test_dce(self): + """ + network topology: + n4 + | + n1 -- p2p -- n2 -- csma -- n5 -- p2p -- n6 + | | + ping n6 n3 + + + """ + ec = ExperimentController(exp_id = "test-ns3-dce") + + node = ec.register_resource("LinuxNode") + ec.set(node, "hostname", self.fedora_host) + ec.set(node, "username", self.fedora_user) + ec.set(node, "identity", self.fedora_identity) + ec.set(node, "cleanProcesses", True) + #ec.set(node, "cleanHome", True) + + simu = ec.register_resource("LinuxNS3Simulation") + ec.set(simu, "verbose", True) + ec.set(simu, "enableDCE", True) + ec.register_connection(simu, node) + + nsnode1 = add_ns3_node(ec, simu) + p2p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30") + + nsnode2 = add_ns3_node(ec, simu) + p2p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30") + + # Create channel + chan = ec.register_resource("ns3::PointToPointChannel") + ec.set(chan, "Delay", "0s") + ec.register_connection(chan, p2p1) + ec.register_connection(chan, p2p2) + + ### create pinger + ping = ec.register_resource("ns3::V4Ping") + ec.set (ping, "Remote", "10.0.0.2") + ec.set (ping, "Interval", "1s") + ec.set (ping, "Verbose", True) + ec.set (ping, "StartTime", "1s") + ec.set (ping, "StopTime", "21s") + ec.register_connection(ping, nsnode1) + + ec.deploy() + + ec.wait_finished([ping]) + + stdout = ec.trace(simu, "stdout") + + print stdout + + expected = "20 packets transmitted, 20 received, 0% packet loss" + self.assertTrue(stdout.find(expected) > -1) + + ec.shutdown() + if __name__ == '__main__': unittest.main() -- 2.43.0