--- /dev/null
+#!/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()
# 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
return self._flags
@property
- def invsible(self):
+ def invisible(self):
return (self._flags & Attribute.Invisible) == Attribute.Invisible
@property
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)
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 ###
# 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)
# 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)
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()
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()
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()
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]
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
}),
"ns3::TapBridge": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
}),
"ns3::PointToPointNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_device,
"help": "",
"connector_types": ["node", "err", "queue", "chan"],
}),
"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"],
}),
"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"],
}),
"ns3::SimpleNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": ["node", "chan"],
}),
"ns3::LoopbackNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
}),
"ns3::BaseStationNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_device,
"help": "",
"connector_types": [],
}),
"ns3::EmuNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": ["node", "queue"],
}),
"ns3::WifiNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_device,
"help": "",
"connector_types": ["node", "mac", "phy", "manager"],
}),
"ns3::BridgeNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": ["node"],
}),
"ns3::MeshPointDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
}),
"ns3::NonCommunicatingNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
}),
"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"],
}),
"ns3::VirtualNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
}),
"ns3::SubscriberStationNetDevice": dict({
"category": "Device",
- "create_function": create_device,
+ "create_function": create_element,
"configure_function": configure_element,
"help": "",
"connector_types": [],
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)
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)
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 ###