[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Minios-devel] [UNIKRAFT PATCH 04/15] plat/driver: Create a tap dev during configuration



The patch creates a tap device while configuring the net device.

Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
---
 plat/drivers/tap/tap.c               |  92 ++++++++++++++++++++++++++++++-
 plat/linuxu/Makefile.uk              |   1 +
 plat/linuxu/include/linuxu/syscall.h |  27 +++++++++
 plat/linuxu/include/linuxu/tap.h     | 103 +++++++++++++++++++++++++++++++++++
 plat/linuxu/tap_io.c                 |  67 +++++++++++++++++++++++
 5 files changed, 289 insertions(+), 1 deletion(-)
 create mode 100644 plat/linuxu/tap_io.c

diff --git a/plat/drivers/tap/tap.c b/plat/drivers/tap/tap.c
index 2f49788..8c10502 100644
--- a/plat/drivers/tap/tap.c
+++ b/plat/drivers/tap/tap.c
@@ -67,18 +67,41 @@
 #define to_tapnetdev(dev) \
                __containerof(dev, struct tap_net_dev, ndev)
 
+struct uk_netdev_tx_queue {
+       int queue_id;
+       UK_TAILQ_ENTRY(struct uk_netdev_tx_queue) next;
+       struct uk_alloc *a;
+       /* Set the file descriptor for the tap device */
+       int fd;
+};
+
+struct uk_netdev_rx_queue {
+       int queue_id;
+       UK_TAILQ_ENTRY(struct uk_netdev_rx_queue) next;
+       struct uk_alloc *a;
+       /* Set the file descriptor for the tap device */
+       int fd;
+};
+
 struct tap_net_dev {
        /* Net device structure */
        struct uk_netdev    ndev;
        /* max number of queues */
        __u16 max_qpairs;
        /* Number of rxq configured */
+       __u16 rxq_cnt;
+       UK_TAILQ_HEAD(tap_rxqs, struct uk_netdev_rx_queue) rxqs;
+       /* Number of txq configured */
+       __u16 txq_cnt;
+       UK_TAILQ_HEAD(tap_txqs, struct uk_netdev_tx_queue) txqs;
        /* The list of the tap device */
        UK_TAILQ_ENTRY(struct tap_net_dev) next;
        /* UK Netdevice identifier */
        __u16 tid;
        /* UK Netdevice identifier */
        __u16 id;
+       /* File Descriptor for the tap device */
+       int tap_fd;
        /* Name of the character device */
        char name[IFNAMSIZ];
        /* MTU of the device */
@@ -140,6 +163,7 @@ static int tap_netdev_rxq_info_get(struct uk_netdev *dev, 
__u16 queue_id,
                                   struct uk_netdev_queue_info *qinfo);
 static int tap_netdev_txq_info_get(struct uk_netdev *dev, __u16 queue_id,
                                   struct uk_netdev_queue_info *qinfo);
+static int tap_device_create(struct tap_net_dev *tdev, __u32 feature_flags);
 
 /**
  * Local function definitions
@@ -223,6 +247,10 @@ static void tap_netdev_info_get(struct uk_netdev *dev 
__unused,
                                struct uk_netdev_info *dev_info)
 {
        UK_ASSERT(dev_info);
+       dev_info->max_rx_queues = 1;
+       dev_info->max_tx_queues = 1;
+       dev_info->nb_encap_tx = 0;
+       dev_info->nb_encap_rx = 0;
 }
 
 static unsigned int tap_netdev_promisc_get(struct uk_netdev *n)
@@ -266,10 +294,72 @@ static int tap_netdev_mac_set(struct uk_netdev *n,
 static int tap_netdev_configure(struct uk_netdev *n,
                                const struct uk_netdev_conf *conf)
 {
-       int rc = -EINVAL;
+       int rc = 0;
+       struct tap_net_dev *tdev = NULL;
+       __u32 feature_flag = 0;
 
        UK_ASSERT(n && conf);
+       tdev = to_tapnetdev(n);
+
+       if (conf->nb_rx_queues > tdev->max_qpairs
+           || conf->nb_tx_queues > tdev->max_qpairs) {
+               uk_pr_err(DRIVER_NAME": rx-queue:%d, tx-queue:%d not supported",
+                         conf->nb_rx_queues, conf->nb_tx_queues);
+               rc = -ENOTSUP;
+               goto exit;
+       } else if (conf->nb_rx_queues > 1 || conf->nb_tx_queues > 1) {
+               feature_flag = UK_IFF_MULTI_QUEUE;
+       }
+
+       /* Open the device and set the interface */
+       rc = tap_device_create(tdev, feature_flag);
+       if (rc < 0) {
+               uk_pr_err(DRIVER_NAME": Failed to configure the tap device\n");
+               goto exit;
+       }
+
+       /* Initialize the tx/rx queues */
+       UK_TAILQ_INIT(&tdev->rxqs);
+       tdev->rxq_cnt = 0;
+       UK_TAILQ_INIT(&tdev->txqs);
+       tdev->txq_cnt = 0;
+exit:
        return rc;
+close_tap_dev:
+       tap_close(tdev->tap_fd);
+       goto exit;
+}
+
+static int tap_device_create(struct tap_net_dev *tdev, __u32 feature_flags)
+{
+       int rc = 0;
+       struct uk_ifreq ifreq = {0};
+
+       /* Open the tap device */
+       rc = tap_open(O_RDWR | O_NONBLOCK);
+       if (rc < 0) {
+               uk_pr_err(DRIVER_NAME": Failed(%d) to open the tap device\n",
+                         rc);
+               goto exit;
+       }
+
+       tdev->tap_fd = rc;
+
+       rc = tap_dev_configure(tdev->tap_fd, feature_flags, &ifreq);
+       if (rc < 0) {
+               uk_pr_err(DRIVER_NAME": Failed to setup the tap device\n");
+               goto close_tap;
+       }
+
+       snprintf(tdev->name, sizeof(tdev->name), "%s", ifreq.ifr_name);
+       uk_pr_info(DRIVER_NAME": Configuring tap device %s\n", tdev->name);
+
+exit:
+       return rc;
+close_tap:
+       tap_close(tdev->tap_fd);
+       tdev->tap_fd = -1;
+       goto exit;
 }
 
 static const struct uk_netdev_ops tap_netdev_ops = {
diff --git a/plat/linuxu/Makefile.uk b/plat/linuxu/Makefile.uk
index 561909e..2568d0d 100644
--- a/plat/linuxu/Makefile.uk
+++ b/plat/linuxu/Makefile.uk
@@ -45,6 +45,7 @@ LIBLINUXUPLAT_SRCS-y              += 
$(LIBLINUXUPLAT_BASE)/time.c
 LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/lcpu.c|common
 LIBLINUXUPLAT_SRCS-y              += $(UK_PLAT_COMMON_BASE)/memory.c|common
 LIBLINUXUPLAT_SRCS-y              += $(LIBLINUXUPLAT_BASE)/io.c
+LIBLINUXUPLAT_SRCS-$(CONFIG_TAP_NET) += $(LIBLINUXUPLAT_BASE)/tap_io.c
 LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_X86_64) += \
                        $(LIBLINUXUPLAT_BASE)/x86/link64.lds.S
 LIBLINUXUPLAT_SRCS-$(CONFIG_ARCH_ARM_32) += \
