From patchwork Wed May 23 15:13:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhiyong Wu X-Patchwork-Id: 160939 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 87238B6FC2 for ; Thu, 24 May 2012 01:26:02 +1000 (EST) Received: from localhost ([::1]:42682 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXDRo-00086h-Ce for incoming@patchwork.ozlabs.org; Wed, 23 May 2012 11:26:00 -0400 Received: from eggs.gnu.org ([208.118.235.92]:59183) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXDRg-00086P-5J for qemu-devel@nongnu.org; Wed, 23 May 2012 11:25:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SXDRa-0007En-4q for qemu-devel@nongnu.org; Wed, 23 May 2012 11:25:51 -0400 Received: from e9.ny.us.ibm.com ([32.97.182.139]:59078) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SXDRZ-0007EF-Qb for qemu-devel@nongnu.org; Wed, 23 May 2012 11:25:45 -0400 Received: from /spool/local by e9.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 23 May 2012 11:25:41 -0400 Received: from d01dlp02.pok.ibm.com (9.56.224.85) by e9.ny.us.ibm.com (192.168.1.109) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 23 May 2012 11:25:39 -0400 Received: from d01relay07.pok.ibm.com (d01relay07.pok.ibm.com [9.56.227.147]) by d01dlp02.pok.ibm.com (Postfix) with ESMTP id E5DA06E86EF for ; Wed, 23 May 2012 11:15:32 -0400 (EDT) Received: from d01av02.pok.ibm.com (d01av02.pok.ibm.com [9.56.224.216]) by d01relay07.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q4NFFFxO22151262 for ; Wed, 23 May 2012 11:15:15 -0400 Received: from d01av02.pok.ibm.com (loopback [127.0.0.1]) by d01av02.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q4NFEPmN024926 for ; Wed, 23 May 2012 12:14:25 -0300 Received: from us.ibm.com (f15.cn.ibm.com [9.115.118.120] (may be forged)) by d01av02.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q4NFEKNp024422; Wed, 23 May 2012 12:14:21 -0300 Received: by us.ibm.com (sSMTP sendmail emulation); Wed, 23 May 2012 23:14:12 +0800 From: zwu.kernel@gmail.com To: qemu-devel@nongnu.org Date: Wed, 23 May 2012 23:13:51 +0800 Message-Id: <1337786045-2277-2-git-send-email-zwu.kernel@gmail.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1337786045-2277-1-git-send-email-zwu.kernel@gmail.com> References: <1337786045-2277-1-git-send-email-zwu.kernel@gmail.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12052315-7182-0000-0000-0000019571BC X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.97.182.139 Cc: pbonzini@redhat.com, wuzhy@linux.vnet.ibm.com, linuxram@us.ibm.com, stefanha@linux.vnet.ibm.com, kvm@vger.kernel.org Subject: [Qemu-devel] [PATCH v2 01/15] net: Add a hub net client 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: Stefan Hajnoczi The vlan feature can be implemented in terms of hubs. By introducing a hub net client it becomes possible to remove the special case vlan code from net.c and push the vlan feature out of generic networking code. Signed-off-by: Stefan Hajnoczi Signed-off-by: Zhi Yong Wu --- Makefile.objs | 2 +- net.h | 1 + net/hub.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ net/hub.h | 23 +++++++ 4 files changed, 225 insertions(+), 1 deletions(-) create mode 100644 net/hub.c create mode 100644 net/hub.h diff --git a/Makefile.objs b/Makefile.objs index 70c5c79..a3a3a8a 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -63,7 +63,7 @@ block-nested-$(CONFIG_RBD) += rbd.o block-obj-y += $(addprefix block/, $(block-nested-y)) net-obj-y = net.o -net-nested-y = queue.o checksum.o util.o +net-nested-y = queue.o checksum.o util.o hub.o net-nested-y += socket.o net-nested-y += dump.o net-nested-$(CONFIG_POSIX) += tap.o diff --git a/net.h b/net.h index 64993b4..50c55ad 100644 --- a/net.h +++ b/net.h @@ -38,6 +38,7 @@ typedef enum { NET_CLIENT_TYPE_VDE, NET_CLIENT_TYPE_DUMP, NET_CLIENT_TYPE_BRIDGE, + NET_CLIENT_TYPE_HUB, NET_CLIENT_TYPE_MAX } net_client_type; diff --git a/net/hub.c b/net/hub.c new file mode 100644 index 0000000..0d3df7f --- /dev/null +++ b/net/hub.c @@ -0,0 +1,200 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "monitor.h" +#include "net.h" +#include "hub.h" + +/* + * A hub broadcasts incoming packets to all its ports except the source port. + * Hubs can be used to provide independent network segments, also confusingly + * named the QEMU 'vlan' feature. + */ + +typedef struct NetHub NetHub; + +typedef struct NetHubPort { + VLANClientState nc; + QLIST_ENTRY(NetHubPort) next; + NetHub *hub; + unsigned int id; +} NetHubPort; + +struct NetHub { + unsigned int id; + QLIST_ENTRY(NetHub) next; + unsigned int num_ports; + QLIST_HEAD(, NetHubPort) ports; +}; + +static QLIST_HEAD(, NetHub) hubs = QLIST_HEAD_INITIALIZER(&hubs); + +static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port, + const uint8_t *buf, size_t len) +{ + NetHubPort *port; + + QLIST_FOREACH(port, &hub->ports, next) { + if (port == source_port) { + continue; + } + + qemu_send_packet(&port->nc, buf, len); + } + return len; +} + +static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port, + const struct iovec *iov, int iovcnt) +{ + NetHubPort *port; + ssize_t ret = 0; + + QLIST_FOREACH(port, &hub->ports, next) { + if (port == source_port) { + continue; + } + + ret = qemu_sendv_packet(&port->nc, iov, iovcnt); + } + return ret; +} + +static NetHub *net_hub_new(unsigned int id) +{ + NetHub *hub; + + hub = g_malloc(sizeof(*hub)); + hub->id = id; + hub->num_ports = 0; + QLIST_INIT(&hub->ports); + + QLIST_INSERT_HEAD(&hubs, hub, next); + + return hub; +} + +static ssize_t net_hub_port_receive(VLANClientState *nc, + const uint8_t *buf, size_t len) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + return net_hub_receive(port->hub, port, buf, len); +} + +static ssize_t net_hub_port_receive_iov(VLANClientState *nc, + const struct iovec *iov, int iovcnt) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + return net_hub_receive_iov(port->hub, port, iov, iovcnt); +} + +static void net_hub_port_cleanup(VLANClientState *nc) +{ + NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc); + + QLIST_REMOVE(port, next); +} + +static NetClientInfo net_hub_port_info = { + .type = NET_CLIENT_TYPE_HUB, + .size = sizeof(NetHubPort), + .receive = net_hub_port_receive, + .receive_iov = net_hub_port_receive_iov, + .cleanup = net_hub_port_cleanup, +}; + +static NetHubPort *net_hub_port_new(NetHub *hub) +{ + VLANClientState *nc; + NetHubPort *port; + unsigned int id = hub->num_ports++; + char name[128]; + + snprintf(name, sizeof name, "hub%uport%u", hub->id, id); + + nc = qemu_new_net_client(&net_hub_port_info, NULL, NULL, "hub", name); + port = DO_UPCAST(NetHubPort, nc, nc); + port->id = id; + port->hub = hub; + + QLIST_INSERT_HEAD(&hub->ports, port, next); + + return port; +} + +/** + * Create a port on a given hub + * + * If there is no existing hub with the given id then a new hub is created. + */ +VLANClientState *net_hub_add_port(unsigned int hub_id) +{ + NetHub *hub; + NetHubPort *port; + + QLIST_FOREACH(hub, &hubs, next) { + if (hub->id == hub_id) { + break; + } + } + + if (!hub) { + hub = net_hub_new(hub_id); + } + + port = net_hub_port_new(hub); + return &port->nc; +} + +/** + * Print hub configuration + */ +void net_hub_info(Monitor *mon) +{ + NetHub *hub; + NetHubPort *port; + + QLIST_FOREACH(hub, &hubs, next) { + monitor_printf(mon, "hub %u\n", hub->id); + QLIST_FOREACH(port, &hub->ports, next) { + monitor_printf(mon, " port %u peer %s\n", port->id, + port->nc.peer ? port->nc.peer->name : ""); + } + } +} + +/** + * Get the hub id that a client is connected to + * + * @id Pointer for hub id output, may be NULL + */ +int net_hub_id_for_client(VLANClientState *nc, unsigned int *id) +{ + NetHub *hub; + NetHubPort *port; + + QLIST_FOREACH(hub, &hubs, next) { + QLIST_FOREACH(port, &hub->ports, next) { + if (&port->nc == nc || + (port->nc.peer && port->nc.peer == nc)) { + if (id) { + *id = hub->id; + } + return 0; + } + } + } + return -ENOENT; +} diff --git a/net/hub.h b/net/hub.h new file mode 100644 index 0000000..3ca05dc --- /dev/null +++ b/net/hub.h @@ -0,0 +1,23 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Stefan Hajnoczi + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#ifndef NET_HUB_H +#define NET_HUB_H + +#include "qemu-common.h" + +VLANClientState *net_hub_add_port(unsigned int hub_id); +void net_hub_info(Monitor *mon); +int net_hub_id_for_client(VLANClientState *nc, unsigned int *id); + +#endif /* NET_HUB_H */