From: Claudio-Daniel Freire Date: Wed, 4 May 2011 08:13:34 +0000 (+0200) Subject: Cross connections (initial planetlab-side implementation following the tun protocol) X-Git-Tag: nepi_v2~76 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=49e0f7b1669e635397ad72545a72ccb026b8280d;p=nepi.git Cross connections (initial planetlab-side implementation following the tun protocol) --- diff --git a/src/nepi/core/execute.py b/src/nepi/core/execute.py index de3e7e16..980053cf 100644 --- a/src/nepi/core/execute.py +++ b/src/nepi/core/execute.py @@ -726,7 +726,11 @@ class ExperimentController(object): cross_data[cross_testbed_guid] = dict() cross_testbed = self._testbeds[cross_testbed_guid] for cross_guid in guid_list: - elem_cross_data = dict() + elem_cross_data = dict( + _guid = cross_guid, + _testbed_guid = cross_testbed_guid, + _testbed_id = cross_testbed.testbed_id, + _testbed_version = cross_testbed.testbed_version) cross_data[cross_testbed_guid][cross_guid] = elem_cross_data attributes_list = cross_testbed.get_attribute_list(cross_guid) for attr_name in attributes_list: diff --git a/src/nepi/core/metadata.py b/src/nepi/core/metadata.py index fe92e05d..0b30a411 100644 --- a/src/nepi/core/metadata.py +++ b/src/nepi/core/metadata.py @@ -249,6 +249,31 @@ class Metadata(object): del DC + + STANDARD_ATTRIBUTE_BUNDLES = { + "tun_proto" : dict({ + "name": "tun_proto", + "help": "TUNneling protocol used", + "type": Attribute.STRING, + "flags": Attribute.Invisible | Attribute.ReadOnly, + "validation_function": validation.is_string, + }), + "tun_addr" : dict({ + "name": "tun_addr", + "help": "IP address of the tunnel endpoint", + "type": Attribute.STRING, + "flags": Attribute.Invisible | Attribute.ReadOnly, + "validation_function": validation.is_ip_address, + }), + "tun_port" : dict({ + "name": "tun_port", + "help": "IP port of the tunnel endpoint", + "type": Attribute.INTEGER, + "flags": Attribute.Invisible | Attribute.ReadOnly, + "validation_function": validation.is_integer, + }), + } + def __init__(self, testbed_id, version): self._version = version @@ -372,7 +397,9 @@ class Metadata(object): def _add_attributes(self, factory, info, attr_key, box_attributes = False, attr_bundle = ()): if not attr_bundle and info and attr_key in info: - attr_bundle = [ (attr_id, self._metadata.attributes[attr_id]) + definitions = self.STANDARD_ATTRIBUTE_BUNDLES.copy() + definitions.update(self._metadata.attributes) + attr_bundle = [ (attr_id, definitions[attr_id]) for attr_id in info[attr_key] ] for attr_id, attr_info in attr_bundle: name = attr_info["name"] diff --git a/src/nepi/testbeds/planetlab/interfaces.py b/src/nepi/testbeds/planetlab/interfaces.py index cd0b7f08..8e2a4015 100644 --- a/src/nepi/testbeds/planetlab/interfaces.py +++ b/src/nepi/testbeds/planetlab/interfaces.py @@ -83,6 +83,12 @@ class NodeIface(object): raise RuntimeError, "All external interface devices must be connected to the Internet" +class _CrossIface(object): + def __init__(self, proto, addr, port): + self.tun_proto = proto + self.tun_addr = addr + self.tun_port = port + class TunIface(object): def __init__(self, api=None): if not api: @@ -149,6 +155,12 @@ class TunIface(object): raise RuntimeError, "Misconfigured TUN iface - missing address" def prepare(self, home_path, listening): + if not self.peer_iface and (self.peer_proto and (listening or (self.peer_addr and self.peer_port))): + # Ad-hoc peer_iface + self.peer_iface = CrossIface( + self.peer_proto, + self.peer_addr, + self.peer_port) if self.peer_iface: if not self.peer_proto_impl: self.peer_proto_impl = tunproto.PROTO_MAP[self.peer_proto]( @@ -157,7 +169,7 @@ class TunIface(object): self.peer_proto_impl.prepare() def setup(self): - if self.peer_iface: + if self.peer_proto_impl: self.peer_proto_impl.setup() def cleanup(self): diff --git a/src/nepi/testbeds/planetlab/metadata_v01.py b/src/nepi/testbeds/planetlab/metadata_v01.py index 27d96796..6cb15c7a 100644 --- a/src/nepi/testbeds/planetlab/metadata_v01.py +++ b/src/nepi/testbeds/planetlab/metadata_v01.py @@ -103,6 +103,19 @@ def connect_tun_iface_peer(proto, testbed_instance, iface_guid, peer_iface_guid) iface.peer_proto = \ iface.tun_proto = proto +def crossconnect_tun_iface_peer_init(proto, testbed_instance, iface_guid, peer_iface_data): + iface = testbed_instance._elements[iface_guid] + iface.peer_iface = None + iface.peer_addr = peer_iface_data.get("tun_addr") + iface.peer_proto = peer_iface_data.get("tun_proto") + iface.peer_port = peer_iface_data.get("tun_port") + iface.tun_proto = proto + + preconfigure_tuniface(testbed_instance, iface_guid) + +def crossconnect_tun_iface_peer_compl(proto, testbed_instance, iface_guid, peer_iface_data): + postconfigure_tuniface(testbed_instance, iface_guid) + def connect_dep(testbed_instance, node_guid, app_guid): node = testbed_instance._elements[node_guid] app = testbed_instance._elements[app_guid] @@ -268,8 +281,9 @@ def preconfigure_tuniface(testbed_instance, guid): break # Set standard TUN attributes - element.tun_addr = element.external_iface.address - element.tun_port = 15000 + int(guid) + if (not element.tun_addr or not element.tun_port) and element.external_iface: + element.tun_addr = element.external_iface.address + element.tun_port = 15000 + int(guid) # Set enabled traces traces = testbed_instance._get_traces(guid) @@ -279,9 +293,23 @@ def preconfigure_tuniface(testbed_instance, guid): element.validate() # First-phase setup - element.prepare( - 'tun-%s' % (guid,), - id(element) < id(element.peer_iface) ) + if element.peer_proto: + if element.peer_iface and isinstance(element.peer_iface, testbed_instance._interfaces.TunIface): + # intra tun + listening = id(element) < id(element.peer_iface) + else: + # cross tun + if not element.tun_addr or not element.tun_port: + listening = True + elif not element.peer_addr or not element.peer_port: + listening = True + else: + # both have addresses... + # ...the one with the lesser address listens + listening = element.tun_addr < element.peer_addr + element.prepare( + 'tun-%s' % (guid,), + listening) def postconfigure_tuniface(testbed_instance, guid): element = testbed_instance._elements[guid] @@ -463,6 +491,20 @@ connections = [ "init_code": functools.partial(connect_tun_iface_peer,"udp"), "can_cross": False }), + dict({ + "from": (TESTBED_ID, TUNIFACE, "tcp"), + "to": (None, None, "tcp"), + "init_code": functools.partial(crossconnect_tun_iface_peer_init,"tcp"), + "compl_code": functools.partial(crossconnect_tun_iface_peer_compl,"tcp"), + "can_cross": True + }), + dict({ + "from": (TESTBED_ID, TUNIFACE, "udp"), + "to": (None, None, "udp"), + "init_code": functools.partial(crossconnect_tun_iface_peer_init,"udp"), + "compl_code": functools.partial(crossconnect_tun_iface_peer_compl,"udp"), + "can_cross": True + }), ] attributes = dict({ @@ -823,7 +865,8 @@ factories_info = dict({ "configure_function": postconfigure_tuniface, "box_attributes": [ "up", "device_name", "mtu", "snat", - "txqueuelen" + "txqueuelen", + "tun_proto", "tun_addr", "tun_port" ], "traces": ["packets"], "connector_types": ["node","udp","tcp"]