Serious refactoring of TUN/TAP and tunnel code. Linux udp/gre tunnels not yet functional
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Sat, 24 Jan 2015 18:03:38 +0000 (19:03 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Sat, 24 Jan 2015 18:03:38 +0000 (19:03 +0100)
29 files changed:
examples/omf/nitos_omf6_ping.py
examples/openvswitch/ovs_ping_2_switches.py
src/nepi/resources/linux/netns/netnsemulation.py
src/nepi/resources/linux/ns3/tuntapfdlink.py [moved from src/nepi/resources/linux/ns3/tun_tap_fd_link.py with 88% similarity]
src/nepi/resources/linux/scripts/linux-passfd.py [deleted file]
src/nepi/resources/linux/scripts/linux-tap-create.py [new file with mode: 0644]
src/nepi/resources/linux/scripts/linux-tap-delete.py [new file with mode: 0644]
src/nepi/resources/linux/scripts/linux-tap-passfd.py [moved from src/nepi/resources/planetlab/scripts/pl-vif-passfd.py with 100% similarity]
src/nepi/resources/linux/scripts/linux-udp-connect.py
src/nepi/resources/linux/tap.py
src/nepi/resources/linux/tun.py
src/nepi/resources/linux/udptunnel.py
src/nepi/resources/planetlab/ns3/tuntapfdlink.py [moved from src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py with 81% similarity]
src/nepi/resources/planetlab/openvswitch/ovsport.py
src/nepi/resources/planetlab/scripts/pl-vif-down.py
src/nepi/resources/planetlab/scripts/pl-vif-udp-connect.py [deleted file]
src/nepi/resources/planetlab/tap.py
src/nepi/resources/planetlab/tun.py
src/nepi/util/sshfuncs.py
test/resources/linux/gretunnel.py
test/resources/linux/ns3/cross_dce_linux_ccn.py
test/resources/linux/ns3/cross_ns3_linux_tuntapfdlink_ping.py [moved from test/resources/linux/ns3/cross_ns3_linux_ping.py with 100% similarity]
test/resources/linux/udptunnel.py
test/resources/planetlab/gretunnel.py
test/resources/planetlab/ns3/cross_ns3_planetlab_tuntapfdlink_ping.py [moved from test/resources/planetlab/ns3/cross_ns3_planetlab_ping.py with 100% similarity]
test/resources/planetlab/ovs.py
test/resources/planetlab/tap.py
test/resources/planetlab/tun.py
test/resources/planetlab/udptunnel.py

index 4232200..5fa27ff 100644 (file)
@@ -86,7 +86,7 @@ chan = options.channel
 gateway = options.gateway
 
 # Create the EC
-ec = ExperimentController(exp_id="nitos_omf6_ping2")
+ec = ExperimentController(exp_id="nitos_omf6_ping")
 
 # Create and Configure the Nodes
 node1 = ec.register_resource("omf::Node")
index 155fcbb..18657c9 100644 (file)
@@ -79,7 +79,6 @@ def add_tap(ec, ip, prefix, pointopoint, node):
     ec.set(tap, "ip", ip)
     ec.set(tap, "prefix", prefix)
     ec.set(tap, "pointopoint", pointopoint)
-    ec.set(tap, "up", True)
     ec.register_connection(tap, node)
     return tap
 
index 4ad8062..d7be656 100644 (file)
@@ -228,9 +228,9 @@ class LinuxNetNSEmulation(LinuxApplication, NetNSEmulation):
     @property
     def _dependencies(self):
         if self.node.use_rpm:
-            return ( " python python-devel mercurial unzip bridge-utils iproute")
+            return (" python python-devel mercurial unzip bridge-utils iproute")
         elif self.node.use_deb:
-            return ( " python python-dev mercurial unzip bridge-utils iproute")
+            return (" python python-dev mercurial unzip bridge-utils iproute")
         return ""
 
     @property
@@ -45,7 +45,7 @@ class LinuxTunTapFdLink(LinuxApplication):
             from nepi.resources.ns3.ns3fdnetdevice import NS3BaseFdNetDevice
             devices = self.get_connected(NS3BaseFdNetDevice.get_rtype())
             if not devices or len(devices) != 1: 
-                msg = "linux::ns3::TunTapFdLink must be connected to exactly one FdNetDevice"
+                msg = "TunTapFdLink must be connected to exactly one FdNetDevice"
                 self.error(msg)
                 raise RuntimeError, msg
 
@@ -68,7 +68,7 @@ class LinuxTunTapFdLink(LinuxApplication):
             from nepi.resources.linux.tap import LinuxTap
             devices = self.get_connected(LinuxTap.get_rtype())
             if not devices or len(devices) != 1: 
-                msg = "linux::ns3::TunTapLink must be connected to exactly one LinuxTap"
+                msg = "TunTapLink must be connected to exactly one Tap or Tun"
                 self.error(msg)
                 raise RuntimeError, msg
 
@@ -91,7 +91,7 @@ class LinuxTunTapFdLink(LinuxApplication):
         linux_passfd = os.path.join(os.path.dirname(__file__),
                 "..",
                 "scripts",
-                "linux-passfd.py")
+                "linux-tap-passfd.py")
 
         scripts.append(linux_passfd)
         
@@ -144,20 +144,15 @@ class LinuxTunTapFdLink(LinuxApplication):
 
     @property
     def _start_command(self):
-        vif_name = self.ec.get(self.tap.guid, "deviceName")
-        vif_type = self.tap.vif_type_flag
-        pi = self.ec.get(self.tap.guid, "pi")
         address = base64.b64encode(self.send_address)
 
         command = []
-        # Use pl-vif-passfd.py to send fd from TAP to FdNetDevice
+        # Use tap-passfd.py to send fd from TAP to FdNetDevice
+        command.append("sudo -S")
         command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
-        command.append("python ${SRC}/linux-passfd.py")
+        command.append("python ${SRC}/linux-tap-passfd.py")
         command.append("-a %s" % address)
-        command.append("-N %s " % vif_name)
-        command.append("-t %s " % vif_type)
-        if pi:
-            command.append("-p")
+        command.append("-S %s " % self.tap.sock_name)
 
         command = " ".join(command)
         command = self.replace_paths(command)
diff --git a/src/nepi/resources/linux/scripts/linux-passfd.py b/src/nepi/resources/linux/scripts/linux-passfd.py
deleted file mode 100644 (file)
index ff7014e..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-import base64
-import errno
-import fcntl
-import os
-import passfd
-import socket
-import struct
-
-from optparse import OptionParser
-
-IFF_TUN     = 0x0001
-IFF_TAP     = 0x0002
-IFF_NO_PI   = 0x1000
-TUNSETIFF   = 0x400454ca
-
-def get_options():
-    usage = ("usage: %prog -a <address> -N <vif_name> -t <vif-type> -p <pi> ")
-    
-    parser = OptionParser(usage = usage)
-
-    parser.add_option("-a", "--address", dest="address",
-        help="Socket address to send file descriptor to", type="str")
-    parser.add_option("-N", "--vif-name", dest="vif_name",
-        help="The name of the virtual interface", type="str")
-    parser.add_option("-t", "--vif-type", dest="vif_type",
-        help="Virtual interface type. Either IFF_TAP or IFF_TUN. "
-            "Defaults to IFF_TAP. ", default=IFF_TAP, type="str")
-    parser.add_option("-p", "--pi", dest="pi", action="store_true", 
-            default=False, help="Enable PI header")
-
-    (options, args) = parser.parse_args()
-       
-    vif_type = IFF_TAP
-    if options.vif_type and options.vif_type == "IFF_TUN":
-        vif_type = IFF_TUN
-    
-    address = base64.b64decode(options.address)
-
-    return (address, options.vif_name, vif_type, options.pi)
-
-if __name__ == '__main__':
-
-    (address, vif_name, vif_type, pi) = get_options()
-
-    flags = 0
-    flags |= vif_type
-
-    if not pi:
-        flags |= IFF_NO_PI
-
-    fd = os.open("/dev/net/tun", os.O_RDWR)
-
-    err = fcntl.ioctl(fd, TUNSETIFF, struct.pack("16sH", vif_name, flags))
-    if err < 0:
-        os.close(fd)
-        raise RuntimeError("Could not retrive file descriptor from %s" % vif_name)
-
-
-    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-    sock.connect(address)
-    passfd.sendfd(sock, fd, '0')
-
diff --git a/src/nepi/resources/linux/scripts/linux-tap-create.py b/src/nepi/resources/linux/scripts/linux-tap-create.py
new file mode 100644 (file)
index 0000000..50adaa2
--- /dev/null
@@ -0,0 +1,246 @@
+#
+#    NEPI, a framework to manage network experiments
+#    Copyright (C) 2013 INRIA
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+
+import base64
+import fcntl
+import errno
+import passfd
+import os
+import socket
+import subprocess
+import struct
+from optparse import OptionParser
+
+STOP_MSG = "STOP"
+PASSFD_MSG = "PASSFD"
+
+IFF_NO_PI       = 0x1000
+IFF_TUN         = 0x0001
+IFF_TAP         = 0x0002
+IFF_UP          = 0x1
+IFF_RUNNING     = 0x40
+TUNSETIFF       = 0x400454ca
+SIOCGIFFLAGS    =  0x8913
+SIOCSIFFLAGS    =  0x8914
+SIOCGIFADDR     = 0x8915
+SIOCSIFADDR     = 0x8916
+SIOCGIFNETMASK  = 0x891B
+SIOCSIFNETMASK  = 0x891C
+
+
+def create_socket(socket_name):
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock.bind(socket_name)
+    return sock
+
+def recv_msg(conn):
+    msg = []
+    chunk = ''
+
+    while '\n' not in chunk:
+        try:
+            chunk = conn.recv(1024)
+        except (OSError, socket.error), e:
+            if e[0] != errno.EINTR:
+                raise
+            # Ignore eintr errors
+            continue
+
+        if chunk:
+            msg.append(chunk)
+        else:
+            # empty chunk = EOF
+            break
+
+    msg = ''.join(msg).split('\n')[0]
+    # The message might have arguments that will be appended
+    # as a '|' separated list after the message type
+    args = msg.split("|")
+    msg = args.pop(0)
+
+    dmsg = base64.b64decode(msg)
+    dargs = []
+    for arg in args:
+        darg = base64.b64decode(arg)
+        dargs.append(darg.rstrip())
+
+    return (dmsg.rstrip(), dargs)
+
+def send_reply(conn, reply):
+    encoded = base64.b64encode(reply)
+    conn.send("%s\n" % encoded)
+
+def set_ifupdown(vif_name, up):
+    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+    
+    # get flags
+    ifreq = struct.pack("16sH", vif_name, 0)
+    ifr = fcntl.ioctl(sock.fileno(), SIOCGIFFLAGS, ifreq)
+
+    if ifr < 0:
+        os.close(sock)
+        raise RuntimeError("Could not set device %s UP" % vif_name)
+
+    name, flags = struct.unpack("16sH", ifr)
+    if up:
+        flags = flags | IFF_UP | IFF_RUNNING
+    else:
+        flags = flags & ~IFF_UP & ~IFF_RUNNING
+    
+    # set flags
+    ifreq = struct.pack("16sH", vif_name, flags)
+    ifr = fcntl.ioctl(sock.fileno(), SIOCSIFFLAGS, ifreq)
+
+    if ifr < 0:
+        os.close(sock)
+        raise RuntimeError("Could not set device %s UP" % vif_name)
+
+def set_ifaddr(vif_name, ip, prefix):
+    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
+    # configure IP
+    ifreq = struct.pack("16sH2s4s8s", vif_name, socket.AF_INET, "\x00"*2, 
+            socket.inet_aton(ip), "\x00"*8)
+    ifr = fcntl.ioctl(sock.fileno(), SIOCSIFADDR, ifreq)
+
+    if ifr < 0:
+        os.close(sock)
+        raise RuntimeError("Could not set IP address for device %s" % vif_name)
+
+    netmask = socket.inet_ntoa(struct.pack(">I", (0xffffffff << (32 - prefix)) & 0xffffffff))
+    ifreq = struct.pack("16sH2s4s8s", vif_name, socket.AF_INET, "\x00"*2,
+            socket.inet_aton(netmask), "\x00"*8)
+    ifr = fcntl.ioctl(sock.fileno(), SIOCSIFNETMASK, ifreq)
+
+    if ifr < 0:
+        os.close(sock)
+        raise RuntimeError("Could not set IP mask for device %s" % vif_name)
+
+def create_tap(vif_name, vif_type, pi):
+    flags = 0
+    flags |= vif_type
+    if not pi:
+        flags |= IFF_NO_PI
+    fd = os.open("/dev/net/tun", os.O_RDWR)
+    ifreq = struct.pack("16sH", vif_name, flags)
+    ifr = fcntl.ioctl(fd, TUNSETIFF, ifreq)
+    if ifr < 0:
+        os.close(fd)
+        raise RuntimeError("Could not configure device %s" % vif_name)
+
+    return fd
+
+def passfd_action(fd, args):
+    """ Sends the file descriptor associated to the TAP device 
+    to another process through a unix socket.
+    """
+    address = args.pop(0)
+    print address
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+    sock.connect(address)
+    passfd.sendfd(sock, fd, '0')
+
+    return "PASSFD-ACK"
+
+def down_action(fd, vif_name):
+    updown_action(fd, vif_name, False)
+    return "STOP-ACK"
+
+def get_options():
+    usage = ("usage: %prog -t <vif-type> -a <ip-address> -n <prefix> "
+        "-N <device-name> -p <pi> -S <socket-name>")
+    
+    parser = OptionParser(usage = usage)
+
+    parser.add_option("-t", "--vif-type", dest="vif_type",
+        help = "Virtual interface type. Either IFF_TAP or IFF_TUN. "
+            "Defaults to IFF_TAP. ", type="str")
+
+    parser.add_option("-a", "--ip-address", dest="ip_address",
+        help = "IPv4 address to assign to interface.",
+        type="str")
+
+    parser.add_option("-n", "--prefix", dest="prefix",
+        help = "IPv4 network prefix for the interface. ",
+        type="int")
+
+    parser.add_option("-N", "--vif-name", dest="vif_name",
+        help="The name of the virtual interface", type="str")
+
+    parser.add_option("-p", "--pi", dest="pi", action="store_true", 
+            default=False, help="Enable PI header")
+
+    parser.add_option("-S", "--socket-name", dest="socket_name",
+        help = "Name for the unix socket used to interact with this process", 
+        type="str")
+
+    (options, args) = parser.parse_args()
+    
+    vif_type = IFF_TAP
+    if options.vif_type and options.vif_type == "IFF_TUN":
+        vif_type = IFF_TUN
+
+    return (vif_type, options.vif_name, options.ip_address, options.prefix, 
+            options.pi, options.socket_name)
+
+if __name__ == '__main__':
+
+    (vif_type, vif_name, ip_address, prefix, pi, socket_name) = get_options()
+
+    # create and configure the virtual device 
+    fd = create_tap(vif_name, vif_type, pi)
+    set_ifaddr(vif_name, ip_address, prefix)
+    set_ifupdown(vif_name, True)
+
+    # create unix socket to receive instructions
+    sock = create_socket(socket_name)
+    sock.listen(0)
+
+    # wait for messages to arrive and process them
+    stop = False
+
+    while not stop:
+        conn, addr = sock.accept()
+        conn.settimeout(5)
+
+        while not stop:
+            try:
+                (msg, args) = recv_msg(conn)
+            except socket.timeout, e:
+                # Ingore time-out
+                continue
+
+            if not msg:
+                # Ignore - connection lost
+                break
+
+            if msg == STOP_MSG:
+                stop = True
+                reply = stop_action(vif_name)
+            elif msg == PASSFD_MSG:
+                reply = passfd_action(fd, args)
+
+            try:
+                send_reply(conn, reply)
+            except socket.error:
+                break
+
diff --git a/src/nepi/resources/linux/scripts/linux-tap-delete.py b/src/nepi/resources/linux/scripts/linux-tap-delete.py
new file mode 100644 (file)
index 0000000..2fa97ed
--- /dev/null
@@ -0,0 +1,61 @@
+#
+#    NEPI, a framework to manage network experiments
+#    Copyright (C) 2013 INRIA
+#
+#    This program is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+
+import base64
+import socket
+
+from optparse import OptionParser
+
+STOP_MSG = "STOP"
+
+def get_options():
+    usage = ("usage: %prog -N <vif-name> -S <socket-name>")
+    
+    parser = OptionParser(usage = usage)
+
+    parser.add_option("-N", "--vif-name", dest="vif_name",
+        help = "The name of the virtual interface, or a "
+                "unique numeric identifier to name the interface "
+                "if GRE mode is used.",
+        type="str")
+
+    parser.add_option("-S", "--socket-name", dest="socket_name",
+        help = "Name for the unix socket used to interact with this process", 
+        type="str")
+
+    (options, args) = parser.parse_args()
+   
+    return (options.socket_name, options.vif_name)
+
+if __name__ == '__main__':
+
+    (socket_name, vif_name) = get_options()
+
+    # If a socket name is sent, send the STOP message and wait for a reply
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    try:
+        sock.connect(socket_name)
+        encoded = base64.b64encode(STOP_MSG)
+        sock.send("%s\n" % encoded)
+        reply = sock.recv(1024)
+        reply = base64.b64decode(reply)
+        print reply
+    except:
+        print "Did not properly shutdown device"
+
index 330ed17..a4b662e 100644 (file)
@@ -1,14 +1,16 @@
+import base64
 import errno
 import os
 import time
+import passfd
 import signal
 import socket
 import tunchannel
-import struct
-import fcntl
 
 from optparse import OptionParser
 
+PASSFD_MSG = "PASSFD"
+
 IFF_TUN = 0x0001
 IFF_TAP     = 0x0002
 IFF_NO_PI   = 0x1000
@@ -35,61 +37,75 @@ def _resume(sig,frame):
         SUSPEND.remove(None)
 signal.signal(signal.SIGUSR2, _resume)
 
-def open_tap(vif_name, vif_type, pi):
-    flags = 0
-    flags |= vif_type
-
-    if not pi:
-        flags |= IFF_NO_PI
-
-    fd = os.open("/dev/net/tun", os.O_RDWR)
-
-    err = fcntl.ioctl(fd, TUNSETIFF, struct.pack("16sH", vif_name, flags))
-    if err < 0:
-        os.close(fd)
-        raise RuntimeError("Could not configure device %s" % vif_name)
+def get_fd(socket_name):
+    # Socket to recive the file descriptor
+    fdsock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+    fdsock.bind("")
+    address = fdsock.getsockname()
+
+    # Socket to connect to the pl-vif-create process 
+    # and send the PASSFD message
+    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+    sock.connect(socket_name)
+    emsg = base64.b64encode(PASSFD_MSG)
+    eargs = base64.b64encode(address)
+    encoded = "%s|%s\n" % (emsg, eargs)
+    sock.send(encoded)
+
+    # Receive fd
+    (fd, msg) = passfd.recvfd(fdsock)
+    
+    # Receive reply
+    reply = sock.recv(1024)
+    reply = base64.b64decode(reply)
 
+    sock.close()
+    fdsock.close()
     return fd
 
 def get_options():
