[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Minios-devel] [UNIKRAFT PATCH 04/15] plat/driver: Create a tap dev during configuration
Hi Sharan,
See inline.
Roxana
On 10/7/19 12:46 PM, Sharan Santhanam wrote:
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;
Neither uk_netdev and tap driver supports multi queues feature, but it's
nice to have it for future changes.
+ }
+
+ /* 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:
This label is never reached. I think it should be deleted.
In case `dev_create` fails, the file descriptor is closed before the
function exits.
+ 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)
+
This defines are in the lwip as well. I guess because drivers should not
depend on external libraries, such as lwip. Correct me if I am wrong.
+/* 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);
+}
Again, I don't really understand why this is not included in
/drivers/tap/ folder.
_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel
|