routing support added for ns3 testbed
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Fri, 25 Mar 2011 17:15:24 +0000 (18:15 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Fri, 25 Mar 2011 17:15:24 +0000 (18:15 +0100)
src/nepi/core/execute.py
src/nepi/core/metadata.py
src/nepi/core/testbed_impl.py
src/nepi/testbeds/netns/execute.py
src/nepi/testbeds/netns/metadata_v01.py
src/nepi/testbeds/ns3/execute.py
src/nepi/testbeds/ns3/factories_metadata_v3_9_RC3.py
src/nepi/testbeds/ns3/metadata_v3_9_RC3.py
test/lib/mock/metadata_v01.py
test/testbeds/ns3/execute.py [new file with mode: 0755]

index a796bc4..c37c6d3 100644 (file)
@@ -89,8 +89,8 @@ class ConnectorType(object):
 # need a definition!
 class Factory(AttributesMap):
     def __init__(self, factory_id, create_function, start_function, 
 # need a definition!
 class Factory(AttributesMap):
     def __init__(self, factory_id, create_function, start_function, 
-            stop_function, status_function, allow_addresses = False, 
-            allow_routes = False):
+            stop_function, status_function, configure_function,
+            allow_addresses = False, allow_routes = False):
         super(Factory, self).__init__()
         self._factory_id = factory_id
         self._allow_addresses = (allow_addresses == True)
         super(Factory, self).__init__()
         self._factory_id = factory_id
         self._allow_addresses = (allow_addresses == True)
@@ -99,6 +99,7 @@ class Factory(AttributesMap):
         self._start_function = start_function
         self._stop_function = stop_function
         self._status_function = status_function
         self._start_function = start_function
         self._stop_function = stop_function
         self._status_function = status_function
+        self._configure_function = configure_function
         self._connector_types = dict()
         self._traces = list()
         self._box_attributes = AttributesMap()
         self._connector_types = dict()
         self._traces = list()
         self._box_attributes = AttributesMap()
@@ -135,6 +136,10 @@ class Factory(AttributesMap):
     def status_function(self):
         return self._status_function
 
     def status_function(self):
         return self._status_function
 
+    @property
+    def configure_function(self):
+        return self._configure_function
+
     @property
     def traces(self):
         return self._traces
     @property
     def traces(self):
         return self._traces
index 8180e8e..b4fa746 100644 (file)
@@ -57,12 +57,19 @@ class VersionedMetadataInfo(object):
         raise NotImplementedError
 
     @property
         raise NotImplementedError
 
     @property
-    def factories_order(self):
+    def create_order(self):
         """ list of factory ids that indicates the order in which the elements
         should be instantiated.
         """
         raise NotImplementedError
 
         """ list of factory ids that indicates the order in which the elements
         should be instantiated.
         """
         raise NotImplementedError
 
+    @property
+    def configure_order(self):
+        """ list of factory ids that indicates the order in which the elements
+        should be configured.
+        """
+        raise NotImplementedError
+
     @property
     def factories_info(self):
         """ dictionary of dictionaries of factory specific information
     @property
     def factories_info(self):
         """ dictionary of dictionaries of factory specific information
@@ -75,6 +82,7 @@ class VersionedMetadataInfo(object):
                 "start_function": function for element starting,
                 "stop_function": function for element stoping,
                 "status_function": function for retrieving element status,
                 "start_function": function for element starting,
                 "stop_function": function for element stoping,
                 "status_function": function for retrieving element status,
+                "configure_function": function for element configuration,
                 "factory_attributes": list of references to attribute_ids,
                 "box_attributes": list of regerences to attribute_ids,
                 "traces": list of references to trace_id
                 "factory_attributes": list of references to attribute_ids,
                 "box_attributes": list of regerences to attribute_ids,
                 "traces": list of references to trace_id
@@ -108,8 +116,12 @@ class Metadata(object):
         self._metadata = metadata_module.VersionedMetadataInfo()
 
     @property
         self._metadata = metadata_module.VersionedMetadataInfo()
 
     @property
-    def factories_order(self):
-        return self._metadata.factories_order
+    def create_order(self):
+        return self._metadata.create_order
+
+    @property
+    def configure_order(self):
+        return self._metadata.configure_order
 
     def testbed_attributes(self):
         attributes = AttributesMap()
 
     def testbed_attributes(self):
         attributes = AttributesMap()
@@ -158,13 +170,15 @@ class Metadata(object):
                     if "stop_function" in info else None
             status_function = info["status_function"] \
                     if "status_function" in info else None
                     if "stop_function" in info else None
             status_function = info["status_function"] \
                     if "status_function" in info else None
+            configure_function = info["configure_function"] \
+                    if "configure_function" in info else None
             allow_addresses = info["allow_addresses"] \
                     if "allow_addresses" in info else False
             allow_routes = info["allow_routes"] \
                     if "allow_routes" in info else False
             factory = Factory(factory_id, create_function, start_function,
             allow_addresses = info["allow_addresses"] \
                     if "allow_addresses" in info else False
             allow_routes = info["allow_routes"] \
                     if "allow_routes" in info else False
             factory = Factory(factory_id, create_function, start_function,
-                    stop_function, status_function, allow_addresses, 
-                    allow_routes)
+                    stop_function, status_function, configure_function,
+                    allow_addresses, allow_routes)
             self._add_attributes(factory, info, "factory_attributes")
             self._add_attributes(factory, info, "box_attributes", True)
             self._add_execute_traces(factory, info)
             self._add_attributes(factory, info, "factory_attributes")
             self._add_attributes(factory, info, "box_attributes", True)
             self._add_execute_traces(factory, info)
index 36e8b1f..f669817 100644 (file)
@@ -178,7 +178,7 @@ class TestbedInstance(execute.TestbedInstance):
                guids[factory_id] = list()
             guids[factory_id].append(guid)
         # create elements following the factory_id order
                guids[factory_id] = list()
             guids[factory_id].append(guid)
         # create elements following the factory_id order
-        for factory_id in self._metadata.factories_order:
+        for factory_id in self._metadata.create_order:
             # omit the factories that have no element to create
             if factory_id not in guids:
                 continue
             # omit the factories that have no element to create
             if factory_id not in guids:
                 continue
@@ -209,7 +209,22 @@ class TestbedInstance(execute.TestbedInstance):
                         code_to_connect(self, element1, element2)
 
     def do_configure(self):
                         code_to_connect(self, element1, element2)
 
     def do_configure(self):
-        raise NotImplementedError
+        guids = dict()
+        # order guids (elements) according to factory_id
+        for guid, factory_id in self._create.iteritems():
+            if not factory_id in guids:
+               guids[factory_id] = list()
+            guids[factory_id].append(guid)
+        # configure elements following the factory_id order
+        for factory_id in self._metadata.configure_order:
+            # omit the factories that have no element to create
+            if factory_id not in guids:
+                continue
+            factory = self._factories[factory_id]
+            if not factory.configure_function:
+                continue
+            for guid in guids[factory_id]:
+                factory.configure_function(self, guid)
 
     def do_cross_connect(self):
         for guid, cross_connections in self._cross_connect.iteritems():
 
     def do_cross_connect(self):
         for guid, cross_connections in self._cross_connect.iteritems():
index 70a64b4..c6fa941 100644 (file)
@@ -25,23 +25,6 @@ class TestbedInstance(testbed_impl.TestbedInstance):
             get_attribute_value("homeDirectory")
         self._netns = self._load_netns_module()
 
             get_attribute_value("homeDirectory")
         self._netns = self._load_netns_module()
 
-    def do_configure(self):
-        # TODO: add traces!
-        # configure addressess
-        for guid, addresses in self._add_address.iteritems():
-            element = self._elements[guid]
-            for address in addresses:
-                (address, netprefix, broadcast) = address
-                # TODO: Decide if we should add a ipv4 or ipv6 address
-                element.add_v4_address(address, netprefix)
-        # configure routes
-        for guid, routes in self._add_route.iteritems():
-            element = self._elements[guid]
-            for route in routes:
-                (destination, netprefix, nexthop) = route
-                element.add_route(prefix = destination, prefix_len = netprefix,
-                        nexthop = nexthop)
-
     def set(self, time, guid, name, value):
         super(TestbedInstance, self).set(time, guid, name, value)
         # TODO: take on account schedule time for the task 
     def set(self, time, guid, name, value):
         super(TestbedInstance, self).set(time, guid, name, value)
         # TODO: take on account schedule time for the task 
index fd0ce4f..4672c35 100644 (file)
@@ -133,6 +133,28 @@ def status_application(testbed_instance, guid):
         return STATUS_RUNNING
     return STATUS_FINISHED
 
         return STATUS_RUNNING
     return STATUS_FINISHED
 
+### Configure functions ###
+
+def configure_device(testbed_instance, guid):
+    element = testbed_instance._elements[guid]
+    if not guid in testbed_instance._add_address:
+        return
+    addresses = testbed_instance._add_address[guid]
+    for address in addresses:
+        (address, netprefix, broadcast) = address
+        # TODO: Decide if we should add a ipv4 or ipv6 address
+        element.add_v4_address(address, netprefix)
+
+def configure_node(testbed_instance, guid):
+    element = testbed_instance._elements[guid]
+    if not guid in testbed_instance._add_route:
+        return
+    routes = testbed_instance._add_route[guid]
+    for route in routes:
+        (destination, netprefix, nexthop) = route
+        element.add_route(prefix = destination, prefix_len = netprefix,
+            nexthop = nexthop)
+
 ### Factory information ###
 
 connector_types = dict({
 ### Factory information ###
 
 connector_types = dict({
@@ -309,7 +331,10 @@ traces = dict({
         }) 
     })
 
         }) 
     })
 
-factories_order = [ NODE, P2PIFACE, NODEIFACE, TAPIFACE, SWITCH,
+create_order = [ NODE, P2PIFACE, NODEIFACE, TAPIFACE, SWITCH,
+        APPLICATION ]
+
+configure_order = [ P2PIFACE, NODEIFACE, TAPIFACE, SWITCH, NODE,
         APPLICATION ]
 
 factories_info = dict({
         APPLICATION ]
 
 factories_info = dict({
@@ -318,6 +343,7 @@ factories_info = dict({
             "help": "Emulated Node with virtualized network stack",
             "category": "topology",
             "create_function": create_node,
             "help": "Emulated Node with virtualized network stack",
             "category": "topology",
             "create_function": create_node,
+            "configure_function": configure_node,
             "box_attributes": ["forward_X11"],
             "connector_types": ["devs", "apps"]
        }),
             "box_attributes": ["forward_X11"],
             "connector_types": ["devs", "apps"]
        }),
@@ -326,6 +352,7 @@ factories_info = dict({
             "help": "Point to point network interface",
             "category": "devices",
             "create_function": create_p2piface,
             "help": "Point to point network interface",
             "category": "devices",
             "create_function": create_p2piface,
+            "configure_function": configure_device,
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "p2p"]
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "p2p"]
@@ -335,6 +362,7 @@ factories_info = dict({
             "help": "Tap device network interface",
             "category": "devices",
             "create_function": create_tapiface,
             "help": "Tap device network interface",
             "category": "devices",
             "create_function": create_tapiface,
+            "configure_function": configure_device,
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "fd"]
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "fd"]
@@ -344,6 +372,7 @@ factories_info = dict({
             "help": "Node network interface",
             "category": "devices",
             "create_function": create_nodeiface,
             "help": "Node network interface",
             "category": "devices",
             "create_function": create_nodeiface,
+            "configure_function": configure_device,
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "switch"]
             "box_attributes": ["lladdr", "up", "device_name", "mtu", 
                 "multicast", "broadcast", "arp"],
             "connector_types": ["node", "switch"]
@@ -386,7 +415,7 @@ testbed_attributes = dict({
                 "help": "Path to the directory where traces and other files \
                         will be stored",
                 "type": Attribute.STRING,
                 "help": "Path to the directory where traces and other files \
                         will be stored",
                 "type": Attribute.STRING,
-                "value": False,
+                "value": "",
                 "flags": Attribute.DesignOnly,
                 "validation_function": validation.is_string
             })
                 "flags": Attribute.DesignOnly,
                 "validation_function": validation.is_string
             })
@@ -410,8 +439,12 @@ class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
         return traces
 
     @property
         return traces
 
     @property
-    def factories_order(self):
-        return factories_order
+    def create_order(self):
+        return create_order
+
+    @property
+    def configure_order(self):
+        return configure_order
 
     @property
     def factories_info(self):
 
     @property
     def factories_info(self):
index c7aebea..2a8cc0a 100644 (file)
@@ -5,6 +5,8 @@ from constants import TESTBED_ID
 from nepi.core import testbed_impl
 from nepi.core.attributes import Attribute
 import os
 from nepi.core import testbed_impl
 from nepi.core.attributes import Attribute
 import os
+import sys
+import threading
 
 class TestbedInstance(testbed_impl.TestbedInstance):
     def __init__(self, testbed_version):
 
 class TestbedInstance(testbed_impl.TestbedInstance):
     def __init__(self, testbed_version):
@@ -12,6 +14,8 @@ class TestbedInstance(testbed_impl.TestbedInstance):
         self._ns3 = None
         self._home_directory = None
         self._traces = dict()
         self._ns3 = None
         self._home_directory = None
         self._traces = dict()
+        self._simulator_thread = None
+        self._condition = None
 
     @property
     def home_directory(self):
 
     @property
     def home_directory(self):
@@ -26,74 +30,18 @@ class TestbedInstance(testbed_impl.TestbedInstance):
             get_attribute_value("homeDirectory")
         self._ns3 = self._load_ns3_module()
 
             get_attribute_value("homeDirectory")
         self._ns3 = self._load_ns3_module()
 
-    def do_configure(self):
-        # configure addressess
-        for guid, addresses in self._add_address.iteritems():
-            element = self._elements[guid]
-            for address in addresses:
-                (address, netprefix, broadcast) = address
-                # TODO!!!
-        # configure routes
-        for guid, routes in self._add_route.iteritems():
-            element = self._elements[guid]
-            for route in routes:
-                (destination, netprefix, nexthop) = route
-                # TODO!!
-        """
-        context = self.server.modules.ns3
-        ipv4 = self._object
-        for interface in self._interface2addr:
-            ifindex = ipv4.AddInterface(interface._object)
-            for addr in self._interface2addr[interface]:
-                inaddr = context.Ipv4InterfaceAddress(
-                        context.Ipv4Address(
-                            addr.get_attribute("Address").value),
-                        context.Ipv4Mask(
-                            addr.get_attribute("NetPrefix").value))
-                ipv4.AddAddress(ifindex, inaddr)
-                ipv4.SetMetric(ifindex, 1)
-                ipv4.SetUp(ifindex)
-                self._interface_addrs[addr] = inaddr
-                self._interfaces[interface] = ifindex
-        for entry in self.get_node().routing_table.get_entries(self._af):
-            self._rt_add(entry)
-
-        def _rt_add(self, entry):
-        # Called both at install-time (by NS3Ipv4Stack.post_install) and at
-        # run-time (by RoutingTable.add_entry).
-        context = self.server.modules.ns3
-        ifindex = self._interfaces[entry.interface]
-        prefixlen = entry.prefixlen
-        # print "rt_add %s %s %s %d"% (prefix, prefixlen, entry.nexthop, ifindex)        
-        if entry.nexthop:
-            self._static_routing.AddNetworkRouteTo(
-                    context.Ipv4Address(entry.prefix.address),
-                    context.Ipv4Mask(entry.mask.address),
-                    context.Ipv4Address(entry.nexthop.address),
-                    ifindex)
-        else:
-            self._static_routing.AddNetworkRouteTo(
-                    context.Ipv4Address(entry.prefix.address),
-                    context.Ipv4Mask(entry.mask.address),
-                    ifindex)
-        """
+    def start(self):
+        super(TestbedInstance, self).start()
+        self._condition = threading.Condition()
+        self._simulator_thread = threading.Thread(target = self._simulator_run,
+                args = [self._condition])
+        self._simulator_thread.start()
 
     def set(self, time, guid, name, value):
         super(TestbedInstance, self).set(time, guid, name, value)
         # TODO: take on account schedule time for the task
 
     def set(self, time, guid, name, value):
         super(TestbedInstance, self).set(time, guid, name, value)
         # TODO: take on account schedule time for the task
-        factory_id = self._crerate[guid]
         element = self._elements[guid]
         element = self._elements[guid]
-        TypeId = self.ns3.TypeId()
-        typeid = TypeId.LookupByName(factory_id)
-        info = TypeId.AttributeInfo()
-        if not typeid.LookupAttributeByName(name, info):
-            raise RuntimeError("Attribute %s doesn't belong to element %s" \
-                   % (name, factory_id))
-        value = str(value)
-        if isinstance(value, bool):
-            value = value.lower()
-        ns3_value = info.checker.Create()
-        ns3_value.DeserializeFromString(value, checker)
+        ns3_value = self._to_ns3_value(guid, name, value) 
         element.SetAttribute(name, ns3_value)
 
     def get(self, time, guid, name):
         element.SetAttribute(name, ns3_value)
 
     def get(self, time, guid, name):
@@ -131,7 +79,7 @@ class TestbedInstance(testbed_impl.TestbedInstance):
 
     def trace_filename(self, guid, trace_id):
         # TODO: Need to be defined inside a home!!!! with and experiment id_code
 
     def trace_filename(self, guid, trace_id):
         # TODO: Need to be defined inside a home!!!! with and experiment id_code
-        filename = self._trace_filenames[guid][trace_id]
+        filename = self._traces[guid][trace_id]
         return os.path.join(self.home_directory, filename)
 
     def follow_trace(self, guid, trace_id, filename):
         return os.path.join(self.home_directory, filename)
 
     def follow_trace(self, guid, trace_id, filename):
@@ -143,6 +91,61 @@ class TestbedInstance(testbed_impl.TestbedInstance):
         for element in self._elements.values():
             element = None
 
         for element in self._elements.values():
             element = None
 
+    def _simulator_run(self, condition):
+        # Run simulation
+        self.ns3.Simulator.Run()
+        # Signal condition on simulation end to notify waiting threads
+        condition.acquire()
+        condition.notifyAll()
+        condition.release()
+
+    def _schedule_event(self, condition, func, *args):
+        """Schedules event on running experiment"""
+        def execute_event(condition, has_event_occurred, func, *args):
+            # exec func
+            func(*args)
+            # flag event occured
+            has_event_occurred[0] = True
+            # notify condition indicating attribute was set
+            condition.acquire()
+            condition.notifyAll()
+            condition.release()
+
+        # contextId is defined as general context
+        contextId = long(0xffffffff)
+        # delay 0 means that the event is expected to execute inmediately
+        delay = self.ns3.Seconds(0)
+        # flag to indicate that the event occured
+        # because bool is an inmutable object in python, in order to create a
+        # bool flag, a list is used as wrapper
+        has_event_occurred = [False]
+        condition.acquire()
+        if not self.ns3.Simulator.IsFinished():
+            self.ns3.Simulator.ScheduleWithContext(contextId, delay, execute_event,
+                 condition, has_event_occurred, func, *args)
+            while not has_event_occurred[0] and not self.ns3.Simulator.IsFinished():
+                condition.wait()
+                condition.release()
+                if not has_event_occurred[0]:
+                    raise RuntimeError('Event could not be scheduled : %s %s ' \
+                    % (repr(func), repr(args)))
+
+    def _to_ns3_value(self, guid, name, value):
+        factory_id = self._create[guid]
+        TypeId = self.ns3.TypeId()
+        typeid = TypeId.LookupByName(factory_id)
+        info = TypeId.AttributeInfo()
+        if not typeid.LookupAttributeByName(name, info):
+            raise RuntimeError("Attribute %s doesn't belong to element %s" \
+                   % (name, factory_id))
+        str_value = str(value)
+        if isinstance(value, bool):
+            str_value = str_value.lower()
+        checker = info.checker
+        ns3_value = checker.Create()
+        ns3_value.DeserializeFromString(str_value, checker)
+        return ns3_value
+
     def _load_ns3_module(self):
         import ctypes
         import imp
     def _load_ns3_module(self):
         import ctypes
         import imp
@@ -177,7 +180,7 @@ class TestbedInstance(testbed_impl.TestbedInstance):
         factory_id = self._create[guid]
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
         factory_id = self._create[guid]
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
-        for name, value in params:
+        for name, value in params.iteritems():
             info = self.ns3.TypeId.AttributeInfo()
             typeid.LookupAttributeByName(name, info)
             if info.flags & TypeId.ATTR_CONSTRUCT == TypeId.ATTR_CONSTRUCT:
             info = self.ns3.TypeId.AttributeInfo()
             typeid.LookupAttributeByName(name, info)
             if info.flags & TypeId.ATTR_CONSTRUCT == TypeId.ATTR_CONSTRUCT:
index 0b9b8dc..9021e54 100644 (file)
@@ -1,8 +1,261 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-from metadata_v3_9_RC3 import create_device, create_element, create_ipv4protocol, \
-        create_node, create_wifi_standard_model, start_application, \
-        stop_application, status_application
+
+from nepi.util.constants import AF_INET, STATUS_NOT_STARTED, STATUS_RUNNING, \
+        STATUS_FINISHED, STATUS_UNDETERMINED
+
+def _get_ipv4_protocol_guid(testbed_instance, node_guid):
+    # search for the Ipv4L3Protocol asociated with the device
+    protos_guids = testbed_instance.get_connected(node_guid, "protos", "node")
+    if len(protos_guids) == 0:
+        raise RuntimeError("No protocols where found for the node %d" % node_guid)
+    ipv4_guid = None
+    for proto_guid in protos_guids:
+        proto_factory_id = testbed_instance._create[proto_guid]
+        if proto_factory_id == "ns3::Ipv4L3Protocol":
+            ipv4_guid = proto_guid
+            break
+    if not ipv4_guid:
+        raise RuntimeError("No Ipv4L3Protocol associated to node %d. \
+                can't add Ipv4 addresses" % node_guid)
+    return ipv4_guid
+
+def _get_node_guid(testbed_instance, guid):
+    # search for the node asociated with the device
+    node_guids = testbed_instance.get_connected(guid, "node", "devs")
+    if len(node_guids) == 0:
+        raise RuntimeError("Can't instantiate interface %d outside netns \
+                node" % guid)
+    node_guid = node_guids[0]
+    return node_guid
+
+def _get_dev_number(testbed_instance, guid):
+    dev_guids = testbed_instance.get_connected(guid, "devs", "node")
+    interface_number = 0
+    for guid_ in dev_guids:
+        if guid_ == guid:
+            break
+        inteface_number += 1
+    return interface_number
+
+### create traces functions ###
+
+def p2ppcap_trace(testbed_instance, guid, trace_id):
+    node_guid = _get_node_guid(testbed_instance, guid)
+    interface_number = _get_dev_number(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    filename = "trace-p2p-node-%d-dev-%d.pcap" % (node_guid, interface_number)
+    testbed_instance.follow_trace(guid, trace_id, filename)
+    filepath = testbed_instance.trace_filename(guid, trace_id)
+    helper = testbed_instance.ns3.PointToPointHelper()
+    helper.EnablePcap(filepath, element, explicitFilename = True)
+
+def _csmapcap_trace(testbed_instance, guid, trace_id, promisc):
+    node_guid = _get_node_guid(testbed_instance, guid)
+    interface_number = _get_dev_number(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    filename = "trace-csma-node-%d-dev-%d.pcap" % (node_name, interface_number)
+    testbed_instance.follow_trace(guid, trace_id, filename)
+    filepath = testbed_instance.trace_filename(guid, trace_id)
+    helper = testbed_instance.ns3.CsmaHelper()
+    helper.EnablePcap(filepath, element, promiscuous = promisc, 
+            explicitFilename = True)
+
+def csmapcap_trace(testbed_instance, guid, trace_id):
+    promisc = False
+    _csmapcap_trace(testbed_instance, guid, trace_id, promisc)
+
+def csmapcap_promisc_trace(testbed_instance, guid, trace_id):
+    promisc = True
+    _csmapcap_trace(testbed_instance, guid, trace_id, promisc)
+
+def fdpcap_trace(testbed_instance, guid, trace_id):
+    node_guid = _get_node_guid(testbed_instance, guid)
+    interface_number = _get_dev_number(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    filename = "trace-fd-node-%d-dev-%d.pcap" % (node_name, interface_number)
+    testbed_instance.follow_trace(guid, trace_id, filename)
+    filepath = testbed_instance.trace_filename(guid, trace_id)
+    helper = testbed_instance.ns3.FileDescriptorHelper()
+    helper.EnablePcap(filepath, element, explicitFilename = True)
+
+def yanswifipcap_trace(testbed_instance, guid, trace_id):
+    dev_guid = testbed_instance.get_connected(guid, "dev", "phy")[0]
+    node_guid = _get_node_guid(testbed_instance, dev_guid)
+    interface_number = _get_dev_number(testbed_instance, dev_guid)
+    element = testbed_instance._elements[dev_guid]
+    filename = "trace-yanswifi-node-%d-dev-%d.pcap" % (node_name, interface_number)
+    testbed_instance.follow_trace(guid, trace_id, filename)
+    filepath = testbed_instance.trace_filename(guid, trace_id)
+    helper = testbed_instance.ns3.YansWifiPhyHelper()
+    helper.EnablePcap(filepath, element, explicitFilename = True)
+
+trace_functions = dict({
+    "P2PPcapTrace": p2ppcap_trace,
+    "CsmaPcapTrace": csmapcap_trace,
+    "CsmaPcapPromiscTrace": csmapcap_promisc_trace,
+    "FileDescriptorPcapTrace": fdpcap_trace,
+    "YansWifiPhyPcapTrace": yanswifipcap_trace
+    })
+
+### Creation functions ###
+
+wifi_standards = dict({
+    "WIFI_PHY_STANDARD_holland": 5,
+    "WIFI_PHY_STANDARD_80211p_SCH": 7,
+    "WIFI_PHY_STANDARD_80211_5Mhz": 4,
+    "WIFI_PHY_UNKNOWN": 8,
+    "WIFI_PHY_STANDARD_80211_10Mhz": 3,
+    "WIFI_PHY_STANDARD_80211g": 2,
+    "WIFI_PHY_STANDARD_80211p_CCH": 6,
+    "WIFI_PHY_STANDARD_80211a": 0,
+    "WIFI_PHY_STANDARD_80211b": 1
+})
+
+def create_element(testbed_instance, guid):
+    element_factory = testbed_instance.ns3.ObjectFactory()
+    factory_id = testbed_instance._create[guid]
+    element_factory.SetTypeId(factory_id) 
+    construct_parameters = testbed_instance._get_construct_parameters(guid)
+    for name, value in construct_parameters.iteritems():
+        ns3_value = testbed_instance._to_ns3_value(guid, name, value)
+        element_factory.Set(name, ns3_value)
+    element = element_factory.Create()
+    testbed_instance._elements[guid] = element
+    traces = testbed_instance._get_traces(guid)
+    for trace_id in traces:
+        trace_func = trace_functions[trace_id]
+        trace_func(testbed_instance, guid, trace_id)
+
+def create_node(testbed_instance, guid):
+    create_element(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    element.AggregateObject(testbed_instance.ns3.PacketSocketFactory())
+
+def create_device(testbed_instance, guid):
+    create_element(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    parameters = testbed_instance._get_parameters(guid)
+    if "macAddress" in parameters:
+        address = parameters["macAddress"]
+        macaddr = testbed_instance.ns3.Mac48Address(address)
+    else:
+        macaddr = testbed_instance.ns3.Mac48Address.Allocate()
+    element.SetAddress(macaddr)
+
+def create_wifi_standard_model(testbed_instance, guid):
+    create_element(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    parameters = testbed_instance._get_parameters(guid)
+    if "standard" in parameters:
+        standard = parameters["standard"]
+        if standard:
+            elements.ConfigureStandard(wifi_standards[standard])
+
+def create_ipv4protocol(testbed_instance, guid):
+    create_element(testbed_instance, guid)
+    element = testbed_instance._elements[guid]
+    list_routing = testbed_instance.ns3.Ipv4ListRouting()
+    element.SetRoutingProtocol(list_routing)
+    static_routing = testbed_instance.ns3.Ipv4StaticRouting()
+    list_routing.AddRoutingProtocol(static_routing, 1)
+
+### Start/Stop functions ###
+
+def start_application(testbed_instance, guid):
+    element = testbed_instance.elements[guid]
+    # BUG: without doing this explicit call it doesn't start!!!
+    # Shouldn't be enough to set the StartTime?
+    element.Start()
+
+def stop_application(testbed_instance, guid):
+    element = testbed_instance.elements[guid]
+    now = testbed_instance.ns3.Simulator.Now()
+    element.SetStopTime(now)
+
+### Status functions ###
+
+def status_application(testbed_instance, guid):
+    if guid not in testbed_instance.elements.keys():
+        raise RuntimeError("Can't get status on guid %d" % guid )
+    now = testbed_instance.ns3.Simulator.Now()
+    if now.IsZero():
+        return STATUS_NOT_STARTED
+    app = testbed_instance.elements[guid]
+    parameters = testbed_instance._get_parameters(guid)
+    if "StartTime" in parameters and parameters["StartTime"]:
+        start_value = parameters["StartTime"]
+        start_time = testbed_instance.ns3.Time(start_value)
+        if now.Compare(start_time) < 0:
+            return STATUS_NOT_RUNNING
+    if "StopTime" in parameters and parameters["StopTime"]:
+        stop_value = parameters["StopTime"]
+        stop_time = testbed_instance.ns3.Time(stop_value)
+        if now.Compare(stop_time) < 0:
+            return STATUS_RUNNING
+        else:
+            return STATUS_FINISHED
+    return STATUS_UNDETERMINED
+
+### Configure functions ###
+
+def configure_device(testbed_instance, guid):
+    element = testbed_instance._elements[guid]
+    if not guid in testbed_instance._add_address:
+        return
+    # search for the node asociated with the device
+    node_guid = _get_node_guid(testbed_instance, guid)
+    node = testbed_instance.elements[node_guid]
+    # search for the Ipv4L3Protocol asociated with the device
+    ipv4_guid = _get_ipv4_protocol_guid(testbed_instance, node_guid)
+    ipv4 = testbed_instance._elements[ipv4_guid]
+    ns3 = testbed_instance.ns3
+    # add addresses 
+    addresses = testbed_instance._add_address[guid]
+    for address in addresses:
+        (address, netprefix, broadcast) = address
+        # TODO: missing IPV6 addresses!!
+        ifindex = ipv4.AddInterface(element)
+        inaddr = ns3.Ipv4InterfaceAddress(ns3.Ipv4Address(address),
+                ns3.Ipv4Mask("/%d" % netprefix))
+        ipv4.AddAddress(ifindex, inaddr)
+        ipv4.SetMetric(ifindex, 1)
+        ipv4.SetUp(ifindex)
+
+def configure_node(testbed_instance, guid):
+    element = testbed_instance._elements[guid]
+    if not guid in testbed_instance._add_route:
+        return
+    # search for the Ipv4L3Protocol asociated with the device
+    ipv4_guid = _get_ipv4_protocol_guid(testbed_instance, guid)
+    ipv4 = testbed_instance._elements[ipv4_guid]
+    list_routing = ipv4.GetRoutingProtocol()
+    (static_routing, priority) = list_routing.GetRoutingProtocol(0)
+    ns3 = testbed_instance.ns3
+    routes = testbed_instance._add_route[guid]
+    for route in routes:
+        (destination, netprefix, nexthop) = route
+        address = ns3.Ipv4Address(destination)
+        mask = ns3.Ipv4Mask("/%d" % netprefix) 
+        if nexthop:
+            nexthop_address = ns3.Ipv4Address(nexthop)
+            ifindex = -1
+            # TODO: HACKISH way of getting the ifindex... improve this
+            nifaces = ipv4.GetNInterfaces()
+            for ifidx in range(nifaces):
+                iface = ipv4.GetInterface(ifidx)
+                naddress = iface.GetNAddresses()
+                for addridx in range(naddress):
+                    ifaddr = iface.GetAddress(addridx)
+                    ifmask = ifaddr.GetMask()
+                    ifindex = ipv4.GetInterfaceForPrefix(nexthop_address, ifmask)
+                    if ifindex == ifidx:
+                        break
+            static_routing.AddNetworkRouteTo(address, mask, nexthop_address, 
+                    ifindex) 
+        else:
+            ifindex = ipv4.GetInterfaceForPrefix(address, mask)
+            static_routing.AddNetworkRouteTo(address, mask, ifindex) 
 
 factories_info = dict({
     "ns3::Ping6": dict({
 
 factories_info = dict({
     "ns3::Ping6": dict({
@@ -41,6 +294,7 @@ factories_info = dict({
      "ns3::Node": dict({
         "category": "Topology",
         "create_function": create_node,
      "ns3::Node": dict({
         "category": "Topology",
         "create_function": create_node,
+        "configure_function": configure_node,
         "help": "",
         "connector_types": ["devs", "apps", "protos", "mobility"],
         "allow_routes": True,
         "help": "",
         "connector_types": ["devs", "apps", "protos", "mobility"],
         "allow_routes": True,
@@ -123,6 +377,7 @@ factories_info = dict({
      "ns3::PointToPointNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
      "ns3::PointToPointNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
+        "configure_function": configure_device,
         "help": "",
         "connector_types": ["node", "err", "queue", "chan"],
         "allow_addresses": True,
         "help": "",
         "connector_types": ["node", "err", "queue", "chan"],
         "allow_addresses": True,
@@ -322,6 +577,7 @@ factories_info = dict({
      "ns3::FileDescriptorNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
      "ns3::FileDescriptorNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
+        "configure_function": configure_device,
         "help": "Network interface associated to a file descriptor",
         "connector_types": ["node", "fd"],
         "allow_addresses": True,
         "help": "Network interface associated to a file descriptor",
         "connector_types": ["node", "fd"],
         "allow_addresses": True,
@@ -331,6 +587,7 @@ factories_info = dict({
      "ns3::CsmaNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
      "ns3::CsmaNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
+        "configure_function": configure_device,
         "help": "CSMA (carrier sense, multiple access) interface",
         "connector_types": ["node", "chan", "err", "queue"],
         "allow_addresses": True,
         "help": "CSMA (carrier sense, multiple access) interface",
         "connector_types": ["node", "chan", "err", "queue"],
         "allow_addresses": True,
@@ -671,6 +928,7 @@ factories_info = dict({
      "ns3::BaseStationNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
      "ns3::BaseStationNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
+        "configure_function": configure_device,
         "help": "",
         "connector_types": [],
         "allow_addresses": True,
         "help": "",
         "connector_types": [],
         "allow_addresses": True,
@@ -776,7 +1034,6 @@ factories_info = dict({
         "create_function": create_element,
         "help": "",
         "connector_types": [],
         "create_function": create_element,
         "help": "",
         "connector_types": [],
-        "allow_addresses": True,
         "box_attributes": ["Address",
             "Mtu"],
     }),
         "box_attributes": ["Address",
             "Mtu"],
     }),
@@ -790,6 +1047,7 @@ factories_info = dict({
      "ns3::WifiNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
      "ns3::WifiNetDevice": dict({
         "category": "Device",
         "create_function": create_device,
+        "configure_function": configure_device,
         "help": "",
         "connector_types": ["node", "mac", "phy", "manager"],
         "allow_addresses": True,
         "help": "",
         "connector_types": ["node", "mac", "phy", "manager"],
         "allow_addresses": True,
index 2ad786d..bb51495 100644 (file)
@@ -5,20 +5,6 @@ from constants import TESTBED_ID
 from nepi.core import metadata
 from nepi.core.attributes import Attribute
 from nepi.util import validation
 from nepi.core import metadata
 from nepi.core.attributes import Attribute
 from nepi.util import validation
-from nepi.util.constants import AF_INET, STATUS_NOT_STARTED, STATUS_RUNNING, \
-        STATUS_FINISHED
-
-wifi_standards = dict({
-    "WIFI_PHY_STANDARD_holland": 5,
-    "WIFI_PHY_STANDARD_80211p_SCH": 7,
-    "WIFI_PHY_STANDARD_80211_5Mhz": 4,
-    "WIFI_PHY_UNKNOWN": 8,
-    "WIFI_PHY_STANDARD_80211_10Mhz": 3,
-    "WIFI_PHY_STANDARD_80211g": 2,
-    "WIFI_PHY_STANDARD_80211p_CCH": 6,
-    "WIFI_PHY_STANDARD_80211a": 0,
-    "WIFI_PHY_STANDARD_80211b": 1
-})
 
 ### Connection functions ####
 
 
 ### Connection functions ####
 
@@ -79,160 +65,7 @@ def connect_fd_tap(tesbed_instance, fd, tap):
     # TODO!
     pass
 
     # TODO!
     pass
 
- ### create traces functions ###
-
-def get_node_guid(testbed_instance, guid):
-    node_guid = testbed_instance.get_connected(guid, "node", "devs")[0]
-    return node_guid
-
-def get_dev_number(testbed_instance, guid):
-    dev_guids = testbed_instance.get_connected(node_guid, "devs", "node")
-    interface_number = 0
-    for guid_ in dev_guids:
-        if guid_ == guid:
-            break
-        inteface_number += 1
-    return interface_number
-
-def p2ppcap_trace(testbed_instance, guid):
-    trace_id = "p2ppcap"
-    node_guid = get_node_guid(testbed_instance, guid)
-    interface_number = get_dev_number(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    filename = "trace-p2p-node-%d-dev-%d.pcap" % (node_name, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(self, guid, trace_id)
-    helper = testbed_instance.ns3.PointToPointHelper()
-    helper.EnablePcap(filepath, element, explicitFilename = True)
-
-def _csmapcap_trace(testbed_instance, guid, trace_id, promisc):
-    node_guid = get_node_guid(testbed_instance, guid)
-    interface_number = get_dev_number(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    filename = "trace-csma-node-%d-dev-%d.pcap" % (node_name, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(self, guid, trace_id)
-    helper = testbed_instance.ns3.CsmaHelper()
-    helper.EnablePcap(filepath, element, promiscuous = promisc, 
-            explicitFilename = True)
-
-def csmapcap_trace(testbed_instance, guid):
-    trace_id = "csmapcap"
-    promisc = False
-    _csmapcap_trace(testbed_instance, guid, trace_id, promisc)
-
-def csmapcap_promisc_trace(testbed_instance, guid):
-    trace_id = "csmapcap_promisc"
-    promisc = True
-    _csmapcap_trace(testbed_instance, guid, trace_id, promisc)
-
-def fdpcap_trace(testbed_instance, guid):
-    trace_id = "fdpcap"
-    node_guid = get_node_guid(testbed_instance, guid)
-    interface_number = get_dev_number(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    filename = "trace-fd-node-%d-dev-%d.pcap" % (node_name, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(self, guid, trace_id)
-    helper = testbed_instance.ns3.FileDescriptorHelper()
-    helper.EnablePcap(filepath, element, explicitFilename = True)
-
-def yanswifipcap_trace(testbed_instance, guid):
-    trace_id = "yanswifipcap"
-    dev_guid = testbed_instance.get_connected(guid, "dev", "phy")[0]
-    node_guid = get_node_guid(testbed_instance, dev_guid)
-    interface_number = get_dev_number(testbed_instance, dev_guid)
-    element = testbed_instance._elements[dev_guid]
-    filename = "trace-yanswifi-node-%d-dev-%d.pcap" % (node_name, interface_number)
-    testbed_instance.follow_trace(guid, trace_id, filename)
-    filepath = testbed_instance.trace_filename(self, guid, trace_id)
-    helper = testbed_instance.ns3.YansWifiPhyHelper()
-    helper.EnablePcap(filepath, element, explicitFilename = True)
-
-trace_functions = dict({
-    "p2ppcap": p2ppcap_trace,
-    "csmapcap": csmapcap_trace,
-    "csmapcap_promisc": csmapcap_promisc_trace,
-    "fdpcap": fdpcap_trace,
-    "yanswifipcap": yanswifipcap_trace
-    })
-
-### Creation functions ###
-
-def create_element(testbed_instance, guid):
-    element_factory = testbed_instance.ns3.ObjectFactory()
-    factory_id = testbed_instance._create[guid]
-    element_factory.SetTypeId(factory_id) 
-    construct_parameters = testbed_instance._get_construct_parameters(guid)
-    for name, value in construct_parameters.iteritems():
-        ns3_value = testbed_instance._to_ns3_value(factory_id, name, value)
-        element_factory.Set(name, ns3_value)
-    element = element_factory.Create()
-    testbed_instance._elements[guid] = element
-    traces = testbed_instance._get_traces(guid)
-    for trace_id in traces:
-        trace_func = trace_functions[trace_id]
-        trace_func(testbed_instance, guid)
-
-def create_node(testbed_instance, guid):
-    create_element(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    element.AggregateObject(testbed_instance.PacketSocketFactory())
-
-def create_device(testbed_instance, guid):
-    create_element(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    parameters = testbed_instance._get_parameters(guid)
-    if "macAddress" in parameters:
-        address = parameters["macAddress"]
-        macaddr = testbed_instance.ns3.Mac48Address(address)
-    else:
-        macaddr = testbed_instance.ns3.Mac48Address.Allocate()
-    element.SetAddress(macaddr)
-
-def create_wifi_standard_model(testbed_instance, guid):
-    create_element(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    parameters = testbed_instance._get_parameters(guid)
-    if "standard" in parameters:
-        standard = parameters["standard"]
-        if standard:
-            elements.ConfigureStandard(wifi_standards[standard])
-
-def create_ipv4protocol(testbed_instance, guid):
-    create_element(testbed_instance, guid)
-    element = testbed_instance._elements[guid]
-    list_routing = testbed_instance.ns3.Ipv4ListRouting()
-    element.SetRoutingProtocol(list_routing)
-    static_routing = testbed_instance.ns3.Ipv4StaticRouting()
-    list_routing.AddRoutingProtocol(static_routing, 1)
-
-### Start/Stop functions ###
-
-def start_application(testbed_instance, guid):
-    element = testbed_instance.elements[guid]
-    element.Start()
-
-def stop_application(testbed_instance, guid):
-    element = testbed_instance.elements[guid]
-    element.Stop()
-
-### Status functions ###
-
-def status_application(testbed_instance, guid):
-    if guid not in testbed_instance.elements.keys():
-        return STATUS_NOT_STARTED
-    app = testbed_instance.elements[guid]
-    parameters = testbed_instance._get_parameters(guid)
-    if "stopTime" in parameters:
-        stop = parameters["stopTime"]
-        if stop:
-            simTime = testbed_instance.ns3.Simulator.Now()
-            if simTime.Compare(stopTime) > 0:
-                return STATUS_RUNNING
-    return STATUS_FINISHED
-
-### Factory information ###
+### Connector information ###
 
 connector_types = dict({
     "node": dict({
 
 connector_types = dict({
     "node": dict({
@@ -827,8 +660,17 @@ testbed_attributes = dict({
                 "value": False,
                 "flags": Attribute.DesignOnly,
                 "validation_function": validation.is_bool
                 "value": False,
                 "flags": Attribute.DesignOnly,
                 "validation_function": validation.is_bool
+            }),
+          "home_directory": dict({
+                "name": "homeDirectory",
+                "help": "Path to the directory where traces and other files \
+                        will be stored",
+                "type": Attribute.STRING,
+                "value": "",
+                "flags": Attribute.DesignOnly,
+                "validation_function": validation.is_string
             })
             })
- })
+})
 
 class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
     @property
 
 class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
     @property
@@ -849,7 +691,11 @@ class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
         return traces
 
     @property
         return traces
 
     @property
-    def factories_order(self):
+    def create_order(self):
+        return factories_order
+
+    @property
+    def configure_order(self):
         return factories_order
 
     @property
         return factories_order
 
     @property
index bb175cb..ffbb633 100644 (file)
@@ -170,7 +170,11 @@ class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
         return traces
 
     @property
         return traces
 
     @property
-    def factories_order(self):
+    def create_order(self):
+        return factories_order
+
+    @property
+    def configure_order(self):
         return factories_order
 
     @property
         return factories_order
 
     @property
diff --git a/test/testbeds/ns3/execute.py b/test/testbeds/ns3/execute.py
new file mode 100755 (executable)
index 0000000..5e2f01f
--- /dev/null
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from nepi.util.constants import STATUS_FINISHED
+from nepi.testbeds import ns3
+import os
+import shutil
+import tempfile
+import test_util
+import time
+import unittest
+
+class Ns3ExecuteTestCase(unittest.TestCase):
+    def setUp(self):
+        self.root_dir = tempfile.mkdtemp()
+
+    def test_run_ping_if(self):
+        testbed_version = "3_9_RC3"
+        instance = ns3.TestbedInstance(testbed_version)
+        instance.configure("homeDirectory", self.root_dir)
+        instance.create(2, "ns3::Node")
+        instance.create(3, "ns3::Ipv4L3Protocol")
+        instance.create(4, "ns3::ArpL3Protocol")
+        instance.create(5, "ns3::Icmpv4L4Protocol")
+        instance.create(6, "ns3::UdpL4Protocol")
+        instance.connect(2, "protos", 3, "node")
+        instance.connect(2, "protos", 4, "node")
+        instance.connect(2, "protos", 5, "node")
+        instance.connect(2, "protos", 6, "node")
+        instance.create(7, "ns3::PointToPointNetDevice")
+        instance.create(8, "ns3::DropTailQueue")
+        instance.connect(2, "devs", 7, "node")
+        instance.connect(7, "queue", 8, "dev")
+        instance.add_trace(7, "P2PPcapTrace")
+        instance.add_address(7, "10.0.0.1", 24, None)
+
+        instance.create(9, "ns3::Node")
+        instance.create(10, "ns3::Ipv4L3Protocol")
+        instance.create(11, "ns3::ArpL3Protocol")
+        instance.create(12, "ns3::Icmpv4L4Protocol")
+        instance.create(13, "ns3::UdpL4Protocol")
+        instance.connect(9, "protos", 10, "node")
+        instance.connect(9, "protos", 11, "node")
+        instance.connect(9, "protos", 12, "node")
+        instance.connect(9, "protos", 13, "node")
+        instance.create(14, "ns3::PointToPointNetDevice")
+        instance.create(15, "ns3::DropTailQueue")
+        instance.connect(9, "devs", 14, "node")
+        instance.connect(14, "queue", 15, "dev")
+        instance.add_trace(14, "P2PPcapTrace")
+        instance.add_address(14, "10.0.0.2", 24, None)
+
+        instance.create(16, "ns3::PointToPointChannel")
+        instance.connect(7, "chan", 16, "dev2")
+        instance.connect(14, "chan", 16, "dev2")
+
+        instance.create(17, "ns3::V4Ping")
+        instance.create_set(17, "Remote", "10.0.0.2")
+        instance.create_set(17, "StartTime", "0s")
+        instance.create_set(17, "StopTime", "10s")
+        instance.create_set(17, "Verbose", True)
+        instance.connect(17, "node", 2, "apps")
+
+        instance.do_setup()
+        instance.do_create()
+        instance.do_connect()
+        instance.do_configure()
+        instance.start()
+        while instance.status(17) != STATUS_FINISHED:
+            time.sleep(0.1)
+        comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
+
+--- 10.0.0.2 ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+"""
+        #self.assertTrue(ping_result.startswith(comp_result))
+        instance.stop()
+        instance.shutdown()
+
+    def test_run_ping_routing(self):
+        testbed_version = "3_9_RC3"
+        instance = ns3.TestbedInstance(testbed_version)
+        instance.configure("homeDirectory", self.root_dir)
+        instance.create(2, "ns3::Node")
+        instance.create(3, "ns3::Ipv4L3Protocol")
+        instance.create(4, "ns3::ArpL3Protocol")
+        instance.create(5, "ns3::Icmpv4L4Protocol")
+        instance.create(6, "ns3::UdpL4Protocol")
+        instance.connect(2, "protos", 3, "node")
+        instance.connect(2, "protos", 4, "node")
+        instance.connect(2, "protos", 5, "node")
+        instance.connect(2, "protos", 6, "node")
+        instance.create(7, "ns3::PointToPointNetDevice")
+        instance.create(8, "ns3::DropTailQueue")
+        instance.connect(2, "devs", 7, "node")
+        instance.connect(7, "queue", 8, "dev")
+        instance.add_trace(7, "P2PPcapTrace")
+        instance.add_address(7, "10.0.0.1", 24, None)
+
+        instance.create(9, "ns3::Node")
+        instance.create(10, "ns3::Ipv4L3Protocol")
+        instance.create(11, "ns3::ArpL3Protocol")
+        instance.create(12, "ns3::Icmpv4L4Protocol")
+        instance.create(13, "ns3::UdpL4Protocol")
+        instance.connect(9, "protos", 10, "node")
+        instance.connect(9, "protos", 11, "node")
+        instance.connect(9, "protos", 12, "node")
+        instance.connect(9, "protos", 13, "node")
+        instance.create(14, "ns3::PointToPointNetDevice")
+        instance.create(15, "ns3::DropTailQueue")
+        instance.connect(9, "devs", 14, "node")
+        instance.connect(14, "queue", 15, "dev")
+        instance.add_trace(14, "P2PPcapTrace")
+        instance.add_address(14, "10.0.0.2", 24, None)
+
+        instance.create(16, "ns3::PointToPointChannel")
+        instance.connect(7, "chan", 16, "dev2")
+        instance.connect(14, "chan", 16, "dev2")
+
+        instance.create(17, "ns3::PointToPointNetDevice")
+        instance.create(18, "ns3::DropTailQueue")
+        instance.connect(9, "devs", 17, "node")
+        instance.connect(17, "queue", 18, "dev")
+        instance.add_trace(17, "P2PPcapTrace")
+        instance.add_address(17, "10.0.1.1", 24, None)
+
+        instance.create(19, "ns3::Node")
+        instance.create(20, "ns3::Ipv4L3Protocol")
+        instance.create(21, "ns3::ArpL3Protocol")
+        instance.create(22, "ns3::Icmpv4L4Protocol")
+        instance.create(23, "ns3::UdpL4Protocol")
+        instance.connect(19, "protos", 20, "node")
+        instance.connect(19, "protos", 21, "node")
+        instance.connect(19, "protos", 22, "node")
+        instance.connect(19, "protos", 23, "node")
+        instance.create(24, "ns3::PointToPointNetDevice")
+        instance.create(25, "ns3::DropTailQueue")
+        instance.connect(19, "devs", 24, "node")
+        instance.connect(24, "queue", 25, "dev")
+        instance.add_trace(24, "P2PPcapTrace")
+        instance.add_address(24, "10.0.1.2", 24, None)
+
+        instance.create(26, "ns3::PointToPointChannel")
+        instance.connect(17, "chan", 26, "dev2")
+        instance.connect(24, "chan", 26, "dev2")
+
+        instance.create(27, "ns3::V4Ping")
+        instance.create_set(27, "Remote", "10.0.1.2")
+        instance.create_set(27, "StartTime", "0s")
+        instance.create_set(27, "StopTime", "10s")
+        instance.create_set(27, "Verbose", True)
+        instance.connect(27, "node", 2, "apps")
+
+        instance.add_route(2, "10.0.1.0", 24, "10.0.0.2")
+        instance.add_route(19, "10.0.0.0", 24, "10.0.1.1")
+
+        instance.do_setup()
+        instance.do_create()
+        instance.do_connect()
+        instance.do_configure()
+        instance.start()
+        while instance.status(27) != STATUS_FINISHED:
+            time.sleep(0.1)
+        comp_result = """PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
+
+--- 10.0.0.2 ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time 0ms
+"""
+        #self.assertTrue(ping_result.startswith(comp_result))
+        instance.stop()
+        instance.shutdown()
+
+    def tearDown(self):
+        #shutil.rmtree(self.root_dir)
+        pass
+
+if __name__ == '__main__':
+    unittest.main()
+