diff --git a/plat/linuxu/include/linuxu/syscall.h 
b/plat/linuxu/include/linuxu/syscall.h
index 0dca7c5..1604712 100644
--- a/plat/linuxu/include/linuxu/syscall.h
+++ b/plat/linuxu/include/linuxu/syscall.h
@@ -64,6 +64,33 @@ static inline ssize_t sys_write(int fd, const char *buf, 
size_t len)
                                  (long) (len));
 }
 
+#ifndef O_RDONLY
+#define O_RDONLY                  00000000
+#endif /* O_RDONLY */
+
+#ifndef O_WRONLY
+#define O_WRONLY                  00000001
+#endif /* O_WRONLY */
+#ifndef O_RDWR
+#define O_RDWR                    00000002
+#endif /* O_RDWR */
+
+#ifndef O_NONBLOCK
+#define O_NONBLOCK              04000
+#endif /* O_NONBLOCK */
+static inline int sys_open(const char *pathname, int flags)
+{
+       return (ssize_t) syscall2(__SC_OPEN,
+                                 (long) pathname,
+                                 (long) flags);
+}
+
+static inline int sys_close(int fd)
+{
+       return (ssize_t) syscall1(__SC_CLOSE,
+                                 (long) fd);
+}
+
 static inline int sys_exit(int status)
 {
        return (int) syscall1(__SC_EXIT,
diff --git a/plat/linuxu/include/linuxu/tap.h b/plat/linuxu/include/linuxu/tap.h
index 83116f5..a80c2b7 100644
--- a/plat/linuxu/include/linuxu/tap.h
+++ b/plat/linuxu/include/linuxu/tap.h
@@ -35,6 +35,13 @@
 #define __TAP_H__
 
 #include <uk/arch/types.h>
+#include <linuxu/syscall.h>
+#include <linuxu/ioctl.h>
+
+/**
+ * TAP Device Path
+ */
+#define TAPDEV_PATH             "/dev/net/tun"
 
 /**
  * Using the musl as reference for the data structure definition
@@ -42,4 +49,100 @@
  */
 #define IFNAMSIZ        16
 
+typedef __u16 uk_in_port_t;
+typedef __u32 uk_in_addr_t;
+typedef __u16 uk_sa_family_t;
+
+struct uk_in_addr {
+       uk_in_addr_t s_addr;
+};
+
+struct uk_sockaddr {
+       uk_sa_family_t sa_family;
+       char sa_data[14];
+};
+
+struct uk_ifmap {
+       unsigned long int mem_start;
+       unsigned long int mem_end;
+       unsigned short int base_addr;
+       unsigned char irq;
+       unsigned char dma;
+       unsigned char port;
+};
+
+struct uk_ifreq {
+       union {
+               char ifrn_name[IFNAMSIZ];
+       } uk_ifr_ifrn;
+
+       union {
+               struct uk_sockaddr ifru_addr;
+               struct uk_sockaddr ifru_dstaddr;
+               struct uk_sockaddr ifru_broadaddr;
+               struct uk_sockaddr ifru_netmask;
+               struct uk_sockaddr ifru_hwaddr;
+               short int       ifru_flags;
+               int             ifru_ivalue;
+               int             ifru_mtu;
+               struct uk_ifmap    ifru_map;
+               char            ifru_slave[IFNAMSIZ];
+               char            ifru_newname[IFNAMSIZ];
+               char           *ifru_data;
+       } uk_ifr_ifru;
+};
+
+#define ifr_name    uk_ifr_ifrn.ifrn_name
+#define ifr_hwaddr  uk_ifr_ifru.ifru_hwaddr
+#define ifr_addr    uk_ifr_ifru.ifru_addr
+#define ifr_dstaddr uk_ifr_ifru.ifru_dstaddr
+#define ifr_broadaddr   uk_ifr_ifru.ifru_broadaddr
+#define ifr_netmask uk_ifr_ifru.ifru_netmask
+#define ifr_flags   uk_ifr_ifru.ifru_flags
+#define ifr_metric  uk_ifr_ifru.ifru_ivalue
+#define ifr_mtu     uk_ifr_ifru.ifru_mtu
+#define ifr_map     uk_ifr_ifru.ifru_map
+#define ifr_slave   uk_ifr_ifru.ifru_slave
+#define ifr_data    uk_ifr_ifru.ifru_data
+#define ifr_ifindex uk_ifr_ifru.ifru_ivalue
+#define ifr_bandwidth   uk_ifr_ifru.ifru_ivalue
+#define ifr_qlen    uk_ifr_ifru.ifru_ivalue
+#define ifr_newname uk_ifr_ifru.ifru_newname
+
+#define UK_TUNSETIFF     (0x400454ca)
+#define UK_SIOCGIFNAME   (0x8910)
+#define UK_SIOCGIFFLAGS  (0x8913)
+#define UK_SIOCSIFFLAGS  (0x8914)
+#define UK_SIOCGIFADDR   (0x8915)
+#define UK_SIOCSIFADDR   (0x8916)
+#define UK_SIOCGIFMTU    (0x8921)
+#define UK_SIOCSIFMTU    (0x8922)
+#define UK_SIOCSIFHWADDR (0x8924)
+#define UK_SIOCGIFHWADDR (0x8927)
+#define UK_SIOCGIFTXQLEN (0x8942)
+#define UK_SIOCSIFTXQLEN (0x8943)
+#define UK_SIOCGIFINDEX  (0x8933)
+/* TUNSETIFF ifr flags */
+#define UK_IFF_TUN     (0x0001)
+#define UK_IFF_TAP     (0x0002)
+#define UK_IFF_NO_PI   (0x1000)
+/* This flag has no real effect */
+#define UK_IFF_ONE_QUEUE   (0x2000)
+#define UK_IFF_VNET_HDR    (0x4000)
+#define UK_IFF_TUN_EXCL    (0x8000)
+#define UK_IFF_MULTI_QUEUE (0x0100)
+#define UK_IFF_ATTACH_QUEUE (0x0200)
+#define UK_IFF_DETACH_QUEUE (0x0400)
+/* read-only flag */
+#define UK_IFF_PERSIST (0x0800)
+#define UK_IFF_NOFILTER        (0x1000)
+#define UK_IFF_UP      (0x1)
+#define UK_IFF_PROMISC (0x100)
+
+/* Adding the bridge interface */
+#define UK_SIOCBRADDIF (0x89a2)
+
+int tap_open(__u32 flags);
+int tap_close(int fd);
+int tap_dev_configure(int fd, __u32 feature_flags, void *arg);
 #endif /* LINUXU_TAP_H */
diff --git a/plat/linuxu/tap_io.c b/plat/linuxu/tap_io.c
new file mode 100644
index 0000000..a394134
--- /dev/null
+++ b/plat/linuxu/tap_io.c
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
+ *
+ * Copyright (c) 2019, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <uk/print.h>
+#include <uk/arch/types.h>
+#include <linuxu/tap.h>
+
+int tap_open(__u32 flags)
+{
+       int rc = 0;
+
+       rc = sys_open(TAPDEV_PATH, flags);
+       if (rc < 0)
+               uk_pr_err("Error in opening the tap device\n");
+       return rc;
+}
+
+int tap_dev_configure(int fd, __u32 feature_flags, void *arg)
+{
+       int rc = 0;
+       struct uk_ifreq *ifreq = (struct uk_ifreq *) arg;
+
+       /* Set the tap device configuration */
+       ifreq->ifr_flags = UK_IFF_TAP | UK_IFF_NO_PI | feature_flags;
+       if ((rc = sys_ioctl(fd, UK_TUNSETIFF, ifreq)) < 0)
+               uk_pr_err("Failed to tap device configure %d\n", rc);
+
+       return rc;
+}
+
+int tap_close(int fd)
+{
+       return sys_close(fd);
+}
-- 
2.7.4


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.