FdNetDevice working with PlanetLab TAPs
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 20 Jan 2015 03:40:38 +0000 (04:40 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 20 Jan 2015 03:40:38 +0000 (04:40 +0100)
14 files changed:
examples/openvswitch/ping_over_udpTapTunnel_performance_test_triangleTopo.py
examples/planetlab/update_fedora_repo.py
src/nepi/resources/linux/node.py
src/nepi/resources/linux/ns3/fdtunnel.py
src/nepi/resources/linux/ns3/tun_tap_fd_link.py
src/nepi/resources/linux/rpmfuncs.py
src/nepi/resources/linux/scripts/linux-ns3-fd-udp-connect.py
src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py
src/nepi/resources/planetlab/openvswitch/ovsport.py
src/nepi/resources/planetlab/scripts/pl-vif-passfd.py
src/nepi/resources/planetlab/tap.py
src/nepi/resources/planetlab/vroute.py
src/nepi/util/sshfuncs.py
test/resources/planetlab/ns3/cross_ns3_linux_ping.py

index 5032822..0f347e9 100644 (file)
@@ -65,10 +65,11 @@ def add_udptun(ec, tap1, tap2):
     ec.register_connection(tap2, udptun)
     return udptun
 
-def add_vroute(ec, network, tap):
+def add_vroute(ec, network, prefix, tap):
     vroute = ec.register_resource("planetlab::Vroute")
-    ec.set(vroute, "action", "add")
     ec.set(vroute, "network", network)
+    ec.set(vroute, "prefix", prefix)
+    ec.set(vroute, "nexthop", ec.get(tap, "pointopoint"))
     ec.register_connection(vroute, tap)
     return vroute
 
@@ -127,16 +128,16 @@ udptun5 = add_udptun(ec, tap152, tap156)
 udptun6 = add_udptun(ec, tap204, tap206)
 
 ## Create the PlanetLab Route ## 
-vroute1 = add_vroute(ec, "192.168.3.0", tap1)
-vroute2 = add_vroute(ec, "192.168.3.0", tap13)
-vroute3 = add_vroute(ec, "192.168.3.0", tap25)
-
-vroute7 = add_vroute(ec, "192.168.3.8", tap102)
-vroute8 = add_vroute(ec, "192.168.3.0", tap104)
-vroute9 = add_vroute(ec, "192.168.3.24", tap152)
-vroute10 = add_vroute(ec, "192.168.3.0", tap156)
-vroute11 = add_vroute(ec, "192.168.3.24", tap204)
-vroute12 = add_vroute(ec, "192.168.3.8", tap206)
+vroute1 = add_vroute(ec, "192.168.3.0", "24", tap1)
+vroute2 = add_vroute(ec, "192.168.3.0", "24", tap13)
+vroute3 = add_vroute(ec, "192.168.3.0", "24", tap25)
+
+vroute7 = add_vroute(ec, "192.168.3.8", "29", tap102)
+vroute8 = add_vroute(ec, "192.168.3.0", "29", tap104)
+vroute9 = add_vroute(ec, "192.168.3.24", "29", tap152)
+vroute10 = add_vroute(ec, "192.168.3.0", "29", tap156)
+vroute11 = add_vroute(ec, "192.168.3.24", "29", tap204)
+vroute12 = add_vroute(ec, "192.168.3.8", "29", tap206)
 
 ## Create all the Ping ## 
 
index 8d4b604..7b5d88c 100644 (file)
@@ -77,7 +77,9 @@ for hostname in hosts:
     node = ec.register_resource("planetlab::Node")
     # The username in this case is the slice name, the one to use for login in 
     # via ssh into PlanetLab nodes. Replace with your own slice name.
-    ec.set(node, "hostname", hostname)
+    if hostname != "any":
+        ec.set(node, "hostname", hostname)
+
     ec.set(node, "username", pl_slice)
     ec.set(node, "identity", pl_ssh_key)
     # The pluser and plpassword are the ones used to login in the PlanetLab web 
@@ -94,11 +96,11 @@ for hostname in hosts:
             "fedora.repo")
 
     app = ec.register_resource("linux::Application")
-    ec.set(app, "sources", path_to_repo)
+    ec.set(app, "files", path_to_repo)
     ec.set(app, "sudo", True) 
     ec.set(app, "command", 
         "cp /etc/yum.repos.d/fedora.repo /etc/yum.repos.d/fedora.repo.old; "
-        "cp ${SRC}/fedora.repo /etc/yum.repos.d/fedora.repo")
+        "cp ${SHARE}/fedora.repo /etc/yum.repos.d/fedora.repo")
     ec.register_connection(node, app)
 
     apps.append(app)
@@ -109,11 +111,11 @@ for hostname in hosts:
             "fedora-updates.repo")
 
     app = ec.register_resource("linux::Application")
-    ec.set(app, "sources", path_to_repo)
+    ec.set(app, "files", path_to_repo)
     ec.set(app, "sudo", True) 
     ec.set(app, "command", 
         "cp /etc/yum.repos.d/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo.old; "
-        "cp ${SRC}/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo")
+        "cp ${SHARE}/fedora-updates.repo /etc/yum.repos.d/fedora-updates.repo")
     ec.register_connection(node, app)
     
     apps.append(app)
index ff19bbb..14aab1a 100644 (file)
@@ -28,7 +28,6 @@ import collections
 import os
 import random
 import re
-import socket
 import tempfile
 import time
 import threading
@@ -51,12 +50,12 @@ class OSType:
     """
     Supported flavors of Linux OS
     """
-    FEDORA_8 = "f8"
-    FEDORA_12 = "f12"
-    FEDORA_14 = "f14"
-    FEDORA = "fedora"
-    UBUNTU = "ubuntu"
-    DEBIAN = "debian"
+    DEBIAN = 1 
+    UBUNTU = 1 << 1 
+    FEDORA = 1 << 2
+    FEDORA_8 = 1 << 3 | FEDORA 
+    FEDORA_12 = 1 << 4 | FEDORA 
+    FEDORA_14 = 1 << 5 | FEDORA 
 
 @clsinit_copy
 class LinuxNode(ResourceManager):
@@ -291,18 +290,18 @@ class LinuxNode(ResourceManager):
 
         out = self.get_os()
 
-        if out.find("Fedora release 8") == 0:
-            self._os = OSType.FEDORA_8
-        elif out.find("Fedora release 12") == 0:
-            self._os = OSType.FEDORA_12
-        elif out.find("Fedora release 14") == 0:
-            self._os = OSType.FEDORA_14
-        elif out.find("Fedora release") == 0:
-            self._os = OSType.FEDORA
-        elif out.find("Debian") == 0: 
+        if out.find("Debian") == 0: 
             self._os = OSType.DEBIAN
         elif out.find("Ubuntu") ==0:
             self._os = OSType.UBUNTU
+        elif out.find("Fedora release") == 0:
+            self._os = OSType.FEDORA
+            if out.find("Fedora release 8") == 0:
+                self._os = OSType.FEDORA_8
+            elif out.find("Fedora release 12") == 0:
+                self._os = OSType.FEDORA_12
+            elif out.find("Fedora release 14") == 0:
+                self._os = OSType.FEDORA_14
         else:
             msg = "Unsupported OS"
             self.error(msg, out)
@@ -329,12 +328,11 @@ class LinuxNode(ResourceManager):
 
     @property
     def use_deb(self):
-        return self.os in [OSType.DEBIAN, OSType.UBUNTU]
+        return (self.os & (OSType.DEBIAN|OSType.UBUNTU))
 
     @property
     def use_rpm(self):
-        return self.os in [OSType.FEDORA_12, OSType.FEDORA_14, OSType.FEDORA_8,
-                OSType.FEDORA]
+        return (self.os & OSType.FEDORA)
 
     @property
     def localhost(self):
@@ -369,16 +367,11 @@ class LinuxNode(ResourceManager):
 
         # Get Public IP address if possible
         if not self.get("ip"):
-            ip = None
-
-            if self.localhost:
-                ip = socket.gethostbyname(socket.gethostname())
-            else:
-                try:
-                    ip = socket.gethostbyname(self.get("hostname"))
-                except:
-                    msg = "DNS can not resolve hostname %s" % self.get("hostname") 
-                    self.debug(msg)
+            try:
+                ip = sshfuncs.gethostbyname(self.get("hostname"))
+            except:
+                msg = "DNS can not resolve hostname %s" % self.get("hostname") 
+                self.debug(msg)
 
             self.set("ip", ip)
 
index a934e8d..e968ea3 100644 (file)
@@ -185,17 +185,16 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
 
         # execute the tunnel creation script
         node = self.endpoint_node(remote_endpoint) 
