self-contained tap creation in the switchd
authorGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Tue, 18 Sep 2012 20:09:06 +0000 (22:09 +0200)
committerGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Tue, 18 Sep 2012 20:14:56 +0000 (22:14 +0200)
This patch incorporates the functionality of pltap-ovs,
vsysc and create_bridge into the vswitch server itself.
Now the server is able to re-recreate any bridge contained
in the database after a restart.
The database must also contain the IP/NETMASK of the
tap device. These are stored as options of the bridge
internal interface.

Now the bridge name is no longer required to be the same
as the tap name. Instead, the tap interface remembers
the "real name" internally. The real name can be retrieved
with

ovs-appctl netdev-pltap/get-tapname

The sliver-ovs utility and the exp-tool/Makefile have
been updated accordingly.

TODO:
check wether we are allwed to:
- read the mac address of the tap;
- read the stats.
Otherwise see if we can do that via Vsys.

14 files changed:
lib/automake.mk
lib/dpif-netdev.c
lib/netdev-linux.c
lib/netdev-pltap.c [new file with mode: 0644]
lib/netdev-provider.h
lib/netdev.c
lib/tunalloc.c
planetlab/automake.mk
planetlab/exp-tool/Makefile
planetlab/pltap-ovs/pltap-ovs.c [deleted file]
planetlab/pltap-ovs/tunalloc.c [deleted file]
planetlab/pltap-ovs/tunalloc.h [deleted file]
planetlab/scripts/sliver-ovs.in
planetlab/vsysc/vsysc.c [deleted file]

index a7f469c..238ba34 100644 (file)
@@ -89,6 +89,7 @@ lib_libopenvswitch_a_SOURCES = \
        lib/multipath.h \
        lib/netdev-dummy.c \
        lib/netdev-tunnel.c \
+       lib/netdev-pltap.c \
        lib/netdev-provider.h \
        lib/netdev.c \
        lib/netdev.h \
index 48bc92d..28f64b1 100644 (file)
@@ -321,7 +321,7 @@ static const char* internal_port_type(const struct dp_netdev* dp)
        if (dp->class == &dpif_netdev_class)
                return "tap";
        if (dp->class == &dpif_planetlab_class)
-               return "tap_pl";
+               return "pltap";
        return "dummy";
 }
 
index 08937de..412a92d 100644 (file)
@@ -69,7 +69,6 @@
 #include "sset.h"
 #include "timer.h"
 #include "vlog.h"
-#include "tunalloc.h"
 
 VLOG_DEFINE_THIS_MODULE(netdev_linux);
 
@@ -733,7 +732,7 @@ netdev_linux_destroy(struct netdev_dev *netdev_dev_)
         netdev_dev->tc->ops->tc_destroy(netdev_dev->tc);
     }
 
-    if (class == &netdev_tap_class || class == &netdev_tap_pl_class) {
+    if (class == &netdev_tap_class) {
         destroy_tap(netdev_dev);
     }
     free(netdev_dev);
@@ -769,7 +768,7 @@ netdev_linux_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp)
         }
     }
 
-    if (!strncmp(netdev_dev_get_type(netdev_dev_), "tap", 3) &&
+    if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") &&
         !netdev_dev->state.tap.opened) {
 
         /* We assume that the first user of the tap device is the primary user
@@ -794,7 +793,7 @@ netdev_linux_close(struct netdev *netdev_)
 {
     struct netdev_linux *netdev = netdev_linux_cast(netdev_);
 
-    if (netdev->fd > 0 && strncmp(netdev_get_type(netdev_), "tap", 3)) {
+    if (netdev->fd > 0 && strcmp(netdev_get_type(netdev_), "tap")) {
         close(netdev->fd);
     }
     free(netdev);
@@ -868,8 +867,7 @@ netdev_linux_recv(struct netdev *netdev_, void *data, size_t size)
     for (;;) {
         ssize_t retval;
 
-        retval = ((netdev_->netdev_dev->netdev_class == &netdev_tap_class ||
-                   netdev_->netdev_dev->netdev_class == &netdev_tap_pl_class)
+        retval = (netdev_->netdev_dev->netdev_class == &netdev_tap_class
                   ? read(netdev->fd, data, size)
                   : recv(netdev->fd, data, size, MSG_TRUNC));
         if (retval >= 0) {
@@ -902,7 +900,7 @@ netdev_linux_drain(struct netdev *netdev_)
     struct netdev_linux *netdev = netdev_linux_cast(netdev_);
     if (netdev->fd < 0) {
         return 0;
-    } else if (!strncmp(netdev_get_type(netdev_), "tap", 3)) {
+    } else if (!strcmp(netdev_get_type(netdev_), "tap")) {
         struct ifreq ifr;
         int error = netdev_linux_do_ioctl(netdev_get_name(netdev_), &ifr,
                                           SIOCGIFTXQLEN, "SIOCGIFTXQLEN");
@@ -1013,7 +1011,7 @@ netdev_linux_send_wait(struct netdev *netdev_)
     struct netdev_linux *netdev = netdev_linux_cast(netdev_);
     if (netdev->fd < 0) {
         /* Nothing to do. */
-    } else if (strncmp(netdev_get_type(netdev_), "tap", 3)) {
+    } else if (strcmp(netdev_get_type(netdev_), "tap")) {
         poll_fd_wait(netdev->fd, POLLOUT);
     } else {
         /* TAP device always accepts packets.*/
@@ -1788,51 +1786,6 @@ netdev_linux_get_qos_types(const struct netdev *netdev OVS_UNUSED,
     return 0;
 }
 
-static int
-netdev_linux_create_tap_pl(const struct netdev_class *class OVS_UNUSED,
-                        const char *name, struct netdev_dev **netdev_devp)
-{
-    struct netdev_dev_linux *netdev_dev;
-    struct tap_state *state;
-    char real_name[IFNAMSIZ];
-    int error;
-
-    netdev_dev = xzalloc(sizeof *netdev_dev);
-    state = &netdev_dev->state.tap;
-
-    error = cache_notifier_ref();
-    if (error) {
-        goto error;
-    }
-
-    /* Open tap device. */
-    state->fd = tun_alloc(IFF_TAP, real_name);
-    if (state->fd < 0) {
-        error = errno;
-        VLOG_WARN("tun_alloc(IFF_TAP, %s) failed: %s", name, strerror(error));
-        goto error_unref_notifier;
-    }
-    if (strcmp(name, real_name)) {
-        VLOG_WARN("tap_pl: requested %s, created %s", name, real_name);
-    }
-
-    /* Make non-blocking. */
-    error = set_nonblocking(state->fd);
-    if (error) {
-        goto error_unref_notifier;
-    }
-
-    netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_tap_pl_class);
-    *netdev_devp = &netdev_dev->netdev_dev;
-    return 0;
-
-error_unref_notifier:
-    cache_notifier_unref();
-error:
-    free(netdev_dev);
-    return error;
-}
-
 static const struct tc_ops *
 tc_lookup_ovs_name(const char *name)
 {
@@ -2424,13 +2377,6 @@ netdev_linux_update_flags(struct netdev *netdev, enum netdev_flags off,
     return error;
 }
 
-static int
-netdev_tap_pl_update_flags(struct netdev *netdev OVS_UNUSED, enum netdev_flags off OVS_UNUSED,
-                          enum netdev_flags on OVS_UNUSED, enum netdev_flags *old_flagsp OVS_UNUSED)
-{
-    return 0;
-}
-
 static unsigned int
 netdev_linux_change_seq(const struct netdev *netdev)
 {
@@ -2438,8 +2384,7 @@ netdev_linux_change_seq(const struct netdev *netdev)
 }
 
 #define NETDEV_LINUX_CLASS(NAME, CREATE, GET_STATS, SET_STATS,  \
-                           GET_FEATURES, GET_STATUS,            \
-                           UPDATE_FLAGS)                        \
+                           GET_FEATURES, GET_STATUS)            \
 {                                                               \
     NAME,                                                       \
                                                                 \
@@ -2497,7 +2442,7 @@ netdev_linux_change_seq(const struct netdev *netdev)
     GET_STATUS,                                                 \
     netdev_linux_arp_lookup,                                    \
                                                                 \
-    UPDATE_FLAGS,                                               \
+    netdev_linux_update_flags,                                  \
                                                                 \
     netdev_linux_change_seq                                     \
 }
