From 00be6a6a023debb382d6d351cf005b233da20623 Mon Sep 17 00:00:00 2001 From: Alina Quereilhac Date: Sat, 24 Jan 2015 19:03:38 +0100 Subject: [PATCH] Serious refactoring of TUN/TAP and tunnel code. Linux udp/gre tunnels not yet functional --- examples/omf/nitos_omf6_ping.py | 2 +- examples/openvswitch/ovs_ping_2_switches.py | 1 - .../resources/linux/netns/netnsemulation.py | 4 +- .../{tun_tap_fd_link.py => tuntapfdlink.py} | 19 +- .../resources/linux/scripts/linux-passfd.py | 62 --- .../linux/scripts/linux-tap-create.py | 246 +++++++++++ .../linux/scripts/linux-tap-delete.py | 61 +++ .../scripts/linux-tap-passfd.py} | 0 .../linux/scripts/linux-udp-connect.py | 102 +++-- src/nepi/resources/linux/tap.py | 401 +++++++++++------- src/nepi/resources/linux/tun.py | 21 +- src/nepi/resources/linux/udptunnel.py | 48 +-- .../{tun_tap_fd_link.py => tuntapfdlink.py} | 24 +- .../planetlab/openvswitch/ovsport.py | 8 +- .../planetlab/scripts/pl-vif-down.py | 16 +- .../planetlab/scripts/pl-vif-udp-connect.py | 188 -------- src/nepi/resources/planetlab/tap.py | 390 +---------------- src/nepi/resources/planetlab/tun.py | 14 +- src/nepi/util/sshfuncs.py | 13 +- test/resources/linux/gretunnel.py | 44 +- .../linux/ns3/cross_dce_linux_ccn.py | 4 +- ...y => cross_ns3_linux_tuntapfdlink_ping.py} | 0 test/resources/linux/udptunnel.py | 63 ++- test/resources/planetlab/gretunnel.py | 8 +- ... cross_ns3_planetlab_tuntapfdlink_ping.py} | 0 test/resources/planetlab/ovs.py | 25 +- test/resources/planetlab/tap.py | 3 +- test/resources/planetlab/tun.py | 2 +- test/resources/planetlab/udptunnel.py | 6 +- 29 files changed, 750 insertions(+), 1025 deletions(-) rename src/nepi/resources/linux/ns3/{tun_tap_fd_link.py => tuntapfdlink.py} (88%) delete mode 100644 src/nepi/resources/linux/scripts/linux-passfd.py create mode 100644 src/nepi/resources/linux/scripts/linux-tap-create.py create mode 100644 src/nepi/resources/linux/scripts/linux-tap-delete.py rename src/nepi/resources/{planetlab/scripts/pl-vif-passfd.py => linux/scripts/linux-tap-passfd.py} (100%) rename src/nepi/resources/planetlab/ns3/{tun_tap_fd_link.py => tuntapfdlink.py} (81%) delete mode 100644 src/nepi/resources/planetlab/scripts/pl-vif-udp-connect.py rename test/resources/linux/ns3/{cross_ns3_linux_ping.py => cross_ns3_linux_tuntapfdlink_ping.py} (100%) rename test/resources/planetlab/ns3/{cross_ns3_planetlab_ping.py => cross_ns3_planetlab_tuntapfdlink_ping.py} (100%) diff --git a/examples/omf/nitos_omf6_ping.py b/examples/omf/nitos_omf6_ping.py index 42322007..5fa27ffb 100644 --- a/examples/omf/nitos_omf6_ping.py +++ b/examples/omf/nitos_omf6_ping.py @@ -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") diff --git a/examples/openvswitch/ovs_ping_2_switches.py b/examples/openvswitch/ovs_ping_2_switches.py index 155fcbb7..18657c91 100644 --- a/examples/openvswitch/ovs_ping_2_switches.py +++ b/examples/openvswitch/ovs_ping_2_switches.py @@ -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 diff --git a/src/nepi/resources/linux/netns/netnsemulation.py b/src/nepi/resources/linux/netns/netnsemulation.py index 4ad80629..d7be6563 100644 --- a/src/nepi/resources/linux/netns/netnsemulation.py +++ b/src/nepi/resources/linux/netns/netnsemulation.py @@ -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 diff --git a/src/nepi/resources/linux/ns3/tun_tap_fd_link.py b/src/nepi/resources/linux/ns3/tuntapfdlink.py similarity index 88% rename from src/nepi/resources/linux/ns3/tun_tap_fd_link.py rename to src/nepi/resources/linux/ns3/tuntapfdlink.py index ed4158b4..ce800114 100644 --- a/src/nepi/resources/linux/ns3/tun_tap_fd_link.py +++ b/src/nepi/resources/linux/ns3/tuntapfdlink.py @@ -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 index ff7014ed..00000000 --- a/src/nepi/resources/linux/scripts/linux-passfd.py +++ /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
-N -t -p ") - - 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 index 00000000..50adaa2a --- /dev/null +++ b/src/nepi/resources/linux/scripts/linux-tap-create.py @@ -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 . +# +# Author: Alina Quereilhac + +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 -a -n " + "-N -p -S ") + + 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 index 00000000..2fa97ed8 --- /dev/null +++ b/src/nepi/resources/linux/scripts/linux-tap-delete.py @@ -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 . +# +# Author: Alina Quereilhac + +import base64 +import socket + +from optparse import OptionParser + +STOP_MSG = "STOP" + +def get_options(): + usage = ("usage: %prog -N -S ") + + 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" + diff --git a/src/nepi/resources/planetlab/scripts/pl-vif-passfd.py b/src/nepi/resources/linux/scripts/linux-tap-passfd.py similarity index 100% rename from src/nepi/resources/planetlab/scripts/pl-vif-passfd.py rename to src/nepi/resources/linux/scripts/linux-tap-passfd.py diff --git a/src/nepi/resources/linux/scripts/linux-udp-connect.py b/src/nepi/resources/linux/scripts/linux-udp-connect.py index 330ed17f..a4b662e9 100644 --- a/src/nepi/resources/linux/scripts/linux-udp-connect.py +++ b/src/nepi/resources/linux/scripts/linux-udp-connect.py @@ -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 -t -p " + usage = ("usage: %prog -t -S -n " "-b -c -k -q " - "-l -r -H " + "-p -P " + "-o -P " "-R ") 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! diff --git a/src/nepi/resources/linux/tap.py b/src/nepi/resources/linux/tap.py index 2a78e605..be80ee0b 100644 --- a/src/nepi/resources/linux/tap.py +++ b/src/nepi/resources/linux/tap.py @@ -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! diff --git a/src/nepi/resources/linux/tun.py b/src/nepi/resources/linux/tun.py index 22a5dead..0a448000 100644 --- a/src/nepi/resources/linux/tun.py +++ b/src/nepi/resources/linux/tun.py @@ -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" - diff --git a/src/nepi/resources/linux/udptunnel.py b/src/nepi/resources/linux/udptunnel.py index c00459c8..9a241d8a 100644 --- a/src/nepi/resources/linux/udptunnel.py +++ b/src/nepi/resources/linux/udptunnel.py @@ -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 diff --git a/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py b/src/nepi/resources/planetlab/ns3/tuntapfdlink.py similarity index 81% rename from src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py rename to src/nepi/resources/planetlab/ns3/tuntapfdlink.py index 041e6b88..3f264a57 100644 --- a/src/nepi/resources/planetlab/ns3/tun_tap_fd_link.py +++ b/src/nepi/resources/planetlab/ns3/tuntapfdlink.py @@ -18,7 +18,7 @@ # Author: Alina Quereilhac 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 - diff --git a/src/nepi/resources/planetlab/openvswitch/ovsport.py b/src/nepi/resources/planetlab/openvswitch/ovsport.py index f2cfb3eb..25f7c03d 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovsport.py +++ b/src/nepi/resources/planetlab/openvswitch/ovsport.py @@ -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): diff --git a/src/nepi/resources/planetlab/scripts/pl-vif-down.py b/src/nepi/resources/planetlab/scripts/pl-vif-down.py index caac65ad..8164455b 100644 --- a/src/nepi/resources/planetlab/scripts/pl-vif-down.py +++ b/src/nepi/resources/planetlab/scripts/pl-vif-down.py @@ -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 index fa16879b..00000000 --- a/src/nepi/resources/planetlab/scripts/pl-vif-udp-connect.py +++ /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 -S " - "-b -c -k -q " - "-l -r -H " - "-R ") - - 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 - ) - - diff --git a/src/nepi/resources/planetlab/tap.py b/src/nepi/resources/planetlab/tap.py index 5df36c4b..61ff3d69 100644 --- a/src/nepi/resources/planetlab/tap.py +++ b/src/nepi/resources/planetlab/tap.py @@ -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 diff --git a/src/nepi/resources/planetlab/tun.py b/src/nepi/resources/planetlab/tun.py index c5d56876..acd20e9a 100644 --- a/src/nepi/resources/planetlab/tun.py +++ b/src/nepi/resources/planetlab/tun.py @@ -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" - diff --git a/src/nepi/util/sshfuncs.py b/src/nepi/util/sshfuncs.py index 508d462d..8c83823e 100644 --- a/src/nepi/util/sshfuncs.py +++ b/src/nepi/util/sshfuncs.py @@ -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) diff --git a/test/resources/linux/gretunnel.py b/test/resources/linux/gretunnel.py index a4f7d019..1842a6e8 100755 --- a/test/resources/linux/gretunnel.py +++ b/test/resources/linux/gretunnel.py @@ -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() diff --git a/test/resources/linux/ns3/cross_dce_linux_ccn.py b/test/resources/linux/ns3/cross_dce_linux_ccn.py index d84f6cd5..778077e0 100755 --- a/test/resources/linux/ns3/cross_dce_linux_ccn.py +++ b/test/resources/linux/ns3/cross_dce_linux_ccn.py @@ -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): diff --git a/test/resources/linux/ns3/cross_ns3_linux_ping.py b/test/resources/linux/ns3/cross_ns3_linux_tuntapfdlink_ping.py similarity index 100% rename from test/resources/linux/ns3/cross_ns3_linux_ping.py rename to test/resources/linux/ns3/cross_ns3_linux_tuntapfdlink_ping.py diff --git a/test/resources/linux/udptunnel.py b/test/resources/linux/udptunnel.py index 59c53de5..be6b2752 100755 --- a/test/resources/linux/udptunnel.py +++ b/test/resources/linux/udptunnel.py @@ -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() diff --git a/test/resources/planetlab/gretunnel.py b/test/resources/planetlab/gretunnel.py index 74197f1b..6829eee8 100755 --- a/test/resources/planetlab/gretunnel.py +++ b/test/resources/planetlab/gretunnel.py @@ -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) diff --git a/test/resources/planetlab/ns3/cross_ns3_planetlab_ping.py b/test/resources/planetlab/ns3/cross_ns3_planetlab_tuntapfdlink_ping.py similarity index 100% rename from test/resources/planetlab/ns3/cross_ns3_planetlab_ping.py rename to test/resources/planetlab/ns3/cross_ns3_planetlab_tuntapfdlink_ping.py diff --git a/test/resources/planetlab/ovs.py b/test/resources/planetlab/ovs.py index d8c7a730..c52960e4 100755 --- a/test/resources/planetlab/ovs.py +++ b/test/resources/planetlab/ovs.py @@ -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) diff --git a/test/resources/planetlab/tap.py b/test/resources/planetlab/tap.py index d52de039..1cd85a19 100755 --- a/test/resources/planetlab/tap.py +++ b/test/resources/planetlab/tap.py @@ -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") diff --git a/test/resources/planetlab/tun.py b/test/resources/planetlab/tun.py index 01259713..84a9f7aa 100755 --- a/test/resources/planetlab/tun.py +++ b/test/resources/planetlab/tun.py @@ -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" diff --git a/test/resources/planetlab/udptunnel.py b/test/resources/planetlab/udptunnel.py index 167052b9..bcb487b8 100755 --- a/test/resources/planetlab/udptunnel.py +++ b/test/resources/planetlab/udptunnel.py @@ -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']) -- 2.43.0