|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [UNIKRAFT PATCH v2 05/15] plat/tap: Get/Set hw_addr
Hi Sharan,
Looks good to me so far. I only have a comment/question concerning
tap_mac_generate (inline).
regards,
Hugo
On Tue, 2020-06-30 at 11:58 +0200, Sharan Santhanam wrote:
> The patch implements support for generating a default hw_addr. The
> patch also implements get and set netdev api.
>
> Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
> ---
> plat/drivers/include/tap/tap.h | 2 +
> plat/drivers/tap/tap.c | 97
> ++++++++++++++++++++++++++++-
> plat/linuxu/include/linuxu/syscall-arm_32.h | 1 +
> plat/linuxu/include/linuxu/syscall-x86_64.h | 1 +
> plat/linuxu/include/linuxu/syscall.h | 25 ++++++++
> plat/linuxu/include/linuxu/tap.h | 7 +++
> plat/linuxu/tap_io.c | 31 +++++++++
> 7 files changed, 161 insertions(+), 3 deletions(-)
>
> diff --git a/plat/drivers/include/tap/tap.h
> b/plat/drivers/include/tap/tap.h
> index 3aa90b6..686b666 100644
> --- a/plat/drivers/include/tap/tap.h
> +++ b/plat/drivers/include/tap/tap.h
> @@ -45,5 +45,7 @@
> int tap_open(__u32 flags);
> int tap_close(int fd);
> int tap_dev_configure(int fd, __u32 feature_flags, void *arg);
> +int tap_netif_configure(int fd, __u32 request, void *arg);
> +int tap_netif_create(void);
>
> #endif /* __PLAT_DRV_TAP_H */
> diff --git a/plat/drivers/tap/tap.c b/plat/drivers/tap/tap.c
> index acf958a..d60ca46 100644
> --- a/plat/drivers/tap/tap.c
> +++ b/plat/drivers/tap/tap.c
> @@ -92,12 +92,16 @@ struct tap_net_dev {
> 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;
> + /* Mac address of the device */
> + struct uk_hwaddr hw_addr;
> /* Tap Device identifier */
> __u16 tid;
> /* UK Netdevice identifier */
> __u16 id;
> /* File Descriptor for the tap device */
> int tap_fd;
> + /* Control socket descriptor */
> + int ctrl_sock;
> /* Name of the character device */
> char name[IFNAMSIZ];
> /* MTU of the device */
> @@ -170,6 +174,7 @@ static int tap_netdev_rxq_info_get(struct
> uk_netdev *dev, __u16 queue_id,
> 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);
> +static int tap_mac_generate(__u8 *addr, int len, __u8 dev_id);
>
> /**
> * Local function definitions
> @@ -284,16 +289,78 @@ static int tap_netdev_mtu_set(struct uk_netdev
> *n, __u16 mtu __unused)
>
> static const struct uk_hwaddr *tap_netdev_mac_get(struct uk_netdev
> *n)
> {
> + struct tap_net_dev *tdev;
> +
> UK_ASSERT(n);
> - return NULL;
> + tdev = to_tapnetdev(n);
> + return &tdev->hw_addr;
> }
>
> static int tap_netdev_mac_set(struct uk_netdev *n,
> const struct uk_hwaddr *hwaddr)
> {
> - int rc = -EINVAL;
> + int rc = 0;
> + struct tap_net_dev *tdev;
> + struct uk_ifreq ifrq = {0};
>
> UK_ASSERT(n && hwaddr);
> + tdev = to_tapnetdev(n);
> +
> + snprintf(ifrq.ifr_name, sizeof(ifrq.ifr_name), "%s", tdev-
> >name);
> + uk_pr_info("Setting mac address on tap device %s\n", tdev-
> >name);
> +
> +#ifdef CONFIG_TAP_DEV_DEBUG
> + int i;
> +
> + for (i = 0; i < UK_NETDEV_HWADDR_LEN; i++) {
> + uk_pr_debug("hw_address: %d - %d\n", i,
> + hwaddr->addr_bytes[i] & 0xFF);
> + }
> +#endif /* CONFIG_TAP_DEV_DEBUG */
> +
> + ifrq.ifr_hwaddr.sa_family = AF_LOCAL;
> + memcpy(&ifrq.ifr_hwaddr.sa_data[0], &hwaddr->addr_bytes[0],
> + UK_NETDEV_HWADDR_LEN);
> + rc = tap_netif_configure(tdev->ctrl_sock, UK_SIOCSIFHWADDR,
> &ifrq);
> + if (rc < 0) {
> + uk_pr_err(DRIVER_NAME": Failed(%d) to set the
> hardware address\n",
> + rc);
> + goto exit;
> + }
> + memcpy(&tdev->hw_addr, hwaddr, sizeof(*hwaddr));
> +
> +exit:
> + return rc;
> +}
> +
> +static int tap_mac_generate(__u8 *addr, int len, __u8 dev_id)
> +{
> + const char fmt[] = {0x2, 0x0, 0x0, 0x0, 0x0, 0x0};
> +
> + UK_ASSERT(addr && len > 0);
> +
> + if (len < UK_NETDEV_HWADDR_LEN) {
> + uk_pr_err("Failed to generate the mac address\n");
> + return -ENOSPC;
> + }
What is the point of this `len` argument?
What happens if `len` is larger than UK_NETDEV_HWADDR_LEN?
To me this might result in OOB read if the caller assumes that `addr`
contains `len` > UK_NETDEV_HWADDR_LEN bytes of address data upon
returning of this function.
> + memcpy(addr, fmt, UK_NETDEV_HWADDR_LEN - 1);
> + *(addr + UK_NETDEV_HWADDR_LEN - 1) = (__u8) (dev_id + 1);
> + return 0;
> +}
> +
> +static inline int tapdev_ctrlsock_create(struct tap_net_dev *tdev)
> +{
> + int rc = 0;
> +
> + rc = tap_netif_create();
> + if (rc < 0) {
> + uk_pr_err(DRIVER_NAME":Failed(%d) to create a
> control socket\n",
> + rc);
> + goto exit;
> + }
> + tdev->ctrl_sock = rc;
> + rc = 0;
> +exit:
> return rc;
> }
>
> @@ -328,13 +395,37 @@ static int tap_netdev_configure(struct
> uk_netdev *n,
> goto exit;
> }
>
> - /* Initialize tx/rx queues list */
> + /* Create a control socket for the network interface */
> + rc = tapdev_ctrlsock_create(tdev);
> + if (rc != 0) {
> + uk_pr_err(DRIVER_NAME": Failed to create a control
> socket\n");
> + goto close_tap_dev;
> + }
> +
> + /* Generate MAC address */
> + tap_mac_generate(&tdev->hw_addr.addr_bytes[0],
> UK_NETDEV_HWADDR_LEN,
> + tdev->id);
> +
> + /* MAC Address configuration */
> + rc = tap_netdev_mac_set(n, &tdev->hw_addr);
> + if (rc < 0) {
> + uk_pr_err(DRIVER_NAME": Failed to set the mac
> address\n");
> + goto close_ctrl_sock;
> + }
> +
> + /* 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_ctrl_sock:
> + tap_close(tdev->ctrl_sock);
> +close_tap_dev:
> + tap_close(tdev->tap_fd);
> + goto exit;
> }
>
> static int tap_device_create(struct tap_net_dev *tdev, __u32
> feature_flags)
> diff --git a/plat/linuxu/include/linuxu/syscall-arm_32.h
> b/plat/linuxu/include/linuxu/syscall-arm_32.h
> index 093fd62..4b7218b 100644
> --- a/plat/linuxu/include/linuxu/syscall-arm_32.h
> +++ b/plat/linuxu/include/linuxu/syscall-arm_32.h
> @@ -56,6 +56,7 @@
> #define __SC_TIMER_GETOVERRUN 260
> #define __SC_TIMER_DELETE 261
> #define __SC_CLOCK_GETTIME 263
> +#define __SC_SOCKET 281
> #define __SC_PSELECT6 335
>
> #ifndef O_TMPFILE
> diff --git a/plat/linuxu/include/linuxu/syscall-x86_64.h
> b/plat/linuxu/include/linuxu/syscall-x86_64.h
> index c4b88fc..8714c92 100644
> --- a/plat/linuxu/include/linuxu/syscall-x86_64.h
> +++ b/plat/linuxu/include/linuxu/syscall-x86_64.h
> @@ -47,6 +47,7 @@
> #define __SC_RT_SIGACTION 13
> #define __SC_RT_SIGPROCMASK 14
> #define __SC_IOCTL 16
> +#define __SC_SOCKET 41
> #define __SC_EXIT 60
> #define __SC_FCNTL 72
> #define __SC_ARCH_PRCTL 158
> diff --git a/plat/linuxu/include/linuxu/syscall.h
> b/plat/linuxu/include/linuxu/syscall.h
> index 2c613fc..ad6f038 100644
> --- a/plat/linuxu/include/linuxu/syscall.h
> +++ b/plat/linuxu/include/linuxu/syscall.h
> @@ -125,6 +125,31 @@ static inline int sys_close(int fd)
> (long) fd);
> }
>
> +#ifndef SOCK_STREAM
> +#define SOCK_STREAM 1
> +#endif /* SOCK_STREAM */
> +#ifndef SOCK_DGRAM
> +#define SOCK_DGRAM 2
> +#endif /* SOCK_DGRAM */
> +
> +#ifndef SOCK_RAW
> +#define SOCK_RAW 3
> +#endif /* SOCK_RAW */
> +
> +#ifndef AF_LOCAL
> +#define AF_LOCAL 1
> +#endif /* AF_LOCAL */
> +#ifndef AF_INET
> +#define AF_INET 2
> +#endif /* AF_INET */
> +static inline int sys_socket(int domain, int type, int protocol)
> +{
> + return (ssize_t) syscall3(__SC_SOCKET,
> + (long) domain,
> + (long) type,
> + (long) protocol);
> +}
> +
> 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 65e6eb5..0f3a644 100644
> --- a/plat/linuxu/include/linuxu/tap.h
> +++ b/plat/linuxu/include/linuxu/tap.h
> @@ -58,6 +58,13 @@ struct uk_in_addr {
> uk_in_addr_t s_addr;
> };
>
> +struct uk_sockaddr_in {
> + uk_sa_family_t sin_family;
> + uk_in_port_t sin_port;
> + struct uk_in_addr sin_addr;
> + __u8 sin_zero[8];
> +};
> +
> struct uk_sockaddr {
> uk_sa_family_t sa_family;
> char sa_data[14];
> diff --git a/plat/linuxu/tap_io.c b/plat/linuxu/tap_io.c
> index 118bee8..888ef83 100644
> --- a/plat/linuxu/tap_io.c
> +++ b/plat/linuxu/tap_io.c
> @@ -61,6 +61,37 @@ int tap_dev_configure(int fd, __u32 feature_flags,
> void *arg)
> return rc;
> }
>
> +int tap_netif_configure(int fd, __u32 request, void *arg)
> +{
> + int rc;
> + struct uk_ifreq *usr_ifr = (struct uk_ifreq *) arg;
> +
> + switch (request) {
> + case UK_SIOCGIFHWADDR:
> + case UK_SIOCSIFHWADDR:
> + break;
> + default:
> + rc = -EINVAL;
> + uk_pr_err("Invalid ioctl request\n");
> + goto exit_error;
> + }
> +
> + if ((rc = sys_ioctl(fd, request, usr_ifr)) < 0) {
> + uk_pr_err("Failed to set device control %d\n", rc);
> + goto exit_error;
> + }
> +
> + return 0;
> +
> +exit_error:
> + return rc;
> +}
> +
> +int tap_netif_create(void)
> +{
> + return sys_socket(AF_INET, SOCK_DGRAM, 0);
> +}
> +
> int tap_close(int fd)
> {
> return sys_close(fd);
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |