|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH v2 04/15] plat/driver: Create a tap dev during configuration
The patch creates a tap device and configures the unikraft net device.
Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
---
plat/drivers/include/tap/tap.h | 4 +
plat/drivers/tap/tap.c | 105 +++++++++++++++++++-
plat/linuxu/Makefile.uk | 1 +
plat/linuxu/include/linuxu/syscall-arm_32.h | 5 +
plat/linuxu/include/linuxu/syscall-x86_64.h | 6 ++
plat/linuxu/include/linuxu/syscall.h | 61 ++++++++++++
plat/linuxu/include/linuxu/tap.h | 146 ++++++++++++++++++++++++++++
plat/linuxu/tap_io.c | 67 +++++++++++++
8 files changed, 394 insertions(+), 1 deletion(-)
create mode 100644 plat/linuxu/include/linuxu/tap.h
create mode 100644 plat/linuxu/tap_io.c
diff --git a/plat/drivers/include/tap/tap.h b/plat/drivers/include/tap/tap.h
index 24e31b2..3aa90b6 100644
--- a/plat/drivers/include/tap/tap.h
+++ b/plat/drivers/include/tap/tap.h
@@ -42,4 +42,8 @@
*/
#define IFNAMSIZ 16
+int tap_open(__u32 flags);
+int tap_close(int fd);
+int tap_dev_configure(int fd, __u32 feature_flags, void *arg);
+
#endif /* __PLAT_DRV_TAP_H */
diff --git a/plat/drivers/tap/tap.c b/plat/drivers/tap/tap.c
index ab8e618..acf958a 100644
--- a/plat/drivers/tap/tap.c
+++ b/plat/drivers/tap/tap.c
@@ -32,6 +32,7 @@
* THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
*/
#include <errno.h>
+#include <stdio.h>
#include <string.h>
#include <uk/alloc.h>
#include <uk/arch/types.h>
@@ -43,6 +44,17 @@
#include <uk/bus.h>
#include <tap/tap.h>
+/**
+ * The tap driver is supported only on the linuxu platform. Since the driver is
+ * part of the common codebase we add compiler guard to not include the tap
+ * driver from other platforms.
+ */
+#ifdef CONFIG_PLAT_LINUXU
+#include <linuxu/tap.h>
+#else
+#error "The driver is supported on linuxu platform"
+#endif /* CONFIG_PLAT_LINUXU */
+
#define DRIVER_NAME "tap-net"
#define ETH_PKT_PAYLOAD_LEN 1500
@@ -51,18 +63,41 @@
* TODO: Find a better way of forwarding the command line argument to the
* driver. For now they are defined as macros from this driver.
*/
+
+#define to_tapnetdev(dev) \
+ __containerof(dev, struct tap_net_dev, ndev)
+
+struct uk_netdev_tx_queue {
+ /* tx queue identifier */
+ int queue_id;
+};
+
+struct uk_netdev_rx_queue {
+ /* rx queue identifier */
+ int queue_id;
+};
+
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;
+ /* List of rx queues */
+ UK_TAILQ_HEAD(tap_rxqs, struct uk_netdev_rx_queue) rxqs;
+ /* Number of txq configured */
+ __u16 txq_cnt;
+ /* List of tx queues */
+ 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;
/* Tap Device 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 */
@@ -134,6 +169,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
@@ -217,6 +253,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)
@@ -260,12 +300,75 @@ 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);
+ return -ENOTSUP;
+ } else if (conf->nb_rx_queues > 1 || conf->nb_tx_queues > 1)
+ /**
+ * TODO:
+ * We don't support multi-queues on the uknetdev. Might need to
+ * revisit this when implementing multi-queue support on
+ * uknetdev
+ */
+ feature_flag |= UK_IFF_MULTI_QUEUE;
+
+ /* Open the device and configure the tap 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 tx/rx queues list */
+ UK_TAILQ_INIT(&tdev->rxqs);
+ tdev->rxq_cnt = 0;
+ UK_TAILQ_INIT(&tdev->txqs);
+ tdev->txq_cnt = 0;
+exit:
return rc;
}
+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);
+ return rc;
+ }
+
+ 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": Configured 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 = {
.configure = tap_netdev_configure,
.rxq_configure = tap_netdev_rxq_setup,
diff --git a/plat/linuxu/Makefile.uk b/plat/linuxu/Makefile.uk
index cdb7cd0..4cfe621 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-arm_32.h
b/plat/linuxu/include/linuxu/syscall-arm_32.h
index ef9323b..093fd62 100644
--- a/plat/linuxu/include/linuxu/syscall-arm_32.h
+++ b/plat/linuxu/include/linuxu/syscall-arm_32.h
@@ -46,6 +46,7 @@
#define __SC_MUNMAP 91
#define __SC_EXIT 1
#define __SC_IOCTL 54
+#define __SC_FCNTL 55
#define __SC_RT_SIGPROCMASK 126
#define __SC_ARCH_PRCTL 172
#define __SC_RT_SIGACTION 174
@@ -57,6 +58,10 @@
#define __SC_CLOCK_GETTIME 263
#define __SC_PSELECT6 335
+#ifndef O_TMPFILE
+#define O_TMPFILE 020040000
+#endif
+
/* NOTE: from `man syscall`:
*
* ARM/EABI
diff --git a/plat/linuxu/include/linuxu/syscall-x86_64.h
b/plat/linuxu/include/linuxu/syscall-x86_64.h
index 553f0ba..c4b88fc 100644
--- a/plat/linuxu/include/linuxu/syscall-x86_64.h
+++ b/plat/linuxu/include/linuxu/syscall-x86_64.h
@@ -48,6 +48,7 @@
#define __SC_RT_SIGPROCMASK 14
#define __SC_IOCTL 16
#define __SC_EXIT 60
+#define __SC_FCNTL 72
#define __SC_ARCH_PRCTL 158
#define __SC_TIMER_CREATE 222
#define __SC_TIMER_SETTIME 223
@@ -57,6 +58,11 @@
#define __SC_CLOCK_GETTIME 228
#define __SC_PSELECT6 270
+
+#ifndef O_TMPFILE
+#define O_TMPFILE 020200000
+#endif
+
/* NOTE: from linux-4.6.3 (arch/x86/entry/entry_64.S):
*
* 64-bit SYSCALL saves rip to rcx, clears rflags.RF, then saves rflags to r11,
diff --git a/plat/linuxu/include/linuxu/syscall.h
b/plat/linuxu/include/linuxu/syscall.h
index 0dca7c5..2c613fc 100644
--- a/plat/linuxu/include/linuxu/syscall.h
+++ b/plat/linuxu/include/linuxu/syscall.h
@@ -36,6 +36,7 @@
#ifndef __SYSCALL_H__
#define __SYSCALL_H__
+#include <stdarg.h>
#include <linuxu/time.h>
#include <sys/types.h>
#include <linuxu/signal.h>
@@ -64,6 +65,66 @@ 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 */
+
+#ifndef O_CREAT
+#define O_CREAT 0100
+#endif
+
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 02000000
+#endif /* O_CLOEXEC */
+
+
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+#ifndef F_SETFD
+#define F_SETFD 2
+#endif
+
+static inline int sys_open(const char *pathname, int flags, ...)
+{
+ mode_t mode = 0;
+ int fd;
+
+ if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) {
+ va_list ap;
+
+ va_start(ap, flags);
+ mode = va_arg(ap, mode_t);
+ va_end(ap);
+ }
+
+ fd = syscall3(__SC_OPEN, (long)pathname, (long)flags, (long)mode);
+ if ((fd >= 0) && (flags & O_CLOEXEC))
+ syscall3(__SC_FCNTL, (long) fd, (long)F_SETFD,
+ (long)FD_CLOEXEC);
+
+ return fd;
+}
+
+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
new file mode 100644
index 0000000..65e6eb5
--- /dev/null
+++ b/plat/linuxu/include/linuxu/tap.h
@@ -0,0 +1,146 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
+ *
+ * Copyright (c) 2020, 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.
+ */
+#ifndef __PLAT_LINUXU_TAP_H__
+#define __PLAT_LINUXU_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
+ * Commit-id: 39ef612aa193
+ */
+#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)
+
+#endif /* __PLAT_LINUXU_TAP_H */
diff --git a/plat/linuxu/tap_io.c b/plat/linuxu/tap_io.c
new file mode 100644
index 0000000..118bee8
--- /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(%d) to configure the tap device\n", rc);
+
+ return rc;
+}
+
+int tap_close(int fd)
+{
+ return sys_close(fd);
+}
--
2.7.4
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |