From: Brian King <brking-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
To: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
Cc: Stephen Rothwell <sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org>,
Xen Mailing List
<xen-devel-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org>,
"jmk-zzFmDc4TPjtKvsKVC3L/VUEOCMrvLtNR@public.gmane.org"
<jmk-zzFmDc4TPjtKvsKVC3L/VUEOCMrvLtNR@public.gmane.org>,
Herbert Xu
<herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org>,
kvm-devel
<kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>,
virtualization
<virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>,
Christian Borntraeger
<cborntra-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>,
Latchesar Ionkov <lionkov-YOWKrPYUwWM@public.gmane.org>,
Suzanne McIntosh
<skranjac-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>,
Martin Schwidefsky
<schwidefsky-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org>
Subject: Re: [PATCH RFC 2/3] Virtio draft III: example net driver
Date: Mon, 25 Jun 2007 10:26:37 -0500 [thread overview]
Message-ID: <467FDEAD.4030204@linux.vnet.ibm.com> (raw)
In-Reply-To: <1181999825.6237.260.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
I've started to look at these patches to figure out how easily I
could convert the ibmveth driver to use this new infrastructure
and have ran into a few issues. So far the two biggest issues I've
encountered are:
1. The add_inbuf interface passes an sg list. This causes problems for
ibmveth since its rx buffers cannot be scatterlists.
2. The user of this API does not have access to the sk_buf. This causes
issues for ibmveth since it needs to reserve the first 8 bytes of the
rx buffer for use by the firmware. It currently uses skb_reserve to do this.
Would it be simpler to just pass an sk_buf rather than the scatterlist
on these interfaces for virtio_net users?
-Brian
Rusty Russell wrote:
> Net driver using virtio
>
> TODO:
> 1) GSO.
> 2) Checksum options.
> 3) Big packets.
>
> Signed-off-by: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
> ---
> drivers/net/Makefile | 2
> drivers/net/virtio_net.c | 277 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/virtio_net.h | 12 +
> 3 files changed, 290 insertions(+), 1 deletion(-)
>
> ===================================================================
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -37,7 +37,7 @@ obj-$(CONFIG_CASSINI) += cassini.o
>
> obj-$(CONFIG_MACE) += mace.o
> obj-$(CONFIG_BMAC) += bmac.o
> -
> +obj-y += virtio_net.o
> obj-$(CONFIG_DGRS) += dgrs.o
> obj-$(CONFIG_VORTEX) += 3c59x.o
> obj-$(CONFIG_TYPHOON) += typhoon.o
> ===================================================================
> --- /dev/null
> +++ b/drivers/net/virtio_net.c
> @@ -0,0 +1,277 @@
> +/* A simple network driver using virtio.
> + *
> + * Copyright 2007 Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org> IBM Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +//#define DEBUG
> +#include <linux/netdevice.h>
> +#include <linux/etherdevice.h>
> +#include <linux/module.h>
> +#include <linux/virtio.h>
> +#include <linux/scatterlist.h>
> +
> +/* FIXME: Make dynamic */
> +#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
> +
> +#define SKB_ID(skb) (*(unsigned long *)(skb)->cb)
> +
> +struct virtnet_info
> +{
> + struct virtio_device *vdev;
> + struct net_device *ndev;
> +
> + /* Number of input buffers, and max we've ever had. */
> + unsigned int num, max;
> +
> + /* Receive & send queues. */
> + struct sk_buff_head recv;
> + struct sk_buff_head send;
> +};
> +
> +static bool skb_xmit_done(struct virtio_device *vdev)
> +{
> + struct virtnet_info *vi = vdev->priv;
> +
> + /* In case we were waiting for output buffers. */
> + netif_wake_queue(vi->ndev);
> + return true;
> +}
> +
> +static void receive_skb(struct net_device *dev, struct sk_buff *skb,
> + unsigned len)
> +{
> + if (unlikely(len < ETH_HLEN)) {
> + pr_debug("%s: short packet %i\n", dev->name, len);
> + dev->stats.rx_length_errors++;
> + dev_kfree_skb(skb);
> + return;
> + }
> + BUG_ON(len > MAX_PACKET_LEN);
> +
> + skb_trim(skb, len);
> + skb->protocol = eth_type_trans(skb, dev);
> + pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
> + ntohs(skb->protocol), skb->len, skb->pkt_type);
> + dev->stats.rx_bytes += skb->len;
> + dev->stats.rx_packets++;
> + netif_rx(skb);
> +}
> +
> +static void try_fill_recv(struct virtnet_info *vi)
> +{
> + struct sk_buff *skb;
> + struct scatterlist sg[MAX_SKB_FRAGS];
> + unsigned long sgnum, id;
> +
> + for (;;) {
> + skb = netdev_alloc_skb(vi->ndev, MAX_PACKET_LEN);
> + if (unlikely(!skb))
> + break;
> +
> + skb_put(skb, MAX_PACKET_LEN);
> + sgnum = skb_to_sgvec(skb, sg, 0, skb->len);
> + skb_queue_head(&vi->recv, skb);
> +
> + id = vi->vdev->ops->add_inbuf(vi->vdev, sg, sgnum, skb);
> + if (IS_ERR_VALUE(id)) {
> + skb_unlink(skb, &vi->recv);
> + kfree_skb(skb);
> + break;
> + }
> + vi->num++;
> + }
> + if (unlikely(vi->num > vi->max))
> + vi->max = vi->num;
> + vi->vdev->ops->sync(vi->vdev, VIRTIO_IN);
> +}
> +
> +static bool skb_recv_done(struct virtio_device *vdev)
> +{
> + struct virtnet_info *vi = vdev->priv;
> +
> + netif_rx_schedule(vi->ndev);
> + /* Suppress further interrupts. */
> + return false;
> +}
> +
> +static int virtnet_poll(struct net_device *dev, int *budget)
> +{
> + struct virtnet_info *vi = netdev_priv(dev);
> + struct sk_buff *skb = NULL;
> + unsigned int len, received = 0;
> +
> +again:
> + while (received < dev->quota &&
> + (skb = vi->vdev->ops->get_inbuf(vi->vdev, &len)) != NULL) {
> + __skb_unlink(skb, &vi->recv);
> + receive_skb(vi->ndev, skb, len);
> + vi->num--;
> + received++;
> + }
> +
> + dev->quota -= received;
> + *budget -= received;
> +
> + /* FIXME: If we oom and completely run out of inbufs, we need
> + * to start a timer trying to fill more. */
> + if (vi->num < vi->max / 2)
> + try_fill_recv(vi);
> +
> + /* Still more work to do? */
> + if (skb)
> + return 1; /* not done */
> +
> + netif_rx_complete(dev);
> + if (unlikely(!vi->vdev->ops->restart_in(vi->vdev))
> + && netif_rx_reschedule(dev, received))
> + goto again;
> +
> + return 0;
> +}
> +
> +static void free_old_xmit_skbs(struct virtnet_info *vi)
> +{
> + struct sk_buff *skb;
> + unsigned int len;
> +
> + while ((skb = vi->vdev->ops->get_outbuf(vi->vdev, &len)) != NULL) {
> + pr_debug("Sent skb %p\n", skb);
> + __skb_unlink(skb, &vi->send);
> + vi->ndev->stats.tx_bytes += len;
> + vi->ndev->stats.tx_packets++;
> + kfree_skb(skb);
> + }
> +}
> +
> +static int start_xmit(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct virtnet_info *vi = netdev_priv(dev);
> + unsigned long num, id;
> + struct scatterlist sg[MAX_SKB_FRAGS];
> + const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
> +
> + pr_debug("%s: xmit %p %02x:%02x:%02x:%02x:%02x:%02x\n",
> + dev->name, skb,
> + dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]);
> +
> + free_old_xmit_skbs(vi);
> +
> + num = skb_to_sgvec(skb, sg, 0, skb->len);
> + __skb_queue_head(&vi->send, skb);
> + id = vi->vdev->ops->add_outbuf(vi->vdev, sg, num, skb);
> + if (IS_ERR_VALUE(id)) {
> + pr_debug("%s: virtio not prepared to send\n", dev->name);
> + skb_unlink(skb, &vi->send);
> + netif_stop_queue(dev);
> + return NETDEV_TX_BUSY;
> + }
> + SKB_ID(skb) = id;
> + vi->vdev->ops->sync(vi->vdev, VIRTIO_OUT);
> +
> + return 0;
> +}
> +
> +static int virtnet_open(struct net_device *dev)
> +{
> + struct virtnet_info *vi = netdev_priv(dev);
> +
> + try_fill_recv(vi);
> +
> + /* If we didn't even get one input buffer, we're useless. */
> + if (vi->num == 0)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +static int virtnet_close(struct net_device *dev)
> +{
> + struct virtnet_info *vi = netdev_priv(dev);
> + struct sk_buff *skb;
> +
> + /* networking core has neutered skb_xmit_done/skb_recv_done, so don't
> + * worry about races vs. get_buf(). */
> + while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
> + vi->vdev->ops->detach_inbuf(vi->vdev, SKB_ID(skb));
> + kfree_skb(skb);
> + vi->num--;
> + }
> + while ((skb = __skb_dequeue(&vi->send)) != NULL) {
> + vi->vdev->ops->detach_outbuf(vi->vdev, SKB_ID(skb));
> + kfree_skb(skb);
> + }
> + BUG_ON(vi->num != 0);
> + return 0;
> +}
> +
> +static struct virtio_driver_ops virtnet_ops = {
> + .in = skb_recv_done,
> + .out = skb_xmit_done,
> +};
> +
> +struct net_device *virtnet_probe(struct virtio_device *vdev,
> + const u8 mac[ETH_ALEN])
> +{
> + int err;
> + struct net_device *dev;
> + struct virtnet_info *vi;
> +
> + dev = alloc_etherdev(sizeof(struct virtnet_info));
> + if (!dev)
> + return ERR_PTR(-ENOMEM);
> +
> + SET_MODULE_OWNER(dev);
> +
> + ether_setup(dev);
> + memcpy(dev->dev_addr, mac, ETH_ALEN);
> + dev->open = virtnet_open;
> + dev->stop = virtnet_close;
> + dev->poll = virtnet_poll;
> + dev->hard_start_xmit = start_xmit;
> + dev->weight = 16;
> + SET_NETDEV_DEV(dev, vdev->dev);
> +
> + vi = netdev_priv(dev);
> + vi->vdev = vdev;
> + vi->ndev = dev;
> + vdev->priv = vi;
> + vdev->driver_ops = &virtnet_ops;
> + skb_queue_head_init(&vi->recv);
> + skb_queue_head_init(&vi->send);
> +
> + err = register_netdev(dev);
> + if (err) {
> + pr_debug("virtio_net: registering device failed\n");
> + goto free;
> + }
> + pr_debug("virtnet: registered device %s\n", dev->name);
> + return dev;
> +
> +free:
> + free_netdev(dev);
> + return ERR_PTR(err);
> +}
> +EXPORT_SYMBOL_GPL(virtnet_probe);
> +
> +void virtnet_remove(struct net_device *dev)
> +{
> + unregister_netdev(dev);
> + free_netdev(dev);
> +}
> +EXPORT_SYMBOL_GPL(virtnet_remove);
> +
> +MODULE_DESCRIPTION("Virtio network driver");
> +MODULE_LICENSE("GPL");
> ===================================================================
> --- /dev/null
> +++ b/include/linux/virtio_net.h
> @@ -0,0 +1,12 @@
> +#ifndef _LINUX_VIRTIO_NET_H
> +#define _LINUX_VIRTIO_NET_H
> +#include <linux/types.h>
> +#include <linux/etherdevice.h>
> +struct net_device;
> +struct virtio_device;
> +
> +struct net_device *virtnet_probe(struct virtio_device *vdev,
> + const u8 mac[ETH_ALEN]);
> +void virtnet_remove(struct net_device *dev);
> +
> +#endif /* _LINUX_VIRTIO_NET_H */
>
>
> _______________________________________________
> Virtualization mailing list
> Virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
> https://lists.linux-foundation.org/mailman/listinfo/virtualization
--
Brian King
eServer Storage I/O
IBM Linux Technology Center
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
next prev parent reply other threads:[~2007-06-25 15:26 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-07 12:02 [PATCH RFC 0/3] Virtio draft II Rusty Russell
2007-06-07 12:04 ` [PATCH RFC 1/3] Virtio draft II: virtio.h Rusty Russell
[not found] ` <1181217867.14054.195.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-07 12:05 ` [PATCH RFC 2/3] Virtio draft II: example block driver Rusty Russell
[not found] ` <1181217920.14054.196.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-07 12:07 ` [PATCH RFC 3/3] Virtio draft II: example net driver Rusty Russell
2007-06-07 12:19 ` [PATCH RFC 2/3] Virtio draft II: example block driver Avi Kivity
[not found] ` <4667F7C0.3070604-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-08 1:11 ` Rusty Russell
[not found] ` <1181217762.14054.192.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:12 ` [PATCH RFC 0/3] Virtio draft III Rusty Russell
[not found] ` <1181999552.6237.255.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:14 ` [PATCH RFC 1/3] Virtio draft III: virtio.h Rusty Russell
[not found] ` <1181999669.6237.257.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:17 ` [PATCH RFC 2/3] Virtio draft III: example net driver Rusty Russell
[not found] ` <1181999825.6237.260.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:18 ` [PATCH RFC 3/3] Virtio draft III: example block driver Rusty Russell
[not found] ` <1181999920.6237.263.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:28 ` [PATCH] Lguest implemention of virtio draft III Rusty Russell
[not found] ` <1182000514.6237.273.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-16 13:50 ` Arnd Bergmann
2007-06-17 14:25 ` [PATCH RFC 3/3] Virtio draft III: example block driver Avi Kivity
[not found] ` <46754451.2010305-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 8:08 ` Rusty Russell
[not found] ` <1182154095.19064.24.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-18 9:09 ` Avi Kivity
[not found] ` <46764BB5.6070704-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-19 6:27 ` Rusty Russell
[not found] ` <1182234466.19064.51.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-19 8:34 ` Avi Kivity
2007-06-25 15:26 ` Brian King [this message]
[not found] ` <467FDEAD.4030204-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2007-06-25 19:33 ` [PATCH RFC 2/3] Virtio draft III: example net driver Christoph Hellwig
[not found] ` <20070625193304.GB25736-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
2007-06-25 21:54 ` Avi Kivity
[not found] ` <46803999.4040500-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-25 22:13 ` Brian King
[not found] ` <46803E0E.7080103-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2007-06-25 22:20 ` Avi Kivity
2007-06-28 11:20 ` Rusty Russell
[not found] ` <1183029641.12401.36.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
2007-06-28 15:55 ` Brian King
2007-06-17 14:14 ` [PATCH RFC 0/3] Virtio draft III Avi Kivity
[not found] ` <467541DF.5060907-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 7:48 ` [Xen-devel] " Rusty Russell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=467FDEAD.4030204@linux.vnet.ibm.com \
--to=brking-23vcf4htsmix0ybbhkvfkdbpr1lh4cv8@public.gmane.org \
--cc=cborntra-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org \
--cc=herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org \
--cc=jmk-zzFmDc4TPjtKvsKVC3L/VUEOCMrvLtNR@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=lionkov-YOWKrPYUwWM@public.gmane.org \
--cc=rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org \
--cc=schwidefsky-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org \
--cc=sfr-3FnU+UHB4dNDw9hX6IcOSA@public.gmane.org \
--cc=skranjac-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org \
--cc=virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=xen-devel-GuqFBffKawuULHF6PoxzQEEOCMrvLtNR@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox