All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/11] Various small networking improvements
@ 2009-04-19 10:04 Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add Jan Kiszka
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

This series fixes several smaller issues in the networking code and then
enhances it mostly by the following features:
 - VLAN capturing (derived from Tristan Gringold's work)
 - Handling of requested IP in slirp's DHCP server
 - Runtime -redir setup (host_net_redir)

The first three patches should be considered for stable, so I prepared a
corresponding queue at git://git.kiszka.org/qemu.git queues/stable.

Find this series also at git://git.kiszka.org/qemu.git queues/net

Jan Kiszka (11):
      net: Fix -net socket,listen
      net: Check device passed to host_net_remove
      net: Prevent multiple slirp instances
      monitor: Improve host_net_add
      monitor: Allow host_net_add/remove for all targets
      Allow empty params for check_params
      net: Add parameter checks for VLAN clients
      net: Untangle nested qemu_send_packet
      net: Add support for capturing VLANs
      slirp: Handle DHCP requests for specific IP
      slirp: Enhance host-guest redirection setup

 monitor.c       |    8 +-
 net.c           |  299 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 net.h           |   13 ++-
 qemu-options.hx |    9 ++-
 slirp/bootp.c   |  127 +++++++++++++++++------
 slirp/bootp.h   |    2 +
 vl.c            |    4 +-
 7 files changed, 395 insertions(+), 67 deletions(-)

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

* [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (4 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 05/11] monitor: Allow host_net_add/remove for all targets Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:37   ` Blue Swirl
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 09/11] net: Add support for capturing VLANs Jan Kiszka
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

The slirp stack is full of global variables which prevents instantiating
it more than once. Catch this during net_slirp_init to prevent more harm
later on.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index ff6230c..ca4d87f 100644
--- a/net.c
+++ b/net.c
@@ -519,15 +519,27 @@ static void slirp_receive(void *opaque, const uint8_t *buf, int size)
     slirp_input(buf, size);
 }
 
+static int slirp_in_use;
+
+static void net_slirp_cleanup(VLANClientState *vc)
+{
+    slirp_in_use = 0;
+}
+
 static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
 {
+    if (slirp_in_use) {
+        /* slirp only supports a single instance so far */
+        return -1;
+    }
     if (!slirp_inited) {
         slirp_inited = 1;
         slirp_init(slirp_restrict, slirp_ip);
     }
     slirp_vc = qemu_new_vlan_client(vlan, model, name,
-                                    slirp_receive, NULL, NULL, NULL);
+                                    slirp_receive, NULL, net_slirp_cleanup, NULL);
     slirp_vc->info_str[0] = '\0';
+    slirp_in_use = 1;
     return 0;
 }
 

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

* [Qemu-devel] [PATCH v2 02/11] net: Check device passed to host_net_remove
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 06/11] Allow empty params for check_params Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 01/11] net: Fix -net socket,listen Jan Kiszka
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Make sure that we do not delete guest NICs via host_net_remove.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/net.c b/net.c
index 77c5820..ff6230c 100644
--- a/net.c
+++ b/net.c
@@ -1858,14 +1858,20 @@ void net_host_device_remove(Monitor *mon, int vlan_id, const char *device)
 
     vlan = qemu_find_vlan(vlan_id);
 
-   for(vc = vlan->first_client; vc != NULL; vc = vc->next)
-        if (!strcmp(vc->name, device))
+    for (vc = vlan->first_client; vc != NULL; vc = vc->next) {
+        if (!strcmp(vc->name, device)) {
             break;
+        }
+    }
 
     if (!vc) {
         monitor_printf(mon, "can't find device %s\n", device);
         return;
     }
+    if (!net_host_check_device(vc->model)) {
+        monitor_printf(mon, "invalid host network device %s\n", device);
+        return;
+    }
     qemu_del_vlan_client(vc);
 }
 

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

* [Qemu-devel] [PATCH v2 01/11] net: Fix -net socket,listen
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (2 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 02/11] net: Check device passed to host_net_remove Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 05/11] monitor: Allow host_net_add/remove for all targets Jan Kiszka
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

In case no symbolic name is provided when requesting VLAN connection via
listening TCP socket ('-net socket,listen=...'), qemu crashes. This
fixes the cause.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index 3cd6277..77c5820 100644
--- a/net.c
+++ b/net.c
@@ -1472,7 +1472,7 @@ static int net_socket_listen_init(VLANState *vlan,
     }
     s->vlan = vlan;
     s->model = strdup(model);
-    s->name = strdup(name);
+    s->name = name ? strdup(name) : NULL;
     s->fd = fd;
     qemu_set_fd_handler(fd, net_socket_accept, NULL, s);
     return 0;

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

* [Qemu-devel] [PATCH v2 06/11] Allow empty params for check_params
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 02/11] net: Check device passed to host_net_remove Jan Kiszka
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 vl.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/vl.c b/vl.c
index 72ea0e4..00c9759 100644
--- a/vl.c
+++ b/vl.c
@@ -1934,7 +1934,7 @@ int check_params(char *buf, int buf_size,
     int i;
 
     p = str;
-    for(;;) {
+    while (*p != '\0') {
         p = get_opt_name(buf, buf_size, p);
         if (*p != '=')
             return -1;

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

* [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-28 15:08   ` Krumme, Chris
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 06/11] Allow empty params for check_params Jan Kiszka
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Fix the documentation of the host_net_add monitor command and allow the
user to pass no options at all. Moreover, inform the user on the
monitor terminal if a request failed.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c |    4 ++--
 net.c     |    4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/monitor.c b/monitor.c
index 652d1f0..ca2a56d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1730,8 +1730,8 @@ static const mon_cmd_t mon_cmds[] = {
                                         "add drive to PCI storage controller" },
     { "pci_add", "sss", pci_device_hot_add, "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
     { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
-    { "host_net_add", "ss", net_host_device_add,
-      "[tap,user,socket,vde] options", "add host VLAN client" },
+    { "host_net_add", "ss?", net_host_device_add,
+      "tap|user|socket|vde [options]", "add host VLAN client" },
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
 #endif
diff --git a/net.c b/net.c
index ca4d87f..22faa40 100644
--- a/net.c
+++ b/net.c
@@ -1860,7 +1860,9 @@ void net_host_device_add(Monitor *mon, const char *device, const char *opts)
         monitor_printf(mon, "invalid host network device %s\n", device);
         return;
     }
-    net_client_init(device, opts);
+    if (net_client_init(device, opts ? : "") < 0) {
+        monitor_printf(mon, "adding host network device %s failed\n", device);
+    }
 }
 
 void net_host_device_remove(Monitor *mon, int vlan_id, const char *device)

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

* [Qemu-devel] [PATCH v2 05/11] monitor: Allow host_net_add/remove for all targets
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (3 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 01/11] net: Fix -net socket,listen Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances Jan Kiszka
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

There is nothing x86-specific in host_net_add/remove, so allow them for
all targets.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/monitor.c b/monitor.c
index ca2a56d..e5991ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1730,11 +1730,11 @@ static const mon_cmd_t mon_cmds[] = {
                                         "add drive to PCI storage controller" },
     { "pci_add", "sss", pci_device_hot_add, "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
     { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
+#endif
     { "host_net_add", "ss?", net_host_device_add,
       "tap|user|socket|vde [options]", "add host VLAN client" },
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
-#endif
     { "balloon", "i", do_balloon,
       "target", "request VM to change it's memory allocation (in MB)" },
     { "set_link", "ss", do_set_link,

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

* [Qemu-devel] [PATCH v2 07/11] net: Add parameter checks for VLAN clients
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (7 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 10/11] slirp: Handle DHCP requests for specific IP Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 08/11] net: Untangle nested qemu_send_packet Jan Kiszka
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

This aims at helping the user to find typos or other mistakes in
parameter lists passed for VLAN client initialization. The existing
parsing infrastructure does not allow a leaner approach, but this is
better than nothing IMHO.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/net.c b/net.c
index 22faa40..1ee7504 100644
--- a/net.c
+++ b/net.c
@@ -1634,6 +1634,9 @@ void qemu_check_nic_model_list(NICInfo *nd, const char * const *models,
 
 int net_client_init(const char *device, const char *p)
 {
+    static const char * const fd_params[] = {
+        "vlan", "name", "fd", NULL
+    };
     char buf[1024];
     int vlan_id, ret;
     VLANState *vlan;
@@ -1649,10 +1652,18 @@ int net_client_init(const char *device, const char *p)
         name = strdup(buf);
     }
     if (!strcmp(device, "nic")) {
+        static const char * const nic_params[] = {
+            "vlan", "name", "macaddr", "model", NULL
+        };
         NICInfo *nd;
         uint8_t *macaddr;
         int idx = nic_get_free_idx();
 
+        if (check_params(buf, sizeof(buf), nic_params, p) < 0) {
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
+            return -1;
+        }
         if (idx == -1 || nb_nics >= MAX_NICS) {
             fprintf(stderr, "Too Many NICs\n");
             ret = -1;
@@ -1686,12 +1697,24 @@ int net_client_init(const char *device, const char *p)
         ret = idx;
     } else
     if (!strcmp(device, "none")) {
+        if (*p != '\0') {
+            fprintf(stderr, "qemu: 'none' takes no parameters\n");
+            return -1;
+        }
         /* does nothing. It is needed to signal that no network cards
            are wanted */
         ret = 0;
     } else
 #ifdef CONFIG_SLIRP
     if (!strcmp(device, "user")) {
+        static const char * const slirp_params[] = {
+            "vlan", "name", "hostname", "restrict", "ip", NULL
+        };
+        if (check_params(buf, sizeof(buf), slirp_params, p) < 0) {
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
+            return -1;
+        }
         if (get_param_value(buf, sizeof(buf), "hostname", p)) {
             pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf);
         }
@@ -1733,7 +1756,16 @@ int net_client_init(const char *device, const char *p)
 #endif
 #ifdef _WIN32
     if (!strcmp(device, "tap")) {
+        static const char * const tap_params[] = {
+            "vlan", "name", "ifname", NULL
+        };
         char ifname[64];
+
+        if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
+            return -1;
+        }
         if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
             fprintf(stderr, "tap: no interface name\n");
             ret = -1;
@@ -1750,11 +1782,24 @@ int net_client_init(const char *device, const char *p)
         int fd;
         vlan->nb_host_devs++;
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
+            if (check_params(buf, sizeof(buf), fd_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             fd = strtol(buf, NULL, 0);
             fcntl(fd, F_SETFL, O_NONBLOCK);
             net_tap_fd_init(vlan, device, name, fd);
             ret = 0;
         } else {
+            static const char * const tap_params[] = {
+                "vlan", "name", "ifname", "script", "downscript", NULL
+            };
+            if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
                 ifname[0] = '\0';
             }
@@ -1771,15 +1816,44 @@ int net_client_init(const char *device, const char *p)
     if (!strcmp(device, "socket")) {
         if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
             int fd;
+            if (check_params(buf, sizeof(buf), fd_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             fd = strtol(buf, NULL, 0);
             ret = -1;
             if (net_socket_fd_init(vlan, device, name, fd, 1))
                 ret = 0;
         } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) {
+            static const char * const listen_params[] = {
+                "vlan", "name", "listen", NULL
+            };
+            if (check_params(buf, sizeof(buf), listen_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             ret = net_socket_listen_init(vlan, device, name, buf);
         } else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) {
+            static const char * const connect_params[] = {
+                "vlan", "name", "connect", NULL
+            };
+            if (check_params(buf, sizeof(buf), connect_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             ret = net_socket_connect_init(vlan, device, name, buf);
         } else if (get_param_value(buf, sizeof(buf), "mcast", p) > 0) {
+            static const char * const mcast_params[] = {
+                "vlan", "name", "mcast", NULL
+            };
+            if (check_params(buf, sizeof(buf), mcast_params, p) < 0) {
+                fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                        buf, p);
+                return -1;
+            }
             ret = net_socket_mcast_init(vlan, device, name, buf);
         } else {
             fprintf(stderr, "Unknown socket options: %s\n", p);
@@ -1790,8 +1864,17 @@ int net_client_init(const char *device, const char *p)
     } else
 #ifdef CONFIG_VDE
     if (!strcmp(device, "vde")) {
+        static const char * const vde_params[] = {
+            "vlan", "name", "sock", "port", "group", "mode", NULL
+        };
         char vde_sock[1024], vde_group[512];
 	int vde_port, vde_mode;
+
+        if (check_params(buf, sizeof(buf), vde_params, p) < 0) {
+            fprintf(stderr, "qemu: invalid parameter '%s' in '%s'\n",
+                    buf, p);
+            return -1;
+        }
         vlan->nb_host_devs++;
         if (get_param_value(vde_sock, sizeof(vde_sock), "sock", p) <= 0) {
 	    vde_sock[0] = '\0';

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

* [Qemu-devel] [PATCH v2 10/11] slirp: Handle DHCP requests for specific IP
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (6 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 09/11] net: Add support for capturing VLANs Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 07/11] net: Add parameter checks for VLAN clients Jan Kiszka
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

This adds proper handling of the ciaddr field as well as the "Requested
IP Address" option to slirp's DHCP server. If the client requests an
invalid or used IP, a NAK reply is sent, if it requests a specific but
valid IP, this is now respected.

NAK'ing invalid IPs is specifically useful when changing the slirp IP
range via '-net user,ip=...' while the client saved its previously used
address and tries to reacquire it. Now this will be NAK'ed and the
client will start a new discovery round.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 slirp/bootp.c |  127 ++++++++++++++++++++++++++++++++++++++++++---------------
 slirp/bootp.h |    2 +
 2 files changed, 95 insertions(+), 34 deletions(-)

diff --git a/slirp/bootp.c b/slirp/bootp.c
index ca177f4..8a97660 100644
--- a/slirp/bootp.c
+++ b/slirp/bootp.c
@@ -66,6 +66,24 @@ static BOOTPClient *get_new_addr(struct in_addr *paddr)
     return bc;
 }
 
+static BOOTPClient *request_addr(const struct in_addr *paddr,
+                                 const uint8_t *macaddr)
+{
+    uint32_t req_addr = ntohl(paddr->s_addr);
+    uint32_t spec_addr = ntohl(special_addr.s_addr);
+    BOOTPClient *bc;
+
+    if (req_addr >= (spec_addr | START_ADDR) &&
+        req_addr < (spec_addr | (NB_ADDR + START_ADDR))) {
+        bc = &bootp_clients[(req_addr & 0xff) - START_ADDR];
+        if (!bc->allocated || !memcmp(macaddr, bc->macaddr, 6)) {
+            bc->allocated = 1;
+            return bc;
+        }
+    }
+    return NULL;
+}
+
 static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
 {
     BOOTPClient *bc;
@@ -83,18 +101,17 @@ static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
     return bc;
 }
 
-static void dhcp_decode(const uint8_t *buf, int size,
-                        int *pmsg_type)
+static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
+                        const struct in_addr **preq_addr)
 {
     const uint8_t *p, *p_end;
     int len, tag;
 
     *pmsg_type = 0;
+    *preq_addr = NULL;
 
-    p = buf;
-    p_end = buf + size;
-    if (size < 5)
-        return;
+    p = bp->bp_vend;
+    p_end = p + DHCP_OPT_LEN;
     if (memcmp(p, rfc1533_cookie, 4) != 0)
         return;
     p += 4;
@@ -109,34 +126,46 @@ static void dhcp_decode(const uint8_t *buf, int size,
             if (p >= p_end)
                 break;
             len = *p++;
-            dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
+            dprintf("dhcp: tag=%d len=%d\n", tag, len);
 
             switch(tag) {
             case RFC2132_MSG_TYPE:
                 if (len >= 1)
                     *pmsg_type = p[0];
                 break;
+            case RFC2132_REQ_ADDR:
+                if (len >= 4)
+                    *preq_addr = (struct in_addr *)p;
+                break;
             default:
                 break;
             }
             p += len;
         }
     }
+    if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) {
+        *preq_addr = &bp->bp_ciaddr;
+    }
 }
 
-static void bootp_reply(struct bootp_t *bp)
+static void bootp_reply(const struct bootp_t *bp)
 {
-    BOOTPClient *bc;
+    BOOTPClient *bc = NULL;
     struct mbuf *m;
     struct bootp_t *rbp;
     struct sockaddr_in saddr, daddr;
     struct in_addr dns_addr;
+    const struct in_addr *preq_addr;
     int dhcp_msg_type, val;
     uint8_t *q;
 
     /* extract exact DHCP msg type */
-    dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
-    dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
+    dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
+    dprintf("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
+    if (preq_addr)
+        dprintf(" req_addr=%08x\n", ntohl(preq_addr->s_addr));
+    else
+        dprintf("\n");
 
     if (dhcp_msg_type == 0)
         dhcp_msg_type = DHCPREQUEST; /* Force reply for old BOOTP clients */
@@ -155,13 +184,29 @@ static void bootp_reply(struct bootp_t *bp)
     memset(rbp, 0, sizeof(struct bootp_t));
 
     if (dhcp_msg_type == DHCPDISCOVER) {
-    new_addr:
-        bc = get_new_addr(&daddr.sin_addr);
+        if (preq_addr) {
+            bc = request_addr(preq_addr, client_ethaddr);
+            if (bc) {
+                daddr.sin_addr = *preq_addr;
+            }
+        }
         if (!bc) {
-            dprintf("no address left\n");
-            return;
+         new_addr:
+            bc = get_new_addr(&daddr.sin_addr);
+            if (!bc) {
+                dprintf("no address left\n");
+                return;
+            }
         }
         memcpy(bc->macaddr, client_ethaddr, 6);
+    } else if (preq_addr) {
+        bc = request_addr(preq_addr, client_ethaddr);
+        if (bc) {
+            daddr.sin_addr = *preq_addr;
+            memcpy(bc->macaddr, client_ethaddr, 6);
+        } else {
+            daddr.sin_addr.s_addr = 0;
+        }
     } else {
         bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
         if (!bc) {
@@ -171,12 +216,6 @@ static void bootp_reply(struct bootp_t *bp)
         }
     }
 
-    if (bootp_filename)
-        snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
-                 bootp_filename);
-
-    dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
-
     saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
     saddr.sin_port = htons(BOOTP_SERVER);
 
@@ -191,24 +230,29 @@ static void bootp_reply(struct bootp_t *bp)
     rbp->bp_yiaddr = daddr.sin_addr; /* Client IP address */
     rbp->bp_siaddr = saddr.sin_addr; /* Server IP address */
 
-    daddr.sin_addr.s_addr = 0xffffffffu;
-
     q = rbp->bp_vend;
     memcpy(q, rfc1533_cookie, 4);
     q += 4;
 
-    if (dhcp_msg_type == DHCPDISCOVER) {
-        *q++ = RFC2132_MSG_TYPE;
-        *q++ = 1;
-        *q++ = DHCPOFFER;
-    } else if (dhcp_msg_type == DHCPREQUEST) {
-        *q++ = RFC2132_MSG_TYPE;
-        *q++ = 1;
-        *q++ = DHCPACK;
-    }
+    if (bc) {
+        dprintf("%s addr=%08x\n",
+                (dhcp_msg_type == DHCPDISCOVER) ? "offered" : "ack'ed",
+                ntohl(daddr.sin_addr.s_addr));
+
+        if (dhcp_msg_type == DHCPDISCOVER) {
+            *q++ = RFC2132_MSG_TYPE;
+            *q++ = 1;
+            *q++ = DHCPOFFER;
+        } else /* DHCPREQUEST */ {
+            *q++ = RFC2132_MSG_TYPE;
+            *q++ = 1;
+            *q++ = DHCPACK;
+        }
+
+        if (bootp_filename)
+            snprintf((char *)rbp->bp_file, sizeof(rbp->bp_file), "%s",
+                     bootp_filename);
 
-    if (dhcp_msg_type == DHCPDISCOVER ||
-        dhcp_msg_type == DHCPREQUEST) {
         *q++ = RFC2132_SRV_ID;
         *q++ = 4;
         memcpy(q, &saddr.sin_addr, 4);
@@ -247,9 +291,24 @@ static void bootp_reply(struct bootp_t *bp)
             memcpy(q, slirp_hostname, val);
             q += val;
         }
+    } else {
+        static const char nak_msg[] = "requested address not available";
+
+        dprintf("nak'ed addr=%08x\n", ntohl(preq_addr->s_addr));
+
+        *q++ = RFC2132_MSG_TYPE;
+        *q++ = 1;
+        *q++ = DHCPNAK;
+
+        *q++ = RFC2132_MESSAGE;
+        *q++ = sizeof(nak_msg) - 1;
+        memcpy(q, nak_msg, sizeof(nak_msg) - 1);
+        q += sizeof(nak_msg) - 1;
     }
     *q++ = RFC1533_END;
 
+    daddr.sin_addr.s_addr = 0xffffffffu;
+
     m->m_len = sizeof(struct bootp_t) -
         sizeof(struct ip) - sizeof(struct udphdr);
     udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
diff --git a/slirp/bootp.h b/slirp/bootp.h
index e48f53f..3d80515 100644
--- a/slirp/bootp.h
+++ b/slirp/bootp.h
@@ -63,6 +63,7 @@
 #define RFC2132_MSG_TYPE	53
 #define RFC2132_SRV_ID		54
 #define RFC2132_PARAM_LIST	55
+#define RFC2132_MESSAGE		56
 #define RFC2132_MAX_SIZE	57
 #define RFC2132_RENEWAL_TIME    58
 #define RFC2132_REBIND_TIME     59
@@ -71,6 +72,7 @@
 #define DHCPOFFER		2
 #define DHCPREQUEST		3
 #define DHCPACK			5
+#define DHCPNAK			6
 
 #define RFC1533_VENDOR_MAJOR	0
 #define RFC1533_VENDOR_MINOR	0

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

* [Qemu-devel] [PATCH v2 09/11] net: Add support for capturing VLANs
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (5 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 10/11] slirp: Handle DHCP requests for specific IP Jan Kiszka
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

This patch is derived from Tristan Gingold's patch. It adds a new VLAN
client type that writes all traffic on the VLAN it is attached to into a
pcap file. Such a file can then be analyzed offline with Wireshark or
tcpdump.

Besides rebasing and some minor cleanups, the major differences to the
original version are:
 - support for enabling/disabling via the monitor (host_net_add/remove)
 - no special ordering of VLAN client list, qemu_send_packet now takes
   care of properly ordered packets
 - 64k default capturing limit (I hate tcpdump's default)

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c       |    2 -
 net.c           |  115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 qemu-options.hx |    7 +++
 3 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/monitor.c b/monitor.c
index e5991ff..0accded 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1732,7 +1732,7 @@ static const mon_cmd_t mon_cmds[] = {
     { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
 #endif
     { "host_net_add", "ss?", net_host_device_add,
-      "tap|user|socket|vde [options]", "add host VLAN client" },
+      "tap|user|socket|vde|dump [options]", "add host VLAN client" },
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
     { "balloon", "i", do_balloon,
diff --git a/net.c b/net.c
index 5156cc1..8d688a0 100644
--- a/net.c
+++ b/net.c
@@ -118,6 +118,7 @@
 #include "qemu-char.h"
 #include "audio/audio.h"
 #include "qemu_socket.h"
+#include "qemu-log.h"
 
 #if defined(CONFIG_SLIRP)
 #include "libslirp.h"
@@ -1594,6 +1595,106 @@ static int net_socket_mcast_init(VLANState *vlan,
 
 }
 
+typedef struct DumpState {
+    VLANClientState *pcap_vc;
+    int fd;
+    int pcap_caplen;
+} DumpState;
+
+#define PCAP_MAGIC 0xa1b2c3d4
+
+struct pcap_file_hdr {
+    uint32_t magic;
+    uint16_t version_major;
+    uint16_t version_minor;
+    int32_t thiszone;
+    uint32_t sigfigs;
+    uint32_t snaplen;
+    uint32_t linktype;
+};
+
+struct pcap_sf_pkthdr {
+    struct {
+        int32_t tv_sec;
+        int32_t tv_usec;
+    } ts;
+    uint32_t caplen;
+    uint32_t len;
+};
+
+static void dump_receive(void *opaque, const uint8_t *buf, int size)
+{
+    DumpState *s = opaque;
+    struct pcap_sf_pkthdr hdr;
+    int64_t ts;
+    int caplen;
+
+    /* Early return in case of previous error. */
+    if (s->fd < 0) {
+        return;
+    }
+
+    ts = muldiv64 (qemu_get_clock(vm_clock),1000000, ticks_per_sec);
+    caplen = size > s->pcap_caplen ? s->pcap_caplen : size;
+
+    hdr.ts.tv_sec = ts / 1000000000LL;
+    hdr.ts.tv_usec = ts % 1000000;
+    hdr.caplen = caplen;
+    hdr.len = size;
+    if (write(s->fd, &hdr, sizeof(hdr)) != sizeof(hdr) ||
+        write(s->fd, buf, caplen) != caplen) {
+        qemu_log("-net dump write error - stop dump\n");
+        close(s->fd);
+        s->fd = -1;
+    }
+}
+
+static void net_dump_cleanup(VLANClientState *vc)
+{
+    DumpState *s = vc->opaque;
+
+    close(s->fd);
+    qemu_free(s);
+}
+
+static int net_dump_init(VLANState *vlan, const char *device,
+                         const char *name, const char *filename, int len)
+{
+    struct pcap_file_hdr hdr;
+    DumpState *s;
+
+    s = qemu_malloc(sizeof(DumpState));
+
+    s->fd = open(filename, O_CREAT | O_WRONLY, 0644);
+    if (s->fd < 0) {
+        fprintf(stderr, "-net dump: can't open %s\n", filename);
+        return -1;
+    }
+
+    s->pcap_caplen = len;
+
+    hdr.magic = PCAP_MAGIC;
+    hdr.version_major = 2;
+    hdr.version_minor = 4;
+    hdr.thiszone = 0;
+    hdr.sigfigs = 0;
+    hdr.snaplen = s->pcap_caplen;
+    hdr.linktype = 1;
+
+    if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) {
+        perror("-net dump write error");
+        close(s->fd);
+        qemu_free(s);
+        return -1;
+    }
+
+    s->pcap_vc = qemu_new_vlan_client(vlan, device, name, 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);
+    return 0;
+}
+
 /* find or alloc a new VLAN */
 VLANState *qemu_find_vlan(int id)
 {
@@ -1919,7 +2020,17 @@ int net_client_init(const char *device, const char *p)
 	ret = net_vde_init(vlan, device, name, vde_sock, vde_port, vde_group, vde_mode);
     } else
 #endif
-    {
+    if (!strcmp(device, "dump")) {
+        int len = 65536;
+
+        if (get_param_value(buf, sizeof(buf), "len", p) > 0) {
+            len = strtol(buf, NULL, 0);
+        }
+        if (!get_param_value(buf, sizeof(buf), "file", p)) {
+            snprintf(buf, sizeof(buf), "qemu-vlan%d.pcap", vlan_id);
+        }
+        ret = net_dump_init(vlan, device, name, buf, len);
+    } else {
         fprintf(stderr, "Unknown network device: %s\n", device);
         ret = -1;
         goto out;
@@ -1944,7 +2055,7 @@ void net_client_uninit(NICInfo *nd)
 static int net_host_check_device(const char *device)
 {
     int i;
-    const char *valid_param_list[] = { "tap", "socket"
+    const char *valid_param_list[] = { "tap", "socket", "dump"
 #ifdef CONFIG_SLIRP
                                        ,"user"
 #endif
diff --git a/qemu-options.hx b/qemu-options.hx
index 4d15f9b..a29d1da 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -745,6 +745,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net, \
     "                Use group 'groupname' and mode 'octalmode' to change default\n"
     "                ownership and permissions for communication port.\n"
 #endif
+    "-net dump[,vlan=n][,file=f][,len=n]\n"
+    "                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")
 STEXI
@@ -865,6 +867,11 @@ vde_switch -F -sock /tmp/myswitch
 qemu linux.img -net nic -net vde,sock=/tmp/myswitch
 @end example
 
+@item -net dump[,vlan=@var{n}][,file=@var{file}][,len=@var{len}]
+Dump network traffic on VLAN @var{n} to file @var{file} (@file{qemu-vlan0.pcap} by default).
+At most @var{len} bytes (64k by default) per packet are stored. The file format is
+libpcap, so it can be analyzed with tools such as tcpdump or Wireshark.
+
 @item -net none
 Indicate that no network devices should be configured. It is used to
 override the default configuration (@option{-net nic -net user}) which

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

* [Qemu-devel] [PATCH v2 11/11] slirp: Enhance host-guest redirection setup
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (9 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 08/11] net: Untangle nested qemu_send_packet Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-21 20:55 ` [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Anthony Liguori
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Allow to establish a TCP/UDP connection redirection also via a monitor
command 'host_net_redir'. Moreover, assume TCP as connection type if
that parameter is omitted.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 monitor.c       |    4 ++++
 net.c           |   35 +++++++++++++++++++++--------------
 net.h           |    2 +-
 qemu-options.hx |    2 +-
 vl.c            |    2 +-
 5 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/monitor.c b/monitor.c
index 0accded..9f7fa70 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1735,6 +1735,10 @@ static const mon_cmd_t mon_cmds[] = {
       "tap|user|socket|vde|dump [options]", "add host VLAN client" },
     { "host_net_remove", "is", net_host_device_remove,
       "vlan_id name", "remove host VLAN client" },
+#ifdef CONFIG_SLIRP
+    { "host_net_redir", "s", net_slirp_redir,
+      "[tcp|udp]:host-port:[guest-host]:guest-port", "redirect TCP or UDP connections from host to guest (requires -net user)" },
+#endif
     { "balloon", "i", do_balloon,
       "target", "request VM to change it's memory allocation (in MB)" },
     { "set_link", "ss", do_set_link,
diff --git a/net.c b/net.c
index 8d688a0..db2f8d3 100644
--- a/net.c
+++ b/net.c
@@ -568,11 +568,11 @@ static int net_slirp_init(VLANState *vlan, const char *model, const char *name)
     return 0;
 }
 
-void net_slirp_redir(const char *redir_str)
+void net_slirp_redir(Monitor *mon, const char *redir_str)
 {
     int is_udp;
     char buf[256], *r;
-    const char *p;
+    const char *p, *errmsg;
     struct in_addr guest_addr;
     int host_port, guest_port;
 
@@ -583,41 +583,48 @@ void net_slirp_redir(const char *redir_str)
 
     p = redir_str;
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
-        goto fail;
-    if (!strcmp(buf, "tcp")) {
+        goto fail_syntax;
+    if (!strcmp(buf, "tcp") || buf[0] == '\0') {
         is_udp = 0;
     } else if (!strcmp(buf, "udp")) {
         is_udp = 1;
     } else {
-        goto fail;
+        goto fail_syntax;
     }
 
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
-        goto fail;
+        goto fail_syntax;
     host_port = strtol(buf, &r, 0);
     if (r == buf)
-        goto fail;
+        goto fail_syntax;
 
     if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
-        goto fail;
+        goto fail_syntax;
     if (buf[0] == '\0') {
         pstrcpy(buf, sizeof(buf), "10.0.2.15");
     }
     if (!inet_aton(buf, &guest_addr))
-        goto fail;
+        goto fail_syntax;
 
     guest_port = strtol(p, &r, 0);
     if (r == p)
-        goto fail;
+        goto fail_syntax;
 
     if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
-        fprintf(stderr, "qemu: could not set up redirection\n");
-        exit(1);
+        errmsg = "could not set up redirection\n";
+        goto fail;
     }
     return;
+
+ fail_syntax:
+    errmsg = "invalid redirection format\n";
  fail:
-    fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
-    exit(1);
+    if (mon) {
+        monitor_printf(mon, errmsg);
+    } else {
+        fprintf(stderr, "qemu: %s", errmsg);
+        exit(1);
+    }
 }
 
 #ifndef _WIN32
diff --git a/net.h b/net.h
index fe5ece7..cdf63a4 100644
--- a/net.h
+++ b/net.h
@@ -112,7 +112,7 @@ int net_client_init(const char *device, const char *p);
 void net_client_uninit(NICInfo *nd);
 int net_client_parse(const char *str);
 void net_slirp_smb(const char *exported_dir);
-void net_slirp_redir(const char *redir_str);
+void net_slirp_redir(Monitor *mon, const char *redir_str);
 void net_cleanup(void);
 int slirp_is_inited(void);
 void net_client_check(void);
diff --git a/qemu-options.hx b/qemu-options.hx
index a29d1da..42bf714 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -943,7 +943,7 @@ When using the user mode network stack, redirect incoming TCP or UDP
 connections to the host port @var{host-port} to the guest
 @var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
 is not specified, its value is 10.0.2.15 (default address given by the
-built-in DHCP server).
+built-in DHCP server). If no connection type is specified, TCP is used.
 
 For example, to redirect host X11 connection from screen 1 to guest
 screen 0, use the following:
diff --git a/vl.c b/vl.c
index 00c9759..3541781 100644
--- a/vl.c
+++ b/vl.c
@@ -4589,7 +4589,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_redir:
-                net_slirp_redir(optarg);
+                net_slirp_redir(NULL, optarg);
                 break;
 #endif
             case QEMU_OPTION_bt:

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

* [Qemu-devel] [PATCH v2 08/11] net: Untangle nested qemu_send_packet
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (8 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 07/11] net: Add parameter checks for VLAN clients Jan Kiszka
@ 2009-04-19 10:04 ` Jan Kiszka
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 11/11] slirp: Enhance host-guest redirection setup Jan Kiszka
  2009-04-21 20:55 ` [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Anthony Liguori
  11 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 10:04 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Queue packets that are send during an ongoing packet delivery. This
ensures that packets will always arrive in their logical order at each
client of a VLAN. Currently, slirp generates such immediate relies, and
e.g. packet-sniffing clients on the same VLAN may get confused.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |   36 ++++++++++++++++++++++++++++++------
 net.h |   11 +++++++++++
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/net.c b/net.c
index 1ee7504..5156cc1 100644
--- a/net.c
+++ b/net.c
@@ -402,22 +402,46 @@ int qemu_can_send_packet(VLANClientState *vc1)
     return 0;
 }
 
-void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
+static void
+qemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size)
 {
-    VLANState *vlan = vc1->vlan;
     VLANClientState *vc;
 
-    if (vc1->link_down)
+    for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) {
+        if (vc != sender && !vc->link_down) {
+            vc->fd_read(vc->opaque, buf, size);
+        }
+    }
+}
+
+void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size)
+{
+    VLANState *vlan = vc->vlan;
+    VLANPacket *packet;
+
+    if (vc->link_down)
         return;
 
 #ifdef DEBUG_NET
     printf("vlan %d send:\n", vlan->id);
     hex_dump(stdout, buf, size);
 #endif
-    for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
-        if (vc != vc1 && !vc->link_down) {
-            vc->fd_read(vc->opaque, buf, size);
+    if (vlan->delivering) {
+        packet = qemu_malloc(sizeof(VLANPacket) + size);
+        packet->next = vlan->send_queue;
+        packet->sender = vc;
+        packet->size = size;
+        memcpy(packet->data, buf, size);
+        vlan->send_queue = packet;
+    } else {
+        vlan->delivering = 1;
+        qemu_deliver_packet(vc, buf, size);
+        while ((packet = vlan->send_queue) != NULL) {
+            qemu_deliver_packet(packet->sender, packet->data, packet->size);
+            vlan->send_queue = packet->next;
+            qemu_free(packet);
         }
+        vlan->delivering = 0;
     }
 }
 
diff --git a/net.h b/net.h
index 413f705..fe5ece7 100644
--- a/net.h
+++ b/net.h
@@ -29,11 +29,22 @@ struct VLANClientState {
     char info_str[256];
 };
 
+typedef struct VLANPacket VLANPacket;
+
+struct VLANPacket {
+    struct VLANPacket *next;
+    VLANClientState *sender;
+    int size;
+    uint8_t data[0];
+};
+
 struct VLANState {
     int id;
     VLANClientState *first_client;
     struct VLANState *next;
     unsigned int nb_guest_devs, nb_host_devs;
+    VLANPacket *send_queue;
+    int delivering;
 };
 
 VLANState *qemu_find_vlan(int id);

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

* Re: [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances Jan Kiszka
@ 2009-04-19 10:37   ` Blue Swirl
  2009-04-19 11:51     ` [Qemu-devel] " Jan Kiszka
  0 siblings, 1 reply; 17+ messages in thread
From: Blue Swirl @ 2009-04-19 10:37 UTC (permalink / raw)
  To: qemu-devel

On 4/19/09, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> The slirp stack is full of global variables which prevents instantiating
>  it more than once. Catch this during net_slirp_init to prevent more harm
>  later on.

Alternatively the slirp stack could be taught to support multiple instances:
http://lists.gnu.org/archive/html/qemu-devel/2007-10/msg00470.html

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

* [Qemu-devel] Re: [PATCH v2 03/11] net: Prevent multiple slirp instances
  2009-04-19 10:37   ` Blue Swirl
@ 2009-04-19 11:51     ` Jan Kiszka
  0 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-19 11:51 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1042 bytes --]

Blue Swirl wrote:
> On 4/19/09, Jan Kiszka <jan.kiszka@siemens.com> wrote:
>> The slirp stack is full of global variables which prevents instantiating
>>  it more than once. Catch this during net_slirp_init to prevent more harm
>>  later on.
> 
> Alternatively the slirp stack could be taught to support multiple instances:
> http://lists.gnu.org/archive/html/qemu-devel/2007-10/msg00470.html
> 

For sure - and nice to know that there is a reference! But as your patch
demonstrates, it's a larger effort which comes with some risks of
regression. Therefore I didn't attack this in the first step.

My next to-do item /wrt slirp is making those special IPs and DHCP
ranges fully configurable (ie. dhcpserver=..., gateway=...,
dhcpstart=... etc.). Depending on how many lines I'll have to touch
anyway, I may append multi-instance support to this as well.

In the meantime, and specifically for stable, my patch is required to
catch breakages users can trigger when they do not know about this slirp
limitation.

Jan


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

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

* Re: [Qemu-devel] [PATCH v2 00/11] Various small networking improvements
  2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
                   ` (10 preceding siblings ...)
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 11/11] slirp: Enhance host-guest redirection setup Jan Kiszka
@ 2009-04-21 20:55 ` Anthony Liguori
  11 siblings, 0 replies; 17+ messages in thread
From: Anthony Liguori @ 2009-04-21 20:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Jan Kiszka wrote:
> This series fixes several smaller issues in the networking code and then
> enhances it mostly by the following features:
>  - VLAN capturing (derived from Tristan Gringold's work)
>  - Handling of requested IP in slirp's DHCP server
>  - Runtime -redir setup (host_net_redir)
>
> The first three patches should be considered for stable, so I prepared a
> corresponding queue at git://git.kiszka.org/qemu.git queues/stable.
>
> Find this series also at git://git.kiszka.org/qemu.git queues/net
>   
Applied all (including the first three to stable).  Thanks.

-- 
Regards,

Anthony Liguori

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

* RE: [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add
  2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add Jan Kiszka
@ 2009-04-28 15:08   ` Krumme, Chris
  2009-04-28 19:25     ` [Qemu-devel] [PATCH] net: Avoid gcc'ism in net_host_device_add Jan Kiszka
  0 siblings, 1 reply; 17+ messages in thread
From: Krumme, Chris @ 2009-04-28 15:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark McLoughlin

Sorry for the last comment, but I was out of town. 

> -----Original Message-----
> From: 
> qemu-devel-bounces+chris.krumme=windriver.com@nongnu.org 
> [mailto:qemu-devel-bounces+chris.krumme=windriver.com@nongnu.o
> rg] On Behalf Of Jan Kiszka
> Sent: Sunday, April 19, 2009 5:04 AM
> To: qemu-devel@nongnu.org
> Cc: Mark McLoughlin
> Subject: [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add
> 
> Fix the documentation of the host_net_add monitor command and 
> allow the
> user to pass no options at all. Moreover, inform the user on the
> monitor terminal if a request failed.
> 
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
> 
>  monitor.c |    4 ++--
>  net.c     |    4 +++-
>  2 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/monitor.c b/monitor.c
> index 652d1f0..ca2a56d 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -1730,8 +1730,8 @@ static const mon_cmd_t mon_cmds[] = {
>                                          "add drive to PCI 
> storage controller" },
>      { "pci_add", "sss", pci_device_hot_add, 
> "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage 
> [[vlan=n][,macaddr=addr][,model=type]] 
> [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
>      { "pci_del", "s", pci_device_hot_remove, 
> "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
> -    { "host_net_add", "ss", net_host_device_add,
> -      "[tap,user,socket,vde] options", "add host VLAN client" },
> +    { "host_net_add", "ss?", net_host_device_add,
> +      "tap|user|socket|vde [options]", "add host VLAN client" },
>      { "host_net_remove", "is", net_host_device_remove,
>        "vlan_id name", "remove host VLAN client" },
>  #endif
> diff --git a/net.c b/net.c
> index ca4d87f..22faa40 100644
> --- a/net.c
> +++ b/net.c
> @@ -1860,7 +1860,9 @@ void net_host_device_add(Monitor *mon, 
> const char *device, const char *opts)
>          monitor_printf(mon, "invalid host network device 
> %s\n", device);
>          return;
>      }
> -    net_client_init(device, opts);
> +    if (net_client_init(device, opts ? : "") < 0) {

Is this a gcc extension?  Do we want to introduce this construct to the
code base.

Thanks

Chris


> +        monitor_printf(mon, "adding host network device %s 
> failed\n", device);
> +    }
>  }
>  
>  void net_host_device_remove(Monitor *mon, int vlan_id, const 
> char *device)
> 
> 
> 
> 
> 

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

* [Qemu-devel] [PATCH] net: Avoid gcc'ism in net_host_device_add
  2009-04-28 15:08   ` Krumme, Chris
@ 2009-04-28 19:25     ` Jan Kiszka
  0 siblings, 0 replies; 17+ messages in thread
From: Jan Kiszka @ 2009-04-28 19:25 UTC (permalink / raw)
  To: Krumme, Chris; +Cc: Mark McLoughlin, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 3005 bytes --]

Krumme, Chris wrote:
> Sorry for the last comment, but I was out of town. 
> 
>> -----Original Message-----
>> From: 
>> qemu-devel-bounces+chris.krumme=windriver.com@nongnu.org 
>> [mailto:qemu-devel-bounces+chris.krumme=windriver.com@nongnu.o
>> rg] On Behalf Of Jan Kiszka
>> Sent: Sunday, April 19, 2009 5:04 AM
>> To: qemu-devel@nongnu.org
>> Cc: Mark McLoughlin
>> Subject: [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add
>>
>> Fix the documentation of the host_net_add monitor command and 
>> allow the
>> user to pass no options at all. Moreover, inform the user on the
>> monitor terminal if a request failed.
>>
>> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
>> ---
>>
>>  monitor.c |    4 ++--
>>  net.c     |    4 +++-
>>  2 files changed, 5 insertions(+), 3 deletions(-)
>>
>> diff --git a/monitor.c b/monitor.c
>> index 652d1f0..ca2a56d 100644
>> --- a/monitor.c
>> +++ b/monitor.c
>> @@ -1730,8 +1730,8 @@ static const mon_cmd_t mon_cmds[] = {
>>                                          "add drive to PCI 
>> storage controller" },
>>      { "pci_add", "sss", pci_device_hot_add, 
>> "pci_addr=auto|[[<domain>:]<bus>:]<slot> nic|storage 
>> [[vlan=n][,macaddr=addr][,model=type]] 
>> [file=file][,if=type][,bus=nr]...", "hot-add PCI device" },
>>      { "pci_del", "s", pci_device_hot_remove, 
>> "pci_addr=[[<domain>:]<bus>:]<slot>", "hot remove PCI device" },
>> -    { "host_net_add", "ss", net_host_device_add,
>> -      "[tap,user,socket,vde] options", "add host VLAN client" },
>> +    { "host_net_add", "ss?", net_host_device_add,
>> +      "tap|user|socket|vde [options]", "add host VLAN client" },
>>      { "host_net_remove", "is", net_host_device_remove,
>>        "vlan_id name", "remove host VLAN client" },
>>  #endif
>> diff --git a/net.c b/net.c
>> index ca4d87f..22faa40 100644
>> --- a/net.c
>> +++ b/net.c
>> @@ -1860,7 +1860,9 @@ void net_host_device_add(Monitor *mon, 
>> const char *device, const char *opts)
>>          monitor_printf(mon, "invalid host network device 
>> %s\n", device);
>>          return;
>>      }
>> -    net_client_init(device, opts);
>> +    if (net_client_init(device, opts ? : "") < 0) {
> 
> Is this a gcc extension?  Do we want to introduce this construct to the
> code base.

Valid remark, fix below.

Thanks,
Jan

-------->

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 net.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net.c b/net.c
index dcd27fe..ddcdf5b 100644
--- a/net.c
+++ b/net.c
@@ -2085,7 +2085,7 @@ void net_host_device_add(Monitor *mon, const char *device, const char *opts)
         monitor_printf(mon, "invalid host network device %s\n", device);
         return;
     }
-    if (net_client_init(device, opts ? : "") < 0) {
+    if (net_client_init(device, opts ? opts : "") < 0) {
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

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

end of thread, other threads:[~2009-04-28 19:26 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-04-19 10:04 [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 04/11] monitor: Improve host_net_add Jan Kiszka
2009-04-28 15:08   ` Krumme, Chris
2009-04-28 19:25     ` [Qemu-devel] [PATCH] net: Avoid gcc'ism in net_host_device_add Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 06/11] Allow empty params for check_params Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 02/11] net: Check device passed to host_net_remove Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 01/11] net: Fix -net socket,listen Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 05/11] monitor: Allow host_net_add/remove for all targets Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 03/11] net: Prevent multiple slirp instances Jan Kiszka
2009-04-19 10:37   ` Blue Swirl
2009-04-19 11:51     ` [Qemu-devel] " Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 09/11] net: Add support for capturing VLANs Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 10/11] slirp: Handle DHCP requests for specific IP Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 07/11] net: Add parameter checks for VLAN clients Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 08/11] net: Untangle nested qemu_send_packet Jan Kiszka
2009-04-19 10:04 ` [Qemu-devel] [PATCH v2 11/11] slirp: Enhance host-guest redirection setup Jan Kiszka
2009-04-21 20:55 ` [Qemu-devel] [PATCH v2 00/11] Various small networking improvements Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.