From: Alina Quereilhac Date: Sun, 2 Feb 2014 13:33:29 +0000 (+0100) Subject: Adding base RMs for ns-3 X-Git-Tag: nepi-3.1.0~120^2~17 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=f97424b88767d2ec6143e5264a58a740c5330d11;p=nepi.git Adding base RMs for ns-3 --- diff --git a/src/nepi/resources/ns3/ns3application.py b/src/nepi/resources/ns3/ns3application.py new file mode 100644 index 00000000..736dd654 --- /dev/null +++ b/src/nepi/resources/ns3/ns3application.py @@ -0,0 +1,32 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3BaseApplication(NS3Base): + _rtype = "ns3::Application" + + def _connect_object(self): + node = self.node + if node and node.uuid not in self.connected: + self.simulator.invoke(node.uuid, "AddApplication", self.uuid) + self._connected.add(node.uuid) + diff --git a/src/nepi/resources/ns3/ns3base.py b/src/nepi/resources/ns3/ns3base.py index 3ccd138f..f8d7d12d 100644 --- a/src/nepi/resources/ns3/ns3base.py +++ b/src/nepi/resources/ns3/ns3base.py @@ -20,21 +20,101 @@ from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState, reschedule_delay +from nepi.execute.attributes import Flags from nepi.resources.ns3.ns3simulator import NS3Simulator +from nepi.resources.ns3.ns3node import NS3BaseNode @clsinit_copy class NS3Base(ResourceManager): - _rtype = "NS3Base" + _rtype = "ns3::Object" + + def __init__(self): + super(NS3Base, self).__init__() + self._uuid = None + self._connected = set() + + @property + def connected(self): + return self._connected + + @property + def uuid(self): + return self._uuid @property def simulator(self): - simulator = self.get_connected(NS3Simulator.get_rtype()) - if simulator: return simulator[0] + simulators = self.get_connected(NS3Simulator.get_rtype()) + if simulators: return simulators[0] + # if the object is not directly connected to the simulator, + # it should be connected to a node + node = self.node + if node: return node.simulator + return None + + @property + def node(self): + nodes = self.get_connected(NS3BaseNode.get_rtype()) + if nodes: return nodes[0] return None + @property + def others_to_wait(self): + others = set() + node = self.node + if node: others.add(node) + return others + + def _instantiate_object(self): + if self.uuid: + return + + kwargs = dict() + for attr in self._attrs: + if not attr.value or attr.has_flag(Flags.ReadOnly): + continue + + kwargs[attr.name] = attr.value + + self.uuid = self.simulator.factory(self.get_rtype(), **kwargs) + + def _configure_object(self): + pass + + def _connect_object(self): + node = self.node + if node and node.uuid not in self.connected: + self.simulator.invoke(node.uuid, "AggregateObject", self.uuid) + self._connected.add(node.uuid) + + def _wait_others(self): + """ Returns the collection of ns-3 RMs that this RM needs to + wait for before start + + This method should be overriden to wait for other ns-3 + objects to be deployed before proceeding with the deployment + + """ + for other in self.others_to_wait: + if other and other.state < ResourceState.READY: + return True + return False + + def do_provision(self): + # create run dir for ns3 object + # self.simulator.node.mkdir(self.run_home) + + self._instantiate_object() + self._configure_object() + self._connect_object() + + self.info("Provisioning finished") + + super(NS3Base, self).do_provision() + def do_deploy(self): - if not self.simulator or self.simulator.state < ResourceState.READY: - self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.simulator.state ) + if not self.simulator or self.simulator.state < ResourceState.READY or \ + self._wait_others(): + self.debug("---- RESCHEDULING DEPLOY ----" ) # ccnd needs to wait until node is deployed and running self.ec.schedule(reschedule_delay, self.deploy) @@ -48,9 +128,8 @@ class NS3Base(ResourceManager): def do_start(self): if self.state == ResourceState.READY: - ## TODO!!! - self.info("Starting ...") - + # No need to do anything, simulator.Run() will start every object + self.info("Starting") self.set_started() else: msg = " Failed " @@ -59,14 +138,11 @@ class NS3Base(ResourceManager): def do_stop(self): if self.state == ResourceState.STARTED: + # No need to do anything, simulator.Destroy() will stop every object self.info("Stopping command '%s'" % command) - ## TODO!!! - self.set_stopped() @property def state(self): - # First check if the ccnd has failed - # TODO!!! return self._state diff --git a/src/nepi/resources/ns3/ns3channel.py b/src/nepi/resources/ns3/ns3channel.py new file mode 100644 index 00000000..fe628c85 --- /dev/null +++ b/src/nepi/resources/ns3/ns3channel.py @@ -0,0 +1,37 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3device import NS3BaseNetDevice + +@clsinit_copy +class NS3BaseChannel(NS3Base): + _rtype = "ns3::Channel" + + @property + def devices(self): + return self.get_connected(NS3BaseNetDevice.get_rtype()) + + @property + def simulator(self): + devices = self.devices + if devices: return device[0].node.simulator + return None + diff --git a/src/nepi/resources/ns3/ns3client.py b/src/nepi/resources/ns3/ns3client.py index e3a203bd..86bb77bf 100644 --- a/src/nepi/resources/ns3/ns3client.py +++ b/src/nepi/resources/ns3/ns3client.py @@ -25,6 +25,9 @@ class NS3Client(object): def create(self, clazzname, *args): pass + def factory(self, type_name, **kwargs): + pass + def invoke(self, uuid, operation, *args): pass diff --git a/src/nepi/resources/ns3/ns3delay.py b/src/nepi/resources/ns3/ns3delay.py new file mode 100644 index 00000000..e72c974e --- /dev/null +++ b/src/nepi/resources/ns3/ns3delay.py @@ -0,0 +1,52 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3channel import NS3BaseChannel + +@clsinit_copy +class NS3BasePropagationDelayModel(NS3Base): + _rtype = "ns3::PropagationDelayModel" + + @property + def simulator(self): + channel = self.channel + if channel: return channel.simulator + return None + + @property + def channel(self): + channels = self.get_connected(NS3BaseChannel.get_rtype()) + if channels: return channels[0] + return None + + @property + def others_to_wait(self): + others = set() + channel = self.channel + if channel: others.add(channel) + return others + + def _connect_object(self): + channel = self.channel + if channel and channel.uuid not in self.connected: + self.simulator.invoke(channel.uuid, "SetPropagationDelayModel", self.uuid) + self._connected.add(channel.uuid) + diff --git a/src/nepi/resources/ns3/ns3device.py b/src/nepi/resources/ns3/ns3device.py new file mode 100644 index 00000000..98d72022 --- /dev/null +++ b/src/nepi/resources/ns3/ns3device.py @@ -0,0 +1,54 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3channel import NS3Channel + +@clsinit_copy +class NS3BaseNetDevice(NS3Base): + _rtype = "ns3::NetDevice" + + @property + def channel(self): + channels = self.get_connected(NS3BaseChannel.get_rtype()) + if channels: return channels[0] + return None + + @property + def others_to_wait(self): + others = set() + node = self.node + if node: others.add(node) + + channel = self.channel + if channel: others.add(channel) + return others + + def _connect_object(self): + node = self.node + if node and node.uuid not in self.connected: + self.simulator.invoke(node.uuid, "AddDevice", self.uuid) + self._connected.add(node.uuid) + + channel = self.channel + if channel and channel.uuid not in self.connected: + self.simulator.invoke(self.uuid, "Attach", channel.uuid) + self._connected.add(channel.uuid) + diff --git a/src/nepi/resources/ns3/ns3ipv4protocol.py b/src/nepi/resources/ns3/ns3ipv4protocol.py new file mode 100644 index 00000000..81ce0ac5 --- /dev/null +++ b/src/nepi/resources/ns3/ns3ipv4protocol.py @@ -0,0 +1,40 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3BaseIpV4Protocol(Ns3Base): + _rtype = "ns3::IpV4Protocol" + + def do_provision(self): + # create run dir for ns3 object + # self.simulator.node.mkdir(self.run_home) + + self._instantiate_object() + + uuid_list_routing = simulator.create("Ipv4ListRouting") + simulator.invoke(self.uuid, "SetRoutingProtocol", uuid_list_routing) + + uuid_static_routing = simulator.create("Ipv4StaticRouting") + simulator.invoke(self.uuid, "SetRoutingProtocol", uuid_static_routing, 1) + + super(NS3BaseIpV4Protocol, self).do_provision() + diff --git a/src/nepi/resources/ns3/ns3loss.py b/src/nepi/resources/ns3/ns3loss.py new file mode 100644 index 00000000..617f8cfd --- /dev/null +++ b/src/nepi/resources/ns3/ns3loss.py @@ -0,0 +1,52 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3channel import NS3BaseChannel + +@clsinit_copy +class NS3BasePropagationLossModel(NS3Base): + _rtype = "ns3::PropagationLossModel" + + @property + def simulator(self): + channel = self.channel + if channel: return channel.simulator + return None + + @property + def channel(self): + channels = self.get_connected(NS3BaseChannel.get_rtype()) + if channels: return channels[0] + return None + + @property + def others_to_wait(self): + others = set() + channel = self.channel + if channel: others.add(channel) + return others + + def _connect_object(self): + channel = self.channel + if channel and channel.uuid not in self.connected: + self.simulator.invoke(channel.uuid, "SetPropagationLossModel", self.uuid) + self._connected.add(channel.uuid) + diff --git a/src/nepi/resources/ns3/ns3manager.py b/src/nepi/resources/ns3/ns3manager.py new file mode 100644 index 00000000..f5c8c015 --- /dev/null +++ b/src/nepi/resources/ns3/ns3manager.py @@ -0,0 +1,52 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3device import NS3BaseDevice + +@clsinit_copy +class NS3BaseWifiRemoteStationManager(NS3Base): + _rtype = "ns3::WifiRemoteStationManager" + + @property + def device(self): + devices = self.get_connected(NS3BaseDevice.get_rtype()) + if devices: return devices[0] + return None + + @property + def node(self): + device = self.device + if device: return device.node + return None + + @property + def others_to_wait(self): + others = set() + device = self.device + if device: others.add(device) + return others + + def _connect_object(self): + device = self.device + if device and device.uuid not in self.connected: + self.simulator.invoke(device.uuid, "SetRemoteStationManager", self.uuid) + self._connected.add(device.uuid) + diff --git a/src/nepi/resources/ns3/ns3node.py b/src/nepi/resources/ns3/ns3node.py new file mode 100644 index 00000000..0e78bb09 --- /dev/null +++ b/src/nepi/resources/ns3/ns3node.py @@ -0,0 +1,35 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3BaseNode(Ns3Base): + _rtype = "ns3::Node" + + @property + def others_to_wait(self): + return set() + + def _configure_object(self): + ### node.AggregateObject(PacketSocketFactory()) + uuid_packet_socket_factory = self.simulator.create("PacketSocketFactory") + self.simulator.invoke(self.uuid, "AggregateObject", uuid_packet_socket_factory) + diff --git a/src/nepi/resources/ns3/ns3queue.py b/src/nepi/resources/ns3/ns3queue.py new file mode 100644 index 00000000..4a2b66bb --- /dev/null +++ b/src/nepi/resources/ns3/ns3queue.py @@ -0,0 +1,52 @@ +# +# NEPI, a framework to manage network experiments +# Copyright (C) 2014 INRIA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# 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: Alina Quereilhac + +from nepi.execution.resource import clsinit_copy +from nepi.resources.ns3.ns3base import NS3Base +from nepi.resources.ns3.ns3device import NS3BaseNetDevice + +@clsinit_copy +class NS3BaseQueue(NS3Base): + _rtype = "ns3::Queue" + + @property + def device(self): + devices = self.get_connected(NS3BaseNetDevice.get_rtype()) + if devices: return devices[0] + return None + + @property + def node(self): + device = self.device + if device: return device.node + return None + + @property + def others_to_wait(self): + others = set() + device = self.device + if device: others.add(device) + return others + + def _connect_object(self): + device = self.device + if device and device.uuid not in self.connected: + self.simulator.invoke(device.uuid, "SetQueue", self.uuid) + self._connected.add(device.uuid) + diff --git a/src/nepi/resources/ns3/ns3server.py b/src/nepi/resources/ns3/ns3server.py index f538259a..b6df768a 100644 --- a/src/nepi/resources/ns3/ns3server.py +++ b/src/nepi/resources/ns3/ns3server.py @@ -27,6 +27,7 @@ from ns3wrapper import NS3Wrapper class NS3WrapperMessage: CREATE = "CREATE" + FACTORY = "FACTORY" INVOKE = "INVOKE" SET = "SET" GET = "GET" @@ -58,6 +59,13 @@ def handle_message(ns3_wrapper, msg, args): uuid = ns3_wrapper.create(clazzname, *args) return uuid + if msg == NS3WrapperMessage.FACTORY: + type_name = args.pop(0) + kwargs = args.pop(0) + + uuid = ns3_wrapper.factory(type_name, **kwargs) + return uuid + if msg == NS3WrapperMessage.INVOKE: uuid = args.pop(0) operation = args.pop(0) diff --git a/src/nepi/resources/ns3/ns3simulator.py b/src/nepi/resources/ns3/ns3simulator.py index 1c557e7b..d0f14189 100644 --- a/src/nepi/resources/ns3/ns3simulator.py +++ b/src/nepi/resources/ns3/ns3simulator.py @@ -25,6 +25,9 @@ class NS3Simulator(object): def create(self, clazzname, *args): return self.client.create(clazzname, *args) + def factory(self, type_name, **kwargs): + return self.client.factory(type_name, **kwargs) + def invoke(self, uuid, operation, *args): return self.client.invoke(uuid, operation, *args) diff --git a/src/nepi/resources/ns3/ns3wrapper.py b/src/nepi/resources/ns3/ns3wrapper.py index 0c58df08..064b32ce 100644 --- a/src/nepi/resources/ns3/ns3wrapper.py +++ b/src/nepi/resources/ns3/ns3wrapper.py @@ -179,7 +179,7 @@ class NS3Wrapper(object): def get_object(self, uuid): return self._objects.get(uuid) - def factory(self, type_name, *kwargs): + def factory(self, type_name, **kwargs): if type_name not in allowed_types: msg = "Type %s not supported" % (type_name) self.logger.error(msg) diff --git a/src/nepi/resources/ns3/resource_manager_generator.py b/src/nepi/resources/ns3/resource_manager_generator.py index f5d4acc6..4042bf87 100644 --- a/src/nepi/resources/ns3/resource_manager_generator.py +++ b/src/nepi/resources/ns3/resource_manager_generator.py @@ -23,6 +23,51 @@ from nepi.resources.ns3.ns3wrapper import load_ns3_module import os import re +def select_base_class(ns3, tid): + rtype = tid.GetName() + + type_id = ns3.TypeId() + appbase = type_id.LookupByName("ns3::Application") + devicebase = type_id.LookupByName("ns3::NetDevice") + channelbase = type_id.LookupByName("ns3::Channel") + queuebase = type_id.LookupByName("ns3::Queue") + lossbase = type_id.LookupByName("ns3::PropagationLossModel") + delaybase = type_id.LookupByName("ns3::PropagationDelayModel") + managerbase = type_id.LookupByName("ns3::WifiRemoteStationManager") + + if tid.IsChiledOf(appbase): + base_class_import = "from nepi.resources.ns3.ns3application import NS3BaseApplication" + base_class = "NS3BaseApplication" + elif tid.IsChiledOf(devicebase): + base_class_import = "from nepi.resources.ns3.ns3device import NS3BaseNetDevice" + base_class = "NS3BaseNetDevice" + elif tid.IsChiledOf(channelbase): + base_class_import = "from nepi.resources.ns3.ns3channel import NS3BaseChannel" + base_class = "NS3BaseChannel" + elif tid.IsChiledOf(queuebase): + base_class_import = "from nepi.resources.ns3.ns3queue import NS3BaseQueue" + base_class = "NS3BaseQueue" + elif tid.IsChiledOf(lossbase): + base_class_import = "from nepi.resources.ns3.ns3loss import NS3BasePropagationLossModel" + base_class = "NS3BasePropagationLossDelay" + elif tid.IsChiledOf(delaybase): + base_class_import = "from nepi.resources.ns3.ns3delay import NS3BasePropagationDelayModel" + base_class = "NS3BasePropagationDelayModel" + elif tid.IsChiledOf(managerbase): + base_class_import = "from nepi.resources.ns3.ns3manager import NS3BaseWifiRemoteStationManager" + base_class = "NS3BaseWifiRemoteStationManager" + elif rtype == "ns3::Node": + base_class_import = "from nepi.resources.ns3.ns3node import NS3BaseNode" + base_class = "NS3BaseNode" + elif rtype == "ns3::Ipv4L3Protocol": + base_class_import = "from nepi.resources.ns3.ns3ipv4protocol import NS3BaseIpV4Protocol" + base_class = "NS3BaseIpV4Protocol" + else: + base_class_import = "from nepi.resources.ns3.ns3base import NS3Base" + base_class = "NS3Base" + + return (base_class_import, base_class) + def create_ns3_rms(): ns3 = load_ns3_module() @@ -51,12 +96,11 @@ def create_ns3_rms(): attributes = "\n" + attributes if attributes else "pass" traces = "\n" + traces if traces else "pass" + (base_class_import, base_class) = select_base_class(ns3, tid) + rtype = tid.GetName() category = tid.GetGroupName() - base_class_import = "from nepi.resources.ns3.ns3base import NS3Base" - base_clas = "NS3Base" - classname = rtype.replace("ns3::", "NS3").replace("::","") uncamm_rtype = re.sub('([a-z])([A-Z])', r'\1-\2', rtype).lower() short_rtype = uncamm_rtype.replace("::","-")