@@ -2509,8 +2454,7 @@ const struct netdev_class netdev_linux_class =
         netdev_linux_get_stats,
         NULL,                    /* set_stats */
         netdev_linux_get_features,
-        netdev_linux_get_drv_info,
-        netdev_linux_update_flags);
+        netdev_linux_get_drv_info);
 
 const struct netdev_class netdev_tap_class =
     NETDEV_LINUX_CLASS(
@@ -2519,8 +2463,7 @@ const struct netdev_class netdev_tap_class =
         netdev_tap_get_stats,
         NULL,                   /* set_stats */
         netdev_linux_get_features,
-        netdev_linux_get_drv_info,
-        netdev_linux_update_flags);
+        netdev_linux_get_drv_info);
 
 const struct netdev_class netdev_internal_class =
     NETDEV_LINUX_CLASS(
@@ -2529,18 +2472,7 @@ const struct netdev_class netdev_internal_class =
         netdev_internal_get_stats,
         netdev_vport_set_stats,
         NULL,                  /* get_features */
-        netdev_internal_get_drv_info,
-        netdev_linux_update_flags);
-
-const struct netdev_class netdev_tap_pl_class =
-    NETDEV_LINUX_CLASS(
-        "tap_pl",
-        netdev_linux_create_tap_pl,
-        netdev_tap_get_stats,
-        NULL,                   /* set_stats */
-        netdev_linux_get_features,
-        netdev_linux_get_drv_info,
-       netdev_tap_pl_update_flags);    
+        netdev_internal_get_drv_info);
 \f
 /* HTB traffic control class. */
 
