[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH v3 04/16] 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 | 145 ++++++++++++++++++++ plat/linuxu/tap_io.c | 66 +++++++++ 8 files changed, 392 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 6786e7de..c7ab037c 100644 --- a/plat/drivers/include/tap/tap.h +++ b/plat/drivers/include/tap/tap.h @@ -40,4 +40,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 f817c32a..1a78f610 100644 --- a/plat/drivers/tap/tap.c +++ b/plat/drivers/tap/tap.c @@ -31,6 +31,7 @@ * */ #include <errno.h> +#include <stdio.h> #include <string.h> #include <uk/alloc.h> #include <uk/arch/types.h> @@ -42,6 +43,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 @@ -50,18 +62,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 */ @@ -133,6 +168,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 @@ -216,6 +252,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) @@ -259,12 +299,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 cdb7cd00..4cfe6219 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 ef9323be..093fd629 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 553f0ba4..c4b88fc6 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 0dca7c5c..2c613fc2 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 00000000..b408f72b --- /dev/null +++ b/plat/linuxu/include/linuxu/tap.h @@ -0,0 +1,145 @@ +/* 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. + * + */ +#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 00000000..fb9adc24 --- /dev/null +++ b/plat/linuxu/tap_io.c @@ -0,0 +1,66 @@ +/* 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. + * + */ + +#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.20.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |