vlc wireless hybrid experiment example added
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 2 May 2011 08:17:07 +0000 (10:17 +0200)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 2 May 2011 08:17:07 +0000 (10:17 +0200)
examples/vlc_wireless_netns_ns3.py [new file with mode: 0644]
src/nepi/core/attributes.py
src/nepi/core/design.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

diff --git a/examples/vlc_wireless_netns_ns3.py b/examples/vlc_wireless_netns_ns3.py
new file mode 100644 (file)
index 0000000..9a5ae4c
--- /dev/null
@@ -0,0 +1,220 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import getpass
+from nepi.core.design import ExperimentDescription, FactoriesProvider
+from nepi.core.execute import ExperimentController
+from nepi.util import proxy
+import os
+import shutil
+import tempfile
+import test_util
+import time
+import unittest
+
+class VlcWirelessNetnsNs3TestCase(unittest.TestCase):
+    def setUp(self):
+        self.root_dir = tempfile.mkdtemp()
+
+    def add_netns_tap(self, node, netns_desc):
+        tap = netns_desc.create("TapNodeInterface")
+        tap.set_attribute_value("up", True)
+        node.connector("devs").connect(tap.connector("node"))
+        return tap
+
+    def add_ns3_fdnd(self, node, ns3_desc):
+        fdnd = ns3_desc.create("ns3::FileDescriptorNetDevice")
+        node.connector("devs").connect(fdnd.connector("node"))
+        fdnd.enable_trace("FileDescriptorPcapTrace")
+        return fdnd
+
+    def add_ns3_node(self, ns3_desc):
+        node = ns3_desc.create("ns3::Node")
+        ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
+        arp  = ns3_desc.create("ns3::ArpL3Protocol")
+        icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
+        udp = ns3_desc.create("ns3::UdpL4Protocol")
+        node.connector("protos").connect(ipv4.connector("node"))
+        node.connector("protos").connect(arp.connector("node"))
+        node.connector("protos").connect(icmp.connector("node"))
+        node.connector("protos").connect(udp.connector("node"))
+        return node
+
+    def add_ns3_wifi(self, node, ns3_desc, access_point = False):
+        wifi = ns3_desc.create("ns3::WifiNetDevice")
+        node.connector("devs").connect(wifi.connector("node"))
+
+        phy = ns3_desc.create("ns3::YansWifiPhy")
+        error = ns3_desc.create("ns3::NistErrorRateModel")
+        manager = ns3_desc.create("ns3::ArfWifiManager")
+        if access_point:
+            mac = ns3_desc.create("ns3::QapWifiMac")
+        else:
+            mac = ns3_desc.create("ns3::QstaWifiMac")
+
+        phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
+        mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
+        phy.connector("err").connect(error.connector("phy"))
+        wifi.connector("phy").connect(phy.connector("dev"))
+        wifi.connector("mac").connect(mac.connector("dev"))
+        wifi.connector("manager").connect(manager.connector("dev"))
+
+        phy.enable_trace("YansWifiPhyPcapTrace")
+        return wifi, phy
+
+    def add_ns3_random_mobility(self, node, ns3_desc, x, y, z, speed, 
+            bounds_width, bounds_height):
+        position = "%d:%d:%d" % (x, y, z)
+        bounds = "0|%d|0|%d" % (bounds_width, bounds_height) 
+        speed = "Constant:%d" % speed
+        mobility = ns3_desc.create("ns3::RandomDirection2dMobilityModel")
+        mobility.set_attribute_value("Position", position)
+        mobility.set_attribute_value("Bounds", bounds)
+        mobility.set_attribute_value("Speed", speed)
+        mobility.set_attribute_value("Pause",  "Constant:1")
+        node.connector("mobility").connect(mobility.connector("node"))
+        return mobility
+
+    def add_ns3_constant_mobility(self, node, ns3_desc, x, y, z):
+        mobility = ns3_desc.create("ns3::ConstantPositionMobilityModel") 
+        position = "%d:%d:%d" % (x, y, z)
+        mobility.set_attribute_value("Position", position)
+        node.connector("mobility").connect(mobility.connector("node"))
+        return mobility
+
+    def add_ns3_wifi_channel(self, ns3_desc):
+        channel = ns3_desc.create("ns3::YansWifiChannel")
+        delay = ns3_desc.create("ns3::ConstantSpeedPropagationDelayModel")
+        loss  = ns3_desc.create("ns3::LogDistancePropagationLossModel")
+        channel.connector("delay").connect(delay.connector("chan"))
+        channel.connector("loss").connect(loss.connector("prev"))
+        return channel
+
+    def add_ip_address(self, iface, address):
+        ip = iface.add_address()
+        ip.set_attribute_value("Address", address)
+
+    def add_route(self, node, destination, netprefix, nexthop):
+        route = node.add_route()
+        route.set_attribute_value("Destination", destination)
+        route.set_attribute_value("NetPrefix", netprefix)
+        route.set_attribute_value("NextHop", nexthop)
+
+    @test_util.skipUnless(os.getuid() == 0, "Test requires root privileges")
+    def test_local(self):
+        bounds_width = bounds_height = 200
+        x = y = 100
+        speed = 1
+        user = "alina"
+        movie = "/tmp/test.ts"
+
+        exp_desc = ExperimentDescription()
+
+        ## NS3 Testbed instance description ##
+        testbed_version = "3_9_RC3"
+        testbed_id = "ns3"
+        ns3_provider = FactoriesProvider(testbed_id, testbed_version)
+        ns3_desc = exp_desc.add_testbed_description(ns3_provider)
+        ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
+        ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
+        ns3_desc.set_attribute_value("ChecksumEnabled", True)
+        # create node 1
+        node1 = self.add_ns3_node(ns3_desc)
+        mobility1 = self.add_ns3_constant_mobility(node1, ns3_desc, x, y, 0)
+        wifi1, phy1 = self.add_ns3_wifi(node1, ns3_desc, access_point = False)
+        self.add_ip_address(wifi1, "10.0.1.1")
+        fdnd1 = self.add_ns3_fdnd(node1, ns3_desc)
+        self.add_ip_address(fdnd1, "10.0.0.1")
+        # create node 2
+        node2 = self.add_ns3_node(ns3_desc)
+        mobility2 = self.add_ns3_random_mobility(node2, ns3_desc, 0, 0, 0, 
+                speed, bounds_width, bounds_height)
+        wifi2, phy2 = self.add_ns3_wifi(node2, ns3_desc, access_point = True)
+        self.add_ip_address(wifi2, "10.0.1.2")
+        fdnd2 = self.add_ns3_fdnd(node2, ns3_desc)
+        self.add_ip_address(fdnd2, "10.0.2.1")
+        # interconnect nodes with a wifi channel
+        wifichan = self.add_ns3_wifi_channel(ns3_desc)
+        phy1.connector("chan").connect(wifichan.connector("phys"))
+        phy2.connector("chan").connect(wifichan.connector("phys"))
+
+        ## NETNS testbed description 1 ##
+        testbed_version = "01"
+        testbed_id = "netns"
+        netns_provider = FactoriesProvider(testbed_id, testbed_version)
+        netns_desc1 = exp_desc.add_testbed_description(netns_provider)
+        netns_desc1.set_attribute_value("homeDirectory", self.root_dir)
+        #netns_desc1.set_attribute_value("enableDebug", True
+        # create node 3
+        node3 = netns_desc1.create("Node")
+        node3.set_attribute_value("forward_X11", True)
+        tap1 = self.add_netns_tap(node3, netns_desc1)
+        self.add_ip_address(tap1, "10.0.0.2")
+        # create vlc server
+        # DEBUG!! target = "{#[vlc_client].addr[0].[Address]#}"
+        target = "10.0.2.2" 
+        command = "vlc -I dummy -vvv %s --sout '#rtp{dst=%s,port=5004,mux=ts}' vlc:quit" \
+                % (movie, target)
+        vlc_server = netns_desc1.create("Application")
+        vlc_server.set_attribute_value("command", command)
+        vlc_server.set_attribute_value("user", user)
+        vlc_server.connector("node").connect(node3.connector("apps"))
+
+        #command = "xterm"
+        #xterm1 = netns_desc1.create("Application")
+        #xterm1.set_attribute_value("command", command)
+        #xterm1.set_attribute_value("user", user)
+        #xterm1.connector("node").connect(node3.connector("apps"))
+
+        ## NETNS testbed description 2 ##
+        netns_desc2 = exp_desc.add_testbed_description(netns_provider)
+        netns_desc2.set_attribute_value("homeDirectory", self.root_dir)
+        #netns_desc2.set_attribute_value("enableDebug", True)
+        # create node 4
+        node4 = netns_desc2.create("Node")
+        node4.set_attribute_value("forward_X11", True)
+        node4.set_attribute_value("label", "vlc_client")
+        tap2 = self.add_netns_tap(node4, netns_desc2)
+        self.add_ip_address(tap2, "10.0.2.2")
+        # create vlc client
+        vlc_client = netns_desc2.create("Application")
+        command = "vlc rtp://%s:5004/test.ts" % target
+        vlc_client.set_attribute_value("command", command)
+        vlc_client.set_attribute_value("user", user)
+        vlc_client.connector("node").connect(node4.connector("apps"))
+        #vlc_trace = vlc_server.get_trace("StderrTrace")
+        #vlc_trace.get_attribute("Filename").value = "vlc_server.err"
+        #vlc_trace.enable()        
+
+        #command = "xterm"
+        #xterm2 = netns_desc2.create("Application")
+        #xterm2.set_attribute_value("command", command)
+        #xterm2.set_attribute_value("user", user)
+        #xterm2.connector("node").connect(node4.connector("apps"))
+
+        ## testbed_interconnection
+        fdnd1.connector("fd").connect(tap1.connector("fd"))
+        fdnd2.connector("fd").connect(tap2.connector("fd"))
+      
+        self.add_route(node4, "10.0.0.0", 24, "10.0.2.1")
+        self.add_route(node4, "10.0.1.0", 24, "10.0.2.1")
+        self.add_route(node3, "10.0.2.0", 24, "10.0.0.1")
+        self.add_route(node3, "10.0.1.0", 24, "10.0.0.1")
+
+        self.add_route(node2, "10.0.0.0", 24, "10.0.1.1")
+        self.add_route(node1, "10.0.2.0", 24, "10.0.1.2")
+
+
+        xml = exp_desc.to_xml()
+        controller = ExperimentController(xml, self.root_dir)
+        controller.start()
+        while not controller.is_finished(vlc_server.guid):
+            time.sleep(0.5)
+        controller.stop()
+        controller.shutdown()
+
+    def tearDown(self):
+        shutil.rmtree(self.root_dir)
+
+if __name__ == '__main__':
+    unittest.main()
index 258772c..21a4797 100644 (file)
@@ -24,9 +24,8 @@ class Attribute(object):
     # Attribute is read only and can't be modified by the user
     # Note: ReadOnly implies DesignOnly
     ReadOnly    = 0x03
