From a40af793891b118dba150fa11c0c6875fabc7b09 Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Mon, 24 Feb 2014 18:42:45 +0100 Subject: [PATCH] Fix #143 - [NS3] Integrate DCE bindings --- src/nepi/resources/linux/ns3/ns3simulation.py | 24 +- .../resources/ns3/classes/dce_application.py | 65 +++ .../resources/ns3/classes/dsrdsr_routing.py | 449 ++++++++++++++++++ .../resources/ns3/classes/icmpv6l4protocol.py | 70 +++ .../resources/ns3/classes/tcp_l4protocol.py | 70 +++ .../resources/ns3/classes/udp_l4protocol.py | 50 ++ .../resources/ns3/classes/wifi_net_device.py | 4 +- .../ns3/classes/yans_wifi_channel.py | 4 +- src/nepi/resources/ns3/ns3dceapplication.py | 102 ++++ src/nepi/resources/ns3/ns3node.py | 31 +- .../ns3/resource_manager_generator.py | 36 +- test/resources/linux/ns3/ns3simulation.py | 56 ++- 12 files changed, 884 insertions(+), 77 deletions(-) create mode 100644 src/nepi/resources/ns3/classes/dce_application.py create mode 100644 src/nepi/resources/ns3/classes/dsrdsr_routing.py create mode 100644 src/nepi/resources/ns3/classes/icmpv6l4protocol.py create mode 100644 src/nepi/resources/ns3/classes/tcp_l4protocol.py create mode 100644 src/nepi/resources/ns3/classes/udp_l4protocol.py create mode 100644 src/nepi/resources/ns3/ns3dceapplication.py diff --git a/src/nepi/resources/linux/ns3/ns3simulation.py b/src/nepi/resources/linux/ns3/ns3simulation.py index 5745f543..f4a5a6b8 100644 --- a/src/nepi/resources/linux/ns3/ns3simulation.py +++ b/src/nepi/resources/linux/ns3/ns3simulation.py @@ -119,6 +119,8 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): self._client = None self._home = "ns3-simu-%s" % self.guid self._socket_name = "ns3-%s.sock" % os.urandom(4).encode('hex') + self._dce_helper_uuid = None + self._dce_application_helper_uuid = None @property def socket_name(self): @@ -128,6 +130,14 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): def remote_socket(self): return os.path.join(self.run_home, self.socket_name) + @property + def dce_helper_uuid(self): + return self._dce_helper_uuid + + @property + def dce_application_helper_uuid(self): + return self._dce_application_helper_uuid + @property def ns3_build_home(self): return os.path.join(self.node.bin_dir, "ns-3", self.get("ns3Version"), @@ -207,6 +217,10 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): sched_type = self.get("schedulerType") stype = self.create("StringValue", sched_type) self.invoke(GLOBAL_VALUE_UUID, "Bind", "SchedulerType", btrue) + + if self.get("enableDCE"): + self._dce_helper_uuid = self.create("DceManagerHelper") + self._dce_application_helper_uuid = self.create("DceApplicationHelper") def do_deploy(self): if not self.node or self.node.state < ResourceState.READY: @@ -302,7 +316,7 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): ns_log = self.get("nsLog") if ns_log: - command.append("-L %s" % ns_log) + command.append("-L '%s'" % ns_log) if self.get("verbose"): command.append("-v") @@ -464,16 +478,18 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): " ( " # 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 " + " ./waf configure %(enable_opt)s --with-pybindgen=${SRC}/pybindgen/%(pybindgen_version)s " " --prefix=%(ns3_build_home)s --with-ns3=%(ns3_build_home)s && " " ./waf build && " - " ./waf install " + " ./waf install && " + " mv %(ns3_build_home)s/lib/python*/site-packages/ns/dce.so %(ns3_build_home)s/lib/python/site-packages/ns/ " " )" ) % { 'ns3_version': self.get("ns3Version"), 'pybindgen_version': self.get("pybindgenVersion"), 'ns3_build_home': self.ns3_build_home, 'build_mode': self.get("buildMode"), + 'enable_opt': "--enable-opt" if self.get("buildMode") == "optimized" else "" } return ( @@ -517,6 +533,8 @@ class LinuxNS3Simulation(LinuxApplication, NS3Simulation): env.append("LD_LIBRARY_PATH=${NS3LIBRARIES:=%(ns3_build_home)s/lib/}" % { 'ns3_build_home': self.ns3_build_home }) + env.append("DCE_PATH=$PATH:$NS3LIBRARIES/../bin_dce") + env.append("DCE_ROOT=$PATH:$NS3LIBRARIES/..") return " ".join(env) diff --git a/src/nepi/resources/ns3/classes/dce_application.py b/src/nepi/resources/ns3/classes/dce_application.py new file mode 100644 index 00000000..9b42c54e --- /dev/null +++ b/src/nepi/resources/ns3/classes/dce_application.py @@ -0,0 +1,65 @@ +# +# 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 . +# + +from nepi.execution.attribute import Attribute, Flags, Types +from nepi.execution.trace import Trace, TraceAttr +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay +from nepi.resources.ns3.ns3dceapplication import NS3BaseDceApplication + +@clsinit_copy +class NS3DceApplication(NS3BaseDceApplication): + _rtype = "ns3::DceApplication" + + @classmethod + def _register_attributes(cls): + + attr_starttime = Attribute("StartTime", + "Time at which the application will start", + type = Types.String, + default = "+0.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_starttime) + + attr_stoptime = Attribute("StopTime", + "Time at which the application will stop", + type = Types.String, + default = "+0.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_stoptime) + + + + @classmethod + def _register_traces(cls): + + processstarted = Trace("ProcessStarted", "notify when the dce is started") + + cls._register_trace(processstarted) + + + + def __init__(self, ec, guid): + super(NS3DceApplication, self).__init__(ec, guid) + self._home = "ns3-dce-application-%s" % self.guid diff --git a/src/nepi/resources/ns3/classes/dsrdsr_routing.py b/src/nepi/resources/ns3/classes/dsrdsr_routing.py new file mode 100644 index 00000000..e6f83ffa --- /dev/null +++ b/src/nepi/resources/ns3/classes/dsrdsr_routing.py @@ -0,0 +1,449 @@ +# +# 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 . +# + +from nepi.execution.attribute import Attribute, Flags, Types +from nepi.execution.trace import Trace, TraceAttr +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3dsrDsrRouting(NS3Base): + _rtype = "ns3::dsr::DsrRouting" + + @classmethod + def _register_attributes(cls): + + attr_maxsendbufflen = Attribute("MaxSendBuffLen", + "Maximum number of packets that can be stored in send buffer.", + type = Types.Integer, + default = "64", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxsendbufflen) + + attr_maxsendbufftime = Attribute("MaxSendBuffTime", + "Maximum time packets can be queued in the send buffer .", + type = Types.String, + default = "+30000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxsendbufftime) + + attr_maxmaintlen = Attribute("MaxMaintLen", + "Maximum number of packets that can be stored in maintenance buffer.", + type = Types.Integer, + default = "50", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxmaintlen) + + attr_maxmainttime = Attribute("MaxMaintTime", + "Maximum time packets can be queued in maintenance buffer.", + type = Types.String, + default = "+30000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxmainttime) + + attr_maxcachelen = Attribute("MaxCacheLen", + "Maximum number of route entries that can be stored in route cache.", + type = Types.Integer, + default = "64", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxcachelen) + + attr_routecachetimeout = Attribute("RouteCacheTimeout", + "Maximum time the route cache can be queued in route cache.", + type = Types.String, + default = "+300000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_routecachetimeout) + + attr_maxentrieseachdst = Attribute("MaxEntriesEachDst", + "Maximum number of route entries for a single destination to respond.", + type = Types.Integer, + default = "20", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxentrieseachdst) + + attr_sendbuffinterval = Attribute("SendBuffInterval", + "How often to check send buffer for packet with route.", + type = Types.String, + default = "+500000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_sendbuffinterval) + + attr_nodetraversaltime = Attribute("NodeTraversalTime", + "The time it takes to traverse two neighboring nodes.", + type = Types.String, + default = "+40000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_nodetraversaltime) + + attr_rreqretries = Attribute("RreqRetries", + "Maximum number of retransmissions for request discovery of a route.", + type = Types.Integer, + default = "16", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_rreqretries) + + attr_maintenanceretries = Attribute("MaintenanceRetries", + "Maximum number of retransmissions for data packets from maintenance buffer.", + type = Types.Integer, + default = "2", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maintenanceretries) + + attr_requesttablesize = Attribute("RequestTableSize", + "Maximum number of request entries in the request table, set this as the number of nodes in the simulation.", + type = Types.Integer, + default = "64", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_requesttablesize) + + attr_requestidsize = Attribute("RequestIdSize", + "Maximum number of request source Ids in the request table.", + type = Types.Integer, + default = "16", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_requestidsize) + + attr_uniquerequestidsize = Attribute("UniqueRequestIdSize", + "Maximum number of request Ids in the request table for a single destination.", + type = Types.Integer, + default = "256", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_uniquerequestidsize) + + attr_nonproprequesttimeout = Attribute("NonPropRequestTimeout", + "The timeout value for non-propagation request.", + type = Types.String, + default = "+30000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_nonproprequesttimeout) + + attr_discoveryhoplimit = Attribute("DiscoveryHopLimit", + "The max discovery hop limit for route requests.", + type = Types.Integer, + default = "255", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_discoveryhoplimit) + + attr_maxsalvagecount = Attribute("MaxSalvageCount", + "The max salvage count for a single data packet.", + type = Types.Integer, + default = "15", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxsalvagecount) + + attr_blacklisttimeout = Attribute("BlacklistTimeout", + "The time for a neighbor to stay in blacklist.", + type = Types.String, + default = "+3000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_blacklisttimeout) + + attr_gratreplyholdoff = Attribute("GratReplyHoldoff", + "The time for gratuitous reply entry to expire.", + type = Types.String, + default = "+1000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_gratreplyholdoff) + + attr_broadcastjitter = Attribute("BroadcastJitter", + "The jitter time to avoid collision for broadcast packets.", + type = Types.Integer, + default = "10", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_broadcastjitter) + + attr_linkacktimeout = Attribute("LinkAckTimeout", + "The time a packet in maintenance buffer wait for link acknowledgment.", + type = Types.String, + default = "+100000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_linkacktimeout) + + attr_trylinkacks = Attribute("TryLinkAcks", + "The number of link acknowledgment to use.", + type = Types.Integer, + default = "1", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_trylinkacks) + + attr_passiveacktimeout = Attribute("PassiveAckTimeout", + "The time a packet in maintenance buffer wait for passive acknowledgment.", + type = Types.String, + default = "+100000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_passiveacktimeout) + + attr_trypassiveacks = Attribute("TryPassiveAcks", + "The number of passive acknowledgment to use.", + type = Types.Integer, + default = "1", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_trypassiveacks) + + attr_requestperiod = Attribute("RequestPeriod", + "The base time interval between route requests.", + type = Types.String, + default = "+500000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_requestperiod) + + attr_maxrequestperiod = Attribute("MaxRequestPeriod", + "The max time interval between route requests.", + type = Types.String, + default = "+10000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxrequestperiod) + + attr_grareplytablesize = Attribute("GraReplyTableSize", + "The gratuitous reply table size.", + type = Types.Integer, + default = "64", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_grareplytablesize) + + attr_cachetype = Attribute("CacheType", + "Use Link Cache or use Path Cache", + type = Types.String, + default = "LinkCache", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_cachetype) + + attr_stabilitydecrfactor = Attribute("StabilityDecrFactor", + "The stability decrease factor for link cache", + type = Types.Integer, + default = "2", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_stabilitydecrfactor) + + attr_stabilityincrfactor = Attribute("StabilityIncrFactor", + "The stability increase factor for link cache", + type = Types.Integer, + default = "4", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_stabilityincrfactor) + + attr_initstability = Attribute("InitStability", + "The initial stability factor for link cache", + type = Types.String, + default = "+25000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_initstability) + + attr_minlifetime = Attribute("MinLifeTime", + "The minimal life time for link cache", + type = Types.String, + default = "+1000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_minlifetime) + + attr_useextends = Attribute("UseExtends", + "The extension time for link cache", + type = Types.String, + default = "+120000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_useextends) + + attr_enablesubroute = Attribute("EnableSubRoute", + "Enables saving of sub route when receiving route error messages, only available when using path route cache", + type = Types.Bool, + default = "True", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_enablesubroute) + + attr_retransincr = Attribute("RetransIncr", + "The increase time for retransmission timer when facing network congestion", + type = Types.String, + default = "+20000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_retransincr) + + attr_maxnetworkqueuesize = Attribute("MaxNetworkQueueSize", + "The max number of packet to save in the network queue.", + type = Types.Integer, + default = "400", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxnetworkqueuesize) + + attr_maxnetworkqueuedelay = Attribute("MaxNetworkQueueDelay", + "The max time for a packet to stay in the network queue.", + type = Types.String, + default = "+30000000000.0ns", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_maxnetworkqueuedelay) + + attr_numpriorityqueues = Attribute("NumPriorityQueues", + "The max number of packet to save in the network queue.", + type = Types.Integer, + default = "2", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_numpriorityqueues) + + attr_linkacknowledgment = Attribute("LinkAcknowledgment", + "Enable Link layer acknowledgment mechanism", + type = Types.Bool, + default = "False", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_linkacknowledgment) + + attr_protocolnumber = Attribute("ProtocolNumber", + "The Ip protocol number.", + type = Types.Integer, + default = "0", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_protocolnumber) + + + + @classmethod + def _register_traces(cls): + + tx = Trace("Tx", "Send DSR packet.") + + cls._register_trace(tx) + + drop = Trace("Drop", "Drop DSR packet") + + cls._register_trace(drop) + + + + def __init__(self, ec, guid): + super(NS3dsrDsrRouting, self).__init__(ec, guid) + self._home = "ns3-dsr-dsr-routing-%s" % self.guid diff --git a/src/nepi/resources/ns3/classes/icmpv6l4protocol.py b/src/nepi/resources/ns3/classes/icmpv6l4protocol.py new file mode 100644 index 00000000..23e37b12 --- /dev/null +++ b/src/nepi/resources/ns3/classes/icmpv6l4protocol.py @@ -0,0 +1,70 @@ +# +# 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 . +# + +from nepi.execution.attribute import Attribute, Flags, Types +from nepi.execution.trace import Trace, TraceAttr +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3Icmpv6L4Protocol(NS3Base): + _rtype = "ns3::Icmpv6L4Protocol" + + @classmethod + def _register_attributes(cls): + + attr_dad = Attribute("DAD", + "Always do DAD check.", + type = Types.Bool, + default = "True", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_dad) + + attr_solicitationjitter = Attribute("SolicitationJitter", + "The jitter in ms a node is allowed to wait before sending any solicitation . Some jitter aims to prevent collisions. By default, the model will wait for a duration in ms defined by a uniform random-variable between 0 and SolicitationJitter", + type = Types.String, + default = "ns3::UniformRandomVariable[Min=0.0|Max=10.0]", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_solicitationjitter) + + attr_protocolnumber = Attribute("ProtocolNumber", + "The Ip protocol number.", + type = Types.Integer, + default = "0", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_protocolnumber) + + + + @classmethod + def _register_traces(cls): + pass + + def __init__(self, ec, guid): + super(NS3Icmpv6L4Protocol, self).__init__(ec, guid) + self._home = "ns3-icmpv6l4protocol-%s" % self.guid diff --git a/src/nepi/resources/ns3/classes/tcp_l4protocol.py b/src/nepi/resources/ns3/classes/tcp_l4protocol.py new file mode 100644 index 00000000..ef21f8f8 --- /dev/null +++ b/src/nepi/resources/ns3/classes/tcp_l4protocol.py @@ -0,0 +1,70 @@ +# +# 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 . +# + +from nepi.execution.attribute import Attribute, Flags, Types +from nepi.execution.trace import Trace, TraceAttr +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3TcpL4Protocol(NS3Base): + _rtype = "ns3::TcpL4Protocol" + + @classmethod + def _register_attributes(cls): + + attr_rttestimatortype = Attribute("RttEstimatorType", + "Type of RttEstimator objects.", + type = Types.String, + default = "ns3::RttMeanDeviation", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_rttestimatortype) + + attr_sockettype = Attribute("SocketType", + "Socket type of TCP objects.", + type = Types.String, + default = "ns3::TcpNewReno", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_sockettype) + + attr_protocolnumber = Attribute("ProtocolNumber", + "The Ip protocol number.", + type = Types.Integer, + default = "0", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_protocolnumber) + + + + @classmethod + def _register_traces(cls): + pass + + def __init__(self, ec, guid): + super(NS3TcpL4Protocol, self).__init__(ec, guid) + self._home = "ns3-tcp-l4protocol-%s" % self.guid diff --git a/src/nepi/resources/ns3/classes/udp_l4protocol.py b/src/nepi/resources/ns3/classes/udp_l4protocol.py new file mode 100644 index 00000000..c81c1621 --- /dev/null +++ b/src/nepi/resources/ns3/classes/udp_l4protocol.py @@ -0,0 +1,50 @@ +# +# 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 . +# + +from nepi.execution.attribute import Attribute, Flags, Types +from nepi.execution.trace import Trace, TraceAttr +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState, reschedule_delay +from nepi.resources.ns3.ns3base import NS3Base + +@clsinit_copy +class NS3UdpL4Protocol(NS3Base): + _rtype = "ns3::UdpL4Protocol" + + @classmethod + def _register_attributes(cls): + + attr_protocolnumber = Attribute("ProtocolNumber", + "The Ip protocol number.", + type = Types.Integer, + default = "0", + allowed = None, + range = None, + flags = Flags.Reserved | Flags.Construct) + + cls._register_attribute(attr_protocolnumber) + + + + @classmethod + def _register_traces(cls): + pass + + def __init__(self, ec, guid): + super(NS3UdpL4Protocol, self).__init__(ec, guid) + self._home = "ns3-udp-l4protocol-%s" % self.guid diff --git a/src/nepi/resources/ns3/classes/wifi_net_device.py b/src/nepi/resources/ns3/classes/wifi_net_device.py index 92dd859b..f4f73454 100644 --- a/src/nepi/resources/ns3/classes/wifi_net_device.py +++ b/src/nepi/resources/ns3/classes/wifi_net_device.py @@ -20,10 +20,10 @@ from nepi.execution.attribute import Attribute, Flags, Types from nepi.execution.trace import Trace, TraceAttr from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState, reschedule_delay -from nepi.resources.ns3.ns3wifinetdevice import NS3BaseWifiNetDevice +from nepi.resources.ns3.ns3netdevice import NS3BaseNetDevice @clsinit_copy -class NS3WifiNetDevice(NS3BaseWifiNetDevice): +class NS3WifiNetDevice(NS3BaseNetDevice): _rtype = "ns3::WifiNetDevice" @classmethod diff --git a/src/nepi/resources/ns3/classes/yans_wifi_channel.py b/src/nepi/resources/ns3/classes/yans_wifi_channel.py index 314d391a..325c29b9 100644 --- a/src/nepi/resources/ns3/classes/yans_wifi_channel.py +++ b/src/nepi/resources/ns3/classes/yans_wifi_channel.py @@ -20,10 +20,10 @@ from nepi.execution.attribute import Attribute, Flags, Types from nepi.execution.trace import Trace, TraceAttr from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState, reschedule_delay -from nepi.resources.ns3.ns3wifichannel import NS3BaseWifiChannel +from nepi.resources.ns3.ns3channel import NS3BaseChannel @clsinit_copy -class NS3YansWifiChannel(NS3BaseWifiChannel): +class NS3YansWifiChannel(NS3BaseChannel): _rtype = "ns3::YansWifiChannel" @classmethod diff --git a/src/nepi/resources/ns3/ns3dceapplication.py b/src/nepi/resources/ns3/ns3dceapplication.py new file mode 100644 index 00000000..5d34e848 --- /dev/null +++ b/src/nepi/resources/ns3/ns3dceapplication.py @@ -0,0 +1,102 @@ +# +# 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.attribute import Attribute, Flags, Types +from nepi.execution.resource import clsinit_copy, ResourceState, reschedule_delay +from nepi.resources.ns3.ns3application import NS3BaseApplication + +@clsinit_copy +class NS3BaseDceApplication(NS3BaseApplication): + _rtype = "abstract::ns3::DceApplication" + + @classmethod + def _register_attributes(cls): + binary = Attribute("binary", + "Name of binary to execute", + flags = Flags.Design) + + stack_size = Attribute("stackSize", + "Stack Size for DCE", + type = Types.Integer, + default = 1<<20, + flags = Flags.Design) + + arguments = Attribute("arguments", + "Semi-colon separated list of arguments for the application", + flags = Flags.Design) + + cls._register_attribute(binary) + cls._register_attribute(stack_size) + cls._register_attribute(arguments) + + @property + def node(self): + from nepi.resources.ns3.ns3node import NS3BaseNode + nodes = self.get_connected(NS3BaseNode.get_rtype()) + + if not nodes: + msg = "DceApplication not connected to node" + self.error(msg) + raise RuntimeError, msg + + if nodes[0].get("enableDCE") == False: + raise RuntimeError("DceApplication not connected to DCE enabled node") + + return nodes[0] + + def _connect_object(self): + node = self.node + if node.uuid not in self.connected: + self._connected.add(node.uuid) + self.simulation.invoke(self.simulation.dce_application_helper_uuid, + "ResetArguments") + + self.simulation.invoke(self.simulation.dce_application_helper_uuid, + "SetBinary", self.get("binary")) + + self.simulation.invoke(self.simulation.dce_application_helper_uuid, + "SetStackSize", self.get("stackSize")) + + arguments = self.get("arguments") or "" + for arg in map(str.strip, arguments.split(";")): + self.simulation.invoke(self.simulation.dce_application_helper_uuid, + "AddArgument", arg) + + apps_uuid = self.simulation.invoke(self.simulation.dce_application_helper_uuid, + "InstallInNode", self.node.uuid) + + #start_time = self.get("StartTime") + #time_uuid = self.simulation.create("Time", start_time) + #self.simulation.invoke(apps_uuid, "Start", time_uuid) + + def do_stop(self): + if self.state == ResourceState.STARTED: + # No need to do anything, simulation.Destroy() will stop every object + self.info("Stopping command '%s'" % command) + self.simulation.invoke(self.uuid, "Stop") + self.set_stopped() + + def do_start(self): + if self.simulation.state < ResourceState.STARTED: + self.debug("---- RESCHEDULING START ----" ) + self.ec.schedule(reschedule_delay, self.start) + else: + super(NS3BaseApplication, self).do_start() + self._start_time = self.simulation.start_time + diff --git a/src/nepi/resources/ns3/ns3node.py b/src/nepi/resources/ns3/ns3node.py index 491cd917..dded05ff 100644 --- a/src/nepi/resources/ns3/ns3node.py +++ b/src/nepi/resources/ns3/ns3node.py @@ -106,31 +106,8 @@ class NS3BaseNode(NS3Base): 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 + container_uuid = self.simulation.create("NodeContainer") + self.simulation.invoke(container_uuid, "Add", self.uuid) + self.simulation.invoke(self.simulation.dce_helper_uuid, "Install", + container_uuid) diff --git a/src/nepi/resources/ns3/resource_manager_generator.py b/src/nepi/resources/ns3/resource_manager_generator.py index 9ec844e9..5eae3c82 100644 --- a/src/nepi/resources/ns3/resource_manager_generator.py +++ b/src/nepi/resources/ns3/resource_manager_generator.py @@ -23,8 +23,9 @@ from nepi.resources.ns3.ns3wrapper import load_ns3_module import os import re -base_types = ["ns3::Node", +adapted_types = ["ns3::Node", "ns3::Application", + #"ns3::DceApplication", "ns3::NetDevice", "ns3::Channel", "ns3::Queue", @@ -42,34 +43,34 @@ base_types = ["ns3::Node", "ns3::ErrorModel", "ns3::ErrorRateModel"] -def discard(ns3, tid): - rtype = tid.GetName() - type_id = ns3.TypeId() - - for type_name in base_types: - tid_base = type_id.LookupByName(type_name) - if type_name == rtype or tid.IsChildOf(tid_base): - return False - - return True +base_types = ["ns3::IpL4Protocol"] def select_base_class(ns3, tid): - base_class_import = "from nepi.resources.ns3.ns3base import NS3Base" - base_class = "NS3Base" + base_class_import = None + base_class = None rtype = tid.GetName() type_id = ns3.TypeId() - for type_name in base_types: + for type_name in adapted_types: tid_base = type_id.LookupByName(type_name) if type_name == rtype or tid.IsChildOf(tid_base): base_class = "NS3Base" + type_name.replace("ns3::", "") base_module = "ns3" + type_name.replace("ns3::", "").lower() base_class_import = "from nepi.resources.ns3.%s import %s " % ( base_module, base_class) + return (base_class_import, base_class) - return (base_class_import, base_class) + base_class_import = "from nepi.resources.ns3.ns3base import NS3Base" + base_class = "NS3Base" + + for type_name in base_types: + tid_base = type_id.LookupByName(type_name) + if type_name == rtype or tid.IsChildOf(tid_base): + return (base_class_import, base_class) + + return (None, None) def create_ns3_rms(): ns3 = load_ns3_module() @@ -83,7 +84,8 @@ def create_ns3_rms(): for i in xrange(tid_count): tid = type_id.GetRegistered(i) - if discard(ns3, tid): + (base_class_import, base_class) = select_base_class(ns3, tid) + if not base_class: continue if tid.MustHideFromDocumentation() or \ @@ -102,8 +104,6 @@ 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) - category = tid.GetGroupName() rtype = tid.GetName() diff --git a/test/resources/linux/ns3/ns3simulation.py b/test/resources/linux/ns3/ns3simulation.py index 19f2b32e..d5cec09b 100644 --- a/test/resources/linux/ns3/ns3simulation.py +++ b/test/resources/linux/ns3/ns3simulation.py @@ -49,6 +49,9 @@ def add_ns3_node(ec, simu): icmp = ec.register_resource("ns3::Icmpv4L4Protocol") ec.register_connection(node, icmp) + udp = ec.register_resource("ns3::UdpL4Protocol") + ec.register_connection(node, udp) + return node def add_point2point_device(ec, node, address = None, prefix = None): @@ -763,16 +766,6 @@ 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") @@ -785,39 +778,52 @@ class LinuxNS3ClientTest(unittest.TestCase): simu = ec.register_resource("LinuxNS3Simulation") ec.set(simu, "verbose", True) ec.set(simu, "enableDCE", True) + ec.set(simu, "buildMode", "debug") + ec.set(simu, "nsLog", "DceApplication") ec.register_connection(simu, node) nsnode1 = add_ns3_node(ec, simu) + ec.set(nsnode1, "enableDCE", True) p2p1 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30") + ec.set(p2p1, "DataRate", "5Mbps") nsnode2 = add_ns3_node(ec, simu) + ec.set(nsnode2, "enableDCE", True) p2p2 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30") + ec.set(p2p2, "DataRate", "5Mbps") # Create channel chan = ec.register_resource("ns3::PointToPointChannel") - ec.set(chan, "Delay", "0s") + ec.set(chan, "Delay", "2ms") + 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) + ### create applications + udp_perf = ec.register_resource("ns3::DceApplication") + ec.set (udp_perf, "binary", "udp-perf") + ec.set (udp_perf, "stackSize", 1<<20) + ec.set (udp_perf, "arguments", "--duration=10;--nodes=2") + ec.set (udp_perf, "StartTime", "1s") + ec.set (udp_perf, "StopTime", "20s") + ec.register_connection(udp_perf, nsnode1) + + udp_perf_client = ec.register_resource("ns3::DceApplication") + ec.set (udp_perf_client, "binary", "udp-perf") + ec.set (udp_perf_client, "stackSize", 1<<20) + ec.set (udp_perf_client, "arguments", "--client;--nodes=2;--host=10.0.0.1;--duration=10") + ec.set (udp_perf_client, "StartTime", "2s") + ec.set (udp_perf_client, "StopTime", "20s") + ec.register_connection(udp_perf_client, nsnode2) ec.deploy() - ec.wait_finished([ping]) + ec.wait_finished([udp_perf_client]) - stdout = ec.trace(simu, "stdout") - - print stdout + stderr = ec.trace(simu, "stderr") - expected = "20 packets transmitted, 20 received, 0% packet loss" - self.assertTrue(stdout.find(expected) > -1) + expected = "DceApplication:StartApplication" + self.assertTrue(stderr.find(expected) > -1) ec.shutdown() -- 2.43.0