From patchwork Wed Jun 20 09:42:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhiyong Wu X-Patchwork-Id: 165981 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 9593FB6FA8 for ; Wed, 20 Jun 2012 20:20:30 +1000 (EST) Received: from localhost ([::1]:41544 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ShHSw-0003lr-Ko for incoming@patchwork.ozlabs.org; Wed, 20 Jun 2012 05:44:46 -0400 Received: from eggs.gnu.org ([208.118.235.92]:59565) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ShHSY-0003Ad-Rt for qemu-devel@nongnu.org; Wed, 20 Jun 2012 05:44:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ShHSR-0002hT-4C for qemu-devel@nongnu.org; Wed, 20 Jun 2012 05:44:22 -0400 Received: from e33.co.us.ibm.com ([32.97.110.151]:36607) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ShHSQ-0002gW-LA for qemu-devel@nongnu.org; Wed, 20 Jun 2012 05:44:15 -0400 Received: from /spool/local by e33.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 20 Jun 2012 03:44:11 -0600 Received: from d03dlp01.boulder.ibm.com (9.17.202.177) by e33.co.us.ibm.com (192.168.1.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 20 Jun 2012 03:43:43 -0600 Received: from d03relay04.boulder.ibm.com (d03relay04.boulder.ibm.com [9.17.195.106]) by d03dlp01.boulder.ibm.com (Postfix) with ESMTP id B18491FF001A for ; Wed, 20 Jun 2012 09:43:16 +0000 (WET) Received: from d03av01.boulder.ibm.com (d03av01.boulder.ibm.com [9.17.195.167]) by d03relay04.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q5K9glOE194382 for ; Wed, 20 Jun 2012 03:42:59 -0600 Received: from d03av01.boulder.ibm.com (loopback [127.0.0.1]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q5K9gVfS018137 for ; Wed, 20 Jun 2012 03:42:32 -0600 Received: from us.ibm.com (f15.cn.ibm.com [9.115.118.27]) by d03av01.boulder.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with SMTP id q5K9gRke017965; Wed, 20 Jun 2012 03:42:28 -0600 Received: by us.ibm.com (sSMTP sendmail emulation); Wed, 20 Jun 2012 17:42:26 +0800 From: zwu.kernel@gmail.com To: qemu-devel@nongnu.org Date: Wed, 20 Jun 2012 17:42:05 +0800 Message-Id: <1340185341-30803-2-git-send-email-zwu.kernel@gmail.com> X-Mailer: git-send-email 1.7.6 In-Reply-To: <1340185341-30803-1-git-send-email-zwu.kernel@gmail.com> References: <1340185341-30803-1-git-send-email-zwu.kernel@gmail.com> X-Content-Scanned: Fidelis XPS MAILER x-cbid: 12062009-2398-0000-0000-000007B0C4FD X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 32.97.110.151 Cc: pbonzini@redhat.com, aliguori@us.ibm.com, Zhi Yong Wu , stefanha@linux.vnet.ibm.com, jan.kiszka@siemens.com Subject: [Qemu-devel] [PATCH v6 01/17] 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 --- net.h | 1 + net/Makefile.objs | 2 +- net/hub.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++ net/hub.h | 24 ++++++ 4 files changed, 227 insertions(+), 1 deletions(-) create mode 100644 net/hub.c create mode 100644 net/hub.h diff --git a/net.h b/net.h index bdc2a06..c1198b6 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/Makefile.objs b/net/Makefile.objs index 72f50bc..cf04187 100644 --- a/net/Makefile.objs +++ b/net/Makefile.objs @@ -1,4 +1,4 @@ -common-obj-y = queue.o checksum.o util.o +common-obj-y = 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/hub.c b/net/hub.c new file mode 100644 index 0000000..28ff45c --- /dev/null +++ b/net/hub.c @@ -0,0 +1,201 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Stefan Hajnoczi + * Zhi Yong Wu + * + * 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..bf8798b --- /dev/null +++ b/net/hub.h @@ -0,0 +1,24 @@ +/* + * Hub net client + * + * Copyright IBM, Corp. 2012 + * + * Authors: + * Stefan Hajnoczi + * Zhi Yong Wu + * + * 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 */