From: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
To: virtualization
<virtualization-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>
Cc: Jimi Xenidis <jimix-aZOuKsOsJu3MbYB6QlFGEg@public.gmane.org>,
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>,
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: [PATCH RFC 3/3] Virtio draft II: example net driver
Date: Thu, 07 Jun 2007 22:07:03 +1000 [thread overview]
Message-ID: <1181218023.14054.199.camel@localhost.localdomain> (raw)
In-Reply-To: <1181217920.14054.196.camel-bi+AKbBUZKY6gyzm1THtWbp2dZbC/Bob@public.gmane.org>
TODO:
1) NAPI (will require way of suppressing virtio callbacks)
2) GSO.
3) Checksum options.
Signed-off-by: Rusty Russell <rusty-8n+1lVoiYb80n/F98K4Iww@public.gmane.org>
---
drivers/net/Makefile | 2
drivers/net/virtio_net.c | 243 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/virtio_net.h | 12 ++
3 files changed, 256 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,243 @@
+/* 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;
+
+ /* Receive & send queues. */
+ struct sk_buff_head recv;
+ struct sk_buff_head send;
+
+ /* Transmitted packets waiting to be freed */
+ struct sk_buff_head free;
+};
+
+static void skb_xmit_done(struct virtio_device *vdev, void *_skb, unsigned len)
+{
+ struct virtnet_info *vi = vdev->priv;
+ struct sk_buff *skb = _skb;
+
+ assert_spin_locked(&vdev->lock);
+
+ __skb_unlink(skb, &vi->send);
+ vi->ndev->stats.tx_bytes += len;
+ vi->ndev->stats.tx_packets++;
+ __skb_queue_head(&vi->free, skb);
+
+ pr_debug("Sent skb %p\n", skb);
+ /* In case we were waiting for output buffers. */
+ netif_wake_queue(vi->ndev);
+}
+
+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 skb_recv_done(struct virtio_device *, void *, unsigned);
+static int try_fill_recv(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ struct scatterlist sg[MAX_SKB_FRAGS];
+ unsigned long num, id;
+
+ assert_spin_locked(&vi->vdev->lock);
+
+ skb = netdev_alloc_skb(vi->ndev, MAX_PACKET_LEN);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ skb_put(skb, MAX_PACKET_LEN);
+ num = skb_to_sgvec(skb, sg, 0, skb->len);
+ skb_queue_head(&vi->recv, skb);
+
+ id = vi->vdev->ops->add_inbuf(vi->vdev, sg, num, skb_recv_done, skb);
+ if (IS_ERR_VALUE(id)) {
+ skb_unlink(skb, &vi->recv);
+ kfree_skb(skb);
+ return id;
+ }
+ return 0;
+}
+
+static void skb_recv_done(struct virtio_device *vdev, void *_skb, unsigned len)
+{
+ struct virtnet_info *vi = vdev->priv;
+ struct sk_buff *skb = _skb;
+
+ assert_spin_locked(&vdev->lock);
+ __skb_unlink(skb, &vi->recv);
+ receive_skb(vi->ndev, skb, len);
+ try_fill_recv(vi);
+}
+
+static void free_old_skbs(struct sk_buff_head *free)
+{
+ struct sk_buff *skb;
+ while ((skb = __skb_dequeue(free)) != NULL)
+ 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;
+ unsigned long flags;
+
+ 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]);
+
+ spin_lock_irqsave(&vi->vdev->lock, flags);
+ /* Free any transmitted packets: not supposed to do it in interrupt */
+ free_old_skbs(&vi->free);
+
+ 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_xmit_done, 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);
+ spin_unlock_irqrestore(&vi->vdev->lock, flags);
+
+ return 0;
+}
+
+static int virtnet_open(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ int i, err;
+
+ spin_lock_irq(&vi->vdev->lock);
+ for (i = 0; (err = try_fill_recv(vi)) == 0; i++);
+ vi->vdev->ops->sync(vi->vdev);
+ spin_unlock_irq(&vi->vdev->lock);
+
+ /* If we didn't even get one input buffer, we're useless. */
+ if (i == 0)
+ return err;
+
+ return 0;
+}
+
+static int virtnet_close(struct net_device *dev)
+{
+ struct virtnet_info *vi = netdev_priv(dev);
+ struct sk_buff *skb;
+
+ spin_lock_irq(&vi->vdev->lock);
+ while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
+ vi->vdev->ops->detach_inbuf(vi->vdev, SKB_ID(skb));
+ kfree_skb(skb);
+ }
+ while ((skb = __skb_dequeue(&vi->send)) != NULL) {
+ vi->vdev->ops->detach_outbuf(vi->vdev, SKB_ID(skb));
+ kfree_skb(skb);
+ }
+ free_old_skbs(&vi->free);
+ spin_unlock_irq(&vi->vdev->lock);
+ return 0;
+}
+
+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->hard_start_xmit = start_xmit;
+ SET_NETDEV_DEV(dev, vdev->dev);
+
+ vi = netdev_priv(dev);
+ vi->vdev = vdev;
+ vi->ndev = dev;
+ vdev->priv = vi;
+ skb_queue_head_init(&vi->recv);
+ skb_queue_head_init(&vi->send);
+ skb_queue_head_init(&vi->free);
+
+ 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 */
-------------------------------------------------------------------------
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-07 12:07 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 ` Rusty Russell [this message]
2007-06-07 12:19 ` 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 ` [PATCH RFC 2/3] Virtio draft III: example net driver Brian King
[not found] ` <467FDEAD.4030204-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2007-06-25 19:33 ` 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=1181218023.14054.199.camel@localhost.localdomain \
--to=rusty-8n+1lvoiyb80n/f98k4iww@public.gmane.org \
--cc=cborntra-tA70FqPdS9bQT0dZR+AlfA@public.gmane.org \
--cc=herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q@public.gmane.org \
--cc=jimix-aZOuKsOsJu3MbYB6QlFGEg@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=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