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

Re: [UNIKRAFT PATCH v2 14/15] plat/tap: Support tap_netdev_xmit



Hi Sharan,

thanks a lot for this patch. There are a few issues in tap_write,
comments inline.

regards,
Hugo

On Tue, 2020-06-30 at 11:58 +0200, Sharan Santhanam wrote:
> Implement packet send on a tap device.
> 
> Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
> ---
>  plat/drivers/include/tap/tap.h |  1 +
>  plat/drivers/tap/tap.c         | 18 +++++++++++++++---
>  plat/linuxu/tap_io.c           | 20 ++++++++++++++++++++
>  3 files changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/plat/drivers/include/tap/tap.h
> b/plat/drivers/include/tap/tap.h
> index 797a62e..648f9ef 100644
> --- a/plat/drivers/include/tap/tap.h
> +++ b/plat/drivers/include/tap/tap.h
> @@ -48,5 +48,6 @@ 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);
>  __ssz tap_read(int fd, void *buf, size_t count);
> +__ssz tap_write(int fd, const void *buf, size_t count);
>  
>  #endif /* __PLAT_DRV_TAP_H */
> diff --git a/plat/drivers/tap/tap.c b/plat/drivers/tap/tap.c
> index 998b9e8..505f0cc 100644
> --- a/plat/drivers/tap/tap.c
> +++ b/plat/drivers/tap/tap.c
> @@ -274,14 +274,13 @@ static int tap_netdev_recv(struct uk_netdev
> *dev,
>       rc = queue->alloc_rxpkts(queue->alloc_rxpkts_argp, &_pkt,
> 1);
>       if (rc == 0) {
>               uk_pr_err(DRIVER_NAME": Failed to allocate the
> memory\n");
> -             rc = -ENOMEM;
>               _pkt = NULL;
> -             goto err_exit;
> +             rc = UK_NETDEV_STATUS_UNDERRUN |
> UK_NETDEV_STATUS_MORE;
> +             return 0;
>       }
>       uk_pr_debug(DRIVER_NAME": Receiving on interface %s(%d)
> %p(%d)\n",
>                   tdev->name, queue->fd, _pkt->data, _pkt->len);
>       rc = tap_read(queue->fd, _pkt->data, _pkt->len);
> -
>       if (rc > 0) {
>               uk_pr_debug(DRIVER_NAME": Recv pkt size: %d\n", rc);
>               /* Setting the length of the packet */
> @@ -313,10 +312,23 @@ static int tap_netdev_xmit(struct uk_netdev
> *dev,
>                          struct uk_netbuf *pkt)
>  {
>       int rc = -EINVAL;
> +     struct tap_net_dev *tdev __unused;
>  
>       UK_ASSERT(dev);
>       UK_ASSERT(queue && pkt);
>  
> +     tdev = to_tapnetdev(dev);
> +
> +     rc = tap_write(queue->fd, pkt->data, pkt->len);
> +     if (rc > 0) {
> +             uk_pr_info(DRIVER_NAME": Send packet of size %d\n",
> rc);
> +             uk_netbuf_free(pkt);
> +             rc = UK_NETDEV_STATUS_SUCCESS |
> UK_NETDEV_STATUS_MORE;
> +     } else if (rc == -EWOULDBLOCK || rc == -EAGAIN) {
> +             uk_pr_info(DRIVER_NAME": The send queue is full\n");
> +             rc = UK_NETDEV_STATUS_UNDERRUN;
> +     }
> +
>       return rc;
>  }
>  
> diff --git a/plat/linuxu/tap_io.c b/plat/linuxu/tap_io.c
> index 01c9bff..030c192 100644
> --- a/plat/linuxu/tap_io.c
> +++ b/plat/linuxu/tap_io.c
> @@ -123,6 +123,26 @@ ssize_t tap_read(int fd, void *buf, size_t
> count)
>       return rc;
>  }
>  
> +ssize_t tap_write(int fd, const void *buf, size_t count)
> +{
> +     ssize_t rc = -EINTR;
> +     int written = 0;

This is a corner case, but `written` might overflow with very large
values of `count`. `size_t written` would be safer.

> +
> +     while (count > 0) {
> +             rc = sys_write(fd, buf, count);

We should write `buf + written` here. If the first sys_write fails, we
will attempt to write the first `count - rc` bytes of the buffer (which
have already been successfully written) instead of the last `count -
rc` bytes.

> +             if (rc == -EINTR)
> +                     continue;
> +             else if (rc < 0) {
> +                     uk_pr_err("Failed(%ld) to write to the tap
> device\n",
> +                               rc);
> +                     return rc;
> +             }
> +             count -= rc;
> +             written += rc;
> +     }
> +     return written;

Missing cast here?

> +}
> +
>  int tap_close(int fd)
>  {
>       return sys_close(fd);



 


Rackspace

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