From patchwork Wed Jun 6 13:26:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhiyong Wu X-Patchwork-Id: 163376 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 3048EB6FA1 for ; Wed, 6 Jun 2012 23:28:59 +1000 (EST) Received: from localhost ([::1]:35477 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ScGID-0004Nq-0L for incoming@patchwork.ozlabs.org; Wed, 06 Jun 2012 09:28:57 -0400 Received: from eggs.gnu.org ([208.118.235.92]:53066) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ScGHy-0004MI-Kh for qemu-devel@nongnu.org; Wed, 06 Jun 2012 09:28:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ScGHp-0006Is-BY for qemu-devel@nongnu.org; Wed, 06 Jun 2012 09:28:42 -0400 Received: from e32.co.us.ibm.com ([32.97.110.150]:54361) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ScGHo-0006IM-WF for qemu-devel@nongnu.org; Wed, 06 Jun 2012 09:28:33 -0400 Received: from /spool/local by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 6 Jun 2012 07:28:26 -0600 Received: from d03dlp01.boulder.ibm.com (9.17.202.177) by e32.co.us.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 6 Jun 2012 07:26:37 -0600 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id 894391FF0025 for ; Wed, 6 Jun 2012 13:26:35 +0000 (WET) Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q56DQUFS096594 for ; Wed, 6 Jun 2012 07:26:32 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q56DQUk7011167 for ; Wed, 6 Jun 2012 07:26:30 -0600 Received: from us.ibm.com (f15.cn.ibm.com [9.115.118.120] (may be forged)) by d03av02.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q56DQRIr010803; Wed, 6 Jun 2012 07:26:28 -0600 Received: by us.ibm.com (sSMTP sendmail emulation); Wed, 6 Jun 2012 21:26:24 +0800 From: zwu.kernel@gmail.com To: qemu-devel@nongnu.org Date: Wed, 6 Jun 2012 21:26:23 +0800 Message-Id: <1338989183-28869-1-git-send-email-zwu.kernel@gmail.com> X-Mailer: git-send-email 1.7.6 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12060613-3270-0000-0000-000006F2618C X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.97.110.150 Cc: Zhi Yong Wu , stefanha@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH v4] net: add the support for -netdev socket, listen X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Zhi Yong Wu The -net socket,listen option does not work with the newer -netdev syntax: http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg01508.html This patch makes it work now. For the case where one vlan has multiple listenning sockets, the patch will also provide the support. Supported syntax: 1.) -net socket,listen=127.0.0.1:1234,vlan=0 2.) -net socket,listen=127.0.0.1:1234,vlan=0 -net socket,listen=127.0.0.1:1235,vlan=0 3.) -netdev socket,listen=127.0.0.1:1234,id=socket0 Suggested-by: Stefan Hajnoczi Signed-off-by: Zhi Yong Wu --- net.c | 24 +++++++++++ net.h | 3 + net/socket.c | 123 ++++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 117 insertions(+), 33 deletions(-) diff --git a/net.c b/net.c index 1922d8a..0114537 100644 --- a/net.c +++ b/net.c @@ -190,6 +190,30 @@ static ssize_t qemu_deliver_packet_iov(VLANClientState *sender, int iovcnt, void *opaque); +VLANClientState *qemu_lookup_net_client(VLANState *vlan, + const char *name) +{ + VLANClientState *vc = NULL; + + if (vlan) { + QTAILQ_FOREACH(vc, &vlan->clients, next) { + if ((vc->info->type == NET_CLIENT_TYPE_SOCKET) + && (!vc->consumed)) { + return vc; + } + } + } else { + QTAILQ_FOREACH(vc, &non_vlan_clients, next) { + if (!strcmp(vc->name, name) + && (!vc->consumed)) { + return vc; + } + } + } + + return NULL; +} + VLANClientState *qemu_new_net_client(NetClientInfo *info, VLANState *vlan, VLANClientState *peer, diff --git a/net.h b/net.h index 64993b4..6033f43 100644 --- a/net.h +++ b/net.h @@ -72,6 +72,7 @@ struct VLANClientState { char *name; char info_str[256]; unsigned receive_disabled : 1; + bool consumed; }; typedef struct NICState { @@ -90,6 +91,8 @@ struct VLANState { VLANState *qemu_find_vlan(int id, int allocate); VLANClientState *qemu_find_netdev(const char *id); +VLANClientState *qemu_lookup_net_client(VLANState *vlan, + const char *name); VLANClientState *qemu_new_net_client(NetClientInfo *info, VLANState *vlan, VLANClientState *peer, diff --git a/net/socket.c b/net/socket.c index 0bcf229..2ddca64 100644 --- a/net/socket.c +++ b/net/socket.c @@ -32,8 +32,21 @@ #include "qemu-option.h" #include "qemu_socket.h" +#define NET_SOCKET_CONNECT 0x0001 +#define NET_SOCKET_LISTEN 0x0002 +#define NET_SOCKET_CREATE 0x0004 + +typedef struct NetSocketListenState { + VLANState *vlan; + char *model; + char *name; + int fd; + bool consumed; +} NetSocketListenState; + typedef struct NetSocketState { VLANClientState nc; + NetSocketListenState *nls; int fd; int state; /* 0 = getting length, 1 = getting data */ unsigned int index; @@ -42,13 +55,6 @@ typedef struct NetSocketState { struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ } NetSocketState; -typedef struct NetSocketListenState { - VLANState *vlan; - char *model; - char *name; - int fd; -} NetSocketListenState; - /* XXX: we consider we can send the whole packet without blocking */ static ssize_t net_socket_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { @@ -86,6 +92,17 @@ static void net_socket_send(void *opaque) eoc: qemu_set_fd_handler(s->fd, NULL, NULL, NULL); closesocket(s->fd); + s->fd = 0; + s->state = 0; + s->index = 0; + s->packet_len = 0; + memset(s->buf, 0, sizeof(s->buf)); + if (s->nls) { + s->nls->consumed = false; + s->nc.consumed = false; + memset(s->nc.info_str, 0, sizeof(s->nc.info_str)); + } + return; } buf = buf1; @@ -247,7 +264,7 @@ static NetClientInfo net_dgram_socket_info = { static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, const char *model, const char *name, - int fd, int is_connected) + int fd, int flag) { struct sockaddr_in saddr; int newfd; @@ -260,7 +277,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, * by ONLY ONE process: we must "clone" this dgram socket --jjo */ - if (is_connected) { + if (flag & NET_SOCKET_CONNECT) { if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) { /* must be bound */ if (saddr.sin_addr.s_addr == 0) { @@ -290,7 +307,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d (%s mcast=%s:%d)", - fd, is_connected ? "cloned" : "", + fd, flag & NET_SOCKET_CONNECT ? "cloned" : "", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); s = DO_UPCAST(NetSocketState, nc, nc); @@ -300,7 +317,9 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); /* mcast: save bound address as dst */ - if (is_connected) s->dgram_dst=saddr; + if (flag & NET_SOCKET_CONNECT) { + s->dgram_dst = saddr; + } return s; @@ -325,20 +344,31 @@ static NetClientInfo net_socket_info = { static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, const char *model, const char *name, - int fd, int is_connected) + int fd, int flag) { VLANClientState *nc; NetSocketState *s; - nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name); - - snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); + if (flag & NET_SOCKET_CREATE) { + nc = qemu_new_net_client(&net_socket_info, vlan, NULL, model, name); + } else { + nc = qemu_lookup_net_client(vlan, name); + if (!nc) { + return NULL; + } + } s = DO_UPCAST(NetSocketState, nc, nc); + if (flag & NET_SOCKET_LISTEN) { + return s; + } + + snprintf(nc->info_str, sizeof(nc->info_str), "socket: fd=%d", fd); + s->fd = fd; - if (is_connected) { + if (flag & NET_SOCKET_CONNECT) { net_socket_connect(s); } else { qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); @@ -348,7 +378,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, static NetSocketState *net_socket_fd_init(VLANState *vlan, const char *model, const char *name, - int fd, int is_connected) + int fd, int flag) { int so_type = -1, optlen=sizeof(so_type); @@ -361,13 +391,13 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, } switch(so_type) { case SOCK_DGRAM: - return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected); + return net_socket_fd_init_dgram(vlan, model, name, fd, flag); case SOCK_STREAM: - return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); + return net_socket_fd_init_stream(vlan, model, name, fd, flag); default: /* who knows ... this could be a eg. a pty, do warn and continue as stream */ fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd); - return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); + return net_socket_fd_init_stream(vlan, model, name, fd, flag); } return NULL; } @@ -378,9 +408,13 @@ static void net_socket_accept(void *opaque) NetSocketState *s1; struct sockaddr_in saddr; socklen_t len; - int fd; + int fd, flag = 0; for(;;) { + if (s->consumed) { + return; + } + len = sizeof(saddr); fd = qemu_accept(s->fd, (struct sockaddr *)&saddr, &len); if (fd < 0 && errno != EINTR) { @@ -389,8 +423,14 @@ static void net_socket_accept(void *opaque) break; } } - s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1); + + flag |= NET_SOCKET_CONNECT; + flag &= ~NET_SOCKET_LISTEN & ~NET_SOCKET_CREATE; + s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, flag); if (s1) { + s->consumed = true; + s1->nc.link_down = false; + s1->nc.consumed = true; snprintf(s1->nc.info_str, sizeof(s1->nc.info_str), "socket: connection from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); @@ -403,8 +443,9 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str) { NetSocketListenState *s; - int fd, val, ret; + int fd, val, ret, flag = 0; struct sockaddr_in saddr; + NetSocketState *ns; if (parse_host_port(&saddr, host_str) < 0) return -1; @@ -441,6 +482,13 @@ static int net_socket_listen_init(VLANState *vlan, s->model = g_strdup(model); s->name = name ? g_strdup(name) : NULL; s->fd = fd; + + flag &= ~NET_SOCKET_CONNECT; + flag |= NET_SOCKET_LISTEN | NET_SOCKET_CREATE; + ns = net_socket_fd_init(s->vlan, s->model, s->name, fd, flag); + ns->nls = s; + ns->nc.link_down = true; + qemu_set_fd_handler(fd, net_socket_accept, NULL, s); return 0; } @@ -451,7 +499,7 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str) { NetSocketState *s; - int fd, connected, ret, err; + int fd, ret, err, flag = 0; struct sockaddr_in saddr; if (parse_host_port(&saddr, host_str) < 0) @@ -464,7 +512,7 @@ static int net_socket_connect_init(VLANState *vlan, } socket_set_nonblock(fd); - connected = 0; + flag &= ~NET_SOCKET_CONNECT; for(;;) { ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { @@ -482,11 +530,14 @@ static int net_socket_connect_init(VLANState *vlan, return -1; } } else { - connected = 1; + flag |= NET_SOCKET_CONNECT; break; } } - s = net_socket_fd_init(vlan, model, name, fd, connected); + + flag |= NET_SOCKET_CREATE; + flag &= ~NET_SOCKET_LISTEN; + s = net_socket_fd_init(vlan, model, name, fd, flag); if (!s) return -1; snprintf(s->nc.info_str, sizeof(s->nc.info_str), @@ -502,7 +553,7 @@ static int net_socket_mcast_init(VLANState *vlan, const char *localaddr_str) { NetSocketState *s; - int fd; + int fd, flag = 0; struct sockaddr_in saddr; struct in_addr localaddr, *param_localaddr; @@ -521,7 +572,9 @@ static int net_socket_mcast_init(VLANState *vlan, if (fd < 0) return -1; - s = net_socket_fd_init(vlan, model, name, fd, 0); + flag |= NET_SOCKET_CREATE; + flag &= ~NET_SOCKET_CONNECT & ~NET_SOCKET_LISTEN; + s = net_socket_fd_init(vlan, model, name, fd, flag); if (!s) return -1; @@ -541,7 +594,7 @@ static int net_socket_udp_init(VLANState *vlan, const char *lhost) { NetSocketState *s; - int fd, val, ret; + int fd, val, ret, flag = 0; struct sockaddr_in laddr, raddr; if (parse_host_port(&laddr, lhost) < 0) { @@ -572,7 +625,9 @@ static int net_socket_udp_init(VLANState *vlan, return -1; } - s = net_socket_fd_init(vlan, model, name, fd, 0); + flag |= NET_SOCKET_CREATE; + flag &= ~NET_SOCKET_CONNECT & ~NET_SOCKET_LISTEN; + s = net_socket_fd_init(vlan, model, name, fd, flag); if (!s) { return -1; } @@ -591,7 +646,7 @@ int net_init_socket(QemuOpts *opts, VLANState *vlan) { if (qemu_opt_get(opts, "fd")) { - int fd; + int fd, flag = 0; if (qemu_opt_get(opts, "listen") || qemu_opt_get(opts, "connect") || @@ -606,7 +661,9 @@ int net_init_socket(QemuOpts *opts, return -1; } - if (!net_socket_fd_init(vlan, "socket", name, fd, 1)) { + flag |= NET_SOCKET_CREATE | NET_SOCKET_CONNECT; + flag &= ~NET_SOCKET_LISTEN; + if (!net_socket_fd_init(vlan, "socket", name, fd, flag)) { return -1; } } else if (qemu_opt_get(opts, "listen")) {