From: Alina Quereilhac Date: Mon, 2 May 2011 08:17:07 +0000 (+0200) Subject: vlc wireless hybrid experiment example added X-Git-Tag: nepi_v2~93 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=eea6191380695c456280a1624aa7037d2f098f7e;p=nepi.git vlc wireless hybrid experiment example added --- diff --git a/examples/vlc_wireless_netns_ns3.py b/examples/vlc_wireless_netns_ns3.py new file mode 100644 index 00000000..9a5ae4c6 --- /dev/null +++ b/examples/vlc_wireless_netns_ns3.py @@ -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() diff --git a/src/nepi/core/attributes.py b/src/nepi/core/attributes.py index 258772c7..21a47973 100644 --- a/src/nepi/core/attributes.py +++ b/src/nepi/core/attributes.py @@ -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 diff --git a/src/nepi/core/design.py b/src/nepi/core/design.py index efdd9380..4a6f6c27 100644 --- a/src/nepi/core/design.py +++ b/src/nepi/core/design.py @@ -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) diff --git a/src/nepi/testbeds/netns/metadata_v01.py b/src/nepi/testbeds/netns/metadata_v01.py index 2af898d5..60cc096e 100644 --- a/src/nepi/testbeds/netns/metadata_v01.py +++ b/src/nepi/testbeds/netns/metadata_v01.py @@ -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 ### diff --git a/src/nepi/testbeds/ns3/execute.py b/src/nepi/testbeds/ns3/execute.py index 84b8f0f2..5befa69c 100644 --- a/src/nepi/testbeds/ns3/execute.py +++ b/src/nepi/testbeds/ns3/execute.py @@ -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) diff --git a/src/nepi/testbeds/ns3/factories_metadata_v3_9_RC3.py b/src/nepi/testbeds/ns3/factories_metadata_v3_9_RC3.py index fc740db1..be21fc92 100644 --- a/src/nepi/testbeds/ns3/factories_metadata_v3_9_RC3.py +++ b/src/nepi/testbeds/ns3/factories_metadata_v3_9_RC3.py @@ -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": [], diff --git a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py index 57cbf664..9ce7f03e 100644 --- a/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py +++ b/src/nepi/testbeds/ns3/metadata_v3_9_RC3.py @@ -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 ###