From a96ed02fc73e23748c8b3e38880eeac91f83ab9f Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 21 Aug 2012 20:52:07 +0000 Subject: monitor: Rename+move net_handle_fd_param -> monitor_handle_fd_param This patch renames+moves the net_handle_fd_param() caller used to obtain a file descriptor from either qemu_parse_fd() (the normal case) or from monitor_get_fd() (migration case) into a generically prefixed monitor_handle_fd_param() to be used by vhost-scsi code. Also update net/[socket,tap].c consumers to use the new prefix. Reported-by: Michael S. Tsirkin Cc: Michael S. Tsirkin Cc: Stefan Hajnoczi Cc: Paolo Bonzini Cc: Anthony Liguori Signed-off-by: Nicholas Bellinger Signed-off-by: Michael S. Tsirkin --- net/socket.c | 2 +- net/tap.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index c172c249be..7c602e4c3a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -629,7 +629,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, if (sock->has_fd) { int fd; - fd = net_handle_fd_param(cur_mon, sock->fd); + fd = monitor_handle_fd_param(cur_mon, sock->fd); if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } diff --git a/net/tap.c b/net/tap.c index 1971525794..a88ae8f61a 100644 --- a/net/tap.c +++ b/net/tap.c @@ -610,7 +610,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return -1; } - fd = net_handle_fd_param(cur_mon, tap->fd); + fd = monitor_handle_fd_param(cur_mon, tap->fd); if (fd == -1) { return -1; } @@ -686,7 +686,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, int vhostfd; if (tap->has_vhostfd) { - vhostfd = net_handle_fd_param(cur_mon, tap->vhostfd); + vhostfd = monitor_handle_fd_param(cur_mon, tap->vhostfd); if (vhostfd == -1) { return -1; } -- cgit v1.2.3 From 987a9b4800003567b1a47a379255e886a77d57ea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 9 Aug 2012 16:45:55 +0200 Subject: net: notify iothread after flushing queue virtio-net has code to flush the queue and notify the iothread whenever new receive buffers are added by the guest. That is fine, and indeed we need to do the same in all other drivers. However, notifying the iothread should be work for the network subsystem. And since we are at it we can add a little smartness: if some of the queued packets already could not be delivered, there is no need to notify the iothread. Reported-by: Luigi Rizzo Cc: Stefan Hajnoczi Cc: Jan Kiszka Signed-off-by: Paolo Bonzini Reviewed-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- net/queue.c | 5 +++-- net/queue.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/queue.c b/net/queue.c index e8030aafe4..6e64091463 100644 --- a/net/queue.c +++ b/net/queue.c @@ -228,7 +228,7 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) } } -void qemu_net_queue_flush(NetQueue *queue) +bool qemu_net_queue_flush(NetQueue *queue) { while (!QTAILQ_EMPTY(&queue->packets)) { NetPacket *packet; @@ -244,7 +244,7 @@ void qemu_net_queue_flush(NetQueue *queue) packet->size); if (ret == 0) { QTAILQ_INSERT_HEAD(&queue->packets, packet, entry); - break; + return false; } if (packet->sent_cb) { @@ -253,4 +253,5 @@ void qemu_net_queue_flush(NetQueue *queue) g_free(packet); } + return true; } diff --git a/net/queue.h b/net/queue.h index 9d44a9b3b8..fc02b33915 100644 --- a/net/queue.h +++ b/net/queue.h @@ -53,6 +53,6 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, NetPacketSent *sent_cb); void qemu_net_queue_purge(NetQueue *queue, NetClientState *from); -void qemu_net_queue_flush(NetQueue *queue); +bool qemu_net_queue_flush(NetQueue *queue); #endif /* QEMU_NET_QUEUE_H */ -- cgit v1.2.3 From 06b5f36d052b540a59b52150582d65674199b2ce Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 13:35:23 +0100 Subject: net: do not report queued packets as sent Net send functions have a return value where 0 means the packet has not been sent and will be queued. A non-zero value means the packet was sent or an error caused the packet to be dropped. This patch fixes two instances where packets are queued but we return their size. This causes callers to believe the packets were sent. When the caller uses the async send interface this creates a real problem because the callback will be invoked for a packet that the caller believed to be already sent. This bug can cause double-frees in the caller. Signed-off-by: Stefan Hajnoczi --- net/queue.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/queue.c b/net/queue.c index 6e64091463..254f28013a 100644 --- a/net/queue.c +++ b/net/queue.c @@ -83,12 +83,12 @@ void qemu_del_net_queue(NetQueue *queue) g_free(queue); } -static ssize_t qemu_net_queue_append(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const uint8_t *buf, - size_t size, - NetPacketSent *sent_cb) +static void qemu_net_queue_append(NetQueue *queue, + NetClientState *sender, + unsigned flags, + const uint8_t *buf, + size_t size, + NetPacketSent *sent_cb) { NetPacket *packet; @@ -100,16 +100,14 @@ static ssize_t qemu_net_queue_append(NetQueue *queue, memcpy(packet->data, buf, size); QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); - - return size; } -static ssize_t qemu_net_queue_append_iov(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - NetPacketSent *sent_cb) +static void qemu_net_queue_append_iov(NetQueue *queue, + NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt, + NetPacketSent *sent_cb) { NetPacket *packet; size_t max_len = 0; @@ -133,8 +131,6 @@ static ssize_t qemu_net_queue_append_iov(NetQueue *queue, } QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); - - return packet->size; } static ssize_t qemu_net_queue_deliver(NetQueue *queue, @@ -177,7 +173,8 @@ ssize_t qemu_net_queue_send(NetQueue *queue, ssize_t ret; if (queue->delivering || !qemu_can_send_packet(sender)) { - return qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); + qemu_net_queue_append(queue, sender, flags, data, size, sent_cb); + return 0; } ret = qemu_net_queue_deliver(queue, sender, flags, data, size); @@ -201,8 +198,8 @@ ssize_t qemu_net_queue_send_iov(NetQueue *queue, ssize_t ret; if (queue->delivering || !qemu_can_send_packet(sender)) { - return qemu_net_queue_append_iov(queue, sender, flags, - iov, iovcnt, sent_cb); + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb); + return 0; } ret = qemu_net_queue_deliver_iov(queue, sender, flags, iov, iovcnt); -- cgit v1.2.3 From 61518a74ca98870e8ff132f91dd5dda252e31f58 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Fri, 24 Aug 2012 13:50:30 +0100 Subject: net: broadcast hub packets if at least one port can receive In commit 60c07d933c66c4b30a83b7ccbc8a0cb3df1b2d0e ("net: fix qemu_can_send_packet logic") the "VLAN" broadcast behavior was changed to queue packets if any net client cannot receive. It turns out that this was not actually the right fix and just hides the real bug that hw/usb/dev-network.c:usbnet_receive() clobbers its receive buffer when called multiple times in a row. The commit also introduced a new bug that "VLAN" packets would not be sent if one of multiple net clients was down. The hw/usb/dev-network.c bug has since been fixed, so this patch reverts broadcast behavior to send packets as long as one net client can receive. Packets simply get queued for the net clients that are temporarily unable to receive. Reported-by: Roy.Li Signed-off-by: Stefan Hajnoczi --- net/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/hub.c b/net/hub.c index ac157e32ee..650a8b4a40 100644 --- a/net/hub.c +++ b/net/hub.c @@ -97,12 +97,12 @@ static int net_hub_port_can_receive(NetClientState *nc) continue; } - if (!qemu_can_send_packet(&port->nc)) { - return 0; + if (qemu_can_send_packet(&port->nc)) { + return 1; } } - return 1; + return 0; } static ssize_t net_hub_port_receive(NetClientState *nc, -- cgit v1.2.3 From 863f678fba4191f3b695620f41056cb7c124425d Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:21:54 +0100 Subject: net: asynchronous send/receive infrastructure for net/socket.c The net/socket.c net client is not truly asynchronous. This patch borrows the qemu_set_fd_handler2() code from net/tap.c as the basis for proper asynchronous send/receive. Only read packets from the socket when the peer is able to receive. This avoids needless queuing. Later patches implement asynchronous send. Signed-off-by: Stefan Hajnoczi --- net/socket.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 7c602e4c3a..7bff5367ac 100644 --- a/net/socket.c +++ b/net/socket.c @@ -42,9 +42,51 @@ typedef struct NetSocketState { unsigned int packet_len; uint8_t buf[4096]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ + IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ + bool read_poll; /* waiting to receive data? */ + bool write_poll; /* waiting to transmit data? */ } NetSocketState; static void net_socket_accept(void *opaque); +static void net_socket_writable(void *opaque); + +/* Only read packets from socket when peer can receive them */ +static int net_socket_can_send(void *opaque) +{ + NetSocketState *s = opaque; + + return qemu_can_send_packet(&s->nc); +} + +static void net_socket_update_fd_handler(NetSocketState *s) +{ + qemu_set_fd_handler2(s->fd, + s->read_poll ? net_socket_can_send : NULL, + s->read_poll ? s->send_fn : NULL, + s->write_poll ? net_socket_writable : NULL, + s); +} + +static void net_socket_read_poll(NetSocketState *s, bool enable) +{ + s->read_poll = enable; + net_socket_update_fd_handler(s); +} + +static void net_socket_write_poll(NetSocketState *s, bool enable) +{ + s->write_poll = enable; + net_socket_update_fd_handler(s); +} + +static void net_socket_writable(void *opaque) +{ + NetSocketState *s = opaque; + + net_socket_write_poll(s, false); + + qemu_flush_queued_packets(&s->nc); +} /* XXX: we consider we can send the whole packet without blocking */ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) @@ -81,7 +123,8 @@ static void net_socket_send(void *opaque) } else if (size == 0) { /* end of connection */ eoc: - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); if (s->listen_fd != -1) { qemu_set_fd_handler(s->listen_fd, net_socket_accept, NULL, s); } @@ -152,7 +195,8 @@ static void net_socket_send_dgram(void *opaque) return; if (size == 0) { /* end of connection */ - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); return; } qemu_send_packet(&s->nc, s->buf, size); @@ -243,7 +287,8 @@ static void net_socket_cleanup(NetClientState *nc) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); if (s->fd != -1) { - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); + net_socket_read_poll(s, false); + net_socket_write_poll(s, false); close(s->fd); s->fd = -1; } @@ -314,8 +359,8 @@ static NetSocketState *net_socket_fd_init_dgram(NetClientState *peer, s->fd = fd; s->listen_fd = -1; - - qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); + s->send_fn = net_socket_send_dgram; + net_socket_read_poll(s, true); /* mcast: save bound address as dst */ if (is_connected) { @@ -332,7 +377,8 @@ err: static void net_socket_connect(void *opaque) { NetSocketState *s = opaque; - qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); + s->send_fn = net_socket_send; + net_socket_read_poll(s, true); } static NetClientInfo net_socket_info = { -- cgit v1.2.3 From 213fd5087e2e4e2da10ad266df0ba950cf7618bf Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:28:53 +0100 Subject: net: EAGAIN handling for net/socket.c UDP Implement asynchronous send for UDP (or other SOCK_DGRAM) sockets. If send fails with EAGAIN we wait for the socket to become writable again. Signed-off-by: Stefan Hajnoczi --- net/socket.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 7bff5367ac..aabf0a48c5 100644 --- a/net/socket.c +++ b/net/socket.c @@ -102,9 +102,19 @@ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); + ssize_t ret; - return sendto(s->fd, (const void *)buf, size, 0, - (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); + do { + ret = sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); + } while (ret == -1 && errno == EINTR); + + if (ret == -1 && errno == EAGAIN) { + net_socket_write_poll(s, true); + return 0; + } + return ret; } static void net_socket_send(void *opaque) -- cgit v1.2.3 From 45a7f54a8bb3928ffa58d522e0d61acaee8277bb Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 20 Aug 2012 10:14:35 +0100 Subject: net: EAGAIN handling for net/socket.c TCP Replace spinning send_all() with a proper non-blocking send. When the socket write buffer limit is reached, we should stop trying to send and wait for the socket to become writable again. Non-blocking TCP sockets can return in two different ways when the write buffer limit is reached: 1. ret = -1 and errno = EAGAIN/EWOULDBLOCK. No data has been written. 2. ret < total_size. Short write, only part of the message was transmitted. Handle both cases and keep track of how many bytes have been written in s->send_index. (This includes the 'length' header before the actual payload buffer.) Signed-off-by: Stefan Hajnoczi --- net/socket.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index aabf0a48c5..5e0c92e062 100644 --- a/net/socket.c +++ b/net/socket.c @@ -32,6 +32,7 @@ #include "qemu-error.h" #include "qemu-option.h" #include "qemu_socket.h" +#include "iov.h" typedef struct NetSocketState { NetClientState nc; @@ -40,6 +41,7 @@ typedef struct NetSocketState { int state; /* 0 = getting length, 1 = getting data */ unsigned int index; unsigned int packet_len; + unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */ uint8_t buf[4096]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ @@ -88,15 +90,39 @@ static void net_socket_writable(void *opaque) qemu_flush_queued_packets(&s->nc); } -/* XXX: we consider we can send the whole packet without blocking */ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size) { NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc); - uint32_t len; - len = htonl(size); + uint32_t len = htonl(size); + struct iovec iov[] = { + { + .iov_base = &len, + .iov_len = sizeof(len), + }, { + .iov_base = (void *)buf, + .iov_len = size, + }, + }; + size_t remaining; + ssize_t ret; + + remaining = iov_size(iov, 2) - s->send_index; + ret = iov_send(s->fd, iov, 2, s->send_index, remaining); - send_all(s->fd, (const uint8_t *)&len, sizeof(len)); - return send_all(s->fd, buf, size); + if (ret == -1 && errno == EAGAIN) { + ret = 0; /* handled further down */ + } + if (ret == -1) { + s->send_index = 0; + return -errno; + } + if (ret < (ssize_t)remaining) { + s->send_index += ret; + net_socket_write_poll(s, true); + return 0; + } + s->send_index = 0; + return size; } static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size) -- cgit v1.2.3 From 73062dfe6be0050dbd43ce3516e935ebb2545add Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Sat, 22 Sep 2012 21:13:28 +0200 Subject: net/socket: Fix compiler warning (regression for MinGW) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 213fd5087e2e4e2da10ad266df0ba950cf7618bf removed a type cast which is needed for MinGW: net/socket.c:136: warning: pointer targets in passing argument 2 of ‘sendto’ differ in signedness /usr/lib/gcc/amd64-mingw32msvc/4.4.4/../../../../amd64-mingw32msvc/include/winsock2.h:1313: note: expected ‘const char *’ but argument is of type ‘const uint8_t *’ Add a 'qemu_sendto' macro which provides that type cast where needed and use the new macro instead of 'sendto'. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 5e0c92e062..f3d7878264 100644 --- a/net/socket.c +++ b/net/socket.c @@ -131,9 +131,9 @@ static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, ssize_t ret; do { - ret = sendto(s->fd, buf, size, 0, - (struct sockaddr *)&s->dgram_dst, - sizeof(s->dgram_dst)); + ret = qemu_sendto(s->fd, buf, size, 0, + (struct sockaddr *)&s->dgram_dst, + sizeof(s->dgram_dst)); } while (ret == -1 && errno == EINTR); if (ret == -1 && errno == EAGAIN) { -- cgit v1.2.3 From a245fc18352fe286ba45ae0661a73b3841514889 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Sep 2012 18:43:51 +0200 Subject: net: consolidate NetClientState header files into one This patch doesn't seem much useful alone, I must admit. However, it makes sense as part of the upcoming directory reorganization, where I want to have include/net/tap.h as the net<->hw interface for tap. Then having both net/tap.h and include/net/tap.h does not work. "Fixed" by moving all the init functions to a single header file net/clients.h. The patch also adopts a uniform style for including net/*.h files from net/*.c, without the net/ path. Signed-off-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- net/clients.h | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/dump.c | 2 +- net/dump.h | 33 --------------------------------- net/hub.c | 1 + net/hub.h | 2 -- net/slirp.c | 3 ++- net/slirp.h | 3 --- net/socket.c | 3 +-- net/socket.h | 33 --------------------------------- net/tap-win32.c | 2 +- net/tap.c | 3 ++- net/tap.h | 6 ------ net/vde.c | 3 +-- net/vde.h | 37 ------------------------------------- 14 files changed, 64 insertions(+), 122 deletions(-) create mode 100644 net/clients.h delete mode 100644 net/dump.h delete mode 100644 net/socket.h delete mode 100644 net/vde.h (limited to 'net') diff --git a/net/clients.h b/net/clients.h new file mode 100644 index 0000000000..c58cc6087c --- /dev/null +++ b/net/clients.h @@ -0,0 +1,55 @@ +/* + * 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. + */ +#ifndef QEMU_NET_CLIENTS_H +#define QEMU_NET_CLIENTS_H + +#include "net.h" +#include "qapi-types.h" + +int net_init_dump(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +#ifdef CONFIG_SLIRP +int net_init_slirp(const NetClientOptions *opts, const char *name, + NetClientState *peer); +#endif + +int net_init_hubport(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +int net_init_socket(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +int net_init_tap(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +int net_init_bridge(const NetClientOptions *opts, const char *name, + NetClientState *peer); + +#ifdef CONFIG_VDE +int net_init_vde(const NetClientOptions *opts, const char *name, + NetClientState *peer); +#endif + +#endif /* QEMU_NET_CLIENTS_H */ diff --git a/net/dump.c b/net/dump.c index 004231d481..e0a5d74644 100644 --- a/net/dump.c +++ b/net/dump.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "dump.h" +#include "clients.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-log.h" diff --git a/net/dump.h b/net/dump.h deleted file mode 100644 index 33f152b460..0000000000 --- a/net/dump.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ -#ifndef QEMU_NET_DUMP_H -#define QEMU_NET_DUMP_H - -#include "net.h" -#include "qapi-types.h" - -int net_init_dump(const NetClientOptions *opts, const char *name, - NetClientState *peer); - -#endif /* QEMU_NET_DUMP_H */ diff --git a/net/hub.c b/net/hub.c index 650a8b4a40..be413012bb 100644 --- a/net/hub.c +++ b/net/hub.c @@ -14,6 +14,7 @@ #include "monitor.h" #include "net.h" +#include "clients.h" #include "hub.h" #include "iov.h" diff --git a/net/hub.h b/net/hub.h index 26a1ade1f9..4cbfdb128b 100644 --- a/net/hub.h +++ b/net/hub.h @@ -17,8 +17,6 @@ #include "qemu-common.h" -int net_init_hubport(const NetClientOptions *opts, const char *name, - NetClientState *peer); NetClientState *net_hub_add_port(int hub_id, const char *name); NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); diff --git a/net/slirp.c b/net/slirp.c index 8db66ea539..bf86a446c3 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -30,7 +30,8 @@ #include #endif #include "net.h" -#include "net/hub.h" +#include "clients.h" +#include "hub.h" #include "monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" diff --git a/net/slirp.h b/net/slirp.h index 5f685c4fb1..2ca09b65b7 100644 --- a/net/slirp.h +++ b/net/slirp.h @@ -31,9 +31,6 @@ #ifdef CONFIG_SLIRP -int net_init_slirp(const NetClientOptions *opts, const char *name, - NetClientState *peer); - void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); diff --git a/net/socket.c b/net/socket.c index f3d7878264..b75d567695 100644 --- a/net/socket.c +++ b/net/socket.c @@ -21,11 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "net/socket.h" - #include "config-host.h" #include "net.h" +#include "clients.h" #include "monitor.h" #include "qemu-char.h" #include "qemu-common.h" diff --git a/net/socket.h b/net/socket.h deleted file mode 100644 index 3f8a092459..0000000000 --- a/net/socket.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ -#ifndef QEMU_NET_SOCKET_H -#define QEMU_NET_SOCKET_H - -#include "net.h" -#include "qapi-types.h" - -int net_init_socket(const NetClientOptions *opts, const char *name, - NetClientState *peer); - -#endif /* QEMU_NET_SOCKET_H */ diff --git a/net/tap-win32.c b/net/tap-win32.c index c0ea954ca1..f1801e22d2 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -26,7 +26,7 @@ * distribution); if not, see . */ -#include "net/tap.h" +#include "tap.h" #include "qemu-common.h" #include "net.h" diff --git a/net/tap.c b/net/tap.c index a88ae8f61a..df89caaac6 100644 --- a/net/tap.c +++ b/net/tap.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap.h" #include "config-host.h" @@ -34,6 +34,7 @@ #include #include "net.h" +#include "clients.h" #include "monitor.h" #include "sysemu.h" #include "qemu-char.h" diff --git a/net/tap.h b/net/tap.h index 0fb018c4b7..d44d83ae73 100644 --- a/net/tap.h +++ b/net/tap.h @@ -32,9 +32,6 @@ #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -int net_init_tap(const NetClientOptions *opts, const char *name, - NetClientState *peer); - int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); @@ -58,7 +55,4 @@ int tap_get_fd(NetClientState *nc); struct vhost_net; struct vhost_net *tap_get_vhost_net(NetClientState *nc); -int net_init_bridge(const NetClientOptions *opts, const char *name, - NetClientState *peer); - #endif /* QEMU_NET_TAP_H */ diff --git a/net/vde.c b/net/vde.c index b91a6c799b..275bda92c3 100644 --- a/net/vde.c +++ b/net/vde.c @@ -21,13 +21,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "net/vde.h" - #include "config-host.h" #include #include "net.h" +#include "clients.h" #include "qemu-char.h" #include "qemu-common.h" #include "qemu-option.h" diff --git a/net/vde.h b/net/vde.h deleted file mode 100644 index 6ce6698937..0000000000 --- a/net/vde.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ -#ifndef QEMU_NET_VDE_H -#define QEMU_NET_VDE_H - -#include "qemu-common.h" -#include "qapi-types.h" - -#ifdef CONFIG_VDE - -int net_init_vde(const NetClientOptions *opts, const char *name, - NetClientState *peer); - -#endif /* CONFIG_VDE */ - -#endif /* QEMU_NET_VDE_H */ -- cgit v1.2.3 From 08778b398328c4978e6e6bed023e37a3141dba84 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Wed, 17 Oct 2012 19:53:50 +0200 Subject: net/tap-win32: Fix compiler warning caused by missing include statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The include file for net_init_tap was missing: net/tap-win32.c:703: warning: no previous prototype for ‘net_init_tap’ Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/tap-win32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index f1801e22d2..22dad3f8fb 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -29,6 +29,7 @@ #include "tap.h" #include "qemu-common.h" +#include "clients.h" /* net_init_tap */ #include "net.h" #include "sysemu.h" #include "qemu-error.h" -- cgit v1.2.3 From aee0bf7d8d7564f8f2c40e4501695c492b7dd8d1 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 30 Oct 2012 16:04:50 +0200 Subject: tap-win32: stubs to fix win32 build Add missing stubs to win32 to fix link failure. Signed-off-by: Michael S. Tsirkin Reported-by: Paolo Bonzini Signed-off-by: Blue Swirl --- net/tap-win32.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index 22dad3f8fb..8d2d32b1c3 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -752,3 +752,13 @@ struct vhost_net *tap_get_vhost_net(NetClientState *nc) { return NULL; } + +int tap_has_vnet_hdr_len(NetClientState *nc, int len) +{ + return 0; +} + +void tap_set_vnet_hdr_len(NetClientState *nc, int len) +{ + assert(0); +} -- cgit v1.2.3 From f0e3ac70341febed02591b61b579723279783053 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Thu, 1 Nov 2012 17:39:55 +0800 Subject: net: use "socket" model name for UDP sockets Fix the problem that can not delete the udp socket. It's caused by passing "udp" model to net_socket_udp_init, but we do not have "udp" model in our model list. Pass the right model "socket" to init function. https://bugs.launchpad.net/qemu/+bug/1073585?comments=all Signed-off-by: Lei Li Signed-off-by: Stefan Hajnoczi --- net/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index b75d567695..c01323d4b0 100644 --- a/net/socket.c +++ b/net/socket.c @@ -747,7 +747,7 @@ int net_init_socket(const NetClientOptions *opts, const char *name, error_report("localaddr= is mandatory with udp="); return -1; } - if (net_socket_udp_init(peer, "udp", name, sock->udp, sock->localaddr) == + if (net_socket_udp_init(peer, "socket", name, sock->udp, sock->localaddr) == -1) { return -1; } -- cgit v1.2.3 From 63d2960bc46f63137d7fbd5ff56b81e54710d195 Mon Sep 17 00:00:00 2001 From: Klaus Stengel Date: Sat, 27 Oct 2012 19:53:39 +0200 Subject: slirp: Add domain-search option to slirp's DHCP server This patch will allow the user to include the domain-search option in replies from the built-in DHCP server. The domain suffixes can be specified by adding dnssearch= entries to the "-net user" parameter. [Jan: tiny style adjustments] Signed-off-by: Klaus Stengel Signed-off-by: Jan Kiszka --- net/slirp.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/slirp.c b/net/slirp.c index bf86a446c3..afb52c3af1 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -136,7 +136,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, const char *vhostname, const char *tftp_export, const char *bootfile, const char *vdhcp_start, const char *vnameserver, const char *smb_export, - const char *vsmbserver) + const char *vsmbserver, const char **dnssearch) { /* default settings according to historic slirp */ struct in_addr net = { .s_addr = htonl(0x0a000200) }; /* 10.0.2.0 */ @@ -242,7 +242,7 @@ static int net_slirp_init(NetClientState *peer, const char *model, s = DO_UPCAST(SlirpState, nc, nc); s->slirp = slirp_init(restricted, net, mask, host, vhostname, - tftp_export, bootfile, dhcp, dns, s); + tftp_export, bootfile, dhcp, dns, dnssearch, s); QTAILQ_INSERT_TAIL(&slirp_stacks, s, entry); for (config = slirp_configs; config; config = config->next) { @@ -699,6 +699,31 @@ net_init_slirp_configs(const StringList *fwd, int flags) } } +static const char **slirp_dnssearch(const StringList *dnsname) +{ + const StringList *c = dnsname; + size_t i = 0, num_opts = 0; + const char **ret; + + while (c) { + num_opts++; + c = c->next; + } + + if (num_opts == 0) { + return NULL; + } + + ret = g_malloc((num_opts + 1) * sizeof(*ret)); + c = dnsname; + while (c) { + ret[i++] = c->value->str; + c = c->next; + } + ret[i] = NULL; + return ret; +} + int net_init_slirp(const NetClientOptions *opts, const char *name, NetClientState *peer) { @@ -706,6 +731,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, char *vnet; int ret; const NetdevUserOptions *user; + const char **dnssearch; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_USER); user = opts->user; @@ -714,6 +740,8 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, user->has_ip ? g_strdup_printf("%s/24", user->ip) : NULL; + dnssearch = slirp_dnssearch(user->dnssearch); + /* all optional fields are initialized to "all bits zero" */ net_init_slirp_configs(user->hostfwd, SLIRP_CFG_HOSTFWD); @@ -722,7 +750,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, ret = net_slirp_init(peer, "user", name, user->q_restrict, vnet, user->host, user->hostname, user->tftp, user->bootfile, user->dhcpstart, user->dns, user->smb, - user->smbserver); + user->smbserver, dnssearch); while (slirp_configs) { config = slirp_configs; @@ -731,6 +759,7 @@ int net_init_slirp(const NetClientOptions *opts, const char *name, } g_free(vnet); + g_free(dnssearch); return ret; } -- cgit v1.2.3 From 58ddcd50f30cb5c020bd4f9f36b01ee160a27cac Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 13 Nov 2012 12:23:23 +0200 Subject: tap: reset vnet header size on open For tap, we currently assume the vnet header size is 10 (the default value) but that might not be the case if tap is persistent and has been used by qemu previously. To fix, set host header size in tap device on open. Signed-off-by: Michael S. Tsirkin Tested-by: Alexander Graf Signed-off-by: Stefan Hajnoczi --- net/tap.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index df89caaac6..1abfd44bd9 100644 --- a/net/tap.c +++ b/net/tap.c @@ -341,6 +341,13 @@ static TAPState *net_tap_fd_init(NetClientState *peer, s->using_vnet_hdr = 0; s->has_ufo = tap_probe_has_ufo(s->fd); tap_set_offload(&s->nc, 0, 0, 0, 0, 0); + /* + * Make sure host header length is set correctly in tap: + * it might have been modified by another instance of qemu. + */ + if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) { + tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len); + } tap_read_poll(s, 1); s->vhost_net = NULL; return s; -- cgit v1.2.3 From eac29d87c883fcbb54913ae20ed2bdccb4bcf7a3 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 2 Nov 2012 08:14:12 +0100 Subject: Fix spelling (prefered -> preferred) Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/tap-win32.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index 8d2d32b1c3..f9bd74109c 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -565,7 +565,7 @@ static void tap_win32_free_buffer(tap_win32_overlapped_t *overlapped, } static int tap_win32_open(tap_win32_overlapped_t **phandle, - const char *prefered_name) + const char *preferred_name) { char device_path[256]; char device_guid[0x100]; @@ -581,8 +581,9 @@ static int tap_win32_open(tap_win32_overlapped_t **phandle, DWORD version_len; DWORD idThread; - if (prefered_name != NULL) - snprintf(name_buffer, sizeof(name_buffer), "%s", prefered_name); + if (preferred_name != NULL) { + snprintf(name_buffer, sizeof(name_buffer), "%s", preferred_name); + } rc = get_device_guid(device_guid, sizeof(device_guid), name_buffer, sizeof(name_buffer)); if (rc) -- cgit v1.2.3 From 89e6d68ef3c45b2c4e3199c3397b5525b752698d Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 12 Nov 2012 09:13:04 +0200 Subject: tap: reset vnet header size on open For tap, we currently assume the vnet header size is 10 (the default value) but that might not be the case if tap is persistent and has been used by qemu previously. To fix, set vnet header size correctly on open. Signed-off-by: Michael S. Tsirkin --- net/tap-linux.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net') diff --git a/net/tap-linux.c b/net/tap-linux.c index c6521bec34..3eaedc40ad 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -39,6 +39,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required { struct ifreq ifr; int fd, ret; + int len = sizeof(struct virtio_net_hdr); TFR(fd = open(PATH_NET_TUN, O_RDWR)); if (fd < 0) { @@ -65,6 +66,13 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required close(fd); return -1; } + /* + * Make sure vnet header size has the default value: for a persistent + * tap it might have been modified e.g. by another instance of qemu. + * Ignore errors since old kernels do not support this ioctl: in this + * case the header size implicitly has the correct value. + */ + ioctl(fd, TUNSETVNETHDRSZ, &len); } if (ifname[0] != '\0') -- cgit v1.2.3 From e103129b1b5746f8388b37d18317e61d6b139b69 Mon Sep 17 00:00:00 2001 From: Zhi Yong Wu Date: Fri, 7 Dec 2012 09:43:18 +0800 Subject: net, hub: fix the indent in the comments Remove some redundant blanks in the comments of net_hub_id_for_client(). Signed-off-by: Zhi Yong Wu Signed-off-by: Stefan Hajnoczi --- net/hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/hub.c b/net/hub.c index be413012bb..3b2d1ffcd2 100644 --- a/net/hub.c +++ b/net/hub.c @@ -256,7 +256,7 @@ void net_hub_info(Monitor *mon) /** * Get the hub id that a client is connected to * - * @id Pointer for hub id output, may be NULL + * @id: Pointer for hub id output, may be NULL */ int net_hub_id_for_client(NetClientState *nc, int *id) { -- cgit v1.2.3 From f8fe796407d8b340def61a6b57991e47aee3cfc4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 08:49:51 +0200 Subject: janitor: do not include qemu-char everywhere Touching char/char.h basically causes the whole of QEMU to be rebuilt. Avoid this, it is usually unnecessary. Signed-off-by: Paolo Bonzini --- net/slirp.c | 1 + net/socket.c | 1 - net/tap.c | 1 - net/vde.c | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/slirp.c b/net/slirp.c index afb52c3af1..f117412bad 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -35,6 +35,7 @@ #include "monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" +#include "qemu-char.h" static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { diff --git a/net/socket.c b/net/socket.c index c01323d4b0..cf309cd5b9 100644 --- a/net/socket.c +++ b/net/socket.c @@ -26,7 +26,6 @@ #include "net.h" #include "clients.h" #include "monitor.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-option.h" diff --git a/net/tap.c b/net/tap.c index 1abfd44bd9..5ff78934dc 100644 --- a/net/tap.c +++ b/net/tap.c @@ -37,7 +37,6 @@ #include "clients.h" #include "monitor.h" #include "sysemu.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-error.h" diff --git a/net/vde.c b/net/vde.c index 275bda92c3..cc5a07d65e 100644 --- a/net/vde.c +++ b/net/vde.c @@ -27,7 +27,6 @@ #include "net.h" #include "clients.h" -#include "qemu-char.h" #include "qemu-common.h" #include "qemu-option.h" -- cgit v1.2.3 From fd9400b302ef582c3ae8a8d5288338ea5f0f4c9a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 11:27:28 +0200 Subject: net: move net.c to net/ Signed-off-by: Paolo Bonzini --- net/Makefile.objs | 2 +- net/net.c | 1056 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1057 insertions(+), 1 deletion(-) create mode 100644 net/net.c (limited to 'net') diff --git a/net/Makefile.objs b/net/Makefile.objs index cf04187717..a08cd14e2e 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = queue.o checksum.o util.o hub.o +common-obj-y = net.o queue.o checksum.o util.o hub.o common-obj-y += socket.o common-obj-y += dump.o common-obj-$(CONFIG_POSIX) += tap.o diff --git a/net/net.c b/net/net.c new file mode 100644 index 0000000000..7b1600f17c --- /dev/null +++ b/net/net.c @@ -0,0 +1,1056 @@ +/* + * 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 "config-host.h" + +#include "net.h" +#include "clients.h" +#include "hub.h" +#include "slirp.h" +#include "util.h" + +#include "monitor.h" +#include "qemu-common.h" +#include "qemu_socket.h" +#include "qemu-config.h" +#include "qmp-commands.h" +#include "hw/qdev.h" +#include "iov.h" +#include "qapi-visit.h" +#include "qapi/opts-visitor.h" +#include "qapi/qapi-dealloc-visitor.h" + +/* Net bridge is currently not supported for W32. */ +#if !defined(_WIN32) +# define CONFIG_NET_BRIDGE +#endif + +static QTAILQ_HEAD(, NetClientState) net_clients; + +int default_net = 1; + +/***********************************************************/ +/* network device redirectors */ + +#if defined(DEBUG_NET) +static void hex_dump(FILE *f, const uint8_t *buf, int size) +{ + int len, i, j, c; + + for(i=0;i 16) + len = 16; + fprintf(f, "%08x ", i); + for(j=0;j<16;j++) { + if (j < len) + fprintf(f, " %02x", buf[i+j]); + else + fprintf(f, " "); + } + fprintf(f, " "); + for(j=0;j '~') + c = '.'; + fprintf(f, "%c", c); + } + fprintf(f, "\n"); + } +} +#endif + +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) +{ + const char *p, *p1; + int len; + p = *pp; + p1 = strchr(p, sep); + if (!p1) + return -1; + len = p1 - p; + p1++; + if (buf_size > 0) { + if (len > buf_size - 1) + len = buf_size - 1; + memcpy(buf, p, len); + buf[len] = '\0'; + } + *pp = p1; + return 0; +} + +int parse_host_port(struct sockaddr_in *saddr, const char *str) +{ + char buf[512]; + struct hostent *he; + const char *p, *r; + int port; + + p = str; + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + return -1; + saddr->sin_family = AF_INET; + if (buf[0] == '\0') { + saddr->sin_addr.s_addr = 0; + } else { + if (qemu_isdigit(buf[0])) { + if (!inet_aton(buf, &saddr->sin_addr)) + return -1; + } else { + if ((he = gethostbyname(buf)) == NULL) + return - 1; + saddr->sin_addr = *(struct in_addr *)he->h_addr; + } + } + port = strtol(p, (char **)&r, 0); + if (r == p) + return -1; + saddr->sin_port = htons(port); + return 0; +} + +void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]) +{ + snprintf(nc->info_str, sizeof(nc->info_str), + "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x", + nc->model, + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); +} + +void qemu_macaddr_default_if_unset(MACAddr *macaddr) +{ + static int index = 0; + static const MACAddr zero = { .a = { 0,0,0,0,0,0 } }; + + if (memcmp(macaddr, &zero, sizeof(zero)) != 0) + return; + macaddr->a[0] = 0x52; + macaddr->a[1] = 0x54; + macaddr->a[2] = 0x00; + macaddr->a[3] = 0x12; + macaddr->a[4] = 0x34; + macaddr->a[5] = 0x56 + index++; +} + +/** + * Generate a name for net client + * + * Only net clients created with the legacy -net option need this. Naming is + * mandatory for net clients created with -netdev. + */ +static char *assign_name(NetClientState *nc1, const char *model) +{ + NetClientState *nc; + char buf[256]; + int id = 0; + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc == nc1) { + continue; + } + /* For compatibility only bump id for net clients on a vlan */ + if (strcmp(nc->model, model) == 0 && + net_hub_id_for_client(nc, NULL) == 0) { + id++; + } + } + + snprintf(buf, sizeof(buf), "%s.%d", model, id); + + return g_strdup(buf); +} + +NetClientState *qemu_new_net_client(NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name) +{ + NetClientState *nc; + + assert(info->size >= sizeof(NetClientState)); + + nc = g_malloc0(info->size); + + nc->info = info; + nc->model = g_strdup(model); + if (name) { + nc->name = g_strdup(name); + } else { + nc->name = assign_name(nc, model); + } + + if (peer) { + assert(!peer->peer); + nc->peer = peer; + peer->peer = nc; + } + QTAILQ_INSERT_TAIL(&net_clients, nc, next); + + nc->send_queue = qemu_new_net_queue(nc); + + return nc; +} + +NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, + void *opaque) +{ + NetClientState *nc; + NICState *nic; + + assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); + assert(info->size >= sizeof(NICState)); + + nc = qemu_new_net_client(info, conf->peer, model, name); + + nic = DO_UPCAST(NICState, nc, nc); + nic->conf = conf; + nic->opaque = opaque; + + return nic; +} + +static void qemu_cleanup_net_client(NetClientState *nc) +{ + QTAILQ_REMOVE(&net_clients, nc, next); + + if (nc->info->cleanup) { + nc->info->cleanup(nc); + } +} + +static void qemu_free_net_client(NetClientState *nc) +{ + if (nc->send_queue) { + qemu_del_net_queue(nc->send_queue); + } + if (nc->peer) { + nc->peer->peer = NULL; + } + g_free(nc->name); + g_free(nc->model); + g_free(nc); +} + +void qemu_del_net_client(NetClientState *nc) +{ + /* If there is a peer NIC, delete and cleanup client, but do not free. */ + if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, nc->peer); + if (nic->peer_deleted) { + return; + } + nic->peer_deleted = true; + /* Let NIC know peer is gone. */ + nc->peer->link_down = true; + if (nc->peer->info->link_status_changed) { + nc->peer->info->link_status_changed(nc->peer); + } + qemu_cleanup_net_client(nc); + return; + } + + /* If this is a peer NIC and peer has already been deleted, free it now. */ + if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + NICState *nic = DO_UPCAST(NICState, nc, nc); + if (nic->peer_deleted) { + qemu_free_net_client(nc->peer); + } + } + + qemu_cleanup_net_client(nc); + qemu_free_net_client(nc); +} + +void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) +{ + NetClientState *nc; + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + func(DO_UPCAST(NICState, nc, nc), opaque); + } + } +} + +int qemu_can_send_packet(NetClientState *sender) +{ + if (!sender->peer) { + return 1; + } + + if (sender->peer->receive_disabled) { + return 0; + } else if (sender->peer->info->can_receive && + !sender->peer->info->can_receive(sender->peer)) { + return 0; + } + return 1; +} + +ssize_t qemu_deliver_packet(NetClientState *sender, + unsigned flags, + const uint8_t *data, + size_t size, + void *opaque) +{ + NetClientState *nc = opaque; + ssize_t ret; + + if (nc->link_down) { + return size; + } + + if (nc->receive_disabled) { + return 0; + } + + if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) { + ret = nc->info->receive_raw(nc, data, size); + } else { + ret = nc->info->receive(nc, data, size); + } + + if (ret == 0) { + nc->receive_disabled = 1; + }; + + return ret; +} + +void qemu_purge_queued_packets(NetClientState *nc) +{ + if (!nc->peer) { + return; + } + + qemu_net_queue_purge(nc->peer->send_queue, nc); +} + +void qemu_flush_queued_packets(NetClientState *nc) +{ + nc->receive_disabled = 0; + + if (qemu_net_queue_flush(nc->send_queue)) { + /* We emptied the queue successfully, signal to the IO thread to repoll + * the file descriptor (for tap, for example). + */ + qemu_notify_event(); + } +} + +static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender, + unsigned flags, + const uint8_t *buf, int size, + NetPacketSent *sent_cb) +{ + NetQueue *queue; + +#ifdef DEBUG_NET + printf("qemu_send_packet_async:\n"); + hex_dump(stdout, buf, size); +#endif + + if (sender->link_down || !sender->peer) { + return size; + } + + queue = sender->peer->send_queue; + + return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); +} + +ssize_t qemu_send_packet_async(NetClientState *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(NetClientState *nc, const uint8_t *buf, int size) +{ + qemu_send_packet_async(nc, buf, size, NULL); +} + +ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) +{ + return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW, + buf, size, NULL); +} + +static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov, + int iovcnt) +{ + uint8_t buffer[4096]; + size_t offset; + + offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer)); + + return nc->info->receive(nc, buffer, offset); +} + +ssize_t qemu_deliver_packet_iov(NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt, + void *opaque) +{ + NetClientState *nc = opaque; + int ret; + + if (nc->link_down) { + return iov_size(iov, iovcnt); + } + + if (nc->receive_disabled) { + return 0; + } + + if (nc->info->receive_iov) { + ret = nc->info->receive_iov(nc, iov, iovcnt); + } else { + ret = nc_sendv_compat(nc, iov, iovcnt); + } + + if (ret == 0) { + nc->receive_disabled = 1; + } + + return ret; +} + +ssize_t qemu_sendv_packet_async(NetClientState *sender, + const struct iovec *iov, int iovcnt, + NetPacketSent *sent_cb) +{ + NetQueue *queue; + + if (sender->link_down || !sender->peer) { + return iov_size(iov, iovcnt); + } + + queue = sender->peer->send_queue; + + return qemu_net_queue_send_iov(queue, sender, + QEMU_NET_PACKET_FLAG_NONE, + iov, iovcnt, sent_cb); +} + +ssize_t +qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt) +{ + return qemu_sendv_packet_async(nc, iov, iovcnt, NULL); +} + +NetClientState *qemu_find_netdev(const char *id) +{ + NetClientState *nc; + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) + continue; + if (!strcmp(nc->name, id)) { + return nc; + } + } + + return NULL; +} + +static int nic_get_free_idx(void) +{ + int index; + + for (index = 0; index < MAX_NICS; index++) + if (!nd_table[index].used) + return index; + return -1; +} + +int qemu_show_nic_models(const char *arg, const char *const *models) +{ + int i; + + if (!arg || !is_help_option(arg)) { + return 0; + } + + fprintf(stderr, "qemu: Supported NIC models: "); + for (i = 0 ; models[i]; i++) + fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n'); + return 1; +} + +void qemu_check_nic_model(NICInfo *nd, const char *model) +{ + const char *models[2]; + + models[0] = model; + models[1] = NULL; + + if (qemu_show_nic_models(nd->model, models)) + exit(0); + if (qemu_find_nic_model(nd, models, model) < 0) + exit(1); +} + +int qemu_find_nic_model(NICInfo *nd, const char * const *models, + const char *default_model) +{ + int i; + + if (!nd->model) + nd->model = g_strdup(default_model); + + for (i = 0 ; models[i]; i++) { + if (strcmp(nd->model, models[i]) == 0) + return i; + } + + error_report("Unsupported NIC model: %s", nd->model); + return -1; +} + +static int net_init_nic(const NetClientOptions *opts, const char *name, + NetClientState *peer) +{ + int idx; + NICInfo *nd; + const NetLegacyNicOptions *nic; + + assert(opts->kind == NET_CLIENT_OPTIONS_KIND_NIC); + nic = opts->nic; + + idx = nic_get_free_idx(); + if (idx == -1 || nb_nics >= MAX_NICS) { + error_report("Too Many NICs"); + return -1; + } + + nd = &nd_table[idx]; + + memset(nd, 0, sizeof(*nd)); + + if (nic->has_netdev) { + nd->netdev = qemu_find_netdev(nic->netdev); + if (!nd->netdev) { + error_report("netdev '%s' not found", nic->netdev); + return -1; + } + } else { + assert(peer); + nd->netdev = peer; + } + if (name) { + nd->name = g_strdup(name); + } + if (nic->has_model) { + nd->model = g_strdup(nic->model); + } + if (nic->has_addr) { + nd->devaddr = g_strdup(nic->addr); + } + + if (nic->has_macaddr && + net_parse_macaddr(nd->macaddr.a, nic->macaddr) < 0) { + error_report("invalid syntax for ethernet address"); + return -1; + } + qemu_macaddr_default_if_unset(&nd->macaddr); + + if (nic->has_vectors) { + if (nic->vectors > 0x7ffffff) { + error_report("invalid # of vectors: %"PRIu32, nic->vectors); + return -1; + } + nd->nvectors = nic->vectors; + } else { + nd->nvectors = DEV_NVECTORS_UNSPECIFIED; + } + + nd->used = 1; + nb_nics++; + + return idx; +} + + +static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])( + const NetClientOptions *opts, + const char *name, + NetClientState *peer) = { + [NET_CLIENT_OPTIONS_KIND_NIC] = net_init_nic, +#ifdef CONFIG_SLIRP + [NET_CLIENT_OPTIONS_KIND_USER] = net_init_slirp, +#endif + [NET_CLIENT_OPTIONS_KIND_TAP] = net_init_tap, + [NET_CLIENT_OPTIONS_KIND_SOCKET] = net_init_socket, +#ifdef CONFIG_VDE + [NET_CLIENT_OPTIONS_KIND_VDE] = net_init_vde, +#endif + [NET_CLIENT_OPTIONS_KIND_DUMP] = net_init_dump, +#ifdef CONFIG_NET_BRIDGE + [NET_CLIENT_OPTIONS_KIND_BRIDGE] = net_init_bridge, +#endif + [NET_CLIENT_OPTIONS_KIND_HUBPORT] = net_init_hubport, +}; + + +static int net_client_init1(const void *object, int is_netdev, Error **errp) +{ + union { + const Netdev *netdev; + const NetLegacy *net; + } u; + const NetClientOptions *opts; + const char *name; + + if (is_netdev) { + u.netdev = object; + opts = u.netdev->opts; + name = u.netdev->id; + + switch (opts->kind) { +#ifdef CONFIG_SLIRP + case NET_CLIENT_OPTIONS_KIND_USER: +#endif + case NET_CLIENT_OPTIONS_KIND_TAP: + case NET_CLIENT_OPTIONS_KIND_SOCKET: +#ifdef CONFIG_VDE + case NET_CLIENT_OPTIONS_KIND_VDE: +#endif +#ifdef CONFIG_NET_BRIDGE + case NET_CLIENT_OPTIONS_KIND_BRIDGE: +#endif + case NET_CLIENT_OPTIONS_KIND_HUBPORT: + break; + + default: + error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type", + "a netdev backend type"); + return -1; + } + } else { + u.net = object; + opts = u.net->opts; + /* missing optional values have been initialized to "all bits zero" */ + name = u.net->has_id ? u.net->id : u.net->name; + } + + if (net_client_init_fun[opts->kind]) { + NetClientState *peer = NULL; + + /* Do not add to a vlan if it's a -netdev or a nic with a netdev= + * parameter. */ + if (!is_netdev && + (opts->kind != NET_CLIENT_OPTIONS_KIND_NIC || + !opts->nic->has_netdev)) { + peer = net_hub_add_port(u.net->has_vlan ? u.net->vlan : 0, NULL); + } + + if (net_client_init_fun[opts->kind](opts, name, peer) < 0) { + /* TODO push error reporting into init() methods */ + error_set(errp, QERR_DEVICE_INIT_FAILED, + NetClientOptionsKind_lookup[opts->kind]); + return -1; + } + } + return 0; +} + + +static void net_visit(Visitor *v, int is_netdev, void **object, Error **errp) +{ + if (is_netdev) { + visit_type_Netdev(v, (Netdev **)object, NULL, errp); + } else { + visit_type_NetLegacy(v, (NetLegacy **)object, NULL, errp); + } +} + + +int net_client_init(QemuOpts *opts, int is_netdev, Error **errp) +{ + void *object = NULL; + Error *err = NULL; + int ret = -1; + + { + OptsVisitor *ov = opts_visitor_new(opts); + + net_visit(opts_get_visitor(ov), is_netdev, &object, &err); + opts_visitor_cleanup(ov); + } + + if (!err) { + ret = net_client_init1(object, is_netdev, &err); + } + + if (object) { + QapiDeallocVisitor *dv = qapi_dealloc_visitor_new(); + + net_visit(qapi_dealloc_get_visitor(dv), is_netdev, &object, NULL); + qapi_dealloc_visitor_cleanup(dv); + } + + error_propagate(errp, err); + return ret; +} + + +static int net_host_check_device(const char *device) +{ + int i; + const char *valid_param_list[] = { "tap", "socket", "dump" +#ifdef CONFIG_NET_BRIDGE + , "bridge" +#endif +#ifdef CONFIG_SLIRP + ,"user" +#endif +#ifdef CONFIG_VDE + ,"vde" +#endif + }; + for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) { + if (!strncmp(valid_param_list[i], device, + strlen(valid_param_list[i]))) + return 1; + } + + return 0; +} + +void net_host_device_add(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *opts_str = qdict_get_try_str(qdict, "opts"); + Error *local_err = NULL; + QemuOpts *opts; + + if (!net_host_check_device(device)) { + monitor_printf(mon, "invalid host network device %s\n", device); + return; + } + + opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); + if (!opts) { + return; + } + + qemu_opt_set(opts, "type", device); + + net_client_init(opts, 0, &local_err); + if (error_is_set(&local_err)) { + qerror_report_err(local_err); + error_free(local_err); + monitor_printf(mon, "adding host network device %s failed\n", device); + } +} + +void net_host_device_remove(Monitor *mon, const QDict *qdict) +{ + NetClientState *nc; + int vlan_id = qdict_get_int(qdict, "vlan_id"); + const char *device = qdict_get_str(qdict, "device"); + + nc = net_hub_find_client_by_name(vlan_id, device); + if (!nc) { + return; + } + if (!net_host_check_device(nc->model)) { + monitor_printf(mon, "invalid host network device %s\n", device); + return; + } + qemu_del_net_client(nc); +} + +void netdev_add(QemuOpts *opts, Error **errp) +{ + net_client_init(opts, 1, errp); +} + +int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret) +{ + Error *local_err = NULL; + QemuOptsList *opts_list; + QemuOpts *opts; + + opts_list = qemu_find_opts_err("netdev", &local_err); + if (error_is_set(&local_err)) { + goto exit_err; + } + + opts = qemu_opts_from_qdict(opts_list, qdict, &local_err); + if (error_is_set(&local_err)) { + goto exit_err; + } + + netdev_add(opts, &local_err); + if (error_is_set(&local_err)) { + qemu_opts_del(opts); + goto exit_err; + } + + return 0; + +exit_err: + qerror_report_err(local_err); + error_free(local_err); + return -1; +} + +void qmp_netdev_del(const char *id, Error **errp) +{ + NetClientState *nc; + QemuOpts *opts; + + nc = qemu_find_netdev(id); + if (!nc) { + error_set(errp, QERR_DEVICE_NOT_FOUND, id); + return; + } + + opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), id); + if (!opts) { + error_setg(errp, "Device '%s' is not a netdev", id); + return; + } + + qemu_del_net_client(nc); + qemu_opts_del(opts); +} + +void print_net_client(Monitor *mon, NetClientState *nc) +{ + monitor_printf(mon, "%s: type=%s,%s\n", nc->name, + NetClientOptionsKind_lookup[nc->info->type], nc->info_str); +} + +void do_info_network(Monitor *mon) +{ + NetClientState *nc, *peer; + NetClientOptionsKind type; + + net_hub_info(mon); + + QTAILQ_FOREACH(nc, &net_clients, next) { + peer = nc->peer; + type = nc->info->type; + + /* Skip if already printed in hub info */ + if (net_hub_id_for_client(nc, NULL) == 0) { + continue; + } + + if (!peer || type == NET_CLIENT_OPTIONS_KIND_NIC) { + print_net_client(mon, nc); + } /* else it's a netdev connected to a NIC, printed with the NIC */ + if (peer && type == NET_CLIENT_OPTIONS_KIND_NIC) { + monitor_printf(mon, " \\ "); + print_net_client(mon, peer); + } + } +} + +void qmp_set_link(const char *name, bool up, Error **errp) +{ + NetClientState *nc = NULL; + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (!strcmp(nc->name, name)) { + goto done; + } + } +done: + if (!nc) { + error_set(errp, QERR_DEVICE_NOT_FOUND, name); + return; + } + + nc->link_down = !up; + + if (nc->info->link_status_changed) { + nc->info->link_status_changed(nc); + } + + /* Notify peer. Don't update peer link status: this makes it possible to + * disconnect from host network without notifying the guest. + * FIXME: is disconnected link status change operation useful? + * + * Current behaviour is compatible with qemu vlans where there could be + * multiple clients that can still communicate with each other in + * disconnected mode. For now maintain this compatibility. */ + if (nc->peer && nc->peer->info->link_status_changed) { + nc->peer->info->link_status_changed(nc->peer); + } +} + +void net_cleanup(void) +{ + NetClientState *nc, *next_vc; + + QTAILQ_FOREACH_SAFE(nc, &net_clients, next, next_vc) { + qemu_del_net_client(nc); + } +} + +void net_check_clients(void) +{ + NetClientState *nc; + int i; + + /* Don't warn about the default network setup that you get if + * no command line -net or -netdev options are specified. There + * are two cases that we would otherwise complain about: + * (1) board doesn't support a NIC but the implicit "-net nic" + * requested one + * (2) CONFIG_SLIRP not set, in which case the implicit "-net nic" + * sets up a nic that isn't connected to anything. + */ + if (default_net) { + return; + } + + net_hub_check_clients(); + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (!nc->peer) { + fprintf(stderr, "Warning: %s %s has no peer\n", + nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC ? + "nic" : "netdev", nc->name); + } + } + + /* Check that all NICs requested via -net nic actually got created. + * NICs created via -device don't need to be checked here because + * they are always instantiated. + */ + for (i = 0; i < MAX_NICS; i++) { + NICInfo *nd = &nd_table[i]; + if (nd->used && !nd->instantiated) { + fprintf(stderr, "Warning: requested NIC (%s, model %s) " + "was not created (not supported by this machine?)\n", + nd->name ? nd->name : "anonymous", + nd->model ? nd->model : "unspecified"); + } + } +} + +static int net_init_client(QemuOpts *opts, void *dummy) +{ + Error *local_err = NULL; + + net_client_init(opts, 0, &local_err); + if (error_is_set(&local_err)) { + qerror_report_err(local_err); + error_free(local_err); + return -1; + } + + return 0; +} + +static int net_init_netdev(QemuOpts *opts, void *dummy) +{ + Error *local_err = NULL; + int ret; + + ret = net_client_init(opts, 1, &local_err); + if (error_is_set(&local_err)) { + qerror_report_err(local_err); + error_free(local_err); + return -1; + } + + return ret; +} + +int net_init_clients(void) +{ + QemuOptsList *net = qemu_find_opts("net"); + + if (default_net) { + /* if no clients, we use a default config */ + qemu_opts_set(net, NULL, "type", "nic"); +#ifdef CONFIG_SLIRP + qemu_opts_set(net, NULL, "type", "user"); +#endif + } + + QTAILQ_INIT(&net_clients); + + if (qemu_opts_foreach(qemu_find_opts("netdev"), net_init_netdev, NULL, 1) == -1) + return -1; + + if (qemu_opts_foreach(net, net_init_client, NULL, 1) == -1) { + return -1; + } + + return 0; +} + +int net_client_parse(QemuOptsList *opts_list, const char *optarg) +{ +#if defined(CONFIG_SLIRP) + int ret; + if (net_slirp_parse_legacy(opts_list, optarg, &ret)) { + return ret; + } +#endif + + if (!qemu_opts_parse(opts_list, optarg, 1)) { + return -1; + } + + default_net = 0; + return 0; +} + +/* From FreeBSD */ +/* XXX: optimize */ +unsigned compute_mcast_idx(const uint8_t *ep) +{ + uint32_t crc; + int carry, i, j; + uint8_t b; + + crc = 0xffffffff; + for (i = 0; i < 6; i++) { + b = *ep++; + for (j = 0; j < 8; j++) { + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); + crc <<= 1; + b >>= 1; + if (carry) { + crc = ((crc ^ POLYNOMIAL) | carry); + } + } + } + return crc >> 26; +} -- cgit v1.2.3 From 1422e32db51ff2b1194fb24a6201c4310be5667d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Oct 2012 08:43:34 +0200 Subject: net: reorganize headers Move public headers to include/net, and leave private headers in net/. Put the virtio headers in include/net/tap.h, removing the multiple copies that existed. Leave include/net/tap.h as the interface for NICs, and net/tap_int.h as the interface for OS-specific parts of the tap backend. Signed-off-by: Paolo Bonzini --- net/checksum.h | 29 ---------------------------- net/clients.h | 2 +- net/hub.c | 2 +- net/hub.h | 2 -- net/net.c | 4 ++-- net/queue.c | 2 +- net/queue.h | 58 ------------------------------------------------------- net/slirp.c | 2 +- net/slirp.h | 47 -------------------------------------------- net/socket.c | 2 +- net/tap-aix.c | 2 +- net/tap-bsd.c | 2 +- net/tap-haiku.c | 2 +- net/tap-linux.c | 3 ++- net/tap-linux.h | 20 ++----------------- net/tap-solaris.c | 2 +- net/tap-win32.c | 4 ++-- net/tap.c | 6 +++--- net/tap.h | 58 ------------------------------------------------------- net/tap_int.h | 46 +++++++++++++++++++++++++++++++++++++++++++ net/util.c | 2 +- net/vde.c | 2 +- 22 files changed, 68 insertions(+), 231 deletions(-) delete mode 100644 net/checksum.h delete mode 100644 net/queue.h delete mode 100644 net/slirp.h delete mode 100644 net/tap.h create mode 100644 net/tap_int.h (limited to 'net') diff --git a/net/checksum.h b/net/checksum.h deleted file mode 100644 index 1f052986e6..0000000000 --- a/net/checksum.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * IP checksumming functions. - * (c) 2008 Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ - -#ifndef QEMU_NET_CHECKSUM_H -#define QEMU_NET_CHECKSUM_H - -#include - -uint32_t net_checksum_add(int len, uint8_t *buf); -uint16_t net_checksum_finish(uint32_t sum); -uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto, - uint8_t *addrs, uint8_t *buf); -void net_checksum_calculate(uint8_t *data, int length); - -#endif /* QEMU_NET_CHECKSUM_H */ diff --git a/net/clients.h b/net/clients.h index c58cc6087c..77932942bd 100644 --- a/net/clients.h +++ b/net/clients.h @@ -24,7 +24,7 @@ #ifndef QEMU_NET_CLIENTS_H #define QEMU_NET_CLIENTS_H -#include "net.h" +#include "net/net.h" #include "qapi-types.h" int net_init_dump(const NetClientOptions *opts, const char *name, diff --git a/net/hub.c b/net/hub.c index be413012bb..8508ecf380 100644 --- a/net/hub.c +++ b/net/hub.c @@ -13,7 +13,7 @@ */ #include "monitor.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" #include "iov.h" diff --git a/net/hub.h b/net/hub.h index 4cbfdb128b..583ada89d8 100644 --- a/net/hub.h +++ b/net/hub.h @@ -20,8 +20,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name); NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); -int net_hub_id_for_client(NetClientState *nc, int *id); void net_hub_check_clients(void); -NetClientState *net_hub_port_find(int hub_id); #endif /* NET_HUB_H */ diff --git a/net/net.c b/net/net.c index 7b1600f17c..a4395be140 100644 --- a/net/net.c +++ b/net/net.c @@ -23,10 +23,10 @@ */ #include "config-host.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" -#include "slirp.h" +#include "net/slirp.h" #include "util.h" #include "monitor.h" diff --git a/net/queue.c b/net/queue.c index 254f28013a..542c549b1a 100644 --- a/net/queue.c +++ b/net/queue.c @@ -23,7 +23,7 @@ #include "net/queue.h" #include "qemu-queue.h" -#include "net.h" +#include "net/net.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 diff --git a/net/queue.h b/net/queue.h deleted file mode 100644 index fc02b33915..0000000000 --- a/net/queue.h +++ /dev/null @@ -1,58 +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. - */ - -#ifndef QEMU_NET_QUEUE_H -#define QEMU_NET_QUEUE_H - -#include "qemu-common.h" - -typedef struct NetPacket NetPacket; -typedef struct NetQueue NetQueue; - -typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret); - -#define QEMU_NET_PACKET_FLAG_NONE 0 -#define QEMU_NET_PACKET_FLAG_RAW (1<<0) - -NetQueue *qemu_new_net_queue(void *opaque); - -void qemu_del_net_queue(NetQueue *queue); - -ssize_t qemu_net_queue_send(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const uint8_t *data, - size_t size, - NetPacketSent *sent_cb); - -ssize_t qemu_net_queue_send_iov(NetQueue *queue, - NetClientState *sender, - unsigned flags, - const struct iovec *iov, - int iovcnt, - NetPacketSent *sent_cb); - -void qemu_net_queue_purge(NetQueue *queue, NetClientState *from); -bool qemu_net_queue_flush(NetQueue *queue); - -#endif /* QEMU_NET_QUEUE_H */ diff --git a/net/slirp.c b/net/slirp.c index f117412bad..5a11ac5859 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -29,7 +29,7 @@ #include #include #endif -#include "net.h" +#include "net/net.h" #include "clients.h" #include "hub.h" #include "monitor.h" diff --git a/net/slirp.h b/net/slirp.h deleted file mode 100644 index 2ca09b65b7..0000000000 --- a/net/slirp.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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. - */ -#ifndef QEMU_NET_SLIRP_H -#define QEMU_NET_SLIRP_H - -#include "qemu-common.h" -#include "qdict.h" -#include "qemu-option.h" -#include "qapi-types.h" - -#ifdef CONFIG_SLIRP - -void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict); -void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict); - -int net_slirp_redir(const char *redir_str); - -int net_slirp_parse_legacy(QemuOptsList *opts_list, const char *optarg, int *ret); - -int net_slirp_smb(const char *exported_dir); - -void do_info_usernet(Monitor *mon); - -#endif - -#endif /* QEMU_NET_SLIRP_H */ diff --git a/net/socket.c b/net/socket.c index cf309cd5b9..8430f1a161 100644 --- a/net/socket.c +++ b/net/socket.c @@ -23,7 +23,7 @@ */ #include "config-host.h" -#include "net.h" +#include "net/net.h" #include "clients.h" #include "monitor.h" #include "qemu-common.h" diff --git a/net/tap-aix.c b/net/tap-aix.c index f27c17729e..aff6c527e9 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) diff --git a/net/tap-bsd.c b/net/tap-bsd.c index a3b717dd1c..a1c55ad3de 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include "qemu-common.h" #include "sysemu.h" #include "qemu-error.h" diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 34739d1562..08cc034cee 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) diff --git a/net/tap-linux.c b/net/tap-linux.c index 3eaedc40ad..3de7b3b6ce 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -23,8 +23,9 @@ * THE SOFTWARE. */ +#include "tap_int.h" +#include "tap-linux.h" #include "net/tap.h" -#include "net/tap-linux.h" #include #include diff --git a/net/tap-linux.h b/net/tap-linux.h index 659e98122b..cb2a6d480a 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -13,8 +13,8 @@ * GNU General Public License for more details. */ -#ifndef QEMU_TAP_H -#define QEMU_TAP_H +#ifndef QEMU_TAP_LINUX_H +#define QEMU_TAP_LINUX_H #include #ifdef __linux__ @@ -44,20 +44,4 @@ #define TUN_F_TSO_ECN 0x08 /* I can handle TSO with ECN bits. */ #define TUN_F_UFO 0x10 /* I can handle UFO packets */ -struct virtio_net_hdr -{ - uint8_t flags; - uint8_t gso_type; - uint16_t hdr_len; - uint16_t gso_size; - uint16_t csum_start; - uint16_t csum_offset; -}; - -struct virtio_net_hdr_mrg_rxbuf -{ - struct virtio_net_hdr hdr; - uint16_t num_buffers; /* Number of merged rx buffers */ -}; - #endif /* QEMU_TAP_H */ diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 5d6ac42f24..f228fffb6d 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/tap.h" +#include "tap_int.h" #include "sysemu.h" #include diff --git a/net/tap-win32.c b/net/tap-win32.c index f9bd74109c..e37d8ee458 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -26,11 +26,11 @@ * distribution); if not, see . */ -#include "tap.h" +#include "tap_int.h" #include "qemu-common.h" #include "clients.h" /* net_init_tap */ -#include "net.h" +#include "net/net.h" #include "sysemu.h" #include "qemu-error.h" #include diff --git a/net/tap.c b/net/tap.c index 5ff78934dc..f8cabc4f86 100644 --- a/net/tap.c +++ b/net/tap.c @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "tap.h" +#include "tap_int.h" #include "config-host.h" @@ -33,14 +33,14 @@ #include #include -#include "net.h" +#include "net/net.h" #include "clients.h" #include "monitor.h" #include "sysemu.h" #include "qemu-common.h" #include "qemu-error.h" -#include "net/tap-linux.h" +#include "net/tap.h" #include "hw/vhost_net.h" diff --git a/net/tap.h b/net/tap.h deleted file mode 100644 index d44d83ae73..0000000000 --- a/net/tap.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * QEMU System Emulator - * - * 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. - */ - -#ifndef QEMU_NET_TAP_H -#define QEMU_NET_TAP_H - -#include "qemu-common.h" -#include "qapi-types.h" - -#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" -#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" - -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); - -ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); - -int tap_has_ufo(NetClientState *nc); -int tap_has_vnet_hdr(NetClientState *nc); -int tap_has_vnet_hdr_len(NetClientState *nc, int len); -void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr); -void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo); -void tap_set_vnet_hdr_len(NetClientState *nc, int len); - -int tap_set_sndbuf(int fd, const NetdevTapOptions *tap); -int tap_probe_vnet_hdr(int fd); -int tap_probe_vnet_hdr_len(int fd, int len); -int tap_probe_has_ufo(int fd); -void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); -void tap_fd_set_vnet_hdr_len(int fd, int len); - -int tap_get_fd(NetClientState *nc); - -struct vhost_net; -struct vhost_net *tap_get_vhost_net(NetClientState *nc); - -#endif /* QEMU_NET_TAP_H */ diff --git a/net/tap_int.h b/net/tap_int.h new file mode 100644 index 0000000000..1dffe12a45 --- /dev/null +++ b/net/tap_int.h @@ -0,0 +1,46 @@ +/* + * QEMU System Emulator + * + * 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. + */ + +#ifndef QEMU_TAP_H +#define QEMU_TAP_H + +#include "qemu-common.h" +#include "qapi-types.h" + +#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" +#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" + +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); + +ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); + +int tap_set_sndbuf(int fd, const NetdevTapOptions *tap); +int tap_probe_vnet_hdr(int fd); +int tap_probe_vnet_hdr_len(int fd, int len); +int tap_probe_has_ufo(int fd); +void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); +void tap_fd_set_vnet_hdr_len(int fd, int len); + +#endif /* QEMU_TAP_H */ diff --git a/net/util.c b/net/util.c index 1e9afbc1ae..7e9507679d 100644 --- a/net/util.c +++ b/net/util.c @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -#include "net/util.h" +#include "util.h" #include #include diff --git a/net/vde.c b/net/vde.c index cc5a07d65e..52d4f19fba 100644 --- a/net/vde.c +++ b/net/vde.c @@ -25,7 +25,7 @@ #include -#include "net.h" +#include "net/net.h" #include "clients.h" #include "qemu-common.h" #include "qemu-option.h" -- cgit v1.2.3 From 7b1b5d191385ca52e96caae2a05c64f3a63855d9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:43 +0100 Subject: qapi: move include files to include/qobject/ Signed-off-by: Paolo Bonzini --- net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index a4395be140..ead7e96fe1 100644 --- a/net/net.c +++ b/net/net.c @@ -38,7 +38,7 @@ #include "iov.h" #include "qapi-visit.h" #include "qapi/opts-visitor.h" -#include "qapi/qapi-dealloc-visitor.h" +#include "qapi/dealloc-visitor.h" /* Net bridge is currently not supported for W32. */ #if !defined(_WIN32) -- cgit v1.2.3 From 83c9089e73b81c69dc1ecdf859fa84d2c500fb5f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:19:49 +0100 Subject: monitor: move include files to include/monitor/ Signed-off-by: Paolo Bonzini --- net/hub.c | 2 +- net/net.c | 2 +- net/slirp.c | 2 +- net/socket.c | 2 +- net/tap.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/hub.c b/net/hub.c index 8508ecf380..81a73b54a7 100644 --- a/net/hub.c +++ b/net/hub.c @@ -12,7 +12,7 @@ * */ -#include "monitor.h" +#include "monitor/monitor.h" #include "net/net.h" #include "clients.h" #include "hub.h" diff --git a/net/net.c b/net/net.c index ead7e96fe1..e4d85a9cfa 100644 --- a/net/net.c +++ b/net/net.c @@ -29,7 +29,7 @@ #include "net/slirp.h" #include "util.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-common.h" #include "qemu_socket.h" #include "qemu-config.h" diff --git a/net/slirp.c b/net/slirp.c index 5a11ac5859..c37a5ef959 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -32,7 +32,7 @@ #include "net/net.h" #include "clients.h" #include "hub.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu_socket.h" #include "slirp/libslirp.h" #include "qemu-char.h" diff --git a/net/socket.c b/net/socket.c index 8430f1a161..bc2b951832 100644 --- a/net/socket.c +++ b/net/socket.c @@ -25,7 +25,7 @@ #include "net/net.h" #include "clients.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "qemu-common.h" #include "qemu-error.h" #include "qemu-option.h" diff --git a/net/tap.c b/net/tap.c index f8cabc4f86..9a677e9864 100644 --- a/net/tap.c +++ b/net/tap.c @@ -35,7 +35,7 @@ #include "net/net.h" #include "clients.h" -#include "monitor.h" +#include "monitor/monitor.h" #include "sysemu.h" #include "qemu-common.h" #include "qemu-error.h" -- cgit v1.2.3 From 1de7afc984b49af164e2619e6850b9732b173b34 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:00 +0100 Subject: misc: move include files to include/qemu/ Signed-off-by: Paolo Bonzini --- net/dump.c | 6 +++--- net/hub.c | 2 +- net/net.c | 6 +++--- net/queue.c | 2 +- net/slirp.c | 2 +- net/socket.c | 8 ++++---- net/tap-bsd.c | 2 +- net/tap-linux.c | 2 +- net/tap-solaris.c | 2 +- net/tap-win32.c | 2 +- net/tap.c | 2 +- net/vde.c | 2 +- 12 files changed, 19 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/dump.c b/net/dump.c index e0a5d74644..4119721720 100644 --- a/net/dump.c +++ b/net/dump.c @@ -24,9 +24,9 @@ #include "clients.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-log.h" -#include "qemu-timer.h" +#include "qemu/error-report.h" +#include "qemu/log.h" +#include "qemu/timer.h" #include "hub.h" typedef struct DumpState { diff --git a/net/hub.c b/net/hub.c index 81a73b54a7..5adfce444b 100644 --- a/net/hub.c +++ b/net/hub.c @@ -16,7 +16,7 @@ #include "net/net.h" #include "clients.h" #include "hub.h" -#include "iov.h" +#include "qemu/iov.h" /* * A hub broadcasts incoming packets to all its ports except the source port. diff --git a/net/net.c b/net/net.c index e4d85a9cfa..dbf3e1b003 100644 --- a/net/net.c +++ b/net/net.c @@ -31,11 +31,11 @@ #include "monitor/monitor.h" #include "qemu-common.h" -#include "qemu_socket.h" -#include "qemu-config.h" +#include "qemu/sockets.h" +#include "qemu/config-file.h" #include "qmp-commands.h" #include "hw/qdev.h" -#include "iov.h" +#include "qemu/iov.h" #include "qapi-visit.h" #include "qapi/opts-visitor.h" #include "qapi/dealloc-visitor.h" diff --git a/net/queue.c b/net/queue.c index 542c549b1a..6eaf5b63c0 100644 --- a/net/queue.c +++ b/net/queue.c @@ -22,7 +22,7 @@ */ #include "net/queue.h" -#include "qemu-queue.h" +#include "qemu/queue.h" #include "net/net.h" /* The delivery handler may only return zero if it will call diff --git a/net/slirp.c b/net/slirp.c index c37a5ef959..87bdc9d031 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -33,7 +33,7 @@ #include "clients.h" #include "hub.h" #include "monitor/monitor.h" -#include "qemu_socket.h" +#include "qemu/sockets.h" #include "slirp/libslirp.h" #include "qemu-char.h" diff --git a/net/socket.c b/net/socket.c index bc2b951832..396dc8c0b1 100644 --- a/net/socket.c +++ b/net/socket.c @@ -27,10 +27,10 @@ #include "clients.h" #include "monitor/monitor.h" #include "qemu-common.h" -#include "qemu-error.h" -#include "qemu-option.h" -#include "qemu_socket.h" -#include "iov.h" +#include "qemu/error-report.h" +#include "qemu/option.h" +#include "qemu/sockets.h" +#include "qemu/iov.h" typedef struct NetSocketState { NetClientState nc; diff --git a/net/tap-bsd.c b/net/tap-bsd.c index a1c55ad3de..b48182f678 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -25,7 +25,7 @@ #include "tap_int.h" #include "qemu-common.h" #include "sysemu.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #ifdef __NetBSD__ #include diff --git a/net/tap-linux.c b/net/tap-linux.c index 3de7b3b6ce..dd4b915243 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -32,7 +32,7 @@ #include "sysemu.h" #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #define PATH_NET_TUN "/dev/net/tun" diff --git a/net/tap-solaris.c b/net/tap-solaris.c index f228fffb6d..3d5fee5542 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -38,7 +38,7 @@ #include #include #include -#include "qemu-error.h" +#include "qemu/error-report.h" ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) { diff --git a/net/tap-win32.c b/net/tap-win32.c index e37d8ee458..1ddd6fa6e6 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -32,7 +32,7 @@ #include "clients.h" /* net_init_tap */ #include "net/net.h" #include "sysemu.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include #include #include diff --git a/net/tap.c b/net/tap.c index 9a677e9864..d34ff13398 100644 --- a/net/tap.c +++ b/net/tap.c @@ -38,7 +38,7 @@ #include "monitor/monitor.h" #include "sysemu.h" #include "qemu-common.h" -#include "qemu-error.h" +#include "qemu/error-report.h" #include "net/tap.h" diff --git a/net/vde.c b/net/vde.c index 52d4f19fba..754a141543 100644 --- a/net/vde.c +++ b/net/vde.c @@ -28,7 +28,7 @@ #include "net/net.h" #include "clients.h" #include "qemu-common.h" -#include "qemu-option.h" +#include "qemu/option.h" typedef struct VDEState { NetClientState nc; -- cgit v1.2.3 From 9c17d615a66ebd655871bf891ec0fe901ad8b332 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:04 +0100 Subject: softmmu: move include files to include/sysemu/ Signed-off-by: Paolo Bonzini --- net/tap-bsd.c | 2 +- net/tap-linux.c | 2 +- net/tap-solaris.c | 2 +- net/tap-win32.c | 2 +- net/tap.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/tap-bsd.c b/net/tap-bsd.c index b48182f678..01c705b4c0 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -24,7 +24,7 @@ #include "tap_int.h" #include "qemu-common.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/error-report.h" #ifdef __NetBSD__ diff --git a/net/tap-linux.c b/net/tap-linux.c index dd4b915243..059f5f34ab 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -30,7 +30,7 @@ #include #include -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-common.h" #include "qemu/error-report.h" diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 3d5fee5542..486a7ea838 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -23,7 +23,7 @@ */ #include "tap_int.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include #include diff --git a/net/tap-win32.c b/net/tap-win32.c index 1ddd6fa6e6..0c63cbd203 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -31,7 +31,7 @@ #include "qemu-common.h" #include "clients.h" /* net_init_tap */ #include "net/net.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu/error-report.h" #include #include diff --git a/net/tap.c b/net/tap.c index d34ff13398..eb40c42d7d 100644 --- a/net/tap.c +++ b/net/tap.c @@ -36,7 +36,7 @@ #include "net/net.h" #include "clients.h" #include "monitor/monitor.h" -#include "sysemu.h" +#include "sysemu/sysemu.h" #include "qemu-common.h" #include "qemu/error-report.h" -- cgit v1.2.3 From 927d4878b0ff319ed87fed9363f314613b0a5ed9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 17 Dec 2012 18:20:05 +0100 Subject: softmmu: move remaining include files to include/ subdirectories Signed-off-by: Paolo Bonzini --- net/slirp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/slirp.c b/net/slirp.c index 87bdc9d031..c14259f004 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -35,7 +35,7 @@ #include "monitor/monitor.h" #include "qemu/sockets.h" #include "slirp/libslirp.h" -#include "qemu-char.h" +#include "char/char.h" static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { -- cgit v1.2.3 From b2136140f68ce05122f611eb9cde4f0365ab6a00 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 20 Dec 2012 23:09:53 +0100 Subject: net: Add missing include statement (fix compiler warnings for MinGW) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These and some more compiler warnings were caused by a recent commit: net/tap-win32.c:724: warning: no previous prototype for ‘tap_has_ufo’ net/tap-win32.c:729: warning: no previous prototype for ‘tap_has_vnet_hdr’ ... Signed-off-by: Stefan Weil Signed-off-by: Blue Swirl --- net/tap-win32.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index 0c63cbd203..265369c3c5 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -31,6 +31,7 @@ #include "qemu-common.h" #include "clients.h" /* net_init_tap */ #include "net/net.h" +#include "net/tap.h" /* tap_has_ufo, ... */ #include "sysemu/sysemu.h" #include "qemu/error-report.h" #include -- cgit v1.2.3 From 3f124b687462ce3140d963a024705a89cdc8cee8 Mon Sep 17 00:00:00 2001 From: Liming Wang Date: Fri, 21 Dec 2012 16:56:58 +0800 Subject: net: add missing include file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To fix building error: CC net/vde.o net/vde.c: In function ‘vde_cleanup’: net/vde.c:65:5: error: implicit declaration of function ‘qemu_set_fd_handler’ [-Werror=implicit-function-declaration] net/vde.c:65:5: error: nested extern declaration of ‘qemu_set_fd_handler’ [-Werror=nested-externs] cc1: all warnings being treated as errors Signed-off-by: Liming Wang Signed-off-by: Blue Swirl --- net/vde.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/vde.c b/net/vde.c index 754a141543..4dea32d07a 100644 --- a/net/vde.c +++ b/net/vde.c @@ -29,6 +29,7 @@ #include "clients.h" #include "qemu-common.h" #include "qemu/option.h" +#include "qemu/main-loop.h" typedef struct VDEState { NetClientState nc; -- cgit v1.2.3 From 4d4545743f55b37d37535f7b32456b82c97efeb8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Nov 2012 16:03:42 +0100 Subject: qemu-option: move standard option definitions out of qemu-config.c Signed-off-by: Paolo Bonzini --- net/net.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'net') diff --git a/net/net.c b/net/net.c index dbf3e1b003..02b5458a1b 100644 --- a/net/net.c +++ b/net/net.c @@ -1054,3 +1054,29 @@ unsigned compute_mcast_idx(const uint8_t *ep) } return crc >> 26; } + +QemuOptsList qemu_netdev_opts = { + .name = "netdev", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_netdev_opts.head), + .desc = { + /* + * no elements => accept any params + * validation will happen later + */ + { /* end of list */ } + }, +}; + +QemuOptsList qemu_net_opts = { + .name = "net", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head), + .desc = { + /* + * no elements => accept any params + * validation will happen later + */ + { /* end of list */ } + }, +}; -- cgit v1.2.3 From 84f2d0ea0f39bc140a6c69ba8e3ffd6b10cae6fa Mon Sep 17 00:00:00 2001 From: Wenchao Xia Date: Mon, 14 Jan 2013 14:06:25 +0800 Subject: HMP: add QDict to info callback handler This patch change all info call back function to take additional QDict * parameter, which allow those command take parameter. Now it is set to NULL at default case. Signed-off-by: Wenchao Xia Signed-off-by: Luiz Capitulino --- net/net.c | 2 +- net/slirp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 02b5458a1b..cdd9b04989 100644 --- a/net/net.c +++ b/net/net.c @@ -852,7 +852,7 @@ void print_net_client(Monitor *mon, NetClientState *nc) NetClientOptionsKind_lookup[nc->info->type], nc->info_str); } -void do_info_network(Monitor *mon) +void do_info_network(Monitor *mon, const QDict *qdict) { NetClientState *nc, *peer; NetClientOptionsKind type; diff --git a/net/slirp.c b/net/slirp.c index c14259f004..4df550faf6 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -670,7 +670,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, return -1; } -void do_info_usernet(Monitor *mon) +void do_info_usernet(Monitor *mon, const QDict *qdict) { SlirpState *s; -- cgit v1.2.3 From c64f50d1e250879611e6f328e2c4fb18c8a4ab0c Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 22 Jan 2013 11:07:57 +0100 Subject: g_strdup(NULL) returns NULL; simplify Signed-off-by: Markus Armbruster Reviewed-by: Eric Blake Signed-off-by: Stefan Hajnoczi --- net/net.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index cdd9b04989..2f0ab3a121 100644 --- a/net/net.c +++ b/net/net.c @@ -566,9 +566,7 @@ static int net_init_nic(const NetClientOptions *opts, const char *name, assert(peer); nd->netdev = peer; } - if (name) { - nd->name = g_strdup(name); - } + nd->name = g_strdup(name); if (nic->has_model) { nd->model = g_strdup(nic->model); } -- cgit v1.2.3 From ec45f08313ce92039d52ea0338db4a0c862fef6a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:20 +0800 Subject: net: tap: using bool instead of bitfield Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-win32.c | 6 +++--- net/tap.c | 38 ++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index 265369c3c5..3052bbac14 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -722,9 +722,9 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return 0; } -int tap_has_ufo(NetClientState *nc) +bool tap_has_ufo(NetClientState *nc) { - return 0; + return false; } int tap_has_vnet_hdr(NetClientState *nc) @@ -741,7 +741,7 @@ void tap_fd_set_vnet_hdr_len(int fd, int len) { } -void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr) +void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr) { } diff --git a/net/tap.c b/net/tap.c index eb40c42d7d..5542c98c03 100644 --- a/net/tap.c +++ b/net/tap.c @@ -55,10 +55,10 @@ typedef struct TAPState { 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 using_vnet_hdr : 1; - unsigned int has_ufo: 1; + bool read_poll; + bool write_poll; + bool using_vnet_hdr; + bool has_ufo; VHostNetState *vhost_net; unsigned host_vnet_hdr_len; } TAPState; @@ -78,15 +78,15 @@ static void tap_update_fd_handler(TAPState *s) s); } -static void tap_read_poll(TAPState *s, int enable) +static void tap_read_poll(TAPState *s, bool enable) { - s->read_poll = !!enable; + s->read_poll = enable; tap_update_fd_handler(s); } -static void tap_write_poll(TAPState *s, int enable) +static void tap_write_poll(TAPState *s, bool enable) { - s->write_poll = !!enable; + s->write_poll = enable; tap_update_fd_handler(s); } @@ -94,7 +94,7 @@ static void tap_writable(void *opaque) { TAPState *s = opaque; - tap_write_poll(s, 0); + tap_write_poll(s, false); qemu_flush_queued_packets(&s->nc); } @@ -108,7 +108,7 @@ static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt } while (len == -1 && errno == EINTR); if (len == -1 && errno == EAGAIN) { - tap_write_poll(s, 1); + tap_write_poll(s, true); return 0; } @@ -186,7 +186,7 @@ ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) static void tap_send_completed(NetClientState *nc, ssize_t len) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - tap_read_poll(s, 1); + tap_read_poll(s, true); } static void tap_send(void *opaque) @@ -209,12 +209,12 @@ static void tap_send(void *opaque) size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed); if (size == 0) { - tap_read_poll(s, 0); + tap_read_poll(s, false); } } while (size > 0 && qemu_can_send_packet(&s->nc)); } -int tap_has_ufo(NetClientState *nc) +bool tap_has_ufo(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -253,12 +253,10 @@ void tap_set_vnet_hdr_len(NetClientState *nc, int len) s->host_vnet_hdr_len = len; } -void tap_using_vnet_hdr(NetClientState *nc, int using_vnet_hdr) +void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr) { TAPState *s = DO_UPCAST(TAPState, nc, nc); - using_vnet_hdr = using_vnet_hdr != 0; - assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); assert(!!s->host_vnet_hdr_len == using_vnet_hdr); @@ -290,8 +288,8 @@ static void tap_cleanup(NetClientState *nc) if (s->down_script[0]) launch_script(s->down_script, s->down_script_arg, s->fd); - tap_read_poll(s, 0); - tap_write_poll(s, 0); + tap_read_poll(s, false); + tap_write_poll(s, false); close(s->fd); s->fd = -1; } @@ -337,7 +335,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, s->fd = fd; s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; - s->using_vnet_hdr = 0; + s->using_vnet_hdr = false; s->has_ufo = tap_probe_has_ufo(s->fd); tap_set_offload(&s->nc, 0, 0, 0, 0, 0); /* @@ -347,7 +345,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) { tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len); } - tap_read_poll(s, 1); + tap_read_poll(s, true); s->vhost_net = NULL; return s; } -- cgit v1.2.3 From 28a65891a0deb10b222890b9eb916ca32cb977bb Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:21 +0800 Subject: net: tap: use abort() instead of assert(0) Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-linux.c | 4 ++-- net/tap-win32.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/tap-linux.c b/net/tap-linux.c index 059f5f34ab..0a6acc7d5a 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -164,7 +164,7 @@ int tap_probe_vnet_hdr_len(int fd, int len) if (ioctl(fd, TUNSETVNETHDRSZ, &orig) == -1) { fprintf(stderr, "TUNGETVNETHDRSZ ioctl() failed: %s. Exiting.\n", strerror(errno)); - assert(0); + abort(); return -errno; } return 1; @@ -175,7 +175,7 @@ void tap_fd_set_vnet_hdr_len(int fd, int len) if (ioctl(fd, TUNSETVNETHDRSZ, &len) == -1) { fprintf(stderr, "TUNSETVNETHDRSZ ioctl() failed: %s. Exiting.\n", strerror(errno)); - assert(0); + abort(); } } diff --git a/net/tap-win32.c b/net/tap-win32.c index 3052bbac14..601437ee2d 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -762,5 +762,5 @@ int tap_has_vnet_hdr_len(NetClientState *nc, int len) void tap_set_vnet_hdr_len(NetClientState *nc, int len) { - assert(0); + abort(); } -- cgit v1.2.3 From b356f76de31e343121cdab3a01b39182edce9519 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:22 +0800 Subject: net: introduce qemu_get_queue() To support multiqueue, the patch introduce a helper qemu_get_queue() which is used to get the NetClientState of a device. The following patches would refactor this helper to support multiqueue. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'net') diff --git a/net/net.c b/net/net.c index 2f0ab3a121..b98616172d 100644 --- a/net/net.c +++ b/net/net.c @@ -234,6 +234,11 @@ NICState *qemu_new_nic(NetClientInfo *info, return nic; } +NetClientState *qemu_get_queue(NICState *nic) +{ + return &nic->nc; +} + static void qemu_cleanup_net_client(NetClientState *nc) { QTAILQ_REMOVE(&net_clients, nc, next); -- cgit v1.2.3 From cc1f0f45425d0cca41ad421623f92bebc93a21a9 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:23 +0800 Subject: net: introduce qemu_get_nic() To support multiqueue, this patch introduces a helper qemu_get_nic() to get NICState from a NetClientState. The following patches would refactor this helper to support multiqueue. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index b98616172d..606e8606de 100644 --- a/net/net.c +++ b/net/net.c @@ -227,7 +227,7 @@ NICState *qemu_new_nic(NetClientInfo *info, nc = qemu_new_net_client(info, conf->peer, model, name); - nic = DO_UPCAST(NICState, nc, nc); + nic = qemu_get_nic(nc); nic->conf = conf; nic->opaque = opaque; @@ -239,6 +239,18 @@ NetClientState *qemu_get_queue(NICState *nic) return &nic->nc; } +NICState *qemu_get_nic(NetClientState *nc) +{ + return DO_UPCAST(NICState, nc, nc); +} + +void *qemu_get_nic_opaque(NetClientState *nc) +{ + NICState *nic = qemu_get_nic(nc); + + return nic->opaque; +} + static void qemu_cleanup_net_client(NetClientState *nc) { QTAILQ_REMOVE(&net_clients, nc, next); @@ -265,7 +277,7 @@ void qemu_del_net_client(NetClientState *nc) { /* If there is a peer NIC, delete and cleanup client, but do not free. */ if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - NICState *nic = DO_UPCAST(NICState, nc, nc->peer); + NICState *nic = qemu_get_nic(nc->peer); if (nic->peer_deleted) { return; } @@ -281,7 +293,7 @@ void qemu_del_net_client(NetClientState *nc) /* If this is a peer NIC and peer has already been deleted, free it now. */ if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - NICState *nic = DO_UPCAST(NICState, nc, nc); + NICState *nic = qemu_get_nic(nc); if (nic->peer_deleted) { qemu_free_net_client(nc->peer); } @@ -297,7 +309,7 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) QTAILQ_FOREACH(nc, &net_clients, next) { if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - func(DO_UPCAST(NICState, nc, nc), opaque); + func(qemu_get_nic(nc), opaque); } } } -- cgit v1.2.3 From 948ecf219c032e3483b35ba4e162e5eee17d8b77 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:24 +0800 Subject: net: intorduce qemu_del_nic() To support multiqueue nic, this patch separate the nic destructor from qemu_del_net_client() to a new helper qemu_del_nic() since the mapping bettween NiCState and NetClientState were not 1:1 in multiqueue. The following patches would refactor this function to support multiqueue nic. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 606e8606de..47d56e3a14 100644 --- a/net/net.c +++ b/net/net.c @@ -291,6 +291,15 @@ void qemu_del_net_client(NetClientState *nc) return; } + assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC); + + qemu_cleanup_net_client(nc); + qemu_free_net_client(nc); +} + +void qemu_del_nic(NICState *nic) +{ + NetClientState *nc = qemu_get_queue(nic); /* If this is a peer NIC and peer has already been deleted, free it now. */ if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { NICState *nic = qemu_get_nic(nc); @@ -931,7 +940,11 @@ void net_cleanup(void) NetClientState *nc, *next_vc; QTAILQ_FOREACH_SAFE(nc, &net_clients, next, next_vc) { - qemu_del_net_client(nc); + if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { + qemu_del_nic(qemu_get_nic(nc)); + } else { + qemu_del_net_client(nc); + } } } -- cgit v1.2.3 From 6c51ae73fc68de2a4f11f5a7ebb52a4e79687e7d Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:25 +0800 Subject: net: introduce qemu_find_net_clients_except() In multiqueue, all NetClientState that belongs to the same netdev or nic has the same id. So this patches introduces an helper qemu_find_net_clients_except() which finds all NetClientState with the same id. This will be used by multiqueue networking. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'net') diff --git a/net/net.c b/net/net.c index 47d56e3a14..16dd327782 100644 --- a/net/net.c +++ b/net/net.c @@ -508,6 +508,27 @@ NetClientState *qemu_find_netdev(const char *id) return NULL; } +int qemu_find_net_clients_except(const char *id, NetClientState **ncs, + NetClientOptionsKind type, int max) +{ + NetClientState *nc; + int ret = 0; + + QTAILQ_FOREACH(nc, &net_clients, next) { + if (nc->info->type == type) { + continue; + } + if (!strcmp(nc->name, id)) { + if (ret < max) { + ncs[ret] = nc; + } + ret++; + } + } + + return ret; +} + static int nic_get_free_idx(void) { int index; -- cgit v1.2.3 From 18a1541a8da40271056aab99100bdc38283c42ac Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:26 +0800 Subject: net: introduce qemu_net_client_setup() This patch separates the setup of NetClientState from its allocation, this will allow allocating an arrays of NetClientState and does the initialization one by one which is what multiqueue needs. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 16dd327782..3a5bdf6b3f 100644 --- a/net/net.c +++ b/net/net.c @@ -182,17 +182,12 @@ static char *assign_name(NetClientState *nc1, const char *model) return g_strdup(buf); } -NetClientState *qemu_new_net_client(NetClientInfo *info, - NetClientState *peer, - const char *model, - const char *name) +static void qemu_net_client_setup(NetClientState *nc, + NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name) { - NetClientState *nc; - - assert(info->size >= sizeof(NetClientState)); - - nc = g_malloc0(info->size); - nc->info = info; nc->model = g_strdup(model); if (name) { @@ -210,6 +205,20 @@ NetClientState *qemu_new_net_client(NetClientInfo *info, nc->send_queue = qemu_new_net_queue(nc); +} + +NetClientState *qemu_new_net_client(NetClientInfo *info, + NetClientState *peer, + const char *model, + const char *name) +{ + NetClientState *nc; + + assert(info->size >= sizeof(NetClientState)); + + nc = g_malloc0(info->size); + qemu_net_client_setup(nc, info, peer, model, name); + return nc; } -- cgit v1.2.3 From f7860455fd582b171e526b4b4647b9b9c9a3e703 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:27 +0800 Subject: net: introduce NetClientState destructor To allow allocating an array of NetClientState and free it once, this patch introduces destructor of NetClientState. Which could do type specific free, which could be used by multiqueue to free the array once. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 3a5bdf6b3f..98a1934b62 100644 --- a/net/net.c +++ b/net/net.c @@ -182,11 +182,17 @@ static char *assign_name(NetClientState *nc1, const char *model) return g_strdup(buf); } +static void qemu_net_client_destructor(NetClientState *nc) +{ + g_free(nc); +} + static void qemu_net_client_setup(NetClientState *nc, NetClientInfo *info, NetClientState *peer, const char *model, - const char *name) + const char *name, + NetClientDestructor *destructor) { nc->info = info; nc->model = g_strdup(model); @@ -204,7 +210,7 @@ static void qemu_net_client_setup(NetClientState *nc, QTAILQ_INSERT_TAIL(&net_clients, nc, next); nc->send_queue = qemu_new_net_queue(nc); - + nc->destructor = destructor; } NetClientState *qemu_new_net_client(NetClientInfo *info, @@ -217,7 +223,8 @@ NetClientState *qemu_new_net_client(NetClientInfo *info, assert(info->size >= sizeof(NetClientState)); nc = g_malloc0(info->size); - qemu_net_client_setup(nc, info, peer, model, name); + qemu_net_client_setup(nc, info, peer, model, name, + qemu_net_client_destructor); return nc; } @@ -279,7 +286,9 @@ static void qemu_free_net_client(NetClientState *nc) } g_free(nc->name); g_free(nc->model); - g_free(nc); + if (nc->destructor) { + nc->destructor(nc); + } } void qemu_del_net_client(NetClientState *nc) -- cgit v1.2.3 From 1ceef9f27359cbe92ef124bf74de6f792e71f6fb Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:28 +0800 Subject: net: multiqueue support This patch adds basic multiqueue support for qemu. The idea is simple, an array of NetClientStates were introduced in NICState, parse_netdev() were extended to find and match all NetClientStates belongs to the backend and place their pointers in NICConf. Then qemu_new_nic can setup a N:N mapping between NICStates that belongs to a nic and NICStates belongs to the netdev. And a queue_index were introduced in NetClientState to track its index. After this, each peers of a NICState were abstracted as a queue. After this change, all NetClientState that belongs to the same backend/nic has the same id. When use want to change the link status, all NetClientStates that belongs to the same backend/nic will be also changed. When user want to delete a device or netdev, all NetClientStates that belongs to the same backend/nic will be deleted also. Changing or deleting an specific queue is not allowed. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/net.c | 113 ++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 32 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 98a1934b62..98068625d4 100644 --- a/net/net.c +++ b/net/net.c @@ -236,28 +236,44 @@ NICState *qemu_new_nic(NetClientInfo *info, void *opaque) { NetClientState *nc; + NetClientState **peers = conf->peers.ncs; NICState *nic; + int i; assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); assert(info->size >= sizeof(NICState)); - nc = qemu_new_net_client(info, conf->peer, model, name); + nc = qemu_new_net_client(info, peers[0], model, name); + nc->queue_index = 0; nic = qemu_get_nic(nc); nic->conf = conf; nic->opaque = opaque; + for (i = 1; i < conf->queues; i++) { + qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name, + NULL); + nic->ncs[i].queue_index = i; + } + return nic; } +NetClientState *qemu_get_subqueue(NICState *nic, int queue_index) +{ + return &nic->ncs[queue_index]; +} + NetClientState *qemu_get_queue(NICState *nic) { - return &nic->nc; + return qemu_get_subqueue(nic, 0); } NICState *qemu_get_nic(NetClientState *nc) { - return DO_UPCAST(NICState, nc, nc); + NetClientState *nc0 = nc - nc->queue_index; + + return DO_UPCAST(NICState, ncs[0], nc0); } void *qemu_get_nic_opaque(NetClientState *nc) @@ -271,9 +287,7 @@ static void qemu_cleanup_net_client(NetClientState *nc) { QTAILQ_REMOVE(&net_clients, nc, next); - if (nc->info->cleanup) { - nc->info->cleanup(nc); - } + nc->info->cleanup(nc); } static void qemu_free_net_client(NetClientState *nc) @@ -293,6 +307,17 @@ static void qemu_free_net_client(NetClientState *nc) void qemu_del_net_client(NetClientState *nc) { + NetClientState *ncs[MAX_QUEUE_NUM]; + int queues, i; + + /* If the NetClientState belongs to a multiqueue backend, we will change all + * other NetClientStates also. + */ + queues = qemu_find_net_clients_except(nc->name, ncs, + NET_CLIENT_OPTIONS_KIND_NIC, + MAX_QUEUE_NUM); + assert(queues != 0); + /* If there is a peer NIC, delete and cleanup client, but do not free. */ if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { NICState *nic = qemu_get_nic(nc->peer); @@ -300,34 +325,47 @@ void qemu_del_net_client(NetClientState *nc) return; } nic->peer_deleted = true; - /* Let NIC know peer is gone. */ - nc->peer->link_down = true; + + for (i = 0; i < queues; i++) { + ncs[i]->peer->link_down = true; + } + if (nc->peer->info->link_status_changed) { nc->peer->info->link_status_changed(nc->peer); } - qemu_cleanup_net_client(nc); + + for (i = 0; i < queues; i++) { + qemu_cleanup_net_client(ncs[i]); + } + return; } assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC); - qemu_cleanup_net_client(nc); - qemu_free_net_client(nc); + for (i = 0; i < queues; i++) { + qemu_cleanup_net_client(ncs[i]); + qemu_free_net_client(ncs[i]); + } } void qemu_del_nic(NICState *nic) { - NetClientState *nc = qemu_get_queue(nic); + int i, queues = nic->conf->queues; + /* If this is a peer NIC and peer has already been deleted, free it now. */ - if (nc->peer && nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - NICState *nic = qemu_get_nic(nc); - if (nic->peer_deleted) { - qemu_free_net_client(nc->peer); + if (nic->peer_deleted) { + for (i = 0; i < queues; i++) { + qemu_free_net_client(qemu_get_subqueue(nic, i)->peer); } } - qemu_cleanup_net_client(nc); - qemu_free_net_client(nc); + for (i = queues - 1; i >= 0; i--) { + NetClientState *nc = qemu_get_subqueue(nic, i); + + qemu_cleanup_net_client(nc); + qemu_free_net_client(nc); + } } void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) @@ -336,7 +374,9 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) QTAILQ_FOREACH(nc, &net_clients, next) { if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { - func(qemu_get_nic(nc), opaque); + if (nc->queue_index == 0) { + func(qemu_get_nic(nc), opaque); + } } } } @@ -911,8 +951,10 @@ void qmp_netdev_del(const char *id, Error **errp) void print_net_client(Monitor *mon, NetClientState *nc) { - monitor_printf(mon, "%s: type=%s,%s\n", nc->name, - NetClientOptionsKind_lookup[nc->info->type], nc->info_str); + monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name, + nc->queue_index, + NetClientOptionsKind_lookup[nc->info->type], + nc->info_str); } void do_info_network(Monitor *mon, const QDict *qdict) @@ -943,20 +985,23 @@ void do_info_network(Monitor *mon, const QDict *qdict) void qmp_set_link(const char *name, bool up, Error **errp) { - NetClientState *nc = NULL; + NetClientState *ncs[MAX_QUEUE_NUM]; + NetClientState *nc; + int queues, i; - QTAILQ_FOREACH(nc, &net_clients, next) { - if (!strcmp(nc->name, name)) { - goto done; - } - } -done: - if (!nc) { + queues = qemu_find_net_clients_except(name, ncs, + NET_CLIENT_OPTIONS_KIND_MAX, + MAX_QUEUE_NUM); + + if (queues == 0) { error_set(errp, QERR_DEVICE_NOT_FOUND, name); return; } + nc = ncs[0]; - nc->link_down = !up; + for (i = 0; i < queues; i++) { + ncs[i]->link_down = !up; + } if (nc->info->link_status_changed) { nc->info->link_status_changed(nc); @@ -976,9 +1021,13 @@ done: void net_cleanup(void) { - NetClientState *nc, *next_vc; + NetClientState *nc; - QTAILQ_FOREACH_SAFE(nc, &net_clients, next, next_vc) { + /* We may del multiple entries during qemu_del_net_client(), + * so QTAILQ_FOREACH_SAFE() is also not safe here. + */ + while (!QTAILQ_EMPTY(&net_clients)) { + nc = QTAILQ_FIRST(&net_clients); if (nc->info->type == NET_CLIENT_OPTIONS_KIND_NIC) { qemu_del_nic(qemu_get_nic(nc)); } else { -- cgit v1.2.3 From 4e4f9ae7da90b55fe77307e58c867aa6b02a7384 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:29 +0800 Subject: tap: import linux multiqueue constants Import multiqueue constants from if_tun.h from 3.8-rc3. A new ifr flag IFF_MULTI_QUEUE were introduced to create a multiqueue backend by calling TUNSETIFF with the this flag and with the same interface name many times. A new ioctl TUNSETQUEUE were introduced. When doing this ioctl with IFF_DETACH_QUEUE, the queue were disabled in the linux kernel. When doing this ioctl with IFF_ATTACH_QUEUE, the queue were enabled in the linux kernel. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-linux.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/tap-linux.h b/net/tap-linux.h index cb2a6d480a..65087e1419 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -29,6 +29,7 @@ #define TUNSETSNDBUF _IOW('T', 212, int) #define TUNGETVNETHDRSZ _IOR('T', 215, int) #define TUNSETVNETHDRSZ _IOW('T', 216, int) +#define TUNSETQUEUE _IOW('T', 217, int) #endif @@ -36,6 +37,9 @@ #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 #define IFF_VNET_HDR 0x4000 +#define IFF_MULTI_QUEUE 0x0100 +#define IFF_ATTACH_QUEUE 0x0200 +#define IFF_DETACH_QUEUE 0x0400 /* Features for GSO (TUNSETOFFLOAD). */ #define TUN_F_CSUM 0x01 /* You can hand me unchecksummed packets. */ -- cgit v1.2.3 From 5193e5fbb52a33f1f684b0d42d29a452dfd29e4a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:30 +0800 Subject: tap: factor out common tap initialization This patch factors out the common initialization of tap into a new helper net_init_tap_one(). This will be used by multiqueue tap patches. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap.c | 130 +++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 57 deletions(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index 5542c98c03..23fb6e0306 100644 --- a/net/tap.c +++ b/net/tap.c @@ -591,6 +591,73 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, return fd; } +static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + const char *model, const char *name, + const char *ifname, const char *script, + const char *downscript, const char *vhostfdname, + int vnet_hdr, int fd) +{ + TAPState *s; + + s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); + if (!s) { + close(fd); + return -1; + } + + if (tap_set_sndbuf(s->fd, tap) < 0) { + return -1; + } + + if (tap->has_fd) { + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); + } else if (tap->has_helper) { + snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", + tap->helper); + } else { + const char *downscript; + + downscript = tap->has_downscript ? tap->downscript : + DEFAULT_NETWORK_DOWN_SCRIPT; + + snprintf(s->nc.info_str, sizeof(s->nc.info_str), + "ifname=%s,script=%s,downscript=%s", ifname, script, + downscript); + + if (strcmp(downscript, "no") != 0) { + snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); + snprintf(s->down_script_arg, sizeof(s->down_script_arg), + "%s", ifname); + } + } + + if (tap->has_vhost ? tap->vhost : + vhostfdname || (tap->has_vhostforce && tap->vhostforce)) { + int vhostfd; + + if (tap->has_vhostfd) { + vhostfd = monitor_handle_fd_param(cur_mon, vhostfdname); + if (vhostfd == -1) { + return -1; + } + } else { + vhostfd = -1; + } + + s->vhost_net = vhost_net_init(&s->nc, vhostfd, + tap->has_vhostforce && tap->vhostforce); + if (!s->vhost_net) { + error_report("vhost-net requested but could not be initialized"); + return -1; + } + } else if (tap->has_vhostfd) { + error_report("vhostfd= is not valid without vhost"); + return -1; + } + + return 0; +} + int net_init_tap(const NetClientOptions *opts, const char *name, NetClientState *peer) { @@ -598,10 +665,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name, int fd, vnet_hdr = 0; const char *model; - TAPState *s; /* for the no-fd, no-helper case */ const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ + const char *downscript = NULL; char ifname[128]; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); @@ -647,6 +714,8 @@ int net_init_tap(const NetClientOptions *opts, const char *name, } else { script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; + downscript = tap->has_downscript ? tap->downscript : + DEFAULT_NETWORK_DOWN_SCRIPT; fd = net_tap_init(tap, &vnet_hdr, script, ifname, sizeof ifname); if (fd == -1) { return -1; @@ -655,62 +724,9 @@ int net_init_tap(const NetClientOptions *opts, const char *name, model = "tap"; } - s = net_tap_fd_init(peer, model, name, fd, vnet_hdr); - if (!s) { - close(fd); - return -1; - } - - if (tap_set_sndbuf(s->fd, tap) < 0) { - return -1; - } - - if (tap->has_fd) { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); - } else if (tap->has_helper) { - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", - tap->helper); - } else { - const char *downscript; - - downscript = tap->has_downscript ? tap->downscript : - DEFAULT_NETWORK_DOWN_SCRIPT; - - snprintf(s->nc.info_str, sizeof(s->nc.info_str), - "ifname=%s,script=%s,downscript=%s", ifname, script, - downscript); - - if (strcmp(downscript, "no") != 0) { - snprintf(s->down_script, sizeof(s->down_script), "%s", downscript); - snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); - } - } - - if (tap->has_vhost ? tap->vhost : - tap->has_vhostfd || (tap->has_vhostforce && tap->vhostforce)) { - int vhostfd; - - if (tap->has_vhostfd) { - vhostfd = monitor_handle_fd_param(cur_mon, tap->vhostfd); - if (vhostfd == -1) { - return -1; - } - } else { - vhostfd = -1; - } - - s->vhost_net = vhost_net_init(&s->nc, vhostfd, - tap->has_vhostforce && tap->vhostforce); - if (!s->vhost_net) { - error_report("vhost-net requested but could not be initialized"); - return -1; - } - } else if (tap->has_vhostfd) { - error_report("vhostfd= is not valid without vhost"); - return -1; - } - - return 0; + return net_init_tap_one(tap, peer, model, name, ifname, script, + downscript, tap->has_vhostfd ? tap->vhostfd : NULL, + vnet_hdr, fd); } VHostNetState *tap_get_vhost_net(NetClientState *nc) -- cgit v1.2.3 From 94fdc6d03034f594c53d5413590e23fcb7ffc268 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:31 +0800 Subject: tap: add Linux multiqueue support This patch add basic multiqueue support for Linux. When multiqueue is needed, we will first check whether kernel support multiqueue tap before creating more queues. Two new functions tap_fd_enable() and tap_fd_disable() were introduced to enable and disable a specific queue. Since the multiqueue is only supported in Linux, return error on other platforms. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-aix.c | 10 ++++++++++ net/tap-bsd.c | 11 +++++++++++ net/tap-haiku.c | 11 +++++++++++ net/tap-linux.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ net/tap-solaris.c | 11 +++++++++++ net/tap_int.h | 2 ++ 6 files changed, 97 insertions(+) (limited to 'net') diff --git a/net/tap-aix.c b/net/tap-aix.c index aff6c527e9..66e0574fd7 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -59,3 +59,13 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 01c705b4c0..cfc7a289f8 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -145,3 +145,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 08cc034cee..664d40fb4d 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -59,3 +59,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap-linux.c b/net/tap-linux.c index 0a6acc7d5a..bdb0a790c8 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -41,6 +41,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required struct ifreq ifr; int fd, ret; int len = sizeof(struct virtio_net_hdr); + int mq_required = 0; TFR(fd = open(PATH_NET_TUN, O_RDWR)); if (fd < 0) { @@ -76,6 +77,20 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required ioctl(fd, TUNSETVNETHDRSZ, &len); } + if (mq_required) { + unsigned int features; + + if ((ioctl(fd, TUNGETFEATURES, &features) != 0) || + !(features & IFF_MULTI_QUEUE)) { + error_report("multiqueue required, but no kernel " + "support for IFF_MULTI_QUEUE available"); + close(fd); + return -1; + } else { + ifr.ifr_flags |= IFF_MULTI_QUEUE; + } + } + if (ifname[0] != '\0') pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); else @@ -209,3 +224,40 @@ void tap_fd_set_offload(int fd, int csum, int tso4, } } } + +/* Enable a specific queue of tap. */ +int tap_fd_enable(int fd) +{ + struct ifreq ifr; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_ATTACH_QUEUE; + ret = ioctl(fd, TUNSETQUEUE, (void *) &ifr); + + if (ret != 0) { + error_report("could not enable queue"); + } + + return ret; +} + +/* Disable a specific queue of tap/ */ +int tap_fd_disable(int fd) +{ + struct ifreq ifr; + int ret; + + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = IFF_DETACH_QUEUE; + ret = ioctl(fd, TUNSETQUEUE, (void *) &ifr); + + if (ret != 0) { + error_report("could not disable queue"); + } + + return ret; +} + diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 486a7ea838..12cc392c94 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -225,3 +225,14 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo) { } + +int tap_fd_enable(int fd) +{ + return -1; +} + +int tap_fd_disable(int fd) +{ + return -1; +} + diff --git a/net/tap_int.h b/net/tap_int.h index 1dffe12a45..ca1c21b451 100644 --- a/net/tap_int.h +++ b/net/tap_int.h @@ -42,5 +42,7 @@ int tap_probe_vnet_hdr_len(int fd, int len); int tap_probe_has_ufo(int fd); void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); +int tap_fd_enable(int fd); +int tap_fd_disable(int fd); #endif /* QEMU_TAP_H */ -- cgit v1.2.3 From 16dbaf905b72636d1bb066968bceabd64eaa1a9d Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:32 +0800 Subject: tap: support enabling or disabling a queue This patch introduce a new bit - enabled in TAPState which tracks whether a specific queue/fd is enabled. The tap/fd is enabled during initialization and could be enabled/disabled by tap_enalbe() and tap_disable() which calls platform specific helpers to do the real work. Polling of a tap fd can only done when the tap was enabled. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-win32.c | 10 ++++++++++ net/tap.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/tap-win32.c b/net/tap-win32.c index 601437ee2d..91e9e844a0 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -764,3 +764,13 @@ void tap_set_vnet_hdr_len(NetClientState *nc, int len) { abort(); } + +int tap_enable(NetClientState *nc) +{ + abort(); +} + +int tap_disable(NetClientState *nc) +{ + abort(); +} diff --git a/net/tap.c b/net/tap.c index 23fb6e0306..8610ba2231 100644 --- a/net/tap.c +++ b/net/tap.c @@ -59,6 +59,7 @@ typedef struct TAPState { bool write_poll; bool using_vnet_hdr; bool has_ufo; + bool enabled; VHostNetState *vhost_net; unsigned host_vnet_hdr_len; } TAPState; @@ -72,9 +73,9 @@ 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->read_poll && s->enabled ? tap_can_send : NULL, + s->read_poll && s->enabled ? tap_send : NULL, + s->write_poll && s->enabled ? tap_writable : NULL, s); } @@ -337,6 +338,7 @@ static TAPState *net_tap_fd_init(NetClientState *peer, s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0; s->using_vnet_hdr = false; s->has_ufo = tap_probe_has_ufo(s->fd); + s->enabled = true; tap_set_offload(&s->nc, 0, 0, 0, 0, 0); /* * Make sure host header length is set correctly in tap: @@ -735,3 +737,38 @@ VHostNetState *tap_get_vhost_net(NetClientState *nc) assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP); return s->vhost_net; } + +int tap_enable(NetClientState *nc) +{ + TAPState *s = DO_UPCAST(TAPState, nc, nc); + int ret; + + if (s->enabled) { + return 0; + } else { + ret = tap_fd_enable(s->fd); + if (ret == 0) { + s->enabled = true; + tap_update_fd_handler(s); + } + return ret; + } +} + +int tap_disable(NetClientState *nc) +{ + TAPState *s = DO_UPCAST(TAPState, nc, nc); + int ret; + + if (s->enabled == 0) { + return 0; + } else { + ret = tap_fd_disable(s->fd); + if (ret == 0) { + qemu_purge_queued_packets(nc); + s->enabled = false; + tap_update_fd_handler(s); + } + return ret; + } +} -- cgit v1.2.3 From e5dc0b402e64d245956c47cf22776e5206f322dc Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:33 +0800 Subject: tap: introduce a helper to get the name of an interface This patch introduces a helper tap_get_ifname() to get the device name of tap device. This is needed when ifname is unspecified in the command line and qemu were asked to create tap device by itself. In this situation, the name were allocated by kernel, so if multiqueue is asked, we need to fetch its name after creating the first queue. Only linux has this support since it's the only platform that supports multiqueue tap. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-aix.c | 6 ++++++ net/tap-bsd.c | 4 ++++ net/tap-haiku.c | 4 ++++ net/tap-linux.c | 13 +++++++++++++ net/tap-solaris.c | 4 ++++ net/tap_int.h | 1 + 6 files changed, 32 insertions(+) (limited to 'net') diff --git a/net/tap-aix.c b/net/tap-aix.c index 66e0574fd7..e760e9a0e7 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -69,3 +69,9 @@ int tap_fd_disable(int fd) { return -1; } + +int tap_fd_get_ifname(int fd, char *ifname) +{ + return -1; +} + diff --git a/net/tap-bsd.c b/net/tap-bsd.c index cfc7a289f8..4f22109e94 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -156,3 +156,7 @@ int tap_fd_disable(int fd) return -1; } +int tap_fd_get_ifname(int fd, char *ifname) +{ + return -1; +} diff --git a/net/tap-haiku.c b/net/tap-haiku.c index 664d40fb4d..b3b5fbb61e 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -70,3 +70,7 @@ int tap_fd_disable(int fd) return -1; } +int tap_fd_get_ifname(int fd, char *ifname) +{ + return -1; +} diff --git a/net/tap-linux.c b/net/tap-linux.c index bdb0a790c8..3b21662c13 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -261,3 +261,16 @@ int tap_fd_disable(int fd) return ret; } +int tap_fd_get_ifname(int fd, char *ifname) +{ + struct ifreq ifr; + + if (ioctl(fd, TUNGETIFF, &ifr) != 0) { + error_report("TUNGETIFF ioctl() failed: %s", + strerror(errno)); + return -1; + } + + pstrcpy(ifname, sizeof(ifr.ifr_name), ifr.ifr_name); + return 0; +} diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 12cc392c94..214d95e626 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -236,3 +236,7 @@ int tap_fd_disable(int fd) return -1; } +int tap_fd_get_ifname(int fd, char *ifname) +{ + return -1; +} diff --git a/net/tap_int.h b/net/tap_int.h index ca1c21b451..125f83d5b0 100644 --- a/net/tap_int.h +++ b/net/tap_int.h @@ -44,5 +44,6 @@ void tap_fd_set_offload(int fd, int csum, int tso4, int tso6, int ecn, int ufo); void tap_fd_set_vnet_hdr_len(int fd, int len); int tap_fd_enable(int fd); int tap_fd_disable(int fd); +int tap_fd_get_ifname(int fd, char *ifname); #endif /* QEMU_TAP_H */ -- cgit v1.2.3 From 264986e2c8f14a0f4a32ac6f1e083905833a5fc7 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Wed, 30 Jan 2013 19:12:34 +0800 Subject: tap: multiqueue support Recently, linux support multiqueue tap which could let userspace call TUNSETIFF for a signle device many times to create multiple file descriptors as independent queues. User could also enable/disabe a specific queue through TUNSETQUEUE. The patch adds the generic infrastructure to create multiqueue taps. To achieve this a new parameter "queues" were introduced to specify how many queues were expected to be created for tap by qemu itself. Alternatively, management could also pass multiple pre-created tap file descriptors separated with ':' through a new parameter fds like -netdev tap,id=hn0,fds="X:Y:..:Z". Multiple vhost file descriptors could also be passed in this way. Each TAPState were still associated to a tap fd, which mean multiple TAPStates were created when user needs multiqueue taps. Since each TAPState contains one NetClientState, with the multiqueue nic support, an N peers of NetClientState were built up. A new parameter, mq_required were introduce in tap_open() to create multiqueue tap fds. Signed-off-by: Jason Wang Signed-off-by: Anthony Liguori --- net/tap-aix.c | 3 +- net/tap-bsd.c | 3 +- net/tap-haiku.c | 3 +- net/tap-linux.c | 4 +- net/tap-solaris.c | 3 +- net/tap.c | 158 ++++++++++++++++++++++++++++++++++++++++++------------ net/tap_int.h | 3 +- 7 files changed, 135 insertions(+), 42 deletions(-) (limited to 'net') diff --git a/net/tap-aix.c b/net/tap-aix.c index e760e9a0e7..804d16448d 100644 --- a/net/tap-aix.c +++ b/net/tap-aix.c @@ -25,7 +25,8 @@ #include "tap_int.h" #include -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) { fprintf(stderr, "no tap on AIX\n"); return -1; diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 4f22109e94..bcdb2682b5 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -33,7 +33,8 @@ #include #endif -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) { int fd; #ifdef TAPGIFNAME diff --git a/net/tap-haiku.c b/net/tap-haiku.c index b3b5fbb61e..e5ce436d24 100644 --- a/net/tap-haiku.c +++ b/net/tap-haiku.c @@ -25,7 +25,8 @@ #include "tap_int.h" #include -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) { fprintf(stderr, "no tap on Haiku\n"); return -1; diff --git a/net/tap-linux.c b/net/tap-linux.c index 3b21662c13..a9531892a6 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -36,12 +36,12 @@ #define PATH_NET_TUN "/dev/net/tun" -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) { struct ifreq ifr; int fd, ret; int len = sizeof(struct virtio_net_hdr); - int mq_required = 0; TFR(fd = open(PATH_NET_TUN, O_RDWR)); if (fd < 0) { diff --git a/net/tap-solaris.c b/net/tap-solaris.c index 214d95e626..9c7278f1bf 100644 --- a/net/tap-solaris.c +++ b/net/tap-solaris.c @@ -173,7 +173,8 @@ static int tap_alloc(char *dev, size_t dev_size) return tap_fd; } -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) { char dev[10]=""; int fd; diff --git a/net/tap.c b/net/tap.c index 8610ba2231..1bf760995d 100644 --- a/net/tap.c +++ b/net/tap.c @@ -558,17 +558,10 @@ int net_init_bridge(const NetClientOptions *opts, const char *name, static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, const char *setup_script, char *ifname, - size_t ifname_sz) + size_t ifname_sz, int mq_required) { int fd, vnet_hdr_required; - if (tap->has_ifname) { - pstrcpy(ifname, ifname_sz, tap->ifname); - } else { - assert(ifname_sz > 0); - ifname[0] = '\0'; - } - if (tap->has_vnet_hdr) { *vnet_hdr = tap->vnet_hdr; vnet_hdr_required = *vnet_hdr; @@ -577,7 +570,8 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, vnet_hdr_required = 0; } - TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required)); + TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required, + mq_required)); if (fd < 0) { return -1; } @@ -593,6 +587,8 @@ static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr, return fd; } +#define MAX_TAP_QUEUES 1024 + static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, const char *model, const char *name, const char *ifname, const char *script, @@ -611,17 +607,12 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, return -1; } - if (tap->has_fd) { + if (tap->has_fd || tap->has_fds) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd); } else if (tap->has_helper) { snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s", tap->helper); } else { - const char *downscript; - - downscript = tap->has_downscript ? tap->downscript : - DEFAULT_NETWORK_DOWN_SCRIPT; - snprintf(s->nc.info_str, sizeof(s->nc.info_str), "ifname=%s,script=%s,downscript=%s", ifname, script, downscript); @@ -652,7 +643,7 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, error_report("vhost-net requested but could not be initialized"); return -1; } - } else if (tap->has_vhostfd) { + } else if (tap->has_vhostfd || tap->has_vhostfds) { error_report("vhostfd= is not valid without vhost"); return -1; } @@ -660,27 +651,54 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, return 0; } +static int get_fds(char *str, char *fds[], int max) +{ + char *ptr = str, *this; + size_t len = strlen(str); + int i = 0; + + while (i < max && ptr < str + len) { + this = strchr(ptr, ':'); + + if (this == NULL) { + fds[i] = g_strdup(ptr); + } else { + fds[i] = g_strndup(ptr, this - ptr); + } + + i++; + if (this == NULL) { + break; + } else { + ptr = this + 1; + } + } + + return i; +} + int net_init_tap(const NetClientOptions *opts, const char *name, NetClientState *peer) { const NetdevTapOptions *tap; - - int fd, vnet_hdr = 0; - const char *model; - + int fd, vnet_hdr = 0, i = 0, queues; /* for the no-fd, no-helper case */ const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */ const char *downscript = NULL; + const char *vhostfdname; char ifname[128]; assert(opts->kind == NET_CLIENT_OPTIONS_KIND_TAP); tap = opts->tap; + queues = tap->has_queues ? tap->queues : 1; + vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; if (tap->has_fd) { if (tap->has_ifname || tap->has_script || tap->has_downscript || - tap->has_vnet_hdr || tap->has_helper) { + tap->has_vnet_hdr || tap->has_helper || tap->has_queues || + tap->has_fds) { error_report("ifname=, script=, downscript=, vnet_hdr=, " - "and helper= are invalid with fd="); + "helper=, queues=, and fds= are invalid with fd="); return -1; } @@ -693,13 +711,61 @@ int net_init_tap(const NetClientOptions *opts, const char *name, vnet_hdr = tap_probe_vnet_hdr(fd); - model = "tap"; + if (net_init_tap_one(tap, peer, "tap", NULL, NULL, + script, downscript, + vhostfdname, vnet_hdr, fd)) { + return -1; + } + } else if (tap->has_fds) { + char *fds[MAX_TAP_QUEUES]; + char *vhost_fds[MAX_TAP_QUEUES]; + int nfds, nvhosts; + + if (tap->has_ifname || tap->has_script || tap->has_downscript || + tap->has_vnet_hdr || tap->has_helper || tap->has_queues || + tap->has_fd) { + error_report("ifname=, script=, downscript=, vnet_hdr=, " + "helper=, queues=, and fd= are invalid with fds="); + return -1; + } + + nfds = get_fds(tap->fds, fds, MAX_TAP_QUEUES); + if (tap->has_vhostfds) { + nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES); + if (nfds != nvhosts) { + error_report("The number of fds passed does not match the " + "number of vhostfds passed"); + return -1; + } + } + + for (i = 0; i < nfds; i++) { + fd = monitor_handle_fd_param(cur_mon, fds[i]); + if (fd == -1) { + return -1; + } + + fcntl(fd, F_SETFL, O_NONBLOCK); + if (i == 0) { + vnet_hdr = tap_probe_vnet_hdr(fd); + } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) { + error_report("vnet_hdr not consistent across given tap fds"); + return -1; + } + + if (net_init_tap_one(tap, peer, "tap", name, ifname, + script, downscript, + tap->has_vhostfds ? vhost_fds[i] : NULL, + vnet_hdr, fd)) { + return -1; + } + } } else if (tap->has_helper) { if (tap->has_ifname || tap->has_script || tap->has_downscript || - tap->has_vnet_hdr) { + tap->has_vnet_hdr || tap->has_queues || tap->has_fds) { error_report("ifname=, script=, downscript=, and vnet_hdr= " - "are invalid with helper="); + "queues=, and fds= are invalid with helper="); return -1; } @@ -709,26 +775,48 @@ int net_init_tap(const NetClientOptions *opts, const char *name, } fcntl(fd, F_SETFL, O_NONBLOCK); - vnet_hdr = tap_probe_vnet_hdr(fd); - model = "bridge"; - + if (net_init_tap_one(tap, peer, "bridge", name, ifname, + script, downscript, vhostfdname, + vnet_hdr, fd)) { + return -1; + } } else { script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; downscript = tap->has_downscript ? tap->downscript : DEFAULT_NETWORK_DOWN_SCRIPT; - fd = net_tap_init(tap, &vnet_hdr, script, ifname, sizeof ifname); - if (fd == -1) { - return -1; + + if (tap->has_ifname) { + pstrcpy(ifname, sizeof ifname, tap->ifname); + } else { + ifname[0] = '\0'; } - model = "tap"; + for (i = 0; i < queues; i++) { + fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script, + ifname, sizeof ifname, queues > 1); + if (fd == -1) { + return -1; + } + + if (queues > 1 && i == 0 && !tap->has_ifname) { + if (tap_fd_get_ifname(fd, ifname)) { + error_report("Fail to get ifname"); + return -1; + } + } + + if (net_init_tap_one(tap, peer, "tap", name, ifname, + i >= 1 ? "no" : script, + i >= 1 ? "no" : downscript, + vhostfdname, vnet_hdr, fd)) { + return -1; + } + } } - return net_init_tap_one(tap, peer, model, name, ifname, script, - downscript, tap->has_vhostfd ? tap->vhostfd : NULL, - vnet_hdr, fd); + return 0; } VHostNetState *tap_get_vhost_net(NetClientState *nc) diff --git a/net/tap_int.h b/net/tap_int.h index 125f83d5b0..86bb224bc8 100644 --- a/net/tap_int.h +++ b/net/tap_int.h @@ -32,7 +32,8 @@ #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown" -int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required); +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required); ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen); -- cgit v1.2.3 From 02cd809099322d6bdbd3fb232e9dd1018b125866 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Fri, 1 Feb 2013 18:02:50 -0600 Subject: tap: unbreak -netdev tap,fd=X The multiqueue patch series broke -netdev tap,fd=X which manifests as libvirt not being able to start a guest. This was because it passed NULL for the netdev name which results in an anonymous netdev device regardless of what the user specified. Cc: Jason Wang Cc: Bruce Rogers Reported-by: Bruce Rogers Signed-off-by: Anthony Liguori --- net/tap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index 1bf760995d..48c254ed85 100644 --- a/net/tap.c +++ b/net/tap.c @@ -711,7 +711,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, vnet_hdr = tap_probe_vnet_hdr(fd); - if (net_init_tap_one(tap, peer, "tap", NULL, NULL, + if (net_init_tap_one(tap, peer, "tap", name, NULL, script, downscript, vhostfdname, vnet_hdr, fd)) { return -1; -- cgit v1.2.3 From b890492110ccdc943554231d40b67d29fef6af82 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Wed, 6 Feb 2013 18:25:48 -0600 Subject: net: fix infinite loop on exit 1ceef9f27359cbe92ef124bf74de6f792e71f6fb added handling for cleaning up multiple queues in qemu_del_nic() for cases where multiqueue is in use. To determine the number of queues it looks at nic->conf->queues, then iterates through all the queues to cleanup the associated NetClientStates. If no queues are found, no NetClientStates are deleted. However, nic->conf->queues is only set when a peer is created via -netdev or netdev_add, and is otherwise 0. This causes us to spin in net_cleanup() if we attempt to shut down qemu before adding a host device. Since qemu_new_nic() unconditionally creates at least 1 queue/NetClientState at queue idx 0, make qemu_del_nic() always attempt to clean it up. Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- net/net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 98068625d4..f9e7136a2b 100644 --- a/net/net.c +++ b/net/net.c @@ -351,7 +351,7 @@ void qemu_del_net_client(NetClientState *nc) void qemu_del_nic(NICState *nic) { - int i, queues = nic->conf->queues; + int i, queues = MAX(nic->conf->queues, 1); /* If this is a peer NIC and peer has already been deleted, free it now. */ if (nic->peer_deleted) { -- cgit v1.2.3 From cc2a90432d9cb7546a2c4360ad7200a2fb3af31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Tue, 12 Feb 2013 23:16:06 +0100 Subject: net: Avoid NULL function pointer dereference on cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pSeries machine and some other devices don't supply a cleanup callback. Revert part of 1ceef9f27359cbe92ef124bf74de6f792e71f6fb that started calling it unconditionally. Cc: Jason Wang Signed-off-by: Andreas Färber Message-id: 1360707366-9271-1-git-send-email-afaerber@suse.de Signed-off-by: Anthony Liguori --- net/net.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index f9e7136a2b..be03a8dd14 100644 --- a/net/net.c +++ b/net/net.c @@ -287,7 +287,9 @@ static void qemu_cleanup_net_client(NetClientState *nc) { QTAILQ_REMOVE(&net_clients, nc, next); - nc->info->cleanup(nc); + if (nc->info->cleanup) { + nc->info->cleanup(nc); + } } static void qemu_free_net_client(NetClientState *nc) -- cgit v1.2.3 From 199ee608f0d08510b5c6c37f31a7fbff211d63c4 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Tue, 5 Feb 2013 17:53:31 +0100 Subject: net: fix qemu_flush_queued_packets() in presence of a hub When frontend and backend are connected through a hub as below (showing only one direction), and the frontend (or in general, all output ports of the hub) cannot accept more traffic, the backend queues packets in queue-A. When the frontend (or in general, one output port) becomes ready again, quemu tries to flush packets from queue-B, which is unfortunately empty. e1000.0 <--[queue B]-- hub0port0(hub)hub0port1 <--[queue A]-- tap.0 To fix this i propose to introduce a new function net_hub_flush() which is called when trying to flush a queue connected to a hub. Signed-off-by: Luigi Rizzo Signed-off-by: Stefan Hajnoczi --- net/hub.c | 14 ++++++++++++++ net/hub.h | 1 + net/net.c | 6 ++++++ 3 files changed, 21 insertions(+) (limited to 'net') diff --git a/net/hub.c b/net/hub.c index a24c9d17f7..df32074de0 100644 --- a/net/hub.c +++ b/net/hub.c @@ -338,3 +338,17 @@ void net_hub_check_clients(void) } } } + +bool net_hub_flush(NetClientState *nc) +{ + NetHubPort *port; + NetHubPort *source_port = DO_UPCAST(NetHubPort, nc, nc); + int ret = 0; + + QLIST_FOREACH(port, &source_port->hub->ports, next) { + if (port != source_port) { + ret += qemu_net_queue_flush(port->nc.send_queue); + } + } + return ret ? true : false; +} diff --git a/net/hub.h b/net/hub.h index 583ada89d8..a625effe00 100644 --- a/net/hub.h +++ b/net/hub.h @@ -21,5 +21,6 @@ NetClientState *net_hub_add_port(int hub_id, const char *name); NetClientState *net_hub_find_client_by_name(int hub_id, const char *name); void net_hub_info(Monitor *mon); void net_hub_check_clients(void); +bool net_hub_flush(NetClientState *nc); #endif /* NET_HUB_H */ diff --git a/net/net.c b/net/net.c index be03a8dd14..a66aa02472 100644 --- a/net/net.c +++ b/net/net.c @@ -441,6 +441,12 @@ void qemu_flush_queued_packets(NetClientState *nc) { nc->receive_disabled = 0; + if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_HUBPORT) { + if (net_hub_flush(nc->peer)) { + qemu_notify_event(); + } + return; + } if (qemu_net_queue_flush(nc->send_queue)) { /* We emptied the queue successfully, signal to the IO thread to repoll * the file descriptor (for tap, for example). -- cgit v1.2.3 From 7d91ddd25e3a4e5008a2ac16127d51a34fd56bf1 Mon Sep 17 00:00:00 2001 From: Luigi Rizzo Date: Tue, 5 Feb 2013 18:29:09 +0100 Subject: net: fix unbounded NetQueue In the current implementation of qemu, running without a network backend will cause the queue to grow unbounded when the guest is transmitting traffic. This patch fixes the problem by implementing bounded size NetQueue, used with an arbitrary limit of 10000 packets, and dropping packets when the queue is full _and_ the sender does not pass a callback. The second condition makes sure that we never drop packets that contains a callback (which would be tricky, because the producer expects the callback to be run when all previous packets have been consumed; so we cannot run it when the packet is dropped). If documentation is correct, producers that submit a callback should stop sending when their packet is queued, so there is no real risk that the queue exceeds the max size by large values. Signed-off-by: Luigi Rizzo Signed-off-by: Stefan Hajnoczi --- net/queue.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'net') diff --git a/net/queue.c b/net/queue.c index 6eaf5b63c0..859d02a136 100644 --- a/net/queue.c +++ b/net/queue.c @@ -50,6 +50,8 @@ struct NetPacket { struct NetQueue { void *opaque; + uint32_t nq_maxlen; + uint32_t nq_count; QTAILQ_HEAD(packets, NetPacket) packets; @@ -63,6 +65,8 @@ NetQueue *qemu_new_net_queue(void *opaque) queue = g_malloc0(sizeof(NetQueue)); queue->opaque = opaque; + queue->nq_maxlen = 10000; + queue->nq_count = 0; QTAILQ_INIT(&queue->packets); @@ -92,6 +96,9 @@ static void qemu_net_queue_append(NetQueue *queue, { NetPacket *packet; + if (queue->nq_count >= queue->nq_maxlen && !sent_cb) { + return; /* drop if queue full and no callback */ + } packet = g_malloc(sizeof(NetPacket) + size); packet->sender = sender; packet->flags = flags; @@ -99,6 +106,7 @@ static void qemu_net_queue_append(NetQueue *queue, packet->sent_cb = sent_cb; memcpy(packet->data, buf, size); + queue->nq_count++; QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); } @@ -113,6 +121,9 @@ static void qemu_net_queue_append_iov(NetQueue *queue, size_t max_len = 0; int i; + if (queue->nq_count >= queue->nq_maxlen && !sent_cb) { + return; /* drop if queue full and no callback */ + } for (i = 0; i < iovcnt; i++) { max_len += iov[i].iov_len; } @@ -130,6 +141,7 @@ static void qemu_net_queue_append_iov(NetQueue *queue, packet->size += len; } + queue->nq_count++; QTAILQ_INSERT_TAIL(&queue->packets, packet, entry); } @@ -220,6 +232,7 @@ void qemu_net_queue_purge(NetQueue *queue, NetClientState *from) QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) { if (packet->sender == from) { QTAILQ_REMOVE(&queue->packets, packet, entry); + queue->nq_count--; g_free(packet); } } @@ -233,6 +246,7 @@ bool qemu_net_queue_flush(NetQueue *queue) packet = QTAILQ_FIRST(&queue->packets); QTAILQ_REMOVE(&queue->packets, packet, entry); + queue->nq_count--; ret = qemu_net_queue_deliver(queue, packet->sender, @@ -240,6 +254,7 @@ bool qemu_net_queue_flush(NetQueue *queue) packet->data, packet->size); if (ret == 0) { + queue->nq_count++; QTAILQ_INSERT_HEAD(&queue->packets, packet, entry); return false; } -- cgit v1.2.3 From ce675a7579fea498397c5d2da3c5367671e9f02a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 21 Feb 2013 11:05:56 +0800 Subject: tap: forbid creating multiqueue tap when hub is used Obviously, hub does not support multiqueue tap. So this patch forbids creating multiple queue tap when hub is used to prevent the crash when command line such as "-net tap,queues=2" is used. Cc: qemu-stable@nongnu.org Signed-off-by: Jason Wang Signed-off-by: Stefan Hajnoczi --- net/tap.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index 48c254ed85..daab350efc 100644 --- a/net/tap.c +++ b/net/tap.c @@ -693,6 +693,13 @@ int net_init_tap(const NetClientOptions *opts, const char *name, queues = tap->has_queues ? tap->queues : 1; vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL; + /* QEMU vlans does not support multiqueue tap, in this case peer is set. + * For -netdev, peer is always NULL. */ + if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) { + error_report("Multiqueue tap cannnot be used with QEMU vlans"); + return -1; + } + if (tap->has_fd) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || -- cgit v1.2.3 From d26e445c80fddcc7483b83f3115e5067fef28fe6 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 25 Feb 2013 10:17:08 +0100 Subject: tap: set IFF_ONE_QUEUE per default historically the kernel queues packets two times. once at the device and second in qdisc. this is believed to cause interface stalls if one of these queues overruns. setting IFF_ONE_QUEUE is the default in kernels >= 3.8. the flag is ignored since then. see kernel commit 5d097109257c03a71845729f8db6b5770c4bbedc Signed-off-by: Peter Lieven Acked-by: Michael S. Tsirkin Signed-off-by: Stefan Hajnoczi --- net/tap-linux.c | 10 ++++++---- net/tap-linux.h | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'net') diff --git a/net/tap-linux.c b/net/tap-linux.c index a9531892a6..36c09e24d8 100644 --- a/net/tap-linux.c +++ b/net/tap-linux.c @@ -42,6 +42,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, struct ifreq ifr; int fd, ret; int len = sizeof(struct virtio_net_hdr); + unsigned int features; TFR(fd = open(PATH_NET_TUN, O_RDWR)); if (fd < 0) { @@ -51,9 +52,12 @@ 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 && + features & IFF_ONE_QUEUE) { + ifr.ifr_flags |= IFF_ONE_QUEUE; + } + if (*vnet_hdr) { if (ioctl(fd, TUNGETFEATURES, &features) == 0 && features & IFF_VNET_HDR) { *vnet_hdr = 1; @@ -78,8 +82,6 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, } if (mq_required) { - unsigned int features; - if ((ioctl(fd, TUNGETFEATURES, &features) != 0) || !(features & IFF_MULTI_QUEUE)) { error_report("multiqueue required, but no kernel " diff --git a/net/tap-linux.h b/net/tap-linux.h index 65087e1419..1cf35d41bd 100644 --- a/net/tap-linux.h +++ b/net/tap-linux.h @@ -34,10 +34,11 @@ #endif /* TUNSETIFF ifr flags */ -#define IFF_TAP 0x0002 -#define IFF_NO_PI 0x1000 -#define IFF_VNET_HDR 0x4000 -#define IFF_MULTI_QUEUE 0x0100 +#define IFF_TAP 0x0002 +#define IFF_NO_PI 0x1000 +#define IFF_ONE_QUEUE 0x2000 +#define IFF_VNET_HDR 0x4000 +#define IFF_MULTI_QUEUE 0x0100 #define IFF_ATTACH_QUEUE 0x0200 #define IFF_DETACH_QUEUE 0x0400 -- cgit v1.2.3 From f6b26cf257232e5854c0e5c98a8685c625bf986e Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 22 Feb 2013 23:15:06 +0800 Subject: net: reduce the unnecessary memory allocation of multiqueue Edivaldo reports a problem that the array of NetClientState in NICState is too large - MAX_QUEUE_NUM(1024) which will wastes memory even if multiqueue is not used. Instead of static arrays, solving this issue by allocating the queues on demand for both the NetClientState array in NICState and VirtIONetQueue array in VirtIONet. Tested by myself, with single virtio-net-pci device. The memory allocation is almost the same as when multiqueue is not merged. Cc: Edivaldo de Araujo Pereira Cc: qemu-stable@nongnu.org Signed-off-by: Jason Wang Signed-off-by: Stefan Hajnoczi --- net/net.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index a66aa02472..f3d67f8322 100644 --- a/net/net.c +++ b/net/net.c @@ -235,23 +235,20 @@ NICState *qemu_new_nic(NetClientInfo *info, const char *name, void *opaque) { - NetClientState *nc; NetClientState **peers = conf->peers.ncs; NICState *nic; - int i; + int i, queues = MAX(1, conf->queues); assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC); assert(info->size >= sizeof(NICState)); - nc = qemu_new_net_client(info, peers[0], model, name); - nc->queue_index = 0; - - nic = qemu_get_nic(nc); + nic = g_malloc0(info->size + sizeof(NetClientState) * queues); + nic->ncs = (void *)nic + info->size; nic->conf = conf; nic->opaque = opaque; - for (i = 1; i < conf->queues; i++) { - qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name, + for (i = 0; i < queues; i++) { + qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name, NULL); nic->ncs[i].queue_index = i; } @@ -261,7 +258,7 @@ NICState *qemu_new_nic(NetClientInfo *info, NetClientState *qemu_get_subqueue(NICState *nic, int queue_index) { - return &nic->ncs[queue_index]; + return nic->ncs + queue_index; } NetClientState *qemu_get_queue(NICState *nic) @@ -273,7 +270,7 @@ NICState *qemu_get_nic(NetClientState *nc) { NetClientState *nc0 = nc - nc->queue_index; - return DO_UPCAST(NICState, ncs[0], nc0); + return (NICState *)((void *)nc0 - nc->info->size); } void *qemu_get_nic_opaque(NetClientState *nc) @@ -368,6 +365,8 @@ void qemu_del_nic(NICState *nic) qemu_cleanup_net_client(nc); qemu_free_net_client(nc); } + + g_free(nic); } void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) -- cgit v1.2.3 From 9957fc7f1ed731e5228089ead3f350341cdd29c0 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 8 Mar 2013 19:58:32 +0100 Subject: MinGW: Replace setsockopt by qemu_setsocketopt Instead of adding missing type casts which are needed by MinGW for the 4th argument, the patch uses qemu_setsockopt which was invented for this purpose. Signed-off-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/socket.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 396dc8c0b1..d8b35a23cb 100644 --- a/net/socket.c +++ b/net/socket.c @@ -262,8 +262,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr } val = 1; - ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); + ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); goto fail; @@ -283,8 +282,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr imr.imr_interface.s_addr = htonl(INADDR_ANY); } - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (const char *)&imr, sizeof(struct ip_mreq)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &imr, sizeof(struct ip_mreq)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); goto fail; @@ -292,8 +291,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr /* Force mcast msgs to loopback (eg. several QEMUs in same host */ loop = 1; - ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, - (const char *)&loop, sizeof(loop)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, + &loop, sizeof(loop)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); goto fail; @@ -301,8 +300,8 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr /* If a bind address is given, only send packets from that address */ if (localaddr != NULL) { - ret = setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (const char *)localaddr, sizeof(*localaddr)); + ret = qemu_setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, + localaddr, sizeof(*localaddr)); if (ret < 0) { perror("setsockopt(IP_MULTICAST_IF)"); goto fail; @@ -521,7 +520,7 @@ static int net_socket_listen_init(NetClientState *peer, /* allow fast reuse */ val = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); + qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { @@ -659,8 +658,8 @@ static int net_socket_udp_init(NetClientState *peer, return -1; } val = 1; - ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (const char *)&val, sizeof(val)); + ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + &val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); closesocket(fd); -- cgit v1.2.3 From 085d813407453e498e05c37d988efba8c6f5af0a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 18 Mar 2013 17:20:07 +0000 Subject: Fix typos and misspellings Fix various typos and misspellings. The bulk of these were found with codespell. Signed-off-by: Peter Maydell Reviewed-by: Stefan Weil Signed-off-by: Stefan Hajnoczi --- net/tap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index daab350efc..ce796997a3 100644 --- a/net/tap.c +++ b/net/tap.c @@ -696,7 +696,7 @@ int net_init_tap(const NetClientOptions *opts, const char *name, /* QEMU vlans does not support multiqueue tap, in this case peer is set. * For -netdev, peer is always NULL. */ if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) { - error_report("Multiqueue tap cannnot be used with QEMU vlans"); + error_report("Multiqueue tap cannot be used with QEMU vlans"); return -1; } -- cgit v1.2.3 From 20048d0a12b1080f688ff9b82696134df1aa3607 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 27 Feb 2013 15:05:47 +0100 Subject: net: use socket_set_nodelay() for -netdev socket Reduce -netdev socket latency by disabling the Nagle algorithm on SOCK_STREAM sockets in net/socket.c. Since we are tunelling Ethernet over TCP we shouldn't artificially delay outgoing packets, let the guest decide packet scheduling. I already get sub-millisecond -netdev socket ping times on localhost, so there was no measurable difference in my testing. This won't hurt though and may improve remote socket performance. Signed-off-by: Stefan Hajnoczi Reviewed-by: Benoit Canet Reviewed-by: Daniel P. Berrange --- net/socket.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index d8b35a23cb..b0c83e022c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -438,6 +438,9 @@ static NetSocketState *net_socket_fd_init_stream(NetClientState *peer, s->fd = fd; s->listen_fd = -1; + /* Disable Nagle algorithm on TCP sockets to reduce latency */ + socket_set_nodelay(fd); + if (is_connected) { net_socket_connect(s); } else { -- cgit v1.2.3 From 5acf5ea4bc1535657692c509092caddec3d719ff Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Sat, 9 Mar 2013 11:21:02 +0200 Subject: Checksum-related utility functions net_checksum_add_cont() checksum calculation for scattered data with odd chunk sizes net_raw_checksum() checksum calculation for a buffer Signed-off-by: Dmitry Fleytman Signed-off-by: Yan Vugenfirer Signed-off-by: Stefan Hajnoczi --- net/checksum.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/checksum.c b/net/checksum.c index 9919b2e5fd..4fa5563e7c 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -20,16 +20,17 @@ #define PROTO_TCP 6 #define PROTO_UDP 17 -uint32_t net_checksum_add(int len, uint8_t *buf) +uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq) { uint32_t sum = 0; int i; - for (i = 0; i < len; i++) { - if (i & 1) - sum += (uint32_t)buf[i]; - else - sum += (uint32_t)buf[i] << 8; + for (i = seq; i < seq + len; i++) { + if (i & 1) { + sum += (uint32_t)buf[i - seq]; + } else { + sum += (uint32_t)buf[i - seq] << 8; + } } return sum; } -- cgit v1.2.3 From 84026301694b98dd08272e613da3497b17023d5c Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Sat, 9 Mar 2013 11:21:03 +0200 Subject: net: iovec checksum calculator Signed-off-by: Dmitry Fleytman Signed-off-by: Yan Vugenfirer Signed-off-by: Stefan Hajnoczi --- net/checksum.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'net') diff --git a/net/checksum.c b/net/checksum.c index 4fa5563e7c..14c08550e0 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -15,6 +15,7 @@ * along with this program; if not, see . */ +#include "qemu-common.h" #include "net/checksum.h" #define PROTO_TCP 6 @@ -84,3 +85,31 @@ void net_checksum_calculate(uint8_t *data, int length) data[14+hlen+csum_offset] = csum >> 8; data[14+hlen+csum_offset+1] = csum & 0xff; } + +uint32_t +net_checksum_add_iov(const struct iovec *iov, const unsigned int iov_cnt, + uint32_t iov_off, uint32_t size) +{ + size_t iovec_off, buf_off; + unsigned int i; + uint32_t res = 0; + uint32_t seq = 0; + + iovec_off = 0; + buf_off = 0; + for (i = 0; i < iov_cnt && size; i++) { + if (iov_off < (iovec_off + iov[i].iov_len)) { + size_t len = MIN((iovec_off + iov[i].iov_len) - iov_off , size); + void *chunk_buf = iov[i].iov_base + (iov_off - iovec_off); + + res += net_checksum_add_cont(len, chunk_buf, seq); + seq += len; + + buf_off += len; + iov_off += len; + size -= len; + } + iovec_off += iov[i].iov_len; + } + return res; +} -- cgit v1.2.3 From 75020a7021513ad4cbad2aa5f6de5d390016f099 Mon Sep 17 00:00:00 2001 From: Dmitry Fleytman Date: Sat, 9 Mar 2013 11:21:04 +0200 Subject: Common definitions for VMWARE devices Signed-off-by: Dmitry Fleytman Signed-off-by: Yan Vugenfirer Signed-off-by: Stefan Hajnoczi --- net/Makefile.objs | 1 + net/eth.c | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 net/eth.c (limited to 'net') diff --git a/net/Makefile.objs b/net/Makefile.objs index a08cd14e2e..4854a14fe4 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -1,6 +1,7 @@ common-obj-y = net.o queue.o checksum.o util.o hub.o common-obj-y += socket.o common-obj-y += dump.o +common-obj-y += eth.o common-obj-$(CONFIG_POSIX) += tap.o common-obj-$(CONFIG_LINUX) += tap-linux.o common-obj-$(CONFIG_WIN32) += tap-win32.o diff --git a/net/eth.c b/net/eth.c new file mode 100644 index 0000000000..1d7494d5e5 --- /dev/null +++ b/net/eth.c @@ -0,0 +1,217 @@ +/* + * QEMU network structures definitions and helper functions + * + * Copyright (c) 2012 Ravello Systems LTD (http://ravellosystems.com) + * + * Developed by Daynix Computing LTD (http://www.daynix.com) + * + * Authors: + * Dmitry Fleytman + * Tamir Shomer + * Yan Vugenfirer + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "net/eth.h" +#include "net/checksum.h" +#include "qemu-common.h" +#include "net/tap.h" + +void eth_setup_vlan_headers(struct eth_header *ehdr, uint16_t vlan_tag, + bool *is_new) +{ + struct vlan_header *vhdr = PKT_GET_VLAN_HDR(ehdr); + + switch (be16_to_cpu(ehdr->h_proto)) { + case ETH_P_VLAN: + case ETH_P_DVLAN: + /* vlan hdr exists */ + *is_new = false; + break; + + default: + /* No VLAN header, put a new one */ + vhdr->h_proto = ehdr->h_proto; + ehdr->h_proto = cpu_to_be16(ETH_P_VLAN); + *is_new = true; + break; + } + vhdr->h_tci = cpu_to_be16(vlan_tag); +} + +uint8_t +eth_get_gso_type(uint16_t l3_proto, uint8_t *l3_hdr, uint8_t l4proto) +{ + uint8_t ecn_state = 0; + + if (l3_proto == ETH_P_IP) { + struct ip_header *iphdr = (struct ip_header *) l3_hdr; + + if (IP_HEADER_VERSION(iphdr) == IP_HEADER_VERSION_4) { + if (IPTOS_ECN(iphdr->ip_tos) == IPTOS_ECN_CE) { + ecn_state = VIRTIO_NET_HDR_GSO_ECN; + } + if (l4proto == IP_PROTO_TCP) { + return VIRTIO_NET_HDR_GSO_TCPV4 | ecn_state; + } else if (l4proto == IP_PROTO_UDP) { + return VIRTIO_NET_HDR_GSO_UDP | ecn_state; + } + } + } else if (l3_proto == ETH_P_IPV6) { + struct ip6_header *ip6hdr = (struct ip6_header *) l3_hdr; + + if (IP6_ECN(ip6hdr->ip6_ecn_acc) == IP6_ECN_CE) { + ecn_state = VIRTIO_NET_HDR_GSO_ECN; + } + + if (l4proto == IP_PROTO_TCP) { + return VIRTIO_NET_HDR_GSO_TCPV6 | ecn_state; + } + } + + /* Unsupported offload */ + assert(false); + + return VIRTIO_NET_HDR_GSO_NONE | ecn_state; +} + +void eth_get_protocols(const uint8_t *headers, + uint32_t hdr_length, + bool *isip4, bool *isip6, + bool *isudp, bool *istcp) +{ + int proto; + size_t l2hdr_len = eth_get_l2_hdr_length(headers); + assert(hdr_length >= eth_get_l2_hdr_length(headers)); + *isip4 = *isip6 = *isudp = *istcp = false; + + proto = eth_get_l3_proto(headers, l2hdr_len); + if (proto == ETH_P_IP) { + *isip4 = true; + + struct ip_header *iphdr; + + assert(hdr_length >= + eth_get_l2_hdr_length(headers) + sizeof(struct ip_header)); + + iphdr = PKT_GET_IP_HDR(headers); + + if (IP_HEADER_VERSION(iphdr) == IP_HEADER_VERSION_4) { + if (iphdr->ip_p == IP_PROTO_TCP) { + *istcp = true; + } else if (iphdr->ip_p == IP_PROTO_UDP) { + *isudp = true; + } + } + } else if (proto == ETH_P_IPV6) { + uint8_t l4proto; + size_t full_ip6hdr_len; + + struct iovec hdr_vec; + hdr_vec.iov_base = (void *) headers; + hdr_vec.iov_len = hdr_length; + + *isip6 = true; + if (eth_parse_ipv6_hdr(&hdr_vec, 1, l2hdr_len, + &l4proto, &full_ip6hdr_len)) { + if (l4proto == IP_PROTO_TCP) { + *istcp = true; + } else if (l4proto == IP_PROTO_UDP) { + *isudp = true; + } + } + } +} + +void +eth_setup_ip4_fragmentation(const void *l2hdr, size_t l2hdr_len, + void *l3hdr, size_t l3hdr_len, + size_t l3payload_len, + size_t frag_offset, bool more_frags) +{ + if (eth_get_l3_proto(l2hdr, l2hdr_len) == ETH_P_IP) { + uint16_t orig_flags; + struct ip_header *iphdr = (struct ip_header *) l3hdr; + uint16_t frag_off_units = frag_offset / IP_FRAG_UNIT_SIZE; + uint16_t new_ip_off; + + assert(frag_offset % IP_FRAG_UNIT_SIZE == 0); + assert((frag_off_units & ~IP_OFFMASK) == 0); + + orig_flags = be16_to_cpu(iphdr->ip_off) & ~(IP_OFFMASK|IP_MF); + new_ip_off = frag_off_units | orig_flags | (more_frags ? IP_MF : 0); + iphdr->ip_off = cpu_to_be16(new_ip_off); + iphdr->ip_len = cpu_to_be16(l3payload_len + l3hdr_len); + } +} + +void +eth_fix_ip4_checksum(void *l3hdr, size_t l3hdr_len) +{ + struct ip_header *iphdr = (struct ip_header *) l3hdr; + iphdr->ip_sum = 0; + iphdr->ip_sum = cpu_to_be16(net_raw_checksum(l3hdr, l3hdr_len)); +} + +uint32_t +eth_calc_pseudo_hdr_csum(struct ip_header *iphdr, uint16_t csl) +{ + struct ip_pseudo_header ipph; + ipph.ip_src = iphdr->ip_src; + ipph.ip_dst = iphdr->ip_dst; + ipph.ip_payload = cpu_to_be16(csl); + ipph.ip_proto = iphdr->ip_p; + ipph.zeros = 0; + return net_checksum_add(sizeof(ipph), (uint8_t *) &ipph); +} + +static bool +eth_is_ip6_extension_header_type(uint8_t hdr_type) +{ + switch (hdr_type) { + case IP6_HOP_BY_HOP: + case IP6_ROUTING: + case IP6_FRAGMENT: + case IP6_ESP: + case IP6_AUTHENTICATION: + case IP6_DESTINATON: + case IP6_MOBILITY: + return true; + default: + return false; + } +} + +bool eth_parse_ipv6_hdr(struct iovec *pkt, int pkt_frags, + size_t ip6hdr_off, uint8_t *l4proto, + size_t *full_hdr_len) +{ + struct ip6_header ip6_hdr; + struct ip6_ext_hdr ext_hdr; + size_t bytes_read; + + bytes_read = iov_to_buf(pkt, pkt_frags, ip6hdr_off, + &ip6_hdr, sizeof(ip6_hdr)); + if (bytes_read < sizeof(ip6_hdr)) { + return false; + } + + *full_hdr_len = sizeof(struct ip6_header); + + if (!eth_is_ip6_extension_header_type(ip6_hdr.ip6_nxt)) { + *l4proto = ip6_hdr.ip6_nxt; + return true; + } + + do { + bytes_read = iov_to_buf(pkt, pkt_frags, ip6hdr_off + *full_hdr_len, + &ext_hdr, sizeof(ext_hdr)); + *full_hdr_len += (ext_hdr.ip6r_len + 1) * IP6_EXT_GRANULARITY; + } while (eth_is_ip6_extension_header_type(ext_hdr.ip6r_nxt)); + + *l4proto = ext_hdr.ip6r_nxt; + return true; +} -- cgit v1.2.3 From d32fcad366e5f45d33dab2ee4de0e5729439680b Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Mon, 18 Mar 2013 11:43:44 -0700 Subject: net: increase buffer size to accommodate Jumbo frame pkts Socket buffer sizes were hard-coded to 4K for VDE and socket netdevs. Bump this up to 68K (ala tap netdev) to handle maximum GSO packet size (64k) plus plenty of room for the ethernet and virtio_net headers. Originally, ran into this limitation when using -netdev UDP sockets to connect VM-to-VM, where VM interface is configure with MTU=9000. (Using virtio_net NIC model). Test is simple: ping -M do -s 8500 . This test will attempt to ping with unfragmented packet of given size. Without patch, size is limited to < 4K (minus protocol hdrs). With patch, ping test works with pkt size up to 9000 (again, minus protocol hdrs). v2: per Stefan, increase buf size to (4096+65536) as done in tap and apply to vde and socket netdevs. v1: increase buf size to 12K just for -netdev UDP sockets Signed-off-by: Scott Feldman Signed-off-by: Stefan Hajnoczi --- net/net.c | 2 +- net/socket.c | 4 ++-- net/tap.c | 7 +------ net/vde.c | 2 +- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index f3d67f8322..7869161d8d 100644 --- a/net/net.c +++ b/net/net.c @@ -497,7 +497,7 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size) static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov, int iovcnt) { - uint8_t buffer[4096]; + uint8_t buffer[NET_BUFSIZE]; size_t offset; offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer)); diff --git a/net/socket.c b/net/socket.c index b0c83e022c..6c3752b88a 100644 --- a/net/socket.c +++ b/net/socket.c @@ -40,7 +40,7 @@ typedef struct NetSocketState { unsigned int index; unsigned int packet_len; unsigned int send_index; /* number of bytes sent (only SOCK_STREAM) */ - uint8_t buf[4096]; + uint8_t buf[NET_BUFSIZE]; struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ IOHandler *send_fn; /* differs between SOCK_STREAM/SOCK_DGRAM */ bool read_poll; /* waiting to receive data? */ @@ -146,7 +146,7 @@ static void net_socket_send(void *opaque) NetSocketState *s = opaque; int size, err; unsigned l; - uint8_t buf1[4096]; + uint8_t buf1[NET_BUFSIZE]; const uint8_t *buf; size = qemu_recv(s->fd, buf1, sizeof(buf1), 0); diff --git a/net/tap.c b/net/tap.c index ce796997a3..e7c84811ac 100644 --- a/net/tap.c +++ b/net/tap.c @@ -44,17 +44,12 @@ #include "hw/vhost_net.h" -/* Maximum GSO packet size (64k) plus plenty of room for - * the ethernet and virtio_net headers - */ -#define TAP_BUFSIZE (4096 + 65536) - typedef struct TAPState { NetClientState nc; int fd; char down_script[1024]; char down_script_arg[128]; - uint8_t buf[TAP_BUFSIZE]; + uint8_t buf[NET_BUFSIZE]; bool read_poll; bool write_poll; bool using_vnet_hdr; diff --git a/net/vde.c b/net/vde.c index 4dea32d07a..2a619fbc81 100644 --- a/net/vde.c +++ b/net/vde.c @@ -39,7 +39,7 @@ typedef struct VDEState { static void vde_to_qemu(void *opaque) { VDEState *s = opaque; - uint8_t buf[4096]; + uint8_t buf[NET_BUFSIZE]; int size; size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); -- cgit v1.2.3 From f9e8cacc5557e4372401da74141f833fcacda038 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 27 Mar 2013 10:10:43 +0100 Subject: oslib-posix: rename socket_set_nonblock() to qemu_set_nonblock() The fcntl(fd, F_SETFL, O_NONBLOCK) flag is not specific to sockets. Rename to qemu_set_nonblock() just like qemu_set_cloexec(). Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- net/socket.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index 6c3752b88a..b5c8e659ec 100644 --- a/net/socket.c +++ b/net/socket.c @@ -308,7 +308,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr } } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); return fd; fail: if (fd >= 0) @@ -519,7 +519,7 @@ static int net_socket_listen_init(NetClientState *peer, perror("socket"); return -1; } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); /* allow fast reuse */ val = 1; @@ -565,7 +565,7 @@ static int net_socket_connect_init(NetClientState *peer, perror("socket"); return -1; } - socket_set_nonblock(fd); + qemu_set_nonblock(fd); connected = 0; for(;;) { -- cgit v1.2.3 From fc13fa00eaff6797c67abc9b0f748b346f238986 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 27 Mar 2013 10:10:44 +0100 Subject: net: ensure "socket" backend uses non-blocking fds There are several code paths in net_init_socket() depending on how the socket is created: file descriptor passing, UDP multicast, TCP, or UDP. Some of these support both listen and connect. Not all code paths set the socket to non-blocking. This patch addresses the file descriptor passing and UDP cases which were missing socket_set_nonblock(fd) calls. I considered moving socket_set_nonblock(fd) to a central location but it turns out the code paths are different enough to require non-blocking at different places. Signed-off-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Luiz Capitulino --- net/socket.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/socket.c b/net/socket.c index b5c8e659ec..87af1d3d39 100644 --- a/net/socket.c +++ b/net/socket.c @@ -674,6 +674,7 @@ static int net_socket_udp_init(NetClientState *peer, closesocket(fd); return -1; } + qemu_set_nonblock(fd); s = net_socket_fd_init(peer, model, name, fd, 0); if (!s) { @@ -712,7 +713,11 @@ int net_init_socket(const NetClientOptions *opts, const char *name, int fd; fd = monitor_handle_fd_param(cur_mon, sock->fd); - if (fd == -1 || !net_socket_fd_init(peer, "socket", name, fd, 1)) { + if (fd == -1) { + return -1; + } + qemu_set_nonblock(fd); + if (!net_socket_fd_init(peer, "socket", name, fd, 1)) { return -1; } return 0; -- cgit v1.2.3 From 456d60692310e7ac25cf822cc1e98192ad636ece Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 27 Mar 2013 20:29:40 +0100 Subject: qemu-char: Call fe_claim / fe_release when not using qdev chr properties chardev-frontends need to explictly check, increase and decrement the avail_connections "property" of the chardev when they are not using a qdev-chardev-property for the chardev. This fixes things like: qemu-kvm -chardev stdio,id=foo -device isa-serial,chardev=foo \ -mon chardev=foo Working, where they should fail. Most of the changes here are due to old hardware emulation code which is using serial_hds directly rather then a qdev-chardev-property. Signed-off-by: Hans de Goede Message-id: 1364412581-3672-3-git-send-email-hdegoede@redhat.com Signed-off-by: Anthony Liguori --- net/slirp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/slirp.c b/net/slirp.c index 4df550faf6..eabfee6d4f 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -660,6 +660,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str, fwd->port = port; fwd->slirp = s->slirp; + qemu_chr_fe_claim_no_fail(fwd->hd); qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read, NULL, fwd); } -- cgit v1.2.3 From 0d09e41a51aa0752b1ce525ce084f7cd210e461b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 5 Feb 2013 17:06:20 +0100 Subject: hw: move headers to include/ Many of these should be cleaned up with proper qdev-/QOM-ification. Right now there are many catch-all headers in include/hw/ARCH depending on cpu.h, and this makes it necessary to compile these files per-target. However, fixing this does not belong in these patches. Signed-off-by: Paolo Bonzini --- net/tap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index e7c84811ac..17bdf014a9 100644 --- a/net/tap.c +++ b/net/tap.c @@ -42,7 +42,7 @@ #include "net/tap.h" -#include "hw/vhost_net.h" +#include "net/vhost_net.h" typedef struct TAPState { NetClientState nc; -- cgit v1.2.3 From dccfcd0e5f8f37360ebda11ccc4dab164c04d5a3 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 8 Apr 2013 16:55:25 +0200 Subject: sysemu: avoid proliferation of include/ subdirectories Signed-off-by: Paolo Bonzini --- net/slirp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/slirp.c b/net/slirp.c index eabfee6d4f..b3f35d5861 100644 --- a/net/slirp.c +++ b/net/slirp.c @@ -35,7 +35,7 @@ #include "monitor/monitor.h" #include "qemu/sockets.h" #include "slirp/libslirp.h" -#include "char/char.h" +#include "sysemu/char.h" static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) { -- cgit v1.2.3 From c963530a5b3e3e0f7304841adfe84416d82f59f6 Mon Sep 17 00:00:00 2001 From: Amos Kong Date: Mon, 15 Apr 2013 18:55:19 +0800 Subject: net: make network client name unique assign_name() creates a name MODEL.NUM, where MODEL is the client's model, and NUM is the number of MODELs that already exist. Markus added NIC naming for non-VLAN clients in commit 53e51d85. commit d33d93b2 incorrectly added a judgement of net-hub. It caused net clients created with -netdev get same names. eg: # qemu-upstream -device virtio-net-pci,netdev=h1 -netdev tap,id=h1 \ -device virtio-net-pci,netdev=h2 -netdev tap,id=h2 .. (qemu) info network virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56 \ h1: index=0,type=tap,ifname=tap0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:57 \ h2: index=0,type=tap,ifname=tap1,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown This patch removed the check of nic-hub, and created unique names for all net clients that have same model. v2: update commitlog & comments Signed-off-by: Amos Kong Signed-off-by: Stefan Hajnoczi --- net/net.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/net.c b/net/net.c index 7869161d8d..43a74e43ae 100644 --- a/net/net.c +++ b/net/net.c @@ -157,8 +157,7 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr) /** * Generate a name for net client * - * Only net clients created with the legacy -net option need this. Naming is - * mandatory for net clients created with -netdev. + * Only net clients created with the legacy -net option and NICs need this. */ static char *assign_name(NetClientState *nc1, const char *model) { @@ -170,9 +169,7 @@ static char *assign_name(NetClientState *nc1, const char *model) if (nc == nc1) { continue; } - /* For compatibility only bump id for net clients on a vlan */ - if (strcmp(nc->model, model) == 0 && - net_hub_id_for_client(nc, NULL) == 0) { + if (strcmp(nc->model, model) == 0) { id++; } } -- cgit v1.2.3 From 7873df408dd44eb92840b108211d5aa5db7db526 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Fri, 19 Apr 2013 15:11:15 +0800 Subject: tap: properly initialize vhostfds Only tap->vhostfd were checked net_init_tap_one(), but tap->vhostfds were forgot, this will lead qemu to ignore all fds passed by management through vhostfds, and tries to create vhost_net device itself. Fix by adding this check also. Reportyed-by: Michal Privoznik Cc: Michal Privoznik Cc: qemu-stable@nongnu.org Signed-off-by: Jason Wang Reviewed-by: Michal Privoznik Signed-off-by: Stefan Hajnoczi --- net/tap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index 17bdf014a9..e0b7a2a5a0 100644 --- a/net/tap.c +++ b/net/tap.c @@ -623,7 +623,7 @@ static int net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, vhostfdname || (tap->has_vhostforce && tap->vhostforce)) { int vhostfd; - if (tap->has_vhostfd) { + if (tap->has_vhostfd || tap->has_vhostfds) { vhostfd = monitor_handle_fd_param(cur_mon, vhostfdname); if (vhostfd == -1) { return -1; -- cgit v1.2.3 From 5a893b0d37795f1f1d89caa2e36d9ff311cd2dc9 Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Tue, 4 Jun 2013 13:18:17 +0800 Subject: tap: fix NULL dereference when passing invalid parameters to tap This patch forbid the following invalid parameters to tap: 1) fd and vhostfds were specified but vhostfd were not specified 2) vhostfds were specified but fds were not specified 3) fds and vhostfd were specified For 1 and 2, net_init_tap_one() will still pass NULL as vhostfdname to monitor_handle_fd_param(), which may crash the qemu. Also remove the unnecessary has_fd check. Cc: Paolo Bonzini Cc: Stefan Hajnoczi Cc: Laszlo Ersek Cc: qemu-stable@nongnu.org Signed-off-by: Jason Wang Signed-off-by: Stefan Hajnoczi (cherry picked from commit c87826a878be05208c3906eb9d5e1f37cff5e98e) Signed-off-by: Michael Roth --- net/tap.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/tap.c b/net/tap.c index e0b7a2a5a0..39c1cda3e4 100644 --- a/net/tap.c +++ b/net/tap.c @@ -698,9 +698,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name, if (tap->has_fd) { if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || - tap->has_fds) { + tap->has_fds || tap->has_vhostfds) { error_report("ifname=, script=, downscript=, vnet_hdr=, " - "helper=, queues=, and fds= are invalid with fd="); + "helper=, queues=, fds=, and vhostfds= " + "are invalid with fd="); return -1; } @@ -725,9 +726,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name, if (tap->has_ifname || tap->has_script || tap->has_downscript || tap->has_vnet_hdr || tap->has_helper || tap->has_queues || - tap->has_fd) { + tap->has_vhostfd) { error_report("ifname=, script=, downscript=, vnet_hdr=, " - "helper=, queues=, and fd= are invalid with fds="); + "helper=, queues=, and vhostfd= " + "are invalid with fds="); return -1; } @@ -765,9 +767,9 @@ int net_init_tap(const NetClientOptions *opts, const char *name, } } else if (tap->has_helper) { if (tap->has_ifname || tap->has_script || tap->has_downscript || - tap->has_vnet_hdr || tap->has_queues || tap->has_fds) { + tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) { error_report("ifname=, script=, downscript=, and vnet_hdr= " - "queues=, and fds= are invalid with helper="); + "queues=, and vhostfds= are invalid with helper="); return -1; } @@ -785,6 +787,10 @@ int net_init_tap(const NetClientOptions *opts, const char *name, return -1; } } else { + if (tap->has_vhostfds) { + error_report("vhostfds= is invalid if fds= wasn't specified"); + return -1; + } script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT; downscript = tap->has_downscript ? tap->downscript : DEFAULT_NETWORK_DOWN_SCRIPT; -- cgit v1.2.3