-    # Attribute is invisible to the user
-    # Note: Invisible implies ReadOnly and DesignOnly
-    Invisible   = 0x07
+    # Attribute is invisible to the user but can be modified
+    Invisible   = 0x04
     # Attribute has no default value in the testbed instance. 
     # So it needs to be set explicitely
     HasNoDefaultValue = 0x08
@@ -64,7 +63,7 @@ class Attribute(object):
         return self._flags
 
     @property
-    def invsible(self):
+    def invisible(self):
         return (self._flags & Attribute.Invisible) == Attribute.Invisible
 
     @property
index efdd938..4a6f6c2 100644 (file)
@@ -157,7 +157,7 @@ class Route(AttributesMap):
         self.add_attribute(name = "NetPrefix",
                 help = "Network destination prefix", 
                 type = Attribute.INTEGER, 
-                prefix_range = (0,128),
+                range = (0, 128),
                 value = 24,
                 flags = Attribute.HasNoDefaultValue,
                 validation_function = validation.is_integer)
index 2af898d..60cc096 100644 (file)
@@ -29,11 +29,10 @@ def connect_fd(testbed_instance, tap_guid, cross_data):
     import passfd
     import socket
     tap = testbed_instance._elements[tap_guid]
-    fd = tap.file_descriptor
     address = cross_data["LinuxSocketAddress"]
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
     sock.connect(address)
-    passfd.sendfd(sock, fd, '0')
+    passfd.sendfd(sock, tap.fd, '0')
     # TODO: after succesful transfer, the tap device should close the fd
 
 ### Creation functions ###
index 84b8f0f..5befa69 100644 (file)
@@ -44,7 +44,8 @@ class TestbedController(testbed_impl.TestbedController):
         # TODO: take on account schedule time for the task
         factory_id = self._create[guid]
         factory = self._factories[factory_id]
-        if factory.box_attributes.is_attribute_design_only(name):
+        if factory.box_attributes.is_attribute_design_only(name) or \
+                factory.box_attributes.is_attribute_invisible(name):
             return
         element = self._elements[guid]
         ns3_value = self._to_ns3_value(guid, name, value) 
@@ -55,7 +56,8 @@ class TestbedController(testbed_impl.TestbedController):
         # TODO: take on account schedule time for the task
         factory_id = self._create[guid]
         factory = self._factories[factory_id]
-        if factory.box_attributes.is_attribute_design_only(name):
+        if factory.box_attributes.is_attribute_design_only(name) or \
+                factory.box_attributes.is_attribute_invisible(name):
             return value
         TypeId = self.ns3.TypeId()
         typeid = TypeId.LookupByName(factory_id)
index fc740db..be21fc9 100644 (file)
@@ -67,7 +67,7 @@ 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)
+    filename = "trace-csma-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.CsmaHelper()
@@ -86,7 +86,7 @@ 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)
+    filename = "trace-fd-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.FileDescriptorHelper()
@@ -97,7 +97,7 @@ def yanswifipcap_trace(testbed_instance, guid, trace_id):
     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)
+    filename = "trace-yanswifi-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.YansWifiPhyHelper()
@@ -142,17 +142,6 @@ def create_node(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]
@@ -222,6 +211,15 @@ def configure_device(testbed_instance, guid):
     configure_traces(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)
+
     if not guid in testbed_instance._add_address:
         return
     # search for the node asociated with the device
@@ -341,7 +339,7 @@ factories_info = dict({
     }),
      "ns3::TapBridge": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
@@ -408,7 +406,7 @@ factories_info = dict({
     }),
      "ns3::PointToPointNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_device,
         "help": "",
         "connector_types": ["node", "err", "queue", "chan"],
@@ -624,7 +622,7 @@ factories_info = dict({
     }),
      "ns3::FileDescriptorNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_device,
         "help": "Network interface associated to a file descriptor",
         "connector_types": ["node", "fd"],
@@ -635,7 +633,7 @@ factories_info = dict({
     }),
      "ns3::CsmaNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_device,
         "help": "CSMA (carrier sense, multiple access) interface",
         "connector_types": ["node", "chan", "err", "queue"],
@@ -685,7 +683,7 @@ factories_info = dict({
     }),
      "ns3::SimpleNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": ["node", "chan"],
@@ -740,7 +738,7 @@ factories_info = dict({
     }),
      "ns3::LoopbackNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
@@ -1013,7 +1011,7 @@ factories_info = dict({
     }),
      "ns3::BaseStationNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_device,
         "help": "",
         "connector_types": [],
@@ -1085,7 +1083,7 @@ factories_info = dict({
     }),
      "ns3::EmuNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": ["node", "queue"],
@@ -1142,7 +1140,7 @@ factories_info = dict({
     }),
      "ns3::WifiNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_device,
         "help": "",
         "connector_types": ["node", "mac", "phy", "manager"],
@@ -1160,7 +1158,7 @@ factories_info = dict({
     }),
      "ns3::BridgeNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": ["node"],
@@ -1317,7 +1315,7 @@ factories_info = dict({
     }),
      "ns3::MeshPointDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
@@ -1381,7 +1379,7 @@ factories_info = dict({
     }),
      "ns3::NonCommunicatingNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
@@ -1445,7 +1443,7 @@ factories_info = dict({
     }),
      "ns3::YansWifiPhy": dict({
         "category": "Phy",
-        "create_function": create_element,
+        "create_function": create_wifi_standard_model,
         "configure_function": configure_element,
         "help": "",
         "connector_types": ["dev", "err", "chan"],
@@ -1679,7 +1677,7 @@ factories_info = dict({
     }),
      "ns3::VirtualNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
@@ -1968,7 +1966,7 @@ factories_info = dict({
     }),
      "ns3::SubscriberStationNetDevice": dict({
         "category": "Device",
-        "create_function": create_device,
+        "create_function": create_element,
         "configure_function": configure_element,
         "help": "",
         "connector_types": [],
index 57cbf66..9ce7f03 100644 (file)
@@ -29,10 +29,10 @@ def connect_phy_device(testbed_instance, phy_guid, device_guid):
     device.SetPhy(phy)
     phy.SetDevice(device)
     # search for the node asociated with the device
-    node_guid = testbed_instance.get_connected(guid, "node", "devs")
+    node_guid = testbed_instance.get_connected(device_guid, "node", "devs")
     if len(node_guid) == 0:
         raise RuntimeError("Can't instantiate interface %d outside netns \
-                node" % guid)
+                node" % device_guid)
     node = testbed_instance.elements[node_guid[0]]
     phy.SetMobility(node)
 
@@ -61,7 +61,7 @@ def connect_simple_channel_device(testbed_instance, channel_guid, device_guid):
     device = testbed_instance._elements[device_guid]
     device.SetChannel(channel)
 
-def connect_loss_channel(testbed_instance, loss, channel):
+def connect_loss_channel(testbed_instance, loss_guid, channel_guid):
     loss = testbed_instance._elements[loss_guid]
     channel = testbed_instance._elements[channel_guid]
     channel.SetPropagationLossModel(loss)
@@ -91,8 +91,11 @@ def connect_node_other(testbed_instance, node_guid, other_guid):
 
 def connect_fd(testbed_instance, fdnd_guid, cross_data):
     fdnd = testbed_instance._elements[fdnd_guid]
-    address = fdnd.socket_address
-    fdnd.set_attribute_value("LinuxSocketAddress", address)
+    endpoint = fdnd.GetEndpoint()
+    # XXX: check the method StringToBuffer of ns3::FileDescriptorNetDevice
+    # to see how the address should be decoded
+    address = endpoint.replace(":", "").decode('hex')[2:]
+    testbed_instance.set(fdnd_guid, "LinuxSocketAddress", address)
 
 ### Connector information ###