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

Re: [Minios-devel] [UNIKRAFT PATCH v4 1/8] plat/drivers: Introduce the virtio-net device



Hi Sharan and Simon,

I have a few questions and comments, please see inline.

On 10/25/18 12:49 PM, Sharan Santhanam wrote:
> This patch introduces the virtio net driver initialization, the API
> functions callback to interact with the libuknet.
> 
> Signed-off-by: Sharan Santhanam <sharan.santhanam@xxxxxxxxx>
> Signed-off-by: Razvan Cojocaru <razvan.cojocaru93@xxxxxxxxx>
> Reviewed-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
> ---
>  plat/drivers/include/virtio/virtio_net.h | 258 +++++++++++++++++++
>  plat/drivers/virtio/virtio_net.c         | 417 
> +++++++++++++++++++++++++++++++
>  plat/kvm/Config.uk                       |   8 +
>  plat/kvm/Makefile.uk                     |   2 +
>  4 files changed, 685 insertions(+)
>  create mode 100644 plat/drivers/include/virtio/virtio_net.h
>  create mode 100644 plat/drivers/virtio/virtio_net.c
> 
> diff --git a/plat/drivers/include/virtio/virtio_net.h 
> b/plat/drivers/include/virtio/virtio_net.h
> new file mode 100644
> index 0000000..f33fce4
> --- /dev/null
> +++ b/plat/drivers/include/virtio/virtio_net.h
> @@ -0,0 +1,258 @@
> +/* SPDX-License-Identifier: BSD-3-Clause */
> +/* This header is BSD licensed so anyone can use the definitions to implement
> + * compatible drivers/servers.
> + *
> + * 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 IBM 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 IBM 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. */
> +/**
> + * Taken and modified from Linux kernel
> + * include/uapi/linux/virtio_net.h
> + *
> + * commit-id: faa9b39f0e9d
> + */
> +#ifndef __PLAT_DRV_VIRTIO_NET_H
> +#define __PLAT_DRV_VIRTIO_NET_H
> +#include <uk/config.h>
> +#include <uk/arch/types.h>
> +
> +#ifdef CONFIG_LIBUKNETDEV
> +#include <uk/netdev_core.h>
> +#endif /* CONFIG_LIBUKNETDEV */
> +
> +#include <virtio/virtio_ids.h>
> +#include <virtio/virtio_config.h>
> +#include <virtio/virtio_types.h>
> +
> +/* The feature bitmap for virtio net */
> +#define VIRTIO_NET_F_CSUM    0       /* Host handles pkts w/ partial csum */
> +#define VIRTIO_NET_F_GUEST_CSUM      1       /* Guest handles pkts w/ 
> partial csum */
> +#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. 
> */
> +#define VIRTIO_NET_F_MTU     3       /* Initial MTU advice */
> +#define VIRTIO_NET_F_MAC     5       /* Host has given MAC address. */
> +#define VIRTIO_NET_F_GUEST_TSO4      7       /* Guest can handle TSOv4 in. */
> +#define VIRTIO_NET_F_GUEST_TSO6      8       /* Guest can handle TSOv6 in. */
> +#define VIRTIO_NET_F_GUEST_ECN       9       /* Guest can handle TSO[6] w/ 
> ECN in. */
> +#define VIRTIO_NET_F_GUEST_UFO       10      /* Guest can handle UFO in. */
> +#define VIRTIO_NET_F_HOST_TSO4       11      /* Host can handle TSOv4 in. */
> +#define VIRTIO_NET_F_HOST_TSO6       12      /* Host can handle TSOv6 in. */
> +#define VIRTIO_NET_F_HOST_ECN        13      /* Host can handle TSO[6] w/ 
> ECN in. */
> +#define VIRTIO_NET_F_HOST_UFO        14      /* Host can handle UFO in. */
> +#define VIRTIO_NET_F_MRG_RXBUF       15      /* Host can merge receive 
> buffers. */
> +#define VIRTIO_NET_F_STATUS  16      /* virtio_net_config.status available */
> +#define VIRTIO_NET_F_CTRL_VQ 17      /* Control channel available */
> +#define VIRTIO_NET_F_CTRL_RX 18      /* Control channel RX mode support */
> +#define VIRTIO_NET_F_CTRL_VLAN       19      /* Control channel VLAN 
> filtering */
> +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20        /* Extra RX mode control 
> support */
> +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21       /* Guest can announce device on 
> the
> +                                      * network
> +                                      */
> +#define VIRTIO_NET_F_MQ      22              /* Device supports Receive Flow
> +                                      * Steering
> +                                      */
> +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23        /* Set MAC address */
> +
> +#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */
> +
> +#ifndef VIRTIO_NET_NO_LEGACY
> +#define VIRTIO_NET_F_GSO     6       /* Host handles pkts w/ any GSO type */
> +#endif /* VIRTIO_NET_NO_LEGACY */
> +
> +#define VIRTIO_NET_S_LINK_UP 1       /* Link is up */
> +#define VIRTIO_NET_S_ANNOUNCE        2       /* Announcement is needed */
> +
> +struct virtio_net_config {
> +     /* The config defining mac address (if VIRTIO_NET_F_MAC) */
> +     __u8 mac[UK_NETDEV_HWADDR_LEN];
> +     /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
> +     __u16 status;
> +     /* Maximum number of each of transmit and receive queues;
> +      * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
> +      * Legal values are between 1 and 0x8000
> +      */
> +     __u16 max_virtqueue_pairs;
> +     /* Default maximum transmit unit advice */
> +     __u16 mtu;
> +     /*
> +      * speed, in units of 1Mb. All values 0 to INT_MAX are legal.
> +      * Any other value stands for unknown.
> +      */
> +     __u32 speed;
> +     /*
> +      * 0x00 - half duplex
> +      * 0x01 - full duplex
> +      * Any other value stands for unknown.
> +      */
> +     __u8 duplex;
> +} __packed;
> +
> +/* This header comes first in the scatter-gather list.
> + * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must
> + * be the first element of the scatter-gather list.  If you don't
> + * specify GSO or CSUM features, you can simply ignore the header.
> + */
> +struct virtio_net_hdr {
> +#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1   /* Use csum_start, csum_offset */
> +#define VIRTIO_NET_HDR_F_DATA_VALID 2   /* Csum is valid */
> +     /* See VIRTIO_NET_HDR_F_* */
> +     __u8 flags;
> +#define VIRTIO_NET_HDR_GSO_NONE     0   /* Not a GSO frame */
> +#define VIRTIO_NET_HDR_GSO_TCPV4    1   /* GSO frame, IPv4 TCP (TSO) */
> +#define VIRTIO_NET_HDR_GSO_UDP      3   /* GSO frame, IPv4 UDP (UFO) */
> +#define VIRTIO_NET_HDR_GSO_TCPV6    4   /* GSO frame, IPv6 TCP */
> +#define VIRTIO_NET_HDR_GSO_ECN      0x80    /* TCP has ECN set */
> +     /* See VIRTIO_NET_HDR_GSO_* */
> +     __u8 gso_type;
> +     __virtio_le16 hdr_len;  /* Ethernet + IP + tcp/udp hdrs */
> +     __virtio_le16 gso_size; /* Bytes to append to hdr_len per frame */
> +     __virtio_le16 csum_start; /* Position to start checksumming from */
> +     __virtio_le16 csum_offset; /* Offset after that to place checksum */
> +};
> +
> +/* This is the version of the header to use when the MRG_RXBUF
> + * feature has been negotiated.
> + */
> +struct virtio_net_hdr_mrg_rxbuf {
> +     struct virtio_net_hdr hdr;
> +     __virtio_le16 num_buffers;      /* Number of merged rx buffers */
> +};
> +
> +/*
> + * Control virtqueue data structures
> + *
> + * The control virtqueue expects a header in the first sg entry
> + * and an ack/status response in the last entry.  Data for the
> + * command goes in between.
> + */
> +struct virtio_net_ctrl_hdr {
> +     __u8 class;
> +     __u8 cmd;
> +} __packed;
> +
> +typedef __u8 virtio_net_ctrl_ack;
> +
> +#define VIRTIO_NET_OK     0
> +#define VIRTIO_NET_ERR    1
> +
> +/*
> + * Control the RX mode, ie. promisucous, allmulti, etc...
> + * All commands require an "out" sg entry containing a 1 byte
> + * state value, zero = disable, non-zero = enable.  Commands
> + * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.
> + * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.
> + */
> +#define VIRTIO_NET_CTRL_RX    0
> + #define VIRTIO_NET_CTRL_RX_PROMISC      0
> + #define VIRTIO_NET_CTRL_RX_ALLMULTI     1
> + #define VIRTIO_NET_CTRL_RX_ALLUNI       2
> + #define VIRTIO_NET_CTRL_RX_NOMULTI      3
> + #define VIRTIO_NET_CTRL_RX_NOUNI        4
> + #define VIRTIO_NET_CTRL_RX_NOBCAST      5
> +
> +/*
> + * Control the MAC
> + *
> + * The MAC filter table is managed by the hypervisor, the guest should
> + * assume the size is infinite.  Filtering should be considered
> + * non-perfect, ie. based on hypervisor resources, the guest may
> + * received packets from sources not specified in the filter list.
> + *
> + * In addition to the class/cmd header, the TABLE_SET command requires
> + * two out scatterlists.  Each contains a 4 byte count of entries followed
> + * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The
> + * first sg list contains unicast addresses, the second is for multicast.
> + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
> + * is available.
> + *
> + * The ADDR_SET command requests one out scatterlist, it contains a
> + * 6 bytes MAC address. This functionality is present if the
> + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
> + */
> +struct virtio_net_ctrl_mac {
> +     __virtio_le32 entries;
> +     __u8 macs[][UK_NETDEV_HWADDR_LEN];
> +} __packed;
> +
> +#define VIRTIO_NET_CTRL_MAC    1
> + #define VIRTIO_NET_CTRL_MAC_TABLE_SET        0
> + #define VIRTIO_NET_CTRL_MAC_ADDR_SET         1
> +
> +/*
> + * Control VLAN filtering
> + *
> + * The VLAN filter table is controlled via a simple ADD/DEL interface.
> + * VLAN IDs not added may be filterd by the hypervisor.  Del is the
> + * opposite of add.  Both commands expect an out entry containing a 2
> + * byte VLAN ID.  VLAN filterting is available with the
> + * VIRTIO_NET_F_CTRL_VLAN feature bit.
> + */
> +#define VIRTIO_NET_CTRL_VLAN       2
> + #define VIRTIO_NET_CTRL_VLAN_ADD             0
> + #define VIRTIO_NET_CTRL_VLAN_DEL             1
> +
> +/*
> + * Control link announce acknowledgment
> + *
> + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
> + * driver has recevied the notification; device would clear the
> + * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives
> + * this command.
> + */
> +#define VIRTIO_NET_CTRL_ANNOUNCE       3
> + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
> +
> +/*
> + * Control Receive Flow Steering
> + *
> + * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
> + * enables Receive Flow Steering, specifying the number of the transmit and
> + * receive queues that will be used. After the command is consumed and acked 
> by
> + * the device, the device will not steer new packets on receive virtqueues
> + * other than specified nor read from transmit virtqueues other than 
> specified.
> + * Accordingly, driver should not transmit new packets  on virtqueues other 
> than
> + * specified.
> + */
> +struct virtio_net_ctrl_mq {
> +     __virtio_le16 virtqueue_pairs;
> +};
> +
> +#define VIRTIO_NET_CTRL_MQ   4
> + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET        0
> + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
> + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
> +
> +/*
> + * Control network offloads
> + *
> + * Reconfigures the network offloads that Guest can handle.
> + *
> + * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit.
> + *
> + * Command data format matches the feature bit mask exactly.
> + *
> + * See VIRTIO_NET_F_GUEST_* for the list of offloads
> + * that can be enabled/disabled.
> + */
> +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS   5
> +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET        0
> +
> +#endif /* __PLAT_CMN_VIRTIO_NET_H */
> diff --git a/plat/drivers/virtio/virtio_net.c 
> b/plat/drivers/virtio/virtio_net.c
> new file mode 100644
> index 0000000..41ba860
> --- /dev/null
> +++ b/plat/drivers/virtio/virtio_net.c
> @@ -0,0 +1,417 @@
> +/*
> + * Authors: Dan Williams
> + *          Martin Lucina
> + *          Ricardo Koller
> + *          Razvan Cojocaru <razvan.cojocaru93@xxxxxxxxx>
> + *          Sharan Santhanam
> + *
> + * Copyright (c) 2015-2017 IBM
> + * Copyright (c) 2016-2017 Docker, Inc.
> + * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation
> + *
> + * Permission to use, copy, modify, and/or distribute this software
> + * for any purpose with or without fee is hereby granted, provided
> + * that the above copyright notice and this permission notice appear
> + * in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
> + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
> + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
> + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
> + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
> + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
> + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <uk/print.h>
> +#include <uk/assert.h>
> +#include <uk/essentials.h>
> +#include <uk/sglist.h>
> +#include <uk/arch/types.h>
> +#include <uk/arch/limits.h>
> +#include <uk/netbuf.h>
> +#include <uk/netdev.h>
> +#include <uk/netdev_core.h>
> +#include <uk/netdev_driver.h>
> +#include <virtio/virtio_bus.h>
> +#include <virtio/virtqueue.h>
> +#include <virtio/virtio_net.h>
> +
> +/**
> + * VIRTIO_PKT_BUFFER_LEN = VIRTIO_NET_HDR + ETH_HDR + ETH_PKT_PAYLOAD_LEN
> + * VIRTIO_NET_HDR: 10 bytes in length in legacy mode + 2 byte of padded data.
> + *              12 bytes in length in modern mode.
> + */
> +#define VIRTIO_HDR_LEN          12
> +#define ETH_HDR_LEN             14
> +#define ETH_PKT_PAYLOAD_LEN   1500
> +#define VIRTIO_PKT_BUFFER_LEN ((ETH_PKT_PAYLOAD_LEN) \
> +                            + (ETH_HDR_LEN)          \
> +                            + (VIRTIO_HDR_LEN))
> +
> +#define DRIVER_NAME           "virtio-net"
> +
> +
> +#define  VTNET_RX_HEADER_PAD (4)
> +#define  VTNET_INTR_EN   (1 << 0)
> +#define  VTNET_INTR_EN_MASK   (1)
> +#define  VTNET_INTR_USR_EN   (1 << 1)
> +#define  VTNET_INTR_USR_EN_MASK   (2)
> +