-    usage = ("usage: %prog -N <vif_name> -t <vif-type> -p <pi> "
+    usage = ("usage: %prog -t <vif-type> -S <fd-socket-name> -n <pi> "
             "-b <bwlimit> -c <cipher> -k <cipher-key> -q <txqueuelen> " 
-            "-l <local-port-file> -r <remote-port-file> -H <remote-host> "
+            "-p <local-port-file> -P <remote-port-file> "
+            "-o <local-ip> -P <remote-ip> "
             "-R <ret-file> ")
     
     parser = OptionParser(usage = usage)
 
-    parser.add_option("-N", "--vif-name", dest="vif_name",
-        help="The name of the virtual interface", type="str")
     parser.add_option("-t", "--vif-type", dest="vif_type",
-        help="Virtual interface type. Either IFF_TAP or IFF_TUN. "
-            "Defaults to IFF_TAP. ", default=IFF_TAP, type="str")
+        help = "Virtual interface type. Either IFF_TAP or IFF_TUN. "
+            "Defaults to IFF_TAP. ", type="str")
+    parser.add_option("-S", "--fd-socket-name", dest="fd_socket_name",
+        help = "Name for the unix socket to request the TAP file descriptor", 
+        default = "tap.sock", type="str")
     parser.add_option("-n", "--pi", dest="pi", action="store_true", 
             default=False, help="Enable PI header")
 
     parser.add_option("-b", "--bwlimit", dest="bwlimit",
-        help="Specifies the interface's emulated bandwidth in bytes ",
-        default=None, type="int")
+        help = "Specifies the interface's emulated bandwidth in bytes ",
+        default = None, type="int")
     parser.add_option("-q", "--txqueuelen", dest="txqueuelen",
-        help="Specifies the interface's transmission queue length. ",
-        default=1000, type="int")
+        help = "Specifies the interface's transmission queue length. ",
+        default = 1000, type="int")
     parser.add_option("-c", "--cipher", dest="cipher",
-        help="Cipher to encript communication. "
+        help = "Cipher to encript communication. "
             "One of PLAIN, AES, Blowfish, DES, DES3. ",
-        default=None, type="str")
+        default = None, type="str")
     parser.add_option("-k", "--cipher-key", dest="cipher_key",
-        help="Specify a symmetric encryption key with which to protect "
+        help = "Specify a symmetric encryption key with which to protect "
             "packets across the tunnel. python-crypto must be installed "
             "on the system." ,
-        default=None, type="str")
+        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",
+    parser.add_option("-o", "--local-ip", dest="local_ip",
+        help = "Local host IP", default = "local_host", type="str")
+    parser.add_option("-O", "--remote-ip", dest="remote_ip",
         help = "Remote host IP", default = "remote_host", type="str")
     parser.add_option("-R", "--ret-file", dest="ret_file",
         help = "File where to store return code (success of connection) ", 
@@ -101,25 +117,25 @@ def get_options():
     if options.vif_type and options.vif_type == "IFF_TUN":
         vif_type = IFF_TUN
 
-    return ( options.vif_name, vif_type, options.pi
+    return (vif_type, options.pi, options.fd_socket_name
             options.local_port_file, options.remote_port_file, 
-            options.remote_host, options.ret_file, options.bwlimit, 
-            options.cipher, options.cipher_key, options.txqueuelen )
+            options.local_ip, options.remote_ip, options.ret_file, 
+            options.bwlimit, options.cipher, options.cipher_key,
+            options.txqueuelen )
 
 if __name__ == '__main__':
+    ( vif_type, pi, socket_name, local_port_file, remote_port_file,
+            local_ip, remote_ip, ret_file, bwlimit, cipher, cipher_key, 
+            txqueuelen ) = get_options()
 
-    ( vif_name, vif_type, pi, local_port_file, remote_port_file,
-      remote_host, ret_file, bwlimit, cipher, cipher_key, txqueuelen 
-         ) = get_options()
-   
     # Get the file descriptor of the TAP device from the process
     # that created it
-    fd = open_tap(vif_name, vif_type, pi)
+    fd = get_fd(socket_name)
+    tun = os.fdopen(fd, 'r+b', 0)
 
     # Create a local socket to stablish the tunnel connection
-    hostaddr = socket.gethostbyname(socket.gethostname())
     sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
-    sock.bind((hostaddr, 0))
+    sock.bind((local_ip, 0))
     (local_host, local_port) = sock.getsockname()
 
     # Save local port information to file
@@ -152,7 +168,7 @@ if __name__ == '__main__':
     remote_port = int(remote_port)
 
     # Connect local socket to remote port
-    sock.connect((remote_host, remote_port))
+    sock.connect((remote_ip, remote_port))
     remote = os.fdopen(sock.fileno(), 'r+b', 0)
 
     # TODO: Test connectivity!    
index 2a78e60..be80ee0 100644 (file)
@@ -54,7 +54,7 @@ class LinuxTap(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)
         
         pointopoint = Attribute("pointopoint", "Peer IP address", 
@@ -98,10 +98,12 @@ class LinuxTap(LinuxApplication):
 
     def __init__(self, ec, guid):
         super(LinuxTap, self).__init__(ec, guid)
-        self._home = "tap-%s" % self.guid
-        self._gre_enabled = False
-        self._tunnel_mode = False
-
+        self._gre_enabled = None
+        self._vif_prefix = "tap"
+        self._vif_type = "IFF_TAP"
+        self._vif_type_flag = LinuxTap.IFF_TAP
+        self._home = "%s-%s" % (self.vif_prefix, self.guid)
     @property
     def node(self):
         node = self.get_connected(LinuxNode.get_rtype())
@@ -110,22 +112,13 @@ class LinuxTap(LinuxApplication):
 
     @property
     def gre_enabled(self):
-        if not self._gre_enabled:
+        if self._gre_enabled is None:
             from nepi.resources.linux.gretunnel import LinuxGRETunnel
             gre = self.get_connected(LinuxGRETunnel.get_rtype())
             if gre: self._gre_enabled = True
 
         return self._gre_enabled
 
-    @property
-    def tunnel_mode(self):
-        if not self._tunnel_mode:
-            from nepi.resources.linux.tunnel import LinuxTunnel
-            tunnel = self.get_connected(LinuxTunnel.get_rtype())
-            if tunnel: self._tunnel_mode = True
-
-        return self._tunnel_mode
-
     def upload_sources(self):
         scripts = []
 
@@ -135,6 +128,16 @@ class LinuxTap(LinuxApplication):
         
         scripts.append(udp_connect)
 
+        tap_create = os.path.join(os.path.dirname(__file__), "scripts",
+                "linux-tap-create.py")
+        
+        scripts.append(tap_create)
+
+        tap_delete = os.path.join(os.path.dirname(__file__), "scripts",
+                "linux-tap-delete.py")
+        
+        scripts.append(tap_delete)
+
         # tunnel creation python script
         tunchannel = os.path.join(os.path.dirname(__file__), "scripts", 
                 "tunchannel.py")
@@ -162,7 +165,7 @@ class LinuxTap(LinuxApplication):
     def upload_start_command(self):
         # If GRE mode is enabled, TAP creation is delayed until the
         # tunnel is established
-        if not self.tunnel_mode:
+        if not self.gre_enabled:
             # We want to make sure the device is up and running
             # before the deploy is over, so we execute the 
             # start script now and wait until it finishes. 
@@ -174,16 +177,59 @@ class LinuxTap(LinuxApplication):
                 shfile = shfile,
                 overwrite = True)
 
+    def upload_start_command(self):
+        # If GRE mode is enabled, TAP creation is delayed until the
+        # tunnel is established
+        if not self.gre_enabled:
+            # Overwrite file every time. 
+            # The start.sh has the path to the socket, wich should change
+            # on every experiment run.
+            command = self.get("command")
+            
+            self.info("Uploading command '%s'" % command)
+            
+            # replace application specific paths in the command
+            command = self.replace_paths(command)
+            
+            # replace application specific paths in the environment
+            env = self.get("env")
+            env = env and self.replace_paths(env)
+
+            shfile = os.path.join(self.app_home, "start.sh")
+
+            self.node.upload_command(command, 
+                    shfile = shfile,
+                    env = env,
+                    overwrite = True)
+
+            # We want to make sure the device is up and running
+            # before the deploy finishes, so we execute now the 
+            # start script. We run it in background, because the 
+            # TAP will live for as long as the process that 
+            # created it is running, and wait until the TAP  
+            # is created. 
+            self._run_in_background()
+            
     def do_deploy(self):
         if not self.node or self.node.state < ResourceState.PROVISIONED:
             self.ec.schedule(self.reschedule_delay, self.deploy)
         else:
+            if self.gre_enabled:
+                self._vif_prefix = "gre"
+                self._home = "%s-%s" % (self.vif_prefix, self.guid)
+
             if not self.get("deviceName"):
                 self.set("deviceName", "%s%d" % (self.vif_prefix, self.guid)) 
 
             if not self.get("command"):
                 self.set("command", self._start_command)
 
+            if not self.get("depends"):
+                self.set("depends", self._dependencies)
+
+            if not self.get("install"):
+                self.set("install", self._install)
+
             self.do_discover()
             self.do_provision()
 
@@ -223,7 +269,7 @@ class LinuxTap(LinuxApplication):
                 tdiffsec(tnow(), self._last_state_check) > state_check_delay:
 
             if self.get("deviceName"):
-                (out, err), proc = self.node.execute("ip a")
+                (out, err), proc = self.node.execute("ifconfig")
 
                 if out.strip().find(self.get("deviceName")) == -1: 
                     # tap is not running is not running (socket not found)
@@ -248,8 +294,8 @@ class LinuxTap(LinuxApplication):
 
     def gre_connect(self, remote_endpoint, connection_app_home,
             connection_run_home):
-        gre_connect_command = self._gre_connect_command(
-                remote_endpoint, connection_run_home)
+        gre_connect_command = self._gre_connect_command(remote_endpoint,
+                connection_app_home, connection_run_home)
 
         # upload command to connect.sh script
         shfile = os.path.join(connection_app_home, "gre-connect.sh")
@@ -259,7 +305,11 @@ class LinuxTap(LinuxApplication):
 
         # invoke connect script
         cmd = "bash %s" % shfile
-        (out, err), proc = self.node.run(cmd, connection_run_home)
+        (out, err), proc = self.node.run(cmd, connection_run_home,
+                pidfile = "gre_connect_pidfile",
+                stdout = "gre_connect_stdout",
+                stderr = "gre_connect_stderr", 
+                )
              
         # check if execution errors occurred
         msg = " Failed to connect endpoints "
@@ -269,12 +319,15 @@ class LinuxTap(LinuxApplication):
             raise RuntimeError, msg
     
         # Wait for pid file to be generated
-        pid, ppid = self.node.wait_pid(connection_run_home)
+        pid, ppid = self.node.wait_pid(connection_run_home, 
+                pidfile = "gre_connect_pidfile")
         
         # If the process is not running, check for error information
         # on the remote machine
         if not pid or not ppid:
-            (out, err), proc = self.node.check_errors(connection_run_home)
+            (out, err), proc = self.node.check_errors(connection_run_home,
+                    stderr = "gre_connect_stderr") 
+
             # Out is what was written in the stderr file
             if err:
                 msg = " Failed to start command '%s' " % command
@@ -292,18 +345,22 @@ class LinuxTap(LinuxApplication):
     def udp_connect(self, remote_endpoint, connection_app_home, 
             connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
         udp_connect_command = self._udp_connect_command(
-                remote_endpoint, connection_run_home,
+                remote_endpoint, connection_app_home, connection_run_home,
                 cipher, cipher_key, bwlimit, txqueuelen)
 
         # upload command to connect.sh script
-        shfile = os.path.join(self.app_home, "udp-connect.sh")
+        shfile = os.path.join(connection_app_home, "udp-connect.sh")
         self.node.upload_command(udp_connect_command,
                 shfile = shfile,
                 overwrite = False)
 
         # invoke connect script
         cmd = "bash %s" % shfile
-        (out, err), proc = self.node.run(cmd, self.run_home) 
+        (out, err), proc = self.node.run(cmd, connection_run_home,
+               pidfile = "udp_connect_pidfile",
+               stdout = "udp_connect_stdout",
+               stderr = "udp_connect_stderr", 
+                ) 
              
         # check if execution errors occurred
         msg = "Failed to connect endpoints "
@@ -313,114 +370,41 @@ class LinuxTap(LinuxApplication):
             raise RuntimeError, msg
     
         # Wait for pid file to be generated
-        self._pid, self._ppid = self.node.wait_pid(self.run_home)
+        self._pid, self._ppid = self.node.wait_pid(
+                connection_run_home,
+                pidfile = "udp_connect_pidfile")
         
         # If the process is not running, check for error information
         # on the remote machine
         if not self._pid or not self._ppid:
-            (out, err), proc = self.node.check_errors(self.run_home)
+            (out, err), proc = self.node.check_errors(
+                    connection_run_home,
+                    stderr = "udp_connect_stderr")
+
             # Out is what was written in the stderr file
             if err:
                 msg = " Failed to start command '%s' " % command
                 self.error(msg, out, err)
                 raise RuntimeError, msg
 
-        port = self.wait_local_port()
-
-        return port
-
-    def _udp_connect_command(self, remote_endpoint, connection_run_home, 
-            cipher, cipher_key, bwlimit, txqueuelen):
-
-        # Set the remote endpoint to the IP of the device
-        self.set("pointopoint", remote_endpoint.get("ip"))
-        
-        # Planetlab TAPs always use PI headers
-        from nepi.resources.planetlab.tap import PlanetlabTap
-        if self.is_rm_instance(PlanetlabTap.get_rtype()):
-            self.set("pi", True)
-
-        # Public IP of the remote NODE to stablish tunnel
-        remote_ip = remote_endpoint.node.get("ip")
-
-        local_port_file = os.path.join(self.run_home, 
-                "local_port")
-
-        remote_port_file = os.path.join(self.run_home, 
-                "remote_port")
-
-        ret_file = os.path.join(self.run_home, 
-                "ret_file")
-
-        # Generate UDP connect command
-        # Use the start command to configure TAP with peer info
-        start_command = self._start_command
-        
-        command = ["( "]
-        command.append(start_command)
-
-        # Use pl-vid-udp-connect.py to stablish the tunnel between endpoints
-        command.append(") & (")
-        command.append("sudo -S")
-        command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
-        command.append("python ${SRC}/linux-udp-connect.py")
-        command.append("-N %s" % self.get("deviceName"))
-        command.append("-t %s" % self.vif_type)
-        if self.get("pi"):
-            command.append("-p")
-        command.append("-l %s " % local_port_file)
-        command.append("-r %s " % remote_port_file)
-        command.append("-H %s " % remote_ip)
-        command.append("-R %s " % ret_file)
-        if cipher:
-            command.append("-c %s " % cipher)
-        if cipher_key:
-            command.append("-k %s " % cipher_key)
-        if txqueuelen:
-            command.append("-q %s " % txqueuelen)
-        if bwlimit:
-            command.append("-b %s " % bwlimit)
-
-        command.append(")")
-
-        command = " ".join(command)
-        command = self.replace_paths(command)
-
-        return command
-
-    def _gre_connect_command(self, remote_endpoint, connection_run_home): 
-        # Set the remote endpoint to (private) device IP
-        self.set("pointopoint", remote_endpoint.get("ip"))
-        ## public node IP
-        self.set("greRemote", remote_endpoint.node.get("ip"))
-
-        # Generate GRE connect command
-        command = ["("]
-        command.append(self._stop_command)
-        command.append(") ; (")
-        command.append(self._start_gre_command)
-        command.append(")")
-
-        command = " ".join(command)
-        command = self.replace_paths(command)
-
-        return command
+        return self.wait_file(connection_run_home, "local_port")
 
     def establish_udp_connection(self, remote_endpoint,
-            connection_app_home,
-            connection_run_home, 
-            port):
+            connection_app_home, connection_run_home, port):
         # upload remote port number to file
         rem_port = "%s\n" % port
         self.node.upload(rem_port,
-                os.path.join(self.run_home, "remote_port"),
+                os.path.join(connection_run_home, "remote_port"),
                 text = True, 
                 overwrite = False)
 
-    def verify_connection(self):
-        self.wait_result()
+    def verify_connection(self, remote_endpoint,
+            connection_app_home, connection_run_home):
 
-    def terminate_connection(self):
+        return self.wait_file(connection_run_home, "ret_file")
+
+    def terminate_connection(self, remote_endpoint,
+            connection_app_home, connection_run_home):
         if  self._pid and self._ppid:
             (out, err), proc = self.node.kill(self._pid, self._ppid, 
                     sudo = True) 
@@ -434,27 +418,13 @@ class LinuxTap(LinuxApplication):
     def check_status(self):
         return self.node.status(self._pid, self._ppid)
 
-    def wait_local_port(self):
-        """ Waits until the local_port file for the endpoint is generated, 
-        and returns the port number 
-        
-        """
-        return self.wait_file("local_port")
-
-    def wait_result(self):
-        """ Waits until the return code file for the endpoint is generated 
-        
-        """ 
-        return self.wait_file("ret_file")
-    def wait_file(self, filename):
+    def wait_file(self, home, filename):
         """ Waits until file on endpoint is generated """
         result = None
         delay = 1.0
 
         for i in xrange(20):
-            (out, err), proc = self.node.check_output(
-                    self.run_home, filename)
+            (out, err), proc = self.node.check_output(home, filename)
             if out:
                 result = out.strip()
                 break
@@ -470,46 +440,60 @@ class LinuxTap(LinuxApplication):
 
     @property
     def _start_command(self):
-        command = []
-        if not self.gre_enabled:
-            # Make sure to clean TAP if it existed
-            stop_command = self._stop_command
-            
-            start_command = []
-            start_command.append("sudo -S ip tuntap add %s mode %s %s" % (
-                self.get("deviceName"),
-                self.vif_prefix,
-                "pi" if self.get("pi") else ""))
-            start_command.append("sudo -S ip link set %s up" % self.get("deviceName"))
-            start_command.append("sudo -S ip addr add %s/%s dev %s" % (
-                self.get("ip"),
-                self.get("prefix"),
-                self.get("deviceName"),
-                ))
-
-            start_command = ";".join(start_command)
-
-            command.append("(")
-            command.append(stop_command)
-            command.append(") ; (")
-            command.append(start_command)
-            command.append(")")
+        if self.gre_enabled:
+            command = []
+        else:
+            command = ["sudo -S "]
+            command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
+            command.append("python ${SRC}/linux-tap-create.py")
+            command.append("-t %s" % self.vif_type)
+            command.append("-a %s" % self.get("ip"))
+            command.append("-n %s" % self.get("prefix"))
+            command.append("-N %s " % self.get("deviceName"))
+            command.append("-S %s " % self.sock_name)
+            if self.get("pi"):
+                command.append("-p")
 
         return " ".join(command)
 
     @property
     def _stop_command(self):
-        command = []
-        command.append("sudo -S ip link set %s down" % self.get("deviceName"))
-        command.append("sudo -S ip link del %s" % self.get("deviceName"))
-        
-        return ";".join(command)
+        if self.gre_enabled:
+            command = self._stop_gre_command
+        else:
+            command = ["sudo -S "]
+            command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
+            command.append("python ${SRC}/linux-tap-delete.py")
+            command.append("-N %s " % self.get("deviceName"))
+            command.append("-S %s " % self.sock_name)
+            command = " ".join(command)
+
+        return command
+
+    def _gre_connect_command(self, remote_endpoint, 
+            connection_app_home, connecrion_app_home):
+        # Set the remote endpoint to (private) device IP
+        self.set("pointopoint", remote_endpoint.get("ip"))
+        ## public node IP
+        self.set("greRemote", remote_endpoint.node.get("ip"))
+
+        # Generate GRE connect command
+        command = ["("]
+        command.append(self._stop_gre_command)
+        command.append(") ; (")
+        command.append(self._start_gre_command)
+        command.append(")")
+
+        command = " ".join(command)
+        command = self.replace_paths(command)
+
+        return command
 
     @property
     def _start_gre_command(self):
         command = []
         command.append("sudo -S modprobe ip_gre")
-        command.append("sudo -S ip link add %s type gre remote %s local %s ttl 64 csum key %s" % (
+        command.append("sudo -S ip tunnel add %s mode gre remote %s local %s ttl 64 csum key %s" % (
                 self.get("deviceName"),
                 self.get("greRemote"),
                 self.node.get("ip"),
@@ -526,20 +510,109 @@ class LinuxTap(LinuxApplication):
 
         return ";".join(command)
 
+    @property
+    def _stop_gre_command(self):
+        command = []
+        command.append("sudo -S modprobe -r ip_gre")
+        command.append("sudo -S ip link set down dev %s" % (
+                self.get("deviceName"),
+            ))
+        command.append("sudo -S ip link del dev %s" % (
+                self.get("deviceName"),
+                ))
+
+        return ";".join(command)
+
+    def _udp_connect_command(self, remote_endpoint, 
+            connection_app_home, connection_run_home,
+            cipher, cipher_key, bwlimit, txqueuelen):
+
+        # Set the remote endpoint to the IP of the device
+        self.set("pointopoint", remote_endpoint.get("ip"))
+        
+        # Public IP of the remote NODE to stablish tunnel
+        remote_ip = remote_endpoint.node.get("ip")
+        local_ip = self.node.get("ip")
+
+        local_port_file = os.path.join(connection_run_home, 
+                "local_port")
+
+        remote_port_file = os.path.join(connection_run_home, 
+                "remote_port")
+
+        ret_file = os.path.join(connection_run_home, 
+                "ret_file")
+
+        # Generate UDP connect command
+        # Use the start command to configure TAP with peer info
+        start_command = self._start_command
+        
+        command = [""]
+        # Use pl-vid-udp-connect.py to stablish the tunnel between endpoints
+        command.append("sudo -S")
+        command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
+        command.append("python ${SRC}/linux-udp-connect.py")
+        command.append("-t %s" % self.vif_type)
+        command.append("-S %s " % self.sock_name)
+        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 self.get("pi"):
+            command.append("-n")
+        if cipher:
+            command.append("-c %s " % cipher)
+        if cipher_key:
+            command.append("-k %s " % cipher_key)
+        if txqueuelen:
+            command.append("-q %s " % txqueuelen)
+        if bwlimit:
+            command.append("-b %s " % bwlimit)
+
+        command = " ".join(command)
+        command = self.replace_paths(command)
+
+        return command
+    
+    @property
+    def _dependencies(self):
+        return "mercurial make gcc"
+
+    @property
+    def _install(self):
+        # Install python-vsys and python-passfd
+        install_passfd = ( " ( python -c 'import passfd' ) "
+                    " || "
+                    " ( "
+                    "   cd ${SRC} ; "
+                    "   hg clone http://nepi.inria.fr/code/python-passfd ; "
+                    "   cd python-passfd ; "
+                    "   make all ; "
+                    "   sudo -S make install "
+                    " )" )
+
+        return install_passfd
+
+    def valid_connection(self, guid):
+        # TODO: Validate!
+        return True
+
     @property
     def vif_type(self):
-        return "IFF_TAP"
+        return self._vif_type
 
     @property
     def vif_type_flag(self):
-        return LinuxTap.IFF_TAP
+        return self._vif_type_flag
  
     @property
     def vif_prefix(self):
-        return "tap"
+        return self._vif_prefix
 
+    @property
     def sock_name(self):
-        return os.path.join(self.run_home, "tap.sock")
+        return os.path.join(self.run_home, "%s.sock" % self.vif_prefix)
 
     def valid_connection(self, guid):
         # TODO: Validate!
index 22a5dea..0a44800 100644 (file)
@@ -29,22 +29,9 @@ class LinuxTun(LinuxTap):
 
     def __init__(self, ec, guid):
         super(LinuxTun, self).__init__(ec, guid)
-        self._home = "tun-%s" % self.guid
-
-    @property
-    def sock_name(self):
-        return os.path.join(self.run_home, "tun.sock")
+        self._vif_prefix = "tun"
+        self._vif_type = "IFF_TUN"
+        self._vif_type_flag = LinuxTap.IFF_TUN
+        self._home = "%s-%s" % (self.vif_prefix, self.guid)
     
-    @property
-    def vif_type(self):
-        return "IFF_TUN"
-
-    @property
-    def vif_type_flag(self):
-        return LinuxTap.IFF_TAP
-
-    @property
-    def vif_prefix(self):
-        return "tun"
-
 
index c00459c..9a241d8 100644 (file)
@@ -113,10 +113,20 @@ class LinuxUdpTunnel(LinuxTunnel):
                 port)
 
     def verify_connection(self, endpoint, remote_endpoint):
-        endpoint.verify_connection()
+        connection_app_home = self.app_home(endpoint)
+        connection_run_home = self.run_home(endpoint)
+
+        endpoint.verify_connection(remote_endpoint,
+                connection_app_home, 
+                connection_run_home)
 
     def terminate_connection(self, endpoint, remote_endpoint):
-        endpoint.terminate_connection()
+        connection_app_home = self.app_home(endpoint)
+        connection_run_home = self.run_home(endpoint)
+
+        endpoint.terminate_connection(remote_endpoint,
+                connection_app_home, 
+                connection_run_home)
 
     def check_state_connection(self):
         # Make sure the process is still running in background
@@ -143,38 +153,4 @@ class LinuxUdpTunnel(LinuxTunnel):
             else:
                 self.set_stopped()
 
-    def wait_local_port(self, endpoint):
-        """ Waits until the local_port file for the endpoint is generated, 
-        and returns the port number 
-        
-        """
-        return self.wait_file(endpoint, "local_port")
-
-    def wait_result(self, endpoint):
-        """ Waits until the return code file for the endpoint is generated 
-        
-        """ 
-        return self.wait_file(endpoint, "ret_file")
-    def wait_file(self, endpoint, filename):
-        """ Waits until file on endpoint is generated """
-        result = None
-        delay = 1.0
-
-        for i in xrange(20):
-            (out, err), proc = endpoint.node.check_output(
-                    self.run_home(endpoint), filename)
-
-            if out:
-                result = out.strip()
-                break
-            else:
-                time.sleep(delay)
-                delay = delay * 1.5
-        else:
-            msg = "Couldn't retrieve %s" % filename
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-
-        return result
 
@@ -18,7 +18,7 @@
 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
 
 from nepi.execution.resource import ResourceState, clsinit_copy
-from nepi.resources.linux.ns3.tun_tap_fd_link import LinuxTunTapFdLink
+from nepi.resources.linux.ns3.tuntapfdlink import LinuxTunTapFdLink
 
 import base64
 import fcntl
@@ -77,9 +77,10 @@ class PlanetlabTunTapFdLink(LinuxTunTapFdLink):
 
         # vif-passfd python script
         pl_vif_passfd = os.path.join(os.path.dirname(__file__), 
-                "..",
+                "..", "..",
+                "linux",
                 "scripts",
-                "pl-vif-passfd.py")
+                "linux-tap-passfd.py")
 
         scripts.append(pl_vif_passfd)
         
@@ -90,20 +91,3 @@ class PlanetlabTunTapFdLink(LinuxTunTapFdLink):
                 os.path.join(self.node.src_dir),
                 overwrite = False)
 
-    @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.py")
-        command.append("-a %s" % address)
-        command.append("-S %s " % self.tap.sock_name)
-
-        command = " ".join(command)
-        command = self.replace_paths(command)
-
-        return command
-
index f2cfb3e..25f7c03 100644 (file)
@@ -229,11 +229,13 @@ class PlanetlabOVSPort(LinuxApplication):
         command = " ".join(command)
         command = self.replace_paths(command)
         return command
-        
-    def verify_connection(self):
+       
+    def verify_connection(self, remote_endpoint, connection_app_home, 
+                connection_run_home):
         self.ovsswitch.ovs_status()
 
-    def terminate_connection(self):
+    def terminate_connection(self, endpoint, connection_app_home, 
+                connection_run_home):
         return True
 
     def check_status(self):
index caac65a..8164455 100644 (file)
@@ -70,13 +70,15 @@ if __name__ == '__main__':
     # If a socket name is sent, send the STOP message and wait for a reply
     if socket_name:
         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-        sock.connect(socket_name)
-        encoded = base64.b64encode(STOP_MSG)
-        sock.send("%s\n" % encoded)
-        reply = sock.recv(1024)
-        reply = base64.b64decode(reply)
-        print reply
-
+        try:
+            sock.connect(socket_name)
+            encoded = base64.b64encode(STOP_MSG)
+            sock.send("%s\n" % encoded)
+            reply = sock.recv(1024)
+            reply = base64.b64decode(reply)
+            print reply
+        except:
+            print "Did not properly shutdown device"
     # If a slicename is provided, use it to remove a GRE device
     elif slicename:
         import pwd
diff --git a/src/nepi/resources/planetlab/scripts/pl-vif-udp-connect.py b/src/nepi/resources/planetlab/scripts/pl-vif-udp-connect.py
deleted file mode 100644 (file)
index fa16879..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-import base64
-import errno
-import os
-import passfd
-import signal
-import socket
-import time
-import tunchannel
-import vsys
-
-from optparse import OptionParser
-
-PASSFD_MSG = "PASSFD"
-
-# Trak SIGTERM, and set global termination flag instead of dying
-TERMINATE = []
-def _finalize(sig,frame):
-    global TERMINATE
-    TERMINATE.append(None)
-signal.signal(signal.SIGTERM, _finalize)
-
-# SIGUSR1 suspends forwading, SIGUSR2 resumes forwarding
-SUSPEND = []
-def _suspend(sig,frame):
-    global SUSPEND
-    if not SUSPEND:
-        SUSPEND.append(None)
-signal.signal(signal.SIGUSR1, _suspend)
-
-def _resume(sig,frame):
-    global SUSPEND
-    if SUSPEND:
-        SUSPEND.remove(None)
-signal.signal(signal.SIGUSR2, _resume)
-
-def get_fd(socket_name):
-    # Socket to recive the file descriptor
-    fdsock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
-    fdsock.bind("")
-    address = fdsock.getsockname()
-
-    # Socket to connect to the pl-vif-create process 
-    # and send the PASSFD message
-    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    sock.connect(socket_name)
-    emsg = base64.b64encode(PASSFD_MSG)
-    eargs = base64.b64encode(address)
-    encoded = "%s|%s\n" % (emsg, eargs)
-    sock.send(encoded)
-
-    # Receive fd
-    (fd, msg) = passfd.recvfd(fdsock)
-    
-    # Receive reply
-    reply = sock.recv(1024)
-    reply = base64.b64decode(reply)
-
-    sock.close()
-    fdsock.close()
-    return fd
-
-def get_options():
-    usage = ("usage: %prog -t <vif-type> -S <fd-socket-name> "
-            "-b <bwlimit> -c <cipher> -k <cipher-key> -q <txqueuelen> " 
-            "-l <local-port-file> -r <remote-port-file> -H <remote-host> "
-            "-R <ret-file> ")
-    
-    parser = OptionParser(usage = usage)
-
-    parser.add_option("-t", "--vif-type", dest="vif_type",
-        help = "Virtual interface type. Either IFF_TAP or IFF_TUN. "
-            "Defaults to IFF_TAP. ", type="str")
-    parser.add_option("-S", "--fd-socket-name", dest="fd_socket_name",
-        help = "Name for the unix socket to request the TAP file descriptor", 
-        default = "tap.sock", type="str")
-
-    parser.add_option("-b", "--bwlimit", dest="bwlimit",
-        help = "Specifies the interface's emulated bandwidth in bytes ",
-        default = None, type="int")
-    parser.add_option("-q", "--txqueuelen", dest="txqueuelen",
-        help = "Specifies the interface's transmission queue length. ",
-        default = 1000, type="int")
-    parser.add_option("-c", "--cipher", dest="cipher",
-        help = "Cipher to encript communication. "
-            "One of PLAIN, AES, Blowfish, DES, DES3. ",
-        default = None, type="str")
-    parser.add_option("-k", "--cipher-key", dest="cipher_key",
-        help = "Specify a symmetric encryption key with which to protect "
-            "packets across the tunnel. python-crypto must be installed "
-            "on the system." ,
-        default = None, type="str")
-
-    parser.add_option("-l", "--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",
-        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("-R", "--ret-file", dest="ret_file",
-        help = "File where to store return code (success of connection) ", 
-        default = "ret_file", type="str")
-
-    (options, args) = parser.parse_args()
-       
-    vif_type = vsys.IFF_TAP
-    if options.vif_type and options.vif_type == "IFF_TUN":
-        vif_type = vsys.IFF_TUN
-
-    return ( vif_type, options.fd_socket_name, options.local_port_file,
-            options.remote_port_file, options.remote_host, options.ret_file, 
-            options.bwlimit, options.cipher, options.cipher_key,
-            options.txqueuelen )
-
-if __name__ == '__main__':
-
-    ( vif_type, socket_name, local_port_file, remote_port_file,
-      remote_host, ret_file, bwlimit, cipher, cipher_key, txqueuelen 
-         ) = get_options()
-   
-    # Get the file descriptor of the TAP device from the process
-    # that created it
-    fd = get_fd(socket_name)
-    tun = os.fdopen(int(fd), 'r+b', 0)
-
-    # Create a local socket to stablish the tunnel connection
-    hostaddr = socket.gethostbyname(socket.gethostname())
-    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
-    sock.bind((hostaddr, 0))
-    (local_host, local_port) = sock.getsockname()
-
-    # Save local port information to file
-    f = open(local_port_file, 'w')
-    f.write("%d\n" % local_port)
-    f.close()
-
-    # Wait until remote port information is available
-    while not os.path.exists(remote_port_file):
-        time.sleep(2)
-
-    remote_port = ''
-    # Read remote port from file
-    # Try until something is read...
-    # xxx: There seems to be a weird behavior where
-    #       even if the file exists and had the port number,
-    #       the read operation returns empty string!
-    #       Maybe a race condition?
-    for i in xrange(10):
-        f = open(remote_port_file, 'r')
-        remote_port = f.read()
-        f.close()
-
-        if remote_port:
-            break
-        
-        time.sleep(2)
-    
-    remote_port = remote_port.strip()
-    remote_port = int(remote_port)
-
-    # Connect local socket to remote port
-    sock.connect((remote_host, remote_port))
-    remote = os.fdopen(sock.fileno(), 'r+b', 0)
-
-    # TODO: Test connectivity!    
-
-    # Create a ret_file to indicate success
-    f = open(ret_file, 'w')
-    f.write("0")
-    f.close()
-
-    # Establish tunnel
-    tunchannel.tun_fwd(tun, remote,
-        with_pi = True, # Planetlab TAP devices add PI headers 
-        ether_mode = (vif_type == vsys.IFF_TAP),
-        udp = True,
-        cipher_key = cipher_key,
-        cipher = cipher,
-        TERMINATE = TERMINATE,
-        SUSPEND = SUSPEND,
-        tunqueue = txqueuelen,
-        tunkqueue = 500,
-        bwlimit = bwlimit
-    ) 
-
index 5df36c4..61ff3d6 100644 (file)
@@ -19,7 +19,7 @@
 
 from nepi.execution.attribute import Attribute, Flags, Types
 from nepi.execution.resource import clsinit_copy, ResourceState 
-from nepi.resources.linux.application import LinuxApplication
+from nepi.resources.linux.tap import LinuxTap
 from nepi.resources.planetlab.node import PlanetlabNode
 from nepi.util.timefuncs import tnow, tdiffsec
 
@@ -29,72 +29,18 @@ import time
 PYTHON_VSYS_VERSION = "1.0"
 
 @clsinit_copy
-class PlanetlabTap(LinuxApplication):
+class PlanetlabTap(LinuxTap):
     _rtype = "planetlab::Tap"
     _help = "Creates a TAP device on a PlanetLab host"
     _platform = "planetlab"
 
     @classmethod
     def _register_attributes(cls):
-        ip = Attribute("ip", "IP of the endpoint. This is the attribute " 
-                                "you should use to establish a tunnel or a remote "
-                                "connection between endpoint",
-              flags = Flags.Design)
-
-        mac = Attribute("mac", "MAC Address",
-                flags = Flags.Design)
-
-        prefix = Attribute("prefix", "IPv4 network prefix of the endpoint",
-                flags = Flags.Design)
-
-        mtu = Attribute("mtu", "Maximum transmition unit for device",
-                type = Types.Integer)
-
-        devname = Attribute("deviceName", 
-                "Name of the network interface (e.g. eth0, wlan0, etc)",
-                flags = Flags.NoWrite)
-
-        up = Attribute("up", "Link up", default = True, 
-                type = Types.Bool)
-        
         snat = Attribute("snat", "Set SNAT=1", 
                 type = Types.Bool,
                 flags = Flags.Design)
         
-        pointopoint = Attribute("pointopoint", "Peer IP address", 
-                flags = Flags.Design)
-
-        txqueuelen = Attribute("txqueuelen", "Length of transmission queue", 
-                flags = Flags.Design)
-
-        txqueuelen = Attribute("txqueuelen", "Length of transmission queue", 
-                flags = Flags.Design)
-
-        gre_key = Attribute("greKey", 
-                "GRE key to be used to configure GRE tunnel", 
-                default = "1",
-                flags = Flags.Design)
-
-        gre_remote = Attribute("greRemote", 
-                "Public IP of remote endpoint for GRE tunnel", 
-                flags = Flags.Design)
-
-        tear_down = Attribute("tearDown", 
-                "Bash script to be executed before releasing the resource",
-                flags = Flags.Design)
-
-        cls._register_attribute(ip)
-        cls._register_attribute(mac)
-        cls._register_attribute(prefix)
-        cls._register_attribute(mtu)
-        cls._register_attribute(devname)
-        cls._register_attribute(up)
         cls._register_attribute(snat)
-        cls._register_attribute(pointopoint)
-        cls._register_attribute(txqueuelen)
-        cls._register_attribute(gre_key)
-        cls._register_attribute(gre_remote)
-        cls._register_attribute(tear_down)
 
     def __init__(self, ec, guid):
         super(PlanetlabTap, self).__init__(ec, guid)
@@ -107,15 +53,6 @@ class PlanetlabTap(LinuxApplication):
         if node: return node[0]
         raise RuntimeError, "TAP/TUN devices must be connected to Node"
 
-    @property
-    def gre_enabled(self):
-        if not self._gre_enabled:
-            from nepi.resources.linux.gretunnel import LinuxGRETunnel
-            gre = self.get_connected(LinuxGRETunnel.get_rtype())
-            if gre: self._gre_enabled = True
-
-        return self._gre_enabled
-
     def upload_sources(self):
         scripts = []
 
@@ -138,14 +75,20 @@ class PlanetlabTap(LinuxApplication):
         scripts.append(pl_vif_down)
 
         # udp-connect python script
-        pl_vif_connect = os.path.join(os.path.dirname(__file__), "scripts",
-                "pl-vif-udp-connect.py")
+        udp_connect = os.path.join(os.path.dirname(__file__), 
+                "..",
+                "linux",
+                "scripts",
+                "linux-udp-connect.py")
         
-        scripts.append(pl_vif_connect)
+        scripts.append(udp_connect)
 
         # tunnel creation python script
-        tunchannel = os.path.join(os.path.dirname(__file__), "..", "linux",
-                "scripts", "tunchannel.py")
+        tunchannel = os.path.join(os.path.dirname(__file__), 
+                "..", 
+                "linux",
+                "scripts", 
+                "tunchannel.py")
 
         scripts.append(tunchannel)
 
@@ -167,103 +110,18 @@ class PlanetlabTap(LinuxApplication):
                 overwrite = True)
 
     def upload_start_command(self):
-        # If GRE mode is enabled, TAP creation is delayed until the
-        # tunnel is established
+        super(PlanetlabTap, self).upload_start_command()
+
+        # Planetlab TAPs always add a PI header
+        self.set("pi", True)
+
         if not self.gre_enabled:
-            # Overwrite file every time. 
-            # The start.sh has the path to the socket, wich should change
-            # on every experiment run.
-            super(PlanetlabTap, self).upload_start_command(overwrite = True)
-
-            # We want to make sure the device is up and running
-            # before the deploy finishes, so we execute now the 
-            # start script. We run it in background, because the 
-            # TAP will live for as long as the process that 
-            # created it is running, and wait until the TAP  
-            # is created. 
-            self._run_in_background()
-            
             # After creating the TAP, the pl-vif-create.py script
             # will write the name of the TAP to a file. We wait until
             # we can read the interface name from the file.
             vif_name = self.wait_vif_name()
             self.set("deviceName", vif_name) 
 
-    def do_deploy(self):
-        if not self.node or self.node.state < ResourceState.PROVISIONED:
-            self.ec.schedule(self.reschedule_delay, self.deploy)
-        else:
-            if not self.get("command"):
-                self.set("command", self._start_command)
-
-            if not self.get("depends"):
-                self.set("depends", self._dependencies)
-
-            if not self.get("install"):
-                self.set("install", self._install)
-
-            self.do_discover()
-            self.do_provision()
-
-            self.set_ready()
-
-    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
-
-    def do_stop(self):
-        command = self.get('command') or ''
-        
-        if self.state == ResourceState.STARTED:
-            self.info("Stopping command '%s'" % command)
-
-            command = "bash %s" % os.path.join(self.app_home, "stop.sh")
-            (out, err), proc = self.execute_command(command,
-                    blocking = True)
-
-            if err:
-                msg = " Failed to stop command '%s' " % command
-                self.error(msg, out, err)
-
-            self.set_stopped()
-
-    @property
-    def state(self):
-        state_check_delay = 0.5
-        if self._state == ResourceState.STARTED and \
-                tdiffsec(tnow(), self._last_state_check) > state_check_delay:
-
-            if self.get("deviceName"):
-                (out, err), proc = self.node.execute("ifconfig")
-
-                if out.strip().find(self.get("deviceName")) == -1: 
-                    # tap is not running is not running (socket not found)
-                    self.set_stopped()
-
-            self._last_state_check = tnow()
-
-        return self._state
-
-    def do_release(self):
-        # Node needs to wait until all associated RMs are released
-        # to be released
-        from nepi.resources.linux.tunnel import LinuxTunnel
-        rms = self.get_connected(LinuxTunnel.get_rtype())
-
-        for rm in rms:
-            if rm.state < ResourceState.STOPPED:
-                self.ec.schedule(self.reschedule_delay, self.release)
-                return 
-
-        super(PlanetlabTap, self).do_release()
-
     def wait_vif_name(self, exec_run_home = None):
         """ Waits until the vif_name file for the command is generated, 
             and returns the vif_name for the device """
@@ -300,40 +158,9 @@ class PlanetlabTap(LinuxApplication):
 
     def gre_connect(self, remote_endpoint, connection_app_home,
             connection_run_home):
-        gre_connect_command = self._gre_connect_command(
-                remote_endpoint, connection_run_home)
-
-        # upload command to connect.sh script
-        shfile = os.path.join(connection_app_home, "gre-connect.sh")
-        self.node.upload_command(gre_connect_command,
-                shfile = shfile,
-                overwrite = False)
-
-        # invoke connect script
-        cmd = "bash %s" % shfile
-        (out, err), proc = self.node.run(cmd, connection_run_home) 
-             
-        # check if execution errors occurred
-        msg = " Failed to connect endpoints "
-        
-        if proc.poll() or err:
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-    
-        # Wait for pid file to be generated
-        pid, ppid = self.node.wait_pid(connection_run_home)
-        
-        # If the process is not running, check for error information
-        # on the remote machine
-        if not pid or not ppid:
-            (out, err), proc = self.node.check_errors(connection_run_home)
-            # Out is what was written in the stderr file
-            if err:
-                msg = " Failed to start command '%s' " % command
-                self.error(msg, out, err)
-                raise RuntimeError, msg
-        
-        # After creating the TAP, the pl-vif-create.py script
+        super(PlanetlabTap, self).gre_connect(remote_endpoint, 
+                connection_app_home, connection_run_home)
+         # After creating the TAP, the pl-vif-create.py script
         # will write the name of the TAP to a file. We wait until
         # we can read the interface name from the file.
         vif_name = self.wait_vif_name(exec_run_home = connection_run_home)
@@ -341,167 +168,8 @@ class PlanetlabTap(LinuxApplication):
 
         return True
 
-    def initiate_udp_connection(self, remote_endpoint, connection_app_home, 
-            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
-        port = self.udp_connect(remote_endpoint, connection_app_home, 
-            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen)
-        return port
-
-    def udp_connect(self, remote_endpoint, connection_app_home, 
-            connection_run_home, cipher, cipher_key, bwlimit, txqueuelen):
-        udp_connect_command = self._udp_connect_command(
-                remote_endpoint, connection_run_home,
-                cipher, cipher_key, bwlimit, txqueuelen)
-
-        # upload command to connect.sh script
-        shfile = os.path.join(self.app_home, "udp-connect.sh")
-        self.node.upload_command(udp_connect_command,
-                shfile = shfile,
-                overwrite = False)
-
-        # invoke connect script
-        cmd = "bash %s" % shfile
-        (out, err), proc = self.node.run(cmd, self.run_home) 
-             
-        # check if execution errors occurred
-        msg = "Failed to connect endpoints "
-        
-        if proc.poll():
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-    
-        # Wait for pid file to be generated
-        self._pid, self._ppid = self.node.wait_pid(self.run_home)
-        
-        # If the process is not running, check for error information
-        # on the remote machine
-        if not self._pid or not self._ppid:
-            (out, err), proc = self.node.check_errors(self.run_home)
-            # Out is what was written in the stderr file
-            if err:
-                msg = " Failed to start command '%s' " % command
-                self.error(msg, out, err)
-                raise RuntimeError, msg
-
-        port = self.wait_local_port()
-
-        return port
-
-    def _udp_connect_command(self, remote_endpoint, connection_run_home, 
-            cipher, cipher_key, bwlimit, txqueuelen):
-
-        # Set the remote endpoint, (private) IP of the device
-        self.set("pointopoint", remote_endpoint.get("ip"))
-
-        # Public IP of the node
-        remote_ip = remote_endpoint.node.get("ip")
-
-        local_port_file = os.path.join(self.run_home, 
-                "local_port")
-
-        remote_port_file = os.path.join(self.run_home, 
-                "remote_port")
-
-        ret_file = os.path.join(self.run_home, 
-                "ret_file")
-
-        # Generate UDP connect command
-        # Use pl-vif-up.py script to configure TAP with peer info
-        vif_up_command = self._vif_up_command
-        
-        command = ["( "]
-        command.append(vif_up_command)
-
-        # Use pl-vid-udp-connect.py to stablish the tunnel between endpoints
-        command.append(") & (")
-        command.append("sudo -S")
-        command.append("PYTHONPATH=$PYTHONPATH:${SRC}")
-        command.append("python ${SRC}/pl-vif-udp-connect.py")
-        command.append("-t %s" % self.vif_type)
-        command.append("-S %s " % self.sock_name)
-        command.append("-l %s " % local_port_file)
-        command.append("-r %s " % remote_port_file)
-        command.append("-H %s " % remote_ip)
-        command.append("-R %s " % ret_file)
-        if cipher:
-            command.append("-c %s " % cipher)
-        if cipher_key:
-            command.append("-k %s " % cipher_key)
-        if txqueuelen:
-            command.append("-q %s " % txqueuelen)
-        if bwlimit:
-            command.append("-b %s " % bwlimit)
-
-        command.append(")")
-
-        command = " ".join(command)
-        command = self.replace_paths(command)
-
-        return command
-
-    def establish_udp_connection(self, remote_endpoint, 
-            connection_app_home,
-            connection_run_home, 
-            port):
-        # upload remote port number to file
-        rem_port = "%s\n" % port
-        self.node.upload(rem_port,
-                os.path.join(self.run_home, "remote_port"),
-                text = True, 
-                overwrite = False)
-
-    def verify_connection(self):
-        self.wait_result()
-
-    def terminate_connection(self):
-        if  self._pid and self._ppid:
-            (out, err), proc = self.node.kill(self._pid, self._ppid, 
-                    sudo = True) 
-
-            # check if execution errors occurred
-            if proc.poll() and err:
-                msg = " Failed to Kill the Tap"
-                self.error(msg, out, err)
-                raise RuntimeError, msg
-
-    def check_status(self):
-        return self.node.status(self._pid, self._ppid)
-
-    def wait_local_port(self):
-        """ Waits until the local_port file for the endpoint is generated, 
-        and returns the port number 
-        
-        """
-        return self.wait_file("local_port")
-
-    def wait_result(self):
-        """ Waits until the return code file for the endpoint is generated 
-        
-        """ 
-        return self.wait_file("ret_file")
-    def wait_file(self, filename):
-        """ Waits until file on endpoint is generated """
-        result = None
-        delay = 1.0
-
-        for i in xrange(20):
-            (out, err), proc = self.node.check_output(
-                    self.run_home, filename)
-            if out:
-                result = out.strip()
-                break
-            else:
-                time.sleep(delay)
-                delay = delay * 1.5
-        else:
-            msg = "Couldn't retrieve %s" % filename
-            self.error(msg, out, err)
-            raise RuntimeError, msg
-
-        return result
-
-    def _gre_connect_command(self, remote_endpoint, connection_run_home): 
+    def _gre_connect_command(self, remote_endpoint, connection_app_home, 
+            connection_run_home): 
         # Set the remote endpoint, (private) IP of the device
         self.set("pointopoint", remote_endpoint.get("ip"))
         # Public IP of the node
@@ -616,22 +284,10 @@ class PlanetlabTap(LinuxApplication):
 
         return " ".join(command)
 
-    @property
-    def vif_type(self):
-        return "IFF_TAP"
-
     @property
     def vif_name_file(self):
         return os.path.join(self.run_home, "vif_name")
 
-    @property
-    def sock_name(self):
-        return os.path.join(self.run_home, "tap.sock")
-
-    @property
-    def _dependencies(self):
-        return "mercurial make gcc"
-
     @property
     def _install(self):
         # Install python-vsys and python-passfd
index c5d5687..acd20e9 100644 (file)
@@ -19,6 +19,7 @@
 
 from nepi.execution.resource import clsinit_copy
 from nepi.resources.planetlab.tap import PlanetlabTap
+from nepi.resources.linux.tap import LinuxTap
 
 import os
 
@@ -30,14 +31,9 @@ class PlanetlabTun(PlanetlabTap):
 
     def __init__(self, ec, guid):
         super(PlanetlabTun, self).__init__(ec, guid)
-        self._home = "tun-%s" % self.guid
-
-    @property
-    def sock_name(self):
-        return os.path.join(self.run_home, "tun.sock")
+        self._vif_prefix = "tun"
+        self._vif_type = "IFF_TUN"
+        self._vif_type_flag = LinuxTap.IFF_TUN
+        self._home = "%s-%s" % (self.vif_prefix, self.guid)
     
-    @property
-    def vif_type(self):
-        return "IFF_TUN"
-
 
index 508d462..8c83823 100644 (file)
@@ -81,14 +81,11 @@ 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]
+        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)
 
index a4f7d01..1842a6e 100755 (executable)
@@ -30,23 +30,17 @@ import unittest
 
 class LinuxGRETunnelTestCase(unittest.TestCase):
     def setUp(self):
-        self.host1 = "roseval.pl.sophia.inria.fr"
-        self.host2 = "138.96.118.11"
-        self.user1 = "inria_nepi"
-        self.user2 = "omflab"
-        self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
+        self.host = "roseval.pl.sophia.inria.fr"
+        self.user = "inria_nepi"
+        self.identity = "%s/.ssh/id_rsa" % (os.environ['HOME'])
         self.netblock = "192.168.1"
 
     @skipIfAnyNotAliveWithIdentity
-    def t_tap_gre_tunnel(self, user1, host1, identity1, user2, host2, 
-            identity2):
-
+    def t_tap_gre_tunnel(self, user, host, identity):
         ec = ExperimentController(exp_id = "test-tap-gre-tunnel")
         
         node1 = ec.register_resource("linux::Node")
-        ec.set(node1, "hostname", host1)
-        ec.set(node1, "username", user1)
-        ec.set(node1, "identity", identity1)
+        ec.set(node1, "hostname", "localhost")
         ec.set(node1, "cleanExperiment", True)
         ec.set(node1, "cleanProcesses", True)
 
@@ -56,9 +50,9 @@ class LinuxGRETunnelTestCase(unittest.TestCase):
         ec.register_connection(tap1, node1)
 
         node2 = ec.register_resource("linux::Node")
-        ec.set(node2, "hostname", host2)
-        ec.set(node2, "username", user2)
-        ec.set(node2, "identity", identity2)
+        ec.set(node2, "hostname", host)
+        ec.set(node2, "username", user)
+        ec.set(node2, "identity", identity)
         ec.set(node2, "cleanExperiment", True)
         ec.set(node2, "cleanProcesses", True)
 
@@ -93,15 +87,11 @@ class LinuxGRETunnelTestCase(unittest.TestCase):
         ec.shutdown()
 
     @skipIfAnyNotAliveWithIdentity
-    def t_tun_gre_tunnel(self, user1, host1, identity1, user2, host2, 
-            identity2):
-
+    def t_tun_gre_tunnel(self, user, host, identity):
         ec = ExperimentController(exp_id = "test-tun-gre-tunnel")
         
         node1 = ec.register_resource("linux::Node")
-        ec.set(node1, "hostname", host1)
-        ec.set(node1, "username", user1)
-        ec.set(node1, "identity", identity1)
+        ec.set(node1, "hostname", "localhost")
         ec.set(node1, "cleanExperiment", True)
         ec.set(node1, "cleanProcesses", True)
 
@@ -111,9 +101,9 @@ class LinuxGRETunnelTestCase(unittest.TestCase):
         ec.register_connection(tun1, node1)
 
         node2 = ec.register_resource("linux::Node")
-        ec.set(node2, "hostname", host2)
-        ec.set(node2, "username", user2)
-        ec.set(node2, "identity", identity2)
+        ec.set(node2, "hostname", host)
+        ec.set(node2, "username", user)
+        ec.set(node2, "identity", identity)
         ec.set(node2, "cleanExperiment", True)
         ec.set(node2, "cleanProcesses", True)
 
@@ -148,12 +138,10 @@ class LinuxGRETunnelTestCase(unittest.TestCase):
         ec.shutdown()
 
     def test_tap_gre_tunnel(self):
-        self.t_tap_gre_tunnel(self.user1, self.host1, self.identity,
-                self.user2, self.host2, self.identity)
+        self.t_tap_gre_tunnel(self.user, self.host, self.identity)
 
-    def test_tun_gre_tunnel(self):
-        self.t_tun_gre_tunnel(self.user1, self.host1, self.identity,
-                self.user2, self.host2, self.identity)
+    def ztest_tun_gre_tunnel(self):
+        self.t_tun_gre_tunnel(self.user, self.host, self.identity)
 
 if __name__ == '__main__':
     unittest.main()
index d84f6cd..778077e 100755 (executable)
@@ -241,7 +241,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
 
         #ec.wait_finished([ccncat])
         import time
-        time.sleep(80)
+        time.sleep(60)
 
         stdout = ec.trace(ccncat, "stdout")
         f = open("bunny.ts", "w")
@@ -256,7 +256,7 @@ class LinuxNS3FdNetDeviceTest(unittest.TestCase):
     def ztest_cross_ccnpeek_fedora(self):
         self.t_cross_cnnpeek(self.fedora_host, self.fedora_user, self.fedora_identity)
 
-    def test_cross_ccnpeek_local(self):
+    def ztest_cross_ccnpeek_local(self):
         self.t_cross_ccnpeek("localhost")
 
     def test_cross_ccncat_local(self):
index 59c53de..be6b275 100755 (executable)
@@ -28,41 +28,35 @@ import unittest
 
 class LinuxUdpTunnelTestCase(unittest.TestCase):
     def setUp(self):
-        self.host1 = "roseval.pl.sophia.inria.fr"
-        self.host2 = "138.96.118.11"
-        self.user1 = "inria_nepi"
-        self.user2 = "omflab"
-        self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
-        self.netblock = "192.168.1"
+        self.host = "roseval.pl.sophia.inria.fr"
+        self.user = "inria_nepi"
+        self.identity = "%s/.ssh/id_rsa" % (os.environ['HOME'])
 
     @skipIfAnyNotAliveWithIdentity
-    def t_tap_udp_tunnel(self, user1, host1, identity1, user2, host2, 
-            identity2):
+    def t_tap_udp_tunnel(self, user, host, identity):
 
         ec = ExperimentController(exp_id="test-tap-udp-tunnel")
         
         node1 = ec.register_resource("linux::Node")
-        ec.set(node1, "hostname", host1)
-        ec.set(node1, "username", user1)
-        ec.set(node1, "identity", identity1)
+        ec.set(node1, "hostname", "localhost")
         ec.set(node1, "cleanExperiment", True)
         ec.set(node1, "cleanProcesses", True)
 
         tap1 = ec.register_resource("linux::Tap")
-        ec.set(tap1, "ip", "%s.1" % self.netblock)
-        ec.set(tap1, "prefix", "32")
+        ec.set(tap1, "ip", "192.168.3.1")
+        ec.set(tap1, "prefix", "30")
         ec.register_connection(tap1, node1)
 
         node2 = ec.register_resource("linux::Node")
-        ec.set(node2, "hostname", host2)
-        ec.set(node2, "username", user2)
-        ec.set(node2, "identity", identity2)
+        ec.set(node2, "hostname", host)
+        ec.set(node2, "username", user)
+        ec.set(node2, "identity", identity)
         ec.set(node2, "cleanExperiment", True)
         ec.set(node2, "cleanProcesses", True)
 
         tap2 = ec.register_resource("linux::Tap")
-        ec.set(tap2, "ip", "%s.2" % self.netblock)
-        ec.set(tap2, "prefix", "32")
+        ec.set(tap2, "ip", "192.168.3.2")
+        ec.set(tap2, "prefix", "30")
         ec.register_connection(tap2, node2)
 
         udptun = ec.register_resource("linux::UdpTunnel")
@@ -70,7 +64,7 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.register_connection(tap2, udptun)
 
         app = ec.register_resource("linux::Application")
-        cmd = "ping -c3 %s.2" % self.netblock
+        cmd = "ping -c3 192.168.3.2"
         ec.set(app, "command", cmd)
         ec.register_connection(app, node1)
 
@@ -79,6 +73,7 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.wait_finished(app)
 
         ping = ec.trace(app, "stdout")
+        print ping
         expected = """3 packets transmitted, 3 received, 0% packet loss"""
         self.assertTrue(ping.find(expected) > -1)
         
@@ -91,32 +86,30 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.shutdown()
 
     @skipIfAnyNotAliveWithIdentity
-    def t_tun_udp_tunnel(self, user1, host1, identity1, user2, host2, identity2):
+    def t_tun_udp_tunnel(self, user, host, identity):
 
         ec = ExperimentController(exp_id="test-tun-udp-tunnel")
         
         node1 = ec.register_resource("linux::Node")
-        ec.set(node1, "hostname", host1)
-        ec.set(node1, "username", user1)
-        ec.set(node1, "identity", identity1)
+        ec.set(node1, "hostname", "localhost")
         ec.set(node1, "cleanExperiment", True)
         ec.set(node1, "cleanProcesses", True)
 
         tun1 = ec.register_resource("linux::Tun")
-        ec.set(tun1, "ip", "%s.1" % self.netblock)
-        ec.set(tun1, "prefix", "32")
+        ec.set(tun1, "ip", "192.168.3.1")
+        ec.set(tun1, "prefix", "30")
         ec.register_connection(tun1, node1)
 
         node2 = ec.register_resource("linux::Node")
-        ec.set(node2, "hostname", host2)
-        ec.set(node2, "username", user2)
-        ec.set(node2, "identity", identity2)
+        ec.set(node2, "hostname", host)
+        ec.set(node2, "username", user)
+        ec.set(node2, "identity", identity)
         ec.set(node2, "cleanExperiment", True)
         ec.set(node2, "cleanProcesses", True)
 
         tun2 = ec.register_resource("linux::Tun")
-        ec.set(tun2, "ip", "%s.2" % self.netblock)
-        ec.set(tun2, "prefix", "32")
+        ec.set(tun2, "ip", "192.168.3.2")
+        ec.set(tun2, "prefix", "30")
         ec.register_connection(tun2, node2)
 
         udptun = ec.register_resource("linux::UdpTunnel")
@@ -124,7 +117,7 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.register_connection(tun2, udptun)
 
         app = ec.register_resource("linux::Application")
-        cmd = "ping -c3 %s.2" % self.netblock
+        cmd = "ping -c3 192.168.3.2"
         ec.set(app, "command", cmd)
         ec.register_connection(app, node1)
 
@@ -133,6 +126,8 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.wait_finished(app)
 
         ping = ec.trace(app, "stdout")
+
+        print ping
         expected = """3 packets transmitted, 3 received, 0% packet loss"""
         self.assertTrue(ping.find(expected) > -1)
         
@@ -145,12 +140,10 @@ class LinuxUdpTunnelTestCase(unittest.TestCase):
         ec.shutdown()
 
     def test_tap_udp_tunnel(self):
-        self.t_tap_udp_tunnel(self.user1, self.host1, self.identity,
-                self.user2, self.host2, self.identity)
+        self.t_tap_udp_tunnel(self.user, self.host, self.identity)
 
     def ztest_tun_udp_tunnel(self):
-        self.t_tun_udp_tunnel(self.user1, self.host1, self.identity,
-                self.user2, self.host2, self.identity)
+        self.t_tun_udp_tunnel(self.user, self.host, self.identity)
 
 if __name__ == '__main__':
     unittest.main()
index 74197f1..6829eee 100755 (executable)
@@ -30,9 +30,8 @@ class PlanetLabGRETunnelTestCase(unittest.TestCase):
     def setUp(self):
         #self.host1 = "nepi2.pl.sophia.inria.fr"
         #self.host2 = "nepi5.pl.sophia.inria.fr"
-        #self.host2 = "planetlab1.informatik.uni-goettingen.de" 
-        self.host1 = "planetlab1.informatik.uni-erlangen.de"
-        self.host2 = "planck227ple.test.ibbt.be"
+        self.host1 = "onelab4.warsaw.rd.tp.pl"
+        self.host2 = "inriarennes1.irisa.fr"
         self.host3 = "roseval.pl.sophia.inria.fr"
         self.user = "inria_nepi"
         self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
@@ -214,7 +213,8 @@ class PlanetLabGRETunnelTestCase(unittest.TestCase):
         self.t_tun_gre_tunnel(self.user, self.host1, self.identity,
                 self.user, self.host2, self.identity)
 
-    def test_tun_hybrid_gre_tunnel(self):
+    # does not work
+    def ztest_tun_hybrid_gre_tunnel(self):
         self.t_tun_hybrid_gre_tunnel(self.user, self.host1, self.identity, 
                 self.user, self.host3, self.identity)
 
index d8c7a73..c52960e 100755 (executable)
@@ -37,12 +37,13 @@ class OvsTestCase(unittest.TestCase):
     def setUp(self):
         self.switch1 = "planetlab2.virtues.fi"
         self.switch2 = "planetlab2.upc.es"
-        self.host1 = "planetlab2.ionio.gr"
-        self.host2 = "planetlab2.cs.aueb.gr"
+        self.host1 = "onelab4.warsaw.rd.tp.pl"
+        self.host2 = "inriarennes1.irisa.fr"
         self.user = "inria_nepi"
 
     @skipIfAnyNotAlive
     def t_ovs(self, user1, switch1, user2, switch2, user3, host1, user4, host2):
+        network = "192.168.3.0"
 
         ec = ExperimentController(exp_id = "test-ovs")
         
@@ -61,13 +62,15 @@ class OvsTestCase(unittest.TestCase):
 
         port1 = ec.register_resource("planetlab::OVSPort")
         ec.set(port1, "port_name", "port-1")
+        ec.set(port1, "network", network)
         ec.register_connection(port1, ovs1)
 
         port2 = ec.register_resource("planetlab::OVSPort")
         ec.set(port2, "port_name", "port-2")
+        ec.set(port2, "network", network)
         ec.register_connection(port2, ovs1)
 
-        node2 = ec.register_resource("planetlab::PlanetlabNode")
+        node2 = ec.register_resource("planetlab::Node")
         ec.set(node2, "hostname", switch2)
         ec.set(node2, "username", user2)
         ec.set(node2, "cleanExperiment", True)
@@ -82,10 +85,12 @@ class OvsTestCase(unittest.TestCase):
 
         port3 = ec.register_resource("planetlab::OVSPort")
         ec.set(port3, "port_name", "port-3")
+        ec.set(port3, "network", network)
         ec.register_connection(port3, ovs2)  
 
         port4 = ec.register_resource("planetlab::OVSPort")
         ec.set(port4, "port_name", "port-4")
+        ec.set(port4, "network", network)
         ec.register_connection(port4, ovs2)
 
         node3 = ec.register_resource("planetlab::Node")
@@ -95,9 +100,9 @@ class OvsTestCase(unittest.TestCase):
         ec.set(node3, "cleanProcesses", True)
 
         tap1 = ec.register_resource("planetlab::Tap")
-        ec.set(tap1, "ip4", "192.168.3.3")
+        ec.set(tap1, "ip", "192.168.3.3")
         ec.set(tap1, "pointopoint", "192.168.3.1")
-        ec.set(tap1, "prefix4", 24)
+        ec.set(tap1, "prefix", "24")
         ec.register_connection(tap1, node3)
 
         node4 = ec.register_resource("planetlab::Node")
@@ -107,20 +112,20 @@ class OvsTestCase(unittest.TestCase):
         ec.set(node4, "cleanProcesses", True)
 
         tap2 = ec.register_resource("planetlab::Tap")
-        ec.set(tap2, "ip4", "192.168.3.4")
+        ec.set(tap2, "ip", "192.168.3.4")
         ec.set(tap2, "pointopoint", "192.168.3.2")
-        ec.set(tap2, "prefix4", 24)
+        ec.set(tap2, "prefix", "24")
         ec.register_connection(tap2, node4)
 
-        ovstun1 = ec.register_resource("planetlab::OVSTunnel")
+        ovstun1 = ec.register_resource("linux::UdpTunnel")
         ec.register_connection(port1, ovstun1)
         ec.register_connection(tap1, ovstun1)
 
-        ovstun2 = ec.register_resource("plantelab::OVSTunnel")
+        ovstun2 = ec.register_resource("linux::UdpTunnel")
         ec.register_connection(port3, ovstun2)
         ec.register_connection(tap2, ovstun2)
 
-        ovstun3 = ec.register_resource("planetlab::OVSTunnel")
+        ovstun3 = ec.register_resource("linux::UdpTunnel")
         ec.register_connection(port2, ovstun3)
         ec.register_connection(port4, ovstun3)
 
index d52de03..1cd85a1 100755 (executable)
@@ -28,7 +28,7 @@ import unittest
 
 class PlanetlabTapTestCase(unittest.TestCase):
     def setUp(self):
-        self.host = "planetlab1.informatik.uni-erlangen.de"
+        self.host = "planetlab2.upc.es"
         self.user = "inria_nepi"
         self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
         self.netblock = "192.168.3"
@@ -39,7 +39,6 @@ class PlanetlabTapTestCase(unittest.TestCase):
 
     @skipIfNotAlive
     def t_tap_create(self, host, user, identity):
-
         ec = ExperimentController(exp_id="test-tap-create")
         
         node = ec.register_resource("planetlab::Node")
index 0125971..84a9f7a 100755 (executable)
@@ -28,7 +28,7 @@ import unittest
 
 class PlanetlabTunTestCase(unittest.TestCase):
     def setUp(self):
-        self.host = "planetlab1.informatik.uni-erlangen.de"
+        self.host = "planetlab2.upc.es"
         self.user = "inria_nepi"
         self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
         self.netblock = "192.168.3"
index 167052b..bcb487b 100755 (executable)
@@ -30,9 +30,9 @@ class PlanetlabUdpTunnelTestCase(unittest.TestCase):
     def setUp(self):
         #self.host1 = "nepi2.pl.sophia.inria.fr"
         #self.host2 = "nepi5.pl.sophia.inria.fr"
-        #self.host2 = "planetlab1.informatik.uni-goettingen.de" 
-        self.host1 = "planetlab1.informatik.uni-erlangen.de"
-        self.host2 = "planck227ple.test.ibbt.be"
+        #self.host2 = "planetlab1.informatik.uni-goettingen.de"
+        self.host1 = "onelab4.warsaw.rd.tp.pl"
+        self.host2 = "inriarennes1.irisa.fr"
         self.user = "inria_nepi"
         #self.identity = "%s/.ssh/id_rsa_planetlab" % (os.environ['HOME'])
         self.identity = "%s/.ssh/id_rsa" % (os.environ['HOME'])