lib/timer.h \
lib/timeval.c \
lib/timeval.h \
+ lib/tunalloc.c \
+ lib/tunalloc.h \
lib/type-props.h \
lib/unaligned.h \
lib/unicode.c \
{
if (dp->class == &dpif_netdev_class)
return "tap";
+ if (dp->class == &dpif_planetlab_class)
+ return "tap_pl";
return "dummy";
}
struct dp_netdev *dp = get_dp_netdev(dpif);
int port_no;
- if (dpif->dpif_class != &dpif_netdev_class) {
+ if (dpif->dpif_class != &dpif_netdev_class &&
+ dpif->dpif_class != &dpif_planetlab_class)
+ {
/* If the port name contains a number, try to assign that port number.
* This can make writing unit tests easier because port numbers are
* predictable. */
DPIF_NETDEV_CLASS_FUNCTIONS
};
+const struct dpif_class dpif_planetlab_class = {
+ "planetlab",
+ DPIF_NETDEV_CLASS_FUNCTIONS
+};
+
static void
dpif_dummy_register__(const char *type)
{
extern const struct dpif_class dpif_linux_class;
extern const struct dpif_class dpif_netdev_class;
+extern const struct dpif_class dpif_planetlab_class;
#ifdef __cplusplus
}
&dpif_linux_class,
#endif
&dpif_netdev_class,
+ &dpif_planetlab_class,
};
struct registered_dpif_class {
#include "sset.h"
#include "timer.h"
#include "vlog.h"
+#include "tunalloc.h"
VLOG_DEFINE_THIS_MODULE(netdev_linux);
}
}
- if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") &&
+ if (!strncmp(netdev_dev_get_type(netdev_dev_), "tap", 3) &&
!netdev_dev->state.tap.opened) {
/* We assume that the first user of the tap device is the primary user
{
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
- if (netdev->fd > 0 && strcmp(netdev_get_type(netdev_), "tap")) {
+ if (netdev->fd > 0 && strncmp(netdev_get_type(netdev_), "tap", 3)) {
close(netdev->fd);
}
free(netdev);
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
if (netdev->fd < 0) {
return 0;
- } else if (!strcmp(netdev_get_type(netdev_), "tap")) {
+ } else if (!strncmp(netdev_get_type(netdev_), "tap", 3)) {
struct ifreq ifr;
int error = netdev_linux_do_ioctl(netdev_get_name(netdev_), &ifr,
SIOCGIFTXQLEN, "SIOCGIFTXQLEN");
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
if (netdev->fd < 0) {
/* Nothing to do. */
- } else if (strcmp(netdev_get_type(netdev_), "tap")) {
+ } else if (strncmp(netdev_get_type(netdev_), "tap", 3)) {
poll_fd_wait(netdev->fd, POLLOUT);
} else {
/* TAP device always accepts packets.*/
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_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)
{
netdev_vport_set_stats,
NULL, /* get_features */
netdev_internal_get_drv_info);
+
+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);
\f
/* HTB traffic control class. */
extern const struct netdev_class netdev_linux_class;
extern const struct netdev_class netdev_internal_class;
extern const struct netdev_class netdev_tap_class;
+extern const struct netdev_class netdev_tap_pl_class;
extern const struct netdev_class netdev_tunnel_class;
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
netdev_register_provider(&netdev_tunnel_class);
--- /dev/null
+/* 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 <unistd.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+#include "tunalloc.h"
+
+#define VSYS_TUNTAP "/var/run/pl-ovs.control"
+
+/* 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;
+
+ /* 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) {
+ return -1;
+ }
+ if(!rv) {
+ /* EOF */
+ return -1;
+ }
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+ if (!cmsg->cmsg_type == SCM_RIGHTS) {
+ return -1;
+ }
+ return *(int*)CMSG_DATA(cmsg);
+}
+
+
+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) {
+ return -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) {
+ return -1;
+ }
+
+ /* passing type param */
+ if (send(control_fd, &iftype, sizeof(iftype), 0) != sizeof(iftype)) {
+ return -1;
+ }
+
+ remotefd = receive_vif_fd(control_fd, if_name);
+
+ close(control_fd);
+
+ return remotefd;
+}
--- /dev/null
+#ifndef _TUNALLOC_H
+#define _TUNALLOC_H
+
+int tun_alloc(int iftype, char *if_name);
+
+#endif