eal: fix check for power of 2 in 0 case
[dpdk.git] / lib / librte_vhost / virtio-net.c
index 6d8de09..b041849 100644 (file)
 #include <sys/mman.h>
 #include <unistd.h>
 
+#include <sys/socket.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+
 #include <rte_ethdev.h>
 #include <rte_log.h>
 #include <rte_string_fns.h>
@@ -68,7 +72,8 @@ static struct virtio_net_device_ops const *notify_ops;
 static struct virtio_net_config_ll *ll_root;
 
 /* Features supported by this lib. */
-#define VHOST_SUPPORTED_FEATURES (1ULL << VIRTIO_NET_F_MRG_RXBUF)
+#define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+                                 (1ULL << VIRTIO_NET_F_CTRL_RX))
 static uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
 
 /* Line size for reading maps file. */
@@ -998,6 +1003,46 @@ set_vring_kick(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
        return 0;
 }
 
+/*
+ * Function to get the tap device name from the provided file descriptor and
+ * save it in the device structure.
+ */
+static int
+get_ifname(struct virtio_net *dev, int tap_fd, int pid)
+{
+       struct eventfd_copy fd_tap;
+       struct ifreq ifr;
+       uint32_t size, ifr_size;
+       int ret;
+
+       fd_tap.source_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
+       fd_tap.target_fd = tap_fd;
+       fd_tap.target_pid = pid;
+
+       if (eventfd_copy(dev, &fd_tap))
+               return -1;
+
+       ret = ioctl(fd_tap.source_fd, TUNGETIFF, &ifr);
+
+       if (close(fd_tap.source_fd) < 0)
+               RTE_LOG(ERR, VHOST_CONFIG,
+                       "(%"PRIu64") fd close failed\n",
+                       dev->device_fh);
+
+       if (ret >= 0) {
+               ifr_size = strnlen(ifr.ifr_name, sizeof(ifr.ifr_name));
+               size = ifr_size > sizeof(dev->ifname) ?
+                               sizeof(dev->ifname) : ifr_size;
+
+               strncpy(dev->ifname, ifr.ifr_name, size);
+       } else
+               RTE_LOG(ERR, VHOST_CONFIG,
+                       "(%"PRIu64") TUNGETIFF ioctl failed\n",
+                       dev->device_fh);
+
+       return 0;
+}
+
 /*
  * Called from CUSE IOCTL: VHOST_NET_SET_BACKEND
  * To complete device initialisation when the virtio driver is loaded,
@@ -1025,8 +1070,10 @@ set_backend(struct vhost_device_ctx ctx, struct vhost_vring_file *file)
         */
        if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
                if (((int)dev->virtqueue[VIRTIO_TXQ]->backend != VIRTIO_DEV_STOPPED) &&
-                       ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED))
+                       ((int)dev->virtqueue[VIRTIO_RXQ]->backend != VIRTIO_DEV_STOPPED)) {
+                       get_ifname(dev, file->fd, ctx.pid);
                        return notify_ops->new_device(dev);
+               }
        /* Otherwise we remove it. */
        } else
                if (file->fd == VIRTIO_DEV_STOPPED)