qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/16] Add a -netdev option
@ 2009-10-08 18:58 Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 01/16] slirp: fix !CONFIG_SLIRP compilation Mark McLoughlin
                   ` (18 more replies)
  0 siblings, 19 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel

Hi,
        Here's a series of patches which gets the ball rolling on adding
a -netdev option.

        The idea is to de-emphasise the vlan support, and instead make
a nic directly connected to a host backend the default and recommended
configuration. We want this because it is only with this configuration
that we feasibly add optimizations like GSO support or vhost-net.

        Where we're going is that rather '-net user -net nic' being the
default, it would instead be:

  -netdev user,id=default_slirp -device e1000,netdev=default_slirp

        This patch series has a lot of this done, but there's still a
significant TODO list including:

  * qdev-ify the NICs so that we can use -device rather than '-net nic'
    which Gerd has started looking at

  * add hotplug equivalent to netdev - we should probably add a 'nic='
    argument to -netdev for this to allow changing the backend without
    changing the frontend

  * 'info network' should list netdevs

  * merging in GSO support from qemu-kvm.git, substantially cleaned up

  * VLAN support should be implemented as just another network client,
    but one which is connected to multiple backends and frontends

  * re-naming e.g. VLANClientState to NetClient

  * killing off NICInfo

  * ...

        I've given this series significant testing including building
with all targets (really!), mingw, --disable-slirp, --enable-vde,
without TUNSETSNDBUF and running with various nic models, backends,
with both -net and -netdev, some different guests, hotplug, ... No
doubt I've still managed to screw something up.

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 01/16] slirp: fix !CONFIG_SLIRP compilation
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device Mark McLoughlin
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin, Juan Quintela

From: Juan Quintela <quintela@redhat.com>

This moves the code that depens on slirp under CONFIG_SLIRP again.

Signed-off-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index 2e4dd58..e93017d 100644
--- a/net.c
+++ b/net.c
@@ -2451,6 +2451,7 @@ static int net_init_nic(QemuOpts *opts, Monitor *mon)
     return idx;
 }
 
+#if defined(CONFIG_SLIRP)
 static int net_init_slirp_configs(const char *name, const char *value, void *opaque)
 {
     struct slirp_config_str *config;
@@ -2546,6 +2547,7 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon)
 
     return ret;
 }
+#endif /* CONFIG_SLIRP */
 
 #ifdef _WIN32
 static int net_init_tap_win32(QemuOpts *opts, Monitor *mon)
@@ -3227,6 +3229,7 @@ int net_init_clients(void)
 
 int net_client_parse(const char *optarg)
 {
+#if defined(CONFIG_SLIRP)
     /* handle legacy -net channel,port:chr */
     if (!strncmp(optarg, "channel,", strlen("channel,"))) {
         int ret;
@@ -3248,7 +3251,7 @@ int net_client_parse(const char *optarg)
 
         return ret;
     }
-
+#endif
     if (!qemu_opts_parse(&qemu_net_opts, optarg, "type")) {
         return -1;
     }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 01/16] slirp: fix !CONFIG_SLIRP compilation Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-12 13:16   ` [Qemu-devel] " Gerd Hoffmann
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 03/16] net: pass monitor handle to client init functions Mark McLoughlin
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin, Gerd Hoffmann

Without this, I'm seeing a segfault when unpluging a NIC.

Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 hw/acpi.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/acpi.c b/hw/acpi.c
index 4373133..d73aee9 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -695,11 +695,11 @@ static uint32_t pciej_read(void *opaque, uint32_t addr)
 static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
 {
     BusState *bus = opaque;
-    DeviceState *qdev;
+    DeviceState *qdev, *next;
     PCIDevice *dev;
     int slot = ffs(val) - 1;
 
-    QLIST_FOREACH(qdev, &bus->children, sibling) {
+    QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
         dev = DO_UPCAST(PCIDevice, qdev, qdev);
         if (PCI_SLOT(dev->devfn) == slot) {
 #if defined (TARGET_I386)
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 03/16] net: pass monitor handle to client init functions
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 01/16] slirp: fix !CONFIG_SLIRP compilation Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 04/16] net: remove unused qemu_handler_true() Mark McLoughlin
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Needed for e.g. looking up a file descriptor name using
monitor_get_fd() in net_init_tap()

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index e93017d..898b9af 100644
--- a/net.c
+++ b/net.c
@@ -3021,7 +3021,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
             }
 
             if (net_client_types[i].init) {
-                return net_client_types[i].init(opts, NULL);
+                return net_client_types[i].init(opts, mon);
             } else {
                 return 0;
             }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 04/16] net: remove unused qemu_handler_true()
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (2 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 03/16] net: pass monitor handle to client init functions Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 05/16] net: handle id= parameter for -net Mark McLoughlin
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.h |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/net.h b/net.h
index 2b0ed9b..49e160d 100644
--- a/net.h
+++ b/net.h
@@ -80,7 +80,6 @@ int qemu_show_nic_models(const char *arg, const char *const *models);
 void qemu_check_nic_model(NICInfo *nd, const char *model);
 int qemu_find_nic_model(NICInfo *nd, const char * const *models,
                         const char *default_model);
-void qemu_handler_true(void *opaque);
 
 void do_info_network(Monitor *mon);
 void do_set_link(Monitor *mon, const QDict *qdict);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 05/16] net: handle id= parameter for -net
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (3 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 04/16] net: remove unused qemu_handler_true() Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 06/16] net: remove id field from NICInfo Mark McLoughlin
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Use id= in the same was as the current name= parameter; if both are
specified, id= is used.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   48 ++++++++++++++++++++----------------------------
 1 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/net.c b/net.c
index 898b9af..8895e87 100644
--- a/net.c
+++ b/net.c
@@ -2394,7 +2394,7 @@ static int net_handle_fd_param(Monitor *mon, const char *param)
     }
 }
 
-static int net_init_nic(QemuOpts *opts, Monitor *mon)
+static int net_init_nic(QemuOpts *opts, Monitor *mon, const char *name)
 {
     int idx;
     NICInfo *nd;
@@ -2411,12 +2411,12 @@ static int net_init_nic(QemuOpts *opts, Monitor *mon)
 
     nd->vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
+    if (name) {
+        nd->name = qemu_strdup(name);
+    }
     if (qemu_opts_id(opts)) {
         nd->id = qemu_strdup(qemu_opts_id(opts));
     }
-    if (qemu_opt_get(opts, "name")) {
-        nd->name = qemu_strdup(qemu_opt_get(opts, "name"));
-    }
     if (qemu_opt_get(opts, "model")) {
         nd->model = qemu_strdup(qemu_opt_get(opts, "model"));
     }
@@ -2474,11 +2474,10 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa
     return 0;
 }
 
-static int net_init_slirp(QemuOpts *opts, Monitor *mon)
+static int net_init_slirp(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
     struct slirp_config_str *config;
-    const char *name;
     const char *vhost;
     const char *vhostname;
     const char *vdhcp_start;
@@ -2493,8 +2492,6 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon)
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name = qemu_opt_get(opts, "name");
-
     vhost       = qemu_opt_get(opts, "host");
     vhostname   = qemu_opt_get(opts, "hostname");
     vdhcp_start = qemu_opt_get(opts, "dhcpstart");
@@ -2550,15 +2547,13 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon)
 #endif /* CONFIG_SLIRP */
 
 #ifdef _WIN32
-static int net_init_tap_win32(QemuOpts *opts, Monitor *mon)
+static int net_init_tap_win32(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
-    const char *name;
     const char *ifname;
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name   = qemu_opt_get(opts, "name");
     ifname = qemu_opt_get(opts, "ifname");
 
     if (!ifname) {
@@ -2575,16 +2570,13 @@ static int net_init_tap_win32(QemuOpts *opts, Monitor *mon)
     return 0;
 }
 #elif !defined(_AIX)
-static int net_init_tap(QemuOpts *opts, Monitor *mon)
+static int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
-    const char *name;
     TAPState *s;
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name = qemu_opt_get(opts, "name");
-
     if (qemu_opt_get(opts, "fd")) {
         int fd;
 
@@ -2637,15 +2629,12 @@ static int net_init_tap(QemuOpts *opts, Monitor *mon)
 }
 #endif
 
-static int net_init_socket(QemuOpts *opts, Monitor *mon)
+static int net_init_socket(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
-    const char *name;
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name = qemu_opt_get(opts, "name");
-
     if (qemu_opt_get(opts, "fd")) {
         int fd;
 
@@ -2721,17 +2710,15 @@ static int net_init_socket(QemuOpts *opts, Monitor *mon)
 }
 
 #ifdef CONFIG_VDE
-static int net_init_vde(QemuOpts *opts, Monitor *mon)
+static int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
-    const char *name;
     const char *sock;
     const char *group;
     int port, mode;
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name  = qemu_opt_get(opts, "name");
     sock  = qemu_opt_get(opts, "sock");
     group = qemu_opt_get(opts, "group");
 
@@ -2748,18 +2735,15 @@ static int net_init_vde(QemuOpts *opts, Monitor *mon)
 }
 #endif
 
-static int net_init_dump(QemuOpts *opts, Monitor *mon)
+static int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name)
 {
     VLANState *vlan;
     int len;
     const char *file;
-    const char *name;
     char def_file[128];
 
     vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
 
-    name = qemu_opt_get(opts, "name");
-
     file = qemu_opt_get(opts, "file");
     if (!file) {
         snprintf(def_file, sizeof(def_file), "qemu-vlan%d.pcap", vlan->id);
@@ -2786,7 +2770,9 @@ static int net_init_dump(QemuOpts *opts, Monitor *mon)
         .help = "identifier for monitor commands", \
      }
 
-typedef int (*net_client_init_func)(QemuOpts *opts, Monitor *mon);
+typedef int (*net_client_init_func)(QemuOpts *opts,
+                                    Monitor *mon,
+                                    const char *name);
 
 /* magic number, but compiler will warn if too small */
 #define NET_MAX_DESC 20
@@ -3005,6 +2991,7 @@ static struct {
 
 int net_client_init(Monitor *mon, QemuOpts *opts)
 {
+    const char *name;
     const char *type;
     int i;
 
@@ -3014,6 +3001,11 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
         return -1;
     }
 
+    name = qemu_opts_id(opts);
+    if (!name) {
+        name = qemu_opt_get(opts, "name");
+    }
+
     for (i = 0; net_client_types[i].type != NULL; i++) {
         if (!strcmp(net_client_types[i].type, type)) {
             if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
@@ -3021,7 +3013,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
             }
 
             if (net_client_types[i].init) {
-                return net_client_types[i].init(opts, mon);
+                return net_client_types[i].init(opts, mon, name);
             } else {
                 return 0;
             }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 06/16] net: remove id field from NICInfo
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (4 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 05/16] net: handle id= parameter for -net Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 07/16] net: use qtailq for vlan and client lists Mark McLoughlin
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Just use the name field instead since we now use the id paramater as
the name, if supplied. Only implication with this change is that if
id is not supplied, the value of the name paramater is used as an
id.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 hw/pci.c |    4 ++--
 net.c    |    4 ----
 net.h    |    1 -
 3 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/hw/pci.c b/hw/pci.c
index 49651d0..abf07ca 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -857,8 +857,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
 
     pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
     dev = &pci_dev->qdev;
-    if (nd->id)
-        dev->id = qemu_strdup(nd->id);
+    if (nd->name)
+        dev->id = qemu_strdup(nd->name);
     dev->nd = nd;
     if (qdev_init(dev) < 0)
         return NULL;
diff --git a/net.c b/net.c
index 8895e87..87dcf06 100644
--- a/net.c
+++ b/net.c
@@ -2414,9 +2414,6 @@ static int net_init_nic(QemuOpts *opts, Monitor *mon, const char *name)
     if (name) {
         nd->name = qemu_strdup(name);
     }
-    if (qemu_opts_id(opts)) {
-        nd->id = qemu_strdup(qemu_opts_id(opts));
-    }
     if (qemu_opt_get(opts, "model")) {
         nd->model = qemu_strdup(qemu_opt_get(opts, "model"));
     }
@@ -3032,7 +3029,6 @@ void net_client_uninit(NICInfo *nd)
     qemu_free(nd->model);
     qemu_free(nd->name);
     qemu_free(nd->devaddr);
-    qemu_free(nd->id);
 
     nd->used = 0;
 }
diff --git a/net.h b/net.h
index 49e160d..164ea3d 100644
--- a/net.h
+++ b/net.h
@@ -98,7 +98,6 @@ struct NICInfo {
     char *model;
     char *name;
     char *devaddr;
-    char *id;
     VLANState *vlan;
     VLANClientState *vc;
     void *private;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 07/16] net: use qtailq for vlan and client lists
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (5 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 06/16] net: remove id field from NICInfo Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 08/16] net: allow clients not associated with a vlan Mark McLoughlin
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c    |  116 +++++++++++++++++++++++++++++++-------------------------------
 net.h    |    6 ++--
 savevm.c |    2 +-
 3 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/net.c b/net.c
index 87dcf06..35547a5 100644
--- a/net.c
+++ b/net.c
@@ -113,10 +113,8 @@
 #include "qemu-config.h"
 
 #include "slirp/libslirp.h"
-#include "qemu-queue.h"
 
-
-static VLANState *first_vlan;
+static QTAILQ_HEAD(, VLANState) vlans;
 
 /***********************************************************/
 /* network device redirectors */
@@ -287,12 +285,14 @@ static char *assign_name(VLANClientState *vc1, const char *model)
     char buf[256];
     int id = 0;
 
-    for (vlan = first_vlan; vlan; vlan = vlan->next) {
+    QTAILQ_FOREACH(vlan, &vlans, next) {
         VLANClientState *vc;
 
-        for (vc = vlan->first_client; vc; vc = vc->next)
-            if (vc != vc1 && strcmp(vc->model, model) == 0)
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
+            if (vc != vc1 && strcmp(vc->model, model) == 0) {
                 id++;
+            }
+        }
     }
 
     snprintf(buf, sizeof(buf), "%s.%d", model, id);
@@ -309,8 +309,10 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
                                       NetCleanup *cleanup,
                                       void *opaque)
 {
-    VLANClientState *vc, **pvc;
+    VLANClientState *vc;
+
     vc = qemu_mallocz(sizeof(VLANClientState));
+
     vc->model = qemu_strdup(model);
     if (name)
         vc->name = qemu_strdup(name);
@@ -321,43 +323,35 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
     vc->receive_iov = receive_iov;
     vc->cleanup = cleanup;
     vc->opaque = opaque;
+
     vc->vlan = vlan;
+    QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
 
-    vc->next = NULL;
-    pvc = &vlan->first_client;
-    while (*pvc != NULL)
-        pvc = &(*pvc)->next;
-    *pvc = vc;
     return vc;
 }
 
 void qemu_del_vlan_client(VLANClientState *vc)
 {
-    VLANClientState **pvc = &vc->vlan->first_client;
+    QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
 
-    while (*pvc != NULL)
-        if (*pvc == vc) {
-            *pvc = vc->next;
-            if (vc->cleanup) {
-                vc->cleanup(vc);
-            }
-            qemu_free(vc->name);
-            qemu_free(vc->model);
-            qemu_free(vc);
-            break;
-        } else
-            pvc = &(*pvc)->next;
+    if (vc->cleanup) {
+        vc->cleanup(vc);
+    }
+
+    qemu_free(vc->name);
+    qemu_free(vc->model);
+    qemu_free(vc);
 }
 
 VLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque)
 {
-    VLANClientState **pvc = &vlan->first_client;
+    VLANClientState *vc;
 
-    while (*pvc != NULL)
-        if ((*pvc)->opaque == opaque)
-            return *pvc;
-        else
-            pvc = &(*pvc)->next;
+    QTAILQ_FOREACH(vc, &vlan->clients, next) {
+        if (vc->opaque == opaque) {
+            return vc;
+        }
+    }
 
     return NULL;
 }
@@ -375,7 +369,7 @@ qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
         return NULL;
     }
 
-    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+    QTAILQ_FOREACH(vc, &vlan->clients, next) {
         if (!strcmp(vc->name, client_str)) {
             break;
         }
@@ -393,7 +387,7 @@ int qemu_can_send_packet(VLANClientState *sender)
     VLANState *vlan = sender->vlan;
     VLANClientState *vc;
 
-    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+    QTAILQ_FOREACH(vc, &vlan->clients, next) {
         if (vc == sender) {
             continue;
         }
@@ -414,7 +408,7 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size)
 
     sender->vlan->delivering = 1;
 
-    for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
+    QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
         ssize_t len;
 
         if (vc == sender) {
@@ -557,7 +551,7 @@ static int qemu_deliver_packet_iov(VLANClientState *sender,
 
     sender->vlan->delivering = 1;
 
-    for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
+    QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
         ssize_t len;
 
         if (vc == sender) {
@@ -2305,22 +2299,25 @@ static int net_dump_init(VLANState *vlan, const char *device,
 /* find or alloc a new VLAN */
 VLANState *qemu_find_vlan(int id, int allocate)
 {
-    VLANState **pvlan, *vlan;
-    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
-        if (vlan->id == id)
+    VLANState *vlan;
+
+    QTAILQ_FOREACH(vlan, &vlans, next) {
+        if (vlan->id == id) {
             return vlan;
+        }
     }
+
     if (!allocate) {
         return NULL;
     }
+
     vlan = qemu_mallocz(sizeof(VLANState));
     vlan->id = id;
+    QTAILQ_INIT(&vlan->clients);
     QTAILQ_INIT(&vlan->send_queue);
-    vlan->next = NULL;
-    pvlan = &first_vlan;
-    while (*pvlan != NULL)
-        pvlan = &(*pvlan)->next;
-    *pvlan = vlan;
+
+    QTAILQ_INSERT_TAIL(&vlans, vlan, next);
+
     return vlan;
 }
 
@@ -3118,12 +3115,15 @@ void net_set_boot_mask(int net_boot_mask)
 void do_info_network(Monitor *mon)
 {
     VLANState *vlan;
-    VLANClientState *vc;
 
-    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+    QTAILQ_FOREACH(vlan, &vlans, next) {
+        VLANClientState *vc;
+
         monitor_printf(mon, "VLAN %d devices:\n", vlan->id);
-        for(vc = vlan->first_client; vc != NULL; vc = vc->next)
+
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
             monitor_printf(mon, "  %s: %s\n", vc->name, vc->info_str);
+        }
     }
 }
 
@@ -3134,10 +3134,13 @@ void do_set_link(Monitor *mon, const QDict *qdict)
     const char *name = qdict_get_str(qdict, "name");
     const char *up_or_down = qdict_get_str(qdict, "up_or_down");
 
-    for (vlan = first_vlan; vlan != NULL; vlan = vlan->next)
-        for (vc = vlan->first_client; vc != NULL; vc = vc->next)
-            if (strcmp(vc->name, name) == 0)
+    QTAILQ_FOREACH(vlan, &vlans, next) {
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
+            if (strcmp(vc->name, name) == 0) {
                 goto done;
+            }
+        }
+    }
 done:
 
     if (!vc) {
@@ -3161,16 +3164,11 @@ void net_cleanup(void)
 {
     VLANState *vlan;
 
-    /* close network clients */
-    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
-        VLANClientState *vc = vlan->first_client;
-
-        while (vc) {
-            VLANClientState *next = vc->next;
+    QTAILQ_FOREACH(vlan, &vlans, next) {
+        VLANClientState *vc, *next_vc;
 
+        QTAILQ_FOREACH_SAFE(vc, &vlan->clients, next, next_vc) {
             qemu_del_vlan_client(vc);
-
-            vc = next;
         }
     }
 }
@@ -3179,7 +3177,7 @@ static void net_check_clients(void)
 {
     VLANState *vlan;
 
-    for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) {
+    QTAILQ_FOREACH(vlan, &vlans, next) {
         if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0)
             continue;
         if (vlan->nb_guest_devs == 0)
@@ -3206,6 +3204,8 @@ int net_init_clients(void)
 #endif
     }
 
+    QTAILQ_INIT(&vlans);
+
     if (qemu_opts_foreach(&qemu_net_opts, net_init_client, NULL, 1) == -1) {
         return -1;
     }
diff --git a/net.h b/net.h
index 164ea3d..79e9b47 100644
--- a/net.h
+++ b/net.h
@@ -26,7 +26,7 @@ struct VLANClientState {
     LinkStatusChanged *link_status_changed;
     int link_down;
     void *opaque;
-    struct VLANClientState *next;
+    QTAILQ_ENTRY(VLANClientState) next;
     struct VLANState *vlan;
     char *model;
     char *name;
@@ -47,8 +47,8 @@ struct VLANPacket {
 
 struct VLANState {
     int id;
-    VLANClientState *first_client;
-    struct VLANState *next;
+    QTAILQ_HEAD(, VLANClientState) clients;
+    QTAILQ_ENTRY(VLANState) next;
     unsigned int nb_guest_devs, nb_host_devs;
     QTAILQ_HEAD(send_queue, VLANPacket) send_queue;
     int delivering;
diff --git a/savevm.c b/savevm.c
index 7a363b6..27a7686 100644
--- a/savevm.c
+++ b/savevm.c
@@ -131,7 +131,7 @@ static void qemu_announce_self_once(void *opaque)
             continue;
         len = announce_self_create(buf, nd_table[i].macaddr);
         vlan = nd_table[i].vlan;
-	for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
+        QTAILQ_FOREACH(vc, &vlan->clients, next) {
             vc->receive(vc, buf, len);
         }
     }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 08/16] net: allow clients not associated with a vlan
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (6 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 07/16] net: use qtailq for vlan and client lists Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 09/16] net: add QemuOptsList arg to net_client_parse() Mark McLoughlin
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Allow net clients to be created which are not connected to any vlan.

This is needed by Gerd in order to allow adding -device nic, where
the absence of a vlan parameter will not imply vlan=0. Also needed
to allow adding a -netdevice option which doesn't connect the backend
to a vlan.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   30 +++++++++++++++++++++++-------
 1 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/net.c b/net.c
index 35547a5..6cd63aa 100644
--- a/net.c
+++ b/net.c
@@ -324,15 +324,19 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
     vc->cleanup = cleanup;
     vc->opaque = opaque;
 
-    vc->vlan = vlan;
-    QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
+    if (vlan) {
+        vc->vlan = vlan;
+        QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
+    }
 
     return vc;
 }
 
 void qemu_del_vlan_client(VLANClientState *vc)
 {
-    QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
+    if (vc->vlan) {
+        QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
+    }
 
     if (vc->cleanup) {
         vc->cleanup(vc);
@@ -387,6 +391,10 @@ int qemu_can_send_packet(VLANClientState *sender)
     VLANState *vlan = sender->vlan;
     VLANClientState *vc;
 
+    if (!sender->vlan) {
+        return 1;
+    }
+
     QTAILQ_FOREACH(vc, &vlan->clients, next) {
         if (vc == sender) {
             continue;
@@ -434,6 +442,9 @@ void qemu_purge_queued_packets(VLANClientState *vc)
 {
     VLANPacket *packet, *next;
 
+    if (!vc->vlan)
+        return;
+
     QTAILQ_FOREACH_SAFE(packet, &vc->vlan->send_queue, entry, next) {
         if (packet->sender == vc) {
             QTAILQ_REMOVE(&vc->vlan->send_queue, packet, entry);
@@ -444,6 +455,9 @@ void qemu_purge_queued_packets(VLANClientState *vc)
 
 void qemu_flush_queued_packets(VLANClientState *vc)
 {
+    if (!vc->vlan)
+        return;
+
     while (!QTAILQ_EMPTY(&vc->vlan->send_queue)) {
         VLANPacket *packet;
         int ret;
@@ -485,12 +499,12 @@ ssize_t qemu_send_packet_async(VLANClientState *sender,
 {
     int ret;
 
-    if (sender->link_down) {
+    if (sender->link_down || !sender->vlan) {
         return size;
     }
 
 #ifdef DEBUG_NET
-    printf("vlan %d send:\n", sender->vlan->id);
+    printf("qemu_send_packet_async:\n");
     hex_dump(stdout, buf, size);
 #endif
 
@@ -610,7 +624,7 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender,
 {
     int ret;
 
-    if (sender->link_down) {
+    if (sender->link_down || !sender->vlan) {
         return calc_iov_length(iov, iovcnt);
     }
 
@@ -3020,7 +3034,9 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
 
 void net_client_uninit(NICInfo *nd)
 {
-    nd->vlan->nb_guest_devs--;
+    if (nd->vlan) {
+        nd->vlan->nb_guest_devs--;
+    }
     nb_nics--;
 
     qemu_free(nd->model);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 09/16] net: add QemuOptsList arg to net_client_parse()
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (7 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 08/16] net: allow clients not associated with a vlan Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 10/16] net: add -netdev option Mark McLoughlin
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |    7 ++++---
 net.h |    2 +-
 vl.c  |    2 +-
 3 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/net.c b/net.c
index 6cd63aa..2cfdd30 100644
--- a/net.c
+++ b/net.c
@@ -3231,11 +3231,12 @@ int net_init_clients(void)
     return 0;
 }
 
-int net_client_parse(const char *optarg)
+int net_client_parse(QemuOptsList *opts_list, const char *optarg)
 {
 #if defined(CONFIG_SLIRP)
     /* handle legacy -net channel,port:chr */
-    if (!strncmp(optarg, "channel,", strlen("channel,"))) {
+    if (!strcmp(opts_list->name, "net") &&
+        !strncmp(optarg, "channel,", strlen("channel,"))) {
         int ret;
 
         optarg += strlen("channel,");
@@ -3256,7 +3257,7 @@ int net_client_parse(const char *optarg)
         return ret;
     }
 #endif
-    if (!qemu_opts_parse(&qemu_net_opts, optarg, "type")) {
+    if (!qemu_opts_parse(opts_list, optarg, "type")) {
         return -1;
     }
 
diff --git a/net.h b/net.h
index 79e9b47..404190c 100644
--- a/net.h
+++ b/net.h
@@ -136,7 +136,7 @@ extern const char *legacy_bootp_filename;
 
 int net_client_init(Monitor *mon, QemuOpts *opts);
 void net_client_uninit(NICInfo *nd);
-int net_client_parse(const char *str);
+int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
 int net_slirp_smb(const char *exported_dir);
 void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index 374f85b..13e56bc 100644
--- a/vl.c
+++ b/vl.c
@@ -5088,7 +5088,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_net:
-                if (net_client_parse(optarg) == -1) {
+                if (net_client_parse(&qemu_net_opts, optarg) == -1) {
                     exit(1);
                 }
                 break;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 10/16] net: add -netdev option
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (8 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 09/16] net: add QemuOptsList arg to net_client_parse() Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 11/16] net: handle -netdevice options Mark McLoughlin
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 qemu-config.c   |   13 +++++++++++++
 qemu-config.h   |    1 +
 qemu-options.hx |   10 ++++++++++
 vl.c            |    5 +++++
 4 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index bafaea2..cae92f7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -152,6 +152,18 @@ QemuOptsList qemu_device_opts = {
     },
 };
 
+QemuOptsList qemu_netdev_opts = {
+    .name = "netdev",
+    .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",
     .head = QTAILQ_HEAD_INITIALIZER(qemu_net_opts.head),
@@ -188,6 +200,7 @@ static QemuOptsList *lists[] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
     &qemu_device_opts,
+    &qemu_netdev_opts,
     &qemu_net_opts,
     &qemu_rtc_opts,
     NULL,
diff --git a/qemu-config.h b/qemu-config.h
index cdad5ac..3cc8864 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -4,6 +4,7 @@
 extern QemuOptsList qemu_drive_opts;
 extern QemuOptsList qemu_chardev_opts;
 extern QemuOptsList qemu_device_opts;
+extern QemuOptsList qemu_netdev_opts;
 extern QemuOptsList qemu_net_opts;
 extern QemuOptsList qemu_rtc_opts;
 
diff --git a/qemu-options.hx b/qemu-options.hx
index 3dd76b3..d4cac04 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -839,6 +839,16 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
     "                dump traffic on vlan 'n' to file 'f' (max n bytes per packet)\n"
     "-net none       use it alone to have zero network devices; if no -net option\n"
     "                is provided, the default is '-net nic -net user'\n")
+DEF("netdev", HAS_ARG, QEMU_OPTION_netdev,
+    "-netdev ["
+#ifdef CONFIG_SLIRP
+    "user|"
+#endif
+    "tap|"
+#ifdef CONFIG_VDE
+    "vde|"
+#endif
+    "socket],id=str[,option][,option][,...]\n")
 STEXI
 @item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}][,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
 Create a new Network Interface Card and connect it to VLAN @var{n} (@var{n}
diff --git a/vl.c b/vl.c
index 13e56bc..49fea66 100644
--- a/vl.c
+++ b/vl.c
@@ -5087,6 +5087,11 @@ int main(int argc, char **argv, char **envp)
                 fd_bootchk = 0;
                 break;
 #endif
+            case QEMU_OPTION_netdev:
+                if (net_client_parse(&qemu_netdev_opts, optarg) == -1) {
+                    exit(1);
+                }
+                break;
             case QEMU_OPTION_net:
                 if (net_client_parse(&qemu_net_opts, optarg) == -1) {
                     exit(1);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 11/16] net: handle -netdevice options
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (9 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 10/16] net: add -netdev option Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 12/16] net: maintain a list of vlan-less clients Mark McLoughlin
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Same as for -net except for:

  - only tap, user, vde and socket types are supported
  - the vlan parameter is not allowed
  - the name parameter is not allowed but the id parameter is
    required

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 hw/pci-hotplug.c |    2 +-
 net.c            |  128 ++++++++++++++++++++++++++++++++++++++---------------
 net.h            |    2 +-
 vl.c             |    2 +-
 4 files changed, 95 insertions(+), 39 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index ccd2cf3..1b99640 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -51,7 +51,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     qemu_opt_set(opts, "type", "nic");
 
-    ret = net_client_init(mon, opts);
+    ret = net_client_init(mon, opts, 0);
     if (ret < 0)
         return NULL;
     if (nd_table[ret].devaddr) {
diff --git a/net.c b/net.c
index 2cfdd30..9af217e 100644
--- a/net.c
+++ b/net.c
@@ -2405,7 +2405,10 @@ static int net_handle_fd_param(Monitor *mon, const char *param)
     }
 }
 
-static int net_init_nic(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_nic(QemuOpts *opts,
+                        Monitor *mon,
+                        const char *name,
+                        VLANState *vlan)
 {
     int idx;
     NICInfo *nd;
@@ -2420,7 +2423,8 @@ static int net_init_nic(QemuOpts *opts, Monitor *mon, const char *name)
 
     memset(nd, 0, sizeof(*nd));
 
-    nd->vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
+    assert(vlan);
+    nd->vlan = vlan;
 
     if (name) {
         nd->name = qemu_strdup(name);
@@ -2482,9 +2486,11 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa
     return 0;
 }
 
-static int net_init_slirp(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_slirp(QemuOpts *opts,
+                          Monitor *mon,
+                          const char *name,
+                          VLANState *vlan)
 {
-    VLANState *vlan;
     struct slirp_config_str *config;
     const char *vhost;
     const char *vhostname;
@@ -2498,8 +2504,6 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon, const char *name)
     int restricted = 0;
     int ret;
 
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
-
     vhost       = qemu_opt_get(opts, "host");
     vhostname   = qemu_opt_get(opts, "hostname");
     vdhcp_start = qemu_opt_get(opts, "dhcpstart");
@@ -2544,7 +2548,7 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon, const char *name)
         qemu_free(config);
     }
 
-    if (ret != -1) {
+    if (ret != -1 && vlan) {
         vlan->nb_host_devs++;
     }
 
@@ -2555,13 +2559,13 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon, const char *name)
 #endif /* CONFIG_SLIRP */
 
 #ifdef _WIN32
-static int net_init_tap_win32(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_tap_win32(QemuOpts *opts,
+                              Monitor *mon,
+                              const char *name,
+                              VLANState *vlan)
 {
-    VLANState *vlan;
     const char *ifname;
 
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
-
     ifname = qemu_opt_get(opts, "ifname");
 
     if (!ifname) {
@@ -2573,18 +2577,20 @@ static int net_init_tap_win32(QemuOpts *opts, Monitor *mon, const char *name)
         return -1;
     }
 
-    vlan->nb_host_devs++;
+    if (vlan) {
+        vlan->nb_host_devs++;
+    }
 
     return 0;
 }
 #elif !defined(_AIX)
-static int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_tap(QemuOpts *opts,
+                        Monitor *mon,
+                        const char *name,
+                        VLANState *vlan)
 {
-    VLANState *vlan;
     TAPState *s;
 
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
-
     if (qemu_opt_get(opts, "fd")) {
         int fd;
 
@@ -2631,18 +2637,19 @@ static int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name)
         return -1;
     }
 
-    vlan->nb_host_devs++;
+    if (vlan) {
+        vlan->nb_host_devs++;
+    }
 
     return 0;
 }
 #endif
 
-static int net_init_socket(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_socket(QemuOpts *opts,
+                           Monitor *mon,
+                           const char *name,
+                           VLANState *vlan)
 {
-    VLANState *vlan;
-
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
-
     if (qemu_opt_get(opts, "fd")) {
         int fd;
 
@@ -2712,21 +2719,23 @@ static int net_init_socket(QemuOpts *opts, Monitor *mon, const char *name)
         return -1;
     }
 
-    vlan->nb_host_devs++;
+    if (vlan) {
+        vlan->nb_host_devs++;
+    }
 
     return 0;
 }
 
 #ifdef CONFIG_VDE
-static int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_vde(QemuOpts *opts,
+                        Monitor *mon,
+                        const char *name,
+                        VLANState *vlan)
 {
-    VLANState *vlan;
     const char *sock;
     const char *group;
     int port, mode;
 
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
-
     sock  = qemu_opt_get(opts, "sock");
     group = qemu_opt_get(opts, "group");
 
@@ -2737,20 +2746,24 @@ static int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name)
         return -1;
     }
 
-    vlan->nb_host_devs++;
+    if (vlan) {
+        vlan->nb_host_devs++;
+    }
 
     return 0;
 }
 #endif
 
-static int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name)
+static int net_init_dump(QemuOpts *opts,
+                         Monitor *mon,
+                         const char *name,
+                         VLANState *vlan)
 {
-    VLANState *vlan;
     int len;
     const char *file;
     char def_file[128];
 
-    vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
+    assert(vlan);
 
     file = qemu_opt_get(opts, "file");
     if (!file) {
@@ -2780,7 +2793,8 @@ static int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name)
 
 typedef int (*net_client_init_func)(QemuOpts *opts,
                                     Monitor *mon,
-                                    const char *name);
+                                    const char *name,
+                                    VLANState *vlan);
 
 /* magic number, but compiler will warn if too small */
 #define NET_MAX_DESC 20
@@ -2997,7 +3011,7 @@ static struct {
     { /* end of list */ }
 };
 
-int net_client_init(Monitor *mon, QemuOpts *opts)
+int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
 {
     const char *name;
     const char *type;
@@ -3009,6 +3023,34 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
         return -1;
     }
 
+    if (is_netdev) {
+        if (strcmp(type, "tap") != 0 &&
+#ifdef CONFIG_SLIRP
+            strcmp(type, "user") != 0 &&
+#endif
+#ifdef CONFIG_VDE
+            strcmp(type, "vde") != 0 &&
+#endif
+            strcmp(type, "socket") != 0) {
+            qemu_error("The '%s' network backend type is not valid with -netdev\n",
+                       type);
+            return -1;
+        }
+
+        if (qemu_opt_get(opts, "vlan")) {
+            qemu_error("The 'vlan' parameter is not valid with -netdev\n");
+            return -1;
+        }
+        if (qemu_opt_get(opts, "name")) {
+            qemu_error("The 'name' parameter is not valid with -netdev\n");
+            return -1;
+        }
+        if (!qemu_opts_id(opts)) {
+            qemu_error("The id= parameter is required with -netdev\n");
+            return -1;
+        }
+    }
+
     name = qemu_opts_id(opts);
     if (!name) {
         name = qemu_opt_get(opts, "name");
@@ -3016,12 +3058,18 @@ int net_client_init(Monitor *mon, QemuOpts *opts)
 
     for (i = 0; net_client_types[i].type != NULL; i++) {
         if (!strcmp(net_client_types[i].type, type)) {
+            VLANState *vlan = NULL;
+
             if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
                 return -1;
             }
 
+            if (!is_netdev) {
+                vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
+            }
+
             if (net_client_types[i].init) {
-                return net_client_types[i].init(opts, mon, name);
+                return net_client_types[i].init(opts, mon, name, vlan);
             } else {
                 return 0;
             }
@@ -3086,7 +3134,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     qemu_opt_set(opts, "type", device);
 
-    if (net_client_init(mon, opts) < 0) {
+    if (net_client_init(mon, opts, 0) < 0) {
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -3207,7 +3255,12 @@ static void net_check_clients(void)
 
 static int net_init_client(QemuOpts *opts, void *dummy)
 {
-    return net_client_init(NULL, opts);
+    return net_client_init(NULL, opts, 0);
+}
+
+static int net_init_netdev(QemuOpts *opts, void *dummy)
+{
+    return net_client_init(NULL, opts, 1);
 }
 
 int net_init_clients(void)
@@ -3222,6 +3275,9 @@ int net_init_clients(void)
 
     QTAILQ_INIT(&vlans);
 
+    if (qemu_opts_foreach(&qemu_netdev_opts, net_init_netdev, NULL, 1) == -1)
+        return -1;
+
     if (qemu_opts_foreach(&qemu_net_opts, net_init_client, NULL, 1) == -1) {
         return -1;
     }
diff --git a/net.h b/net.h
index 404190c..edaf942 100644
--- a/net.h
+++ b/net.h
@@ -134,7 +134,7 @@ void net_checksum_calculate(uint8_t *data, int length);
 extern const char *legacy_tftp_prefix;
 extern const char *legacy_bootp_filename;
 
-int net_client_init(Monitor *mon, QemuOpts *opts);
+int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
diff --git a/vl.c b/vl.c
index 49fea66..73bc15c 100644
--- a/vl.c
+++ b/vl.c
@@ -2606,7 +2606,7 @@ static int usb_device_add(const char *devname, int is_hotplug)
         qemu_opt_set(opts, "type", "nic");
         qemu_opt_set(opts, "model", "usb");
 
-        idx = net_client_init(NULL, opts);
+        idx = net_client_init(NULL, opts, 0);
         if (idx == -1) {
             return -1;
         }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 12/16] net: maintain a list of vlan-less clients
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (10 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 11/16] net: handle -netdevice options Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 13/16] net: add -net nic,netdev= option Mark McLoughlin
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Allows them to be cleaned up at shutdown.

This is pretty lame, but will eventually go away as we make vlans
the special case.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/net.c b/net.c
index 9af217e..d6fe84b 100644
--- a/net.c
+++ b/net.c
@@ -115,6 +115,7 @@
 #include "slirp/libslirp.h"
 
 static QTAILQ_HEAD(, VLANState) vlans;
+static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
 
 /***********************************************************/
 /* network device redirectors */
@@ -327,6 +328,8 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
     if (vlan) {
         vc->vlan = vlan;
         QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
+    } else {
+        QTAILQ_INSERT_TAIL(&non_vlan_clients, vc, next);
     }
 
     return vc;
@@ -336,6 +339,8 @@ void qemu_del_vlan_client(VLANClientState *vc)
 {
     if (vc->vlan) {
         QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
+    } else {
+        QTAILQ_REMOVE(&non_vlan_clients, vc, next);
     }
 
     if (vc->cleanup) {
@@ -3227,14 +3232,17 @@ done:
 void net_cleanup(void)
 {
     VLANState *vlan;
+    VLANClientState *vc, *next_vc;
 
     QTAILQ_FOREACH(vlan, &vlans, next) {
-        VLANClientState *vc, *next_vc;
-
         QTAILQ_FOREACH_SAFE(vc, &vlan->clients, next, next_vc) {
             qemu_del_vlan_client(vc);
         }
     }
+
+    QTAILQ_FOREACH_SAFE(vc, &non_vlan_clients, next, next_vc) {
+        qemu_del_vlan_client(vc);
+    }
 }
 
 static void net_check_clients(void)
@@ -3274,6 +3282,7 @@ int net_init_clients(void)
     }
 
     QTAILQ_INIT(&vlans);
+    QTAILQ_INIT(&non_vlan_clients);
 
     if (qemu_opts_foreach(&qemu_netdev_opts, net_init_netdev, NULL, 1) == -1)
         return -1;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 13/16] net: add -net nic,netdev= option
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (11 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 12/16] net: maintain a list of vlan-less clients Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 14/16] net: allow NICs to be connected to netdevs Mark McLoughlin
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |   41 ++++++++++++++++++++++++++++++++++++-----
 net.h |    1 +
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/net.c b/net.c
index d6fe84b..3f997cc 100644
--- a/net.c
+++ b/net.c
@@ -2340,6 +2340,19 @@ VLANState *qemu_find_vlan(int id, int allocate)
     return vlan;
 }
 
+static VLANClientState *qemu_find_netdev(const char *id)
+{
+    VLANClientState *vc;
+
+    QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
+        if (!strcmp(vc->name, id)) {
+            return vc;
+        }
+    }
+
+    return NULL;
+}
+
 static int nic_get_free_idx(void)
 {
     int index;
@@ -2417,6 +2430,7 @@ static int net_init_nic(QemuOpts *opts,
 {
     int idx;
     NICInfo *nd;
+    const char *netdev;
 
     idx = nic_get_free_idx();
     if (idx == -1 || nb_nics >= MAX_NICS) {
@@ -2428,9 +2442,16 @@ static int net_init_nic(QemuOpts *opts,
 
     memset(nd, 0, sizeof(*nd));
 
-    assert(vlan);
-    nd->vlan = vlan;
-
+    if ((netdev = qemu_opt_get(opts, "netdev"))) {
+        nd->netdev = qemu_find_netdev(netdev);
+        if (!nd->netdev) {
+            qemu_error("netdev '%s' not found\n", netdev);
+            return -1;
+        }
+    } else {
+        assert(vlan);
+        nd->vlan = vlan;
+    }
     if (name) {
         nd->name = qemu_strdup(name);
     }
@@ -2462,7 +2483,9 @@ static int net_init_nic(QemuOpts *opts,
     }
 
     nd->used = 1;
-    nd->vlan->nb_guest_devs++;
+    if (vlan) {
+        nd->vlan->nb_guest_devs++;
+    }
     nb_nics++;
 
     return idx;
@@ -2821,6 +2844,11 @@ static struct {
         .desc = {
             NET_COMMON_PARAMS_DESC,
             {
+                .name = "netdev",
+                .type = QEMU_OPT_STRING,
+                .help = "id of -netdev to connect to",
+            },
+            {
                 .name = "macaddr",
                 .type = QEMU_OPT_STRING,
                 .help = "MAC address",
@@ -3069,7 +3097,10 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
                 return -1;
             }
 
-            if (!is_netdev) {
+            /* Do not add to a vlan if it's a -netdev or a nic with a
+             * netdev= parameter. */
+            if (!(is_netdev ||
+                  (strcmp(type, "nic") == 0 && qemu_opt_get(opts, "netdev")))) {
                 vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
             }
 
diff --git a/net.h b/net.h
index edaf942..e23047c 100644
--- a/net.h
+++ b/net.h
@@ -99,6 +99,7 @@ struct NICInfo {
     char *name;
     char *devaddr;
     VLANState *vlan;
+    VLANClientState *netdev;
     VLANClientState *vc;
     void *private;
     int used;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 14/16] net: allow NICs to be connected to netdevs
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (12 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 13/16] net: add -net nic,netdev= option Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 15/16] net: refactor packet queueing code Mark McLoughlin
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Introduce a 'peer' member to VLANClientState as an alternative
to a vlan. The idea being that packets are transfered directly
from peer clients rather than going through a vlan.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 hw/dp8393x.c     |    3 ++-
 hw/etraxfs_eth.c |    3 ++-
 hw/mcf_fec.c     |    3 ++-
 hw/mipsnet.c     |    5 +++--
 hw/qdev.c        |    6 ++++--
 hw/usb-net.c     |    3 ++-
 hw/xen_nic.c     |    2 +-
 net.c            |   35 +++++++++++++++++++++++++----------
 net.h            |    2 ++
 tap-win32.c      |    3 ++-
 10 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/hw/dp8393x.c b/hw/dp8393x.c
index 067831d..e4caab0 100644
--- a/hw/dp8393x.c
+++ b/hw/dp8393x.c
@@ -889,7 +889,8 @@ void dp83932_init(NICInfo *nd, target_phys_addr_t base, int it_shift,
     s->watchdog = qemu_new_timer(vm_clock, dp8393x_watchdog, s);
     s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
 
-    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
+    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                          nd->model, nd->name,
                                           nic_can_receive, nic_receive, NULL,
                                           nic_cleanup, s);
 
diff --git a/hw/etraxfs_eth.c b/hw/etraxfs_eth.c
index 54786c5..a411dab 100644
--- a/hw/etraxfs_eth.c
+++ b/hw/etraxfs_eth.c
@@ -590,7 +590,8 @@ void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
 	eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth);
 	cpu_register_physical_memory (base, 0x5c, eth->ethregs);
 
-	eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
+	eth->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                                nd->model, nd->name,
                                                 eth_can_receive, eth_receive,
                                                 NULL, eth_cleanup, eth);
 	eth->vc->opaque = eth;
diff --git a/hw/mcf_fec.c b/hw/mcf_fec.c
index f6d2bab..f9f437a 100644
--- a/hw/mcf_fec.c
+++ b/hw/mcf_fec.c
@@ -462,7 +462,8 @@ void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
                                            mcf_fec_writefn, s);
     cpu_register_physical_memory(base, 0x400, s->mmio_index);
 
-    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
+    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                          nd->model, nd->name,
                                           mcf_fec_can_receive, mcf_fec_receive,
                                           NULL, mcf_fec_cleanup, s);
     memcpy(s->macaddr, nd->macaddr, 6);
diff --git a/hw/mipsnet.c b/hw/mipsnet.c
index e98c576..ea8b570 100644
--- a/hw/mipsnet.c
+++ b/hw/mipsnet.c
@@ -262,8 +262,9 @@ void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
 
     s->io_base = base;
     s->irq = irq;
-    if (nd && nd->vlan) {
-        s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
+    if (nd) {
+        s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                              nd->model, nd->name,
                                               mipsnet_can_receive, mipsnet_receive,
                                               NULL, mipsnet_cleanup, s);
     } else {
diff --git a/hw/qdev.c b/hw/qdev.c
index 906e897..20f931c 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -370,8 +370,10 @@ VLANClientState *qdev_get_vlan_client(DeviceState *dev,
 {
     NICInfo *nd = dev->nd;
     assert(nd);
-    nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, can_receive,
-                                  receive, receive_iov, cleanup, opaque);
+    nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                  nd->model, nd->name,
+                                  can_receive, receive, receive_iov,
+                                  cleanup, opaque);
     return nd->vc;
 }
 
diff --git a/hw/usb-net.c b/hw/usb-net.c
index b33e329..5c753e0 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1460,7 +1460,8 @@ USBDevice *usb_net_init(NICInfo *nd)
 
     memcpy(s->mac, nd->macaddr, 6);
 
-    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
+    s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->netdev,
+                                          nd->model, nd->name,
                                           usbnet_can_receive,
                                           usbnet_receive,
                                           NULL,
diff --git a/hw/xen_nic.c b/hw/xen_nic.c
index c9e9199..b09b48a 100644
--- a/hw/xen_nic.c
+++ b/hw/xen_nic.c
@@ -301,7 +301,7 @@ static int net_init(struct XenDevice *xendev)
 	return -1;
 
     vlan = qemu_find_vlan(netdev->xendev.dev, 1);
-    netdev->vs = qemu_new_vlan_client(vlan, "xen", NULL,
+    netdev->vs = qemu_new_vlan_client(vlan, NULL, "xen", NULL,
                                       net_rx_ok, net_rx_packet, NULL,
                                       NULL, netdev);
     snprintf(netdev->vs->info_str, sizeof(netdev->vs->info_str),
diff --git a/net.c b/net.c
index 3f997cc..5d78f04 100644
--- a/net.c
+++ b/net.c
@@ -302,6 +302,7 @@ static char *assign_name(VLANClientState *vc1, const char *model)
 }
 
 VLANClientState *qemu_new_vlan_client(VLANState *vlan,
+                                      VLANClientState *peer,
                                       const char *model,
                                       const char *name,
                                       NetCanReceive *can_receive,
@@ -326,9 +327,14 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
     vc->opaque = opaque;
 
     if (vlan) {
+        assert(!peer);
         vc->vlan = vlan;
         QTAILQ_INSERT_TAIL(&vc->vlan->clients, vc, next);
     } else {
+        if (peer) {
+            vc->peer = peer;
+            peer->peer = vc;
+        }
         QTAILQ_INSERT_TAIL(&non_vlan_clients, vc, next);
     }
 
@@ -341,6 +347,9 @@ void qemu_del_vlan_client(VLANClientState *vc)
         QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
     } else {
         QTAILQ_REMOVE(&non_vlan_clients, vc, next);
+        if (vc->peer) {
+            vc->peer->peer = NULL;
+        }
     }
 
     if (vc->cleanup) {
@@ -866,7 +875,8 @@ static int net_slirp_init(VLANState *vlan, const char *model,
     }
 #endif
 
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, NULL,
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL,
+                                 slirp_receive, NULL,
                                  net_slirp_cleanup, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "net=%s, restricted=%c", inet_ntoa(net), restricted ? 'y' : 'n');
@@ -1426,8 +1436,9 @@ static TAPState *net_tap_fd_init(VLANState *vlan,
 
     s = qemu_mallocz(sizeof(TAPState));
     s->fd = fd;
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, tap_receive,
-                                 tap_receive_iov, tap_cleanup, s);
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL,
+                                 tap_receive, tap_receive_iov,
+                                 tap_cleanup, s);
     tap_read_poll(s, 1);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
     return s;
@@ -1760,8 +1771,9 @@ static int net_vde_init(VLANState *vlan, const char *model,
         free(s);
         return -1;
     }
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, vde_receive,
-                                 NULL, vde_cleanup, s);
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL,
+                                 vde_receive, NULL,
+                                 vde_cleanup, s);
     qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d",
              sock, vde_datafd(s->vde));
@@ -1999,8 +2011,9 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan,
     s = qemu_mallocz(sizeof(NetSocketState));
     s->fd = fd;
 
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, net_socket_receive_dgram,
-                                 NULL, net_socket_cleanup, s);
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL,
+                                 net_socket_receive_dgram, NULL,
+                                 net_socket_cleanup, s);
     qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
 
     /* mcast: save bound address as dst */
@@ -2027,8 +2040,9 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan,
     NetSocketState *s;
     s = qemu_mallocz(sizeof(NetSocketState));
     s->fd = fd;
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, net_socket_receive,
-                                 NULL, net_socket_cleanup, s);
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name, NULL,
+                                 net_socket_receive, NULL,
+                                 net_socket_cleanup, s);
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
              "socket: fd=%d", fd);
     if (is_connected) {
@@ -2308,7 +2322,8 @@ static int net_dump_init(VLANState *vlan, const char *device,
         return -1;
     }
 
-    s->pcap_vc = qemu_new_vlan_client(vlan, device, name, NULL, dump_receive, NULL,
+    s->pcap_vc = qemu_new_vlan_client(vlan, NULL, device, name, NULL,
+                                      dump_receive, NULL,
                                       net_dump_cleanup, s);
     snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str),
              "dump to %s (len=%d)", filename, len);
diff --git a/net.h b/net.h
index e23047c..fa59c3d 100644
--- a/net.h
+++ b/net.h
@@ -28,6 +28,7 @@ struct VLANClientState {
     void *opaque;
     QTAILQ_ENTRY(VLANClientState) next;
     struct VLANState *vlan;
+    VLANClientState *peer;
     char *model;
     char *name;
     char info_str[256];
@@ -56,6 +57,7 @@ struct VLANState {
 
 VLANState *qemu_find_vlan(int id, int allocate);
 VLANClientState *qemu_new_vlan_client(VLANState *vlan,
+                                      VLANClientState *peer,
                                       const char *model,
                                       const char *name,
                                       NetCanReceive *can_receive,
diff --git a/tap-win32.c b/tap-win32.c
index 2c02ce3..e4fdde8 100644
--- a/tap-win32.c
+++ b/tap-win32.c
@@ -677,7 +677,8 @@ int tap_win32_init(VLANState *vlan, const char *model,
         return -1;
     }
 
-    s->vc = qemu_new_vlan_client(vlan, model, name, NULL, tap_receive,
+    s->vc = qemu_new_vlan_client(vlan, NULL, model, name,
+                                 NULL, tap_receive,
                                  NULL, tap_cleanup, s);
 
     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 15/16] net: refactor packet queueing code
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (13 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 14/16] net: allow NICs to be connected to netdevs Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 16/16] net: add queue for peer-to-peer packet forwarding Mark McLoughlin
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

The packet queue code is fairly standalone, has some complex details and
easily reusable. It makes sense to split it out on its own. This patch
doesn't contain any functional changes.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 Makefile      |    3 +-
 net-queue.c   |  250 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 net-queue.h   |   64 +++++++++++++++
 net.c         |  138 +++++--------------------------
 net.h         |   18 +----
 qemu-common.h |    1 +
 6 files changed, 342 insertions(+), 132 deletions(-)
 create mode 100644 net-queue.c
 create mode 100644 net-queue.h

diff --git a/Makefile b/Makefile
index c552739..e94dd2c 100644
--- a/Makefile
+++ b/Makefile
@@ -96,7 +96,8 @@ obj-y += usb-serial.o usb-net.o usb-bus.o
 obj-y += sd.o ssi-sd.o
 obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
 obj-y += bt-hci-csr.o
-obj-y += buffered_file.o migration.o migration-tcp.o net.o qemu-sockets.o
+obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
+obj-y += net.o net-queue.o
 obj-y += qemu-char.o aio.o net-checksum.o savevm.o
 obj-y += msmouse.o ps2.o
 obj-y += qdev.o qdev-properties.o ssi.o
diff --git a/net-queue.c b/net-queue.c
new file mode 100644
index 0000000..75457f0
--- /dev/null
+++ b/net-queue.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "net-queue.h"
+#include "qemu-queue.h"
+
+/* The delivery handler may only return zero if it will call
+ * qemu_net_queue_flush() when it determines that it is once again able
+ * to deliver packets. It must also call qemu_net_queue_purge() in its
+ * cleanup path.
+ *
+ * If a sent callback is provided to send(), the caller must handle a
+ * zero return from the delivery handler by not sending any more packets
+ * until we have invoked the callback. Only in that case will we queue
+ * the packet.
+ *
+ * If a sent callback isn't provided, we just drop the packet to avoid
+ * unbounded queueing.
+ */
+
+struct NetPacket {
+    QTAILQ_ENTRY(NetPacket) entry;
+    VLANClientState *sender;
+    int size;
+    NetPacketSent *sent_cb;
+    uint8_t data[0];
+};
+
+struct NetQueue {
+    NetPacketDeliver *deliver;
+    NetPacketDeliverIOV *deliver_iov;
+    void *opaque;
+
+    QTAILQ_HEAD(packets, NetPacket) packets;
+
+    unsigned delivering : 1;
+};
+
+NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver,
+                             NetPacketDeliverIOV *deliver_iov,
+                             void *opaque)
+{
+    NetQueue *queue;
+
+    queue = qemu_mallocz(sizeof(NetQueue));
+
+    queue->deliver = deliver;
+    queue->deliver_iov = deliver_iov;
+    queue->opaque = opaque;
+
+    QTAILQ_INIT(&queue->packets);
+
+    queue->delivering = 0;
+
+    return queue;
+}
+
+void qemu_del_net_queue(NetQueue *queue)
+{
+    NetPacket *packet, *next;
+
+    QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
+        QTAILQ_REMOVE(&queue->packets, packet, entry);
+        qemu_free(packet);
+    }
+
+    qemu_free(queue);
+}
+
+static ssize_t qemu_net_queue_append(NetQueue *queue,
+                                     VLANClientState *sender,
+                                     const uint8_t *buf,
+                                     size_t size,
+                                     NetPacketSent *sent_cb)
+{
+    NetPacket *packet;
+
+    packet = qemu_malloc(sizeof(NetPacket) + size);
+    packet->sender = sender;
+    packet->size = size;
+    packet->sent_cb = sent_cb;
+    memcpy(packet->data, buf, size);
+
+    QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
+
+    return size;
+}
+
+static ssize_t qemu_net_queue_append_iov(NetQueue *queue,
+                                         VLANClientState *sender,
+                                         const struct iovec *iov,
+                                         int iovcnt,
+                                         NetPacketSent *sent_cb)
+{
+    NetPacket *packet;
+    size_t max_len = 0;
+    int i;
+
+    for (i = 0; i < iovcnt; i++) {
+        max_len += iov[i].iov_len;
+    }
+
+    packet = qemu_malloc(sizeof(NetPacket) + max_len);
+    packet->sender = sender;
+    packet->sent_cb = sent_cb;
+    packet->size = 0;
+
+    for (i = 0; i < iovcnt; i++) {
+        size_t len = iov[i].iov_len;
+
+        memcpy(packet->data + packet->size, iov[i].iov_base, len);
+        packet->size += len;
+    }
+
+    QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
+
+    return packet->size;
+}
+
+static ssize_t qemu_net_queue_deliver(NetQueue *queue,
+                                      VLANClientState *sender,
+                                      const uint8_t *data,
+                                      size_t size)
+{
+    ssize_t ret = -1;
+
+    queue->delivering = 1;
+    ret = queue->deliver(sender, data, size, queue->opaque);
+    queue->delivering = 0;
+
+    return ret;
+}
+
+static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
+                                          VLANClientState *sender,
+                                          const struct iovec *iov,
+                                          int iovcnt)
+{
+    ssize_t ret = -1;
+
+    queue->delivering = 1;
+    ret = queue->deliver_iov(sender, iov, iovcnt, queue->opaque);
+    queue->delivering = 0;
+
+    return ret;
+}
+
+ssize_t qemu_net_queue_send(NetQueue *queue,
+                            VLANClientState *sender,
+                            const uint8_t *data,
+                            size_t size,
+                            NetPacketSent *sent_cb)
+{
+    ssize_t ret;
+
+    if (queue->delivering) {
+        return qemu_net_queue_append(queue, sender, data, size, NULL);
+    }
+
+    ret = qemu_net_queue_deliver(queue, sender, data, size);
+    if (ret == 0 && sent_cb != NULL) {
+        qemu_net_queue_append(queue, sender, data, size, sent_cb);
+        return 0;
+    }
+
+    qemu_net_queue_flush(queue);
+
+    return ret;
+}
+
+ssize_t qemu_net_queue_send_iov(NetQueue *queue,
+                                VLANClientState *sender,
+                                const struct iovec *iov,
+                                int iovcnt,
+                                NetPacketSent *sent_cb)
+{
+    ssize_t ret;
+
+    if (queue->delivering) {
+        return qemu_net_queue_append_iov(queue, sender, iov, iovcnt, NULL);
+    }
+
+    ret = qemu_net_queue_deliver_iov(queue, sender, iov, iovcnt);
+    if (ret == 0 && sent_cb != NULL) {
+        qemu_net_queue_append_iov(queue, sender, iov, iovcnt, sent_cb);
+        return 0;
+    }
+
+    qemu_net_queue_flush(queue);
+
+    return ret;
+}
+
+void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from)
+{
+    NetPacket *packet, *next;
+
+    QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
+        if (packet->sender == from) {
+            QTAILQ_REMOVE(&queue->packets, packet, entry);
+            qemu_free(packet);
+        }
+    }
+}
+
+void qemu_net_queue_flush(NetQueue *queue)
+{
+    while (!QTAILQ_EMPTY(&queue->packets)) {
+        NetPacket *packet;
+        int ret;
+
+        packet = QTAILQ_FIRST(&queue->packets);
+        QTAILQ_REMOVE(&queue->packets, packet, entry);
+
+        ret = qemu_net_queue_deliver(queue,
+                                     packet->sender,
+                                     packet->data,
+                                     packet->size);
+        if (ret == 0 && packet->sent_cb != NULL) {
+            QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
+            break;
+        }
+
+        if (packet->sent_cb) {
+            packet->sent_cb(packet->sender, ret);
+        }
+
+        qemu_free(packet);
+    }
+}
diff --git a/net-queue.h b/net-queue.h
new file mode 100644
index 0000000..ea17df6
--- /dev/null
+++ b/net-queue.h
@@ -0,0 +1,64 @@
+/*
+ * 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) (VLANClientState *sender, ssize_t ret);
+
+typedef ssize_t (NetPacketDeliver) (VLANClientState *sender,
+                                    const uint8_t *buf,
+                                    size_t size,
+                                    void *opaque);
+
+typedef ssize_t (NetPacketDeliverIOV) (VLANClientState *sender,
+                                       const struct iovec *iov,
+                                       int iovcnt,
+                                       void *opaque);
+
+NetQueue *qemu_new_net_queue(NetPacketDeliver *deliver,
+                             NetPacketDeliverIOV *deliver_iov,
+                             void *opaque);
+void qemu_del_net_queue(NetQueue *queue);
+
+ssize_t qemu_net_queue_send(NetQueue *queue,
+                            VLANClientState *sender,
+                            const uint8_t *data,
+                            size_t size,
+                            NetPacketSent *sent_cb);
+
+ssize_t qemu_net_queue_send_iov(NetQueue *queue,
+                                VLANClientState *sender,
+                                const struct iovec *iov,
+                                int iovcnt,
+                                NetPacketSent *sent_cb);
+
+void qemu_net_queue_purge(NetQueue *queue, VLANClientState *from);
+void qemu_net_queue_flush(NetQueue *queue);
+
+#endif /* QEMU_NET_QUEUE_H */
diff --git a/net.c b/net.c
index 5d78f04..2c7b2ef 100644
--- a/net.c
+++ b/net.c
@@ -422,15 +422,16 @@ int qemu_can_send_packet(VLANClientState *sender)
     return 0;
 }
 
-static int
-qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size)
+static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
+                                        const uint8_t *buf,
+                                        size_t size,
+                                        void *opaque)
 {
+    VLANState *vlan = opaque;
     VLANClientState *vc;
     int ret = -1;
 
-    sender->vlan->delivering = 1;
-
-    QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
+    QTAILQ_FOREACH(vc, &vlan->clients, next) {
         ssize_t len;
 
         if (vc == sender) {
@@ -447,24 +448,15 @@ qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size)
         ret = (ret >= 0) ? ret : len;
     }
 
-    sender->vlan->delivering = 0;
-
     return ret;
 }
 
 void qemu_purge_queued_packets(VLANClientState *vc)
 {
-    VLANPacket *packet, *next;
-
     if (!vc->vlan)
         return;
 
-    QTAILQ_FOREACH_SAFE(packet, &vc->vlan->send_queue, entry, next) {
-        if (packet->sender == vc) {
-            QTAILQ_REMOVE(&vc->vlan->send_queue, packet, entry);
-            qemu_free(packet);
-        }
-    }
+    qemu_net_queue_purge(vc->vlan->send_queue, vc);
 }
 
 void qemu_flush_queued_packets(VLANClientState *vc)
@@ -472,47 +464,13 @@ void qemu_flush_queued_packets(VLANClientState *vc)
     if (!vc->vlan)
         return;
 
-    while (!QTAILQ_EMPTY(&vc->vlan->send_queue)) {
-        VLANPacket *packet;
-        int ret;
-
-        packet = QTAILQ_FIRST(&vc->vlan->send_queue);
-        QTAILQ_REMOVE(&vc->vlan->send_queue, packet, entry);
-
-        ret = qemu_deliver_packet(packet->sender, packet->data, packet->size);
-        if (ret == 0 && packet->sent_cb != NULL) {
-            QTAILQ_INSERT_HEAD(&vc->vlan->send_queue, packet, entry);
-            break;
-        }
-
-        if (packet->sent_cb)
-            packet->sent_cb(packet->sender, ret);
-
-        qemu_free(packet);
-    }
-}
-
-static void qemu_enqueue_packet(VLANClientState *sender,
-                                const uint8_t *buf, int size,
-                                NetPacketSent *sent_cb)
-{
-    VLANPacket *packet;
-
-    packet = qemu_malloc(sizeof(VLANPacket) + size);
-    packet->sender = sender;
-    packet->size = size;
-    packet->sent_cb = sent_cb;
-    memcpy(packet->data, buf, size);
-
-    QTAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry);
+    qemu_net_queue_flush(vc->vlan->send_queue);
 }
 
 ssize_t qemu_send_packet_async(VLANClientState *sender,
                                const uint8_t *buf, int size,
                                NetPacketSent *sent_cb)
 {
-    int ret;
-
     if (sender->link_down || !sender->vlan) {
         return size;
     }
@@ -522,20 +480,8 @@ ssize_t qemu_send_packet_async(VLANClientState *sender,
     hex_dump(stdout, buf, size);
 #endif
 
-    if (sender->vlan->delivering) {
-        qemu_enqueue_packet(sender, buf, size, NULL);
-        return size;
-    }
-
-    ret = qemu_deliver_packet(sender, buf, size);
-    if (ret == 0 && sent_cb != NULL) {
-        qemu_enqueue_packet(sender, buf, size, sent_cb);
-        return 0;
-    }
-
-    qemu_flush_queued_packets(sender);
-
-    return ret;
+    return qemu_net_queue_send(sender->vlan->send_queue,
+                               sender, buf, size, sent_cb);
 }
 
 void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
@@ -571,15 +517,16 @@ static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
     return offset;
 }
 
-static int qemu_deliver_packet_iov(VLANClientState *sender,
-                                   const struct iovec *iov, int iovcnt)
+static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
+                                            const struct iovec *iov,
+                                            int iovcnt,
+                                            void *opaque)
 {
+    VLANState *vlan = opaque;
     VLANClientState *vc;
-    int ret = -1;
-
-    sender->vlan->delivering = 1;
+    ssize_t ret = -1;
 
-    QTAILQ_FOREACH(vc, &sender->vlan->clients, next) {
+    QTAILQ_FOREACH(vc, &vlan->clients, next) {
         ssize_t len;
 
         if (vc == sender) {
@@ -600,61 +547,19 @@ static int qemu_deliver_packet_iov(VLANClientState *sender,
         ret = (ret >= 0) ? ret : len;
     }
 
-    sender->vlan->delivering = 0;
-
     return ret;
 }
 
-static ssize_t qemu_enqueue_packet_iov(VLANClientState *sender,
-                                       const struct iovec *iov, int iovcnt,
-                                       NetPacketSent *sent_cb)
-{
-    VLANPacket *packet;
-    size_t max_len = 0;
-    int i;
-
-    max_len = calc_iov_length(iov, iovcnt);
-
-    packet = qemu_malloc(sizeof(VLANPacket) + max_len);
-    packet->sender = sender;
-    packet->sent_cb = sent_cb;
-    packet->size = 0;
-
-    for (i = 0; i < iovcnt; i++) {
-        size_t len = iov[i].iov_len;
-
-        memcpy(packet->data + packet->size, iov[i].iov_base, len);
-        packet->size += len;
-    }
-
-    QTAILQ_INSERT_TAIL(&sender->vlan->send_queue, packet, entry);
-
-    return packet->size;
-}
-
 ssize_t qemu_sendv_packet_async(VLANClientState *sender,
                                 const struct iovec *iov, int iovcnt,
                                 NetPacketSent *sent_cb)
 {
-    int ret;
-
     if (sender->link_down || !sender->vlan) {
         return calc_iov_length(iov, iovcnt);
     }
 
-    if (sender->vlan->delivering) {
-        return qemu_enqueue_packet_iov(sender, iov, iovcnt, NULL);
-    }
-
-    ret = qemu_deliver_packet_iov(sender, iov, iovcnt);
-    if (ret == 0 && sent_cb != NULL) {
-        qemu_enqueue_packet_iov(sender, iov, iovcnt, sent_cb);
-        return 0;
-    }
-
-    qemu_flush_queued_packets(sender);
-
-    return ret;
+    return qemu_net_queue_send_iov(sender->vlan->send_queue,
+                                   sender, iov, iovcnt, sent_cb);
 }
 
 ssize_t
@@ -2348,7 +2253,10 @@ VLANState *qemu_find_vlan(int id, int allocate)
     vlan = qemu_mallocz(sizeof(VLANState));
     vlan->id = id;
     QTAILQ_INIT(&vlan->clients);
-    QTAILQ_INIT(&vlan->send_queue);
+
+    vlan->send_queue = qemu_new_net_queue(qemu_vlan_deliver_packet,
+                                          qemu_vlan_deliver_packet_iov,
+                                          vlan);
 
     QTAILQ_INSERT_TAIL(&vlans, vlan, next);
 
diff --git a/net.h b/net.h
index fa59c3d..e79f524 100644
--- a/net.h
+++ b/net.h
@@ -5,11 +5,10 @@
 #include "qemu-common.h"
 #include "qdict.h"
 #include "qemu-option.h"
+#include "net-queue.h"
 
 /* VLANs support */
 
-typedef struct VLANClientState VLANClientState;
-
 typedef int (NetCanReceive)(VLANClientState *);
 typedef ssize_t (NetReceive)(VLANClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(VLANClientState *, const struct iovec *, int);
@@ -34,25 +33,12 @@ struct VLANClientState {
     char info_str[256];
 };
 
-typedef struct VLANPacket VLANPacket;
-
-typedef void (NetPacketSent) (VLANClientState *, ssize_t);
-
-struct VLANPacket {
-    QTAILQ_ENTRY(VLANPacket) entry;
-    VLANClientState *sender;
-    int size;
-    NetPacketSent *sent_cb;
-    uint8_t data[0];
-};
-
 struct VLANState {
     int id;
     QTAILQ_HEAD(, VLANClientState) clients;
     QTAILQ_ENTRY(VLANState) next;
     unsigned int nb_guest_devs, nb_host_devs;
-    QTAILQ_HEAD(send_queue, VLANPacket) send_queue;
-    int delivering;
+    NetQueue *send_queue;
 };
 
 VLANState *qemu_find_vlan(int id, int allocate);
diff --git a/qemu-common.h b/qemu-common.h
index 12e7dd0..9ad2f0d 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -178,6 +178,7 @@ typedef struct TextConsole TextConsole;
 typedef TextConsole QEMUConsole;
 typedef struct CharDriverState CharDriverState;
 typedef struct VLANState VLANState;
+typedef struct VLANClientState VLANClientState;
 typedef struct QEMUFile QEMUFile;
 typedef struct i2c_bus i2c_bus;
 typedef struct i2c_slave i2c_slave;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH 16/16] net: add queue for peer-to-peer packet forwarding
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (14 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 15/16] net: refactor packet queueing code Mark McLoughlin
@ 2009-10-08 18:58 ` Mark McLoughlin
  2009-10-08 20:29 ` [Qemu-devel] [PATCH 00/16] Add a -netdev option Stefan Weil
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-08 18:58 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Now that we have re-factored the packet queue code, we can re-use
it for peer-to-peer also.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
 net.c |  111 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 net.h |    1 +
 2 files changed, 99 insertions(+), 13 deletions(-)

diff --git a/net.c b/net.c
index 2c7b2ef..ef40199 100644
--- a/net.c
+++ b/net.c
@@ -301,6 +301,15 @@ static char *assign_name(VLANClientState *vc1, const char *model)
     return qemu_strdup(buf);
 }
 
+static ssize_t qemu_deliver_packet(VLANClientState *sender,
+                                   const uint8_t *data,
+                                   size_t size,
+                                   void *opaque);
+static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
+                                       const struct iovec *iov,
+                                       int iovcnt,
+                                       void *opaque);
+
 VLANClientState *qemu_new_vlan_client(VLANState *vlan,
                                       VLANClientState *peer,
                                       const char *model,
@@ -336,6 +345,10 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
             peer->peer = vc;
         }
         QTAILQ_INSERT_TAIL(&non_vlan_clients, vc, next);
+
+        vc->send_queue = qemu_new_net_queue(qemu_deliver_packet,
+                                            qemu_deliver_packet_iov,
+                                            vc);
     }
 
     return vc;
@@ -346,6 +359,9 @@ void qemu_del_vlan_client(VLANClientState *vc)
     if (vc->vlan) {
         QTAILQ_REMOVE(&vc->vlan->clients, vc, next);
     } else {
+        if (vc->send_queue) {
+            qemu_del_net_queue(vc->send_queue);
+        }
         QTAILQ_REMOVE(&non_vlan_clients, vc, next);
         if (vc->peer) {
             vc->peer->peer = NULL;
@@ -405,6 +421,15 @@ int qemu_can_send_packet(VLANClientState *sender)
     VLANState *vlan = sender->vlan;
     VLANClientState *vc;
 
+    if (sender->peer) {
+        if (!sender->peer->can_receive ||
+            sender->peer->can_receive(sender->peer)) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
     if (!sender->vlan) {
         return 1;
     }
@@ -422,6 +447,20 @@ int qemu_can_send_packet(VLANClientState *sender)
     return 0;
 }
 
+static ssize_t qemu_deliver_packet(VLANClientState *sender,
+                                   const uint8_t *data,
+                                   size_t size,
+                                   void *opaque)
+{
+    VLANClientState *vc = opaque;
+
+    if (vc->link_down) {
+        return size;
+    }
+
+    return vc->receive(vc, data, size);
+}
+
 static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
                                         const uint8_t *buf,
                                         size_t size,
@@ -453,35 +492,56 @@ static ssize_t qemu_vlan_deliver_packet(VLANClientState *sender,
 
 void qemu_purge_queued_packets(VLANClientState *vc)
 {
-    if (!vc->vlan)
+    NetQueue *queue;
+
+    if (!vc->peer && !vc->vlan) {
         return;
+    }
 
-    qemu_net_queue_purge(vc->vlan->send_queue, vc);
+    if (vc->peer) {
+        queue = vc->peer->send_queue;
+    } else {
+        queue = vc->vlan->send_queue;
+    }
+
+    qemu_net_queue_purge(queue, vc);
 }
 
 void qemu_flush_queued_packets(VLANClientState *vc)
 {
-    if (!vc->vlan)
-        return;
+    NetQueue *queue;
 
-    qemu_net_queue_flush(vc->vlan->send_queue);
+    if (vc->vlan) {
+        queue = vc->vlan->send_queue;
+    } else {
+        queue = vc->send_queue;
+    }
+
+    qemu_net_queue_flush(queue);
 }
 
 ssize_t qemu_send_packet_async(VLANClientState *sender,
                                const uint8_t *buf, int size,
                                NetPacketSent *sent_cb)
 {
-    if (sender->link_down || !sender->vlan) {
-        return size;
-    }
+    NetQueue *queue;
 
 #ifdef DEBUG_NET
     printf("qemu_send_packet_async:\n");
     hex_dump(stdout, buf, size);
 #endif
 
-    return qemu_net_queue_send(sender->vlan->send_queue,
-                               sender, buf, size, sent_cb);
+    if (sender->link_down || (!sender->peer && !sender->vlan)) {
+        return size;
+    }
+
+    if (sender->peer) {
+        queue = sender->peer->send_queue;
+    } else {
+        queue = sender->vlan->send_queue;
+    }
+
+    return qemu_net_queue_send(queue, sender, buf, size, sent_cb);
 }
 
 void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
@@ -517,6 +577,24 @@ static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt)
     return offset;
 }
 
+static ssize_t qemu_deliver_packet_iov(VLANClientState *sender,
+                                       const struct iovec *iov,
+                                       int iovcnt,
+                                       void *opaque)
+{
+    VLANClientState *vc = opaque;
+
+    if (vc->link_down) {
+        return calc_iov_length(iov, iovcnt);
+    }
+
+    if (vc->receive_iov) {
+        return vc->receive_iov(vc, iov, iovcnt);
+    } else {
+        return vc_sendv_compat(vc, iov, iovcnt);
+    }
+}
+
 static ssize_t qemu_vlan_deliver_packet_iov(VLANClientState *sender,
                                             const struct iovec *iov,
                                             int iovcnt,
@@ -554,12 +632,19 @@ ssize_t qemu_sendv_packet_async(VLANClientState *sender,
                                 const struct iovec *iov, int iovcnt,
                                 NetPacketSent *sent_cb)
 {
-    if (sender->link_down || !sender->vlan) {
+    NetQueue *queue;
+
+    if (sender->link_down || (!sender->peer && !sender->vlan)) {
         return calc_iov_length(iov, iovcnt);
     }
 
-    return qemu_net_queue_send_iov(sender->vlan->send_queue,
-                                   sender, iov, iovcnt, sent_cb);
+    if (sender->peer) {
+        queue = sender->peer->send_queue;
+    } else {
+        queue = sender->vlan->send_queue;
+    }
+
+    return qemu_net_queue_send_iov(queue, sender, iov, iovcnt, sent_cb);
 }
 
 ssize_t
diff --git a/net.h b/net.h
index e79f524..439de2a 100644
--- a/net.h
+++ b/net.h
@@ -28,6 +28,7 @@ struct VLANClientState {
     QTAILQ_ENTRY(VLANClientState) next;
     struct VLANState *vlan;
     VLANClientState *peer;
+    NetQueue *send_queue;
     char *model;
     char *name;
     char info_str[256];
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (15 preceding siblings ...)
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 16/16] net: add queue for peer-to-peer packet forwarding Mark McLoughlin
@ 2009-10-08 20:29 ` Stefan Weil
  2009-10-08 21:37   ` Anthony Liguori
  2009-10-09  7:09   ` Mark McLoughlin
  2009-10-09 15:26 ` Anthony Liguori
  2009-11-10 15:44 ` Paul Brook
  18 siblings, 2 replies; 29+ messages in thread
From: Stefan Weil @ 2009-10-08 20:29 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

Mark McLoughlin schrieb:
> Hi,
>         Here's a series of patches which gets the ball rolling on adding
> a -netdev option.
>
>         The idea is to de-emphasise the vlan support, and instead make
> a nic directly connected to a host backend the default and recommended
> configuration. We want this because it is only with this configuration
> that we feasibly add optimizations like GSO support or vhost-net.
>
>         Where we're going is that rather '-net user -net nic' being the
> default, it would instead be:
>
>   -netdev user,id=default_slirp -device e1000,netdev=default_slirp
>
>         This patch series has a lot of this done, but there's still a
> significant TODO list including:
>
>   * qdev-ify the NICs so that we can use -device rather than '-net nic'
>     which Gerd has started looking at
>
>   * add hotplug equivalent to netdev - we should probably add a 'nic='
>     argument to -netdev for this to allow changing the backend without
>     changing the frontend
>
>   * 'info network' should list netdevs
>
>   * merging in GSO support from qemu-kvm.git, substantially cleaned up
>
>   * VLAN support should be implemented as just another network client,
>     but one which is connected to multiple backends and frontends
>
>   * re-naming e.g. VLANClientState to NetClient
>
>   * killing off NICInfo
>
>   * ...
>
>         I've given this series significant testing including building
> with all targets (really!), mingw, --disable-slirp, --enable-vde,
> without TUNSETSNDBUF and running with various nic models, backends,
> with both -net and -netdev, some different guests, hotplug, ... No
> doubt I've still managed to screw something up.
>
> Cheers,
> Mark.

Hi Mark,

today, qemu's ethernet devices are a fixed combination of
MAC (Media Access Controller) and PHY (Physical Layer).

Real hardware is different: the controllers provide a MAC,
and many provide a PHY, too, but all controllers allow
one or even several external PHY(s).

Most (or all?) controllers use the same standard interface
to address their PHY (internal or external), something
which is completely missing today in qemu.

A better solution would use separate code for MAC and
PHY, so the controllers could share common code for the
PHY.

Configuration of a different PHY should be possible,
so users can run a system emulation of different
MAC-PHY combinations.

In addition to the PHY type, a PHY needs attributes
(link speed and link status).

Maybe you can address these requirements in your
redesign.

Regards,
Stefan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 20:29 ` [Qemu-devel] [PATCH 00/16] Add a -netdev option Stefan Weil
@ 2009-10-08 21:37   ` Anthony Liguori
  2009-10-09  6:23     ` Edgar E. Iglesias
  2009-10-09  7:09   ` Mark McLoughlin
  1 sibling, 1 reply; 29+ messages in thread
From: Anthony Liguori @ 2009-10-08 21:37 UTC (permalink / raw)
  To: Stefan Weil; +Cc: Mark McLoughlin, qemu-devel

Stefan Weil wrote:
> Hi Mark,
>
> today, qemu's ethernet devices are a fixed combination of
> MAC (Media Access Controller) and PHY (Physical Layer).
>
> Real hardware is different: the controllers provide a MAC,
> and many provide a PHY, too, but all controllers allow
> one or even several external PHY(s).
>
> Most (or all?) controllers use the same standard interface
> to address their PHY (internal or external), something
> which is completely missing today in qemu.
>
> A better solution would use separate code for MAC and
> PHY, so the controllers could share common code for the
> PHY.
>
> Configuration of a different PHY should be possible,
> so users can run a system emulation of different
> MAC-PHY combinations.
>
> In addition to the PHY type, a PHY needs attributes
> (link speed and link status).
>   

But PHY doesn't really exist in the context of QEMU because virtualizing 
at the ethernet level.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 21:37   ` Anthony Liguori
@ 2009-10-09  6:23     ` Edgar E. Iglesias
  2009-10-09 17:33       ` Stefan Weil
  0 siblings, 1 reply; 29+ messages in thread
From: Edgar E. Iglesias @ 2009-10-09  6:23 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Mark McLoughlin

On Thu, Oct 08, 2009 at 04:37:41PM -0500, Anthony Liguori wrote:
> Stefan Weil wrote:
> > Hi Mark,
> >
> > today, qemu's ethernet devices are a fixed combination of
> > MAC (Media Access Controller) and PHY (Physical Layer).
> >
> > Real hardware is different: the controllers provide a MAC,
> > and many provide a PHY, too, but all controllers allow
> > one or even several external PHY(s).
> >
> > Most (or all?) controllers use the same standard interface
> > to address their PHY (internal or external), something
> > which is completely missing today in qemu.
> >
> > A better solution would use separate code for MAC and
> > PHY, so the controllers could share common code for the
> > PHY.
> >
> > Configuration of a different PHY should be possible,
> > so users can run a system emulation of different
> > MAC-PHY combinations.
> >
> > In addition to the PHY type, a PHY needs attributes
> > (link speed and link status).
> >   
> 
> But PHY doesn't really exist in the context of QEMU because virtualizing 
> at the ethernet level.

I think PHY's exist, at least with pure emulation.

Regarding the MII path I think you are right. But many if not most ethernet
controllers expose a way for software to directly communicate with PHY's
over MDIO. And software drivers usually read/write PHY registers to
check/change PHY related settings (speed, link status, duplex settings etc).

etraxfs_eth.c has a small dummy model of a PHY at the MDIO level. Enough to
fool software to think that's there is a one. Off-tree I've got at least 2
more controllers with emulated PHY's that are needed to please guest
software.

Cheers

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 20:29 ` [Qemu-devel] [PATCH 00/16] Add a -netdev option Stefan Weil
  2009-10-08 21:37   ` Anthony Liguori
@ 2009-10-09  7:09   ` Mark McLoughlin
  2009-10-09  8:41     ` Edgar E. Iglesias
  1 sibling, 1 reply; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-09  7:09 UTC (permalink / raw)
  To: Stefan Weil; +Cc: qemu-devel

Hi Stefan,

On Thu, 2009-10-08 at 22:29 +0200, Stefan Weil wrote:

> Hi Mark,
> 
> today, qemu's ethernet devices are a fixed combination of
> MAC (Media Access Controller) and PHY (Physical Layer).
> 
> Real hardware is different: the controllers provide a MAC,
> and many provide a PHY, too, but all controllers allow
> one or even several external PHY(s).
> 
> Most (or all?) controllers use the same standard interface
> to address their PHY (internal or external), something
> which is completely missing today in qemu.
> 
> A better solution would use separate code for MAC and
> PHY, so the controllers could share common code for the
> PHY.
> 
> Configuration of a different PHY should be possible,
> so users can run a system emulation of different
> MAC-PHY combinations.
> 
> In addition to the PHY type, a PHY needs attributes
> (link speed and link status).
> 
> Maybe you can address these requirements in your
> redesign.

Doesn't that sound like something purely for the device model itself, as
opposed to the core packet handling code?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-09  7:09   ` Mark McLoughlin
@ 2009-10-09  8:41     ` Edgar E. Iglesias
  0 siblings, 0 replies; 29+ messages in thread
From: Edgar E. Iglesias @ 2009-10-09  8:41 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

On Fri, Oct 09, 2009 at 08:09:35AM +0100, Mark McLoughlin wrote:
> Hi Stefan,
> 
> On Thu, 2009-10-08 at 22:29 +0200, Stefan Weil wrote:
> 
> > Hi Mark,
> > 
> > today, qemu's ethernet devices are a fixed combination of
> > MAC (Media Access Controller) and PHY (Physical Layer).
> > 
> > Real hardware is different: the controllers provide a MAC,
> > and many provide a PHY, too, but all controllers allow
> > one or even several external PHY(s).
> > 
> > Most (or all?) controllers use the same standard interface
> > to address their PHY (internal or external), something
> > which is completely missing today in qemu.
> > 
> > A better solution would use separate code for MAC and
> > PHY, so the controllers could share common code for the
> > PHY.
> > 
> > Configuration of a different PHY should be possible,
> > so users can run a system emulation of different
> > MAC-PHY combinations.
> > 
> > In addition to the PHY type, a PHY needs attributes
> > (link speed and link status).
> > 
> > Maybe you can address these requirements in your
> > redesign.
> 
> Doesn't that sound like something purely for the device model itself, as
> opposed to the core packet handling code?

Right, this kind of PHY emulation is purely for emulated control not
for packet data paths.

Cheers

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (16 preceding siblings ...)
  2009-10-08 20:29 ` [Qemu-devel] [PATCH 00/16] Add a -netdev option Stefan Weil
@ 2009-10-09 15:26 ` Anthony Liguori
  2009-10-10 19:26   ` Michael S. Tsirkin
  2009-11-10 15:44 ` Paul Brook
  18 siblings, 1 reply; 29+ messages in thread
From: Anthony Liguori @ 2009-10-09 15:26 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: Avi Kivity, qemu-devel, Michael S. Tsirkin

Hi Mark,

Mark McLoughlin wrote:
> Hi,
>         Here's a series of patches which gets the ball rolling on adding
> a -netdev option.
>
>         The idea is to de-emphasise the vlan support, and instead make
> a nic directly connected to a host backend the default and recommended
> configuration. We want this because it is only with this configuration
> that we feasibly add optimizations like GSO support or vhost-net.
>   

I think this series is a good first step.  I've looked through the 
patches and they all look pretty good.  I plan on pushing after some 
testing assuming noone objects in the interim.

With respect to moving forward, I wanted to bring up a couple of topics.

To eliminate VLANs, I think the reasonable approach is to implemented an 
emulated hub.  I'd suggest treating the hub like a device.  Instantiate 
it through qdev, support it via -device, etc.  I think it would even be 
reasonable to have it support a fixed number of ports.  I doubt there 
would be any compatibility issues emulating a 32-bit port hub, for instance.

The current syntax would become just a convenient short cut for the 
-netdev syntax along with creating a hub device for each vlan that gets 
instantiated.

I think merging vhost_net support will depend on finishing out the 
netdev work.  Logically, I think vhost_net is a netdev backend and we 
extend the netdev API to support async submission of packets (basically 
mirroring the virtio-net ABI).  In the case of a virtio-net front-end to 
a vhost_net backend, I think we special case that assuming we're running 
kvm.

Regards,

Anthony Liguori

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-09  6:23     ` Edgar E. Iglesias
@ 2009-10-09 17:33       ` Stefan Weil
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Weil @ 2009-10-09 17:33 UTC (permalink / raw)
  Cc: Edgar E. Iglesias, qemu-devel, Mark McLoughlin

Edgar E. Iglesias schrieb:
> On Thu, Oct 08, 2009 at 04:37:41PM -0500, Anthony Liguori wrote:
>   
>> Stefan Weil wrote:
>>     
>>> Hi Mark,
>>>
>>> today, qemu's ethernet devices are a fixed combination of
>>> MAC (Media Access Controller) and PHY (Physical Layer).
>>>
>>> Real hardware is different: the controllers provide a MAC,
>>> and many provide a PHY, too, but all controllers allow
>>> one or even several external PHY(s).
>>>
>>> Most (or all?) controllers use the same standard interface
>>> to address their PHY (internal or external), something
>>> which is completely missing today in qemu.
>>>
>>> A better solution would use separate code for MAC and
>>> PHY, so the controllers could share common code for the
>>> PHY.
>>>
>>> Configuration of a different PHY should be possible,
>>> so users can run a system emulation of different
>>> MAC-PHY combinations.
>>>
>>> In addition to the PHY type, a PHY needs attributes
>>> (link speed and link status).
>>>   
>>>       
>> But PHY doesn't really exist in the context of QEMU because virtualizing 
>> at the ethernet level.
>>     
>
> I think PHY's exist, at least with pure emulation.
>
> Regarding the MII path I think you are right. But many if not most ethernet
> controllers expose a way for software to directly communicate with PHY's
> over MDIO. And software drivers usually read/write PHY registers to
> check/change PHY related settings (speed, link status, duplex settings etc).
>
> etraxfs_eth.c has a small dummy model of a PHY at the MDIO level. Enough to
> fool software to think that's there is a one. Off-tree I've got at least 2
> more controllers with emulated PHY's that are needed to please guest
> software.
>
> Cheers

All other controllers do it the same way as etraxfs_eth.c.
And yes, most operating systems do read/write PHY registers.

PHY emulation needs code for the device model, and for
configuration (PHY type, link status (online / offline),
link speed (10, 100, 1000 Mbps), link type (half duplex,
full duplex). There is a 1:n relationship between MAC and PHY.

Maybe the link status is needed for the core packet handling,
too.

Cheers,
Stefan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-09 15:26 ` Anthony Liguori
@ 2009-10-10 19:26   ` Michael S. Tsirkin
  0 siblings, 0 replies; 29+ messages in thread
From: Michael S. Tsirkin @ 2009-10-10 19:26 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Mark McLoughlin, qemu-devel, Avi Kivity

On Fri, Oct 09, 2009 at 10:26:10AM -0500, Anthony Liguori wrote:
> Hi Mark,
>
> Mark McLoughlin wrote:
>> Hi,
>>         Here's a series of patches which gets the ball rolling on adding
>> a -netdev option.
>>
>>         The idea is to de-emphasise the vlan support, and instead make
>> a nic directly connected to a host backend the default and recommended
>> configuration. We want this because it is only with this configuration
>> that we feasibly add optimizations like GSO support or vhost-net.
>>   
>
> I think this series is a good first step.  I've looked through the  
> patches and they all look pretty good.  I plan on pushing after some  
> testing assuming noone objects in the interim.
>
> With respect to moving forward, I wanted to bring up a couple of topics.
>
> To eliminate VLANs, I think the reasonable approach is to implemented an  
> emulated hub.  I'd suggest treating the hub like a device.  Instantiate  
> it through qdev, support it via -device, etc.  I think it would even be  
> reasonable to have it support a fixed number of ports.  I doubt there  
> would be any compatibility issues emulating a 32-bit port hub, for 
> instance.
>
> The current syntax would become just a convenient short cut for the  
> -netdev syntax along with creating a hub device for each vlan that gets  
> instantiated.
>
> I think merging vhost_net support will depend on finishing out the  
> netdev work.

More importantly, we need interrupt injection from kvm merged.
We can have userspace poll vhost net and inject the interrupt,
but I think this defeats the purpose of the in-kernel backend.

> Logically, I think vhost_net is a netdev backend and we  
> extend the netdev API to support async submission of packets (basically  
> mirroring the virtio-net ABI).  In the case of a virtio-net front-end to  
> a vhost_net backend, I think we special case that assuming we're running  
> kvm.
>
> Regards,
>
> Anthony Liguori

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] Re: [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device
  2009-10-08 18:58 ` [Qemu-devel] [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device Mark McLoughlin
@ 2009-10-12 13:16   ` Gerd Hoffmann
  2009-10-12 13:22     ` Mark McLoughlin
  0 siblings, 1 reply; 29+ messages in thread
From: Gerd Hoffmann @ 2009-10-12 13:16 UTC (permalink / raw)
  To: Mark McLoughlin; +Cc: qemu-devel

On 10/08/09 20:58, Mark McLoughlin wrote:
> Without this, I'm seeing a segfault when unpluging a NIC.

Patch looks good.

I'm wondering I didn't see segfaults in my testing.  The bug doesn't 
look nic-specific.  Where does it crash?

cheers,
   Gerd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] Re: [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device
  2009-10-12 13:16   ` [Qemu-devel] " Gerd Hoffmann
@ 2009-10-12 13:22     ` Mark McLoughlin
  0 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-10-12 13:22 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Mon, 2009-10-12 at 15:16 +0200, Gerd Hoffmann wrote:
> On 10/08/09 20:58, Mark McLoughlin wrote:
> > Without this, I'm seeing a segfault when unpluging a NIC.
> 
> Patch looks good.
> 
> I'm wondering I didn't see segfaults in my testing.  The bug doesn't 
> look nic-specific.  Where does it crash?

I didn't investigate in great detail, but it looked like it crashed
while trying to iterate the list after the qdev_free()

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
                   ` (17 preceding siblings ...)
  2009-10-09 15:26 ` Anthony Liguori
@ 2009-11-10 15:44 ` Paul Brook
  2009-11-10 15:45   ` Mark McLoughlin
  18 siblings, 1 reply; 29+ messages in thread
From: Paul Brook @ 2009-11-10 15:44 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

On Thursday 08 October 2009, Mark McLoughlin wrote:
> Hi,
>         Here's a series of patches which gets the ball rolling on adding
> a -netdev option.
>...
>         The idea is to de-emphasise the vlan support, and instead make
> a nic directly connected to a host backend the default and recommended
> configuration. We want this because it is only with this configuration
> that we feasibly add optimizations like GSO support or vhost-net.

If we're going to introduce point-point connections then IMO everything should 
be a point-point connection. Having separate point-point and multiple-peer 
cases is just going to come back and bite us later.

Once you have a symmetric point-point API, negotiation of features (such as 
offload, filtering, etc) should be relatively straightforward.  Device 
creation and port connection should be separate events, with feature 
negotiation occurring at connection. This gives you hotplug for free, and 
avoids ordering issues.  vlan functionality is implemented via a fairly 
trivial hub device that has many ports and doesn't implement any of the fancy 
optional features.

Paul

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH 00/16] Add a -netdev option
  2009-11-10 15:44 ` Paul Brook
@ 2009-11-10 15:45   ` Mark McLoughlin
  0 siblings, 0 replies; 29+ messages in thread
From: Mark McLoughlin @ 2009-11-10 15:45 UTC (permalink / raw)
  To: Paul Brook; +Cc: qemu-devel

On Tue, 2009-11-10 at 15:44 +0000, Paul Brook wrote:
> On Thursday 08 October 2009, Mark McLoughlin wrote:
> > Hi,
> >         Here's a series of patches which gets the ball rolling on adding
> > a -netdev option.
> >...
> >         The idea is to de-emphasise the vlan support, and instead make
> > a nic directly connected to a host backend the default and recommended
> > configuration. We want this because it is only with this configuration
> > that we feasibly add optimizations like GSO support or vhost-net.
> 
> If we're going to introduce point-point connections then IMO everything should 
> be a point-point connection. Having separate point-point and multiple-peer 
> cases is just going to come back and bite us later.
> 
> Once you have a symmetric point-point API, negotiation of features (such as 
> offload, filtering, etc) should be relatively straightforward.  Device 
> creation and port connection should be separate events, with feature 
> negotiation occurring at connection. This gives you hotplug for free, and 
> avoids ordering issues.  vlan functionality is implemented via a fairly 
> trivial hub device that has many ports and doesn't implement any of the fancy 
> optional features.

Yep, that's roughly the plan.

Cheers,
Mark.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2009-11-10 15:48 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-10-08 18:58 [Qemu-devel] [PATCH 00/16] Add a -netdev option Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 01/16] slirp: fix !CONFIG_SLIRP compilation Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 02/16] hotplug: safely iterate bus's sibling list while removing a device Mark McLoughlin
2009-10-12 13:16   ` [Qemu-devel] " Gerd Hoffmann
2009-10-12 13:22     ` Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 03/16] net: pass monitor handle to client init functions Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 04/16] net: remove unused qemu_handler_true() Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 05/16] net: handle id= parameter for -net Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 06/16] net: remove id field from NICInfo Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 07/16] net: use qtailq for vlan and client lists Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 08/16] net: allow clients not associated with a vlan Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 09/16] net: add QemuOptsList arg to net_client_parse() Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 10/16] net: add -netdev option Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 11/16] net: handle -netdevice options Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 12/16] net: maintain a list of vlan-less clients Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 13/16] net: add -net nic,netdev= option Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 14/16] net: allow NICs to be connected to netdevs Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 15/16] net: refactor packet queueing code Mark McLoughlin
2009-10-08 18:58 ` [Qemu-devel] [PATCH 16/16] net: add queue for peer-to-peer packet forwarding Mark McLoughlin
2009-10-08 20:29 ` [Qemu-devel] [PATCH 00/16] Add a -netdev option Stefan Weil
2009-10-08 21:37   ` Anthony Liguori
2009-10-09  6:23     ` Edgar E. Iglesias
2009-10-09 17:33       ` Stefan Weil
2009-10-09  7:09   ` Mark McLoughlin
2009-10-09  8:41     ` Edgar E. Iglesias
2009-10-09 15:26 ` Anthony Liguori
2009-10-10 19:26   ` Michael S. Tsirkin
2009-11-10 15:44 ` Paul Brook
2009-11-10 15:45   ` Mark McLoughlin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).