Re: [Qemu-devel] [PATCH 0/2] netdev fixes
On Wed, 2011-07-20 at 11:19 +0300, Michael S. Tsirkin wrote: > On Tue, Jul 19, 2011 at 07:52:39PM +0200, Jan Kiszka wrote: > > On 2011-07-19 14:10, Michael S. Tsirkin wrote: > > > On Thu, Jun 16, 2011 at 06:45:35PM +0200, Markus Armbruster wrote: > > >> Markus Armbruster (2): > > >> Fix automatically assigned network names for netdev > > >> Fix netdev name lookup in -device, device_add, netdev_del > > >> > > >> net.c | 19 +++ > > >> 1 files changed, 15 insertions(+), 4 deletions(-) > > > > > > Thanks, applied. > > > I think going forward we should bring more order into ways we assign > > > IDs. > > > > Did you take over net subsystem integration? > > No, Markus just asked me to look at his patches, and I took interest. > I applied the patches to my tree, from there pull requests go to Anthony > who is a maintainer for net/ so I think that's all right. > > Also, it's just my tree, pull request won't go out before > Thursday at the earliest, so if someone objects > (or wants to merge them himself), there's plenty of time. > > > Or who should initially receive related patches now? > > > > Jan > > I think running ./scripts/get_maintainer.pl is generally > a good idea. For net you'd get: > > [qemu]$ ./scripts/get_maintainer.pl -f net.c net/ > Anthony Liguori (maintainer:Network device > layer,commit_signer:4/16=25%) > Mark McLoughlin (maintainer:Network device layer) This is clearly out of date - feel free to remove it Cheers, Mark.
[Qemu-devel] Open Source Virtualization and Cloud at FOSDEM
Hey, Here's one for the calendar - a 2 day track at FOSDEM devoted to Open Source Virtualization and Cloud. Hope to see you there! :) Cheers, Mark. Forwarded Message > From: Thierry Carrez > To: openst...@lists.launchpad.net > Subject: [Openstack] OpenStack at FOSDEM > Date: Fri, 11 Nov 2011 11:34:22 +0100 > > Hi everyone, > > Our OpenStack devroom was accepted for FOSDEM, February 4-5, 2012 in > Brussels. It was actually grouped with other "Open Source virtualization > and cloud" projects in a giant devroom (550-seat auditorium) that lasts > the full 2 days ! > > Expect a CFP in the coming weeks... > > See other devrooms at: > http://fosdem.org/2012/devrooms_for_2012 > > -- > Thierry Carrez (ttx) > Release Manager, OpenStack > > ___ > Mailing list: https://launchpad.net/~openstack > Post to : openst...@lists.launchpad.net > Unsubscribe : https://launchpad.net/~openstack > More help : https://help.launchpad.net/ListHelp
[Qemu-devel] Re: [PATCH 0/6] Assorted netdev fixes
On Thu, 2010-02-11 at 14:44 +0100, Markus Armbruster wrote: > The fixes fall into three groups: > > * Dead code removal. > > * Fix bogus "Warning: vlan 0 with no nics" with -device > > * When we added network clients not associated with a VLAN (-netdev & > friends), we missed a few places. Fix them up. > > Markus Armbruster (6): > net: Remove unused net_client_uninit() > net: net_check_clients() runs too early to see -device, fix > net: Fix bogus "Warning: vlan 0 with no nics" with -device > net: net_check_clients() checks only VLAN clients, fix > net: info network shows only VLAN clients, fix > net: Monitor command set_link finds only VLAN clients, fix Nice. They all look good to me Acked-by: Mark McLoughlin Cheers, Mark.
[Qemu-devel] [PATCH] net: initialize vnet_hdr in net_tap_init()
Hi Pierre, On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote: > vnet_hdr is initialized at 1 by default. We need to reset it to 0 if > the kernel doesn't support IFF_VNET_HDR. Thanks for the patch, but I'd prefer us to make sure we catch all cases. Does this work for you? Thanks, Mark. From: Mark McLoughlin Subject: [PATCH] net: initialize vnet_hdr in net_tap_init() Don't assume that all tap_open() implementations will set it to zero if VNET_HDR support isn't found. Fixes tap networking on host kernels lacking IFF_VNET_HDR support. Reported-by: Pierre Riteau Signed-off-by: Mark McLoughlin --- net/tap.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/tap.c b/net/tap.c index d34feec..7fb9e16 100644 --- a/net/tap.c +++ b/net/tap.c @@ -378,7 +378,7 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr) int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) { TAPState *s; -int fd, vnet_hdr; +int fd, vnet_hdr = 0; if (qemu_opt_get(opts, "fd")) { if (qemu_opt_get(opts, "ifname") || -- 1.6.5.2
[Qemu-devel] Re: [PATCH] Fix TAP networking on host kernels without IFF_VNET_HDR support
On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote: > vnet_hdr is initialized at 1 by default. We need to reset it to 0 if > the kernel doesn't support IFF_VNET_HDR. > > Signed-off-by: Pierre Riteau Thanks Pierre, I see why this is needed now Acked-by: Mark McLoughlin Cheers, Mark.
Re: [Qemu-devel] Re: [PATCH] Fix TAP networking on host kernels without IFF_VNET_HDR support
On Tue, 2009-11-24 at 12:17 +0100, Pierre Riteau wrote: > On 24 nov. 2009, at 11:28, Mark McLoughlin wrote: > > > On Tue, 2009-11-24 at 10:06 +0100, Pierre Riteau wrote: > >> vnet_hdr is initialized at 1 by default. We need to reset it to 0 if > >> the kernel doesn't support IFF_VNET_HDR. > >> > >> Signed-off-by: Pierre Riteau > > > > Thanks Pierre, I see why this is needed now > > > > Acked-by: Mark McLoughlin > > > > Cheers, > > Mark. > > > Thanks for your rapid answer! > > BTW, every time I run qemu I see this error message: > > TUNSETOFFLOAD ioctl() failed: Invalid argument > > It is caused by the piece of code at the end of net/tap-linux.c: > > if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { > offload &= ~TUN_F_UFO; > if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { > fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", > strerror(errno)); > } > } > > Isn't there a way to detect whether the kernel supports the > TUNSETOFFLOAD ioctl at all? The kernel will set errno to EINVAL if TUNSETOFFLOAD isn't supported, so we could just ignore that case: if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { offload &= ~TUN_F_UFO; if (ioctl(fd, TUNSETOFFLOAD, offload) != 0 && errno != EINVAL) { fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", strerror(errno)); } } The only concern is that we'll also miss out on an error message if EINVAL is set for another reason. Currently, the only other reason if we pass a offload flag not supported by the kernel, but that should never happen. Feel free to send a patch with that change and I'll ack it Thanks, Mark.
Re: [Qemu-devel] Re: [PATCH] Fix TAP networking on host kernels without IFF_VNET_HDR support
On Tue, 2009-11-24 at 22:27 +0100, Pierre Riteau wrote: > On 24 nov. 2009, at 12:22, Mark McLoughlin wrote: > > > On Tue, 2009-11-24 at 12:17 +0100, Pierre Riteau wrote: > >> Isn't there a way to detect whether the kernel supports the > >> TUNSETOFFLOAD ioctl at all? > > > > The kernel will set errno to EINVAL if TUNSETOFFLOAD isn't supported, so > > we could just ignore that case: > > > > if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { > > offload &= ~TUN_F_UFO; > > if (ioctl(fd, TUNSETOFFLOAD, offload) != 0 && errno != EINVAL) { > > fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", > > strerror(errno)); > > } > > } > > > > The only concern is that we'll also miss out on an error message if > > EINVAL is set for another reason. Currently, the only other reason if we > > pass a offload flag not supported by the kernel, but that should never > > happen. > > > > Feel free to send a patch with that change and I'll ack it > > Couldn't we probe the kernel with a 0 offload value to check if it supports > TUNSETOFFLOAD? > I tried the following and it works on my 2.6.26 Debian kernel. > What do you think? I will send a proper patch if you agree. > > diff --git a/net/tap-linux.c b/net/tap-linux.c > index 0f621a2..e038e1a 100644 > --- a/net/tap-linux.c > +++ b/net/tap-linux.c > @@ -129,6 +129,11 @@ void tap_fd_set_offload(int fd, int csum, int tso4, > { > unsigned int offload = 0; > > +/* Check if our kernel supports TUNSETOFFLOAD */ > +if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { > +return; > +} > + It's not ideal because a) it's another syscall and b) you're briefly disabling any flags that may have been set previously ... but in our case, neither is a real concern and it's a nice, simple solution. So, sounds good to me :) Cheers, Mark.
Re: [Qemu-devel] [PATCH] Check for TUNSETOFFLOAD support before trying to enable offload features
On Wed, 2009-11-25 at 11:04 +0100, Pierre Riteau wrote: > This avoids the "TUNSETOFFLOAD ioctl() failed: Invalid argument" message > on kernels without TUNSETOFFLOAD support. > > Signed-off-by: Pierre Riteau Acked-by: Mark McLoughlin Thanks, Mark. > --- > net/tap-linux.c |5 + > 1 files changed, 5 insertions(+), 0 deletions(-) > > diff --git a/net/tap-linux.c b/net/tap-linux.c > index 0f621a2..e038e1a 100644 > --- a/net/tap-linux.c > +++ b/net/tap-linux.c > @@ -129,6 +129,11 @@ void tap_fd_set_offload(int fd, int csum, int tso4, > { > unsigned int offload = 0; > > +/* Check if our kernel supports TUNSETOFFLOAD */ > +if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { > +return; > +} > + > if (csum) { > offload |= TUN_F_CSUM; > if (tso4)
[Qemu-devel] [PATCH 03/44] net: move socket backend code from net.c to net/socket.c
Signed-off-by: Mark McLoughlin --- Makefile |1 + net.c| 530 +-- net/socket.c | 561 ++ net/socket.h | 33 4 files changed, 596 insertions(+), 529 deletions(-) create mode 100644 net/socket.c create mode 100644 net/socket.h diff --git a/Makefile b/Makefile index ee00ecc..fa1070d 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,7 @@ block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o net-nested-y = queue.o checksum.o +net-nested-y += socket.o net-nested-$(CONFIG_POSIX) += tap.o net-nested-$(CONFIG_LINUX) += tap-linux.o net-nested-$(CONFIG_WIN32) += tap-win32.o diff --git a/net.c b/net.c index 5f8457c..3b3f3d6 100644 --- a/net.c +++ b/net.c @@ -92,6 +92,7 @@ #include "qemu-common.h" #include "net.h" #include "net/tap.h" +#include "net/socket.h" #include "net/slirp.h" #include "net/vde.h" #include "monitor.h" @@ -719,454 +720,6 @@ qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); } -/* network connection */ -typedef struct NetSocketState { -VLANClientState *vc; -int fd; -int state; /* 0 = getting length, 1 = getting data */ -unsigned int index; -unsigned int packet_len; -uint8_t buf[4096]; -struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ -} NetSocketState; - -typedef struct NetSocketListenState { -VLANState *vlan; -char *model; -char *name; -int fd; -} NetSocketListenState; - -/* XXX: we consider we can send the whole packet without blocking */ -static ssize_t net_socket_receive(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -NetSocketState *s = vc->opaque; -uint32_t len; -len = htonl(size); - -send_all(s->fd, (const uint8_t *)&len, sizeof(len)); -return send_all(s->fd, buf, size); -} - -static ssize_t net_socket_receive_dgram(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -NetSocketState *s = vc->opaque; - -return sendto(s->fd, (const void *)buf, size, 0, - (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); -} - -static void net_socket_send(void *opaque) -{ -NetSocketState *s = opaque; -int size, err; -unsigned l; -uint8_t buf1[4096]; -const uint8_t *buf; - -size = recv(s->fd, (void *)buf1, sizeof(buf1), 0); -if (size < 0) { -err = socket_error(); -if (err != EWOULDBLOCK) -goto eoc; -} else if (size == 0) { -/* end of connection */ -eoc: -qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -closesocket(s->fd); -return; -} -buf = buf1; -while (size > 0) { -/* reassemble a packet from the network */ -switch(s->state) { -case 0: -l = 4 - s->index; -if (l > size) -l = size; -memcpy(s->buf + s->index, buf, l); -buf += l; -size -= l; -s->index += l; -if (s->index == 4) { -/* got length */ -s->packet_len = ntohl(*(uint32_t *)s->buf); -s->index = 0; -s->state = 1; -} -break; -case 1: -l = s->packet_len - s->index; -if (l > size) -l = size; -if (s->index + l <= sizeof(s->buf)) { -memcpy(s->buf + s->index, buf, l); -} else { -fprintf(stderr, "serious error: oversized packet received," -"connection terminated.\n"); -s->state = 0; -goto eoc; -} - -s->index += l; -buf += l; -size -= l; -if (s->index >= s->packet_len) { -qemu_send_packet(s->vc, s->buf, s->packet_len); -s->index = 0; -s->state = 0; -} -break; -} -} -} - -static void net_socket_send_dgram(void *opaque) -{ -NetSocketState *s = opaque; -int size; - -size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0); -if (size < 0) -return; -if (size == 0) { -/* end of connection */ -qemu_set_fd_handler(s->fd, NULL, NULL, NULL); -return; -} -qemu_send_packet(s->vc, s->buf, size); -} - -static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) -{ -struct ip_mreq imr; -int fd; -int val, ret; -if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { - fprintf(stderr, "qemu: error: specified mcastaddr
[Qemu-devel] [PATCH 00/44] Fix announce_self(), misc net fixes and cleanups
Hi, Here's a new series of patches mainly to fix qemu_announce_self() with -netdev as discussed earlier on the list. I would have liked to have split the series in three, but there would be conflicts between each, so here goes: 1) Patches 01 to 05 - net.c cleanups These patches continue the job of moving net backends from net.c to individual files in the net/ directory 2) Patches 06 to 39 - fix qemu_annonuce_self() The basic issue is that we need a sane way of iterating all the NICs on the system, obtaining the MAC address for each and inject a packet from each. The series splits out the per-device-type data from VLANClientState into a new structure called NetClientInfo. It further allows devices to inherit from VLANClientState and introduces a NICState struct and qemu_new_nic() constructor for NICs. That's a huge amount of churn just to fix qemu_announce_self(), but I think the end result is a very nice cleanup to the net API. 3) Patches 40 to 44 - misc fixes Some small misc networking fixes, including the two posted by Pierre Riteau earlier. I've given all this quite a bit of compile and runtime testing and it seems in good shape. Thanks, Mark.
[Qemu-devel] [PATCH 02/44] net: move vde code from net.c to net/vde.c
Signed-off-by: Mark McLoughlin --- Makefile |1 + net.c | 102 +- net/vde.c | 124 + net/vde.h | 36 ++ 4 files changed, 162 insertions(+), 101 deletions(-) create mode 100644 net/vde.c create mode 100644 net/vde.h diff --git a/Makefile b/Makefile index 45362fa..ee00ecc 100644 --- a/Makefile +++ b/Makefile @@ -107,6 +107,7 @@ net-nested-$(CONFIG_BSD) += tap-bsd.o net-nested-$(CONFIG_SOLARIS) += tap-solaris.o net-nested-$(CONFIG_AIX) += tap-aix.o net-nested-$(CONFIG_SLIRP) += slirp.o +net-nested-$(CONFIG_VDE) += vde.o net-obj-y += $(addprefix net/, $(net-nested-y)) ## diff --git a/net.c b/net.c index 9b030a1..5f8457c 100644 --- a/net.c +++ b/net.c @@ -89,14 +89,11 @@ #include #endif -#if defined(CONFIG_VDE) -#include -#endif - #include "qemu-common.h" #include "net.h" #include "net/tap.h" #include "net/slirp.h" +#include "net/vde.h" #include "monitor.h" #include "sysemu.h" #include "qemu-timer.h" @@ -722,75 +719,6 @@ qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); } -#if defined(CONFIG_VDE) -typedef struct VDEState { -VLANClientState *vc; -VDECONN *vde; -} VDEState; - -static void vde_to_qemu(void *opaque) -{ -VDEState *s = opaque; -uint8_t buf[4096]; -int size; - -size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); -if (size > 0) { -qemu_send_packet(s->vc, buf, size); -} -} - -static ssize_t vde_receive(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -VDEState *s = vc->opaque; -ssize_t ret; - -do { - ret = vde_send(s->vde, (const char *)buf, size, 0); -} while (ret < 0 && errno == EINTR); - -return ret; -} - -static void vde_cleanup(VLANClientState *vc) -{ -VDEState *s = vc->opaque; -qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); -vde_close(s->vde); -qemu_free(s); -} - -static int net_vde_init(VLANState *vlan, const char *model, -const char *name, const char *sock, -int port, const char *group, int mode) -{ -VDEState *s; -char *init_group = (char *)group; -char *init_sock = (char *)sock; - -struct vde_open_args args = { -.port = port, -.group = init_group, -.mode = mode, -}; - -s = qemu_mallocz(sizeof(VDEState)); -s->vde = vde_open(init_sock, (char *)"QEMU", &args); -if (!s->vde){ -free(s); -return -1; -} -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_VDE, - vlan, NULL, model, name, NULL, - vde_receive, NULL, NULL, - vde_cleanup, s); -qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d", - sock, vde_datafd(s->vde)); -return 0; -} -#endif - /* network connection */ typedef struct NetSocketState { VLANClientState *vc; @@ -1603,34 +1531,6 @@ static int net_init_socket(QemuOpts *opts, return 0; } -#ifdef CONFIG_VDE -static int net_init_vde(QemuOpts *opts, -Monitor *mon, -const char *name, -VLANState *vlan) -{ -const char *sock; -const char *group; -int port, mode; - -sock = qemu_opt_get(opts, "sock"); -group = qemu_opt_get(opts, "group"); - -port = qemu_opt_get_number(opts, "port", 0); -mode = qemu_opt_get_number(opts, "mode", 0700); - -if (net_vde_init(vlan, "vde", name, sock, port, group, mode) == -1) { -return -1; -} - -if (vlan) { -vlan->nb_host_devs++; -} - -return 0; -} -#endif - static int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name, diff --git a/net/vde.c b/net/vde.c new file mode 100644 index 000..4d09967 --- /dev/null +++ b/net/vde.c @@ -0,0 +1,124 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice
[Qemu-devel] [PATCH 04/44] net: move dump backend code from net.c to net/dump.c
Signed-off-by: Mark McLoughlin --- Makefile |1 + net.c | 127 +-- net/dump.c | 151 net/dump.h | 33 + 4 files changed, 186 insertions(+), 126 deletions(-) create mode 100644 net/dump.c create mode 100644 net/dump.h diff --git a/Makefile b/Makefile index fa1070d..6ed4bf8 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,7 @@ block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o net-nested-y = queue.o checksum.o net-nested-y += socket.o +net-nested-y += dump.o net-nested-$(CONFIG_POSIX) += tap.o net-nested-$(CONFIG_LINUX) += tap-linux.o net-nested-$(CONFIG_WIN32) += tap-win32.o diff --git a/net.c b/net.c index 3b3f3d6..5667485 100644 --- a/net.c +++ b/net.c @@ -93,6 +93,7 @@ #include "net.h" #include "net/tap.h" #include "net/socket.h" +#include "net/dump.h" #include "net/slirp.h" #include "net/vde.h" #include "monitor.h" @@ -720,110 +721,6 @@ qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); } -typedef struct DumpState { -VLANClientState *pcap_vc; -int fd; -int pcap_caplen; -} DumpState; - -#define PCAP_MAGIC 0xa1b2c3d4 - -struct pcap_file_hdr { -uint32_t magic; -uint16_t version_major; -uint16_t version_minor; -int32_t thiszone; -uint32_t sigfigs; -uint32_t snaplen; -uint32_t linktype; -}; - -struct pcap_sf_pkthdr { -struct { -int32_t tv_sec; -int32_t tv_usec; -} ts; -uint32_t caplen; -uint32_t len; -}; - -static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -DumpState *s = vc->opaque; -struct pcap_sf_pkthdr hdr; -int64_t ts; -int caplen; - -/* Early return in case of previous error. */ -if (s->fd < 0) { -return size; -} - -ts = muldiv64(qemu_get_clock(vm_clock), 100, get_ticks_per_sec()); -caplen = size > s->pcap_caplen ? s->pcap_caplen : size; - -hdr.ts.tv_sec = ts / 100; -hdr.ts.tv_usec = ts % 100; -hdr.caplen = caplen; -hdr.len = size; -if (write(s->fd, &hdr, sizeof(hdr)) != sizeof(hdr) || -write(s->fd, buf, caplen) != caplen) { -qemu_log("-net dump write error - stop dump\n"); -close(s->fd); -s->fd = -1; -} - -return size; -} - -static void net_dump_cleanup(VLANClientState *vc) -{ -DumpState *s = vc->opaque; - -close(s->fd); -qemu_free(s); -} - -static int net_dump_init(VLANState *vlan, const char *device, - const char *name, const char *filename, int len) -{ -struct pcap_file_hdr hdr; -DumpState *s; - -s = qemu_malloc(sizeof(DumpState)); - -s->fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644); -if (s->fd < 0) { -qemu_error("-net dump: can't open %s\n", filename); -return -1; -} - -s->pcap_caplen = len; - -hdr.magic = PCAP_MAGIC; -hdr.version_major = 2; -hdr.version_minor = 4; -hdr.thiszone = 0; -hdr.sigfigs = 0; -hdr.snaplen = s->pcap_caplen; -hdr.linktype = 1; - -if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { -qemu_error("-net dump write error: %s\n", strerror(errno)); -close(s->fd); -qemu_free(s); -return -1; -} - -s->pcap_vc = qemu_new_vlan_client(NET_CLIENT_TYPE_DUMP, - vlan, NULL, device, name, NULL, - dump_receive, NULL, NULL, - net_dump_cleanup, s); -snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str), - "dump to %s (len=%d)", filename, len); -return 0; -} - /* find or alloc a new VLAN */ VLANState *qemu_find_vlan(int id, int allocate) { @@ -1003,28 +900,6 @@ static int net_init_nic(QemuOpts *opts, return idx; } -static int net_init_dump(QemuOpts *opts, - Monitor *mon, - const char *name, - VLANState *vlan) -{ -int len; -const char *file; -char def_file[128]; - -assert(vlan); - -file = qemu_opt_get(opts, "file"); -if (!file) { -snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id); -file = def_file; -} - -len = qemu_opt_get_size(opts, "len", 65536); - -return net_dump_init(vlan, "dump", name, file, len); -} - #define NET_COMMON_PARAMS_DESC \ { \ .name = "type",\ diff --git a/net/dump.c b/net/dump.c new file mode 1
[Qemu-devel] [PATCH 01/44] net: move slirp code from net.c to net/slirp.c
Signed-off-by: Mark McLoughlin --- Makefile|1 + monitor.c |1 + net.c | 718 +--- net.h |8 +- net/slirp.c | 752 +++ net/slirp.h | 51 vl.c|1 + 7 files changed, 814 insertions(+), 718 deletions(-) create mode 100644 net/slirp.c create mode 100644 net/slirp.h diff --git a/Makefile b/Makefile index 63a7128..45362fa 100644 --- a/Makefile +++ b/Makefile @@ -106,6 +106,7 @@ net-nested-$(CONFIG_WIN32) += tap-win32.o net-nested-$(CONFIG_BSD) += tap-bsd.o net-nested-$(CONFIG_SOLARIS) += tap-solaris.o net-nested-$(CONFIG_AIX) += tap-aix.o +net-nested-$(CONFIG_SLIRP) += slirp.o net-obj-y += $(addprefix net/, $(net-nested-y)) ## diff --git a/monitor.c b/monitor.c index 3286ba2..fa1561a 100644 --- a/monitor.c +++ b/monitor.c @@ -32,6 +32,7 @@ #include "hw/loader.h" #include "gdbstub.h" #include "net.h" +#include "net/slirp.h" #include "qemu-char.h" #include "sysemu.h" #include "monitor.h" diff --git a/net.c b/net.c index 9ea66e3..9b030a1 100644 --- a/net.c +++ b/net.c @@ -40,9 +40,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -98,6 +96,7 @@ #include "qemu-common.h" #include "net.h" #include "net/tap.h" +#include "net/slirp.h" #include "monitor.h" #include "sysemu.h" #include "qemu-timer.h" @@ -107,15 +106,13 @@ #include "qemu-log.h" #include "qemu-config.h" -#include "slirp/libslirp.h" - static QTAILQ_HEAD(, VLANState) vlans; static QTAILQ_HEAD(, VLANClientState) non_vlan_clients; /***/ /* network device redirectors */ -#if defined(DEBUG_NET) || defined(DEBUG_SLIRP) +#if defined(DEBUG_NET) static void hex_dump(FILE *f, const uint8_t *buf, int size) { int len, i, j, c; @@ -406,7 +403,7 @@ VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque) return NULL; } -static VLANClientState * +VLANClientState * qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, const char *client_str) { @@ -725,597 +722,6 @@ qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); } -#if defined(CONFIG_SLIRP) - -/* slirp network adapter */ - -#define SLIRP_CFG_HOSTFWD 1 -#define SLIRP_CFG_LEGACY 2 - -struct slirp_config_str { -struct slirp_config_str *next; -int flags; -char str[1024]; -int legacy_format; -}; - -typedef struct SlirpState { -QTAILQ_ENTRY(SlirpState) entry; -VLANClientState *vc; -Slirp *slirp; -#ifndef _WIN32 -char smb_dir[128]; -#endif -} SlirpState; - -static struct slirp_config_str *slirp_configs; -const char *legacy_tftp_prefix; -const char *legacy_bootp_filename; -static QTAILQ_HEAD(slirp_stacks, SlirpState) slirp_stacks = -QTAILQ_HEAD_INITIALIZER(slirp_stacks); - -static int slirp_hostfwd(SlirpState *s, const char *redir_str, - int legacy_format); -static int slirp_guestfwd(SlirpState *s, const char *config_str, - int legacy_format); - -#ifndef _WIN32 -static const char *legacy_smb_export; - -static int slirp_smb(SlirpState *s, const char *exported_dir, - struct in_addr vserver_addr); -static void slirp_smb_cleanup(SlirpState *s); -#else -static inline void slirp_smb_cleanup(SlirpState *s) { } -#endif - -int slirp_can_output(void *opaque) -{ -SlirpState *s = opaque; - -return qemu_can_send_packet(s->vc); -} - -void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len) -{ -SlirpState *s = opaque; - -#ifdef DEBUG_SLIRP -printf("slirp output:\n"); -hex_dump(stdout, pkt, pkt_len); -#endif -qemu_send_packet(s->vc, pkt, pkt_len); -} - -static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -SlirpState *s = vc->opaque; - -#ifdef DEBUG_SLIRP -printf("slirp input:\n"); -hex_dump(stdout, buf, size); -#endif -slirp_input(s->slirp, buf, size); -return size; -} - -static void net_slirp_cleanup(VLANClientState *vc) -{ -SlirpState *s = vc->opaque; - -slirp_cleanup(s->slirp); -slirp_smb_cleanup(s); -QTAILQ_REMOVE(&slirp_stacks, s, entry); -qemu_free(s); -} - -static int net_slirp_init(VLANState *vlan, const char *model, - const char *name, int restricted, - const char *vnetwork, const char *vhost, - const char *vhostname, const char *tftp_export, - const char *bootfile, const char *vdhcp_star
[Qemu-devel] [PATCH 06/44] net: remove NICInfo::vc
Since 1cc33683, this field is not set for most devices, so just remove it and its remaining few uses. Signed-off-by: Mark McLoughlin --- hw/dp8393x.c | 10 +- hw/etraxfs_eth.c | 10 +- hw/mcf_fec.c | 10 +- hw/mipsnet.c | 10 +- hw/usb-net.c | 14 +++--- net.h|1 - 6 files changed, 27 insertions(+), 28 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index ae8b16e..5143cc8 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -889,11 +889,11 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ -s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - nic_can_receive, nic_receive, NULL, NULL, - nic_cleanup, s); +s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, + nd->model, nd->name, + nic_can_receive, nic_receive, NULL, NULL, + nic_cleanup, s); qemu_format_nic_info_str(s->vc, nd->macaddr); qemu_register_reset(nic_reset, s); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index ffe7082..2cc2332 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -590,11 +590,11 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth); cpu_register_physical_memory (base, 0x5c, eth->ethregs); - eth->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, -nd->vlan, nd->netdev, -nd->model, nd->name, -eth_can_receive, eth_receive, -NULL, NULL, eth_cleanup, eth); + eth->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, + nd->model, nd->name, + eth_can_receive, eth_receive, + NULL, NULL, eth_cleanup, eth); eth->vc->opaque = eth; eth->vc->link_status_changed = eth_set_link; diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 9f0d0f4..8242c8a 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -462,11 +462,11 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) mcf_fec_writefn, s); cpu_register_physical_memory(base, 0x400, s->mmio_index); -s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - mcf_fec_can_receive, mcf_fec_receive, - NULL, NULL, mcf_fec_cleanup, s); +s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, + nd->model, nd->name, + mcf_fec_can_receive, mcf_fec_receive, + NULL, NULL, mcf_fec_cleanup, s); memcpy(s->macaddr, nd->macaddr, 6); qemu_format_nic_info_str(s->vc, s->macaddr); } diff --git a/hw/mipsnet.c b/hw/mipsnet.c index 65e1d59..67160a4 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -263,11 +263,11 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) s->io_base = base; s->irq = irq; if (nd) { -s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - mipsnet_can_receive, mipsnet_receive, - NULL, NULL, mipsnet_cleanup, s); +s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, + nd->model, nd->name, + mipsnet_can_receive, mipsnet_receive, + NULL, NULL, mipsnet_cleanup, s); } else { s->vc = NULL; } diff --git a/hw/usb-net.c b/hw/usb-net.c index 9c6549c..7b8cc7a 100644 --- a/hw/usb-net
[Qemu-devel] [PATCH 09/44] net: introduce qemu_new_net_client()
A replacement for qemu_new_vlan_client(), using NetClientInfo to replace most arguments. Signed-off-by: Mark McLoughlin --- net.c | 70 +--- net.h |5 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/net.c b/net.c index 599e5b0..355eb87 100644 --- a/net.c +++ b/net.c @@ -248,34 +248,31 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, int iovcnt, void *opaque); -VLANClientState *qemu_new_vlan_client(net_client_type type, - VLANState *vlan, - VLANClientState *peer, - const char *model, - const char *name, - NetCanReceive *can_receive, - NetReceive *receive, - NetReceive *receive_raw, - NetReceiveIOV *receive_iov, - NetCleanup *cleanup, - void *opaque) +VLANClientState *qemu_new_net_client(NetClientInfo *info, + VLANState *vlan, + VLANClientState *peer, + const char *model, + const char *name) { VLANClientState *vc; -vc = qemu_mallocz(sizeof(VLANClientState)); +assert(info->size >= sizeof(VLANClientState)); + +vc = qemu_mallocz(info->size); -vc->type = type; +vc->type = info->type; vc->model = qemu_strdup(model); -if (name) +if (name) { vc->name = qemu_strdup(name); -else +} else { vc->name = assign_name(vc, model); -vc->can_receive = can_receive; -vc->receive = receive; -vc->receive_raw = receive_raw; -vc->receive_iov = receive_iov; -vc->cleanup = cleanup; -vc->opaque = opaque; +} +vc->can_receive = info->can_receive; +vc->receive = info->receive; +vc->receive_raw = info->receive_raw; +vc->receive_iov = info->receive_iov; +vc->cleanup = info->cleanup; +vc->link_status_changed = info->link_status_changed; if (vlan) { assert(!peer); @@ -296,6 +293,37 @@ VLANClientState *qemu_new_vlan_client(net_client_type type, return vc; } +VLANClientState *qemu_new_vlan_client(net_client_type type, + VLANState *vlan, + VLANClientState *peer, + const char *model, + const char *name, + NetCanReceive *can_receive, + NetReceive *receive, + NetReceive *receive_raw, + NetReceiveIOV *receive_iov, + NetCleanup *cleanup, + void *opaque) +{ +VLANClientState *ret; +NetClientInfo info; + +info.type = type; +info.size = sizeof(VLANClientState); +info.can_receive = can_receive; +info.receive = receive; +info.receive_raw = receive_raw; +info.receive_iov = receive_iov; +info.cleanup = cleanup; +info.link_status_changed = NULL; + +ret = qemu_new_net_client(&info, vlan, peer, model, name); + +ret->opaque = opaque; + +return ret; +} + void qemu_del_vlan_client(VLANClientState *vc) { if (vc->vlan) { diff --git a/net.h b/net.h index 56c5849..71a9a44 100644 --- a/net.h +++ b/net.h @@ -85,6 +85,11 @@ struct VLANState { VLANState *qemu_find_vlan(int id, int allocate); VLANClientState *qemu_find_netdev(const char *id); +VLANClientState *qemu_new_net_client(NetClientInfo *info, + VLANState *vlan, + VLANClientState *peer, + const char *model, + const char *name); VLANClientState *qemu_new_vlan_client(net_client_type type, VLANState *vlan, VLANClientState *peer, -- 1.6.5.2
[Qemu-devel] [PATCH 17/44] net: introduce NICState and qemu_new_nic()
Common state for all NICs. The opaque member will replace the opaque member in VLANClientState since only NICs need it. The conf member will allow us to iterate over NICs, access the MAC addr for the NIC and send a packet from each NIC in qemu_announce_self(). Signed-off-by: Mark McLoughlin --- net.c | 21 + net.h | 11 +++ 2 files changed, 32 insertions(+), 0 deletions(-) diff --git a/net.c b/net.c index 355eb87..7195827 100644 --- a/net.c +++ b/net.c @@ -293,6 +293,27 @@ VLANClientState *qemu_new_net_client(NetClientInfo *info, return vc; } +NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, + void *opaque) +{ +VLANClientState *nc; +NICState *nic; + +assert(info->type == NET_CLIENT_TYPE_NIC); +assert(info->size >= sizeof(NICState)); + +nc = qemu_new_net_client(info, conf->vlan, conf->peer, model, name); + +nic = DO_UPCAST(NICState, nc, nc); +nic->conf = conf; +nic->opaque = opaque; + +return nic; +} + VLANClientState *qemu_new_vlan_client(net_client_type type, VLANState *vlan, VLANClientState *peer, diff --git a/net.h b/net.h index 71a9a44..4de20de 100644 --- a/net.h +++ b/net.h @@ -75,6 +75,12 @@ struct VLANClientState { unsigned receive_disabled : 1; }; +typedef struct NICState { +VLANClientState nc; +NICConf *conf; +void *opaque; +} NICState; + struct VLANState { int id; QTAILQ_HEAD(, VLANClientState) clients; @@ -90,6 +96,11 @@ VLANClientState *qemu_new_net_client(NetClientInfo *info, VLANClientState *peer, const char *model, const char *name); +NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, + void *opaque); VLANClientState *qemu_new_vlan_client(net_client_type type, VLANState *vlan, VLANClientState *peer, -- 1.6.5.2
[Qemu-devel] [PATCH 10/44] qdev: move DO_UPCAST() into osdep.h
Nothing qdev specific about this, make it available throughtout. Signed-off-by: Mark McLoughlin --- hw/qdev.h | 10 -- osdep.h | 10 ++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/qdev.h b/hw/qdev.h index 41642ee..8d53754 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -154,16 +154,6 @@ CharDriverState *qdev_init_chardev(DeviceState *dev); BusState *qdev_get_parent_bus(DeviceState *dev); -/* Convert from a base type to a parent type, with compile time checking. */ -#ifdef __GNUC__ -#define DO_UPCAST(type, field, dev) ( __extension__ ( { \ -char __attribute__((unused)) offset_must_be_zero[ \ --offsetof(type, field)]; \ -container_of(dev, type, field);})) -#else -#define DO_UPCAST(type, field, dev) container_of(dev, type, field) -#endif - /*** BUS API. ***/ void qbus_create_inplace(BusState *bus, BusInfo *info, diff --git a/osdep.h b/osdep.h index 4b4aad4..75b5816 100644 --- a/osdep.h +++ b/osdep.h @@ -37,6 +37,16 @@ (type *) ((char *) __mptr - offsetof(type, member));}) #endif +/* Convert from a base type to a parent type, with compile time checking. */ +#ifdef __GNUC__ +#define DO_UPCAST(type, field, dev) ( __extension__ ( { \ +char __attribute__((unused)) offset_must_be_zero[ \ +-offsetof(type, field)]; \ +container_of(dev, type, field);})) +#else +#define DO_UPCAST(type, field, dev) container_of(dev, type, field) +#endif + #define typeof_field(type, field) typeof(((type *)0)->field) #define type_check(t1,t2) ((t1*)0 - (t2*)0) -- 1.6.5.2
[Qemu-devel] [PATCH 11/44] net: convert tap to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/tap.c | 82 +--- 1 files changed, 45 insertions(+), 37 deletions(-) diff --git a/net/tap.c b/net/tap.c index b2e5908..d34feec 100644 --- a/net/tap.c +++ b/net/tap.c @@ -47,7 +47,7 @@ #define TAP_BUFSIZE (4096 + 65536) typedef struct TAPState { -VLANClientState *vc; +VLANClientState nc; int fd; char down_script[1024]; char down_script_arg[128]; @@ -92,7 +92,7 @@ static void tap_writable(void *opaque) tap_write_poll(s, 0); -qemu_flush_queued_packets(s->vc); +qemu_flush_queued_packets(&s->nc); } static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt) @@ -111,10 +111,10 @@ static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt return len; } -static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, +static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov, int iovcnt) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); const struct iovec *iovp = iov; struct iovec iov_copy[iovcnt + 1]; struct virtio_net_hdr hdr = { 0, }; @@ -130,9 +130,9 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, return tap_write_packet(s, iovp, iovcnt); } -static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t size) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[2]; int iovcnt = 0; struct virtio_net_hdr hdr = { 0, }; @@ -150,13 +150,13 @@ static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t s return tap_write_packet(s, iov, iovcnt); } -static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); struct iovec iov[1]; if (s->has_vnet_hdr && !s->using_vnet_hdr) { -return tap_receive_raw(vc, buf, size); +return tap_receive_raw(nc, buf, size); } iov[0].iov_base = (char *)buf; @@ -169,7 +169,7 @@ static int tap_can_send(void *opaque) { TAPState *s = opaque; -return qemu_can_send_packet(s->vc); +return qemu_can_send_packet(&s->nc); } #ifndef __sun__ @@ -179,9 +179,9 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) } #endif -static void tap_send_completed(VLANClientState *vc, ssize_t len) +static void tap_send_completed(VLANClientState *nc, ssize_t len) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); tap_read_poll(s, 1); } @@ -203,56 +203,56 @@ static void tap_send(void *opaque) size -= sizeof(struct virtio_net_hdr); } -size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed); +size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed); if (size == 0) { tap_read_poll(s, 0); } -} while (size > 0 && qemu_can_send_packet(s->vc)); +} while (size > 0 && qemu_can_send_packet(&s->nc)); } -int tap_has_ufo(VLANClientState *vc) +int tap_has_ufo(VLANClientState *nc) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); -assert(vc->type == NET_CLIENT_TYPE_TAP); +assert(nc->type == NET_CLIENT_TYPE_TAP); return s->has_ufo; } -int tap_has_vnet_hdr(VLANClientState *vc) +int tap_has_vnet_hdr(VLANClientState *nc) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); -assert(vc->type == NET_CLIENT_TYPE_TAP); +assert(nc->type == NET_CLIENT_TYPE_TAP); return s->has_vnet_hdr; } -void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); using_vnet_hdr = using_vnet_hdr != 0; -assert(vc->type == NET_CLIENT_TYPE_TAP); +assert(nc->type == NET_CLIENT_TYPE_TAP); assert(s->has_vnet_hdr == using_vnet_hdr); s->using_vnet_hdr = using_vnet_hdr; } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, +void tap_set_offload(VLANClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); return tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo); } -static void tap_cleanup(VLANClientState *vc) +static void tap_cleanup(VLANClientState *nc) { -TAPState *s = vc->opaque
[Qemu-devel] [PATCH 28/44] net: convert mipsnet to NICState
Signed-off-by: Mark McLoughlin --- hw/mipsnet.c | 45 +++-- 1 files changed, 27 insertions(+), 18 deletions(-) diff --git a/hw/mipsnet.c b/hw/mipsnet.c index 67160a4..a066f63 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -35,7 +35,8 @@ typedef struct MIPSnetState { uint8_t tx_buffer[MAX_ETH_FRAME_SIZE]; int io_base; qemu_irq irq; -VLANClientState *vc; +NICState *nic; +NICConf conf; } MIPSnetState; static void mipsnet_reset(MIPSnetState *s) @@ -66,23 +67,23 @@ static int mipsnet_buffer_full(MIPSnetState *s) return 0; } -static int mipsnet_can_receive(VLANClientState *vc) +static int mipsnet_can_receive(VLANClientState *nc) { -MIPSnetState *s = vc->opaque; +MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (s->busy) return 0; return !mipsnet_buffer_full(s); } -static ssize_t mipsnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t mipsnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -MIPSnetState *s = vc->opaque; +MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; #ifdef DEBUG_MIPSNET_RECEIVE printf("mipsnet: receiving len=%d\n", size); #endif -if (!mipsnet_can_receive(vc)) +if (!mipsnet_can_receive(nc)) return -1; s->busy = 1; @@ -183,7 +184,7 @@ static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val) #ifdef DEBUG_MIPSNET_SEND printf("mipsnet: sending len=%d\n", s->tx_count); #endif -qemu_send_packet(s->vc, s->tx_buffer, s->tx_count); +qemu_send_packet(&s->nic->nc, s->tx_buffer, s->tx_count); s->tx_count = s->tx_written = 0; s->intctl |= MIPSNET_INTCTL_TXDONE; s->busy = 1; @@ -234,9 +235,9 @@ static int mipsnet_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void mipsnet_cleanup(VLANClientState *vc) +static void mipsnet_cleanup(VLANClientState *nc) { -MIPSnetState *s = vc->opaque; +MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque; unregister_savevm("mipsnet", s); @@ -245,6 +246,14 @@ static void mipsnet_cleanup(VLANClientState *vc) qemu_free(s); } +static NetClientInfo net_mipsnet_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = mipsnet_can_receive, +.receive = mipsnet_receive, +.cleanup = mipsnet_cleanup, +}; + void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) { MIPSnetState *s; @@ -262,17 +271,17 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) s->io_base = base; s->irq = irq; + if (nd) { -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - mipsnet_can_receive, mipsnet_receive, - NULL, NULL, mipsnet_cleanup, s); -} else { -s->vc = NULL; -} +memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr)); +s->conf.vlan = nd->vlan; +s->conf.peer = nd->netdev; -qemu_format_nic_info_str(s->vc, nd->macaddr); +s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf, + nd->model, nd->name, s); + +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); +} mipsnet_reset(s); register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s); -- 1.6.5.2
[Qemu-devel] [PATCH 34/44] net: move parse_macaddr() to net/util.[ch]
Signed-off-by: Mark McLoughlin --- Makefile |2 +- net.c | 35 ++- net/util.c | 60 net/util.h | 32 4 files changed, 95 insertions(+), 34 deletions(-) create mode 100644 net/util.c create mode 100644 net/util.h diff --git a/Makefile b/Makefile index 6ed4bf8..b18bba9 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,7 @@ block-nested-$(CONFIG_CURL) += curl.o block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o -net-nested-y = queue.o checksum.o +net-nested-y = queue.o checksum.o util.o net-nested-y += socket.o net-nested-y += dump.o net-nested-$(CONFIG_POSIX) += tap.o diff --git a/net.c b/net.c index 7195827..cca008a 100644 --- a/net.c +++ b/net.c @@ -30,6 +30,7 @@ #include "net/dump.h" #include "net/slirp.h" #include "net/vde.h" +#include "net/util.h" #include "monitor.h" #include "sysemu.h" #include "qemu-common.h" @@ -69,38 +70,6 @@ static void hex_dump(FILE *f, const uint8_t *buf, int size) } #endif -static int parse_macaddr(uint8_t *macaddr, const char *p) -{ -int i; -char *last_char; -long int offset; - -errno = 0; -offset = strtol(p, &last_char, 0); -if (0 == errno && '\0' == *last_char && -offset >= 0 && offset <= 0xFF) { -macaddr[3] = (offset & 0xFF) >> 16; -macaddr[4] = (offset & 0xFF00) >> 8; -macaddr[5] = offset & 0xFF; -return 0; -} else { -for(i = 0; i < 6; i++) { -macaddr[i] = strtol(p, (char **)&p, 16); -if (i == 5) { -if (*p != '\0') -return -1; -} else { -if (*p != ':' && *p != '-') -return -1; -p++; -} -} -return 0; -} - -return -1; -} - static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { const char *p, *p1; @@ -858,7 +827,7 @@ static int net_init_nic(QemuOpts *opts, nd->macaddr[5] = 0x56 + idx; if (qemu_opt_get(opts, "macaddr") && -parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) { +net_parse_macaddr(nd->macaddr, qemu_opt_get(opts, "macaddr")) < 0) { qemu_error("invalid syntax for ethernet address\n"); return -1; } diff --git a/net/util.c b/net/util.c new file mode 100644 index 000..1e9afbc --- /dev/null +++ b/net/util.c @@ -0,0 +1,60 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "net/util.h" +#include +#include + +int net_parse_macaddr(uint8_t *macaddr, const char *p) +{ +int i; +char *last_char; +long int offset; + +errno = 0; +offset = strtol(p, &last_char, 0); +if (errno == 0 && *last_char == '\0' && +offset >= 0 && offset <= 0xFF) { +macaddr[3] = (offset & 0xFF) >> 16; +macaddr[4] = (offset & 0xFF00) >> 8; +macaddr[5] = offset & 0xFF; +return 0; +} + +for (i = 0; i < 6; i++) { +macaddr[i] = strtol(p, (char **)&p, 16); +if (i == 5) { +if (*p != '\0') { +return -1; +} +} else { +if (*p != ':' && *p != '-') { +return -1; +} +p++; +} +} + +return 0; +} diff --git a/net/util.h b/net/util.h new file mode 100644 index 000..10c7da9 -
[Qemu-devel] [PATCH 35/44] net: convert xen to NICState
Signed-off-by: Mark McLoughlin --- hw/xen_nic.c | 46 +- 1 files changed, 29 insertions(+), 17 deletions(-) diff --git a/hw/xen_nic.c b/hw/xen_nic.c index bcf161c..08055b8 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -41,6 +41,7 @@ #include "hw.h" #include "net.h" #include "net/checksum.h" +#include "net/util.h" #include "qemu-char.h" #include "xen_backend.h" @@ -56,7 +57,8 @@ struct XenNetDev { struct netif_rx_sring *rxs; netif_tx_back_ring_t tx_ring; netif_rx_back_ring_t rx_ring; -VLANClientState *vs; +NICConf conf; +NICState *nic; }; /* - */ @@ -179,9 +181,9 @@ static void net_tx_packets(struct XenNetDev *netdev) tmpbuf = qemu_malloc(XC_PAGE_SIZE); memcpy(tmpbuf, page + txreq.offset, txreq.size); net_checksum_calculate(tmpbuf, txreq.size); -qemu_send_packet(netdev->vs, tmpbuf, txreq.size); +qemu_send_packet(&netdev->nic->nc, tmpbuf, txreq.size); } else { -qemu_send_packet(netdev->vs, page + txreq.offset, txreq.size); +qemu_send_packet(&netdev->nic->nc, page + txreq.offset, txreq.size); } xc_gnttab_munmap(netdev->xendev.gnttabdev, page, 1); net_tx_response(netdev, &txreq, NETIF_RSP_OKAY); @@ -223,9 +225,9 @@ static void net_rx_response(struct XenNetDev *netdev, #define NET_IP_ALIGN 2 -static int net_rx_ok(VLANClientState *vc) +static int net_rx_ok(VLANClientState *nc) { -struct XenNetDev *netdev = vc->opaque; +struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque; RING_IDX rc, rp; if (netdev->xendev.be_state != XenbusStateConnected) @@ -243,9 +245,9 @@ static int net_rx_ok(VLANClientState *vc) return 1; } -static ssize_t net_rx_packet(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t net_rx_packet(VLANClientState *nc, const uint8_t *buf, size_t size) { -struct XenNetDev *netdev = vc->opaque; +struct XenNetDev *netdev = DO_UPCAST(NICState, nc, nc)->opaque; netif_rx_request_t rxreq; RING_IDX rc, rp; void *page; @@ -288,10 +290,16 @@ static ssize_t net_rx_packet(VLANClientState *vc, const uint8_t *buf, size_t siz /* - */ +static NetClientInfo net_xen_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = net_rx_ok, +.receive = net_rx_packet, +}; + static int net_init(struct XenDevice *xendev) { struct XenNetDev *netdev = container_of(xendev, struct XenNetDev, xendev); -VLANState *vlan; /* read xenstore entries */ if (netdev->mac == NULL) @@ -301,12 +309,16 @@ static int net_init(struct XenDevice *xendev) if (netdev->mac == NULL) return -1; -vlan = qemu_find_vlan(netdev->xendev.dev, 1); -netdev->vs = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - vlan, NULL, "xen", NULL, - net_rx_ok, net_rx_packet, NULL, NULL, - NULL, netdev); -snprintf(netdev->vs->info_str, sizeof(netdev->vs->info_str), +if (net_parse_macaddr(netdev->conf.macaddr.a, netdev->mac) < 0) +return -1; + +netdev->conf.vlan = qemu_find_vlan(netdev->xendev.dev, 1); +netdev->conf.peer = NULL; + +netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, + "xen", NULL, netdev); + +snprintf(netdev->nic->nc.info_str, sizeof(netdev->nic->nc.info_str), "nic: xenbus vif macaddr=%s", netdev->mac); /* fill info */ @@ -376,9 +388,9 @@ static void net_disconnect(struct XenDevice *xendev) xc_gnttab_munmap(netdev->xendev.gnttabdev, netdev->rxs, 1); netdev->rxs = NULL; } -if (netdev->vs) { -qemu_del_vlan_client(netdev->vs); -netdev->vs = NULL; +if (netdev->nic) { +qemu_del_vlan_client(&netdev->nic->nc); +netdev->nic = NULL; } } -- 1.6.5.2
[Qemu-devel] [PATCH 22/44] net: convert pcnet to NICState
Signed-off-by: Mark McLoughlin --- hw/lance.c | 14 +++--- hw/pcnet.c | 43 +++ hw/pcnet.h |7 --- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/hw/lance.c b/hw/lance.c index 0a96644..98033a4 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -92,14 +92,22 @@ static CPUWriteMemoryFunc * const lance_mem_write[3] = { NULL, }; -static void lance_cleanup(VLANClientState *vc) +static void lance_cleanup(VLANClientState *nc) { -PCNetState *d = vc->opaque; +PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; vmstate_unregister(&vmstate_pcnet, d); pcnet_common_cleanup(d); } +static NetClientInfo net_lance_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = pcnet_can_receive, +.receive = pcnet_receive, +.cleanup = lance_cleanup, +}; + static int lance_init(SysBusDevice *dev) { SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev); @@ -118,7 +126,7 @@ static int lance_init(SysBusDevice *dev) s->phys_mem_write = ledma_memory_write; vmstate_register(-1, &vmstate_pcnet, d); -return pcnet_common_init(&dev->qdev, s, lance_cleanup); +return pcnet_common_init(&dev->qdev, s, &net_lance_info); } static void lance_reset(DeviceState *dev) diff --git a/hw/pcnet.c b/hw/pcnet.c index ee3db09..195c825 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -1028,9 +1028,9 @@ static int pcnet_tdte_poll(PCNetState *s) return !!(CSR_CXST(s) & 0x8000); } -static int pcnet_can_receive(VLANClientState *vc) +int pcnet_can_receive(VLANClientState *nc) { -PCNetState *s = vc->opaque; +PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (CSR_STOP(s) || CSR_SPND(s)) return 0; @@ -1039,9 +1039,9 @@ static int pcnet_can_receive(VLANClientState *vc) #define MIN_BUF_SIZE 60 -static ssize_t pcnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size_) +ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) { -PCNetState *s = vc->opaque; +PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; int is_padr = 0, is_bcast = 0, is_ladr = 0; uint8_t buf1[60]; int remaining; @@ -1268,11 +1268,11 @@ static void pcnet_transmit(PCNetState *s) if (BCR_SWSTYLE(s) == 1) add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS); s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC; -pcnet_receive(s->vc, s->buffer, s->xmit_pos); +pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos); s->looptest = 0; } else -if (s->vc) -qemu_send_packet(s->vc, s->buffer, s->xmit_pos); +if (s->nic) +qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos); s->csr[0] &= ~0x0008; /* clear TDMD */ s->csr[4] |= 0x0004;/* set TXSTRT */ @@ -1888,21 +1888,16 @@ static const VMStateDescription vmstate_pci_pcnet = { void pcnet_common_cleanup(PCNetState *d) { -d->vc = NULL; +d->nic = NULL; } -int pcnet_common_init(DeviceState *dev, PCNetState *s, - NetCleanup *cleanup) +int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) { s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s); qemu_macaddr_default_if_unset(&s->conf.macaddr); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->info->name, dev->id, - pcnet_can_receive, pcnet_receive, NULL, NULL, - cleanup, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); return 0; } @@ -1945,9 +1940,9 @@ static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, cpu_physical_memory_read(addr, buf, len); } -static void pci_pcnet_cleanup(VLANClientState *vc) +static void pci_pcnet_cleanup(VLANClientState *nc) { -PCNetState *d = vc->opaque; +PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; pcnet_common_cleanup(d); } @@ -1960,10 +1955,18 @@ static int pci_pcnet_uninit(PCIDevice *dev) vmstate_unregister(&vmstate_pci_pcnet, d); qemu_del_timer(d->state.poll_timer); qemu_free_timer(d->state.poll_timer); -qemu_del_vlan_client(d->state.vc); +qemu_del_vlan_client(&d->state.nic->nc); return 0; } +static NetClientInfo net_pci_pcnet_info = { +.type = NET_CLIENT_TYPE_NIC, +
[Qemu-devel] [PATCH 12/44] net: convert tap-win32 to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/tap-win32.c | 39 +++ 1 files changed, 23 insertions(+), 16 deletions(-) diff --git a/net/tap-win32.c b/net/tap-win32.c index ea66471..ef63782 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -630,25 +630,24 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, // typedef struct TAPState { - VLANClientState *vc; + VLANClientState nc; tap_win32_overlapped_t *handle; } TAPState; -static void tap_cleanup(VLANClientState *vc) +static void tap_cleanup(VLANClientState *nc) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); qemu_del_wait_object(s->handle->tap_semaphore, NULL, NULL); /* FIXME: need to kill thread and close file handle: tap_win32_close(s); */ -qemu_free(s); } -static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -TAPState *s = vc->opaque; +TAPState *s = DO_UPCAST(TAPState, nc, nc); return tap_win32_write(s->handle, buf, size); } @@ -662,33 +661,41 @@ static void tap_win32_send(void *opaque) size = tap_win32_read(s->handle, &buf, max_size); if (size > 0) { -qemu_send_packet(s->vc, buf, size); +qemu_send_packet(&s->nc, buf, size); tap_win32_free_buffer(s->handle, buf); } } +static NetClientInfo net_tap_win32_info = { +.type = NET_CLIENT_TYPE_TAP, +.size = sizeof(TAPState), +.receive = tap_receive, +.cleanup = tap_cleanup, +}; + static int tap_win32_init(VLANState *vlan, const char *model, const char *name, const char *ifname) { +VLANClientState *nc; TAPState *s; +tap_win32_overlapped_t *handle; -s = qemu_mallocz(sizeof(TAPState)); -if (!s) -return -1; -if (tap_win32_open(&s->handle, ifname) < 0) { +if (tap_win32_open(&handle, ifname) < 0) { printf("tap: Could not open '%s'\n", ifname); return -1; } -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP, - vlan, NULL, model, name, - NULL, tap_receive, - NULL, NULL, tap_cleanup, s); +nc = qemu_new_net_client(&net_tap_win32_info, vlan, NULL, model, name); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), +snprintf(s->nc.info_str, sizeof(s->nc.info_str), "tap: ifname=%s", ifname); +s = DO_UPCAST(TAPState, nc, nc); + +s->handle = handle; + qemu_add_wait_object(s->handle->tap_semaphore, tap_win32_send, s); + return 0; } -- 1.6.5.2
[Qemu-devel] [PATCH 21/44] net: convert ne2000 to NICState
Signed-off-by: Mark McLoughlin --- hw/ne2000-isa.c | 22 ++ hw/ne2000.c | 35 +-- hw/ne2000.h |2 +- 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/hw/ne2000-isa.c b/hw/ne2000-isa.c index 729e8e2..0260f84 100644 --- a/hw/ne2000-isa.c +++ b/hw/ne2000-isa.c @@ -35,13 +35,21 @@ typedef struct ISANE2000State { NE2000State ne2000; } ISANE2000State; -static void isa_ne2000_cleanup(VLANClientState *vc) +static void isa_ne2000_cleanup(VLANClientState *nc) { -NE2000State *s = vc->opaque; +NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_ne2000_isa_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = ne2000_can_receive, +.receive = ne2000_receive, +.cleanup = isa_ne2000_cleanup, +}; + static int isa_ne2000_initfn(ISADevice *dev) { ISANE2000State *isa = DO_UPCAST(ISANE2000State, dev, dev); @@ -63,11 +71,9 @@ static int isa_ne2000_initfn(ISADevice *dev) qemu_macaddr_default_if_unset(&s->c.macaddr); ne2000_reset(s); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, s->c.vlan, s->c.peer, - dev->qdev.info->name, dev->qdev.id, - ne2000_can_receive, ne2000_receive, NULL, - NULL, isa_ne2000_cleanup, s); -qemu_format_nic_info_str(s->vc, s->c.macaddr.a); +s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->c.macaddr.a); vmstate_register(-1, &vmstate_ne2000, s); return 0; diff --git a/hw/ne2000.c b/hw/ne2000.c index 63efc3a..0be189a 100644 --- a/hw/ne2000.c +++ b/hw/ne2000.c @@ -188,9 +188,9 @@ static int ne2000_buffer_full(NE2000State *s) return 0; } -int ne2000_can_receive(VLANClientState *vc) +int ne2000_can_receive(VLANClientState *nc) { -NE2000State *s = vc->opaque; +NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; if (s->cmd & E8390_STOP) return 1; @@ -199,9 +199,9 @@ int ne2000_can_receive(VLANClientState *vc) #define MIN_BUF_SIZE 60 -ssize_t ne2000_receive(VLANClientState *vc, const uint8_t *buf, size_t size_) +ssize_t ne2000_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) { -NE2000State *s = vc->opaque; +NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; int size = size_; uint8_t *p; unsigned int total_len, next, avail, len, index, mcast_idx; @@ -323,7 +323,7 @@ void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) index -= NE2000_PMEM_SIZE; /* fail safe: check range on the transmitted length */ if (index + s->tcnt <= NE2000_PMEM_END) { -qemu_send_packet(s->vc, s->mem + index, s->tcnt); +qemu_send_packet(&s->nic->nc, s->mem + index, s->tcnt); } /* signal end of transfer */ s->tsr = ENTSR_PTX; @@ -698,13 +698,21 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); } -static void ne2000_cleanup(VLANClientState *vc) +static void ne2000_cleanup(VLANClientState *nc) { -NE2000State *s = vc->opaque; +NE2000State *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_ne2000_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = ne2000_can_receive, +.receive = ne2000_receive, +.cleanup = ne2000_cleanup, +}; + static int pci_ne2000_init(PCIDevice *pci_dev) { PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev); @@ -725,11 +733,10 @@ static int pci_ne2000_init(PCIDevice *pci_dev) qemu_macaddr_default_if_unset(&s->c.macaddr); ne2000_reset(s); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, s->c.vlan, s->c.peer, - pci_dev->qdev.info->name, pci_dev->qdev.id, - ne2000_can_receive, ne2000_receive, NULL, - NULL, ne2000_cleanup, s); -qemu_format_nic_info_str(s->vc, s->c.macaddr.a); + +s->nic = qemu_new_nic(&net_ne2000_info, &s->c, + pci_dev->qdev.info->name, pci_dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->c.macaddr.a); if (!pci_dev->qdev.hotplugged) { static int loaded = 0; @@ -749,7 +756,7 @@ static int pci_ne2000_exit(PCIDevice *pci_dev) NE2000State *s = &d->ne2000; vmstate_unregister(&vm
[Qemu-devel] [PATCH 07/44] net: remove NICInfo::private
Was used by hot-unplug, but not anymore. Signed-off-by: Mark McLoughlin --- net.h |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/net.h b/net.h index bc8392b..9ffcfe3 100644 --- a/net.h +++ b/net.h @@ -124,7 +124,6 @@ struct NICInfo { char *devaddr; VLANState *vlan; VLANClientState *netdev; -void *private; int used; int bootable; int nvectors; -- 1.6.5.2
[Qemu-devel] [PATCH 05/44] net: clean up includes in net.c
This is probably a little drastic, but the includes in this file are now totally out of control when compared with what includes are actually needed. This may break the build on e.g. *BSD, but it will be easily fixed by re-instating an include. Signed-off-by: Mark McLoughlin --- net.c | 74 +--- 1 files changed, 2 insertions(+), 72 deletions(-) diff --git a/net.c b/net.c index 5667485..599e5b0 100644 --- a/net.c +++ b/net.c @@ -21,76 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include -#include -#include -#include -#include -#include -#include - -/* Needed early for CONFIG_BSD etc. */ -#include "config-host.h" - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_BSD -#include -#if defined(__FreeBSD__) || defined(__DragonFly__) -#include -#else -#include -#endif -#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) -#include -#else -#ifdef __linux__ -#include -#include -#include - -/* For the benefit of older linux systems which don't supply it, - we use a local copy of hpet.h. */ -/* #include */ -#include "hpet.h" - -#include -#include -#endif -#ifdef __sun__ -#include -#include -#include -#include -#include -#include -#include -#include // must come after ip.h -#include -#include -#include -#include -#include -#endif -#endif -#endif +#include "net.h" -#if defined(__OpenBSD__) -#include -#endif +#include "config-host.h" -#include "qemu-common.h" -#include "net.h" #include "net/tap.h" #include "net/socket.h" #include "net/dump.h" @@ -98,12 +32,8 @@ #include "net/vde.h" #include "monitor.h" #include "sysemu.h" -#include "qemu-timer.h" -#include "qemu-char.h" -#include "audio/audio.h" +#include "qemu-common.h" #include "qemu_socket.h" -#include "qemu-log.h" -#include "qemu-config.h" static QTAILQ_HEAD(, VLANState) vlans; static QTAILQ_HEAD(, VLANClientState) non_vlan_clients; -- 1.6.5.2
[Qemu-devel] [PATCH 13/44] net: convert slirp to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/slirp.c | 61 +++--- 1 files changed, 37 insertions(+), 24 deletions(-) diff --git a/net/slirp.c b/net/slirp.c index d6d5772..3f91c4b 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -64,8 +64,8 @@ struct slirp_config_str { }; typedef struct SlirpState { +VLANClientState nc; QTAILQ_ENTRY(SlirpState) entry; -VLANClientState *vc; Slirp *slirp; #ifndef _WIN32 char smb_dir[128]; @@ -97,35 +97,41 @@ int slirp_can_output(void *opaque) { SlirpState *s = opaque; -return qemu_can_send_packet(s->vc); +return qemu_can_send_packet(&s->nc); } void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len) { SlirpState *s = opaque; -qemu_send_packet(s->vc, pkt, pkt_len); +qemu_send_packet(&s->nc, pkt, pkt_len); } -static ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t net_slirp_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -SlirpState *s = vc->opaque; +SlirpState *s = DO_UPCAST(SlirpState, nc, nc); slirp_input(s->slirp, buf, size); return size; } -static void net_slirp_cleanup(VLANClientState *vc) +static void net_slirp_cleanup(VLANClientState *nc) { -SlirpState *s = vc->opaque; +SlirpState *s = DO_UPCAST(SlirpState, nc, nc); slirp_cleanup(s->slirp); slirp_smb_cleanup(s); QTAILQ_REMOVE(&slirp_stacks, s, entry); -qemu_free(s); } +static NetClientInfo net_slirp_info = { +.type = NET_CLIENT_TYPE_SLIRP, +.size = sizeof(SlirpState), +.receive = net_slirp_receive, +.cleanup = net_slirp_cleanup, +}; + static int net_slirp_init(VLANState *vlan, const char *model, const char *name, int restricted, const char *vnetwork, const char *vhost, @@ -143,6 +149,7 @@ static int net_slirp_init(VLANState *vlan, const char *model, #ifndef _WIN32 struct in_addr smbsrv = { .s_addr = 0 }; #endif +VLANClientState *nc; SlirpState *s; char buf[20]; uint32_t addr; @@ -228,7 +235,13 @@ static int net_slirp_init(VLANState *vlan, const char *model, } #endif -s = qemu_mallocz(sizeof(SlirpState)); +nc = qemu_new_net_client(&net_slirp_info, vlan, NULL, model, name); + +snprintf(nc->info_str, sizeof(nc->info_str), + "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n'); + +s = DO_UPCAST(SlirpState, nc, nc); + s->slirp = slirp_init(restricted, net, mask, host, vhostname, tftp_export, bootfile, dhcp, dns, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); @@ -237,11 +250,11 @@ static int net_slirp_init(VLANState *vlan, const char *model, if (config->flags & SLIRP_CFG_HOSTFWD) { if (slirp_hostfwd(s, config->str, config->flags & SLIRP_CFG_LEGACY) < 0) -return -1; +goto error; } else { if (slirp_guestfwd(s, config->str, config->flags & SLIRP_CFG_LEGACY) < 0) -return -1; +goto error; } } #ifndef _WIN32 @@ -250,34 +263,32 @@ static int net_slirp_init(VLANState *vlan, const char *model, } if (smb_export) { if (slirp_smb(s, smb_export, smbsrv) < 0) -return -1; +goto error; } #endif -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_SLIRP, - vlan, NULL, model, name, NULL, - slirp_receive, NULL, NULL, - net_slirp_cleanup, s); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n'); return 0; + +error: +qemu_del_vlan_client(nc); +return -1; } static SlirpState *slirp_lookup(Monitor *mon, const char *vlan, const char *stack) { -VLANClientState *vc; if (vlan) { -vc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack); -if (!vc) { +VLANClientState *nc; +nc = qemu_find_vlan_client_by_name(mon, strtol(vlan, NULL, 0), stack); +if (!nc) { return NULL; } -if (strcmp(vc->model, "user")) { +if (strcmp(nc->model, "user")) { monitor_printf(mon, "invalid device specified\n"); return NULL; } -return vc->opaque; +return DO_UPCAST(SlirpState, nc, nc); } else { if (QTAILQ_EMPTY(&slirp_stacks)) { monitor_printf(mon, "user mode network stack not in use\n"); @@ -626,7 +637,9 @@ voi
[Qemu-devel] [PATCH 26/44] net: convert LAN9118 to NICState
Signed-off-by: Mark McLoughlin --- hw/lan9118.c | 45 + 1 files changed, 25 insertions(+), 20 deletions(-) diff --git a/hw/lan9118.c b/hw/lan9118.c index 6394f3a..ba982d1 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -137,7 +137,7 @@ typedef struct { typedef struct { SysBusDevice busdev; -VLANClientState *vc; +NICState *nic; NICConf conf; qemu_irq irq; int mmio_index; @@ -212,7 +212,7 @@ static void lan9118_update(lan9118_state *s) static void lan9118_mac_changed(lan9118_state *s) { -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); } static void lan9118_reload_eeprom(lan9118_state *s) @@ -234,16 +234,16 @@ static void lan9118_reload_eeprom(lan9118_state *s) static void phy_update_link(lan9118_state *s) { /* Autonegotiation status mirrors link status. */ -if (s->vc->link_down) { +if (s->nic->nc.link_down) { s->phy_status &= ~0x0024; } else { s->phy_status |= 0x0024; } } -static void lan9118_set_link(VLANClientState *vc) +static void lan9118_set_link(VLANClientState *nc) { -phy_update_link(vc->opaque); +phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque); } static void phy_reset(lan9118_state *s) @@ -305,7 +305,7 @@ static void lan9118_reset(DeviceState *d) lan9118_reload_eeprom(s); } -static int lan9118_can_receive(VLANClientState *vc) +static int lan9118_can_receive(VLANClientState *nc) { return 1; } @@ -358,10 +358,10 @@ static int lan9118_filter(lan9118_state *s, const uint8_t *addr) } } -static ssize_t lan9118_receive(VLANClientState *vc, const uint8_t *buf, +static ssize_t lan9118_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -lan9118_state *s = vc->opaque; +lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int fifo_len; int offset; int src_pos; @@ -506,9 +506,9 @@ static void do_tx_packet(lan9118_state *s) /* FIXME: Honor TX disable, and allow queueing of packets. */ if (s->phy_control & 0x4000) { /* This assumes the receive routine doesn't touch the VLANClient. */ -lan9118_receive(s->vc, s->txp->data, s->txp->len); +lan9118_receive(&s->nic->nc, s->txp->data, s->txp->len); } else { -qemu_send_packet(s->vc, s->txp->data, s->txp->len); +qemu_send_packet(&s->nic->nc, s->txp->data, s->txp->len); } s->txp->fifo_used = 0; @@ -1022,13 +1022,22 @@ static CPUWriteMemoryFunc * const lan9118_writefn[] = { lan9118_writel }; -static void lan9118_cleanup(VLANClientState *vc) +static void lan9118_cleanup(VLANClientState *nc) { -lan9118_state *s = vc->opaque; +lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_lan9118_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = lan9118_can_receive, +.receive = lan9118_receive, +.cleanup = lan9118_cleanup, +.link_status_changed = lan9118_set_link, +}; + static int lan9118_init1(SysBusDevice *dev) { lan9118_state *s = FROM_SYSBUS(lan9118_state, dev); @@ -1040,13 +1049,9 @@ static int lan9118_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - lan9118_can_receive, lan9118_receive, NULL, - NULL, lan9118_cleanup, s); -s->vc->link_status_changed = lan9118_set_link; -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(&net_lan9118_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); s->eeprom[0] = 0xa5; for (i = 0; i < 6; i++) { s->eeprom[i + 1] = s->conf.macaddr.a[i]; -- 1.6.5.2
[Qemu-devel] [PATCH 39/44] net: fix qemu_announce_self()
Now that we have a way to iterate NICs. Signed-off-by: Mark McLoughlin --- savevm.c | 26 +- 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/savevm.c b/savevm.c index 4668843..3cfc5aa 100644 --- a/savevm.c +++ b/savevm.c @@ -123,24 +123,24 @@ static int announce_self_create(uint8_t *buf, return 60; /* len (FCS will be added by hardware) */ } -static void qemu_announce_self_once(void *opaque) +static void qemu_announce_self_iter(NICState *nic, void *opaque) { -int i, len; -VLANState *vlan; -VLANClientState *vc; uint8_t buf[60]; +int len; + +len = announce_self_create(buf, nic->conf->macaddr.a); + +qemu_send_packet_raw(&nic->nc, buf, len); +} + + +static void qemu_announce_self_once(void *opaque) +{ static int count = SELF_ANNOUNCE_ROUNDS; QEMUTimer *timer = *(QEMUTimer **)opaque; -for (i = 0; i < MAX_NICS; i++) { -if (!nd_table[i].used) -continue; -len = announce_self_create(buf, nd_table[i].macaddr); -vlan = nd_table[i].vlan; -QTAILQ_FOREACH(vc, &vlan->clients, next) { -qemu_send_packet_raw(vc, buf, len); -} -} +qemu_foreach_nic(qemu_announce_self_iter, NULL); + if (--count) { /* delay 50ms, 150ms, 250ms, ... */ qemu_mod_timer(timer, qemu_get_clock(rt_clock) + -- 1.6.5.2
[Qemu-devel] [PATCH 41/44] net: fix TAP networking on host kernels without IFF_VNET_HDR support
From: Pierre Riteau vnet_hdr is initialized at 1 by default. We need to reset it to 0 if the kernel doesn't support IFF_VNET_HDR. Signed-off-by: Pierre Riteau Signed-off-by: Mark McLoughlin --- net/tap-linux.c |2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/net/tap-linux.c b/net/tap-linux.c index 0f621a2..e4f7e27 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -52,6 +52,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required features & IFF_VNET_HDR) { *vnet_hdr = 1; ifr.ifr_flags |= IFF_VNET_HDR; +} else { +*vnet_hdr = 0; } if (vnet_hdr_required && !*vnet_hdr) { -- 1.6.5.2
[Qemu-devel] [PATCH 14/44] net: convert vde to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/vde.c | 45 - 1 files changed, 28 insertions(+), 17 deletions(-) diff --git a/net/vde.c b/net/vde.c index 4d09967..42b4633 100644 --- a/net/vde.c +++ b/net/vde.c @@ -34,7 +34,7 @@ #include "sysemu.h" typedef struct VDEState { -VLANClientState *vc; +VLANClientState nc; VDECONN *vde; } VDEState; @@ -46,13 +46,13 @@ static void vde_to_qemu(void *opaque) size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); if (size > 0) { -qemu_send_packet(s->vc, buf, size); +qemu_send_packet(&s->nc, buf, size); } } -static ssize_t vde_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t vde_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -VDEState *s = vc->opaque; +VDEState *s = DO_UPCAST(VDEState, nc, nc); ssize_t ret; do { @@ -62,19 +62,27 @@ static ssize_t vde_receive(VLANClientState *vc, const uint8_t *buf, size_t size) return ret; } -static void vde_cleanup(VLANClientState *vc) +static void vde_cleanup(VLANClientState *nc) { -VDEState *s = vc->opaque; +VDEState *s = DO_UPCAST(VDEState, nc, nc); qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); vde_close(s->vde); -qemu_free(s); } +static NetClientInfo net_vde_info = { +.type = NET_CLIENT_TYPE_VDE, +.size = sizeof(VDEState), +.receive = vde_receive, +.cleanup = vde_cleanup, +}; + static int net_vde_init(VLANState *vlan, const char *model, const char *name, const char *sock, int port, const char *group, int mode) { +VLANClientState *nc; VDEState *s; +VDECONN *vde; char *init_group = (char *)group; char *init_sock = (char *)sock; @@ -84,19 +92,22 @@ static int net_vde_init(VLANState *vlan, const char *model, .mode = mode, }; -s = qemu_mallocz(sizeof(VDEState)); -s->vde = vde_open(init_sock, (char *)"QEMU", &args); -if (!s->vde){ -free(s); +vde = vde_open(init_sock, (char *)"QEMU", &args); +if (!vde){ return -1; } -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_VDE, - vlan, NULL, model, name, NULL, - vde_receive, NULL, NULL, - vde_cleanup, s); + +nc = qemu_new_net_client(&net_vde_info, vlan, NULL, model, name); + +snprintf(nc->info_str, sizeof(nc->info_str), "sock=%s,fd=%d", + sock, vde_datafd(vde)); + +s = DO_UPCAST(VDEState, nc, nc); + +s->vde = vde; + qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d", - sock, vde_datafd(s->vde)); + return 0; } -- 1.6.5.2
[Qemu-devel] [PATCH 33/44] net: convert xilinx_ethlite to NICState
Signed-off-by: Mark McLoughlin --- hw/xilinx_ethlite.c | 35 --- 1 files changed, 20 insertions(+), 15 deletions(-) diff --git a/hw/xilinx_ethlite.c b/hw/xilinx_ethlite.c index b7129d5..37e33ec 100644 --- a/hw/xilinx_ethlite.c +++ b/hw/xilinx_ethlite.c @@ -51,7 +51,7 @@ struct xlx_ethlite { SysBusDevice busdev; qemu_irq irq; -VLANClientState *vc; +NICState *nic; NICConf conf; uint32_t c_tx_pingpong; @@ -118,7 +118,7 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value)); if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { -qemu_send_packet(s->vc, +qemu_send_packet(&s->nic->nc, (void *) &s->regs[base], s->regs[base + R_TX_LEN0]); D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0])); @@ -160,17 +160,17 @@ static CPUWriteMemoryFunc * const eth_write[] = { NULL, NULL, ð_writel, }; -static int eth_can_rx(VLANClientState *vc) +static int eth_can_rx(VLANClientState *nc) { -struct xlx_ethlite *s = vc->opaque; +struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; int r; r = !(s->regs[R_RX_CTRL0] & CTRL_S); return r; } -static ssize_t eth_rx(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size) { -struct xlx_ethlite *s = vc->opaque; +struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; unsigned int rxbase = s->rxbuf * (0x800 / 4); int i; @@ -201,13 +201,21 @@ static ssize_t eth_rx(VLANClientState *vc, const uint8_t *buf, size_t size) return size; } -static void eth_cleanup(VLANClientState *vc) +static void eth_cleanup(VLANClientState *nc) { -struct xlx_ethlite *s = vc->opaque; +struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_xilinx_ethlite_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = eth_can_rx, +.receive = eth_rx, +.cleanup = eth_cleanup, +}; + static int xilinx_ethlite_init(SysBusDevice *dev) { struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev); @@ -220,12 +228,9 @@ static int xilinx_ethlite_init(SysBusDevice *dev) sysbus_init_mmio(dev, R_MAX * 4, regs); qemu_macaddr_default_if_unset(&s->conf.macaddr); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - eth_can_rx, eth_rx, NULL, - NULL, eth_cleanup, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); return 0; } -- 1.6.5.2
[Qemu-devel] [PATCH 36/44] net: remove qemu_new_vlan_client()
... and VLANClientState::opaque and qemu_find_vlan_client(). All of these are now unused Signed-off-by: Mark McLoughlin --- net.c | 44 net.h | 13 - 2 files changed, 0 insertions(+), 57 deletions(-) diff --git a/net.c b/net.c index cca008a..d77320b 100644 --- a/net.c +++ b/net.c @@ -283,37 +283,6 @@ NICState *qemu_new_nic(NetClientInfo *info, return nic; } -VLANClientState *qemu_new_vlan_client(net_client_type type, - VLANState *vlan, - VLANClientState *peer, - const char *model, - const char *name, - NetCanReceive *can_receive, - NetReceive *receive, - NetReceive *receive_raw, - NetReceiveIOV *receive_iov, - NetCleanup *cleanup, - void *opaque) -{ -VLANClientState *ret; -NetClientInfo info; - -info.type = type; -info.size = sizeof(VLANClientState); -info.can_receive = can_receive; -info.receive = receive; -info.receive_raw = receive_raw; -info.receive_iov = receive_iov; -info.cleanup = cleanup; -info.link_status_changed = NULL; - -ret = qemu_new_net_client(&info, vlan, peer, model, name); - -ret->opaque = opaque; - -return ret; -} - void qemu_del_vlan_client(VLANClientState *vc) { if (vc->vlan) { @@ -337,19 +306,6 @@ void qemu_del_vlan_client(VLANClientState *vc) qemu_free(vc); } -VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque) -{ -VLANClientState *vc; - -QTAILQ_FOREACH(vc, &vlan->clients, next) { -if (vc->opaque == opaque) { -return vc; -} -} - -return NULL; -} - VLANClientState * qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, const char *client_str) diff --git a/net.h b/net.h index 4de20de..9185bcf 100644 --- a/net.h +++ b/net.h @@ -64,7 +64,6 @@ struct VLANClientState { NetCleanup *cleanup; LinkStatusChanged *link_status_changed; int link_down; -void *opaque; QTAILQ_ENTRY(VLANClientState) next; struct VLANState *vlan; VLANClientState *peer; @@ -101,19 +100,7 @@ NICState *qemu_new_nic(NetClientInfo *info, const char *model, const char *name, void *opaque); -VLANClientState *qemu_new_vlan_client(net_client_type type, - VLANState *vlan, - VLANClientState *peer, - const char *model, - const char *name, - NetCanReceive *can_receive, - NetReceive *receive, - NetReceive *receive_raw, - NetReceiveIOV *receive_iov, - NetCleanup *cleanup, - void *opaque); void qemu_del_vlan_client(VLANClientState *vc); -VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque); VLANClientState *qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, const char *client_str); int qemu_can_send_packet(VLANClientState *vc); -- 1.6.5.2
[Qemu-devel] [PATCH 38/44] net: add qemu_foreach_nic()
Signed-off-by: Mark McLoughlin --- net.c | 20 net.h |2 ++ 2 files changed, 22 insertions(+), 0 deletions(-) diff --git a/net.c b/net.c index a1ec243..c71699d 100644 --- a/net.c +++ b/net.c @@ -326,6 +326,26 @@ qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, return vc; } +void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) +{ +VLANClientState *nc; +VLANState *vlan; + +QTAILQ_FOREACH(nc, &non_vlan_clients, next) { +if (nc->info->type == NET_CLIENT_TYPE_NIC) { +func(DO_UPCAST(NICState, nc, nc), opaque); +} +} + +QTAILQ_FOREACH(vlan, &vlans, next) { +QTAILQ_FOREACH(nc, &vlan->clients, next) { +if (nc->info->type == NET_CLIENT_TYPE_NIC) { +func(DO_UPCAST(NICState, nc, nc), opaque); +} +} +} +} + int qemu_can_send_packet(VLANClientState *sender) { VLANState *vlan = sender->vlan; diff --git a/net.h b/net.h index 497a737..d583d59 100644 --- a/net.h +++ b/net.h @@ -95,6 +95,8 @@ NICState *qemu_new_nic(NetClientInfo *info, void qemu_del_vlan_client(VLANClientState *vc); VLANClientState *qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id, const char *client_str); +typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque); +void qemu_foreach_nic(qemu_nic_foreach func, void *opaque); int qemu_can_send_packet(VLANClientState *vc); ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt); -- 1.6.5.2
[Qemu-devel] [PATCH 40/44] net: print correct error for '-netdev ""'
Reported-by: Markus Armbruster Signed-off-by: Mark McLoughlin --- net.c | 16 +++- 1 files changed, 11 insertions(+), 5 deletions(-) diff --git a/net.c b/net.c index c71699d..13bdbb2 100644 --- a/net.c +++ b/net.c @@ -1055,12 +1055,18 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev) int i; type = qemu_opt_get(opts, "type"); -if (!type) { -qemu_error("No type specified for -net\n"); -return -1; -} -if (is_netdev) { +if (!is_netdev) { +if (!type) { +qemu_error("No type specified for -net\n"); +return -1; +} +} else { +if (!type) { +qemu_error("No type specified for -netdev\n"); +return -1; +} + if (strcmp(type, "tap") != 0 && #ifdef CONFIG_SLIRP strcmp(type, "user") != 0 && -- 1.6.5.2
[Qemu-devel] [PATCH 32/44] net: convert usb-net to NICState
Signed-off-by: Mark McLoughlin --- hw/usb-net.c | 57 +++-- 1 files changed, 31 insertions(+), 26 deletions(-) diff --git a/hw/usb-net.c b/hw/usb-net.c index 7b8cc7a..2556e05 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -610,7 +610,6 @@ typedef struct USBNetState { uint32_t media_state; uint16_t filter; uint32_t vendorid; -uint8_t mac[6]; unsigned int out_ptr; uint8_t out_buf[2048]; @@ -620,7 +619,8 @@ typedef struct USBNetState { uint8_t in_buf[2048]; char usbstring_mac[13]; -VLANClientState *vc; +NICState *nic; +NICConf conf; QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp; } USBNetState; @@ -741,12 +741,12 @@ static int ndis_query(USBNetState *s, uint32_t oid, /* ieee802.3 OIDs (table 4-3) */ /* mandatory */ case OID_802_3_PERMANENT_ADDRESS: -memcpy(outbuf, s->mac, 6); +memcpy(outbuf, s->conf.macaddr.a, 6); return 6; /* mandatory */ case OID_802_3_CURRENT_ADDRESS: -memcpy(outbuf, s->mac, 6); +memcpy(outbuf, s->conf.macaddr.a, 6); return 6; /* mandatory */ @@ -1305,7 +1305,7 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p) if (!s->rndis) { if (ret < 64) { -qemu_send_packet(s->vc, s->out_buf, s->out_ptr); +qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr); s->out_ptr = 0; } return ret; @@ -1317,7 +1317,7 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p) uint32_t offs = 8 + le32_to_cpu(msg->DataOffset); uint32_t size = le32_to_cpu(msg->DataLength); if (offs + size <= len) -qemu_send_packet(s->vc, s->out_buf + offs, size); +qemu_send_packet(&s->nic->nc, s->out_buf + offs, size); } s->out_ptr -= len; memmove(s->out_buf, &s->out_buf[len], s->out_ptr); @@ -1369,9 +1369,9 @@ static int usb_net_handle_data(USBDevice *dev, USBPacket *p) return ret; } -static ssize_t usbnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -USBNetState *s = vc->opaque; +USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; struct rndis_packet_msg_type *msg; if (s->rndis) { @@ -1406,9 +1406,9 @@ static ssize_t usbnet_receive(VLANClientState *vc, const uint8_t *buf, size_t si return size; } -static int usbnet_can_receive(VLANClientState *vc) +static int usbnet_can_receive(VLANClientState *nc) { -USBNetState *s = vc->opaque; +USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED) return 1; @@ -1416,9 +1416,9 @@ static int usbnet_can_receive(VLANClientState *vc) return !s->in_len; } -static void usbnet_cleanup(VLANClientState *vc) +static void usbnet_cleanup(VLANClientState *nc) { -USBNetState *s = vc->opaque; +USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque; rndis_clear_responsequeue(s); qemu_free(s); @@ -1429,7 +1429,7 @@ static void usb_net_handle_destroy(USBDevice *dev) USBNetState *s = (USBNetState *) dev; /* TODO: remove the nd_table[] entry */ -qemu_del_vlan_client(s->vc); +qemu_del_vlan_client(&s->nic->nc); } static int usb_net_initfn(USBDevice *dev) @@ -1450,6 +1450,14 @@ static int usb_net_initfn(USBDevice *dev) return 0; } +static NetClientInfo net_usbnet_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = usbnet_can_receive, +.receive = usbnet_receive, +.cleanup = usbnet_cleanup, +}; + USBDevice *usb_net_init(NICInfo *nd) { USBDevice *dev; @@ -1458,25 +1466,22 @@ USBDevice *usb_net_init(NICInfo *nd) dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface"); s = DO_UPCAST(USBNetState, dev, dev); -memcpy(s->mac, nd->macaddr, 6); +memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr)); +s->conf.vlan = nd->vlan; +s->conf.peer = nd->netdev; -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - usbnet_can_receive, - usbnet_receive, - NULL, NULL, - usbnet_cleanup, s); +s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, + nd->model, nd->name, s); -qemu_format_nic_info_str(s->vc, s->mac); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); sn
[Qemu-devel] [PATCH 43/44] net: initialize vnet_hdr in net_init_tap()
net_tap_init() always sets vnet_hdr using qemu_opt_get_bool(), but initialize it in net_init_tap() just to reduce confusion. Signed-off-by: Mark McLoughlin --- net/tap.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/net/tap.c b/net/tap.c index a327a9a..0d8b424 100644 --- a/net/tap.c +++ b/net/tap.c @@ -378,7 +378,7 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr) int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) { TAPState *s; -int fd, vnet_hdr; +int fd, vnet_hdr = 0; if (qemu_opt_get(opts, "fd")) { if (qemu_opt_get(opts, "ifname") || -- 1.6.5.2
[Qemu-devel] [PATCH 25/44] net: convert etrax to NICState
Signed-off-by: Mark McLoughlin --- hw/etraxfs_eth.c | 45 +++-- 1 files changed, 27 insertions(+), 18 deletions(-) diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 2cc2332..dedd107 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -319,7 +319,8 @@ static void mdio_cycle(struct qemu_mdio *bus) struct fs_eth { - VLANClientState *vc; + NICState *nic; + NICConf conf; int ethregs; /* Two addrs in the filter. */ @@ -495,15 +496,15 @@ static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa) return match; } -static int eth_can_receive(VLANClientState *vc) +static int eth_can_receive(VLANClientState *nc) { return 1; } -static ssize_t eth_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - struct fs_eth *eth = vc->opaque; + struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; int use_ma0 = eth->regs[RW_REC_CTRL] & 1; int use_ma1 = eth->regs[RW_REC_CTRL] & 2; int r_bcast = eth->regs[RW_REC_CTRL] & 8; @@ -533,15 +534,15 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len) struct fs_eth *eth = opaque; D(printf("%s buf=%p len=%d\n", __func__, buf, len)); - qemu_send_packet(eth->vc, buf, len); + qemu_send_packet(ð->nic->nc, buf, len); return len; } -static void eth_set_link(VLANClientState *vc) +static void eth_set_link(VLANClientState *nc) { - struct fs_eth *eth = vc->opaque; - D(printf("%s %d\n", __func__, vc->link_down)); - eth->phy.link = !vc->link_down; + struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; + D(printf("%s %d\n", __func__, nc->link_down)); + eth->phy.link = !nc->link_down; } static CPUReadMemoryFunc * const eth_read[] = { @@ -554,9 +555,9 @@ static CPUWriteMemoryFunc * const eth_write[] = { ð_writel, }; -static void eth_cleanup(VLANClientState *vc) +static void eth_cleanup(VLANClientState *nc) { -struct fs_eth *eth = vc->opaque; + struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; cpu_unregister_io_memory(eth->ethregs); @@ -564,6 +565,15 @@ static void eth_cleanup(VLANClientState *vc) qemu_free(eth); } +static NetClientInfo net_etraxfs_info = { + .type = NET_CLIENT_TYPE_NIC, + .size = sizeof(NICState), + .can_receive = eth_can_receive, + .receive = eth_receive, + .cleanup = eth_cleanup, + .link_status_changed = eth_set_link, +}; + void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) { struct etraxfs_dma_client *dma = NULL; @@ -590,13 +600,12 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth); cpu_register_physical_memory (base, 0x5c, eth->ethregs); - eth->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - eth_can_receive, eth_receive, - NULL, NULL, eth_cleanup, eth); - eth->vc->opaque = eth; - eth->vc->link_status_changed = eth_set_link; + memcpy(eth->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr)); + eth->conf.vlan = nd->vlan; + eth->conf.peer = nd->netdev; + + eth->nic = qemu_new_nic(&net_etraxfs_info, ð->conf, + nd->model, nd->name, eth); return dma; } -- 1.6.5.2
[Qemu-devel] [PATCH 42/44] net: check for TUNSETOFFLOAD support before trying to enable offload features
From: Pierre Riteau This avoids the "TUNSETOFFLOAD ioctl() failed: Invalid argument" message on kernels without TUNSETOFFLOAD support. Signed-off-by: Pierre Riteau Signed-off-by: Mark McLoughlin --- net/tap-linux.c |5 + 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/net/tap-linux.c b/net/tap-linux.c index e4f7e27..6af9e82 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -131,6 +131,11 @@ void tap_fd_set_offload(int fd, int csum, int tso4, { unsigned int offload = 0; +/* Check if our kernel supports TUNSETOFFLOAD */ +if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { +return; +} + if (csum) { offload |= TUN_F_CSUM; if (tso4) -- 1.6.5.2
[Qemu-devel] [PATCH 27/44] net: convert mcf_fec to NICState
Signed-off-by: Mark McLoughlin --- hw/mcf_fec.c | 58 +- 1 files changed, 33 insertions(+), 25 deletions(-) diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 8242c8a..4e7fbed 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -25,7 +25,8 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0) typedef struct { qemu_irq *irq; int mmio_index; -VLANClientState *vc; +NICState *nic; +NICConf conf; uint32_t irq_state; uint32_t eir; uint32_t eimr; @@ -42,7 +43,6 @@ typedef struct { uint32_t erdsr; uint32_t etdsr; uint32_t emrbr; -uint8_t macaddr[6]; } mcf_fec_state; #define FEC_INT_HB 0x8000 @@ -172,7 +172,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s) if (bd.flags & FEC_BD_L) { /* Last buffer in frame. */ DPRINTF("Sending packet\n"); -qemu_send_packet(s->vc, frame, len); +qemu_send_packet(&s->nic->nc, frame, len); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; @@ -229,11 +229,11 @@ static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr) case 0x084: return s->rcr; case 0x0c4: return s->tcr; case 0x0e4: /* PALR */ -return (s->macaddr[0] << 24) | (s->macaddr[1] << 16) - | (s->macaddr[2] << 8) | s->macaddr[3]; +return (s->conf.macaddr.a[0] << 24) | (s->conf.macaddr.a[1] << 16) + | (s->conf.macaddr.a[2] << 8) | s->conf.macaddr.a[3]; break; case 0x0e8: /* PAUR */ -return (s->macaddr[4] << 24) | (s->macaddr[5] << 16) | 0x8808; +return (s->conf.macaddr.a[4] << 24) | (s->conf.macaddr.a[5] << 16) | 0x8808; case 0x0ec: return 0x1; /* OPD */ case 0x118: return 0; case 0x11c: return 0; @@ -303,14 +303,14 @@ static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value) s->eir |= FEC_INT_GRA; break; case 0x0e4: /* PALR */ -s->macaddr[0] = value >> 24; -s->macaddr[1] = value >> 16; -s->macaddr[2] = value >> 8; -s->macaddr[3] = value; +s->conf.macaddr.a[0] = value >> 24; +s->conf.macaddr.a[1] = value >> 16; +s->conf.macaddr.a[2] = value >> 8; +s->conf.macaddr.a[3] = value; break; case 0x0e8: /* PAUR */ -s->macaddr[4] = value >> 24; -s->macaddr[5] = value >> 16; +s->conf.macaddr.a[4] = value >> 24; +s->conf.macaddr.a[5] = value >> 16; break; case 0x0ec: /* OPD */ @@ -347,15 +347,15 @@ static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value) mcf_fec_update(s); } -static int mcf_fec_can_receive(VLANClientState *vc) +static int mcf_fec_can_receive(VLANClientState *nc) { -mcf_fec_state *s = vc->opaque; +mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; return s->rx_enabled; } -static ssize_t mcf_fec_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t mcf_fec_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -mcf_fec_state *s = vc->opaque; +mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; mcf_fec_bd bd; uint32_t flags = 0; uint32_t addr; @@ -441,15 +441,23 @@ static CPUWriteMemoryFunc * const mcf_fec_writefn[] = { mcf_fec_write }; -static void mcf_fec_cleanup(VLANClientState *vc) +static void mcf_fec_cleanup(VLANClientState *nc) { -mcf_fec_state *s = vc->opaque; +mcf_fec_state *s = DO_UPCAST(NICState, nc, nc)->opaque; cpu_unregister_io_memory(s->mmio_index); qemu_free(s); } +static NetClientInfo net_mcf_fec_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = mcf_fec_can_receive, +.receive = mcf_fec_receive, +.cleanup = mcf_fec_cleanup, +}; + void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) { mcf_fec_state *s; @@ -462,11 +470,11 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) mcf_fec_writefn, s); cpu_register_physical_memory(base, 0x400, s->mmio_index); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - mcf_fec_can_receive, mcf_fec_receive, - NULL, NULL, mcf_fec_cleanup, s); -memcpy(s->macaddr, nd->macaddr, 6); -qemu_format_nic_info_str(s->vc, s->macaddr); +memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr)); +s->conf.vlan = nd->vlan; +s->conf.peer = nd->netdev; + +s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, nd->model, nd->name, s); + +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); } -- 1.6.5.2
[Qemu-devel] [PATCH 37/44] net: remove VLANClientState members now in NetClientInfo
Add a NetClientInfo pointer to VLANClientState and use that for the typecode and function pointers. Signed-off-by: Mark McLoughlin --- hw/dp8393x.c|4 ++-- hw/virtio-net.c |2 +- net.c | 45 - net.h | 10 +- net/tap.c |6 +++--- 5 files changed, 27 insertions(+), 40 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index be9714d..e65e4d1 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -407,9 +407,9 @@ static void do_transmit_packets(dp8393xState *s) if (s->regs[SONIC_RCR] & (SONIC_RCR_LB1 | SONIC_RCR_LB0)) { /* Loopback */ s->regs[SONIC_TCR] |= SONIC_TCR_CRSL; -if (s->nic->nc.can_receive(&s->nic->nc)) { +if (s->nic->nc.info->can_receive(&s->nic->nc)) { s->loopback_packet = 1; -s->nic->nc.receive(&s->nic->nc, s->tx_buffer, tx_len); +s->nic->nc.info->receive(&s->nic->nc, s->tx_buffer, tx_len); } } else { /* Transmit packet */ diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 4f8d89e..2f201ff 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -129,7 +129,7 @@ static int peer_has_vnet_hdr(VirtIONet *n) if (!n->nic->nc.peer) return 0; -if (n->nic->nc.peer->type != NET_CLIENT_TYPE_TAP) +if (n->nic->nc.peer->info->type != NET_CLIENT_TYPE_TAP) return 0; n->has_vnet_hdr = tap_has_vnet_hdr(n->nic->nc.peer); diff --git a/net.c b/net.c index d77320b..a1ec243 100644 --- a/net.c +++ b/net.c @@ -229,19 +229,13 @@ VLANClientState *qemu_new_net_client(NetClientInfo *info, vc = qemu_mallocz(info->size); -vc->type = info->type; +vc->info = info; vc->model = qemu_strdup(model); if (name) { vc->name = qemu_strdup(name); } else { vc->name = assign_name(vc, model); } -vc->can_receive = info->can_receive; -vc->receive = info->receive; -vc->receive_raw = info->receive_raw; -vc->receive_iov = info->receive_iov; -vc->cleanup = info->cleanup; -vc->link_status_changed = info->link_status_changed; if (vlan) { assert(!peer); @@ -297,8 +291,8 @@ void qemu_del_vlan_client(VLANClientState *vc) } } -if (vc->cleanup) { -vc->cleanup(vc); +if (vc->info->cleanup) { +vc->info->cleanup(vc); } qemu_free(vc->name); @@ -340,8 +334,8 @@ int qemu_can_send_packet(VLANClientState *sender) if (sender->peer) { if (sender->peer->receive_disabled) { return 0; -} else if (sender->peer->can_receive && - !sender->peer->can_receive(sender->peer)) { +} else if (sender->peer->info->can_receive && + !sender->peer->info->can_receive(sender->peer)) { return 0; } else { return 1; @@ -358,7 +352,7 @@ int qemu_can_send_packet(VLANClientState *sender) } /* no can_receive() handler, they can always receive */ -if (!vc->can_receive || vc->can_receive(vc)) { +if (!vc->info->can_receive || vc->info->can_receive(vc)) { return 1; } } @@ -382,10 +376,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender, return 0; } -if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) { -ret = vc->receive_raw(vc, data, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) { +ret = vc->info->receive_raw(vc, data, size); } else { -ret = vc->receive(vc, data, size); +ret = vc->info->receive(vc, data, size); } if (ret == 0) { @@ -422,10 +416,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, continue; } -if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) { -len = vc->receive_raw(vc, buf, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->info->receive_raw) { +len = vc->info->receive_raw(vc, buf, size); } else { -len = vc->receive(vc, buf, size); +len = vc->info->receive(vc, buf, size); } if (len == 0) { @@ -530,7 +524,7 @@ static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, offset += len; } -return vc->receive(vc, buffer, offset); +return vc->info->receive(vc, buffer, offset); } static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt) @@ -555,8 +549,8 @@ static ssize_t qemu_deliver_p
[Qemu-devel] [PATCH 23/44] net: convert eepro100 to NICState
Signed-off-by: Mark McLoughlin --- hw/eepro100.c | 43 --- 1 files changed, 24 insertions(+), 19 deletions(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 8734907..eb16a51 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -195,7 +195,7 @@ typedef struct { PCIDevice dev; uint8_t mult[8];/* multicast mask array */ int mmio_index; -VLANClientState *vc; +NICState *nic; NICConf conf; uint8_t scb_stat; /* SCB stat/ack byte */ uint8_t int_stat; /* PCI interrupt status */ @@ -868,7 +868,7 @@ static void action_command(EEPRO100State *s) } } TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size))); -qemu_send_packet(s->vc, buf, size); +qemu_send_packet(&s->nic->nc, buf, size); s->statistics.tx_good_frames++; /* Transmit with bad status would raise an CX/TNO interrupt. * (82557 only). Emulation never has bad status. */ @@ -1599,21 +1599,21 @@ static void pci_mmio_map(PCIDevice * pci_dev, int region_num, } } -static int nic_can_receive(VLANClientState *vc) +static int nic_can_receive(VLANClientState *nc) { -EEPRO100State *s = vc->opaque; +EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; TRACE(RXTX, logout("%p\n", s)); return get_ru_state(s) == ru_ready; //~ return !eepro100_buffer_full(s); } -static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size) +static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size) { /* TODO: * - Magic packets should set bit 30 in power management driver register. * - Interesting packets should set bit 29 in power management driver register. */ -EEPRO100State *s = vc->opaque; +EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t rfd_status = 0xa000; static const uint8_t broadcast_macaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -1779,11 +1779,11 @@ static const VMStateDescription vmstate_eepro100 = { } }; -static void nic_cleanup(VLANClientState *vc) +static void nic_cleanup(VLANClientState *nc) { -EEPRO100State *s = vc->opaque; +EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } static int pci_nic_uninit(PCIDevice *pci_dev) @@ -1793,10 +1793,18 @@ static int pci_nic_uninit(PCIDevice *pci_dev) cpu_unregister_io_memory(s->mmio_index); vmstate_unregister(s->vmstate, s); eeprom93xx_free(s->eeprom); -qemu_del_vlan_client(s->vc); +qemu_del_vlan_client(&s->nic->nc); return 0; } +static NetClientInfo net_eepro100_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = nic_can_receive, +.receive = nic_receive, +.cleanup = nic_cleanup, +}; + static int nic_init(PCIDevice *pci_dev, uint32_t device) { EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev); @@ -1829,27 +1837,24 @@ static int nic_init(PCIDevice *pci_dev, uint32_t device) nic_reset(s); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - pci_dev->qdev.info->name, pci_dev->qdev.id, - nic_can_receive, nic_receive, NULL, NULL, - nic_cleanup, s); +s->nic = qemu_new_nic(&net_eepro100_info, &s->conf, + pci_dev->qdev.info->name, pci_dev->qdev.id, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); -TRACE(OTHER, logout("%s\n", s->vc->info_str)); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); +TRACE(OTHER, logout("%s\n", s->nic->nc.info_str)); qemu_register_reset(nic_reset, s); s->vmstate = qemu_malloc(sizeof(vmstate_eepro100)); memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100)); -s->vmstate->name = s->vc->model; +s->vmstate->name = s->nic->nc.model; vmstate_register(-1, s->vmstate, s); if (!pci_dev->qdev.hotplugged) { static int loaded = 0; if (!loaded) { char fname[32]; -snprintf(fname, sizeof(fname), "pxe-%s.bin", s->vc->model); +snprintf(fname, sizeof(fname), "pxe-%s.bin", s->nic->nc.model); rom_add_option(fname); loaded = 1; } -- 1.6.5.2
[Qemu-devel] [PATCH 30/44] net: convert smc91c111 to NICState
Signed-off-by: Mark McLoughlin --- hw/smc91c111.c | 35 --- 1 files changed, 20 insertions(+), 15 deletions(-) diff --git a/hw/smc91c111.c b/hw/smc91c111.c index b7398c9..c1a88c9 100644 --- a/hw/smc91c111.c +++ b/hw/smc91c111.c @@ -18,7 +18,7 @@ typedef struct { SysBusDevice busdev; -VLANClientState *vc; +NICState *nic; NICConf conf; uint16_t tcr; uint16_t rcr; @@ -207,7 +207,7 @@ static void smc91c111_do_tx(smc91c111_state *s) smc91c111_release_packet(s, packetnum); else if (s->tx_fifo_done_len < NUM_PACKETS) s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum; -qemu_send_packet(s->vc, p, len); +qemu_send_packet(&s->nic->nc, p, len); } s->tx_fifo_len = 0; smc91c111_update(s); @@ -591,9 +591,9 @@ static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset) return val; } -static int smc91c111_can_receive(VLANClientState *vc) +static int smc91c111_can_receive(VLANClientState *nc) { -smc91c111_state *s = vc->opaque; +smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) return 1; @@ -602,9 +602,9 @@ static int smc91c111_can_receive(VLANClientState *vc) return 1; } -static ssize_t smc91c111_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t smc91c111_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -smc91c111_state *s = vc->opaque; +smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int status; int packetsize; uint32_t crc; @@ -692,13 +692,21 @@ static CPUWriteMemoryFunc * const smc91c111_writefn[] = { smc91c111_writel }; -static void smc91c111_cleanup(VLANClientState *vc) +static void smc91c111_cleanup(VLANClientState *nc) { -smc91c111_state *s = vc->opaque; +smc91c111_state *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_smc91c111_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = smc91c111_can_receive, +.receive = smc91c111_receive, +.cleanup = smc91c111_cleanup, +}; + static int smc91c111_init1(SysBusDevice *dev) { smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev); @@ -711,12 +719,9 @@ static int smc91c111_init1(SysBusDevice *dev) smc91c111_reset(s); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - smc91c111_can_receive, smc91c111_receive, NULL, - NULL, smc91c111_cleanup, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); /* ??? Save/restore. */ return 0; } -- 1.6.5.2
[Qemu-devel] [PATCH 19/44] net: convert e1000 to NICState
Signed-off-by: Mark McLoughlin --- hw/e1000.c | 47 ++- 1 files changed, 26 insertions(+), 21 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index 00f6a57..683fdcc 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -75,7 +75,7 @@ enum { typedef struct E1000State_st { PCIDevice dev; -VLANClientState *vc; +NICState *nic; NICConf conf; int mmio_index; @@ -385,9 +385,9 @@ xmit_seg(E1000State *s) if (tp->vlan_needed) { memmove(tp->vlan, tp->data, 12); memcpy(tp->data + 8, tp->vlan_header, 4); -qemu_send_packet(s->vc, tp->vlan, tp->size + 4); +qemu_send_packet(&s->nic->nc, tp->vlan, tp->size + 4); } else -qemu_send_packet(s->vc, tp->data, tp->size); +qemu_send_packet(&s->nic->nc, tp->data, tp->size); s->mac_reg[TPT]++; s->mac_reg[GPTC]++; n = s->mac_reg[TOTL]; @@ -590,12 +590,12 @@ receive_filter(E1000State *s, const uint8_t *buf, int size) } static void -e1000_set_link_status(VLANClientState *vc) +e1000_set_link_status(VLANClientState *nc) { -E1000State *s = vc->opaque; +E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; uint32_t old_status = s->mac_reg[STATUS]; -if (vc->link_down) +if (nc->link_down) s->mac_reg[STATUS] &= ~E1000_STATUS_LU; else s->mac_reg[STATUS] |= E1000_STATUS_LU; @@ -605,17 +605,17 @@ e1000_set_link_status(VLANClientState *vc) } static int -e1000_can_receive(VLANClientState *vc) +e1000_can_receive(VLANClientState *nc) { -E1000State *s = vc->opaque; +E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; return (s->mac_reg[RCTL] & E1000_RCTL_EN); } static ssize_t -e1000_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -E1000State *s = vc->opaque; +E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; struct e1000_rx_desc desc; target_phys_addr_t base; unsigned int n, rdt; @@ -1037,11 +1037,11 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num, } static void -e1000_cleanup(VLANClientState *vc) +e1000_cleanup(VLANClientState *nc) { -E1000State *d = vc->opaque; +E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; -d->vc = NULL; +s->nic = NULL; } static int @@ -1050,7 +1050,7 @@ pci_e1000_uninit(PCIDevice *dev) E1000State *d = DO_UPCAST(E1000State, dev, dev); cpu_unregister_io_memory(d->mmio_index); -qemu_del_vlan_client(d->vc); +qemu_del_vlan_client(&d->nic->nc); vmstate_unregister(&vmstate_e1000, d); return 0; } @@ -1067,6 +1067,15 @@ static void e1000_reset(void *opaque) memset(&d->tx, 0, sizeof d->tx); } +static NetClientInfo net_e1000_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = e1000_can_receive, +.receive = e1000_receive, +.cleanup = e1000_cleanup, +.link_status_changed = e1000_set_link_status, +}; + static int pci_e1000_init(PCIDevice *pci_dev) { E1000State *d = DO_UPCAST(E1000State, dev, pci_dev); @@ -1107,14 +1116,10 @@ static int pci_e1000_init(PCIDevice *pci_dev) checksum = (uint16_t) EEPROM_SUM - checksum; d->eeprom_data[EEPROM_CHECKSUM_REG] = checksum; -d->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - d->conf.vlan, d->conf.peer, - d->dev.qdev.info->name, d->dev.qdev.id, - e1000_can_receive, e1000_receive, NULL, - NULL, e1000_cleanup, d); -d->vc->link_status_changed = e1000_set_link_status; +d->nic = qemu_new_nic(&net_e1000_info, &d->conf, + d->dev.qdev.info->name, d->dev.qdev.id, d); -qemu_format_nic_info_str(d->vc, macaddr); +qemu_format_nic_info_str(&d->nic->nc, macaddr); vmstate_register(-1, &vmstate_e1000, d); -- 1.6.5.2
[Qemu-devel] [PATCH 20/44] net: convert rtl8139 to NICState
Signed-off-by: Mark McLoughlin --- hw/rtl8139.c | 43 --- 1 files changed, 24 insertions(+), 19 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index c166db0..931cde9 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -459,7 +459,7 @@ typedef struct RTL8139State { uint16_t CpCmd; uint8_t TxThresh; -VLANClientState *vc; +NICState *nic; NICConf conf; int rtl8139_mmio_io_addr; @@ -785,9 +785,9 @@ static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high) #endif } -static int rtl8139_can_receive(VLANClientState *vc) +static int rtl8139_can_receive(VLANClientState *nc) { -RTL8139State *s = vc->opaque; +RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; int avail; /* Receive (drop) packets if card is disabled. */ @@ -807,9 +807,9 @@ static int rtl8139_can_receive(VLANClientState *vc) } } -static ssize_t rtl8139_do_receive(VLANClientState *vc, const uint8_t *buf, size_t size_, int do_interrupt) +static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt) { -RTL8139State *s = vc->opaque; +RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; int size = size_; uint32_t packet_header = 0; @@ -1156,9 +1156,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *vc, const uint8_t *buf, size_ return size_; } -static ssize_t rtl8139_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t rtl8139_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -return rtl8139_do_receive(vc, buf, size, 1); +return rtl8139_do_receive(nc, buf, size, 1); } static void rtl8139_reset_rxring(RTL8139State *s, uint32_t bufferSize) @@ -1744,11 +1744,11 @@ static void rtl8139_transfer_frame(RTL8139State *s, const uint8_t *buf, int size if (TxLoopBack == (s->TxConfig & TxLoopBack)) { DEBUG_PRINT(("RTL8139: +++ transmit loopback mode\n")); -rtl8139_do_receive(s->vc, buf, size, do_interrupt); +rtl8139_do_receive(&s->nic->nc, buf, size, do_interrupt); } else { -qemu_send_packet(s->vc, buf, size); +qemu_send_packet(&s->nic->nc, buf, size); } } @@ -3280,11 +3280,11 @@ static void rtl8139_timer(void *opaque) } #endif /* RTL8139_ONBOARD_TIMER */ -static void rtl8139_cleanup(VLANClientState *vc) +static void rtl8139_cleanup(VLANClientState *nc) { -RTL8139State *s = vc->opaque; +RTL8139State *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } static int pci_rtl8139_uninit(PCIDevice *dev) @@ -3301,10 +3301,18 @@ static int pci_rtl8139_uninit(PCIDevice *dev) qemu_free_timer(s->timer); #endif vmstate_unregister(&vmstate_rtl8139, s); -qemu_del_vlan_client(s->vc); +qemu_del_vlan_client(&s->nic->nc); return 0; } +static NetClientInfo net_rtl8139_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = rtl8139_can_receive, +.receive = rtl8139_receive, +.cleanup = rtl8139_cleanup, +}; + static int pci_rtl8139_init(PCIDevice *dev) { RTL8139State * s = DO_UPCAST(RTL8139State, dev, dev); @@ -3332,12 +3340,9 @@ static int pci_rtl8139_init(PCIDevice *dev) qemu_macaddr_default_if_unset(&s->conf.macaddr); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - rtl8139_can_receive, rtl8139_receive, NULL, - NULL, rtl8139_cleanup, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); s->cplus_txbuffer = NULL; s->cplus_txbuffer_len = 0; -- 1.6.5.2
[Qemu-devel] [PATCH 15/44] net: convert socket to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/socket.c | 74 +++-- 1 files changed, 45 insertions(+), 29 deletions(-) diff --git a/net/socket.c b/net/socket.c index 551fc2b..7331d87 100644 --- a/net/socket.c +++ b/net/socket.c @@ -33,7 +33,7 @@ #include "sysemu.h" typedef struct NetSocketState { -VLANClientState *vc; +VLANClientState nc; int fd; int state; /* 0 = getting length, 1 = getting data */ unsigned int index; @@ -50,9 +50,9 @@ typedef struct NetSocketListenState { } NetSocketListenState; /* XXX: we consider we can send the whole packet without blocking */ -static ssize_t net_socket_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -NetSocketState *s = vc->opaque; +NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); uint32_t len; len = htonl(size); @@ -60,9 +60,9 @@ static ssize_t net_socket_receive(VLANClientState *vc, const uint8_t *buf, size_ return send_all(s->fd, buf, size); } -static ssize_t net_socket_receive_dgram(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t net_socket_receive_dgram(VLANClientState *nc, const uint8_t *buf, size_t size) { -NetSocketState *s = vc->opaque; +NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); return sendto(s->fd, (const void *)buf, size, 0, (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); @@ -124,7 +124,7 @@ static void net_socket_send(void *opaque) buf += l; size -= l; if (s->index >= s->packet_len) { -qemu_send_packet(s->vc, s->buf, s->packet_len); +qemu_send_packet(&s->nc, s->buf, s->packet_len); s->index = 0; s->state = 0; } @@ -146,7 +146,7 @@ static void net_socket_send_dgram(void *opaque) qemu_set_fd_handler(s->fd, NULL, NULL, NULL); return; } -qemu_send_packet(s->vc, s->buf, size); +qemu_send_packet(&s->nc, s->buf, size); } static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) @@ -209,14 +209,20 @@ fail: return -1; } -static void net_socket_cleanup(VLANClientState *vc) +static void net_socket_cleanup(VLANClientState *nc) { -NetSocketState *s = vc->opaque; +NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); qemu_set_fd_handler(s->fd, NULL, NULL, NULL); close(s->fd); -qemu_free(s); } +static NetClientInfo net_dgram_socket_info = { +.type = NET_CLIENT_TYPE_SOCKET, +.size = sizeof(NetSocketState), +.receive = net_socket_receive_dgram, +.cleanup = net_socket_cleanup, +}; + static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, const char *model, const char *name, @@ -225,6 +231,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, struct sockaddr_in saddr; int newfd; socklen_t saddr_len; +VLANClientState *nc; NetSocketState *s; /* fd passed: multicast: "learn" dgram_dst address from bound address and save it @@ -258,22 +265,22 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, } } -s = qemu_mallocz(sizeof(NetSocketState)); +nc = qemu_new_net_client(&net_dgram_socket_info, vlan, NULL, model, name); + +snprintf(nc->info_str, sizeof(nc->info_str), + "socket: fd=%d (%s mcast=%s:%d)", + fd, is_connected ? "cloned" : "", + inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); + +s = DO_UPCAST(NetSocketState, nc, nc); + s->fd = fd; -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_SOCKET, - vlan, NULL, model, name, NULL, - net_socket_receive_dgram, NULL, NULL, - net_socket_cleanup, s); qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); /* mcast: save bound address as dst */ if (is_connected) s->dgram_dst=saddr; -snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: fd=%d (%s mcast=%s:%d)", - fd, is_connected? "cloned" : "", - inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return s; } @@ -283,20 +290,29 @@ static void net_socket_connect(void *opaque) qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); } +static NetClientInfo net_socket_info = { +.type = NET_CLIENT_TYPE_SOCKET, +.size = sizeof(NetSocketState), +.receive = net_socket_receive, +.cleanup = net_socket_cleanup, +};
[Qemu-devel] [PATCH 18/44] net: convert virtio to NICState
Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 73 +- 1 files changed, 39 insertions(+), 34 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 2f147e5..4f8d89e 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -31,7 +31,7 @@ typedef struct VirtIONet VirtQueue *rx_vq; VirtQueue *tx_vq; VirtQueue *ctrl_vq; -VLANClientState *vc; +NICState *nic; QEMUTimer *tx_timer; int tx_timer_active; uint32_t has_vnet_hdr; @@ -85,16 +85,16 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) if (memcmp(netcfg.mac, n->mac, ETH_ALEN)) { memcpy(n->mac, netcfg.mac, ETH_ALEN); -qemu_format_nic_info_str(n->vc, n->mac); +qemu_format_nic_info_str(&n->nic->nc, n->mac); } } -static void virtio_net_set_link_status(VLANClientState *vc) +static void virtio_net_set_link_status(VLANClientState *nc) { -VirtIONet *n = vc->opaque; +VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t old_status = n->status; -if (vc->link_down) +if (nc->link_down) n->status &= ~VIRTIO_NET_S_LINK_UP; else n->status |= VIRTIO_NET_S_LINK_UP; @@ -126,13 +126,13 @@ static void virtio_net_reset(VirtIODevice *vdev) static int peer_has_vnet_hdr(VirtIONet *n) { -if (!n->vc->peer) +if (!n->nic->nc.peer) return 0; -if (n->vc->peer->type != NET_CLIENT_TYPE_TAP) +if (n->nic->nc.peer->type != NET_CLIENT_TYPE_TAP) return 0; -n->has_vnet_hdr = tap_has_vnet_hdr(n->vc->peer); +n->has_vnet_hdr = tap_has_vnet_hdr(n->nic->nc.peer); return n->has_vnet_hdr; } @@ -142,7 +142,7 @@ static int peer_has_ufo(VirtIONet *n) if (!peer_has_vnet_hdr(n)) return 0; -n->has_ufo = tap_has_ufo(n->vc->peer); +n->has_ufo = tap_has_ufo(n->nic->nc.peer); return n->has_ufo; } @@ -159,7 +159,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) (1 << VIRTIO_NET_F_CTRL_RX_EXTRA); if (peer_has_vnet_hdr(n)) { -tap_using_vnet_hdr(n->vc->peer, 1); +tap_using_vnet_hdr(n->nic->nc.peer, 1); features |= (1 << VIRTIO_NET_F_CSUM); features |= (1 << VIRTIO_NET_F_HOST_TSO4); @@ -202,7 +202,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); if (n->has_vnet_hdr) { -tap_set_offload(n->vc->peer, +tap_set_offload(n->nic->nc.peer, (features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (features >> VIRTIO_NET_F_GUEST_TSO4) & 1, (features >> VIRTIO_NET_F_GUEST_TSO6) & 1, @@ -360,16 +360,16 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) { VirtIONet *n = to_virtio_net(vdev); -qemu_flush_queued_packets(n->vc); +qemu_flush_queued_packets(&n->nic->nc); /* We now have RX buffers, signal to the IO thread to break out of the * select to re-poll the tap file descriptor */ qemu_notify_event(); } -static int virtio_net_can_receive(VLANClientState *vc) +static int virtio_net_can_receive(VLANClientState *nc) { -VirtIONet *n = vc->opaque; +VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; if (!virtio_queue_ready(n->rx_vq) || !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) @@ -511,13 +511,13 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) return 0; } -static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -VirtIONet *n = vc->opaque; +VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; struct virtio_net_hdr_mrg_rxbuf *mhdr = NULL; size_t hdr_len, offset, i; -if (!virtio_net_can_receive(n->vc)) +if (!virtio_net_can_receive(&n->nic->nc)) return -1; if (!virtio_net_has_buffers(n, size)) @@ -590,9 +590,9 @@ static ssize_t virtio_net_receive(VLANClientState *vc, const uint8_t *buf, size_ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq); -static void virtio_net_tx_complete(VLANClientState *vc, ssize_t len) +static void virtio_net_tx_complete(VLANClientState *nc, ssize_t len) { -VirtIONet *n = vc->opaque; +VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque; virtqueue_push(n->tx_vq, &n->async_tx.elem, n->async_tx.len); virtio_notify(&n->vdev, n->tx_vq); @@ -644,7 +644,7 @@ static void virtio_net_flush_tx(V
[Qemu-devel] [PATCH 08/44] net: introduce NetClientInfo
This structure holds data which is common to all instances of a given net client type/model. Signed-off-by: Mark McLoughlin --- net.h | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/net.h b/net.h index 9ffcfe3..56c5849 100644 --- a/net.h +++ b/net.h @@ -42,6 +42,17 @@ typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int); typedef void (NetCleanup) (VLANClientState *); typedef void (LinkStatusChanged)(VLANClientState *); +typedef struct NetClientInfo { +net_client_type type; +size_t size; +NetReceive *receive; +NetReceive *receive_raw; +NetReceiveIOV *receive_iov; +NetCanReceive *can_receive; +NetCleanup *cleanup; +LinkStatusChanged *link_status_changed; +} NetClientInfo; + struct VLANClientState { net_client_type type; NetReceive *receive; -- 1.6.5.2
[Qemu-devel] [PATCH 24/44] net: convert dp8393x to NICState
Signed-off-by: Mark McLoughlin --- hw/dp8393x.c | 41 + 1 files changed, 25 insertions(+), 16 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 5143cc8..be9714d 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -154,7 +154,8 @@ typedef struct dp8393xState { #endif QEMUTimer *watchdog; int64_t wt_last_update; -VLANClientState *vc; +NICConf conf; +NICState *nic; int mmio_index; /* Registers */ @@ -406,13 +407,13 @@ static void do_transmit_packets(dp8393xState *s) if (s->regs[SONIC_RCR] & (SONIC_RCR_LB1 | SONIC_RCR_LB0)) { /* Loopback */ s->regs[SONIC_TCR] |= SONIC_TCR_CRSL; -if (s->vc->can_receive(s->vc)) { +if (s->nic->nc.can_receive(&s->nic->nc)) { s->loopback_packet = 1; -s->vc->receive(s->vc, s->tx_buffer, tx_len); +s->nic->nc.receive(&s->nic->nc, s->tx_buffer, tx_len); } } else { /* Transmit packet */ -qemu_send_packet(s->vc, s->tx_buffer, tx_len); +qemu_send_packet(&s->nic->nc, s->tx_buffer, tx_len); } s->regs[SONIC_TCR] |= SONIC_TCR_PTX; @@ -675,9 +676,9 @@ static CPUWriteMemoryFunc * const dp8393x_write[3] = { dp8393x_writel, }; -static int nic_can_receive(VLANClientState *vc) +static int nic_can_receive(VLANClientState *nc) { -dp8393xState *s = vc->opaque; +dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN)) return 0; @@ -724,10 +725,10 @@ static int receive_filter(dp8393xState *s, const uint8_t * buf, int size) return -1; } -static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size) +static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size) { +dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; uint16_t data[10]; -dp8393xState *s = vc->opaque; int packet_type; uint32_t available, address; int width, rx_len = size; @@ -860,9 +861,9 @@ static void nic_reset(void *opaque) dp8393x_update_irq(s); } -static void nic_cleanup(VLANClientState *vc) +static void nic_cleanup(VLANClientState *nc) { -dp8393xState *s = vc->opaque; +dp8393xState *s = DO_UPCAST(NICState, nc, nc)->opaque; cpu_unregister_io_memory(s->mmio_index); @@ -872,6 +873,14 @@ static void nic_cleanup(VLANClientState *vc) qemu_free(s); } +static NetClientInfo net_dp83932_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = nic_can_receive, +.receive = nic_receive, +.cleanup = nic_cleanup, +}; + void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, qemu_irq irq, void* mem_opaque, void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)) @@ -889,13 +898,13 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - nd->vlan, nd->netdev, - nd->model, nd->name, - nic_can_receive, nic_receive, NULL, NULL, - nic_cleanup, s); +memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(s->conf.macaddr)); +s->conf.vlan = nd->vlan; +s->conf.peer = nd->netdev; + +s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s); -qemu_format_nic_info_str(s->vc, nd->macaddr); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); qemu_register_reset(nic_reset, s); nic_reset(s); -- 1.6.5.2
[Qemu-devel] [PATCH 16/44] net: convert dump to NetClientInfo
Signed-off-by: Mark McLoughlin --- net/dump.c | 47 +++ 1 files changed, 27 insertions(+), 20 deletions(-) diff --git a/net/dump.c b/net/dump.c index 05a102b..4ed3f5f 100644 --- a/net/dump.c +++ b/net/dump.c @@ -28,7 +28,7 @@ #include "qemu-log.h" typedef struct DumpState { -VLANClientState *pcap_vc; +VLANClientState nc; int fd; int pcap_caplen; } DumpState; @@ -54,9 +54,9 @@ struct pcap_sf_pkthdr { uint32_t len; }; -static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t dump_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -DumpState *s = vc->opaque; +DumpState *s = DO_UPCAST(DumpState, nc, nc); struct pcap_sf_pkthdr hdr; int64_t ts; int caplen; @@ -83,30 +83,34 @@ static ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size return size; } -static void net_dump_cleanup(VLANClientState *vc) +static void dump_cleanup(VLANClientState *nc) { -DumpState *s = vc->opaque; +DumpState *s = DO_UPCAST(DumpState, nc, nc); close(s->fd); -qemu_free(s); } +static NetClientInfo net_dump_info = { +.type = NET_CLIENT_TYPE_DUMP, +.size = sizeof(DumpState), +.receive = dump_receive, +.cleanup = dump_cleanup, +}; + static int net_dump_init(VLANState *vlan, const char *device, const char *name, const char *filename, int len) { struct pcap_file_hdr hdr; +VLANClientState *nc; DumpState *s; +int fd; -s = qemu_malloc(sizeof(DumpState)); - -s->fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644); -if (s->fd < 0) { +fd = open(filename, O_CREAT | O_WRONLY | O_BINARY, 0644); +if (fd < 0) { qemu_error("-net dump: can't open %s\n", filename); return -1; } -s->pcap_caplen = len; - hdr.magic = PCAP_MAGIC; hdr.version_major = 2; hdr.version_minor = 4; @@ -115,19 +119,22 @@ static int net_dump_init(VLANState *vlan, const char *device, hdr.snaplen = s->pcap_caplen; hdr.linktype = 1; -if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { +if (write(fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { qemu_error("-net dump write error: %s\n", strerror(errno)); -close(s->fd); -qemu_free(s); +close(fd); return -1; } -s->pcap_vc = qemu_new_vlan_client(NET_CLIENT_TYPE_DUMP, - vlan, NULL, device, name, NULL, - dump_receive, NULL, NULL, - net_dump_cleanup, s); -snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str), +nc = qemu_new_net_client(&net_dump_info, vlan, NULL, device, name); + +snprintf(nc->info_str, sizeof(nc->info_str), "dump to %s (len=%d)", filename, len); + +s = DO_UPCAST(DumpState, nc, nc); + +s->fd = fd; +s->pcap_caplen = len; + return 0; } -- 1.6.5.2
[Qemu-devel] [PATCH 29/44] net: convert musicpal to NICState
Signed-off-by: Mark McLoughlin --- hw/musicpal.c | 31 ++- 1 files changed, 18 insertions(+), 13 deletions(-) diff --git a/hw/musicpal.c b/hw/musicpal.c index 264669f..4a33e28 100644 --- a/hw/musicpal.c +++ b/hw/musicpal.c @@ -151,7 +151,7 @@ typedef struct mv88w8618_eth_state { uint32_t rx_queue[4]; uint32_t frx_queue[4]; uint32_t cur_rx[4]; -VLANClientState *vc; +NICState *nic; NICConf conf; } mv88w8618_eth_state; @@ -175,14 +175,14 @@ static void eth_rx_desc_get(uint32_t addr, mv88w8618_rx_desc *desc) le32_to_cpus(&desc->next); } -static int eth_can_receive(VLANClientState *vc) +static int eth_can_receive(VLANClientState *nc) { return 1; } -static ssize_t eth_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -mv88w8618_eth_state *s = vc->opaque; +mv88w8618_eth_state *s = DO_UPCAST(NICState, nc, nc)->opaque; uint32_t desc_addr; mv88w8618_rx_desc desc; int i; @@ -250,7 +250,7 @@ static void eth_send(mv88w8618_eth_state *s, int queue_index) len = desc.bytes; if (len < 2048) { cpu_physical_memory_read(desc.buffer, buf, len); -qemu_send_packet(s->vc, buf, len); +qemu_send_packet(&s->nic->nc, buf, len); } desc.cmdstat &= ~MP_ETH_TX_OWN; s->icr |= 1 << (MP_ETH_IRQ_TXLO_BIT - queue_index); @@ -365,23 +365,28 @@ static CPUWriteMemoryFunc * const mv88w8618_eth_writefn[] = { mv88w8618_eth_write }; -static void eth_cleanup(VLANClientState *vc) +static void eth_cleanup(VLANClientState *nc) { -mv88w8618_eth_state *s = vc->opaque; +mv88w8618_eth_state *s = DO_UPCAST(NICState, nc, nc)->opaque; -s->vc = NULL; +s->nic = NULL; } +static NetClientInfo net_mv88w8618_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = eth_can_receive, +.receive = eth_receive, +.cleanup = eth_cleanup, +}; + static int mv88w8618_eth_init(SysBusDevice *dev) { mv88w8618_eth_state *s = FROM_SYSBUS(mv88w8618_eth_state, dev); sysbus_init_irq(dev, &s->irq); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - eth_can_receive, eth_receive, NULL, - NULL, eth_cleanup, s); +s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); s->mmio_index = cpu_register_io_memory(mv88w8618_eth_readfn, mv88w8618_eth_writefn, s); sysbus_init_mmio(dev, MP_ETH_SIZE, s->mmio_index); -- 1.6.5.2
[Qemu-devel] [PATCH 44/44] net: fix vnet_hdr handling in solaris tap code
Print an error if the user specifies vnet_hdr=1 on the cmdline. Signed-off-by: Mark McLoughlin --- net/tap-solaris.c | 11 +++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/net/tap-solaris.c b/net/tap-solaris.c index ef4e60c..e14fe36 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -180,6 +180,17 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required return -1; } pstrcpy(ifname, ifname_size, dev); +if (*vnet_hdr) { +/* Solaris doesn't have IFF_VNET_HDR */ +*vnet_hdr = 0; + +if (vnet_hdr_required && !*vnet_hdr) { +qemu_error("vnet_hdr=1 requested, but no kernel " + "support for IFF_VNET_HDR available"); +close(fd); +return -1; +} +} fcntl(fd, F_SETFL, O_NONBLOCK); return fd; } -- 1.6.5.2
[Qemu-devel] [PATCH 31/44] net: convert stellaris to NICState
Signed-off-by: Mark McLoughlin --- hw/stellaris_enet.c | 34 +++--- 1 files changed, 19 insertions(+), 15 deletions(-) diff --git a/hw/stellaris_enet.c b/hw/stellaris_enet.c index 2252f1a..d1d755e 100644 --- a/hw/stellaris_enet.c +++ b/hw/stellaris_enet.c @@ -66,7 +66,7 @@ typedef struct { uint8_t *rx_fifo; int rx_fifo_len; int next_packet; -VLANClientState *vc; +NICState *nic; NICConf conf; qemu_irq irq; int mmio_index; @@ -78,9 +78,9 @@ static void stellaris_enet_update(stellaris_enet_state *s) } /* TODO: Implement MAC address filtering. */ -static ssize_t stellaris_enet_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t stellaris_enet_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { -stellaris_enet_state *s = vc->opaque; +stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; int n; uint8_t *p; uint32_t crc; @@ -120,9 +120,9 @@ static ssize_t stellaris_enet_receive(VLANClientState *vc, const uint8_t *buf, s return size; } -static int stellaris_enet_can_receive(VLANClientState *vc) +static int stellaris_enet_can_receive(VLANClientState *nc) { -stellaris_enet_state *s = vc->opaque; +stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; if ((s->rctl & SE_RCTL_RXEN) == 0) return 1; @@ -258,7 +258,7 @@ static void stellaris_enet_write(void *opaque, target_phys_addr_t offset, memset(&s->tx_fifo[s->tx_frame_len], 0, 60 - s->tx_frame_len); s->tx_fifo_len = 60; } -qemu_send_packet(s->vc, s->tx_fifo, s->tx_frame_len); +qemu_send_packet(&s->nic->nc, s->tx_fifo, s->tx_frame_len); s->tx_frame_len = -1; s->ris |= SE_INT_TXEMP; stellaris_enet_update(s); @@ -385,9 +385,9 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) return 0; } -static void stellaris_enet_cleanup(VLANClientState *vc) +static void stellaris_enet_cleanup(VLANClientState *nc) { -stellaris_enet_state *s = vc->opaque; +stellaris_enet_state *s = DO_UPCAST(NICState, nc, nc)->opaque; unregister_savevm("stellaris_enet", s); @@ -396,6 +396,14 @@ static void stellaris_enet_cleanup(VLANClientState *vc) qemu_free(s); } +static NetClientInfo net_stellaris_enet_info = { +.type = NET_CLIENT_TYPE_NIC, +.size = sizeof(NICState), +.can_receive = stellaris_enet_can_receive, +.receive = stellaris_enet_receive, +.cleanup = stellaris_enet_cleanup, +}; + static int stellaris_enet_init(SysBusDevice *dev) { stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev); @@ -406,13 +414,9 @@ static int stellaris_enet_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); -s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, - s->conf.vlan, s->conf.peer, - dev->qdev.info->name, dev->qdev.id, - stellaris_enet_can_receive, - stellaris_enet_receive, NULL, NULL, - stellaris_enet_cleanup, s); -qemu_format_nic_info_str(s->vc, s->conf.macaddr.a); +s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, + dev->qdev.info->name, dev->qdev.id, s); +qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); stellaris_enet_reset(s); register_savevm("stellaris_enet", -1, 1, -- 1.6.5.2
Re: [Qemu-devel] [PATCH 09/44] net: introduce qemu_new_net_client()
On Wed, 2009-11-25 at 20:36 +, Blue Swirl wrote: > On Wed, Nov 25, 2009 at 6:49 PM, Mark McLoughlin wrote: > > A replacement for qemu_new_vlan_client(), using NetClientInfo to > > replace most arguments. > > > +VLANClientState *qemu_new_net_client(NetClientInfo *info, > > + VLANState *vlan, > > + VLANClientState *peer, > > + const char *model, > > + const char *name) > > { > > Could you change this to use const NetClientInfo *info instead? Then > the device structures could be const as well. Good idea. I've added the patch below to http://repo.or.cz/w/qemu/markmc.git Thanks, Mark. From: Mark McLoughlin Subject: [PATCH] net: constify NetClientInfo Reported-by: Blue Swirl Signed-off-by: Mark McLoughlin --- hw/dp8393x.c|2 +- hw/e1000.c |2 +- hw/eepro100.c |2 +- hw/etraxfs_eth.c|2 +- hw/lan9118.c|2 +- hw/lance.c |2 +- hw/mcf_fec.c|2 +- hw/mipsnet.c|2 +- hw/musicpal.c |2 +- hw/ne2000-isa.c |2 +- hw/ne2000.c |2 +- hw/pcnet.c |4 ++-- hw/pcnet.h |2 +- hw/rtl8139.c|2 +- hw/smc91c111.c |2 +- hw/stellaris_enet.c |2 +- hw/usb-net.c|2 +- hw/virtio-net.c |2 +- hw/xen_nic.c|2 +- hw/xilinx_ethlite.c |2 +- net.c |4 ++-- net.h |6 +++--- net/dump.c |2 +- net/slirp.c |2 +- net/socket.c|4 ++-- net/tap-win32.c |2 +- net/tap.c |2 +- net/vde.c |2 +- 28 files changed, 33 insertions(+), 33 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index e65e4d1..b4b2e62 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -873,7 +873,7 @@ static void nic_cleanup(VLANClientState *nc) qemu_free(s); } -static NetClientInfo net_dp83932_info = { +static const NetClientInfo net_dp83932_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = nic_can_receive, diff --git a/hw/e1000.c b/hw/e1000.c index 683fdcc..2ca4c07 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -1067,7 +1067,7 @@ static void e1000_reset(void *opaque) memset(&d->tx, 0, sizeof d->tx); } -static NetClientInfo net_e1000_info = { +static const NetClientInfo net_e1000_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = e1000_can_receive, diff --git a/hw/eepro100.c b/hw/eepro100.c index eb16a51..f6816f7 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -1797,7 +1797,7 @@ static int pci_nic_uninit(PCIDevice *pci_dev) return 0; } -static NetClientInfo net_eepro100_info = { +static const NetClientInfo net_eepro100_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = nic_can_receive, diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index dedd107..6398c0c 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -565,7 +565,7 @@ static void eth_cleanup(VLANClientState *nc) qemu_free(eth); } -static NetClientInfo net_etraxfs_info = { +static const NetClientInfo net_etraxfs_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = eth_can_receive, diff --git a/hw/lan9118.c b/hw/lan9118.c index ba982d1..306a16a 100644 --- a/hw/lan9118.c +++ b/hw/lan9118.c @@ -1029,7 +1029,7 @@ static void lan9118_cleanup(VLANClientState *nc) s->nic = NULL; } -static NetClientInfo net_lan9118_info = { +static const NetClientInfo net_lan9118_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = lan9118_can_receive, diff --git a/hw/lance.c b/hw/lance.c index 98033a4..cba111b 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -100,7 +100,7 @@ static void lance_cleanup(VLANClientState *nc) pcnet_common_cleanup(d); } -static NetClientInfo net_lance_info = { +static const NetClientInfo net_lance_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = pcnet_can_receive, diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 4e7fbed..ed7e0c8 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -450,7 +450,7 @@ static void mcf_fec_cleanup(VLANClientState *nc) qemu_free(s); } -static NetClientInfo net_mcf_fec_info = { +static const NetClientInfo net_mcf_fec_info = { .type = NET_CLIENT_TYPE_NIC, .size = sizeof(NICState), .can_receive = mcf_fec_can_receive, diff --git a/hw/mipsnet.c b/hw/mipsnet.c index a066f63..5396489 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -246,7 +246,7 @@ static void mipsnet_cleanup(VLANClientState *nc) qemu_free(s); } -static NetClientInfo net_mipsnet_info = { +static const NetClientInfo net_mipsnet_info = {
Re: [Qemu-devel] [PATCH, try 2] qemu/tap: add -net tap,dev= option
On Tue, 2009-12-08 at 18:41 +0100, Arnd Bergmann wrote: > In order to support macvtap, we need a way to select the actual > tap endpoint. While it would be nice to pass it by network interface > name, passing the character device is more flexible, and we can > easily do both in the long run. > > Signed-off-by: Arnd Bergmann Looks fine to me Acked-by: Mark McLoughlin Cheers, Mark.
Re: [Qemu-devel] vmware video broken in git
Hi Dave, On Fri, 2009-12-11 at 14:59 +1000, Dave Airlie wrote: > Hi guys, > > Building 0.11.0, qemu -vga vmware -sdl works fine. > with git I just get a blank screen. > > I'm trying to bisect but I keep running into a big chunk of NIC changes > where none of the drivers compile, so I thought maybe someone could > make an educated guess. Can't help with the vmware problem, but could you name one of those broken commits out of curiosity? Pretty sure the most recent set of NIC changes are bisectable at least. Thanks, Mark.
Re: [Qemu-devel] Spice project is now open
On Fri, 2009-12-11 at 13:04 -0600, Anthony Liguori wrote: > But to introduce another protocol where a user has to make a choice to > use Spice over VNC, I think we need a really good justification for > that. It's really about complexity. A user shouldn't have to know > about Spice or VNC. They shouldn't have to contemplate the trade-offs > of whether their management tool is aware or not. It should Just Work. That's a good goal. If we add a new protocol, we could achieve the same thing by allowing qemu support both VNC and Spice at runtime. Then you just need a client like virt-viewer that can handle both protocols, and old VNC clients will continue to be able to connect to newer qemu. Cheers, Mark.
Re: [Qemu-devel] Spice project is now open
On Fri, 2009-12-11 at 13:38 -0600, Anthony Liguori wrote: > Mark McLoughlin wrote: > > On Fri, 2009-12-11 at 13:04 -0600, Anthony Liguori wrote: > > > >> But to introduce another protocol where a user has to make a choice to > >> use Spice over VNC, I think we need a really good justification for > >> that. It's really about complexity. A user shouldn't have to know > >> about Spice or VNC. They shouldn't have to contemplate the trade-offs > >> of whether their management tool is aware or not. It should Just Work. > >> > > > > That's a good goal. > > > > If we add a new protocol, we could achieve the same thing by allowing > > qemu support both VNC and Spice at runtime. Then you just need a client > > like virt-viewer that can handle both protocols, and old VNC clients > > will continue to be able to connect to newer qemu. > > > > Supporting them at the same time could be potentially challenging. You > would need to render Spice locally in qemu in order to expose it via vnc. > > Another nasty bit is that two protocols mean two different sets of > authentication mechanisms. Does Spice support SASL based > authentication? Could it make sense to essentially tunnel Spice through > vnc in order to reuse the existing authentication infrastructure? I don't doubt there are challenges. I think your requirement that old clients work with new servers and new clients work with old servers is a good one. Maybe extending VNC is the best way to get there, but it should be recognized there is another way of achieving the same thing if Spice does require a new protocol. The underlying goal is getting lost in the "Spice can't be a VNC extension" discussion :-) Cheers, Mark.
Re: [Qemu-devel] Re: Spice project is now open
On Mon, 2009-12-14 at 15:10 +, Daniel P. Berrange wrote: > The model I had in mind was for the proxy to define a VNC extension that > allows the client to query what 'desktops' are available and request > switching between them at any time. The list of desktop would of course > be authorized per client, and strong authentication is a must for this. > > Any time a switch was made, the RFB protocol would return to the > 'ServerInit' state. The idea is that you should not assume a homogenous > environment, and you really don't want to fall down to the lowest common > denominator of extensions, nor have the proxy doing re-encoding on the FB > data updates. Returning to the ServerInit state allowing the client to > re-negotiate the set of encodings for the new desktop, and so the proxy > can be fairly stateless and while needing to understand the wire protocol, > it can just pass through the actual FB update data unchanged. > > The combo of the an extension for switching desktops on the fly and the > encryption state problem doesn't really seem to fit with passing the VNC > FD over with SCM_RIGHTS. I actually did a demo of this before, in a slightly different context. The idea was: - vnc client connects to gdm, which spawned a Xvnc(A) server with a gdm auth dialog - user logs in and if you've an Xvnc server already, it would move the client connection to the original Xvnc(B) server - first, gdm would tell the (A) to sync it's state; (A) would stop sending updates, flush its zlib/tls streams and pass gdm the current state of the connection - e.g. the protocol version, pixel format, supported encodings etc. - then gdm would pass the connection fd using SCM_RIGHTS to the existing Xvnc along with the connection state, and (B) would pick up the connection - from the users point of view, they were logged instantly back into their old session Simply flushing the encryption/compression state was the key, but AFAIR clients needed a trivial fix to allow them to properly handle the server flushing the stream. The alternative was to somehow get the server to dump its encryption/compression state and pass that to the existing server, but that seemed quite difficult when I looked. SCM_RIGHTS rule ... this was definitely one of the most fun hacks I've done :-) Cheers, Mark. p.s. - I'm sure I can dig up the code, here are some diffs that look like older than what I remember finishing: http://www.gnome.org/~markmc/code/gdm-vnc-support.patch http://www.gnome.org/~markmc/code/test-gnutls-client-close-restart.c http://www.gnome.org/~markmc/code/test-gnutls-server-close-restart.c http://www.gnome.org/~markmc/code/test-zlib.c http://www.gnome.org/~markmc/code/vnc-4.0b5-vncviewer-tls.diff http://www.gnome.org/~markmc/code/vnc-managed.patch http://www.gnome.org/~markmc/code/vnc-tls.patch
Re: [Qemu-devel] [RfC PATCH v3 00/10] qdev-ify network cards
On Fri, 2009-10-16 at 15:41 +0200, Gerd Hoffmann wrote: > Hi, > > Short RfC patch series to get the discussion rolling. We really need to > get the nic drivers qdev-ified properly, so qemu stops segfaulting on > '-device $any_nic_here'. > > New in v3: > * renamed macaddr_t to MACAddr and made it a struct. > * Adapted to netdev changes merged recently. > * Also convert ne2k_pci. > * Some new qdev properties and common bits for nics to ease > conversion. > * load pxe rom unconditionally (ne2k_pci only). Very nice, I like it. Acked-by: Mark McLoughlin Cheers, Mark.
Re: [Qemu-devel] [PATCH] qemu: work around for "posix-aio-compat"
On Thu, 2009-10-08 at 22:37 +0200, Michael S. Tsirkin wrote: > With commit ee3993069ff55fa6f1c64daf1e09963e340db8e4, > "posix-aio-compat: avoid signal race when spawning a thread" > winxp installation on a raw format file fails > during disk format, with a message "your > disk may be damaged". > > This commit moved signal mask from aio thread to creating thread. > It turns out if we keep the mask in aio thread as well, the problem > disappears. It should not be needed, but since this is harmless, let's > keep it around until someone inclined to debug pthread library internals > can check this issue. > > While we are at it, convert sigprocmask to pthread_sigmask > as per posix. FWIW, I just started hitting a boot hang with qemu.git and --enable-kvm on a Fedora 11 machine with a Fedora 11 guest. I bisected it back to malc's commit, found this thread, applied Michael's patch and confirmed that it fixes the problem for me too. Cheers, Mark.
[Qemu-devel] [PATCH 03/19] net: make tap_receive() re-use tap_receive_iov() code
In future we will want to prepend a virtio_net header if the NIC didn't supply one but IFF_VNET_HDR is enabled on the interface. This is most easily achived by using writev() in all cases. Signed-off-by: Mark McLoughlin --- net.c | 23 +++ 1 files changed, 15 insertions(+), 8 deletions(-) diff --git a/net.c b/net.c index 0e3388b..728941a 100644 --- a/net.c +++ b/net.c @@ -1291,10 +1291,8 @@ static void tap_writable(void *opaque) qemu_flush_queued_packets(s->vc); } -static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, - int iovcnt) +static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt) { -TAPState *s = vc->opaque; ssize_t len; do { @@ -1309,16 +1307,25 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, return len; } +static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, + int iovcnt) +{ +TAPState *s = vc->opaque; + +return tap_write_packet(s, iov, iovcnt); +} + static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; -ssize_t len; +struct iovec iov[1]; +int iovcnt = 0; -do { -len = write(s->fd, buf, size); -} while (len == -1 && (errno == EINTR || errno == EAGAIN)); +iov[iovcnt].iov_base = (char *)buf; +iov[iovcnt].iov_len = size; +iovcnt++; -return len; +return tap_write_packet(s, iov, iovcnt); } static int tap_can_send(void *opaque) -- 1.6.2.5
[Qemu-devel] [PATCH 00/19]
Hey, Over a year ago we added some code to qemu-kvm.git which takes advantage of the recent tun/tap IFF_VNET_HDR feature in order to allow virtio-net to send and receive packets with partial checksums and segmentation offloaded: http://article.gmane.org/gmane.comp.emulators.kvm.devel/20440 "This allows us to pass larger packets and packets with partial checkums between the guest and the host, greatly increasing the achievable bandwidth." Unfortunately, that implementation was quite hacky as it made some assumptions that would break if e.g. you added another network client to a vlan where the feature had enabled. Now that we have the -netdev parameter, we can more safely pair the NIC and backend, allowing us to negatiate features like this. What follows is a somewhat cleaned up version of the code from qemu-kvm.git. Further cleanups are probably possible, but I think this much is mergeable. Some points of discussion: - If you start a guest on a host which supports IFF_VNET_HDR and migrate to a host which doesn't support it, we can't just tell the guest to stop using GSO. We need prevent this by rejecting the migration on the destination if IFF_VNET_HDR is required but not available. However, in my testing if a load() function returns an error, the migration is seen to have completed on the source but failed on the destination. Clearly that's wrong, but I haven't investigated further yet. Also, we provide a vnet_hdr= arg so that people can prevent the feature being used on the source or require that is available on the destination. - I've slightly abused QemuOpts in 05/19. Comments welcome. - The whole mess around adding a 'raw' packet flag for the gratuitous ARP packet is gratuitously messy. - I'm always enabling IFF_VNET_HDR if it's available. I don't think that's a problem, especially compared to what would be required to only selectively enable it. Cheers, Mark.
[Qemu-devel] [PATCH 01/19] net: remove unused includes of if_tun.h and if_tap.h
Looks like these are just artifacts of vl.c being split up. Signed-off-by: Mark McLoughlin --- qemu-char.c |6 -- savevm.c|6 -- vl.c|6 -- 3 files changed, 0 insertions(+), 18 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 8084a67..7b39ace 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -51,12 +51,6 @@ #include #include #include -#ifdef __NetBSD__ -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include diff --git a/savevm.c b/savevm.c index 27a7686..99aa15a 100644 --- a/savevm.c +++ b/savevm.c @@ -42,12 +42,6 @@ #include #include #include -#if defined(__NetBSD__) -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include diff --git a/vl.c b/vl.c index eb2744e..7fa7bdc 100644 --- a/vl.c +++ b/vl.c @@ -44,12 +44,6 @@ #include #include #include -#if defined(__NetBSD__) -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include -- 1.6.2.5
[Qemu-devel] [PATCH 08/19] net: add tap_has_vnet_hdr() and tap_using_vnet_hdr() APIs
These lamely named functions allow virtio-net to query whether IFF_VNET_HDR is enabled on a tap interface and inform the tap code that virtio-net will supply packets with a vnet header. Signed-off-by: Mark McLoughlin --- net.c | 39 +++ net.h |3 +++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index 638ba36..56d979b 100644 --- a/net.c +++ b/net.c @@ -1246,7 +1246,15 @@ void do_info_usernet(Monitor *mon) #endif /* CONFIG_SLIRP */ -#if !defined(_WIN32) +#if defined(_WIN32) +int tap_has_vnet_hdr(VLANClientState *vc) +{ +return 0; +} +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +{ +} +#else /* !defined(_WIN32) */ /* Maximum GSO packet size (64k) plus plenty of room for * the ethernet and virtio_net headers @@ -1262,6 +1270,7 @@ typedef struct TAPState { unsigned int read_poll : 1; unsigned int write_poll : 1; unsigned int has_vnet_hdr : 1; +unsigned int using_vnet_hdr : 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1324,7 +1333,7 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, struct iovec iov_copy[iovcnt + 1]; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { iov_copy[0].iov_base = &hdr; iov_copy[0].iov_len = sizeof(hdr); memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); @@ -1342,7 +1351,7 @@ static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) int iovcnt = 0; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { iov[iovcnt].iov_base = &hdr; iov[iovcnt].iov_len = sizeof(hdr); iovcnt++; @@ -1399,7 +1408,7 @@ static void tap_send(void *opaque) break; } -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { buf += sizeof(struct virtio_net_hdr); size -= sizeof(struct virtio_net_hdr); } @@ -1434,6 +1443,27 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +int tap_has_vnet_hdr(VLANClientState *vc) +{ +TAPState *s = vc->opaque; + +assert(vc->type == NET_CLIENT_TYPE_TAP); + +return s->has_vnet_hdr; +} + +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +{ +TAPState *s = vc->opaque; + +using_vnet_hdr = using_vnet_hdr != 0; + +assert(vc->type == NET_CLIENT_TYPE_TAP); +assert(s->has_vnet_hdr == using_vnet_hdr); + +s->using_vnet_hdr = using_vnet_hdr; +} + static int tap_probe_vnet_hdr(int fd) { struct ifreq ifr; @@ -1474,6 +1504,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; s->has_vnet_hdr = vnet_hdr != 0; +s->using_vnet_hdr = 0; s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP, vlan, NULL, model, name, NULL, tap_receive, tap_receive_iov, diff --git a/net.h b/net.h index aefeef4..5f28860 100644 --- a/net.h +++ b/net.h @@ -165,4 +165,7 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, NetCleanup *cleanup, void *opaque); +int tap_has_vnet_hdr(VLANClientState *vc); +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); + #endif -- 1.6.2.5
[Qemu-devel] [PATCH 04/19] net: enable IFF_VNET_HDR on tap fds if available
For now, we just add an empty header before writing and strip the header after reading. We really only want IFF_VNET_HDR when virtio_net is using it, but it would significantly complicate matters to try and do that. There should be little or no performance impact with always adding headers. Signed-off-by: Mark McLoughlin --- net.c | 83 +- tap-linux.h | 14 ++ 2 files changed, 84 insertions(+), 13 deletions(-) diff --git a/net.c b/net.c index 728941a..356a280 100644 --- a/net.c +++ b/net.c @@ -1245,14 +1245,20 @@ void do_info_usernet(Monitor *mon) #if !defined(_WIN32) +/* Maximum GSO packet size (64k) plus plenty of room for + * the ethernet and virtio_net headers + */ +#define TAP_BUFSIZE (4096 + 65536) + typedef struct TAPState { VLANClientState *vc; int fd; char down_script[1024]; char down_script_arg[128]; -uint8_t buf[4096]; +uint8_t buf[TAP_BUFSIZE]; unsigned int read_poll : 1; unsigned int write_poll : 1; +unsigned int has_vnet_hdr : 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1311,15 +1317,33 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, int iovcnt) { TAPState *s = vc->opaque; +const struct iovec *iovp = iov; +struct iovec iov_copy[iovcnt + 1]; +struct virtio_net_hdr hdr = { 0, }; -return tap_write_packet(s, iov, iovcnt); +if (s->has_vnet_hdr) { +iov_copy[0].iov_base = &hdr; +iov_copy[0].iov_len = sizeof(hdr); +memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); +iovp = iov_copy; +iovcnt++; +} + +return tap_write_packet(s, iovp, iovcnt); } static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; -struct iovec iov[1]; +struct iovec iov[2]; int iovcnt = 0; +struct virtio_net_hdr hdr = { 0, }; + +if (s->has_vnet_hdr) { +iov[iovcnt].iov_base = &hdr; +iov[iovcnt].iov_len = sizeof(hdr); +iovcnt++; +} iov[iovcnt].iov_base = (char *)buf; iov[iovcnt].iov_len = size; @@ -1365,12 +1389,19 @@ static void tap_send(void *opaque) int size; do { +uint8_t *buf = s->buf; + size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); if (size <= 0) { break; } -size = qemu_send_packet_async(s->vc, s->buf, size, tap_send_completed); +if (s->has_vnet_hdr) { +buf += sizeof(struct virtio_net_hdr); +size -= sizeof(struct virtio_net_hdr); +} + +size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed); if (size == 0) { tap_read_poll(s, 0); } @@ -1400,6 +1431,18 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +static int tap_probe_vnet_hdr(int fd) +{ +struct ifreq ifr; + +if (ioctl(fd, TUNGETIFF, &ifr) != 0) { +qemu_error("TUNGETIFF ioctl() failed: %s\n", strerror(errno)); +return 0; +} + +return ifr.ifr_flags & IFF_VNET_HDR; +} + static void tap_cleanup(VLANClientState *vc) { TAPState *s = vc->opaque; @@ -1420,12 +1463,14 @@ static void tap_cleanup(VLANClientState *vc) static TAPState *net_tap_fd_init(VLANState *vlan, const char *model, const char *name, - int fd) + int fd, + int vnet_hdr) { TAPState *s; s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; +s->has_vnet_hdr = vnet_hdr != 0; s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL, tap_receive, tap_receive_iov, tap_cleanup, s); @@ -1435,7 +1480,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, } #if defined (CONFIG_BSD) || defined (__FreeBSD_kernel__) -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { int fd; char *dev; @@ -1577,7 +1622,7 @@ static int tap_alloc(char *dev, size_t dev_size) return tap_fd; } -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { char dev[10]=""; int fd; @@ -1590,13 +1635,13 @@ static int tap_open(char *ifname, int ifname_size) return fd; } #elif defined (_AIX) -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { fprintf (stderr, "no tap on AIX\n"); return -1; } #else -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *if
[Qemu-devel] [PATCH 02/19] net: import linux tap ioctl definitions
Making features dependent on the availability of newer versions if_tun.h is going to get seriously clumsy, so let's just import the definitions we need. It's only a small handful. If and when we're comfortable depending on 2.6.30 headers, we can remove this again. Signed-off-by: Mark McLoughlin --- net.c | 11 +-- qemu-options.hx |8 +--- tap-linux.h | 29 + 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 tap-linux.h diff --git a/net.c b/net.c index 4708080..0e3388b 100644 --- a/net.c +++ b/net.c @@ -46,7 +46,7 @@ #include #endif #ifdef __linux__ -#include +#include "tap-linux.h" #endif #include #include @@ -1370,7 +1370,6 @@ static void tap_send(void *opaque) } while (size > 0); } -#ifdef TUNSETSNDBUF /* sndbuf should be set to a value lower than the tx queue * capacity of any destination network interface. * Ethernet NICs generally have txqueuelen=1000, so 1Mb is @@ -1393,12 +1392,6 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) } return 0; } -#else -static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) -{ -return 0; -} -#endif /* TUNSETSNDBUF */ static void tap_cleanup(VLANClientState *vc) { @@ -2972,12 +2965,10 @@ static struct { .name = "downscript", .type = QEMU_OPT_STRING, .help = "script to shut down the interface", -#ifdef TUNSETSNDBUF }, { .name = "sndbuf", .type = QEMU_OPT_SIZE, .help = "send buffer limit" -#endif }, { /* end of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 20aa242..c745e0c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -810,21 +810,15 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, "-net tap[,vlan=n][,name=str],ifname=name\n" "connect the host TAP network interface to VLAN 'n'\n" #else -"-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile]" -#ifdef TUNSETSNDBUF -"[,sndbuf=nbytes]" -#endif -"\n" +"-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes]\n" "connect the host TAP network interface to VLAN 'n' and use the\n" "network scripts 'file' (default=%s)\n" "and 'dfile' (default=%s);\n" "use '[down]script=no' to disable script execution;\n" "use 'fd=h' to connect to an already opened TAP interface\n" -#ifdef TUNSETSNDBUF "use 'sndbuf=nbytes' to limit the size of the send buffer; the\n" "default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n" #endif -#endif "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n" "connect the vlan 'n' to another VLAN using a socket connection\n" "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n" diff --git a/tap-linux.h b/tap-linux.h new file mode 100644 index 000..cd07ea8 --- /dev/null +++ b/tap-linux.h @@ -0,0 +1,29 @@ +/* + * Universal TUN/TAP device driver. + * Copyright (C) 1999-2000 Maxim Krasnyansky + * + * 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. + */ + +#ifndef QEMU_TAP_H +#define QEMU_TAP_H + +#include + +/* Ioctl defines */ +#define TUNSETIFF _IOW('T', 202, int) +#define TUNSETSNDBUF _IOW('T', 212, int) + +/* TUNSETIFF ifr flags */ +#define IFF_TAP0x0002 +#define IFF_NO_PI 0x1000 + +#endif /* QEMU_TAP_H */ -- 1.6.2.5
[Qemu-devel] [PATCH 06/19] net: add a vnet_hdr=on|off parameter
This allows people to disable the IFF_VNET_HDR flag, e.g. for debugging purposes or if they know they may migrate the guest to a machine without IFF_VNET_HDR support. It also allows making the lack of IFF_VNET_HDR support an error condition, e.g. in the case where a guest is being migrated from a host which does support it. Signed-off-by: Mark McLoughlin --- net.c | 42 -- qemu-options.hx |4 +++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/net.c b/net.c index fccabdb..d62ab7b 100644 --- a/net.c +++ b/net.c @@ -1479,7 +1479,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, } #if defined (CONFIG_BSD) || defined (__FreeBSD_kernel__) -static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) +static int tap_open(char *ifname, int ifname_size, +int *vnet_hdr, int vnet_hdr_required) { int fd; char *dev; @@ -1621,7 +1622,8 @@ static int tap_alloc(char *dev, size_t dev_size) return tap_fd; } -static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) +static int tap_open(char *ifname, int ifname_size, +int *vnet_hdr, int vnet_hdr_required) { char dev[10]=""; int fd; @@ -1634,13 +1636,15 @@ static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) return fd; } #elif defined (_AIX) -static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) +static int tap_open(char *ifname, int ifname_size, +int *vnet_hdr, int vnet_hdr_required) { fprintf (stderr, "no tap on AIX\n"); return -1; } #else -static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) +static int tap_open(char *ifname, int ifname_size, +int *vnet_hdr, int vnet_hdr_required) { struct ifreq ifr; int fd, ret; @@ -1653,7 +1657,7 @@ static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; -{ +if (*vnet_hdr) { unsigned int features; if (ioctl(fd, TUNGETFEATURES, &features) == 0 && @@ -1661,6 +1665,13 @@ static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) *vnet_hdr = 1; ifr.ifr_flags |= IFF_VNET_HDR; } + +if (vnet_hdr_required && !*vnet_hdr) { +qemu_error("vnet_hdr=1 requested, but no kernel " + "support for IFF_VNET_HDR available"); +close(fd); +return -1; +} } if (ifname[0] != '\0') @@ -1725,7 +1736,7 @@ static int launch_script(const char *setup_script, const char *ifname, int fd) static int net_tap_init(QemuOpts *opts, int *vnet_hdr) { -int fd; +int fd, vnet_hdr_required; char ifname[128] = {0,}; const char *setup_script; @@ -1733,8 +1744,14 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr) pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname")); } -*vnet_hdr = 0; -TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr)); +*vnet_hdr = qemu_opt_get_bool(opts, "vnet_hdr", 1); +if (qemu_opt_get(opts, "vnet_hdr")) { +vnet_hdr_required = *vnet_hdr; +} else { +vnet_hdr_required = 0; +} + +TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr, vnet_hdr_required)); if (fd < 0) { return -1; } @@ -2683,8 +2700,9 @@ static int net_init_tap(QemuOpts *opts, if (qemu_opt_get(opts, "fd")) { if (qemu_opt_get(opts, "ifname") || qemu_opt_get(opts, "script") || -qemu_opt_get(opts, "downscript")) { -qemu_error("ifname=, script= and downscript= is invalid with fd=\n"); +qemu_opt_get(opts, "downscript") || +qemu_opt_get(opts, "vnet_hdr")) { +qemu_error("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=\n"); return -1; } @@ -3040,6 +3058,10 @@ static struct { .name = "sndbuf", .type = QEMU_OPT_SIZE, .help = "send buffer limit" +}, { +.name = "vnet_hdr", +.type = QEMU_OPT_BOOL, +.help = "enable the IFF_VNET_HDR flag on the tap interface" }, { /* end of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index c745e0c..d78b738 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -810,7 +810,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, "-net tap[,vlan=n][,name=str],ifname=name\n" "connect the host TAP network interface to VLAN 'n'\n" #else -"-net tap[,vlan=n][,name=str][,fd=h][,ifname=
[Qemu-devel] [PATCH 07/19] net: add a client type code
This is so as to allow APIs which operate on specific client types without having to add a function table entry which is only implemented by a single client type. Signed-off-by: Mark McLoughlin --- hw/dp8393x.c |3 ++- hw/etraxfs_eth.c |3 ++- hw/mcf_fec.c |3 ++- hw/mipsnet.c |3 ++- hw/qdev.c|3 ++- hw/usb-net.c |3 ++- hw/xen_nic.c |3 ++- net.c| 22 +++--- net.h| 14 +- tap-win32.c |3 ++- 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index e4caab0..5622170 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -889,7 +889,8 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, nic_can_receive, nic_receive, NULL, nic_cleanup, s); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index a411dab..2a583a3 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -590,7 +590,8 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth); cpu_register_physical_memory (base, 0x5c, eth->ethregs); - eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, + eth->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, +nd->vlan, nd->netdev, nd->model, nd->name, eth_can_receive, eth_receive, NULL, eth_cleanup, eth); diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index f9f437a..0567bcd 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -462,7 +462,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) mcf_fec_writefn, s); cpu_register_physical_memory(base, 0x400, s->mmio_index); -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, mcf_fec_can_receive, mcf_fec_receive, NULL, mcf_fec_cleanup, s); diff --git a/hw/mipsnet.c b/hw/mipsnet.c index ea8b570..d32099f 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -263,7 +263,8 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) s->io_base = base; s->irq = irq; if (nd) { -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, mipsnet_can_receive, mipsnet_receive, NULL, mipsnet_cleanup, s); diff --git a/hw/qdev.c b/hw/qdev.c index 20f931c..bc3a0d5 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -370,7 +370,8 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, { NICInfo *nd = dev->nd; assert(nd); -nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, can_receive, receive, receive_iov, cleanup, opaque); diff --git a/hw/usb-net.c b/hw/usb-net.c index 5c753e0..2393812 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -1460,7 +1460,8 @@ USBDevice *usb_net_init(NICInfo *nd) memcpy(s->mac, nd->macaddr, 6); -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, usbnet_can_receive, usbnet_receive, diff --git a/hw/xen_nic.c b/hw/xen_nic.c index b09b48a..2a179f0 100644 --- a/hw/xen_nic.c +++ b/hw/xen_ni
[Qemu-devel] [PATCH 13/19] net: implement tap support for receive_raw()
tap_receive_raw() always prepends a vnet header if IFF_VNET_HDR is enabled. tap_receive() only prepends when the a header is required but the NIC doesn't supply one. Signed-off-by: Mark McLoughlin --- net.c | 23 +++ 1 files changed, 19 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index 56d9de7..b44495d 100644 --- a/net.c +++ b/net.c @@ -1377,14 +1377,14 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, return tap_write_packet(s, iovp, iovcnt); } -static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; struct iovec iov[2]; int iovcnt = 0; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr && !s->using_vnet_hdr) { +if (s->has_vnet_hdr) { iov[iovcnt].iov_base = &hdr; iov[iovcnt].iov_len = sizeof(hdr); iovcnt++; @@ -1397,6 +1397,21 @@ static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) return tap_write_packet(s, iov, iovcnt); } +static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +{ +TAPState *s = vc->opaque; +struct iovec iov[1]; + +if (s->has_vnet_hdr && !s->using_vnet_hdr) { +return tap_receive_raw(vc, buf, size); +} + +iov[0].iov_base = (char *)buf; +iov[0].iov_len = size; + +return tap_write_packet(s, iov, 1); +} + static int tap_can_send(void *opaque) { TAPState *s = opaque; @@ -1540,8 +1555,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, s->using_vnet_hdr = 0; s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP, vlan, NULL, model, name, NULL, - tap_receive, NULL, tap_receive_iov, - tap_cleanup, s); + tap_receive, tap_receive_raw, + tap_receive_iov, tap_cleanup, s); tap_read_poll(s, 1); return s; } -- 1.6.2.5
[Qemu-devel] [PATCH 05/19] net: refactor tap initialization
Re-factor things so that there is only one call site for net_tap_fd_init(). Two concerns about the QemuOpts usage here - firstly, we set the script arguments to their default value and, secondly, we set the ifname value to the name allocated by the kernel if none is supplied. Are we okay with such things ending up in writeconfig output? Signed-off-by: Mark McLoughlin --- net.c | 97 +++-- 1 files changed, 52 insertions(+), 45 deletions(-) diff --git a/net.c b/net.c index 356a280..fccabdb 100644 --- a/net.c +++ b/net.c @@ -1475,7 +1475,6 @@ static TAPState *net_tap_fd_init(VLANState *vlan, tap_receive, tap_receive_iov, tap_cleanup, s); tap_read_poll(s, 1); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd); return s; } @@ -1724,38 +1723,34 @@ static int launch_script(const char *setup_script, const char *ifname, int fd) return -1; } -static TAPState *net_tap_init(VLANState *vlan, const char *model, - const char *name, const char *ifname1, - const char *setup_script, const char *down_script) +static int net_tap_init(QemuOpts *opts, int *vnet_hdr) { -TAPState *s; -int fd, vnet_hdr; -char ifname[128]; +int fd; +char ifname[128] = {0,}; +const char *setup_script; -if (ifname1 != NULL) -pstrcpy(ifname, sizeof(ifname), ifname1); -else -ifname[0] = '\0'; -vnet_hdr = 0; -TFR(fd = tap_open(ifname, sizeof(ifname), &vnet_hdr)); -if (fd < 0) -return NULL; +if (qemu_opt_get(opts, "ifname")) { +pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname")); +} -if (!setup_script || !strcmp(setup_script, "no")) -setup_script = ""; -if (setup_script[0] != '\0' && -launch_script(setup_script, ifname, fd)) { -return NULL; +*vnet_hdr = 0; +TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr)); +if (fd < 0) { +return -1; } -s = net_tap_fd_init(vlan, model, name, fd, vnet_hdr); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "ifname=%s,script=%s,downscript=%s", - ifname, setup_script, down_script); -if (down_script && strcmp(down_script, "no")) { -snprintf(s->down_script, sizeof(s->down_script), "%s", down_script); -snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); + +setup_script = qemu_opt_get(opts, "script"); +if (setup_script && +setup_script[0] != '\0' && +strcmp(setup_script, "no") != 0 && +launch_script(setup_script, ifname, fd)) { +close(fd); +return -1; } -return s; + +qemu_opt_set(opts, "ifname", ifname); + +return fd; } #endif /* !_WIN32 */ @@ -2683,10 +2678,9 @@ static int net_init_tap(QemuOpts *opts, VLANState *vlan) { TAPState *s; +int fd, vnet_hdr; if (qemu_opt_get(opts, "fd")) { -int fd; - if (qemu_opt_get(opts, "ifname") || qemu_opt_get(opts, "script") || qemu_opt_get(opts, "downscript")) { @@ -2701,28 +2695,22 @@ static int net_init_tap(QemuOpts *opts, fcntl(fd, F_SETFL, O_NONBLOCK); -s = net_tap_fd_init(vlan, "tap", name, fd, tap_probe_vnet_hdr(fd)); -if (!s) { -close(fd); -} +vnet_hdr = tap_probe_vnet_hdr(fd); } else { -const char *ifname, *script, *downscript; - -ifname = qemu_opt_get(opts, "ifname"); -script = qemu_opt_get(opts, "script"); -downscript = qemu_opt_get(opts, "downscript"); - -if (!script) { -script = DEFAULT_NETWORK_SCRIPT; +if (!qemu_opt_get(opts, "script")) { +qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT); } -if (!downscript) { -downscript = DEFAULT_NETWORK_DOWN_SCRIPT; + +if (!qemu_opt_get(opts, "downscript")) { +qemu_opt_set(opts, "downscript", DEFAULT_NETWORK_DOWN_SCRIPT); } -s = net_tap_init(vlan, "tap", name, ifname, script, downscript); +fd = net_tap_init(opts, &vnet_hdr); } +s = net_tap_fd_init(vlan, "tap", name, fd, vnet_hdr); if (!s) { +close(fd); return -1; } @@ -2730,6 +2718,25 @@ static int net_init_tap(QemuOpts *opts, return -1; } +if (qemu_opt_get(opts, "fd")) { +snprintf(s->vc->info_str, sizeof(s-&g
[Qemu-devel] [PATCH 15/19] net: add tap_set_offload()
This API allows virtio-net to enable various offload features on a tap interface - e.g. to tell the host kernel it can pass up partial checksums to userspace. Signed-off-by: Mark McLoughlin --- net.c | 24 net.h |1 + tap-linux.h |7 +++ 3 files changed, 32 insertions(+), 0 deletions(-) diff --git a/net.c b/net.c index b44495d..746a3d6 100644 --- a/net.c +++ b/net.c @@ -1287,6 +1287,9 @@ int tap_has_vnet_hdr(VLANClientState *vc) void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) { } +void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +{ +} #else /* !defined(_WIN32) */ /* Maximum GSO packet size (64k) plus plenty of room for @@ -1524,6 +1527,27 @@ static int tap_probe_vnet_hdr(int fd) return ifr.ifr_flags & IFF_VNET_HDR; } +void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +{ +TAPState *s = vc->opaque; +unsigned int offload = 0; + +if (csum) { +offload |= TUN_F_CSUM; +if (tso4) +offload |= TUN_F_TSO4; +if (tso6) +offload |= TUN_F_TSO6; +if ((tso4 || tso6) && ecn) +offload |= TUN_F_TSO_ECN; +} + +if (ioctl(s->fd, TUNSETOFFLOAD, offload) != 0) { +fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", +strerror(errno)); +} +} + static void tap_cleanup(VLANClientState *vc) { TAPState *s = vc->opaque; diff --git a/net.h b/net.h index 6255e2b..a0f0359 100644 --- a/net.h +++ b/net.h @@ -170,5 +170,6 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, int tap_has_vnet_hdr(VLANClientState *vc); void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); +void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn); #endif diff --git a/tap-linux.h b/tap-linux.h index 8e75348..241cf83 100644 --- a/tap-linux.h +++ b/tap-linux.h @@ -22,6 +22,7 @@ /* Ioctl defines */ #define TUNSETIFF _IOW('T', 202, int) #define TUNGETFEATURES _IOR('T', 207, unsigned int) +#define TUNSETOFFLOAD _IOW('T', 208, unsigned int) #define TUNGETIFF _IOR('T', 210, unsigned int) #define TUNSETSNDBUF _IOW('T', 212, int) @@ -30,6 +31,12 @@ #define IFF_NO_PI 0x1000 #define IFF_VNET_HDR 0x4000 +/* Features for GSO (TUNSETOFFLOAD). */ +#define TUN_F_CSUM 0x01/* You can hand me unchecksummed packets. */ +#define TUN_F_TSO4 0x02/* I can handle TSO for IPv4 packets */ +#define TUN_F_TSO6 0x04/* I can handle TSO for IPv6 packets */ +#define TUN_F_TSO_ECN 0x08/* I can handle TSO with ECN bits. */ + struct virtio_net_hdr { uint8_t flags; -- 1.6.2.5
[Qemu-devel] [PATCH 14/19] virtio-net: add vnet_hdr support
With '-netdev tap,id=foo -nic model=virtio,netdev=foo' virtio-net can detect that its peer (i.e. the tap backend) supports vnet headers and advertise to the guest that it can send packets with partial checksums and/or TSO packets. One complication is that if we're migrating and the source host supports IFF_VNET_HDR but the destination host doesn't, we can't then stop the guest from using those features. In this scenario, we just fail the migration. Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 49 ++--- 1 files changed, 42 insertions(+), 7 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 218f985..5ce4b42 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -120,8 +120,20 @@ static void virtio_net_reset(VirtIODevice *vdev) memset(n->vlans, 0, MAX_VLAN >> 3); } +static int peer_has_vnet_hdr(VirtIONet *n) +{ +if (!n->vc->peer) +return 0; + +if (n->vc->peer->type != NET_CLIENT_TYPE_TAP) +return 0; + +return tap_has_vnet_hdr(n->vc->peer); +} + static uint32_t virtio_net_get_features(VirtIODevice *vdev) { +VirtIONet *n = to_virtio_net(vdev); uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_MRG_RXBUF) | (1 << VIRTIO_NET_F_STATUS) | @@ -130,6 +142,15 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) (1 << VIRTIO_NET_F_CTRL_VLAN) | (1 << VIRTIO_NET_F_CTRL_RX_EXTRA); +if (peer_has_vnet_hdr(n)) { +tap_using_vnet_hdr(n->vc->peer, 1); + +features |= (1 << VIRTIO_NET_F_CSUM); +features |= (1 << VIRTIO_NET_F_HOST_TSO4); +features |= (1 << VIRTIO_NET_F_HOST_TSO6); +features |= (1 << VIRTIO_NET_F_HOST_ECN); +} + return features; } @@ -359,6 +380,11 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, hdr->flags = 0; hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; +if (peer_has_vnet_hdr(n)) { +memcpy(hdr, buf, sizeof(*hdr)); +offset = sizeof(*hdr); +} + /* We only ever receive a struct virtio_net_hdr from the tapfd, * but we may be passing along a larger header to the guest. */ @@ -378,6 +404,10 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) if (n->promisc) return 1; +if (peer_has_vnet_hdr(n)) { +ptr += sizeof(struct virtio_net_hdr); +} + if (!memcmp(&ptr[12], vlan, sizeof(vlan))) { int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff; if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f @@ -510,7 +540,6 @@ static void virtio_net_tx_complete(VLANClientState *vc, ssize_t len) static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) { VirtQueueElement elem; -int has_vnet_hdr = 0; if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) return; @@ -537,7 +566,7 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) } /* ignore the header if GSO is not supported */ -if (!has_vnet_hdr) { +if (!peer_has_vnet_hdr(n)) { out_num--; out_sg++; len += hdr_len; @@ -610,7 +639,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque) qemu_put_be32(f, n->mac_table.in_use); qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN); qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); -qemu_put_be32(f, 0); /* vnet-hdr placeholder */ +qemu_put_be32(f, peer_has_vnet_hdr(n)); qemu_put_byte(f, n->mac_table.multi_overflow); qemu_put_byte(f, n->mac_table.uni_overflow); qemu_put_byte(f, n->alluni); @@ -662,10 +691,16 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) if (version_id >= 6) qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); -if (version_id >= 7 && qemu_get_be32(f)) { -fprintf(stderr, -"virtio-net: saved image requires vnet header support\n"); -exit(1); +if (version_id >= 7) { +if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) { +fprintf(stderr, +"virtio-net: saved image requires vnet_hdr=on\n"); +return -1; +} + +if (peer_has_vnet_hdr(n)) { +tap_using_vnet_hdr(n->vc->peer, 1); +} } if (version_id >= 9) { -- 1.6.2.5
[Qemu-devel] [PATCH 19/19] virtio-net: add tap_has_ufo flag to saved state
If we tell the guest we support UFO and then migrate to host which doesn't support it, we will find ourselves in grave difficulties. Prevent this scenario by adding a flag to virtio-net's savevm format which indicates whether the device requires host UFO support. Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 12 +++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 3349800..f919952 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -16,7 +16,7 @@ #include "qemu-timer.h" #include "virtio-net.h" -#define VIRTIO_NET_VM_VERSION10 +#define VIRTIO_NET_VM_VERSION11 #define MAC_TABLE_ENTRIES64 #define MAX_VLAN(1 << 12) /* Per 802.1Q definition */ @@ -694,6 +694,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque) qemu_put_byte(f, n->nomulti); qemu_put_byte(f, n->nouni); qemu_put_byte(f, n->nobcast); +qemu_put_byte(f, peer_has_vnet_hdr(n) && tap_has_ufo(n->vc->peer)); } static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) @@ -769,6 +770,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) n->nobcast = qemu_get_byte(f); } +if (version_id >= 11) { +if (qemu_get_byte(f) && +(!peer_has_vnet_hdr(n) || !tap_has_ufo(n->vc->peer))) { +fprintf(stderr, +"virtio-net: saved image requires TUN_F_UFO support\n"); +return -1; +} +} + /* Find the first multicast entry in the saved MAC filter */ for (i = 0; i < n->mac_table.in_use; i++) { if (n->mac_table.macs[i * ETH_ALEN] & 1) { -- 1.6.2.5
[Qemu-devel] [PATCH 10/19] net: add an API for 'raw' packets
In the case where a NIC and backend agree on a packet header format, this API allows injecting packets which lack the agreed upon header. We need this for sending our gratuitous ARP. Signed-off-by: Mark McLoughlin --- net-queue.h |1 + net.c | 37 + net.h |2 ++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/net-queue.h b/net-queue.h index 343760e..a31958e 100644 --- a/net-queue.h +++ b/net-queue.h @@ -44,6 +44,7 @@ typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender, void *opaque); #define QEMU_NET_PACKET_FLAG_NONE 0 +#define QEMU_NET_PACKET_FLAG_RAW (1<<0) NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, NetPacketDeliverIOV *deliver_iov, diff --git a/net.c b/net.c index 30dc402..50d2f83 100644 --- a/net.c +++ b/net.c @@ -463,7 +463,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender, return size; } -return vc->receive(vc, data, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) +return vc->receive_raw(vc, data, size); +else +return vc->receive(vc, data, size); } static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, @@ -488,7 +491,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, continue; } -len = vc->receive(vc, buf, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) +len = vc->receive_raw(vc, buf, size); +else +len = vc->receive(vc, buf, size); ret = (ret >= 0) ? ret : len; } @@ -526,9 +532,10 @@ void qemu_flush_queued_packets(VLANClientState *vc) qemu_net_queue_flush(queue); } -ssize_t qemu_send_packet_async(VLANClientState *sender, - const uint8_t *buf, int size, - NetPacketSent *sent_cb) +static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender, + unsigned flags, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) { NetQueue *queue; @@ -547,9 +554,15 @@ ssize_t qemu_send_packet_async(VLANClientState *sender, queue = sender->vlan->send_queue; } -return qemu_net_queue_send(queue, sender, - QEMU_NET_PACKET_FLAG_NONE, - buf, size, sent_cb); +return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); +} + +ssize_t qemu_send_packet_async(VLANClientState *sender, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) +{ +return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE, + buf, size, sent_cb); } void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) @@ -557,6 +570,12 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) qemu_send_packet_async(vc, buf, size, NULL); } +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size) +{ +return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW, + buf, size, NULL); +} + static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, int iovcnt) { @@ -626,6 +645,8 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender, continue; } +assert(!(flags & QEMU_NET_PACKET_FLAG_RAW)); + if (vc->receive_iov) { len = vc->receive_iov(vc, iov, iovcnt); } else { diff --git a/net.h b/net.h index 5f28860..53d813c 100644 --- a/net.h +++ b/net.h @@ -28,6 +28,7 @@ typedef void (LinkStatusChanged)(VLANClientState *); struct VLANClientState { net_client_type type; NetReceive *receive; +NetReceive *receive_raw; NetReceiveIOV *receive_iov; /* Packets may still be sent if this returns zero. It's used to rate-limit the slirp code. */ @@ -72,6 +73,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb); void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size); ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf, int size, NetPacketSent *sent_cb); void qemu_purge_queued_packets(VLANClientState *vc); -- 1.6.2.5
[Qemu-devel] [PATCH 12/19] net: use qemu_send_packet_raw() in qemu_announce_self()
From: Gleb Natapov Use qemu_send_packet_raw to send gratuitous arp. This will ensure that vnet header is handled properly. Also, avoid sending the gratuitous packet to the guest. There doesn't appear to be any reason for doing that and the code will currently just crash if the NIC is not associated with a vlan. Signed-off-by: Gleb Natapov Signed-off-by: Mark McLoughlin --- savevm.c |7 +-- 1 files changed, 1 insertions(+), 6 deletions(-) diff --git a/savevm.c b/savevm.c index 99aa15a..ac1ef42 100644 --- a/savevm.c +++ b/savevm.c @@ -114,8 +114,6 @@ static int announce_self_create(uint8_t *buf, static void qemu_announce_self_once(void *opaque) { int i, len; -VLANState *vlan; -VLANClientState *vc; uint8_t buf[256]; static int count = SELF_ANNOUNCE_ROUNDS; QEMUTimer *timer = *(QEMUTimer **)opaque; @@ -124,10 +122,7 @@ static void qemu_announce_self_once(void *opaque) if (!nd_table[i].used) continue; len = announce_self_create(buf, nd_table[i].macaddr); -vlan = nd_table[i].vlan; -QTAILQ_FOREACH(vc, &vlan->clients, next) { -vc->receive(vc, buf, len); -} +qemu_send_packet_raw(nd_table[i].vc, buf, len); } if (count--) { qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100); -- 1.6.2.5
[Qemu-devel] [PATCH 09/19] net: add flags parameter to packet queue interface
This allows for the addition of a raw flag, and leaves the way open for other flags too. Signed-off-by: Mark McLoughlin --- net-queue.c | 26 ++ net-queue.h |6 ++ net.c | 14 -- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/net-queue.c b/net-queue.c index 75457f0..f6b01e9 100644 --- a/net-queue.c +++ b/net-queue.c @@ -41,6 +41,7 @@ struct NetPacket { QTAILQ_ENTRY(NetPacket) entry; VLANClientState *sender; +unsigned flags; int size; NetPacketSent *sent_cb; uint8_t data[0]; @@ -89,6 +90,7 @@ void qemu_del_net_queue(NetQueue *queue) static ssize_t qemu_net_queue_append(NetQueue *queue, VLANClientState *sender, + unsigned flags, const uint8_t *buf, size_t size, NetPacketSent *sent_cb) @@ -97,6 +99,7 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, packet = qemu_malloc(sizeof(NetPacket) + size); packet->sender = sender; +packet->flags = flags; packet->size = size; packet->sent_cb = sent_cb; memcpy(packet->data, buf, size); @@ -108,6 +111,7 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, static ssize_t qemu_net_queue_append_iov(NetQueue *queue, VLANClientState *sender, + unsigned flags, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb) @@ -123,6 +127,7 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, packet = qemu_malloc(sizeof(NetPacket) + max_len); packet->sender = sender; packet->sent_cb = sent_cb; +packet->flags = flags; packet->size = 0; for (i = 0; i < iovcnt; i++) { @@ -139,13 +144,14 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, static ssize_t qemu_net_queue_deliver(NetQueue *queue, VLANClientState *sender, + unsigned flags, const uint8_t *data, size_t size) { ssize_t ret = -1; queue->delivering = 1; -ret = queue->deliver(sender, data, size, queue->opaque); +ret = queue->deliver(sender, flags, data, size, queue->opaque); queue->delivering = 0; return ret; @@ -153,13 +159,14 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue, static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, VLANClientState *sender, + unsigned flags, const struct iovec *iov, int iovcnt) { ssize_t ret = -1; queue->delivering = 1; -ret = queue->deliver_iov(sender, iov, iovcnt, queue->opaque); +ret = queue->deliver_iov(sender, flags, iov, iovcnt, queue->opaque); queue->delivering = 0; return ret; @@ -167,6 +174,7 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, ssize_t qemu_net_queue_send(NetQueue *queue, VLANClientState *sender, +unsigned flags, const uint8_t *data, size_t size, NetPacketSent *sent_cb) @@ -174,12 +182,12 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t ret; if (queue->delivering) { -return qemu_net_queue_append(queue, sender, data, size, NULL); +return qemu_net_queue_append(queue, sender, flags, data, size, NULL); } -ret = qemu_net_queue_deliver(queue, sender, data, size); +ret = qemu_net_queue_deliver(queue, sender, flags, data, size); if (ret == 0 && sent_cb != NULL) { -qemu_net_queue_append(queue, sender, data, size, sent_cb); +qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); return 0; } @@ -190,6 +198,7 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t qemu_net_queue_send_iov(NetQueue *queue, VLANClientState *sender, +unsigned flags, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb) @@ -197,12 +206,12 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, ssize_t ret; if (queue->delivering) { -return qemu_net_queue_append_iov(queue, sender, iov, iovcnt, NULL); +return qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, NULL);
[Qemu-devel] [PATCH 16/19] virtio-net: enable tap offload if guest supports it
We query the guest's feature set to see if it supports offload and, if so, we enable those features on the tap interface. Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 18 ++ 1 files changed, 18 insertions(+), 0 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 5ce4b42..19d00a6 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -149,6 +149,11 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) features |= (1 << VIRTIO_NET_F_HOST_TSO4); features |= (1 << VIRTIO_NET_F_HOST_TSO6); features |= (1 << VIRTIO_NET_F_HOST_ECN); + +features |= (1 << VIRTIO_NET_F_GUEST_CSUM); +features |= (1 << VIRTIO_NET_F_GUEST_TSO4); +features |= (1 << VIRTIO_NET_F_GUEST_TSO6); +features |= (1 << VIRTIO_NET_F_GUEST_ECN); } return features; @@ -174,6 +179,14 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) VirtIONet *n = to_virtio_net(vdev); n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); + +if (peer_has_vnet_hdr(n)) { +tap_set_offload(n->vc->peer, +(features >> VIRTIO_NET_F_GUEST_CSUM) & 1, +(features >> VIRTIO_NET_F_GUEST_TSO4) & 1, +(features >> VIRTIO_NET_F_GUEST_TSO6) & 1, +(features >> VIRTIO_NET_F_GUEST_ECN) & 1); +} } static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd, @@ -700,6 +713,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) if (peer_has_vnet_hdr(n)) { tap_using_vnet_hdr(n->vc->peer, 1); +tap_set_offload(n->vc->peer, +(n->vdev.features >> VIRTIO_NET_F_GUEST_CSUM) & 1, +(n->vdev.features >> VIRTIO_NET_F_GUEST_TSO4) & 1, +(n->vdev.features >> VIRTIO_NET_F_GUEST_TSO6) & 1, +(n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1); } } -- 1.6.2.5
[Qemu-devel] [PATCH 17/19] Work around dhclient brokenness
From: Anthony Liguori With the latest GSO/csum offload patches, any guest using an unpatched version of dhclient (any Ubuntu guest, for instance), will no longer be able to get a DHCP address. dhclient is actually at fault here. It uses AF_PACKET to receive DHCP responses but does not check auxdata to see if the packet has a valid csum. This causes it to throw out the DHCP responses it gets from the virtio interface as there is not a valid checksum. Fedora has carried a patch to fix their dhclient (it's needed for Xen too) but this patch has not made it into a release of dhclient. AFAIK, the patch is in the dhclient CVS but I cannot confirm since their CVS is not public. This patch, suggested by Rusty, looks for UDP packets (of a normal MTU) and explicitly adds a checksum to them if they are missing one. This allows unpatched dhclients to continue to work without needing to update the guest kernels. Signed-off-by: Anthony Liguori Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 29 + 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 19d00a6..4590594 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -369,6 +369,34 @@ static int virtio_net_can_receive(VLANClientState *vc) return do_virtio_net_can_receive(n, VIRTIO_NET_MAX_BUFSIZE); } +/* dhclient uses AF_PACKET but doesn't pass auxdata to the kernel so + * it never finds out that the packets don't have valid checksums. This + * causes dhclient to get upset. Fedora's carried a patch for ages to + * fix this with Xen but it hasn't appeared in an upstream release of + * dhclient yet. + * + * To avoid breaking existing guests, we catch udp packets and add + * checksums. This is terrible but it's better than hacking the guest + * kernels. + * + * N.B. if we introduce a zero-copy API, this operation is no longer free so + * we should provide a mechanism to disable it to avoid polluting the host + * cache. + */ +static void work_around_broken_dhclient(struct virtio_net_hdr *hdr, +const uint8_t *buf, size_t size) +{ +if ((hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && /* missing csum */ +(size > 27 && size < 1500) && /* normal sized MTU */ +(buf[12] == 0x08 && buf[13] == 0x00) && /* ethertype == IPv4 */ +(buf[23] == 17) && /* ip.protocol == UDP */ +(buf[34] == 0 && buf[35] == 67)) { /* udp.srcport == bootps */ +/* FIXME this cast is evil */ +net_checksum_calculate((uint8_t *)buf, size); +hdr->flags &= ~VIRTIO_NET_HDR_F_NEEDS_CSUM; +} +} + static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count) { int offset, i; @@ -396,6 +424,7 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, if (peer_has_vnet_hdr(n)) { memcpy(hdr, buf, sizeof(*hdr)); offset = sizeof(*hdr); +work_around_broken_dhclient(hdr, buf + offset, size - offset); } /* We only ever receive a struct virtio_net_hdr from the tapfd, -- 1.6.2.5
[Qemu-devel] [PATCH 18/19] Enable UFO on virtio-net and tap devices
From: Sridhar Samudrala Enable UFO on the host tap device if supported and allow setting UFO on virtio-net in the guest. Signed-off-by: Sridhar Samudrala Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 11 +-- net.c | 36 net.h |3 ++- tap-linux.h |1 + 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 4590594..3349800 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -154,6 +154,11 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) features |= (1 << VIRTIO_NET_F_GUEST_TSO4); features |= (1 << VIRTIO_NET_F_GUEST_TSO6); features |= (1 << VIRTIO_NET_F_GUEST_ECN); + +if (tap_has_ufo(n->vc->peer)) { +features |= (1 << VIRTIO_NET_F_GUEST_UFO); +features |= (1 << VIRTIO_NET_F_HOST_UFO); +} } return features; @@ -185,7 +190,8 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) (features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (features >> VIRTIO_NET_F_GUEST_TSO4) & 1, (features >> VIRTIO_NET_F_GUEST_TSO6) & 1, -(features >> VIRTIO_NET_F_GUEST_ECN) & 1); +(features >> VIRTIO_NET_F_GUEST_ECN) & 1, +(features >> VIRTIO_NET_F_GUEST_UFO) & 1); } } @@ -746,7 +752,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) (n->vdev.features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO4) & 1, (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO6) & 1, -(n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1); +(n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1, +(n->vdev.features >> VIRTIO_NET_F_GUEST_UFO) & 1); } } diff --git a/net.c b/net.c index 746a3d6..3e54c53 100644 --- a/net.c +++ b/net.c @@ -1280,6 +1280,10 @@ void do_info_usernet(Monitor *mon) #endif /* CONFIG_SLIRP */ #if defined(_WIN32) +int tap_has_ufo(VLANClientState *vc) +{ +return 0; +} int tap_has_vnet_hdr(VLANClientState *vc) { return 0; @@ -1287,7 +1291,8 @@ int tap_has_vnet_hdr(VLANClientState *vc) void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) { } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +void tap_set_offload(VLANClientState *vc, int csum, int tso4, + int tso6, int ecn, int ufo) { } #else /* !defined(_WIN32) */ @@ -1307,6 +1312,7 @@ typedef struct TAPState { unsigned int write_poll : 1; unsigned int has_vnet_hdr : 1; unsigned int using_vnet_hdr : 1; +unsigned int has_ufo: 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1494,6 +1500,15 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +int tap_has_ufo(VLANClientState *vc) +{ +TAPState *s = vc->opaque; + +assert(vc->type == NET_CLIENT_TYPE_TAP); + +return s->has_ufo; +} + int tap_has_vnet_hdr(VLANClientState *vc) { TAPState *s = vc->opaque; @@ -1527,7 +1542,8 @@ static int tap_probe_vnet_hdr(int fd) return ifr.ifr_flags & IFF_VNET_HDR; } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +void tap_set_offload(VLANClientState *vc, int csum, int tso4, + int tso6, int ecn, int ufo) { TAPState *s = vc->opaque; unsigned int offload = 0; @@ -1540,11 +1556,16 @@ void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) offload |= TUN_F_TSO6; if ((tso4 || tso6) && ecn) offload |= TUN_F_TSO_ECN; +if (ufo) +offload |= TUN_F_UFO; } if (ioctl(s->fd, TUNSETOFFLOAD, offload) != 0) { -fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", -strerror(errno)); +offload &= ~TUN_F_UFO; +if (ioctl(s->fd, TUNSETOFFLOAD, offload) != 0) { +fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", +strerror(errno)); +} } } @@ -1572,6 +1593,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int vnet_hdr) { TAPState *s; +unsigned int offload; s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; @@ -1581,6 +1603,12 @@ static TAPState *net_tap_fd_init(VLANState *vlan, vlan, NULL, model, name, NULL,
[Qemu-devel] [PATCH 11/19] net: add receive_raw parameter to qemu_new_vlan_client()
Trivial patch to allow supplying a receive_raw function. A future cleanup should combine this function pointer parameters into a table. Signed-off-by: Mark McLoughlin --- hw/dp8393x.c |2 +- hw/etraxfs_eth.c |2 +- hw/mcf_fec.c |2 +- hw/mipsnet.c |2 +- hw/qdev.c|3 ++- hw/usb-net.c |2 +- hw/xen_nic.c |2 +- net.c| 14 -- net.h|1 + tap-win32.c |2 +- 10 files changed, 18 insertions(+), 14 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index 5622170..ae8b16e 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -892,7 +892,7 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, nd->vlan, nd->netdev, nd->model, nd->name, - nic_can_receive, nic_receive, NULL, + nic_can_receive, nic_receive, NULL, NULL, nic_cleanup, s); qemu_format_nic_info_str(s->vc, nd->macaddr); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index 2a583a3..ffe7082 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -594,7 +594,7 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) nd->vlan, nd->netdev, nd->model, nd->name, eth_can_receive, eth_receive, -NULL, eth_cleanup, eth); +NULL, NULL, eth_cleanup, eth); eth->vc->opaque = eth; eth->vc->link_status_changed = eth_set_link; diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index 0567bcd..9f0d0f4 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -466,7 +466,7 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) nd->vlan, nd->netdev, nd->model, nd->name, mcf_fec_can_receive, mcf_fec_receive, - NULL, mcf_fec_cleanup, s); + NULL, NULL, mcf_fec_cleanup, s); memcpy(s->macaddr, nd->macaddr, 6); qemu_format_nic_info_str(s->vc, s->macaddr); } diff --git a/hw/mipsnet.c b/hw/mipsnet.c index d32099f..65e1d59 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -267,7 +267,7 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) nd->vlan, nd->netdev, nd->model, nd->name, mipsnet_can_receive, mipsnet_receive, - NULL, mipsnet_cleanup, s); + NULL, NULL, mipsnet_cleanup, s); } else { s->vc = NULL; } diff --git a/hw/qdev.c b/hw/qdev.c index bc3a0d5..38ac037 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -373,7 +373,8 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, nd->vlan, nd->netdev, nd->model, nd->name, - can_receive, receive, receive_iov, + can_receive, receive, + NULL, receive_iov, cleanup, opaque); return nd->vc; } diff --git a/hw/usb-net.c b/hw/usb-net.c index 2393812..9c6549c 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -1465,7 +1465,7 @@ USBDevice *usb_net_init(NICInfo *nd) nd->model, nd->name, usbnet_can_receive, usbnet_receive, - NULL, + NULL, NULL, usbnet_cleanup, s); qemu_format_nic_info_str(s->vc, s->mac); diff --git a/hw/xen_nic.c b/hw/xen_nic.c index 2a179f0..75599d6 100644 --- a/hw/xen_nic.c +++ b/hw/xen_nic.c @@ -303,7 +303,7 @@ static int net_init(struct XenDevice *xendev) vlan = qemu_find_vlan(netdev->xendev.dev, 1); netdev->vs = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, vlan, NULL, "xen", NULL, - net_rx_ok, net_rx_packet, NULL, + net_rx_ok, net_rx_packet, NULL, NULL, NULL, netdev); snprintf(net
[Qemu-devel] [PATCH 01/19] net: remove unused includes of if_tun.h and if_tap.h
Looks like these are just artifacts of vl.c being split up. Signed-off-by: Mark McLoughlin --- qemu-char.c |6 -- savevm.c|6 -- vl.c|6 -- 3 files changed, 0 insertions(+), 18 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 0fd402c..1625703 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -51,12 +51,6 @@ #include #include #include -#ifdef __NetBSD__ -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include diff --git a/savevm.c b/savevm.c index 27a7686..99aa15a 100644 --- a/savevm.c +++ b/savevm.c @@ -42,12 +42,6 @@ #include #include #include -#if defined(__NetBSD__) -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include diff --git a/vl.c b/vl.c index eb2744e..7fa7bdc 100644 --- a/vl.c +++ b/vl.c @@ -44,12 +44,6 @@ #include #include #include -#if defined(__NetBSD__) -#include -#endif -#ifdef __linux__ -#include -#endif #include #include #include -- 1.6.2.5
[Qemu-devel] [PATCH 04/19] net: enable IFF_VNET_HDR on tap fds if available
For now, we just add an empty header before writing and strip the header after reading. We really only want IFF_VNET_HDR when virtio_net is using it, but it would significantly complicate matters to try and do that. There should be little or no performance impact with always adding headers. Signed-off-by: Mark McLoughlin --- net.c | 83 +- tap-linux.h | 14 ++ 2 files changed, 84 insertions(+), 13 deletions(-) diff --git a/net.c b/net.c index 728941a..356a280 100644 --- a/net.c +++ b/net.c @@ -1245,14 +1245,20 @@ void do_info_usernet(Monitor *mon) #if !defined(_WIN32) +/* Maximum GSO packet size (64k) plus plenty of room for + * the ethernet and virtio_net headers + */ +#define TAP_BUFSIZE (4096 + 65536) + typedef struct TAPState { VLANClientState *vc; int fd; char down_script[1024]; char down_script_arg[128]; -uint8_t buf[4096]; +uint8_t buf[TAP_BUFSIZE]; unsigned int read_poll : 1; unsigned int write_poll : 1; +unsigned int has_vnet_hdr : 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1311,15 +1317,33 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, int iovcnt) { TAPState *s = vc->opaque; +const struct iovec *iovp = iov; +struct iovec iov_copy[iovcnt + 1]; +struct virtio_net_hdr hdr = { 0, }; -return tap_write_packet(s, iov, iovcnt); +if (s->has_vnet_hdr) { +iov_copy[0].iov_base = &hdr; +iov_copy[0].iov_len = sizeof(hdr); +memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); +iovp = iov_copy; +iovcnt++; +} + +return tap_write_packet(s, iovp, iovcnt); } static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; -struct iovec iov[1]; +struct iovec iov[2]; int iovcnt = 0; +struct virtio_net_hdr hdr = { 0, }; + +if (s->has_vnet_hdr) { +iov[iovcnt].iov_base = &hdr; +iov[iovcnt].iov_len = sizeof(hdr); +iovcnt++; +} iov[iovcnt].iov_base = (char *)buf; iov[iovcnt].iov_len = size; @@ -1365,12 +1389,19 @@ static void tap_send(void *opaque) int size; do { +uint8_t *buf = s->buf; + size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); if (size <= 0) { break; } -size = qemu_send_packet_async(s->vc, s->buf, size, tap_send_completed); +if (s->has_vnet_hdr) { +buf += sizeof(struct virtio_net_hdr); +size -= sizeof(struct virtio_net_hdr); +} + +size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed); if (size == 0) { tap_read_poll(s, 0); } @@ -1400,6 +1431,18 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +static int tap_probe_vnet_hdr(int fd) +{ +struct ifreq ifr; + +if (ioctl(fd, TUNGETIFF, &ifr) != 0) { +qemu_error("TUNGETIFF ioctl() failed: %s\n", strerror(errno)); +return 0; +} + +return ifr.ifr_flags & IFF_VNET_HDR; +} + static void tap_cleanup(VLANClientState *vc) { TAPState *s = vc->opaque; @@ -1420,12 +1463,14 @@ static void tap_cleanup(VLANClientState *vc) static TAPState *net_tap_fd_init(VLANState *vlan, const char *model, const char *name, - int fd) + int fd, + int vnet_hdr) { TAPState *s; s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; +s->has_vnet_hdr = vnet_hdr != 0; s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL, tap_receive, tap_receive_iov, tap_cleanup, s); @@ -1435,7 +1480,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, } #if defined (CONFIG_BSD) || defined (__FreeBSD_kernel__) -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { int fd; char *dev; @@ -1577,7 +1622,7 @@ static int tap_alloc(char *dev, size_t dev_size) return tap_fd; } -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { char dev[10]=""; int fd; @@ -1590,13 +1635,13 @@ static int tap_open(char *ifname, int ifname_size) return fd; } #elif defined (_AIX) -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *ifname, int ifname_size, int *vnet_hdr) { fprintf (stderr, "no tap on AIX\n"); return -1; } #else -static int tap_open(char *ifname, int ifname_size) +static int tap_open(char *if
[Qemu-devel] [PATCH 07/19] net: add a client type code
This is so as to allow APIs which operate on specific client types without having to add a function table entry which is only implemented by a single client type. Signed-off-by: Mark McLoughlin --- hw/dp8393x.c |3 ++- hw/etraxfs_eth.c |3 ++- hw/mcf_fec.c |3 ++- hw/mipsnet.c |3 ++- hw/qdev.c|3 ++- hw/usb-net.c |3 ++- hw/xen_nic.c |3 ++- net.c| 22 +++--- net.h| 14 +- tap-win32.c |3 ++- 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/hw/dp8393x.c b/hw/dp8393x.c index e4caab0..5622170 100644 --- a/hw/dp8393x.c +++ b/hw/dp8393x.c @@ -889,7 +889,8 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift, s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s); s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */ -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, nic_can_receive, nic_receive, NULL, nic_cleanup, s); diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c index a411dab..2a583a3 100644 --- a/hw/etraxfs_eth.c +++ b/hw/etraxfs_eth.c @@ -590,7 +590,8 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr) eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth); cpu_register_physical_memory (base, 0x5c, eth->ethregs); - eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, + eth->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, +nd->vlan, nd->netdev, nd->model, nd->name, eth_can_receive, eth_receive, NULL, eth_cleanup, eth); diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c index f9f437a..0567bcd 100644 --- a/hw/mcf_fec.c +++ b/hw/mcf_fec.c @@ -462,7 +462,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq) mcf_fec_writefn, s); cpu_register_physical_memory(base, 0x400, s->mmio_index); -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, mcf_fec_can_receive, mcf_fec_receive, NULL, mcf_fec_cleanup, s); diff --git a/hw/mipsnet.c b/hw/mipsnet.c index ea8b570..d32099f 100644 --- a/hw/mipsnet.c +++ b/hw/mipsnet.c @@ -263,7 +263,8 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd) s->io_base = base; s->irq = irq; if (nd) { -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, mipsnet_can_receive, mipsnet_receive, NULL, mipsnet_cleanup, s); diff --git a/hw/qdev.c b/hw/qdev.c index 20f931c..bc3a0d5 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -370,7 +370,8 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, { NICInfo *nd = dev->nd; assert(nd); -nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, can_receive, receive, receive_iov, cleanup, opaque); diff --git a/hw/usb-net.c b/hw/usb-net.c index 5c753e0..2393812 100644 --- a/hw/usb-net.c +++ b/hw/usb-net.c @@ -1460,7 +1460,8 @@ USBDevice *usb_net_init(NICInfo *nd) memcpy(s->mac, nd->macaddr, 6); -s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev, +s->vc = nd->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_NIC, + nd->vlan, nd->netdev, nd->model, nd->name, usbnet_can_receive, usbnet_receive, diff --git a/hw/xen_nic.c b/hw/xen_nic.c index b09b48a..2a179f0 100644 --- a/hw/xen_nic.c +++ b/hw/xen_ni
[Qemu-devel] [PATCH 13/19] net: implement tap support for receive_raw()
tap_receive_raw() always prepends a vnet header if IFF_VNET_HDR is enabled. tap_receive() only prepends when the a header is required but the NIC doesn't supply one. Signed-off-by: Mark McLoughlin --- net.c | 23 +++ 1 files changed, 19 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index 56d9de7..b44495d 100644 --- a/net.c +++ b/net.c @@ -1377,14 +1377,14 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, return tap_write_packet(s, iovp, iovcnt); } -static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; struct iovec iov[2]; int iovcnt = 0; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr && !s->using_vnet_hdr) { +if (s->has_vnet_hdr) { iov[iovcnt].iov_base = &hdr; iov[iovcnt].iov_len = sizeof(hdr); iovcnt++; @@ -1397,6 +1397,21 @@ static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) return tap_write_packet(s, iov, iovcnt); } +static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) +{ +TAPState *s = vc->opaque; +struct iovec iov[1]; + +if (s->has_vnet_hdr && !s->using_vnet_hdr) { +return tap_receive_raw(vc, buf, size); +} + +iov[0].iov_base = (char *)buf; +iov[0].iov_len = size; + +return tap_write_packet(s, iov, 1); +} + static int tap_can_send(void *opaque) { TAPState *s = opaque; @@ -1540,8 +1555,8 @@ static TAPState *net_tap_fd_init(VLANState *vlan, s->using_vnet_hdr = 0; s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP, vlan, NULL, model, name, NULL, - tap_receive, NULL, tap_receive_iov, - tap_cleanup, s); + tap_receive, tap_receive_raw, + tap_receive_iov, tap_cleanup, s); tap_read_poll(s, 1); return s; } -- 1.6.2.5
[Qemu-devel] [PATCH 02/19] net: import linux tap ioctl definitions
Making features dependent on the availability of newer versions if_tun.h is going to get seriously clumsy, so let's just import the definitions we need. It's only a small handful. If and when we're comfortable depending on 2.6.30 headers, we can remove this again. Signed-off-by: Mark McLoughlin --- net.c | 11 +-- qemu-options.hx |8 +--- tap-linux.h | 29 + 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 tap-linux.h diff --git a/net.c b/net.c index 4708080..0e3388b 100644 --- a/net.c +++ b/net.c @@ -46,7 +46,7 @@ #include #endif #ifdef __linux__ -#include +#include "tap-linux.h" #endif #include #include @@ -1370,7 +1370,6 @@ static void tap_send(void *opaque) } while (size > 0); } -#ifdef TUNSETSNDBUF /* sndbuf should be set to a value lower than the tx queue * capacity of any destination network interface. * Ethernet NICs generally have txqueuelen=1000, so 1Mb is @@ -1393,12 +1392,6 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) } return 0; } -#else -static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) -{ -return 0; -} -#endif /* TUNSETSNDBUF */ static void tap_cleanup(VLANClientState *vc) { @@ -2972,12 +2965,10 @@ static struct { .name = "downscript", .type = QEMU_OPT_STRING, .help = "script to shut down the interface", -#ifdef TUNSETSNDBUF }, { .name = "sndbuf", .type = QEMU_OPT_SIZE, .help = "send buffer limit" -#endif }, { /* end of list */ } }, diff --git a/qemu-options.hx b/qemu-options.hx index 20aa242..c745e0c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -810,21 +810,15 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, "-net tap[,vlan=n][,name=str],ifname=name\n" "connect the host TAP network interface to VLAN 'n'\n" #else -"-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile]" -#ifdef TUNSETSNDBUF -"[,sndbuf=nbytes]" -#endif -"\n" +"-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes]\n" "connect the host TAP network interface to VLAN 'n' and use the\n" "network scripts 'file' (default=%s)\n" "and 'dfile' (default=%s);\n" "use '[down]script=no' to disable script execution;\n" "use 'fd=h' to connect to an already opened TAP interface\n" -#ifdef TUNSETSNDBUF "use 'sndbuf=nbytes' to limit the size of the send buffer; the\n" "default of 'sndbuf=1048576' can be disabled using 'sndbuf=0'\n" #endif -#endif "-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n" "connect the vlan 'n' to another VLAN using a socket connection\n" "-net socket[,vlan=n][,name=str][,fd=h][,mcast=maddr:port]\n" diff --git a/tap-linux.h b/tap-linux.h new file mode 100644 index 000..cd07ea8 --- /dev/null +++ b/tap-linux.h @@ -0,0 +1,29 @@ +/* + * Universal TUN/TAP device driver. + * Copyright (C) 1999-2000 Maxim Krasnyansky + * + * 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. + */ + +#ifndef QEMU_TAP_H +#define QEMU_TAP_H + +#include + +/* Ioctl defines */ +#define TUNSETIFF _IOW('T', 202, int) +#define TUNSETSNDBUF _IOW('T', 212, int) + +/* TUNSETIFF ifr flags */ +#define IFF_TAP0x0002 +#define IFF_NO_PI 0x1000 + +#endif /* QEMU_TAP_H */ -- 1.6.2.5
[Qemu-devel] [PATCH 00/19 v2] Add virtio-net/tap support for partial csums and GSO
Hey, Over a year ago we added some code to qemu-kvm.git which takes advantage of the recent tun/tap IFF_VNET_HDR feature in order to allow virtio-net to send and receive packets with partial checksums and segmentation offloaded: http://article.gmane.org/gmane.comp.emulators.kvm.devel/20440 "This allows us to pass larger packets and packets with partial checkums between the guest and the host, greatly increasing the achievable bandwidth." Unfortunately, that implementation was quite hacky as it made some assumptions that would break if e.g. you added another network client to a vlan where the feature had enabled. Now that we have the -netdev parameter, we can more safely pair the NIC and backend, allowing us to negatiate features like this. What follows is a somewhat cleaned up version of the code from qemu-kvm.git. Further cleanups are probably possible, but I think this much is mergeable. Some points of discussion: - If you start a guest on a host which supports IFF_VNET_HDR and migrate to a host which doesn't support it, we can't just tell the guest to stop using GSO. We need prevent this by rejecting the migration on the destination if IFF_VNET_HDR is required but not available. However, in my testing if a load() function returns an error, the migration is seen to have completed on the source but failed on the destination. Clearly that's wrong, but I haven't investigated further yet. Also, we provide a vnet_hdr= arg so that people can prevent the feature being used on the source or require that is available on the destination. - I've slightly abused QemuOpts in 05/19. Comments welcome. - The whole mess around adding a 'raw' packet flag for the gratuitous ARP packet is gratuitously messy. - I'm always enabling IFF_VNET_HDR if it's available. I don't think that's a problem, especially compared to what would be required to only selectively enable it. Changes since v1: - add has_vnet_hdr and has_ufo fields for ease of vmstate conversion - use qemu_error() in virtio_net_load() Cheers, Mark.
[Qemu-devel] [PATCH 03/19] net: make tap_receive() re-use tap_receive_iov() code
In future we will want to prepend a virtio_net header if the NIC didn't supply one but IFF_VNET_HDR is enabled on the interface. This is most easily achived by using writev() in all cases. Signed-off-by: Mark McLoughlin --- net.c | 23 +++ 1 files changed, 15 insertions(+), 8 deletions(-) diff --git a/net.c b/net.c index 0e3388b..728941a 100644 --- a/net.c +++ b/net.c @@ -1291,10 +1291,8 @@ static void tap_writable(void *opaque) qemu_flush_queued_packets(s->vc); } -static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, - int iovcnt) +static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt) { -TAPState *s = vc->opaque; ssize_t len; do { @@ -1309,16 +1307,25 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, return len; } +static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, + int iovcnt) +{ +TAPState *s = vc->opaque; + +return tap_write_packet(s, iov, iovcnt); +} + static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) { TAPState *s = vc->opaque; -ssize_t len; +struct iovec iov[1]; +int iovcnt = 0; -do { -len = write(s->fd, buf, size); -} while (len == -1 && (errno == EINTR || errno == EAGAIN)); +iov[iovcnt].iov_base = (char *)buf; +iov[iovcnt].iov_len = size; +iovcnt++; -return len; +return tap_write_packet(s, iov, iovcnt); } static int tap_can_send(void *opaque) -- 1.6.2.5
[Qemu-devel] [PATCH 10/19] net: add an API for 'raw' packets
In the case where a NIC and backend agree on a packet header format, this API allows injecting packets which lack the agreed upon header. We need this for sending our gratuitous ARP. Signed-off-by: Mark McLoughlin --- net-queue.h |1 + net.c | 37 + net.h |2 ++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/net-queue.h b/net-queue.h index 343760e..a31958e 100644 --- a/net-queue.h +++ b/net-queue.h @@ -44,6 +44,7 @@ typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender, void *opaque); #define QEMU_NET_PACKET_FLAG_NONE 0 +#define QEMU_NET_PACKET_FLAG_RAW (1<<0) NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, NetPacketDeliverIOV *deliver_iov, diff --git a/net.c b/net.c index 30dc402..50d2f83 100644 --- a/net.c +++ b/net.c @@ -463,7 +463,10 @@ static ssize_t qemu_deliver_packet(VLANClientState *sender, return size; } -return vc->receive(vc, data, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) +return vc->receive_raw(vc, data, size); +else +return vc->receive(vc, data, size); } static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, @@ -488,7 +491,10 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender, continue; } -len = vc->receive(vc, buf, size); +if (flags & QEMU_NET_PACKET_FLAG_RAW && vc->receive_raw) +len = vc->receive_raw(vc, buf, size); +else +len = vc->receive(vc, buf, size); ret = (ret >= 0) ? ret : len; } @@ -526,9 +532,10 @@ void qemu_flush_queued_packets(VLANClientState *vc) qemu_net_queue_flush(queue); } -ssize_t qemu_send_packet_async(VLANClientState *sender, - const uint8_t *buf, int size, - NetPacketSent *sent_cb) +static ssize_t qemu_send_packet_async_with_flags(VLANClientState *sender, + unsigned flags, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) { NetQueue *queue; @@ -547,9 +554,15 @@ ssize_t qemu_send_packet_async(VLANClientState *sender, queue = sender->vlan->send_queue; } -return qemu_net_queue_send(queue, sender, - QEMU_NET_PACKET_FLAG_NONE, - buf, size, sent_cb); +return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); +} + +ssize_t qemu_send_packet_async(VLANClientState *sender, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) +{ +return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE, + buf, size, sent_cb); } void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) @@ -557,6 +570,12 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) qemu_send_packet_async(vc, buf, size, NULL); } +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size) +{ +return qemu_send_packet_async_with_flags(vc, QEMU_NET_PACKET_FLAG_RAW, + buf, size, NULL); +} + static ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, int iovcnt) { @@ -626,6 +645,8 @@ static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender, continue; } +assert(!(flags & QEMU_NET_PACKET_FLAG_RAW)); + if (vc->receive_iov) { len = vc->receive_iov(vc, iov, iovcnt); } else { diff --git a/net.h b/net.h index 5f28860..53d813c 100644 --- a/net.h +++ b/net.h @@ -28,6 +28,7 @@ typedef void (LinkStatusChanged)(VLANClientState *); struct VLANClientState { net_client_type type; NetReceive *receive; +NetReceive *receive_raw; NetReceiveIOV *receive_iov; /* Packets may still be sent if this returns zero. It's used to rate-limit the slirp code. */ @@ -72,6 +73,7 @@ ssize_t qemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, ssize_t qemu_sendv_packet_async(VLANClientState *vc, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb); void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); +ssize_t qemu_send_packet_raw(VLANClientState *vc, const uint8_t *buf, int size); ssize_t qemu_send_packet_async(VLANClientState *vc, const uint8_t *buf, int size, NetPacketSent *sent_cb); void qemu_purge_queued_packets(VLANClientState *vc); -- 1.6.2.5
[Qemu-devel] [PATCH 08/19] net: add tap_has_vnet_hdr() and tap_using_vnet_hdr() APIs
These lamely named functions allow virtio-net to query whether IFF_VNET_HDR is enabled on a tap interface and inform the tap code that virtio-net will supply packets with a vnet header. Signed-off-by: Mark McLoughlin --- net.c | 39 +++ net.h |3 +++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/net.c b/net.c index 638ba36..56d979b 100644 --- a/net.c +++ b/net.c @@ -1246,7 +1246,15 @@ void do_info_usernet(Monitor *mon) #endif /* CONFIG_SLIRP */ -#if !defined(_WIN32) +#if defined(_WIN32) +int tap_has_vnet_hdr(VLANClientState *vc) +{ +return 0; +} +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +{ +} +#else /* !defined(_WIN32) */ /* Maximum GSO packet size (64k) plus plenty of room for * the ethernet and virtio_net headers @@ -1262,6 +1270,7 @@ typedef struct TAPState { unsigned int read_poll : 1; unsigned int write_poll : 1; unsigned int has_vnet_hdr : 1; +unsigned int using_vnet_hdr : 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1324,7 +1333,7 @@ static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, struct iovec iov_copy[iovcnt + 1]; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { iov_copy[0].iov_base = &hdr; iov_copy[0].iov_len = sizeof(hdr); memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); @@ -1342,7 +1351,7 @@ static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) int iovcnt = 0; struct virtio_net_hdr hdr = { 0, }; -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { iov[iovcnt].iov_base = &hdr; iov[iovcnt].iov_len = sizeof(hdr); iovcnt++; @@ -1399,7 +1408,7 @@ static void tap_send(void *opaque) break; } -if (s->has_vnet_hdr) { +if (s->has_vnet_hdr && !s->using_vnet_hdr) { buf += sizeof(struct virtio_net_hdr); size -= sizeof(struct virtio_net_hdr); } @@ -1434,6 +1443,27 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +int tap_has_vnet_hdr(VLANClientState *vc) +{ +TAPState *s = vc->opaque; + +assert(vc->type == NET_CLIENT_TYPE_TAP); + +return s->has_vnet_hdr; +} + +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) +{ +TAPState *s = vc->opaque; + +using_vnet_hdr = using_vnet_hdr != 0; + +assert(vc->type == NET_CLIENT_TYPE_TAP); +assert(s->has_vnet_hdr == using_vnet_hdr); + +s->using_vnet_hdr = using_vnet_hdr; +} + static int tap_probe_vnet_hdr(int fd) { struct ifreq ifr; @@ -1474,6 +1504,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; s->has_vnet_hdr = vnet_hdr != 0; +s->using_vnet_hdr = 0; s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP, vlan, NULL, model, name, NULL, tap_receive, tap_receive_iov, diff --git a/net.h b/net.h index aefeef4..5f28860 100644 --- a/net.h +++ b/net.h @@ -165,4 +165,7 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev, NetCleanup *cleanup, void *opaque); +int tap_has_vnet_hdr(VLANClientState *vc); +void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); + #endif -- 1.6.2.5
[Qemu-devel] [PATCH 05/19] net: refactor tap initialization
Re-factor things so that there is only one call site for net_tap_fd_init(). Two concerns about the QemuOpts usage here - firstly, we set the script arguments to their default value and, secondly, we set the ifname value to the name allocated by the kernel if none is supplied. Are we okay with such things ending up in writeconfig output? Signed-off-by: Mark McLoughlin --- net.c | 97 +++-- 1 files changed, 52 insertions(+), 45 deletions(-) diff --git a/net.c b/net.c index 356a280..fccabdb 100644 --- a/net.c +++ b/net.c @@ -1475,7 +1475,6 @@ static TAPState *net_tap_fd_init(VLANState *vlan, tap_receive, tap_receive_iov, tap_cleanup, s); tap_read_poll(s, 1); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd); return s; } @@ -1724,38 +1723,34 @@ static int launch_script(const char *setup_script, const char *ifname, int fd) return -1; } -static TAPState *net_tap_init(VLANState *vlan, const char *model, - const char *name, const char *ifname1, - const char *setup_script, const char *down_script) +static int net_tap_init(QemuOpts *opts, int *vnet_hdr) { -TAPState *s; -int fd, vnet_hdr; -char ifname[128]; +int fd; +char ifname[128] = {0,}; +const char *setup_script; -if (ifname1 != NULL) -pstrcpy(ifname, sizeof(ifname), ifname1); -else -ifname[0] = '\0'; -vnet_hdr = 0; -TFR(fd = tap_open(ifname, sizeof(ifname), &vnet_hdr)); -if (fd < 0) -return NULL; +if (qemu_opt_get(opts, "ifname")) { +pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname")); +} -if (!setup_script || !strcmp(setup_script, "no")) -setup_script = ""; -if (setup_script[0] != '\0' && -launch_script(setup_script, ifname, fd)) { -return NULL; +*vnet_hdr = 0; +TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr)); +if (fd < 0) { +return -1; } -s = net_tap_fd_init(vlan, model, name, fd, vnet_hdr); -snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "ifname=%s,script=%s,downscript=%s", - ifname, setup_script, down_script); -if (down_script && strcmp(down_script, "no")) { -snprintf(s->down_script, sizeof(s->down_script), "%s", down_script); -snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); + +setup_script = qemu_opt_get(opts, "script"); +if (setup_script && +setup_script[0] != '\0' && +strcmp(setup_script, "no") != 0 && +launch_script(setup_script, ifname, fd)) { +close(fd); +return -1; } -return s; + +qemu_opt_set(opts, "ifname", ifname); + +return fd; } #endif /* !_WIN32 */ @@ -2683,10 +2678,9 @@ static int net_init_tap(QemuOpts *opts, VLANState *vlan) { TAPState *s; +int fd, vnet_hdr; if (qemu_opt_get(opts, "fd")) { -int fd; - if (qemu_opt_get(opts, "ifname") || qemu_opt_get(opts, "script") || qemu_opt_get(opts, "downscript")) { @@ -2701,28 +2695,22 @@ static int net_init_tap(QemuOpts *opts, fcntl(fd, F_SETFL, O_NONBLOCK); -s = net_tap_fd_init(vlan, "tap", name, fd, tap_probe_vnet_hdr(fd)); -if (!s) { -close(fd); -} +vnet_hdr = tap_probe_vnet_hdr(fd); } else { -const char *ifname, *script, *downscript; - -ifname = qemu_opt_get(opts, "ifname"); -script = qemu_opt_get(opts, "script"); -downscript = qemu_opt_get(opts, "downscript"); - -if (!script) { -script = DEFAULT_NETWORK_SCRIPT; +if (!qemu_opt_get(opts, "script")) { +qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT); } -if (!downscript) { -downscript = DEFAULT_NETWORK_DOWN_SCRIPT; + +if (!qemu_opt_get(opts, "downscript")) { +qemu_opt_set(opts, "downscript", DEFAULT_NETWORK_DOWN_SCRIPT); } -s = net_tap_init(vlan, "tap", name, ifname, script, downscript); +fd = net_tap_init(opts, &vnet_hdr); } +s = net_tap_fd_init(vlan, "tap", name, fd, vnet_hdr); if (!s) { +close(fd); return -1; } @@ -2730,6 +2718,25 @@ static int net_init_tap(QemuOpts *opts, return -1; } +if (qemu_opt_get(opts, "fd")) { +snprintf(s->vc->info_str, sizeof(s-&g
[Qemu-devel] [PATCH 14/19] virtio-net: add vnet_hdr support
With '-netdev tap,id=foo -nic model=virtio,netdev=foo' virtio-net can detect that its peer (i.e. the tap backend) supports vnet headers and advertise to the guest that it can send packets with partial checksums and/or TSO packets. One complication is that if we're migrating and the source host supports IFF_VNET_HDR but the destination host doesn't, we can't then stop the guest from using those features. In this scenario, we just fail the migration. [v2: - add has_vnet_hdr uint32_t field for ease of vmstate conversion - use qemu_error() ] Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 51 --- 1 files changed, 44 insertions(+), 7 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 218f985..bb085ae 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -32,6 +32,7 @@ typedef struct VirtIONet VLANClientState *vc; QEMUTimer *tx_timer; int tx_timer_active; +uint32_t has_vnet_hdr; struct { VirtQueueElement elem; ssize_t len; @@ -120,8 +121,22 @@ static void virtio_net_reset(VirtIODevice *vdev) memset(n->vlans, 0, MAX_VLAN >> 3); } +static int peer_has_vnet_hdr(VirtIONet *n) +{ +if (!n->vc->peer) +return 0; + +if (n->vc->peer->type != NET_CLIENT_TYPE_TAP) +return 0; + +n->has_vnet_hdr = tap_has_vnet_hdr(n->vc->peer); + +return n->has_vnet_hdr; +} + static uint32_t virtio_net_get_features(VirtIODevice *vdev) { +VirtIONet *n = to_virtio_net(vdev); uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_MRG_RXBUF) | (1 << VIRTIO_NET_F_STATUS) | @@ -130,6 +145,15 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) (1 << VIRTIO_NET_F_CTRL_VLAN) | (1 << VIRTIO_NET_F_CTRL_RX_EXTRA); +if (peer_has_vnet_hdr(n)) { +tap_using_vnet_hdr(n->vc->peer, 1); + +features |= (1 << VIRTIO_NET_F_CSUM); +features |= (1 << VIRTIO_NET_F_HOST_TSO4); +features |= (1 << VIRTIO_NET_F_HOST_TSO6); +features |= (1 << VIRTIO_NET_F_HOST_ECN); +} + return features; } @@ -359,6 +383,11 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt, hdr->flags = 0; hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE; +if (n->has_vnet_hdr) { +memcpy(hdr, buf, sizeof(*hdr)); +offset = sizeof(*hdr); +} + /* We only ever receive a struct virtio_net_hdr from the tapfd, * but we may be passing along a larger header to the guest. */ @@ -378,6 +407,10 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size) if (n->promisc) return 1; +if (n->has_vnet_hdr) { +ptr += sizeof(struct virtio_net_hdr); +} + if (!memcmp(&ptr[12], vlan, sizeof(vlan))) { int vid = be16_to_cpup((uint16_t *)(ptr + 14)) & 0xfff; if (!(n->vlans[vid >> 5] & (1U << (vid & 0x1f @@ -510,7 +543,6 @@ static void virtio_net_tx_complete(VLANClientState *vc, ssize_t len) static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) { VirtQueueElement elem; -int has_vnet_hdr = 0; if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) return; @@ -537,7 +569,7 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq) } /* ignore the header if GSO is not supported */ -if (!has_vnet_hdr) { +if (!n->has_vnet_hdr) { out_num--; out_sg++; len += hdr_len; @@ -610,7 +642,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque) qemu_put_be32(f, n->mac_table.in_use); qemu_put_buffer(f, n->mac_table.macs, n->mac_table.in_use * ETH_ALEN); qemu_put_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); -qemu_put_be32(f, 0); /* vnet-hdr placeholder */ +qemu_put_be32(f, n->has_vnet_hdr); qemu_put_byte(f, n->mac_table.multi_overflow); qemu_put_byte(f, n->mac_table.uni_overflow); qemu_put_byte(f, n->alluni); @@ -662,10 +694,15 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) if (version_id >= 6) qemu_get_buffer(f, (uint8_t *)n->vlans, MAX_VLAN >> 3); -if (version_id >= 7 && qemu_get_be32(f)) { -fprintf(stderr, -"virtio-net: saved image requires vnet header support\n"); -exit(1); +if (version_id >= 7) { +if (qemu_get_be32(f) && !peer_has_vnet_hdr(n)) { +qemu_error("virtio-net: saved image requires vnet_hdr=on\n"); +return -1; +} + +if (n->has_vnet_hdr) { +tap_using_vnet_hdr(n->vc->peer, 1); +} } if (version_id >= 9) { -- 1.6.2.5
[Qemu-devel] [PATCH 18/19] Enable UFO on virtio-net and tap devices
From: Sridhar Samudrala Enable UFO on the host tap device if supported and allow setting UFO on virtio-net in the guest. Signed-off-by: Sridhar Samudrala Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 11 +-- net.c | 36 net.h |3 ++- tap-linux.h |1 + 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index e00c404..31ac9ef 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -157,6 +157,11 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) features |= (1 << VIRTIO_NET_F_GUEST_TSO4); features |= (1 << VIRTIO_NET_F_GUEST_TSO6); features |= (1 << VIRTIO_NET_F_GUEST_ECN); + +if (tap_has_ufo(n->vc->peer)) { +features |= (1 << VIRTIO_NET_F_GUEST_UFO); +features |= (1 << VIRTIO_NET_F_HOST_UFO); +} } return features; @@ -188,7 +193,8 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) (features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (features >> VIRTIO_NET_F_GUEST_TSO4) & 1, (features >> VIRTIO_NET_F_GUEST_TSO6) & 1, -(features >> VIRTIO_NET_F_GUEST_ECN) & 1); +(features >> VIRTIO_NET_F_GUEST_ECN) & 1, +(features >> VIRTIO_NET_F_GUEST_UFO) & 1); } } @@ -748,7 +754,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) (n->vdev.features >> VIRTIO_NET_F_GUEST_CSUM) & 1, (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO4) & 1, (n->vdev.features >> VIRTIO_NET_F_GUEST_TSO6) & 1, -(n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1); +(n->vdev.features >> VIRTIO_NET_F_GUEST_ECN) & 1, +(n->vdev.features >> VIRTIO_NET_F_GUEST_UFO) & 1); } } diff --git a/net.c b/net.c index 746a3d6..3e54c53 100644 --- a/net.c +++ b/net.c @@ -1280,6 +1280,10 @@ void do_info_usernet(Monitor *mon) #endif /* CONFIG_SLIRP */ #if defined(_WIN32) +int tap_has_ufo(VLANClientState *vc) +{ +return 0; +} int tap_has_vnet_hdr(VLANClientState *vc) { return 0; @@ -1287,7 +1291,8 @@ int tap_has_vnet_hdr(VLANClientState *vc) void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) { } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +void tap_set_offload(VLANClientState *vc, int csum, int tso4, + int tso6, int ecn, int ufo) { } #else /* !defined(_WIN32) */ @@ -1307,6 +1312,7 @@ typedef struct TAPState { unsigned int write_poll : 1; unsigned int has_vnet_hdr : 1; unsigned int using_vnet_hdr : 1; +unsigned int has_ufo: 1; } TAPState; static int launch_script(const char *setup_script, const char *ifname, int fd); @@ -1494,6 +1500,15 @@ static int tap_set_sndbuf(TAPState *s, QemuOpts *opts) return 0; } +int tap_has_ufo(VLANClientState *vc) +{ +TAPState *s = vc->opaque; + +assert(vc->type == NET_CLIENT_TYPE_TAP); + +return s->has_ufo; +} + int tap_has_vnet_hdr(VLANClientState *vc) { TAPState *s = vc->opaque; @@ -1527,7 +1542,8 @@ static int tap_probe_vnet_hdr(int fd) return ifr.ifr_flags & IFF_VNET_HDR; } -void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) +void tap_set_offload(VLANClientState *vc, int csum, int tso4, + int tso6, int ecn, int ufo) { TAPState *s = vc->opaque; unsigned int offload = 0; @@ -1540,11 +1556,16 @@ void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn) offload |= TUN_F_TSO6; if ((tso4 || tso6) && ecn) offload |= TUN_F_TSO_ECN; +if (ufo) +offload |= TUN_F_UFO; } if (ioctl(s->fd, TUNSETOFFLOAD, offload) != 0) { -fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", -strerror(errno)); +offload &= ~TUN_F_UFO; +if (ioctl(s->fd, TUNSETOFFLOAD, offload) != 0) { +fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", +strerror(errno)); +} } } @@ -1572,6 +1593,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int vnet_hdr) { TAPState *s; +unsigned int offload; s = qemu_mallocz(sizeof(TAPState)); s->fd = fd; @@ -1581,6 +1603,12 @@ static TAPState *net_tap_fd_init(VLANState *vlan, vlan, NULL, model, name, NULL,
[Qemu-devel] [PATCH 09/19] net: add flags parameter to packet queue interface
This allows for the addition of a raw flag, and leaves the way open for other flags too. Signed-off-by: Mark McLoughlin --- net-queue.c | 26 ++ net-queue.h |6 ++ net.c | 14 -- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/net-queue.c b/net-queue.c index 75457f0..f6b01e9 100644 --- a/net-queue.c +++ b/net-queue.c @@ -41,6 +41,7 @@ struct NetPacket { QTAILQ_ENTRY(NetPacket) entry; VLANClientState *sender; +unsigned flags; int size; NetPacketSent *sent_cb; uint8_t data[0]; @@ -89,6 +90,7 @@ void qemu_del_net_queue(NetQueue *queue) static ssize_t qemu_net_queue_append(NetQueue *queue, VLANClientState *sender, + unsigned flags, const uint8_t *buf, size_t size, NetPacketSent *sent_cb) @@ -97,6 +99,7 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, packet = qemu_malloc(sizeof(NetPacket) + size); packet->sender = sender; +packet->flags = flags; packet->size = size; packet->sent_cb = sent_cb; memcpy(packet->data, buf, size); @@ -108,6 +111,7 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, static ssize_t qemu_net_queue_append_iov(NetQueue *queue, VLANClientState *sender, + unsigned flags, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb) @@ -123,6 +127,7 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, packet = qemu_malloc(sizeof(NetPacket) + max_len); packet->sender = sender; packet->sent_cb = sent_cb; +packet->flags = flags; packet->size = 0; for (i = 0; i < iovcnt; i++) { @@ -139,13 +144,14 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, static ssize_t qemu_net_queue_deliver(NetQueue *queue, VLANClientState *sender, + unsigned flags, const uint8_t *data, size_t size) { ssize_t ret = -1; queue->delivering = 1; -ret = queue->deliver(sender, data, size, queue->opaque); +ret = queue->deliver(sender, flags, data, size, queue->opaque); queue->delivering = 0; return ret; @@ -153,13 +159,14 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue, static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, VLANClientState *sender, + unsigned flags, const struct iovec *iov, int iovcnt) { ssize_t ret = -1; queue->delivering = 1; -ret = queue->deliver_iov(sender, iov, iovcnt, queue->opaque); +ret = queue->deliver_iov(sender, flags, iov, iovcnt, queue->opaque); queue->delivering = 0; return ret; @@ -167,6 +174,7 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue, ssize_t qemu_net_queue_send(NetQueue *queue, VLANClientState *sender, +unsigned flags, const uint8_t *data, size_t size, NetPacketSent *sent_cb) @@ -174,12 +182,12 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t ret; if (queue->delivering) { -return qemu_net_queue_append(queue, sender, data, size, NULL); +return qemu_net_queue_append(queue, sender, flags, data, size, NULL); } -ret = qemu_net_queue_deliver(queue, sender, data, size); +ret = qemu_net_queue_deliver(queue, sender, flags, data, size); if (ret == 0 && sent_cb != NULL) { -qemu_net_queue_append(queue, sender, data, size, sent_cb); +qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); return 0; } @@ -190,6 +198,7 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t qemu_net_queue_send_iov(NetQueue *queue, VLANClientState *sender, +unsigned flags, const struct iovec *iov, int iovcnt, NetPacketSent *sent_cb) @@ -197,12 +206,12 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, ssize_t ret; if (queue->delivering) { -return qemu_net_queue_append_iov(queue, sender, iov, iovcnt, NULL); +return qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, NULL);
[Qemu-devel] [PATCH 19/19] virtio-net: add tap_has_ufo flag to saved state
If we tell the guest we support UFO and then migrate to host which doesn't support it, we will find ourselves in grave difficulties. Prevent this scenario by adding a flag to virtio-net's savevm format which indicates whether the device requires host UFO support. [v2: - add has_ufo uint8_t field for ease of vmstate conversion - use qemu_error() ] Signed-off-by: Mark McLoughlin --- hw/virtio-net.c | 23 +-- 1 files changed, 21 insertions(+), 2 deletions(-) diff --git a/hw/virtio-net.c b/hw/virtio-net.c index 31ac9ef..15b6f45 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -16,7 +16,7 @@ #include "qemu-timer.h" #include "virtio-net.h" -#define VIRTIO_NET_VM_VERSION10 +#define VIRTIO_NET_VM_VERSION11 #define MAC_TABLE_ENTRIES64 #define MAX_VLAN(1 << 12) /* Per 802.1Q definition */ @@ -33,6 +33,7 @@ typedef struct VirtIONet QEMUTimer *tx_timer; int tx_timer_active; uint32_t has_vnet_hdr; +uint8_t has_ufo; struct { VirtQueueElement elem; ssize_t len; @@ -134,6 +135,16 @@ static int peer_has_vnet_hdr(VirtIONet *n) return n->has_vnet_hdr; } +static int peer_has_ufo(VirtIONet *n) +{ +if (!peer_has_vnet_hdr(n)) +return 0; + +n->has_ufo = tap_has_ufo(n->vc->peer); + +return n->has_ufo; +} + static uint32_t virtio_net_get_features(VirtIODevice *vdev) { VirtIONet *n = to_virtio_net(vdev); @@ -158,7 +169,7 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev) features |= (1 << VIRTIO_NET_F_GUEST_TSO6); features |= (1 << VIRTIO_NET_F_GUEST_ECN); -if (tap_has_ufo(n->vc->peer)) { +if (peer_has_ufo(n)) { features |= (1 << VIRTIO_NET_F_GUEST_UFO); features |= (1 << VIRTIO_NET_F_HOST_UFO); } @@ -697,6 +708,7 @@ static void virtio_net_save(QEMUFile *f, void *opaque) qemu_put_byte(f, n->nomulti); qemu_put_byte(f, n->nouni); qemu_put_byte(f, n->nobcast); +qemu_put_byte(f, n->has_ufo); } static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) @@ -771,6 +783,13 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id) n->nobcast = qemu_get_byte(f); } +if (version_id >= 11) { +if (qemu_get_byte(f) && !peer_has_ufo(n)) { +qemu_error("virtio-net: saved image requires TUN_F_UFO support\n"); +return -1; +} +} + /* Find the first multicast entry in the saved MAC filter */ for (i = 0; i < n->mac_table.in_use; i++) { if (n->mac_table.macs[i * ETH_ALEN] & 1) { -- 1.6.2.5
[Qemu-devel] [PATCH 00/15] Some networking code re-organization
Hey, We've been meaning to split net.c up for quite a while now, so here goes with a first cut at. There shouldn't be anything too controversial here, apart from CONFIG_LINUX maybe. I've build tested this on F11, F12 and mingw and also done some basic runtime testing. Building on e.g. *BSD, Solaris and AIX hasn't been tested. I wouldn't be surprised if I've broken the build there despite all my efforts but, if I have, it should be trivial to fix back up. This isn't the end of the cleanups; obviously the other backends could be split out too, we could use module construtors, etc. Cheers, Mark.
[Qemu-devel] [PATCH 03/15] net: move tap-win32.c under net/
Signed-off-by: Mark McLoughlin --- Makefile|2 +- net/tap-win32.c | 690 +++ tap-win32.c | 690 --- 3 files changed, 691 insertions(+), 691 deletions(-) create mode 100644 net/tap-win32.c delete mode 100644 tap-win32.c diff --git a/Makefile b/Makefile index c8c0b18..a49177f 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,7 @@ block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o net-nested-y = queue.o checksum.o +net-nested-$(CONFIG_WIN32) += tap-win32.o net-obj-y += $(addprefix net/, $(net-nested-y)) ## @@ -132,7 +133,6 @@ obj-y += qdev.o qdev-properties.o obj-y += qint.o qstring.o qdict.o qlist.o qemu-config.o obj-$(CONFIG_BRLAPI) += baum.o -obj-$(CONFIG_WIN32) += tap-win32.o obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS) diff --git a/net/tap-win32.c b/net/tap-win32.c new file mode 100644 index 000..7d92df2 --- /dev/null +++ b/net/tap-win32.c @@ -0,0 +1,690 @@ +/* + * TAP-Win32 -- A kernel driver to provide virtual tap device functionality + * on Windows. Originally derived from the CIPE-Win32 + * project by Damion K. Wilson, with extensive modifications by + * James Yonan. + * + * All source code which derives from the CIPE-Win32 project is + * Copyright (C) Damion K. Wilson, 2003, and is released under the + * GPL version 2 (see below). + * + * All other source code is Copyright (C) James Yonan, 2003-2004, + * and is released under the GPL version 2 (see below). + * + * 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 (see the file COPYING included with this + * distribution); if not, see <http://www.gnu.org/licenses/>. + */ +#include "qemu-common.h" +#include "net.h" +#include "sysemu.h" +#include +#include +#include + +//= +// TAP IOCTLs +//= + +#define TAP_CONTROL_CODE(request,method) \ + CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) + +#define TAP_IOCTL_GET_MAC TAP_CONTROL_CODE (1, METHOD_BUFFERED) +#define TAP_IOCTL_GET_VERSION TAP_CONTROL_CODE (2, METHOD_BUFFERED) +#define TAP_IOCTL_GET_MTU TAP_CONTROL_CODE (3, METHOD_BUFFERED) +#define TAP_IOCTL_GET_INFO TAP_CONTROL_CODE (4, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED) +#define TAP_IOCTL_SET_MEDIA_STATUS TAP_CONTROL_CODE (6, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_MASQ TAP_CONTROL_CODE (7, METHOD_BUFFERED) +#define TAP_IOCTL_GET_LOG_LINE TAP_CONTROL_CODE (8, METHOD_BUFFERED) +#define TAP_IOCTL_CONFIG_DHCP_SET_OPT TAP_CONTROL_CODE (9, METHOD_BUFFERED) + +//= +// Registry keys +//= + +#define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +#define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" + +//== +// Filesystem prefixes +//== + +#define USERMODEDEVICEDIR ".\\Global\\" +#define TAPSUFFIX ".tap" + + +//== +// Compile time configuration +//== + +//#define DEBUG_TAP_WIN32 + +#define TUN_ASYNCHRONOUS_WRITES 1 + +#define TUN_BUFFER_SIZE 1560 +#define TUN_MAX_BUFFER_COUNT 32 + +/* + * The data member "buffer" must be the first element in the tun_buffer + * structure. See the function, tap_win32_free_buffer. + */ +typedef struct tun_buffer_s { +unsigned char buffer [TUN_BUFFER_SIZE]; +unsigned long read_size; +struct tun_buffer_s* next; +} tun_buffer_t; + +typedef struct tap_win32_overlapped { +HANDLE handle; +HANDLE read_event; +HANDLE write_event; +HANDLE output_queue_semaphore; +HANDLE free_list_semaphore; +HANDLE tap_semaphore; +CRITICAL_SECTION output_queue_cs; +CRITICAL_SECTION free_list_cs; +OVERLAPPED read_overlapped; +OVERLAPPED write_overlapped; +tun_buffer_t buffers[TUN_MAX_BUFFER_COUNT]; +tun_buffer_t* free_list; +tun_buffer_t* output_q
[Qemu-devel] [PATCH 06/15] net: split all the tap code out into net/tap.c
Signed-off-by: Mark McLoughlin --- Makefile |1 + net.c | 692 +--- net.h |2 + net/tap.c | 759 + 4 files changed, 763 insertions(+), 691 deletions(-) create mode 100644 net/tap.c diff --git a/Makefile b/Makefile index a49177f..69ead10 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,7 @@ block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o net-nested-y = queue.o checksum.o +net-nested-$(CONFIG_POSIX) += tap.o net-nested-$(CONFIG_WIN32) += tap-win32.o net-obj-y += $(addprefix net/, $(net-nested-y)) diff --git a/net.c b/net.c index 3225dcd..365305a 100644 --- a/net.c +++ b/net.c @@ -42,12 +42,6 @@ #include #include #include -#ifdef __NetBSD__ -#include -#endif -#ifdef __linux__ -#include "net/tap-linux.h" -#endif #include #include #include @@ -1280,618 +1274,6 @@ void do_info_usernet(Monitor *mon) #endif /* CONFIG_SLIRP */ -#if !defined(_WIN32) && !defined(_AIX) - -/* Maximum GSO packet size (64k) plus plenty of room for - * the ethernet and virtio_net headers - */ -#define TAP_BUFSIZE (4096 + 65536) - -typedef struct TAPState { -VLANClientState *vc; -int fd; -char down_script[1024]; -char down_script_arg[128]; -uint8_t buf[TAP_BUFSIZE]; -unsigned int read_poll : 1; -unsigned int write_poll : 1; -unsigned int has_vnet_hdr : 1; -unsigned int using_vnet_hdr : 1; -unsigned int has_ufo: 1; -} TAPState; - -static int launch_script(const char *setup_script, const char *ifname, int fd); - -static int tap_can_send(void *opaque); -static void tap_send(void *opaque); -static void tap_writable(void *opaque); - -static void tap_update_fd_handler(TAPState *s) -{ -qemu_set_fd_handler2(s->fd, - s->read_poll ? tap_can_send : NULL, - s->read_poll ? tap_send : NULL, - s->write_poll ? tap_writable : NULL, - s); -} - -static void tap_read_poll(TAPState *s, int enable) -{ -s->read_poll = !!enable; -tap_update_fd_handler(s); -} - -static void tap_write_poll(TAPState *s, int enable) -{ -s->write_poll = !!enable; -tap_update_fd_handler(s); -} - -static void tap_writable(void *opaque) -{ -TAPState *s = opaque; - -tap_write_poll(s, 0); - -qemu_flush_queued_packets(s->vc); -} - -static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt) -{ -ssize_t len; - -do { -len = writev(s->fd, iov, iovcnt); -} while (len == -1 && errno == EINTR); - -if (len == -1 && errno == EAGAIN) { -tap_write_poll(s, 1); -return 0; -} - -return len; -} - -static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, - int iovcnt) -{ -TAPState *s = vc->opaque; -const struct iovec *iovp = iov; -struct iovec iov_copy[iovcnt + 1]; -struct virtio_net_hdr hdr = { 0, }; - -if (s->has_vnet_hdr && !s->using_vnet_hdr) { -iov_copy[0].iov_base = &hdr; -iov_copy[0].iov_len = sizeof(hdr); -memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov)); -iovp = iov_copy; -iovcnt++; -} - -return tap_write_packet(s, iovp, iovcnt); -} - -static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -TAPState *s = vc->opaque; -struct iovec iov[2]; -int iovcnt = 0; -struct virtio_net_hdr hdr = { 0, }; - -if (s->has_vnet_hdr) { -iov[iovcnt].iov_base = &hdr; -iov[iovcnt].iov_len = sizeof(hdr); -iovcnt++; -} - -iov[iovcnt].iov_base = (char *)buf; -iov[iovcnt].iov_len = size; -iovcnt++; - -return tap_write_packet(s, iov, iovcnt); -} - -static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) -{ -TAPState *s = vc->opaque; -struct iovec iov[1]; - -if (s->has_vnet_hdr && !s->using_vnet_hdr) { -return tap_receive_raw(vc, buf, size); -} - -iov[0].iov_base = (char *)buf; -iov[0].iov_len = size; - -return tap_write_packet(s, iov, 1); -} - -static int tap_can_send(void *opaque) -{ -TAPState *s = opaque; - -return qemu_can_send_packet(s->vc); -} - -#ifdef __sun__ -static ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) -{ -struct strbuf sbuf; -int f = 0; - -sbuf.maxlen = maxlen; -sbuf.buf = (char *)buf; - -return getmsg(tapfd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1; -} -#else -static ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) -{ -return read(tapfd, buf, maxlen); -} -#endif - -static void tap_send_completed(VLANClientState *vc, ssize_t len) -{ -TAPState *s = vc->opaque; -tap_read_poll(s, 1); -} - -static void tap_send(void *opa
[Qemu-devel] [PATCH 13/15] net: move tap_probe_vnet_hdr() to tap-linux.c
Only Linux has support for IFF_VNET_HDR Signed-off-by: Mark McLoughlin --- net/tap-aix.c |4 net/tap-bsd.c |5 + net/tap-linux.c | 12 net/tap-solaris.c |5 + net/tap.c | 12 net/tap.h |1 + 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/net/tap-aix.c b/net/tap-aix.c index 3f9ccdd..27143ff 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -36,3 +36,7 @@ int tap_set_sndbuf(int fd, QemuOpts *opts) return 0; } +int tap_probe_vnet_hdr(int fd) +{ +return 0; +} diff --git a/net/tap-bsd.c b/net/tap-bsd.c index e28615f..1cdde90 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -65,3 +65,8 @@ int tap_set_sndbuf(int fd, QemuOpts *opts) { return 0; } + +int tap_probe_vnet_hdr(int fd) +{ +return 0; +} diff --git a/net/tap-linux.c b/net/tap-linux.c index 6c3b6e3..0059404 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -99,3 +99,15 @@ int tap_set_sndbuf(int fd, QemuOpts *opts) } return 0; } + +int tap_probe_vnet_hdr(int fd) +{ +struct ifreq ifr; + +if (ioctl(fd, TUNGETIFF, &ifr) != 0) { +qemu_error("TUNGETIFF ioctl() failed: %s\n", strerror(errno)); +return 0; +} + +return ifr.ifr_flags & IFF_VNET_HDR; +} diff --git a/net/tap-solaris.c b/net/tap-solaris.c index de5855a..3f48e57 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -188,3 +188,8 @@ int tap_set_sndbuf(int fd, QemuOpts *opts) { return 0; } + +int tap_probe_vnet_hdr(int fd) +{ +return 0; +} diff --git a/net/tap.c b/net/tap.c index df2cfbe..3f6722e 100644 --- a/net/tap.c +++ b/net/tap.c @@ -239,18 +239,6 @@ void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr) s->using_vnet_hdr = using_vnet_hdr; } -static int tap_probe_vnet_hdr(int fd) -{ -struct ifreq ifr; - -if (ioctl(fd, TUNGETIFF, &ifr) != 0) { -qemu_error("TUNGETIFF ioctl() failed: %s\n", strerror(errno)); -return 0; -} - -return ifr.ifr_flags & IFF_VNET_HDR; -} - void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo) { diff --git a/net/tap.h b/net/tap.h index 0d67c24..de729a7 100644 --- a/net/tap.h +++ b/net/tap.h @@ -44,5 +44,6 @@ void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr); void tap_set_offload(VLANClientState *vc, int csum, int tso4, int tso6, int ecn, int ufo); int tap_set_sndbuf(int fd, QemuOpts *opts); +int tap_probe_vnet_hdr(int fd); #endif /* QEMU_NET_TAP_H */ -- 1.6.2.5
[Qemu-devel] [PATCH 01/15] net: move net-queue.[ch] under net/
Signed-off-by: Mark McLoughlin --- Makefile|6 +- net-queue.c | 260 --- net-queue.h | 71 net.h |2 +- net/queue.c | 260 +++ net/queue.h | 71 6 files changed, 337 insertions(+), 333 deletions(-) delete mode 100644 net-queue.c delete mode 100644 net-queue.h create mode 100644 net/queue.c create mode 100644 net/queue.h diff --git a/Makefile b/Makefile index e78a3d0..6fb89fb 100644 --- a/Makefile +++ b/Makefile @@ -86,6 +86,10 @@ block-nested-$(CONFIG_CURL) += curl.o block-obj-y += $(addprefix block/, $(block-nested-y)) +net-obj-y = net.o +net-nested-y = queue.o +net-obj-y += $(addprefix net/, $(net-nested-y)) + ## # libqemu_common.a: Target independent part of system emulation. The # long term path is to suppress *all* target specific code in case of @@ -93,6 +97,7 @@ block-obj-y += $(addprefix block/, $(block-nested-y)) # CPUs and machines. obj-y = $(block-obj-y) +obj-y += $(net-obj-y) obj-y += readline.o console.o obj-y += tcg-runtime.o host-utils.o @@ -121,7 +126,6 @@ obj-$(CONFIG_SD) += sd.o obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o obj-y += bt-hci-csr.o obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o -obj-y += net.o net-queue.o obj-y += qemu-char.o aio.o net-checksum.o savevm.o obj-y += msmouse.o ps2.o obj-y += qdev.o qdev-properties.o diff --git a/net-queue.c b/net-queue.c deleted file mode 100644 index f6b01e9..000 --- a/net-queue.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2009 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "net-queue.h" -#include "qemu-queue.h" - -/* The delivery handler may only return zero if it will call - * qemu_net_queue_flush() when it determines that it is once again able - * to deliver packets. It must also call qemu_net_queue_purge() in its - * cleanup path. - * - * If a sent callback is provided to send(), the caller must handle a - * zero return from the delivery handler by not sending any more packets - * until we have invoked the callback. Only in that case will we queue - * the packet. - * - * If a sent callback isn't provided, we just drop the packet to avoid - * unbounded queueing. - */ - -struct NetPacket { -QTAILQ_ENTRY(NetPacket) entry; -VLANClientState *sender; -unsigned flags; -int size; -NetPacketSent *sent_cb; -uint8_t data[0]; -}; - -struct NetQueue { -NetPacketDeliver *deliver; -NetPacketDeliverIOV *deliver_iov; -void *opaque; - -QTAILQ_HEAD(packets, NetPacket) packets; - -unsigned delivering : 1; -}; - -NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver, - NetPacketDeliverIOV *deliver_iov, - void *opaque) -{ -NetQueue *queue; - -queue = qemu_mallocz(sizeof(NetQueue)); - -queue->deliver = deliver; -queue->deliver_iov = deliver_iov; -queue->opaque = opaque; - -QTAILQ_INIT(&queue->packets); - -queue->delivering = 0; - -return queue; -} - -void qemu_del_net_queue(NetQueue *queue) -{ -NetPacket *packet, *next; - -QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) { -QTAILQ_REMOVE(&queue->packets, packet, entry); -qemu_free(packet); -} - -qemu_free(queue); -} - -static ssize_t qemu_net_queue_append(NetQueue *queue, - VLANClientState *sender, - unsigned flags, - const uint8_t *buf, - size_t size, -