diff --git a/lib/netdev-pltap.c b/lib/netdev-pltap.c
new file mode 100644 (file)
index 0000000..adf3ddb
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2012 Giuseppe Lettieri
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <linux/if_tun.h>
+#include <errno.h>
+
+#include "flow.h"
+#include "list.h"
+#include "netdev-provider.h"
+#include "odp-util.h"
+#include "ofp-print.h"
+#include "ofpbuf.h"
+#include "packets.h"
+#include "poll-loop.h"
+#include "shash.h"
+#include "sset.h"
+#include "unixctl.h"
+#include "socket-util.h"
+#include "vlog.h"
+#include "tunalloc.h"
+
+VLOG_DEFINE_THIS_MODULE(netdev_pltap);
+
+struct netdev_dev_pltap {
+    struct netdev_dev netdev_dev;
+    uint8_t hwaddr[ETH_ADDR_LEN];
+    char *real_name;
+    char *error;
+    struct netdev_stats stats;
+    enum netdev_flags flags;
+    int fd;
+    struct sockaddr_in local_addr;
+    int local_netmask;
+    bool valid_local_ip;
+    bool valid_local_netmask;
+    bool finalized;
+    unsigned int change_seq;
+};
+
+struct netdev_pltap {
+    struct netdev netdev;
+} ;
+
+static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
+
+static struct shash pltap_netdev_devs = SHASH_INITIALIZER(&pltap_netdev_devs);
+
+static int netdev_pltap_create(const struct netdev_class *, const char *,
+                               struct netdev_dev **);
+
+static struct shash pltap_creating = SHASH_INITIALIZER(&pltap_creating);
+
+static void netdev_pltap_update_seq(struct netdev_dev_pltap *);
+
+static bool
+is_pltap_class(const struct netdev_class *class)
+{
+    return class->create == netdev_pltap_create;
+}
+
+static struct netdev_dev_pltap *
+netdev_dev_pltap_cast(const struct netdev_dev *netdev_dev)
+{
+    assert(is_pltap_class(netdev_dev_get_class(netdev_dev)));
+    return CONTAINER_OF(netdev_dev, struct netdev_dev_pltap, netdev_dev);
+}
+
+static struct netdev_pltap *
+netdev_pltap_cast(const struct netdev *netdev)
+{
+    struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
+    assert(is_pltap_class(netdev_dev_get_class(netdev_dev)));
+    return CONTAINER_OF(netdev, struct netdev_pltap, netdev);
+}
+
+static int
+netdev_pltap_create(const struct netdev_class *class OVS_UNUSED, const char *name,
+                    struct netdev_dev **netdev_devp)
+{
+    struct netdev_dev_pltap *netdev_dev;
+    int error;
+
+    netdev_dev = xzalloc(sizeof *netdev_dev);
+
+    netdev_dev->real_name = xzalloc(IFNAMSIZ + 1);
+    netdev_dev->error = NULL;
+    memset(&netdev_dev->local_addr, 0, sizeof(netdev_dev->local_addr));
+    netdev_dev->valid_local_ip = false;
+    netdev_dev->valid_local_netmask = false;
+    netdev_dev->finalized = false;
+
+
+    /* Open tap device. */
+    netdev_dev->fd = tun_alloc(IFF_TAP, netdev_dev->real_name);
+    if (netdev_dev->fd < 0) {
+        error = errno;
+        VLOG_WARN("tun_alloc(IFF_TAP, %s) failed: %s", name, strerror(error));
+        goto cleanup;
+    }
+    VLOG_DBG("real_name = %s", netdev_dev->real_name);
+
+    /* Make non-blocking. */
+    error = set_nonblocking(netdev_dev->fd);
+    if (error) {
+        goto cleanup;
+    }
+
+    netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_pltap_class);
+    shash_add(&pltap_netdev_devs, name, netdev_dev);
+    *netdev_devp = &netdev_dev->netdev_dev;
+    return 0;
+
+cleanup:
+    free(netdev_dev);
+    return error;
+}
+
+static void
+netdev_pltap_destroy(struct netdev_dev *netdev_dev_)
+{
+    struct netdev_dev_pltap *netdev_dev = netdev_dev_pltap_cast(netdev_dev_);
+
+    if (netdev_dev->fd != -1)
+       close(netdev_dev->fd);
+
+    shash_find_and_delete(&pltap_netdev_devs,
+                          netdev_dev_get_name(netdev_dev_));
+    free(netdev_dev);
+}
+
+static int
+netdev_pltap_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp)
+{
+    struct netdev_pltap *netdev;
+
+    netdev = xmalloc(sizeof *netdev);
+    netdev_init(&netdev->netdev, netdev_dev_);
+
+    *netdevp = &netdev->netdev;
+    return 0;
+}
+
+static void
+netdev_pltap_close(struct netdev *netdev_)
+{
+    struct netdev_pltap *netdev = netdev_pltap_cast(netdev_);
+    free(netdev);
+}
+
+static int
+netdev_pltap_create_finalize(struct netdev_dev_pltap *dev)
+{
+    int ifd = -1, ofd = -1, maxfd;
+    size_t bytes_to_write, bytes_to_read = 1024,
+           bytes_written = 0, bytes_read = 0;
+    int error = 0;
+    char *msg = NULL, *reply = NULL;
+
+    if (dev->finalized)
+        return 0;
+    if (!dev->valid_local_ip || !dev->valid_local_netmask)
+        return 0;
+    
+    ofd = open("/vsys/vif_up.out", O_RDONLY | O_NONBLOCK);
+    if (ofd < 0) {
+        VLOG_ERR("Cannot open vif_up.out: %s", strerror(errno));
+       error = errno;
+       goto cleanup;
+    }
+    ifd = open("/vsys/vif_up.in", O_WRONLY | O_NONBLOCK);
+    if (ifd < 0) {
+        VLOG_ERR("Cannot open vif_up.in: %s", strerror(errno));
+       error = errno;
+       goto cleanup;
+    }
+    maxfd = (ifd < ofd) ? ofd : ifd;
+
+    msg = xasprintf("%s\n"IP_FMT"\n%d\n",
+       dev->real_name,
+       IP_ARGS(&dev->local_addr.sin_addr),
+       dev->local_netmask);
+    reply = (char*)xmalloc(bytes_to_read);
+    if (!msg || !reply) {
+        VLOG_ERR("Out of memory");
+       error = ENOMEM;
+       goto cleanup;
+    }
+    bytes_to_write = strlen(msg);
+    while (bytes_to_write || bytes_to_read) {
+        fd_set readset, writeset, errorset;
+
+       FD_ZERO(&readset);
+       FD_ZERO(&writeset);
+       FD_ZERO(&errorset);
+       if (bytes_to_write) {
+           FD_SET(ifd, &writeset);
+           FD_SET(ifd, &errorset);
+       }
+       FD_SET(ofd, &readset);
+       FD_SET(ofd, &errorset);
+       if (select(maxfd + 1, &readset, &writeset, &errorset, NULL) < 0) {
+           if (errno == EINTR)
+               continue;
+           VLOG_ERR("selec error: %s", strerror(errno));
+           error = errno;
+           goto cleanup;
+       }
+       if (FD_ISSET(ifd, &errorset) || FD_ISSET(ofd, &errorset)) {
+           VLOG_ERR("error condition on ifd or ofd");
+           goto cleanup;
+       }
+       if (FD_ISSET(ifd, &writeset)) {
+           ssize_t n = write(ifd, msg + bytes_written, bytes_to_write);    
+           if (n < 0) {
+               if (errno != EAGAIN && errno != EINTR) {
+                   VLOG_ERR("write on vif_up.in: %s", strerror(errno));
+                   error = errno;
+                   goto cleanup;
+               }
+            } else {
+               bytes_written += n;
+               bytes_to_write -= n;
+               if (bytes_to_write == 0)
+                   close(ifd);
+           }
+       }
+       if (FD_ISSET(ofd, &readset)) {
+           ssize_t n = read(ofd, reply + bytes_read, bytes_to_read);    
+           if (n < 0) {
+               if (errno != EAGAIN && errno != EINTR) {
+                   VLOG_ERR("read on vif_up.out: %s", strerror(errno));
+                   error = errno;
+                   goto cleanup;
+               }
+            } else if (n == 0) {
+               bytes_to_read = 0;
+            } else {
+               bytes_read += n;
+               bytes_to_read -= n;
+           }
+       }
+    }
+    if (bytes_read) {
+       reply[bytes_read] = '\0';
+        VLOG_ERR("vif_up returned: %s", reply);
+       dev->error = reply;
+       reply = NULL;
+       error = EAGAIN;
+       goto cleanup;
+    }
+    dev->finalized = true;
+    free(dev->error);
+    dev->error = NULL;
+    netdev_pltap_update_seq(dev);
+
+cleanup:
+    free(msg);
+    free(reply);
+    close(ifd);
+    close(ofd);
+    return error;
+}
+
+static int
+netdev_pltap_get_config(struct netdev_dev *dev_, struct smap *args)
+{
+    struct netdev_dev_pltap *netdev_dev = netdev_dev_pltap_cast(dev_);
+
+    if (netdev_dev->valid_local_ip)
+       smap_add_format(args, "local_ip", IP_FMT,
+            IP_ARGS(&netdev_dev->local_addr.sin_addr));
+    if (netdev_dev->valid_local_netmask)
+        smap_add_format(args, "local_netmask", "%"PRIu32,
+            ntohs(netdev_dev->local_netmask));
+    return netdev_pltap_create_finalize(netdev_dev);
+}
+
+static int
+netdev_pltap_set_config(struct netdev_dev *dev_, const struct smap *args)
+{
+    struct netdev_dev_pltap *netdev_dev = netdev_dev_pltap_cast(dev_);
+    struct shash_node *node;
+
+    VLOG_DBG("pltap_set_config(%s)", netdev_dev_get_name(dev_));
+    SMAP_FOR_EACH(node, args) {
+        VLOG_DBG("arg: %s->%s", node->name, (char*)node->data);
+       if (!strcmp(node->name, "local_ip")) {
+           struct in_addr addr;
+           if (lookup_ip(node->data, &addr)) {
+               VLOG_WARN("%s: bad 'local_ip'", node->name);
+           } else {
+               netdev_dev->local_addr.sin_addr = addr;
+               netdev_dev->valid_local_ip = true;
+           }
+       } else if (!strcmp(node->name, "local_netmask")) {
+           netdev_dev->local_netmask = atoi(node->data);
+           // XXX check valididy
+           netdev_dev->valid_local_netmask = true;
+       } else {
+           VLOG_WARN("%s: unknown argument '%s'", 
+               netdev_dev_get_name(dev_), node->name);
+       }
+    }
+    return netdev_pltap_create_finalize(netdev_dev);        
+}
+
+static int
+netdev_pltap_listen(struct netdev *netdev_ OVS_UNUSED)
+{
+    return 0;
+}
+
+static int
+netdev_pltap_recv(struct netdev *netdev_, void *buffer, size_t size)
+{
+    struct netdev_dev_pltap *dev = 
+       netdev_dev_pltap_cast(netdev_get_dev(netdev_));
+    if (!dev->finalized)
+        return -EAGAIN;
+    for (;;) {
+        ssize_t retval;
+        retval = read(dev->fd, buffer, size);
+       VLOG_DBG("%s: read(%"PRIxPTR", %"PRIu64") = %"PRId64,
+                netdev_get_name(netdev_), (uintptr_t)buffer, size, retval);
+        if (retval >= 0) {
+            if (retval <= size) {
+               return retval;
+           } else {
+               return -EMSGSIZE;
+           }
+        } else if (errno != EINTR) {
+            if (errno != EAGAIN) {
+                VLOG_WARN_RL(&rl, "error receiveing Ethernet packet on %s: %s",
+                    netdev_get_name(netdev_), strerror(errno));
+            }
+            return -errno;
+        }
+    }
+}
+
+static void
+netdev_pltap_recv_wait(struct netdev *netdev_)
+{
+    struct netdev_dev_pltap *dev = 
+       netdev_dev_pltap_cast(netdev_get_dev(netdev_));
+    if (dev->finalized && dev->fd >= 0) {
+        poll_fd_wait(dev->fd, POLLIN);
+    }
+}
+
+static int
+netdev_pltap_send(struct netdev *netdev_, const void *buffer, size_t size)
+{
+    struct netdev_dev_pltap *dev = 
+       netdev_dev_pltap_cast(netdev_get_dev(netdev_));
+    if (dev->fd < 0 || !dev->finalized)
+        return -EAGAIN;
+    for (;;) {
+        ssize_t retval;
+        retval = write(dev->fd, buffer, size);
+       VLOG_DBG("%s: write(%"PRIxPTR", %"PRIu64") = %"PRId64,
+                netdev_get_name(netdev_), (uintptr_t)buffer, size, retval);
+        if (retval >= 0) {
+           if (retval != size) {
+               VLOG_WARN_RL(&rl, "sent partial Ethernet packet (%"PRId64" bytes of "
+                            "%"PRIu64") on %s", retval, size, netdev_get_name(netdev_));
+           }
+            return 0;
+        } else if (errno != EINTR) {
+            if (errno != EAGAIN) {
+                VLOG_WARN_RL(&rl, "error sending Ethernet packet on %s: %s",
+                    netdev_get_name(netdev_), strerror(errno));
+            }
+            return errno;
+        }
+    }
+}
+
+static void
+netdev_pltap_send_wait(struct netdev *netdev_)
+{
+    struct netdev_dev_pltap *dev = 
+       netdev_dev_pltap_cast(netdev_get_dev(netdev_));
+    if (dev->finalized && dev->fd >= 0) {
+        poll_fd_wait(dev->fd, POLLOUT);
+    }
+}
+
+static int
+netdev_pltap_drain(struct netdev *netdev_)
+{
+    struct netdev_dev_pltap *dev = 
+       netdev_dev_pltap_cast(netdev_get_dev(netdev_));
+    char buffer[128];
+    int error;
+
+    if (dev->fd < 0 || !dev->finalized)
+       return 0;
+    for (;;) {
+       error = recv(dev->fd, buffer, 128, MSG_TRUNC);
+       if (error) {
+            if (error == -EAGAIN)
+               break;
+            else if (error != -EMSGSIZE)
+               return error;
+       }
+    }
+    return 0;
+}
+
+static int
+netdev_pltap_set_etheraddr(struct netdev *netdev,
+                           const uint8_t mac[ETH_ADDR_LEN])
+{
+    struct netdev_dev_pltap *dev =
+        netdev_dev_pltap_cast(netdev_get_dev(netdev));
+
+    if (!eth_addr_equals(dev->hwaddr, mac)) {
+        memcpy(dev->hwaddr, mac, ETH_ADDR_LEN);
+        netdev_pltap_update_seq(dev);
+    }
+
+    return 0;
+}
+
+// XXX we need the real mac
+static int
+netdev_pltap_get_etheraddr(const struct netdev *netdev,
+                           uint8_t mac[ETH_ADDR_LEN])
+{
+    const struct netdev_dev_pltap *dev =
+        netdev_dev_pltap_cast(netdev_get_dev(netdev));
+
+    memcpy(mac, dev->hwaddr, ETH_ADDR_LEN);
+    return 0;
+}
+
+
+// XXX can we read stats in planetlab?
+static int
+netdev_pltap_get_stats(const struct netdev *netdev OVS_UNUSED, struct netdev_stats *stats OVS_UNUSED)
+{
+    return -ENOTSUP;
+}
+
+static int
+netdev_pltap_set_stats(struct netdev *netdev OVS_UNUSED, const struct netdev_stats *stats OVS_UNUSED)
+{
+    return -ENOTSUP;
+}
+
+static int
+netdev_pltap_update_flags(struct netdev *netdev,
+                          enum netdev_flags off, enum netdev_flags on,
+                          enum netdev_flags *old_flagsp)
+{
+    struct netdev_dev_pltap *dev =
+        netdev_dev_pltap_cast(netdev_get_dev(netdev));
+
+    if ((off | on) & ~(NETDEV_UP | NETDEV_PROMISC)) {
+        return EINVAL;
+    }
+
+    // XXX should we actually do something with these flags?
+    *old_flagsp = dev->flags;
+    dev->flags |= on;
+    dev->flags &= ~off;
+    if (*old_flagsp != dev->flags) {
+        netdev_pltap_update_seq(dev);
+    }
+    return 0;
+}
+
+static unsigned int
+netdev_pltap_change_seq(const struct netdev *netdev)
+{
+    return netdev_dev_pltap_cast(netdev_get_dev(netdev))->change_seq;
+}
+\f
+/* Helper functions. */
+
+static void
+netdev_pltap_update_seq(struct netdev_dev_pltap *dev)
+{
+    dev->change_seq++;
+    if (!dev->change_seq) {
+        dev->change_seq++;
+    }
+}
+
+static void
+netdev_pltap_get_real_name(struct unixctl_conn *conn,
+                     int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED)
+{
+    struct netdev_dev_pltap *pltap_dev;
+
+    pltap_dev = shash_find_data(&pltap_netdev_devs, argv[1]);
+    if (!pltap_dev) {
+        unixctl_command_reply_error(conn, "no such pltap netdev");
+        return;
+    }
+    if (pltap_dev->error) {
+       unixctl_command_reply_error(conn, pltap_dev->error);
+       return;
+    }
+
+    unixctl_command_reply(conn, pltap_dev->real_name);
+}
+
+static int
+netdev_pltap_init(void)
+{
+    unixctl_command_register("netdev-pltap/get-tapname", "port",
+                             1, 1, netdev_pltap_get_real_name, NULL);
+    return 0;
+}
+
+const struct netdev_class netdev_pltap_class = {
+    "pltap",
+    netdev_pltap_init,
+    NULL,  
+    NULL,            
+
+    netdev_pltap_create,
+    netdev_pltap_destroy,
+    netdev_pltap_get_config,
+    netdev_pltap_set_config, 
+
+    netdev_pltap_open,
+    netdev_pltap_close,
+
+    netdev_pltap_listen,
+    netdev_pltap_recv,
+    netdev_pltap_recv_wait,
+    netdev_pltap_drain,
+
+    netdev_pltap_send, 
+    netdev_pltap_send_wait,  
+
+    netdev_pltap_set_etheraddr,
+    netdev_pltap_get_etheraddr,
+    NULL,                      /* get_mtu */
+    NULL,                      /* set_mtu */
+    NULL,                       /* get_ifindex */
+    NULL,                      /* get_carrier */
+    NULL,                       /* get_carrier_resets */
+    NULL,                       /* get_miimon */
+    netdev_pltap_get_stats,
+    netdev_pltap_set_stats,
+
+    NULL,                       /* get_features */
+    NULL,                       /* set_advertisements */
+
+    NULL,                       /* set_policing */
+    NULL,                       /* get_qos_types */
+    NULL,                       /* get_qos_capabilities */
+    NULL,                       /* get_qos */
+    NULL,                       /* set_qos */
+    NULL,                       /* get_queue */
+    NULL,                       /* set_queue */
+    NULL,                       /* delete_queue */
+    NULL,                       /* get_queue_stats */
+    NULL,                       /* dump_queues */
+    NULL,                       /* dump_queue_stats */
+
+    NULL,                       /* get_in4 */
+    NULL,                       /* set_in4 */
+    NULL,                       /* get_in6 */
+    NULL,                       /* add_router */
+    NULL,                       /* get_next_hop */
+    NULL,                       /* get_drv_info */
+    NULL,                       /* arp_lookup */
+
+    netdev_pltap_update_flags,
+
+    netdev_pltap_change_seq
+};
index f56a0ce..f1b123a 100644 (file)
@@ -599,9 +599,9 @@ extern const struct netdev_class netdev_tap_class;
 #ifdef __FreeBSD__
 extern const struct netdev_class netdev_bsd_class;
 #endif
-extern const struct netdev_class netdev_tap_pl_class;
 
 extern const struct netdev_class netdev_tunnel_class;
+extern const struct netdev_class netdev_pltap_class;
 
 #ifdef  __cplusplus
 }
index 2b4dec4..f86068a 100644 (file)
@@ -79,7 +79,6 @@ netdev_initialize(void)
         netdev_register_provider(&netdev_linux_class);
         netdev_register_provider(&netdev_internal_class);
         netdev_register_provider(&netdev_tap_class);
-       netdev_register_provider(&netdev_tap_pl_class);
         netdev_vport_register();
 #endif
 #ifdef __FreeBSD__
@@ -87,6 +86,7 @@ netdev_initialize(void)
         netdev_register_provider(&netdev_bsd_class);
 #endif
        netdev_register_provider(&netdev_tunnel_class);
+       netdev_register_provider(&netdev_pltap_class);
     }
 }
 
index 12c2a70..1f083e5 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
-#include <unistd.h>
 #include <sys/socket.h>
 #include <linux/if.h>
 #include <linux/if_tun.h>
 
-#include "tunalloc.h"
+#define VSYS_TUNTAP "/vsys/fd_tuntap.control"
 
-#define VSYS_TUNTAP "/var/run/pl-ovs.control"
+
+int tun_alloc(int iftype, char *if_name);
 
 /* Reads vif FD from "fd", writes interface name to vif_name, and returns vif FD.
  * vif_name should be IFNAMSIZ chars long. */