Shouldn't these VTNET_INTR_* definitions be in the netdev API?
Interrupts enabling is logic specific to all network device. Even more,
I would say we might even define those as specific to all devices.

> +/**
> + * Define max possible fragments for the network packets.
> + */
> +#define NET_MAX_FRAGMENTS    ((__U16_MAX >> __PAGE_SHIFT) + 2)
> +
> +#define to_virtionetdev(ndev) \
> +     __containerof(ndev, struct virtio_net_device, netdev)
> +
> +#define VIRTIO_NET_DRV_FEATURES(features)           \
> +     (VIRTIO_FEATURES_UPDATE(features, VIRTIO_NET_F_MAC))
> +
> +typedef enum {
> +     VNET_RX,
> +     VNET_TX,
> +} virtq_type_t;
> +
> +/**
> + * @internal structure to represent the transmit queue.
> + */
> +struct uk_netdev_tx_queue {
> +     /* The virtqueue reference */
> +     struct virtqueue *vq;
> +     /* The hw queue identifier */
> +     uint16_t hwvq_id;
> +     /* The user queue identifier */
> +     uint16_t lqueue_id;
> +     /* The nr. of descriptor limit */
> +     uint16_t max_nb_desc;
> +     /* The nr. of descriptor user configured */
> +     uint16_t nb_desc;
> +     /* The flag to interrupt on the transmit queue */
> +     uint8_t intr_enabled;
> +     /* Reference to the uk_netdev */
> +     struct uk_netdev *ndev;
> +     /* The scatter list and its associated fragements */
> +     struct uk_sglist sg;
> +     struct uk_sglist_seg sgsegs[NET_MAX_FRAGMENTS];
> +};
> +
> +/**
> + * @internal structure to represent the receive queue.
> + */
> +struct uk_netdev_rx_queue {
> +     /* The virtqueue reference */
> +     struct virtqueue *vq;
> +     /* The virtqueue hw identifier */
> +     uint16_t hwvq_id;
> +     /* The libuknet queue identifier */
> +     uint16_t lqueue_id;
> +     /* The nr. of descriptor limit */
> +     uint16_t max_nb_desc;
> +     /* The nr. of descriptor user configured */
> +     uint16_t nb_desc;
> +     /* The flag to interrupt on the transmit queue */
> +     uint8_t intr_enabled;
> +     /* Reference to the uk_netdev */
> +     struct uk_netdev *ndev;
> +     /* The scatter list and its associated fragements */
> +     struct uk_sglist sg;
> +     struct uk_sglist_seg sgsegs[NET_MAX_FRAGMENTS];
> +};
> +

Is it expected for uk_netdev_tx_queue and uk_netdev_rx_queue structures
to be identical?

> +struct virtio_net_device {
> +     /* Virtio Device */
> +     struct virtio_dev *vdev;
> +     /* List of all the virtqueue in the pci device */
> +     struct virtqueue *vq;
> +     struct uk_netdev netdev;
> +     /* Count of the number of the virtqueues */
> +     __u16 max_vqueue_pairs;
> +     /* List of the Rx/Tx queue */
> +     __u16    rx_vqueue_cnt;
> +     struct   uk_netdev_rx_queue *rxqs;
> +     __u16    tx_vqueue_cnt;
> +     struct   uk_netdev_tx_queue *txqs;
> +     /* The netdevice identifier */
> +     __u16 uid;
> +     /* The max mtu */
> +     __u16 max_mtu;
> +     /* The mtu */
> +     __u16 mtu;
> +     /* The hw address of the netdevice */
> +     struct uk_hwaddr hw_addr;
> +     /*  Netdev state */
> +     __u8 state;
> +     /* RX promiscuous mode. */
> +     __u8 promisc : 1;
> +};

Shouldn't queues, mtu, hw_addr, promisc be fields of the uk_netdev
structure?

> +
> +/**
> + * Static function declarations.
> + */
> +static int virtio_net_drv_init(struct uk_alloc *drv_allocator);
> +static int virtio_net_add_dev(struct virtio_dev *vdev);
> +static void virtio_net_info_get(struct uk_netdev *dev,
> +                             struct uk_netdev_info *dev_info);
> +static inline void virtio_netdev_feature_set(struct virtio_net_device 
> *vndev);
> +static int virtio_netdev_configure(struct uk_netdev *n,
> +                                const struct uk_netdev_conf *conf);
> +static struct uk_netdev_tx_queue *virtio_netdev_tx_queue_setup(
> +                                     struct uk_netdev *n, uint16_t queue_id,
> +                                     uint16_t nb_desc,
> +                                     struct uk_netdev_txqueue_conf *conf);
> +static struct uk_netdev_rx_queue *virtio_netdev_rx_queue_setup(
> +                                     struct uk_netdev *n,
> +                                     uint16_t queue_id, uint16_t nb_desc,
> +                                     struct uk_netdev_rxqueue_conf *conf);
> +static int virtio_net_rx_intr_disable(struct uk_netdev *n,
> +                                   struct uk_netdev_rx_queue *queue);
> +static int virtio_net_rx_intr_enable(struct uk_netdev *n,
> +                                  struct uk_netdev_rx_queue *queue);
> +static int virtio_netdev_xmit(struct uk_netdev *dev,
> +                           struct uk_netdev_tx_queue *queue,
> +                           struct uk_netbuf *pkt);
> +static int virtio_netdev_recv(struct uk_netdev *dev,
> +                           struct uk_netdev_rx_queue *queue,
> +                           struct uk_netbuf **pkt,
> +                           struct uk_netbuf *fillup[],
> +                           uint16_t *fillup_count);
> +static const struct uk_hwaddr *virtio_net_mac_get(struct uk_netdev *n);
> +static __u16 virtio_net_mtu_get(struct uk_netdev *n);
> +static unsigned virtio_net_promisc_get(struct uk_netdev *n);
> +static int virtio_netdev_rxq_info_get(struct uk_netdev *dev, __u16 queue_id,
> +                                   struct uk_netdev_queue_info *qinfo);
> +static int virtio_netdev_txq_info_get(struct uk_netdev *dev, __u16 queue_id,
> +                                   struct uk_netdev_queue_info *qinfo);
> +
> +/**
> + * Static global constants
> + */
> +static const char *drv_name = DRIVER_NAME;
> +static struct uk_alloc *a;
> +
> +/**
> + * The Driver method implementation.
> + */
> +static int virtio_netdev_xmit(struct uk_netdev *dev,
> +                           struct uk_netdev_tx_queue *queue,
> +                           struct uk_netbuf *pkt)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(dev);
> +     UK_ASSERT(pkt && queue);
> +
> +     return rc;
> +}
> +
> +static int virtio_netdev_recv(struct uk_netdev *dev __unused,
> +                           struct uk_netdev_rx_queue *queue,
> +                           struct uk_netbuf **pkt __unused,
> +                           struct uk_netbuf *fillup[],
> +                           uint16_t *fillup_count)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(dev && queue);
> +     UK_ASSERT(!fillup || (fillup && *fillup_count > 0));
> +
> +     return rc;
> +}
> +
> +static struct uk_netdev_rx_queue *virtio_netdev_rx_queue_setup(
> +                             struct uk_netdev *n, uint16_t queue_id __unused,
> +                             uint16_t nb_desc __unused,
> +                             struct uk_netdev_rxqueue_conf *conf __unused)
> +{
> +     struct uk_netdev_rx_queue *rxq = NULL;
> +
> +     UK_ASSERT(n);
> +
> +     return rxq;
> +}
> +
> +static struct uk_netdev_tx_queue *virtio_netdev_tx_queue_setup(
> +                             struct uk_netdev *n, uint16_t queue_id __unused,
> +                             uint16_t nb_desc __unused,
> +                             struct uk_netdev_txqueue_conf *conf __unused)
> +{
> +     struct uk_netdev_tx_queue *txq = NULL;
> +
> +     UK_ASSERT(n);
> +     return txq;
> +}
> +
> +static int virtio_netdev_rxq_info_get(struct uk_netdev *dev,
> +                                   __u16 queue_id __unused,
> +                                   struct uk_netdev_queue_info *qinfo)
> +{
> +     UK_ASSERT(dev);
> +     UK_ASSERT(qinfo);
> +     return 0;
> +}
> +
> +static int virtio_netdev_txq_info_get(struct uk_netdev *dev,
> +                                   __u16 queue_id __unused,
> +                                   struct uk_netdev_queue_info *qinfo)
> +{
> +     UK_ASSERT(dev);
> +     UK_ASSERT(qinfo);
> +     return 0;
> +}
> +
> +static unsigned virtio_net_promisc_get(struct uk_netdev *n)
> +{
> +     UK_ASSERT(n);
> +     return 0;
> +}
> +
> +static const struct uk_hwaddr *virtio_net_mac_get(struct uk_netdev *n)
> +{
> +     UK_ASSERT(n);
> +     return NULL;
> +}
> +
> +static __u16 virtio_net_mtu_get(struct uk_netdev *n)
> +{
> +     UK_ASSERT(n);
> +     return 0;
> +}
> +
> +static int virtio_netdev_configure(struct uk_netdev *n,
> +                                const struct uk_netdev_conf *conf __unused)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(n);
> +
> +     return rc;
> +}
> +
> +static int virtio_net_rx_intr_enable(struct uk_netdev *n,
> +                                  struct uk_netdev_rx_queue *queue __unused)
> +{
> +     int rc = 0;
> +
> +     UK_ASSERT(n);
> +
> +     return rc;
> +}
> +
> +static int virtio_net_rx_intr_disable(struct uk_netdev *n,
> +                                   struct uk_netdev_rx_queue *queue __unused)
> +{
> +     UK_ASSERT(n);
> +     return 0;
> +}
> +
> +static void virtio_net_info_get(struct uk_netdev *dev,
> +                             struct uk_netdev_info *dev_info)
> +{
> +     struct virtio_net_device *vndev;
> +
> +     UK_ASSERT(dev && dev_info);
> +     vndev = to_virtionetdev(dev);
> +
> +     dev_info->max_rx_queues = vndev->max_vqueue_pairs;
> +     dev_info->max_tx_queues = vndev->max_vqueue_pairs;
> +}
> +
> +static int virtio_net_start(struct uk_netdev *n)
> +{
> +     UK_ASSERT(n != NULL);
> +     return 0;
> +}
> +
> +static inline void virtio_netdev_feature_set(struct virtio_net_device *vndev)
> +{
> +     vndev->vdev->features = 0;
> +     /* Setting the feature the driver support */
> +     VIRTIO_NET_DRV_FEATURES(vndev->vdev->features);
> +     /**
> +      * TODO:
> +      * Adding multiqueue support for the virtio net driver.
> +      */
> +     vndev->max_vqueue_pairs = 1;
> +}
> +
> +static const struct uk_netdev_ops virtio_netdev_ops = {
> +     .configure = virtio_netdev_configure,
> +     .rxq_configure = virtio_netdev_rx_queue_setup,
> +     .txq_configure = virtio_netdev_tx_queue_setup,
> +     .start = virtio_net_start,
> +     .rxq_intr_enable = virtio_net_rx_intr_enable,
> +     .rxq_intr_disable = virtio_net_rx_intr_disable,
> +     .info_get = virtio_net_info_get,
> +     .promiscuous_get = virtio_net_promisc_get,
> +     .hwaddr_get = virtio_net_mac_get,
> +     .mtu_get = virtio_net_mtu_get,
> +     .txq_info_get = virtio_netdev_txq_info_get,
> +     .rxq_info_get = virtio_netdev_rxq_info_get,
> +};
> +
> +static int virtio_net_add_dev(struct virtio_dev *vdev)
> +{
> +     struct virtio_net_device *vndev;
> +     int rc = 0;
> +
> +     UK_ASSERT(vdev != NULL);
> +
> +     vndev = uk_malloc(a, sizeof(*vndev));
> +     if (!vndev) {
> +             rc = -ENOMEM;
> +             goto err_out;
> +     }
> +     vndev->vdev = vdev;
> +     /* register netdev */
> +     vndev->netdev.rx_one = virtio_netdev_recv;
> +     vndev->netdev.tx_one = virtio_netdev_xmit;
> +     vndev->netdev.ops = &virtio_netdev_ops;
> +
> +     rc = uk_netdev_drv_register(&vndev->netdev, a, drv_name);
> +     if (rc < 0) {
> +             uk_pr_err("Failed to register virtio-net device with 
> libuknet\n");
> +             goto err_netdev_data;
> +     }
> +     vndev->uid = rc;
> +     rc = 0;
> +     vndev->max_mtu = ETH_PKT_PAYLOAD_LEN;
> +     vndev->mtu = vndev->max_mtu;
> +     vndev->promisc = 0;
> +     virtio_netdev_feature_set(vndev);
> +     uk_pr_info("virtio-net device registered with libuknet\n");
> +
> +exit:
> +     return rc;
> +err_netdev_data:
> +     uk_free(a, vndev);
> +err_out:
> +     goto exit;
> +}
> +
> +static int virtio_net_drv_init(struct uk_alloc *drv_allocator)
> +{
> +     /* driver initialization */
> +     if (!drv_allocator)
> +             return -EINVAL;
> +
> +     a = drv_allocator;
> +     return 0;
> +}
> +
> +static const struct virtio_dev_id vnet_dev_id[] = {
> +     {VIRTIO_ID_NET},
> +     {VIRTIO_ID_INVALID} /* List Terminator */
> +};
> +
> +static struct virtio_driver vnet_drv = {
> +     .dev_ids = vnet_dev_id,
> +     .init    = virtio_net_drv_init,
> +     .add_dev = virtio_net_add_dev
> +};
> +VIRTIO_BUS_REGISTER_DRIVER(&vnet_drv);
> diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk
> index 13e5575..fb3677a 100644
> --- a/plat/kvm/Config.uk
> +++ b/plat/kvm/Config.uk
> @@ -71,5 +71,13 @@ config VIRTIO_PCI
>         help
>                 Support virtio devices on PCI bus
>  
> +config VIRTIO_NET
> +       bool "Virtio Net device"
> +       default n
> +       depends on LIBUKNETDEV
> +       select VIRTIO
> +       select LIBUKSGLIST
> +       help
> +              Virtual network driver.
>  endmenu
>  endif
> diff --git a/plat/kvm/Makefile.uk b/plat/kvm/Makefile.uk
> index ccc8319..1f9c5dc 100644
> --- a/plat/kvm/Makefile.uk
> +++ b/plat/kvm/Makefile.uk
> @@ -96,3 +96,5 @@ LIBKVMVIRTIO_SRCS-$(CONFIG_VIRTIO_BUS) +=\
>                                                       
> $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_ring.c
>  LIBKVMVIRTIO_SRCS-$(CONFIG_VIRTIO_PCI) +=\
>                                                       
> $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_pci.c
> +LIBKVMVIRTIO_SRCS-$(CONFIG_VIRTIO_NET) +=\
> +                                                     
> $(UK_PLAT_DRIVERS_BASE)/virtio/virtio_net.c
> 

_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

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