From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KNThS-000512-Cu for qemu-devel@nongnu.org; Mon, 28 Jul 2008 10:27:46 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KNThP-000500-WC for qemu-devel@nongnu.org; Mon, 28 Jul 2008 10:27:45 -0400 Received: from [199.232.76.173] (port=58449 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KNThP-0004zl-Kd for qemu-devel@nongnu.org; Mon, 28 Jul 2008 10:27:43 -0400 Received: from wr-out-0506.google.com ([64.233.184.234]:49071) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KNThP-00004s-2Y for qemu-devel@nongnu.org; Mon, 28 Jul 2008 10:27:43 -0400 Received: by wr-out-0506.google.com with SMTP id c46so4021999wra.18 for ; Mon, 28 Jul 2008 07:27:40 -0700 (PDT) Message-ID: <488DD73C.7060302@codemonkey.ws> Date: Mon, 28 Jul 2008 09:27:08 -0500 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH 6/7] xen: add net backend driver. References: <1217251078-6591-1-git-send-email-kraxel@redhat.com> <1217251078-6591-7-git-send-email-kraxel@redhat.com> In-Reply-To: <1217251078-6591-7-git-send-email-kraxel@redhat.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: xen-devel@lists.xensource.com, Gerd Hoffmann Gerd Hoffmann wrote: > This patch adds a network interface backend driver to qemu. It is a pure > userspace implemention using the gntdev interface. It uses "qnet" as > backend name in xenstore so it doesn't interfere with the netback > backend (aka "vnif"). > > The network backend is hooked into the corrosponding qemu vlan, i.e. > vif 0 is hooked into vlan 0. To make the packages actually arrive > somewhere you additionally have to link the vlan to the outside world > using the usual qemu command line options such as "-net tap,...". > > Signed-off-by: Gerd Hoffmann > --- > Makefile.target | 2 +- > hw/xen-backend.h | 1 + > hw/xen-machine.c | 1 + > hw/xen-nic.c | 448 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 451 insertions(+), 1 deletions(-) > create mode 100644 hw/xen-nic.c > > diff --git a/Makefile.target b/Makefile.target > index 2d599d2..281d7fa 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -517,7 +517,7 @@ endif > > # xen backend driver support > XEN_OBJS := xen-machine.o xen-backend.o > -XEN_OBJS += xen-console.o xen-framebuffer.o xen-disk.o > +XEN_OBJS += xen-console.o xen-framebuffer.o xen-disk.o xen-nic.o > ifeq ($(CONFIG_XEN), yes) > OBJS += $(XEN_OBJS) > LIBS += $(XEN_LIBS) > diff --git a/hw/xen-backend.h b/hw/xen-backend.h > index 941b0a6..2db2c3c 100644 > --- a/hw/xen-backend.h > +++ b/hw/xen-backend.h > @@ -120,6 +120,7 @@ struct devops xen_console_ops; /* xen_console.c */ > struct devops xen_kbdmouse_ops; /* xen_framebuffer.c */ > struct devops xen_framebuffer_ops; /* xen_framebuffer.c */ > struct devops xen_blkdev_ops; /* xen_disk.c */ > +struct devops xen_netdev_ops; /* xen_nic.c */ > > void xen_set_display(int domid, DisplayState *ds); > > diff --git a/hw/xen-machine.c b/hw/xen-machine.c > index 1b647a2..3fa4079 100644 > --- a/hw/xen-machine.c > +++ b/hw/xen-machine.c > @@ -62,6 +62,7 @@ static void xenpv_init(ram_addr_t ram_size, int vga_ram_size, > xen_be_register("vkbd", &xen_kbdmouse_ops); > xen_be_register("vfb", &xen_framebuffer_ops); > xen_be_register("qdisk", &xen_blkdev_ops); > + xen_be_register("qnic", &xen_netdev_ops); > > /* setup framebuffer */ > xen_set_display(xen_domid, ds); > diff --git a/hw/xen-nic.c b/hw/xen-nic.c > new file mode 100644 > index 0000000..56d1474 > --- /dev/null > +++ b/hw/xen-nic.c > @@ -0,0 +1,448 @@ > +/* > + * xen paravirt network card backend > + * > + * 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; under version 2 of the License. > + * > + * 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 > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > + > +#include "hw.h" > +#include "net.h" > +#include "qemu-char.h" > +#include "xen-backend.h" > + > +/* ------------------------------------------------------------- */ > + > +struct netdev { > + struct xendev xendev; /* must be first */ > + char *mac; > + int tx_work; > + int tx_ring_ref; > + int rx_ring_ref; > + struct netif_tx_sring *txs; > + struct netif_rx_sring *rxs; > + netif_tx_back_ring_t tx_ring; > + netif_rx_back_ring_t rx_ring; > + VLANClientState *vs; > +}; > + > +/* ------------------------------------------------------------- */ > + > +#define PROTO_TCP 6 > +#define PROTO_UDP 17 > + > +static uint32_t checksum_add(int len, uint8_t *buf) > +{ > + uint32_t sum = 0; > + int i; > + > + for (i = 0; i < len; i++) { > + if (i & 1) > + sum += (uint32_t)buf[i]; > + else > + sum += (uint32_t)buf[i] << 8; > + } > + return sum; > +} > + > +static uint16_t checksum_finish(uint32_t sum) > +{ > + while (sum>>16) > + sum = (sum & 0xFFFF)+(sum >> 16); > + return ~sum; > +} > + > +static uint16_t checksum_tcpudp(uint16_t length, uint16_t proto, > + uint8_t *addrs, uint8_t *buf) > +{ > + uint32_t sum = 0; > + > + sum += checksum_add(length, buf); // payload > + sum += checksum_add(8, addrs); // src + dst address > + sum += proto + length; // protocol & length > + return checksum_finish(sum); > +} > + > +static void checksum_calculate(uint8_t *data, int length) > +{ > + int hlen, plen, proto, csum_offset; > + uint16_t csum; > + > + if ((data[14] & 0xf0) != 0x40) > + return; /* not IPv4 */ > + hlen = (data[14] & 0x0f) * 4; > + plen = (data[16] << 8 | data[17]) - hlen; > + proto = data[23]; > + > + switch (proto) { > + case PROTO_TCP: > + csum_offset = 16; > + break; > + case PROTO_UDP: > + csum_offset = 6; > + break; > + default: > + return; > + } > + > + if (plen < csum_offset+2) > + return; > + > + data[14+hlen+csum_offset] = 0; > + data[14+hlen+csum_offset+1] = 0; > + csum = checksum_tcpudp(plen, proto, data+14+12, data+14+hlen); > + data[14+hlen+csum_offset] = csum >> 8; > + data[14+hlen+csum_offset+1] = csum & 0xff; > +} > > The same thing is done in e1000, I believe. We'll also probably want to be able to support this for virtio so this would be pretty good to make common code. Regards, Anthony Liguori