-static int receive_vif_fd(int fd, char *vif_name)
+static
+int receive_vif_fd(int fd, char *vif_name)
 {
        struct msghdr msg;
        struct iovec iov;
        int rv;
        size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
        struct cmsghdr *cmsg;
+       unsigned char *data;
 
     /* Use IOV to read interface name */
        iov.iov_base = vif_name;
@@ -45,6 +47,7 @@ static int receive_vif_fd(int fd, char *vif_name)
 
        while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
        if (rv == -1) {
+               perror("recvmsg");
                return -1;
        }
        if(!rv) {
@@ -54,9 +57,12 @@ static int receive_vif_fd(int fd, char *vif_name)
 
        cmsg = CMSG_FIRSTHDR(&msg);
        if (!cmsg->cmsg_type == SCM_RIGHTS) {
+               fprintf(stderr, "got control message of unknown type %d\n",
+                       cmsg->cmsg_type);
                return -1;
        }
-       return *(int*)CMSG_DATA(cmsg);
+       data = CMSG_DATA(cmsg);
+       return *(int*)data;
 }
 
 
@@ -68,7 +74,8 @@ int tun_alloc(int iftype, char *if_name)
 
     control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (control_fd == -1) {
-        return -1;
+        perror("Could not create UNIX socket\n");
+        exit(-1);
     }
 
     memset(&addr, 0, sizeof(struct sockaddr_un));
@@ -79,12 +86,16 @@ int tun_alloc(int iftype, char *if_name)
 
     if (connect(control_fd, (struct sockaddr *) &addr,
                 sizeof(struct sockaddr_un)) == -1) {
-        return -1;
+        perror("Could not connect to Vsys control socket");
+        exit(-1);
     }
 
-    remotefd = receive_vif_fd(control_fd, if_name);
-
-    close(control_fd);
+    /* passing type param */
+    if (send(control_fd, &iftype, sizeof(iftype), 0) != sizeof(iftype)) {
+        perror("Could not send paramater to Vsys control socket");
+        exit(-1);
+    }
 
+    remotefd = receive_vif_fd(control_fd, if_name);
     return remotefd;
 }
index efccfa9..f32a083 100644 (file)
@@ -1,5 +1,3 @@
-sbin_PROGRAMS += planetlab/pltap-ovs/pltap-ovs 
-sbin_PROGRAMS += planetlab/vsysc/vsysc
 
 # this Makefile is not intended to go on the sliver image - esp. not in /usr/sbin
 #      planetlab/scripts/Makefile
@@ -7,13 +5,5 @@ sbin_PROGRAMS += planetlab/vsysc/vsysc
 #      planetlab/scripts/showgraph
 dist_sbin_SCRIPTS += planetlab/scripts/sliver-ovs 
 
-planetlab_pltap_ovs_pltap_ovs_SOURCES =
-planetlab_pltap_ovs_pltap_ovs_SOURCES += planetlab/pltap-ovs/pltap-ovs.c
-planetlab_pltap_ovs_pltap_ovs_SOURCES += planetlab/pltap-ovs/tunalloc.c
-planetlab_pltap_ovs_pltap_ovs_SOURCES += planetlab/pltap-ovs/tunalloc.h
-
-planetlab_vsysc_vsysc_SOURCES =
-planetlab_vsysc_vsysc_SOURCES += planetlab/vsysc/vsysc.c
-
 EXTRA_DIST += \
        planetlab/scripts/sliver-ovs.in
index cf4bc60..40e8803 100644 (file)
@@ -11,6 +11,9 @@ include $(CONF)
 # if undefined in the conf file, use single dash
 SEP?=-
 
+# bridge name (XXX the same on all nodes)
+BRIDGE?=$(SLICE)
+
 ### helper functions
 # flip(1) = 2
 # flip(2) = 1
@@ -131,8 +134,8 @@ cache/switch.%: cache/db.%
 
 cache/bridge.%: cache/switch.%
        @echo "Creating bridge on $(call display,$*) - logs in $@.log"
-       @$(SSH) $(HOST_$*) $(SUDO) sliver-ovs create-bridge $(IP_$*) > $@ 2> $@.log || { rm $@; exit 1; }
-       @echo Created bridge $$(cat $@) on $(HOST_$*)
+       @$(SSH) $(HOST_$*) $(SUDO) sliver-ovs create-bridge $(BRIDGE) $(IP_$*) > $@ 2> $@.log || { rm $@; exit 1; }
+       @echo Created bridge with tap $$(cat $@) on $(call display,$*)
 
 # xxx this probably needs a more thorough cleanup in cache/
 cache/stop.%: del-bridge.%
@@ -152,7 +155,7 @@ U/%: del-iface.%@1 del-iface.%@2
 del-bridge.%: cache/db.%
        @echo "Deleting bridge on $(call display,$*)"
        @if [ -f cache/bridge.$* ]; then \
-               $(SSH) $(HOST_$*) $(SUDO) sliver-ovs del-bridge $$(cat cache/bridge.$*);\
+               $(SSH) $(HOST_$*) $(SUDO) sliver-ovs del-bridge $(BRIDGE);\
         fi
        @rm -f cache/bridge.$* \
              cache/iface.$*$(SEP)*@1 cache/iface.*$(SEP)$*@2 \
@@ -195,9 +198,8 @@ del-iface.%: cache/db.$$(call get,%)
 #bridgefile=cache/bridge.$(nodeid)
 cache/iface.%: cache/bridge.$$(call get,%)
        @echo "Creating interface for link $(call linkpart,$(*F)) on $(call display,$(call get,$(*F))) - logs in $@.log"
-       @$(SSH) $(call solve,$(call get,$(*F))) $(SUDO) sliver-ovs create-port $$(cat cache/bridge.$(call get,$(*F))) L$(call linkpart,$(*F)) > $@ 2> $@.log || { rm $@; exit 1; }
-       echo cache/bridge.$(call get,$(*F))
-       echo cache/host.$(call get,$(*F)) cache/iface.$(*F) cache/iface.$(call opp,$(*F))
+       @$(SSH) $(call solve,$(call get,$(*F))) $(SUDO) sliver-ovs create-port $(BRIDGE) \
+               L$(call linkpart,$(*F)) > $@ 2> $@.log || { rm $@; exit 1; }
 
 
 # linkid=$(call linkpart,%)
diff --git a/planetlab/pltap-ovs/pltap-ovs.c b/planetlab/pltap-ovs/pltap-ovs.c
deleted file mode 100644 (file)
index e1660b0..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#include <sys/un.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <errno.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-
-#include "tunalloc.h"
-
-#define OVS_SOCK "/var/run/pl-ovs.control"
-
-void send_fd(int p, int fd, char* vif_name);
-
-char *appname;
-
-#define ERROR(msg)                                                             \
-        do {                                                                   \
-                fprintf(stderr, "%s: %s: %s", appname, msg, strerror(errno));  \
-                exit(1);                                                       \
-        } while (0)
-
-
-static
-int send_vif_fd(int sock_fd, int vif_fd, char *vif_name)
-{
-        int retval;
-        struct msghdr msg;
-        struct cmsghdr *p_cmsg;
-        struct iovec vec;
-        size_t cmsgbuf[CMSG_SPACE(sizeof(vif_fd)) / sizeof(size_t)];
-        int *p_fds;
-
-
-        msg.msg_control = cmsgbuf;
-        msg.msg_controllen = sizeof(cmsgbuf);
-        p_cmsg = CMSG_FIRSTHDR(&msg);
-        p_cmsg->cmsg_level = SOL_SOCKET;
-        p_cmsg->cmsg_type = SCM_RIGHTS;
-        p_cmsg->cmsg_len = CMSG_LEN(sizeof(vif_fd));
-        p_fds = (int *) CMSG_DATA(p_cmsg);
-        *p_fds = vif_fd;
-        msg.msg_controllen = p_cmsg->cmsg_len;
-        msg.msg_name = NULL;
-        msg.msg_namelen = 0;
-        msg.msg_iov = &vec;
-        msg.msg_iovlen = 1;
-        msg.msg_flags = 0;
-
-        /* Send the interface name as the iov */
-        vec.iov_base = vif_name;
-        vec.iov_len = strlen(vif_name)+1;
-
-        while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
-        if (retval == -1) {
-                ERROR("sending file descriptor");
-        }
-        return 0;
-}
-
-void send_fd(int p, int fd, char* vif_name)
-{
-        int control_fd;
-        int accept_fd;
-        struct sockaddr_un addr, accept_addr;
-        socklen_t addr_len = sizeof(accept_addr);
-
-        control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-        if (control_fd == -1 && errno != ENOENT) {
-                ERROR("Could not create UNIX socket");
-        }
-
-        memset(&addr, 0, sizeof(struct sockaddr_un));
-        /* Clear structure */
-        addr.sun_family = AF_UNIX;
-        strncpy(addr.sun_path, OVS_SOCK,
-                        sizeof(addr.sun_path) - 1);
-
-        if (unlink(OVS_SOCK) == -1 && errno != ENOENT) {
-                ERROR("Could not unlink " OVS_SOCK " control socket");
-        }
-
-        if (bind(control_fd, (struct sockaddr *) &addr,
-                                sizeof(struct sockaddr_un)) == -1) {
-                ERROR("Could not bind to " OVS_SOCK " control socket");
-        }
-
-        if (listen(control_fd, 5) == -1) {
-                ERROR("listen on " OVS_SOCK " failed");
-        }
-        if (write(p, "1", 1) != 1) {
-                ERROR("writing on the synch pipe");
-        }
-        if ((accept_fd = accept(control_fd, (struct sockaddr*) &accept_addr,
-                                                &addr_len)) == -1) {
-                ERROR("accept on " OVS_SOCK " failed");
-        }
-        send_vif_fd(accept_fd, fd, vif_name);
-}
-
-int main(int argc, char* argv[])
-{
-        char if_name[IFNAMSIZ];
-        int p[2]; // synchronization pipe
-        char dummy;
-       int tun_fd;
-
-       (void) argc; // unused
-
-        if (pipe(p) < 0) {
-                ERROR("pipe");
-        }
-
-        tun_fd = tun_alloc(IFF_TAP, if_name);
-
-        appname = argv[0];
-
-        switch(fork()) {
-        case -1:
-                ERROR("fork");
-                exit(1);
-        case 0:
-                close(1);
-                open("/dev/null", O_WRONLY);
-                close(p[0]);
-                send_fd(p[1], tun_fd, if_name);
-                exit(0);
-        default:
-                close(p[1]);
-                if (read(p[0], &dummy, 1) != 1) {
-                        ERROR("reading from the synch pipe");
-                }
-                printf("%s\n", if_name);
-        }
-        return 0;
-}
diff --git a/planetlab/pltap-ovs/tunalloc.c b/planetlab/pltap-ovs/tunalloc.c
deleted file mode 100644 (file)
index 1f083e5..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* Slice-side code to allocate tuntap interface in root slice
- * Based on bmsocket.c
- *  Thom Haddow - 08/10/09
- *
- * Call tun_alloc() with IFFTUN or IFFTAP as an argument to get back fd to
- * new tuntap interface. Interface name can be acquired via TUNGETIFF ioctl.
- */
-
-#include <sys/un.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-
-#define VSYS_TUNTAP "/vsys/fd_tuntap.control"
-
-
-int tun_alloc(int iftype, char *if_name);
-
-/* Reads vif FD from "fd", writes interface name to vif_name, and returns vif FD.
- * vif_name should be IFNAMSIZ chars long. */
-static
-int receive_vif_fd(int fd, char *vif_name)
-{
-       struct msghdr msg;
-       struct iovec iov;
-       int rv;
-       size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
-       struct cmsghdr *cmsg;
-       unsigned char *data;
-
-    /* Use IOV to read interface name */
-       iov.iov_base = vif_name;
-       iov.iov_len = IFNAMSIZ;
-
-       msg.msg_name = 0;
-       msg.msg_namelen = 0;
-       msg.msg_iov = &iov;
-       msg.msg_iovlen = 1;
-       /* old BSD implementations should use msg_accrights instead of
-        * msg_control; the interface is different. */
-       msg.msg_control = ccmsg;
-       msg.msg_controllen = sizeof(ccmsg);
-
-       while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
-       if (rv == -1) {
-               perror("recvmsg");
-               return -1;
-       }
-       if(!rv) {
-               /* EOF */
-               return -1;
-       }
-
-       cmsg = CMSG_FIRSTHDR(&msg);
-       if (!cmsg->cmsg_type == SCM_RIGHTS) {
-               fprintf(stderr, "got control message of unknown type %d\n",
-                       cmsg->cmsg_type);
-               return -1;
-       }
-       data = CMSG_DATA(cmsg);
-       return *(int*)data;
-}
-
-
-int tun_alloc(int iftype, char *if_name)
-{
-    int control_fd;
-    struct sockaddr_un addr;
-    int remotefd;
-
-    control_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (control_fd == -1) {
-        perror("Could not create UNIX socket\n");
-        exit(-1);
-    }
-
-    memset(&addr, 0, sizeof(struct sockaddr_un));
-    /* Clear structure */
-    addr.sun_family = AF_UNIX;
-    strncpy(addr.sun_path, VSYS_TUNTAP,
-            sizeof(addr.sun_path) - 1);
-
-    if (connect(control_fd, (struct sockaddr *) &addr,
-                sizeof(struct sockaddr_un)) == -1) {
-        perror("Could not connect to Vsys control socket");
-        exit(-1);
-    }
-
-    /* passing type param */
-    if (send(control_fd, &iftype, sizeof(iftype), 0) != sizeof(iftype)) {
-        perror("Could not send paramater to Vsys control socket");
-        exit(-1);
-    }
-
-    remotefd = receive_vif_fd(control_fd, if_name);
-    return remotefd;
-}
diff --git a/planetlab/pltap-ovs/tunalloc.h b/planetlab/pltap-ovs/tunalloc.h
deleted file mode 100644 (file)
index 3e5caae..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _TUNALLOC_H
-#define _TUNALLOC_H
-
-int tun_alloc(int iftype, char *if_name);
-
-#endif
index 01089ee..dfd596f 100755 (executable)
@@ -157,38 +157,19 @@ function stop () {
 #################### create functions
 function create_bridge () {
     
-    get_params "IP/PREFIX" "$@"
+    get_params "bridge IP/PREFIX" "$@"
 
     IP=${IP_PREFIX%/*}
     PREFIX=${IP_PREFIX#*/}
 
-    set -e
     # ensure ovs-vswitchd is running
     is_switch_running || { echo "ovs-vswitchd not running" >&2 ; exit 1 ; }
 
-    # check whether the address is already assigned
-    TAPNAME=$(tapname $IP)
-    if [ ! -z "$TAPNAME" ]; then
-       if ovs-vsctl --db=unix:$DB_SOCKET br-exists "$TAPNAME"; then
-           echo $TAPNAME
-           exit 0
-       fi
-       kill_pltap_ovs
-       error "$IP already assigned to $TAPNAME"
-    fi
-
-    # we're clear
-    TAPNAME=$(pltap-ovs)
-    trap kill_pltap_ovs EXIT
-    # xxx wouldn't that be safer if left-aligned ?
-    vsysc vif_up << EOF
-       $TAPNAME
-       $IP
-       $PREFIX
-EOF
-    wait_device $TAPNAME 60 && \
-       ovs-vsctl --db=unix:$DB_SOCKET add-br $TAPNAME -- set bridge $TAPNAME datapath_type=planetlab
-    echo $TAPNAME
+    set -e
+    ovs-vsctl --db=unix:$DB_SOCKET -- --may-exist add-br "$bridge" \
+       -- set bridge "$bridge" datapath_type=planetlab \
+       -- set interface "$bridge" options:local_ip="$IP" option:local_netmask="$PREFIX"
+    ovs-appctl netdev-pltap/get-tapname "$bridge"
 }
 
 function create_port () {
diff --git a/planetlab/vsysc/vsysc.c b/planetlab/vsysc/vsysc.c
deleted file mode 100644 (file)
index 98c90e7..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/select.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#define VSYS_PATH "/vsys"
-
-#define MAXPATH 1024
-#define BUFSIZE 4096
-
-#define IN 0
-#define OUT 1
-
-char ctrl[2][MAXPATH]; /* paths of vsys.in & vsys.out */
-
-static void mkpath(int dir, const char* vsys)
-{
-       static const char *suffix[] = { "in", "out" };
-       int n;
-
-       if ( (n = snprintf(ctrl[dir], MAXPATH, "%s/%s.%s", VSYS_PATH, vsys, suffix[dir])) < 0) {
-               perror(vsys);
-               exit(EXIT_FAILURE);
-       } else if (n >= MAXPATH) {
-               fprintf(stderr, "argument too long\n");
-               exit(EXIT_FAILURE);
-       }
-}
-
-static int open_ctrl(int dir)
-{
-       int fd;
-       
-       if ( (fd = open(ctrl[dir], (dir == IN ? O_WRONLY : O_RDONLY) | O_NONBLOCK)) < 0) {
-               perror(ctrl[dir]);
-               exit(EXIT_FAILURE);
-       }
-       return fd;
-}
-
-
-static void set_nonblocking(int fd)
-{
-       int val;
-
-       if ( (val = fcntl(fd, F_GETFL, 0)) < 0) {
-               perror("fcntl F_GETFL");
-               exit(EXIT_FAILURE);
-       }
-       if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
-               perror("fcntl F_SETFL");
-               exit(EXIT_FAILURE);
-       }
-}
-
-#if 0
-static void print_set(const char* name, int max, const fd_set* set)
-{
-       int i, n = 0;
-       fprintf(stderr, "%s: {", name);
-       for (i = 0; i < max; i++) {
-               if (FD_ISSET(i, set)) {
-                       if (n++) fprintf(stderr, ", ");
-                       fprintf(stderr, "%d", i);
-               }
-       }
-       fprintf(stderr, "}\n");
-}
-#endif
-
-struct channel {
-       const char *name;
-       int active;
-       int writing;
-       char buf[BUFSIZE];
-       char *rp, *wp;
-       int rfd, wfd;
-};
-
-static int active_channels = 0;
-
-static void channel_init(struct channel *c, const char* name, int rfd, int wfd)
-{
-       c->name = name;
-       c->rp = c->buf;
-       c->wp = c->buf;
-       c->rfd = rfd;
-       c->wfd = wfd;
-       c->active = 1;
-       active_channels++;
-}
-
-static void channel_fdset(struct channel *c, fd_set* readset, fd_set* writeset)
-{
-       if (!c->active)
-               return;
-       if (c->writing) {
-               FD_SET(c->wfd, writeset);
-       } else {
-               FD_SET(c->rfd, readset);
-       } 
-}
-
-static void channel_run(struct channel *c, const fd_set* readset, const fd_set* writeset)
-{
-       int n;
-
-       if (!c->active)
-               return;
-       if (c->writing) {
-               if (FD_ISSET(c->wfd, writeset)) {
-                       if ( (n = write(c->wfd, c->wp, c->rp - c->wp)) < 0) {
-                               perror(c->name);
-                               exit(EXIT_FAILURE);
-                       }
-                       c->wp += n;
-                       if (c->wp == c->rp) {
-                               c->wp = c->rp = c->buf;
-                               c->writing = 0;
-                       } 
-               }
-       } else {
-               if (FD_ISSET(c->rfd, readset)) {
-                       if ( (n = read(c->rfd, c->rp, BUFSIZE)) < 0) {
-                               perror(c->name);
-                               exit(EXIT_FAILURE);
-                       }
-                       if (n) {
-                               c->wp = c->rp;
-                               c->rp += n;
-                               c->writing = 1;
-                       } else {
-                               close(c->wfd);
-                               c->active = 0;
-                               active_channels--;
-                       }
-               }
-       }
-}
-
-static struct channel channels[2];
-
-
-int main(int argc, char *argv[])
-{
-       int fd[2]; /* fds of vsys.in & vsys.out */
-       int maxfd;
-
-       fd_set readset, writeset;
-
-       if (argc != 2) {
-               fprintf(stderr, "Usage: %s <vsys>\n", argv[0]);
-               exit(EXIT_FAILURE);
-       }
-
-       mkpath(IN,  argv[1]);
-       mkpath(OUT, argv[1]);
-
-       maxfd = (STDOUT_FILENO > STDIN_FILENO ? STDOUT_FILENO : STDIN_FILENO);
-
-       fd[OUT] = open_ctrl(OUT);
-       if (fd[OUT] > maxfd)
-               maxfd = fd[OUT];
-       fd[IN]  = open_ctrl(IN);
-       if (fd[IN] > maxfd)
-               maxfd = fd[IN];
-
-       set_nonblocking(STDIN_FILENO);
-       set_nonblocking(STDOUT_FILENO);
-
-       channel_init(&channels[IN], "IN", STDIN_FILENO, fd[IN]);
-       channel_init(&channels[OUT], "OUT", fd[OUT], STDOUT_FILENO);
-
-       while (active_channels) {
-               FD_ZERO(&readset);
-               FD_ZERO(&writeset);
-               channel_fdset(&channels[IN], &readset, &writeset);
-               channel_fdset(&channels[OUT], &readset, &writeset);
-               if (select(maxfd + 1, &readset, &writeset, NULL, NULL) < 0) {
-                       perror("select");
-                       exit(EXIT_FAILURE);
-               }
-               channel_run(&channels[IN], &readset, &writeset);
-               channel_run(&channels[OUT], &readset, &writeset);
-       }
-       return EXIT_SUCCESS;
-}
-