-        remote_ip = node.get("ip")
-        port = self.initiate(endpoint, address, remote_ip, cipher, 
+        port = self.initiate(endpoint, remote_endpoint, address, cipher, 
                 cipher_key, bwlimit, txqueuelen)
 
         return port
 
     def establish_connection(self, endpoint, remote_endpoint, port):
-        self.establish(remote_endpoint, port)
+        self.establish(endpoint, remote_endpoint, port)
 
     def verify_connection(self, endpoint, remote_endpoint):
-        self.verify()
+        self.verify(endpoint)
 
     def terminate_connection(self, endpoint, remote_endpoint):
         # Nothing to do
@@ -267,10 +266,11 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
 
         return result
 
-    def initiate(self, endpoint, address, remote_ip, cipher, cipher_key, 
+    def initiate(self, endpoint, remote_endpoint, address, cipher, cipher_key, 
             bwlimit, txqueuelen):
-        command = self._initiate_command(endpoint, address, remote_ip, 
-                cipher, cipher_key, bwlimit, txqueuelen)
+
+        command = self._initiate_command(endpoint, remote_endpoint, 
+                address, cipher, cipher_key, bwlimit, txqueuelen)
 
         node = self.endpoint_node(endpoint) 
         run_home = self.run_home(endpoint)
@@ -310,15 +310,19 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
 
         return port
 
-    def _initiate_command(self, endpoint, address, remote_ip, 
+    def _initiate_command(self, endpoint, remote_endpoint, address,
             cipher, cipher_key, bwlimit, txqueuelen):
-        node = self.endpoint_node(endpoint) 
-        run_home = self.run_home(endpoint)
-        app_home = self.app_home(endpoint)
+        local_node = self.endpoint_node(endpoint) 
+        local_run_home = self.run_home(endpoint)
+        local_app_home = self.app_home(endpoint)
+        remote_node = self.endpoint_node(remote_endpoint) 
+
+        local_ip = local_node.get("ip")
+        remote_ip = remote_node.get("ip")
 
-        local_port_file = os.path.join(run_home, "local_port")
-        remote_port_file = os.path.join(run_home,  "remote_port")
-        ret_file = os.path.join(run_home, "ret_file")
+        local_port_file = os.path.join(local_run_home, "local_port")
+        remote_port_file = os.path.join(local_run_home,  "remote_port")
+        ret_file = os.path.join(local_run_home, "ret_file")
 
         address = base64.b64encode(address)
         
@@ -327,9 +331,10 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
         command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
         command.append("python ${SRC}/linux-ns3-fd-udp-connect.py")
         command.append("-a %s" % address)
-        command.append("-l %s " % local_port_file)
-        command.append("-r %s " % remote_port_file)
-        command.append("-H %s " % remote_ip)
+        command.append("-p %s " % local_port_file)
+        command.append("-P %s " % remote_port_file)
+        command.append("-o %s " % local_ip)
+        command.append("-O %s " % remote_ip)
         command.append("-R %s " % ret_file)
         if cipher:
             command.append("-c %s " % cipher)
@@ -341,12 +346,12 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
             command.append("-b %s " % bwlimit)
 
         command = " ".join(command)
-        command = self.replace_paths(command, node=node, app_home=app_home, 
-                run_home=run_home)
+        command = self.replace_paths(command, node=local_node, 
+                app_home=local_app_home, run_home=local_run_home)
 
         return command
 
-    def establish(self, remote_endpoint, port):
+    def establish(self, endpoint, remote_endpoint, port):
         node = self.endpoint_node(endpoint) 
         run_home = self.run_home(endpoint)
 
@@ -357,6 +362,6 @@ class LinuxNs3FdUdpTunnel(LinuxUdpTunnel):
                 text = True, 
                 overwrite = False)
 
-    def verify(self):
-        self.wait_result()
+    def verify(self, endpoint):
+        self.wait_result(endpoint)
 
index cf658fc..5a3a77b 100644 (file)
@@ -16,9 +16,7 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
-
-from nepi.execution.resource import ResourceState, clsinit_copy, \
-        ResourceManager
+from nepi.execution.resource import ResourceState, clsinit_copy
 from nepi.resources.linux.application import LinuxApplication
 
 import base64
@@ -37,9 +35,9 @@ class LinuxTunTapFdLink(LinuxApplication):
         super(LinuxTunTapFdLink, self).__init__(ec, guid)
         self._tap = None
         self._fdnetdevice = None
-        self._fd = None
         self._fd_node = None
         self.send_address = None
+        self._home = "tuntap-link-%s" % self.guid
 
     @property
     def fdnetdevice(self):
index 35aeb61..5d17b31 100644 (file)
@@ -53,18 +53,18 @@ def install_rpmfusion_command(os):
 
     cmd = " { rpm -q rpmfusion-free-release || sudo -S rpm -i %(package)s ; } "
 
-    if os in [OSType.FEDORA, OSType.FEDORA_12]:
+    if (os & OSType.FEDORA_8):
+        # RpmFusion for Fedora 8 is unmaintained 
+        cmd = ""
+    elif (os & OSType.FEDORA_12):
         # For f12
         cmd =  cmd %  {'package': RPM_FUSION_URL_F12}
-    elif os == OSType.FEDORA_14:
+    elif (os & OSType.FEDORA_14):
         # For f14
         cmd = cmd %  {'package': RPM_FUSION_URL_F14}
-    elif os == OSType.FEDORA:
+    else:
         # For f14+
         cmd = cmd %  {'package': RPM_FUSION_URL}
-    else:
-        # Fedora 8 is unmaintained 
-        cmd = ""
 
     return cmd
  
index 4598868..c114122 100644 (file)
@@ -1,19 +1,30 @@
 import base64
 import errno
 import os
-import time
+import passfd
 import signal
 import socket
+import time
 import tunchannel
-import passfd
 
 from optparse import OptionParser
 
+IFF_TAP     = 0x0002
+
 # Trak SIGTERM, and set global termination flag instead of dying
 TERMINATE = []
+STARTED = False
+
 def _finalize(sig,frame):
     global TERMINATE
-    TERMINATE.append(None)
+    global STARTED
+    
+    if STARTED:
+        TERMINATE.append(None)
+    else:
+        signal.signal(signal.SIGTERM, signal.SIG_DFL)
+        os.kill(os.getpid(), signal.SIGTERM)
+
 signal.signal(signal.SIGTERM, _finalize)
 
 # SIGUSR1 suspends forwading, SIGUSR2 resumes forwarding
@@ -31,10 +42,10 @@ def _resume(sig,frame):
 signal.signal(signal.SIGUSR2, _resume)
 
 def get_options():
-    usage = ("usage: %prog -a <address> "
-            "-b <bwlimit> -c <cipher> -k <cipher-key> -q <txqueuelen> " 
-            "-l <local-port-file> -r <remote-port-file> -H <remote-host> "
-            "-R <ret-file> ")
+    usage = ("usage: %prog -a <address> -b <bwlimit> -c <cipher> "
+            "- k <cipher-key> -q <txqueuelen> -p <local-port-file> "
+            "-P <remote-port-file> -o <local-ip> -O <remote-ip> "
+            "-r <ret-file> ")
     
     parser = OptionParser(usage = usage)
 
@@ -57,14 +68,16 @@ def get_options():
             "on the system." ,
         default=None, type="str")
 
-    parser.add_option("-l", "--local-port-file", dest="local_port_file",
+    parser.add_option("-p", "--local-port-file", dest="local_port_file",
         help = "File where to store the local binded UDP port number ", 
         default = "local_port_file", type="str")
-    parser.add_option("-r", "--remote-port-file", dest="remote_port_file",
+    parser.add_option("-P", "--remote-port-file", dest="remote_port_file",
         help = "File where to read the remote UDP port number to connect to", 
         default = "remote_port_file", type="str")
-    parser.add_option("-H", "--remote-host", dest="remote_host",
-        help = "Remote host IP", default = "remote_host", type="str")
+    parser.add_option("-o", "--local-ip", dest="local_ip",
+        help = "Local host IP", type="str")
+    parser.add_option("-O", "--remote-ip", dest="remote_ip",
+        help = "Remote host IP", type="str")
     parser.add_option("-R", "--ret-file", dest="ret_file",
         help = "File where to store return code (success of connection) ", 
         default = "ret_file", type="str")
@@ -73,20 +86,19 @@ def get_options():
        
     address = base64.b64decode(options.address)
 
-    return ( address
-            options.local_port_file, options.remote_port_file, 
-            options.remote_host, options.ret_file, options.bwlimit
-            options.cipher, options.cipher_key, options.txqueuelen )
+    return (address, options.local_port_file, options.remote_port_file
+            options.local_ip, options.remote_ip, options.ret_file, 
+            options.bwlimit, options.cipher, options.cipher_key
+            options.txqueuelen)
 
 if __name__ == '__main__':
 
-    (address, local_port_file, remote_port_file, remote_host, ret_file
-            bwlimit, cipher, cipher_key, txqueuelen) = get_options()
+    (address, local_port_file, remote_port_file, local_ip, remote_ip
+            ret_file, bwlimit, cipher, cipher_key, txqueuelen) = get_options()
 
     # Create a local socket to stablish the tunnel connection
-    hostaddr = socket.gethostbyname(socket.gethostname())
     rsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
-    rsock.bind((hostaddr, 0))
+    rsock.bind((local_ip, 0))
     (local_host, local_port) = rsock.getsockname()
 
     # Save local port information to file
@@ -119,7 +131,7 @@ if __name__ == '__main__':
     remote_port = int(remote_port)
 
     # Connect local socket to remote port
-    rsock.connect((remote_host, remote_port))
+    rsock.connect((remote_ip, remote_port))
     remote = os.fdopen(rsock.fileno(), 'r+b', 0)
 
     # create local socket to pass to fd-net-device
@@ -140,6 +152,8 @@ if __name__ == '__main__':
     f.write("0")
     f.close()
 
+    STARTED = True
+
     # Establish tunnel
     tunchannel.tun_fwd(local, remote,
         with_pi = False, # No PI headers 
index c658fb8..041e6b8 100644 (file)
 #
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
 
-from nepi.execution.attribute import Attribute, Flags, Types
-from nepi.execution.resource import ResourceManager, ResourceState, \
-        clsinit_copy
+from nepi.execution.resource import ResourceState, clsinit_copy
+from nepi.resources.linux.ns3.tun_tap_fd_link import LinuxTunTapFdLink
 
+import base64
+import fcntl
 import os
 import socket
 import struct
-import fcntl
 
 @clsinit_copy
-class PlanetlabTunTapFdLink(ResourceManager):
-    """ Interconnects a TAP or TUN Linux device to a FdNetDevice
+class PlanetlabTunTapFdLink(LinuxTunTapFdLink):
+    """ Interconnects a TAP or TUN PlanetLab device to a FdNetDevice
     """
     _rtype = "planetlab::ns3::TunTapFdLink"
 
     def __init__(self, ec, guid):
         super(PlanetlabTunTapFdLink, self).__init__(ec, guid)
-        self._tap = None
-        self._fdnetdevice = None
-        self._fd_sock_address = None
 
     @property
     def fdnetdevice(self):
@@ -44,11 +41,19 @@ class PlanetlabTunTapFdLink(ResourceManager):
             from nepi.resources.ns3.ns3fdnetdevice import NS3BaseFdNetDevice
             devices = self.get_connected(NS3BaseFdNetDevice.get_rtype())
             if not devices or len(devices) != 1: 
-                msg = "TapFdLink must be connected to exactly one FdNetDevices"
+                msg = "planetlab::ns3::TunTapFdLink must be connected to exactly one FdNetDevice"
                 self.error(msg)
                 raise RuntimeError, msg
 
             self._fdnetdevice = devices[0]
+
+            # Set PI headers on
+            self._fdnetdevice.set("EncapsulationMode", "DixPi")
+        
+            simu = self._fdnetdevice.simulation
+            from nepi.resources.planetlab.node import PlanetlabNode
+            nodes = simu.get_connected(PlanetlabNode.get_rtype())
+            self._fd_node = nodes[0]
         
         return self._fdnetdevice
 
@@ -59,7 +64,7 @@ class PlanetlabTunTapFdLink(ResourceManager):
             devices = self.get_connected(PlanetlabTap.get_rtype())
 
             if not devices or len(devices) != 1: 
-                msg = "TapFdLink must be connected to exactly one PlanetlabTap"
+                msg = "planetlab::ns3::TunTapFdLink must be connected to exactly one PlanetlabTap"
                 self.error(msg)
                 raise RuntimeError, msg
 
@@ -67,19 +72,13 @@ class PlanetlabTunTapFdLink(ResourceManager):
         
         return self._tap
 
-    @property
-    def fd_sock_address(self):
-        return self._fd_sock_address
-
-    @property
-    def node(self):
-        return self.tap.node
-
     def upload_sources(self):
         scripts = []
 
         # vif-passfd python script
-        pl_vif_passfd = os.path.join(os.path.dirname(__file__), "scripts",
+        pl_vif_passfd = os.path.join(os.path.dirname(__file__), 
+                "..",
+                "scripts",
                 "pl-vif-passfd.py")
 
         scripts.append(pl_vif_passfd)
@@ -91,61 +90,16 @@ class PlanetlabTunTapFdLink(ResourceManager):
                 os.path.join(self.node.src_dir),
                 overwrite = False)
 
-    def upload_start_command(self):
-        if self.tap.node.get("hostname") != \
-                self.fdnetdevice.node.get("hostname"):
-            msg = "Tap and FdNetDevice are not in the same host"
-            self.error(msg)
-            raise RuntimeError, msg
-
-        self._fd_sock_address = self.fdnetdevice.recv_fd()
-        self.set("command", self._start_command)
-
-        command = self.get("command")
-        env = self.get("env")
-
-        # We want to make sure the ccnd is running
-        # before the experiment starts.
-        # Run the command as a bash script in background,
-        # in the host ( but wait until the command has
-        # finished to continue )
-        env = self.replace_paths(env)
-        command = self.replace_paths(command)
-
-        shfile = os.path.join(self.app_home, "start.sh")
-        self.node.run_and_wait(command, self.run_home,
-                shfile = shfile,
-                overwrite = True)
-
-    def do_deploy(self):
-        if self.tap.state < ResourceState.READY or \
-                self.fdnetdevice.state < ResourceState.READY:
-            self.ec.schedule(self.reschedule_delay, self.deploy)
-        else:
-            self.do_discover()
-            self.do_provision()
-
-            super(PlanetlabTunTapFdLink, self).do_deploy()
-
-    def do_start(self):
-        if self.state == ResourceState.READY:
-            command = self.get("command")
-            self.info("Starting command '%s'" % command)
-
-            self.set_started()
-        else:
-            msg = " Failed to execute command '%s'" % command
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-
     @property
     def _start_command(self):
+        address = base64.b64encode(self.send_address)
+
         command = []
         # Use pl-vif-passfd.py to send fd from TAP to FdNetDevice
         command.append("sudo -S")
         command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
-        command.append("python ${SRC}/pl-vif-passfd")
-        command.append("-a %s" % self.fd_sock_address)
+        command.append("python ${SRC}/pl-vif-passfd.py")
+        command.append("-a %s" % address)
         command.append("-S %s " % self.tap.sock_name)
 
         command = " ".join(command)
index 4d863d5..f80db45 100644 (file)
@@ -186,6 +186,8 @@ class OVSPort(LinuxApplication):
         if remote_endpoint.is_rm_instance("planetlab::Tap"):
             self._vroute = self.ec.register_resource("planetlab::Vroute")
             self.ec.set(self._vroute, "action", "add")
+            self.ec.set(self._vroute, "prefix", remote_endpoint.get("prefix"))
+            self.ec.set(self._vroute, "nexthop", remote_endpoint.get("pointopoint"))
             self.ec.set(self._vroute, "network", self.get("network"))
 
             print "Vroute Guid :" + str(self._vroute)
index f1f3ce5..6332362 100644 (file)
@@ -21,20 +21,20 @@ def get_options():
 
     (options, args) = parser.parse_args()
        
-    return (options.address, options.fd_socket_name)
+    return (options.address, options.vif_socket)
 
 if __name__ == '__main__':
 
-    (address, socket_name) = get_options()
+    (address, vif_socket) = get_options()
   
     # This script sends a message (PASSFD_MSG) to the process that created 
     # the TUN/TAP device to request that it sens the file descriptor associated
     # to the TUN/TAP to another process. The other process is waiting for
     # the file descriptor on 'address'
     sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    sock.connect(socket_name)
+    sock.connect(vif_socket)
     emsg = base64.b64encode(PASSFD_MSG)
-    eargs = base64.b64encode(address)
+    eargs = address
     encoded = "%s|%s\n" % (emsg, eargs)
     sock.send(encoded)
 
index 0066b90..26277a2 100644 (file)
@@ -54,7 +54,7 @@ class PlanetlabTap(LinuxApplication):
                 "Name of the network interface (e.g. eth0, wlan0, etc)",
                 flags = Flags.NoWrite)
 
-        up = Attribute("up", "Link up", 
+        up = Attribute("up", "Link up", default = True, 
                 type = Types.Bool)
         
         snat = Attribute("snat", "Set SNAT=1", 
index 699c639..fe9c952 100644 (file)
@@ -39,12 +39,21 @@ class PlanetlabVroute(LinuxApplication):
     def _register_attributes(cls):
         action = Attribute("action", "Either add or del",
               allowed = ["add", "del"],
+              default = "add",
+              flags = Flags.Design)
+
+        prefix = Attribute("prefix", "IPv4 Prefix",
+              flags = Flags.Design)
+
+        nexthop = Attribute("nexthop", "IPv4 Address of the next hop",
               flags = Flags.Design)
 
         network = Attribute("network", "IPv4 Network Address",
               flags = Flags.Design)
 
         cls._register_attribute(action)
+        cls._register_attribute(prefix)
+        cls._register_attribute(nexthop)
         cls._register_attribute(network)
 
     def __init__(self, ec, guid):
@@ -65,7 +74,8 @@ class PlanetlabVroute(LinuxApplication):
 
     def upload_sources(self):
         # upload vif-creation python script
-        pl_vroute = os.path.join(os.path.dirname(__file__), "scripts",
+        pl_vroute = os.path.join(os.path.dirname(__file__), 
+                "scripts",
                 "pl-vroute.py")
 
         self.node.upload(pl_vroute,
@@ -86,10 +96,12 @@ class PlanetlabVroute(LinuxApplication):
         # Overwrite file every time. 
         # The stop.sh has the path to the socket, wich should change
         # on every experiment run.
-        super(PlanetlabVroute, self).upload_start_command(overwrite = True)
-
-        (out, err), proc = self.execute_command(self.get("command"), blocking = True)
+        command = self.get("command")
+        shfile = os.path.join(self.app_home, "start.sh")
+        self.node.run_and_wait(command, self.run_home,
+                shfile=shfile,
+                overwrite=True)
+  
     def do_deploy(self):
         if not self.tap or self.tap.state < ResourceState.PROVISIONED:
             self.ec.schedule(self.reschedule_delay, self.deploy)
@@ -147,20 +159,26 @@ class PlanetlabVroute(LinuxApplication):
         command = ["sudo -S python ${SRC}/pl-vroute.py"]
         command.append("-a %s" % self.get("action"))
         command.append("-n %s" % self.get("network"))
-        command.append("-p %s" % self.tap.get("prefix"))
+        command.append("-p %s" % self.get("prefix"))
         command.append("-g %s" % self.tap.get("pointopoint"))
         command.append("-f %s" % self.tap.get("deviceName"))
-        return " ".join(command)
+        command = " ".join(command)
+
+        command = self.replace_paths(command)
+        return command
 
     @property
     def _stop_command(self):
         command = ["sudo -S python ${SRC}/pl-vroute.py"]
         command.append("-a %s" % "del")
         command.append("-n %s" % self.get("network"))
-        command.append("-p %s" % self.tap.get("prefix"))
-        command.append("-g %s" % self.tap.get("pointopoint"))
+        command.append("-p %s" % self.get("prefix"))
+        command.append("-g %s" % self.get("nexthop"))
         command.append("-f %s" % self.tap.get("deviceName"))
-        return " ".join(command)
+        command = " ".join(command)
+        
+        command = self.replace_paths(command)
+        return command
 
     def valid_connection(self, guid):
         # TODO: Validate!
index 33e1e10..508d462 100644 (file)
@@ -35,6 +35,8 @@ import threading
 import time
 import tempfile
 
+_re_inet = re.compile("\d+:\s+(?P<name>[a-z0-9_-]+)\s+inet6?\s+(?P<inet>[a-f0-9.:/]+)\s+(brd\s+[0-9.]+)?.*scope\s+global.*") 
+
 logger = logging.getLogger("sshfuncs")
 
 def log(msg, level, out = None, err = None):
@@ -75,6 +77,23 @@ class ProcStatus:
 hostbyname_cache = dict()
 hostbyname_cache_lock = threading.Lock()
 
+def resolve_hostname(host):
+    ip = None
+
+    if host in ["localhost", "127.0.0.1", "::1"]:
+        try:
+           ip = socket.gethostbyname(socket.gethostname())
+        except socket.gaierror, e: #[Errno -5] No address associated with hostname
+            p = subprocess.Popen("ip -o addr list", shell=True,
+                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            stdout, stderr = p.communicate()
+            m = _re_inet.findall(stdout)
+            ip = m[0][1].split("/")[0]
+    else:
+        ip = socket.gethostbyname(host)
+
+    return ip
+
 def gethostbyname(host):
     global hostbyname_cache
     global hostbyname_cache_lock
@@ -82,7 +101,7 @@ def gethostbyname(host):
     hostbyname = hostbyname_cache.get(host)
     if not hostbyname:
         with hostbyname_cache_lock:
-            hostbyname = socket.gethostbyname(host)
+            hostbyname = resolve_hostname(host)
             hostbyname_cache[host] = hostbyname
 
             msg = " Added hostbyname %s - %s " % (host, hostbyname)
index 4b44e5d..c73d08a 100755 (executable)
@@ -43,10 +43,11 @@ def add_fd_device(ec, node, ip, prefix):
 
     return dev
 
-def add_tap_device(ec, node, ip, prefix):
+def add_tap_device(ec, node, ip, prefix, pointopoint):
     dev = ec.register_resource("planetlab::Tap")
     ec.set(dev, "ip", ip)
     ec.set(dev, "prefix", prefix)
+    ec.set(dev, "pointopoint", pointopoint)
     ec.register_connection(node, dev)
     
     return dev
@@ -65,7 +66,8 @@ def add_point2point_device(ec, node, ip, prefix):
 class LinuxNS3FdNetDeviceTest(unittest.TestCase):
     def setUp(self):
         #self.fedora_host = "nepi2.pl.sophia.inria.fr"
-        self.fedora_host = "planetlab2.sics.se"
+        #self.fedora_host = "planetlab2.s3.kth.se"
+        self.fedora_host = "planet2.servers.ua.pt"
         # ple2.ipv6.lip6.fr
         # inriarennes2.irisa.fr
         # planetlab1.upc.es
@@ -76,6 +78,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
 
     @skipIfNotAlive
     def t_cross_ping(self, host, user, identity):
+
         ec = ExperimentController(exp_id = "test-pl-ns3-tap-fd")
         
         node = ec.register_resource("planetlab::Node")
@@ -93,17 +96,24 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
         #ec.set(simu, "nsLog", "FdNetDevice")
         ec.register_connection(simu, node)
 
+        net1 = "%s.0" % self.netblock
+        net2 = "%s.4" % self.netblock
+        ip1 = "%s.1" % self.netblock
+        ip2 = "%s.2" % self.netblock
+        ip3 = "%s.5" % self.netblock
+        ip4 = "%s.6" % self.netblock
+
         nsnode1 = add_ns3_node(ec, simu)
-        dev1 = add_point2point_device(ec, nsnode1, "%s.1" % self.netblock, "30")
+        dev1 = add_point2point_device(ec, nsnode1, ip1, "30")
 
         nsnode2 = add_ns3_node(ec, simu)
-        dev2 = add_point2point_device(ec, nsnode2, "%s.2" % self.netblock, "30")
+        dev2 = add_point2point_device(ec, nsnode2, ip2, "30")
         
         # Add routes on the NS3 side
         r1 = ec.register_resource("ns3::Route")
-        ec.set(r1, "network", "%s.4" % self.netblock)
+        ec.set(r1, "network", net2)
         ec.set(r1, "prefix", "30")
-        ec.set(r1, "nexthop", "%s.1" % self.netblock)
+        ec.set(r1, "nexthop", ip1)
         ec.register_connection(r1, nsnode2)
 
         # Create channel
@@ -112,24 +122,25 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
         ec.register_connection(chan, dev1)
         ec.register_connection(chan, dev2)
 
-        fddev = add_fd_device(ec, nsnode1, "%s.5" % self.netblock, "30")
+        fddev = add_fd_device(ec, nsnode1, ip3, "30")
         ec.enable_trace(fddev, "pcap")
         ec.enable_trace(fddev, "promiscPcap")
         ec.enable_trace(fddev, "ascii")
 
-        tap = add_tap_device(ec, node, "%s.6" % self.netblock, "30")
+        tap = add_tap_device(ec, node, ip4, "30", ip3)
 
         crosslink = ec.register_resource("planetlab::ns3::TunTapFdLink")
         ec.register_connection(crosslink, tap)
         ec.register_connection(crosslink, fddev)
 
         r2 = ec.register_resource("planetlab::Vroute")
-        ec.set(r2, "action", "add")
-        ec.set(r2, "network", "%s.0/30" % self.netblock)
+        ec.set(r2, "network", net1)
+        ec.set(r2, "prefix", "30")
+        ec.set(r2, "nexthop", ip3)
         ec.register_connection(r2, tap)
 
         app = ec.register_resource("linux::Application")
-        ec.set(app, "command", "ping -c3 %s.1" % self.netblock)
+        ec.set(app, "command", "ping -c3 %s" % ip1)
         ec.register_connection(app, node)
 
         ec.register_condition(app, ResourceAction.START, simu, 
@@ -147,7 +158,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
         ec.release()
         pcap = ec.trace(fddev, "pcap")
 
-        self.assertTrue(len(pcap) > 4000)
+        self.assertTrue(len(pcap) > 1500)
         ec.shutdown()
 
     def test_cross_ping_fedora(self):