All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter
@ 2015-10-13 10:39 Thomas Huth
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function Thomas Huth
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:39 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

The "-net dump" option only works with the "-net" option. So far, it
is not possible to dump network traffic with the "-netdev" option yet.
This patch series now fixes this ugliness by enabling dumping for the
netdev devices via the new netfilter infrastructure from Yang Hongyang.
The dumping filter can be used like this for example:

 ppc64-softmmu/qemu-system-ppc64 -device virtio-net,netdev=mynet \
     -netdev user,id=mynet,tftp=/tmp/tftp,bootfile=zImage \
     -object filter-dump,id=f0,netdev=mynet,file=/tmp/dumpfile.dat

Changes in v2:
- Only rebased to master branch (to suit the final version of the
  netfilter patches that are now merged into master)

Thomas Huth (5):
  net/dump: Add support for receive_iov function
  net/dump: Rework net-dump init functions
  net/dump: Separate the NetClientState from the DumpState
  net/dump: Provide the dumping facility as a net filter
  options: Add documentation for filter-dump

 net/dump.c      | 228 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 qemu-options.hx |   8 ++
 vl.c            |   7 +-
 3 files changed, 212 insertions(+), 31 deletions(-)

-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
@ 2015-10-13 10:39 ` Thomas Huth
  2015-10-14  2:13   ` Yang Hongyang
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions Thomas Huth
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:39 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

Adding a proper receive_iov function to the net dump module.
This will make it easier to support the dump filter feature for
the -netdev option in later patches.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 net/dump.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/net/dump.c b/net/dump.c
index 08259af..aa0d45d 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -25,6 +25,7 @@
 #include "clients.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
+#include "qemu/iov.h"
 #include "qemu/log.h"
 #include "qemu/timer.h"
 #include "hub.h"
@@ -57,12 +58,15 @@ struct pcap_sf_pkthdr {
     uint32_t len;
 };
 
-static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
+                                int cnt)
 {
     DumpState *s = DO_UPCAST(DumpState, nc, nc);
     struct pcap_sf_pkthdr hdr;
     int64_t ts;
     int caplen;
+    size_t size = iov_size(iov, cnt);
+    struct iovec dumpiov[cnt + 1];
 
     /* Early return in case of previous error. */
     if (s->fd < 0) {
@@ -76,8 +80,12 @@ static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     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) {
+
+    dumpiov[0].iov_base = &hdr;
+    dumpiov[0].iov_len = sizeof(hdr);
+    cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, 0, caplen);
+
+    if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
         qemu_log("-net dump write error - stop dump\n");
         close(s->fd);
         s->fd = -1;
@@ -86,6 +94,15 @@ static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
     return size;
 }
 
+static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct iovec iov = {
+        .iov_base = (void *)buf,
+        .iov_len = size
+    };
+    return dump_receive_iov(nc, &iov, 1);
+}
+
 static void dump_cleanup(NetClientState *nc)
 {
     DumpState *s = DO_UPCAST(DumpState, nc, nc);
@@ -97,6 +114,7 @@ static NetClientInfo net_dump_info = {
     .type = NET_CLIENT_OPTIONS_KIND_DUMP,
     .size = sizeof(DumpState),
     .receive = dump_receive,
+    .receive_iov = dump_receive_iov,
     .cleanup = dump_cleanup,
 };
 
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function Thomas Huth
@ 2015-10-13 10:39 ` Thomas Huth
  2015-10-14  2:17   ` Yang Hongyang
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState Thomas Huth
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:39 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

Move the creation of the dump client from net_dump_init() into
net_init_dump(), so we can later use the former function for
dump via netfilter, too. Also rename net_dump_init() to
net_dump_state_init() to make it easier distinguishable from
net_init_dump().

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 net/dump.c | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/net/dump.c b/net/dump.c
index aa0d45d..e6f6be0 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -118,13 +118,10 @@ static NetClientInfo net_dump_info = {
     .cleanup = dump_cleanup,
 };
 
-static int net_dump_init(NetClientState *peer, const char *device,
-                         const char *name, const char *filename, int len,
-                         Error **errp)
+static int net_dump_state_init(DumpState *s, const char *filename,
+                               int len, Error **errp)
 {
     struct pcap_file_hdr hdr;
-    NetClientState *nc;
-    DumpState *s;
     struct tm tm;
     int fd;
 
@@ -148,13 +145,6 @@ static int net_dump_init(NetClientState *peer, const char *device,
         return -1;
     }
 
-    nc = qemu_new_net_client(&net_dump_info, peer, device, name);
-
-    snprintf(nc->info_str, sizeof(nc->info_str),
-             "dump to %s (len=%d)", filename, len);
-
-    s = DO_UPCAST(DumpState, nc, nc);
-
     s->fd = fd;
     s->pcap_caplen = len;
 
@@ -167,10 +157,11 @@ static int net_dump_init(NetClientState *peer, const char *device,
 int net_init_dump(const NetClientOptions *opts, const char *name,
                   NetClientState *peer, Error **errp)
 {
-    int len;
+    int len, rc;
     const char *file;
     char def_file[128];
     const NetdevDumpOptions *dump;
+    NetClientState *nc;
 
     assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
     dump = opts->dump;
@@ -200,5 +191,13 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
         len = 65536;
     }
 
-    return net_dump_init(peer, "dump", name, file, len, errp);
+    nc = qemu_new_net_client(&net_dump_info, peer, "dump", name);
+    snprintf(nc->info_str, sizeof(nc->info_str),
+             "dump to %s (len=%d)", file, len);
+
+    rc = net_dump_state_init(DO_UPCAST(DumpState, nc, nc), file, len, errp);
+    if (rc) {
+        qemu_del_net_client(nc);
+    }
+    return rc;
 }
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function Thomas Huth
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions Thomas Huth
@ 2015-10-13 10:40 ` Thomas Huth
  2015-10-14  2:23   ` Yang Hongyang
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter Thomas Huth
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:40 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

With the upcoming dumping-via-netfilter patch, the DumpState
should not be related to NetClientState anymore, so move the
related information to a new struct called DumpNetClient.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 net/dump.c | 74 +++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 49 insertions(+), 25 deletions(-)

diff --git a/net/dump.c b/net/dump.c
index e6f6be0..e3e82bd 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -31,7 +31,6 @@
 #include "hub.h"
 
 typedef struct DumpState {
-    NetClientState nc;
     int64_t start_ts;
     int fd;
     int pcap_caplen;
@@ -58,10 +57,8 @@ struct pcap_sf_pkthdr {
     uint32_t len;
 };
 
-static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
-                                int cnt)
+static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt)
 {
-    DumpState *s = DO_UPCAST(DumpState, nc, nc);
     struct pcap_sf_pkthdr hdr;
     int64_t ts;
     int caplen;
@@ -94,30 +91,12 @@ static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
     return size;
 }
 
-static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
-{
-    struct iovec iov = {
-        .iov_base = (void *)buf,
-        .iov_len = size
-    };
-    return dump_receive_iov(nc, &iov, 1);
-}
-
-static void dump_cleanup(NetClientState *nc)
+static void dump_cleanup(DumpState *s)
 {
-    DumpState *s = DO_UPCAST(DumpState, nc, nc);
-
     close(s->fd);
+    s->fd = -1;
 }
 
-static NetClientInfo net_dump_info = {
-    .type = NET_CLIENT_OPTIONS_KIND_DUMP,
-    .size = sizeof(DumpState),
-    .receive = dump_receive,
-    .receive_iov = dump_receive_iov,
-    .cleanup = dump_cleanup,
-};
-
 static int net_dump_state_init(DumpState *s, const char *filename,
                                int len, Error **errp)
 {
@@ -154,6 +133,49 @@ static int net_dump_state_init(DumpState *s, const char *filename,
     return 0;
 }
 
+/* Dumping via VLAN netclient */
+
+struct DumpNetClient {
+    NetClientState nc;
+    DumpState ds;
+};
+typedef struct DumpNetClient DumpNetClient;
+
+static ssize_t dumpclient_receive(NetClientState *nc, const uint8_t *buf,
+                                  size_t size)
+{
+    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
+    struct iovec iov = {
+        .iov_base = (void *)buf,
+        .iov_len = size
+    };
+
+    return dump_receive_iov(&dc->ds, &iov, 1);
+}
+
+static ssize_t dumpclient_receive_iov(NetClientState *nc,
+                                      const struct iovec *iov, int cnt)
+{
+    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
+
+    return dump_receive_iov(&dc->ds, iov, cnt);
+}
+
+static void dumpclient_cleanup(NetClientState *nc)
+{
+    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
+
+    dump_cleanup(&dc->ds);
+}
+
+static NetClientInfo net_dump_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_DUMP,
+    .size = sizeof(DumpNetClient),
+    .receive = dumpclient_receive,
+    .receive_iov = dumpclient_receive_iov,
+    .cleanup = dumpclient_cleanup,
+};
+
 int net_init_dump(const NetClientOptions *opts, const char *name,
                   NetClientState *peer, Error **errp)
 {
@@ -162,6 +184,7 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
     char def_file[128];
     const NetdevDumpOptions *dump;
     NetClientState *nc;
+    DumpNetClient *dnc;
 
     assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
     dump = opts->dump;
@@ -195,7 +218,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
     snprintf(nc->info_str, sizeof(nc->info_str),
              "dump to %s (len=%d)", file, len);
 
-    rc = net_dump_state_init(DO_UPCAST(DumpState, nc, nc), file, len, errp);
+    dnc = DO_UPCAST(DumpNetClient, nc, nc);
+    rc = net_dump_state_init(&dnc->ds, file, len, errp);
     if (rc) {
         qemu_del_net_client(nc);
     }
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
                   ` (2 preceding siblings ...)
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState Thomas Huth
@ 2015-10-13 10:40 ` Thomas Huth
  2015-10-14  2:42   ` Yang Hongyang
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 5/5] options: Add documentation for filter-dump Thomas Huth
  2015-10-20  4:35 ` [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Jason Wang
  5 siblings, 1 reply; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:40 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

Use the net-filter infrastructure to provide the dumping
functions for netdev devices, too.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 net/dump.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 vl.c       |   7 +++-
 2 files changed, 134 insertions(+), 2 deletions(-)

diff --git a/net/dump.c b/net/dump.c
index e3e82bd..dd0555f 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -28,7 +28,8 @@
 #include "qemu/iov.h"
 #include "qemu/log.h"
 #include "qemu/timer.h"
-#include "hub.h"
+#include "qapi/visitor.h"
+#include "net/filter.h"
 
 typedef struct DumpState {
     int64_t start_ts;
@@ -225,3 +226,129 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
     }
     return rc;
 }
+
+/* Dumping via filter */
+
+#define TYPE_FILTER_DUMP "filter-dump"
+
+#define FILTER_DUMP(obj) \
+    OBJECT_CHECK(NetFilterDumpState, (obj), TYPE_FILTER_DUMP)
+
+struct NetFilterDumpState {
+    NetFilterState nfs;
+    DumpState ds;
+    char *filename;
+    uint32_t maxlen;
+};
+typedef struct NetFilterDumpState NetFilterDumpState;
+
+static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
+                                       unsigned flags, const struct iovec *iov,
+                                       int iovcnt, NetPacketSent *sent_cb)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(nf);
+
+    dump_receive_iov(&nfds->ds, iov, iovcnt);
+    return 0;
+}
+
+static void filter_dump_cleanup(NetFilterState *nf)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(nf);
+
+    dump_cleanup(&nfds->ds);
+}
+
+static void filter_dump_setup(NetFilterState *nf, Error **errp)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(nf);
+
+    if (!nfds->filename) {
+        error_setg(errp, "dump filter needs 'file' property set!");
+        return;
+    }
+
+    net_dump_state_init(&nfds->ds, nfds->filename, nfds->maxlen, errp);
+}
+
+static void filter_dump_get_maxlen(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(obj);
+    uint32_t value = nfds->maxlen;
+
+    visit_type_uint32(v, &value, name, errp);
+}
+
+static void filter_dump_set_maxlen(Object *obj, Visitor *v, void *opaque,
+                                   const char *name, Error **errp)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(obj);
+    Error *local_err = NULL;
+    uint32_t value;
+
+    visit_type_uint32(v, &value, name, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    if (value == 0) {
+        error_setg(&local_err, "Property '%s.%s' doesn't take value '%u'",
+                   object_get_typename(obj), name, value);
+        goto out;
+    }
+    nfds->maxlen = value;
+
+out:
+    error_propagate(errp, local_err);
+}
+
+static char *file_dump_get_filename(Object *obj, Error **errp)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(obj);
+
+    return g_strdup(nfds->filename);
+}
+
+static void file_dump_set_filename(Object *obj, const char *value, Error **errp)
+{
+   NetFilterDumpState *nfds = FILTER_DUMP(obj);
+
+    g_free(nfds->filename);
+    nfds->filename = g_strdup(value);
+}
+
+static void filter_dump_instance_init(Object *obj)
+{
+    NetFilterDumpState *nfds = FILTER_DUMP(obj);
+
+    nfds->maxlen = 65536;
+
+    object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
+                        filter_dump_set_maxlen, NULL, NULL, NULL);
+    object_property_add_str(obj, "file", file_dump_get_filename,
+                            file_dump_set_filename, NULL);
+}
+
+static void filter_dump_class_init(ObjectClass *oc, void *data)
+{
+    NetFilterClass *nfc = NETFILTER_CLASS(oc);
+
+    nfc->setup = filter_dump_setup;
+    nfc->cleanup = filter_dump_cleanup;
+    nfc->receive_iov = filter_dump_receive_iov;
+}
+
+static const TypeInfo filter_dump_info = {
+    .name = TYPE_FILTER_DUMP,
+    .parent = TYPE_NETFILTER,
+    .class_init = filter_dump_class_init,
+    .instance_init = filter_dump_instance_init,
+    .instance_size = sizeof(NetFilterDumpState),
+};
+
+static void filter_dump_register_types(void)
+{
+    type_register_static(&filter_dump_info);
+}
+
+type_init(filter_dump_register_types);
diff --git a/vl.c b/vl.c
index 7c806a2..b54a800 100644
--- a/vl.c
+++ b/vl.c
@@ -2748,7 +2748,12 @@ static bool object_create_initial(const char *type)
         return false;
     }
 
-    if (g_str_equal(type, "filter-buffer")) {
+    /*
+     * return false for concrete netfilters since
+     * they depend on netdevs already existing
+     */
+    if (g_str_equal(type, "filter-buffer") ||
+        g_str_equal(type, "filter-dump")) {
         return false;
     }
 
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v2 5/5] options: Add documentation for filter-dump
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
                   ` (3 preceding siblings ...)
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter Thomas Huth
@ 2015-10-13 10:40 ` Thomas Huth
  2015-10-20  4:35 ` [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Jason Wang
  5 siblings, 0 replies; 11+ messages in thread
From: Thomas Huth @ 2015-10-13 10:40 UTC (permalink / raw)
  To: qemu-devel, jasowang; +Cc: yanghy, armbru, stefanha, mst

Add a short description for the filter-dump command line options.

Signed-off-by: Thomas Huth <thuth@redhat.com>
---
 qemu-options.hx | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index 2485b94..3ab753d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2012,6 +2012,7 @@ qemu -m 512 -object memory-backend-file,id=mem,size=512M,mem-path=/hugetlbfs,sha
 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.
+Note: For devices created with '-netdev', use '-object filter-dump,...' instead.
 
 @item -net none
 Indicate that no network devices should be configured. It is used to
@@ -3660,6 +3661,13 @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
 @option{tx}: the filter is attached to the transmit queue of the netdev,
              where it will receive packets sent by the netdev.
 
+@item -object filter-dump,id=@var{id},netdev=@var{dev},file=@var{filename}][,maxlen=@var{len}]
+
+Dump the network traffic on netdev @var{dev} to the file specified by
+@var{filename}. 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.
+
 @end table
 
 ETEXI
-- 
1.8.3.1

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

* Re: [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function Thomas Huth
@ 2015-10-14  2:13   ` Yang Hongyang
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Hongyang @ 2015-10-14  2:13 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, jasowang; +Cc: armbru, stefanha, mst



On 10/13/2015 06:39 PM, Thomas Huth wrote:
> Adding a proper receive_iov function to the net dump module.
> This will make it easier to support the dump filter feature for
> the -netdev option in later patches.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>

> ---
>   net/dump.c | 24 +++++++++++++++++++++---
>   1 file changed, 21 insertions(+), 3 deletions(-)
>
> diff --git a/net/dump.c b/net/dump.c
> index 08259af..aa0d45d 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -25,6 +25,7 @@
>   #include "clients.h"
>   #include "qemu-common.h"
>   #include "qemu/error-report.h"
> +#include "qemu/iov.h"
>   #include "qemu/log.h"
>   #include "qemu/timer.h"
>   #include "hub.h"
> @@ -57,12 +58,15 @@ struct pcap_sf_pkthdr {
>       uint32_t len;
>   };
>
> -static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
> +                                int cnt)
>   {
>       DumpState *s = DO_UPCAST(DumpState, nc, nc);
>       struct pcap_sf_pkthdr hdr;
>       int64_t ts;
>       int caplen;
> +    size_t size = iov_size(iov, cnt);
> +    struct iovec dumpiov[cnt + 1];
>
>       /* Early return in case of previous error. */
>       if (s->fd < 0) {
> @@ -76,8 +80,12 @@ static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
>       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) {
> +
> +    dumpiov[0].iov_base = &hdr;
> +    dumpiov[0].iov_len = sizeof(hdr);
> +    cnt = iov_copy(&dumpiov[1], cnt, iov, cnt, 0, caplen);
> +
> +    if (writev(s->fd, dumpiov, cnt + 1) != sizeof(hdr) + caplen) {
>           qemu_log("-net dump write error - stop dump\n");
>           close(s->fd);
>           s->fd = -1;
> @@ -86,6 +94,15 @@ static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
>       return size;
>   }
>
> +static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +{
> +    struct iovec iov = {
> +        .iov_base = (void *)buf,
> +        .iov_len = size
> +    };
> +    return dump_receive_iov(nc, &iov, 1);
> +}
> +
>   static void dump_cleanup(NetClientState *nc)
>   {
>       DumpState *s = DO_UPCAST(DumpState, nc, nc);
> @@ -97,6 +114,7 @@ static NetClientInfo net_dump_info = {
>       .type = NET_CLIENT_OPTIONS_KIND_DUMP,
>       .size = sizeof(DumpState),
>       .receive = dump_receive,
> +    .receive_iov = dump_receive_iov,
>       .cleanup = dump_cleanup,
>   };
>
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions
  2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions Thomas Huth
@ 2015-10-14  2:17   ` Yang Hongyang
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Hongyang @ 2015-10-14  2:17 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, jasowang; +Cc: armbru, stefanha, mst


On 10/13/2015 06:39 PM, Thomas Huth wrote:
> Move the creation of the dump client from net_dump_init() into
> net_init_dump(), so we can later use the former function for
> dump via netfilter, too. Also rename net_dump_init() to
> net_dump_state_init() to make it easier distinguishable from
> net_init_dump().
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>


Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>

> ---
>   net/dump.c | 27 +++++++++++++--------------
>   1 file changed, 13 insertions(+), 14 deletions(-)
>
> diff --git a/net/dump.c b/net/dump.c
> index aa0d45d..e6f6be0 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -118,13 +118,10 @@ static NetClientInfo net_dump_info = {
>       .cleanup = dump_cleanup,
>   };
>
> -static int net_dump_init(NetClientState *peer, const char *device,
> -                         const char *name, const char *filename, int len,
> -                         Error **errp)
> +static int net_dump_state_init(DumpState *s, const char *filename,
> +                               int len, Error **errp)
>   {
>       struct pcap_file_hdr hdr;
> -    NetClientState *nc;
> -    DumpState *s;
>       struct tm tm;
>       int fd;
>
> @@ -148,13 +145,6 @@ static int net_dump_init(NetClientState *peer, const char *device,
>           return -1;
>       }
>
> -    nc = qemu_new_net_client(&net_dump_info, peer, device, name);
> -
> -    snprintf(nc->info_str, sizeof(nc->info_str),
> -             "dump to %s (len=%d)", filename, len);
> -
> -    s = DO_UPCAST(DumpState, nc, nc);
> -
>       s->fd = fd;
>       s->pcap_caplen = len;
>
> @@ -167,10 +157,11 @@ static int net_dump_init(NetClientState *peer, const char *device,
>   int net_init_dump(const NetClientOptions *opts, const char *name,
>                     NetClientState *peer, Error **errp)
>   {
> -    int len;
> +    int len, rc;
>       const char *file;
>       char def_file[128];
>       const NetdevDumpOptions *dump;
> +    NetClientState *nc;
>
>       assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
>       dump = opts->dump;
> @@ -200,5 +191,13 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
>           len = 65536;
>       }
>
> -    return net_dump_init(peer, "dump", name, file, len, errp);
> +    nc = qemu_new_net_client(&net_dump_info, peer, "dump", name);
> +    snprintf(nc->info_str, sizeof(nc->info_str),
> +             "dump to %s (len=%d)", file, len);
> +
> +    rc = net_dump_state_init(DO_UPCAST(DumpState, nc, nc), file, len, errp);
> +    if (rc) {
> +        qemu_del_net_client(nc);
> +    }
> +    return rc;
>   }
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState Thomas Huth
@ 2015-10-14  2:23   ` Yang Hongyang
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Hongyang @ 2015-10-14  2:23 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, jasowang; +Cc: armbru, stefanha, mst



On 10/13/2015 06:40 PM, Thomas Huth wrote:
> With the upcoming dumping-via-netfilter patch, the DumpState
> should not be related to NetClientState anymore, so move the
> related information to a new struct called DumpNetClient.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>

> ---
>   net/dump.c | 74 +++++++++++++++++++++++++++++++++++++++++---------------------
>   1 file changed, 49 insertions(+), 25 deletions(-)
>
> diff --git a/net/dump.c b/net/dump.c
> index e6f6be0..e3e82bd 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -31,7 +31,6 @@
>   #include "hub.h"
>
>   typedef struct DumpState {
> -    NetClientState nc;
>       int64_t start_ts;
>       int fd;
>       int pcap_caplen;
> @@ -58,10 +57,8 @@ struct pcap_sf_pkthdr {
>       uint32_t len;
>   };
>
> -static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
> -                                int cnt)
> +static ssize_t dump_receive_iov(DumpState *s, const struct iovec *iov, int cnt)
>   {
> -    DumpState *s = DO_UPCAST(DumpState, nc, nc);
>       struct pcap_sf_pkthdr hdr;
>       int64_t ts;
>       int caplen;
> @@ -94,30 +91,12 @@ static ssize_t dump_receive_iov(NetClientState *nc, const struct iovec *iov,
>       return size;
>   }
>
> -static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> -{
> -    struct iovec iov = {
> -        .iov_base = (void *)buf,
> -        .iov_len = size
> -    };
> -    return dump_receive_iov(nc, &iov, 1);
> -}
> -
> -static void dump_cleanup(NetClientState *nc)
> +static void dump_cleanup(DumpState *s)
>   {
> -    DumpState *s = DO_UPCAST(DumpState, nc, nc);
> -
>       close(s->fd);
> +    s->fd = -1;
>   }
>
> -static NetClientInfo net_dump_info = {
> -    .type = NET_CLIENT_OPTIONS_KIND_DUMP,
> -    .size = sizeof(DumpState),
> -    .receive = dump_receive,
> -    .receive_iov = dump_receive_iov,
> -    .cleanup = dump_cleanup,
> -};
> -
>   static int net_dump_state_init(DumpState *s, const char *filename,
>                                  int len, Error **errp)
>   {
> @@ -154,6 +133,49 @@ static int net_dump_state_init(DumpState *s, const char *filename,
>       return 0;
>   }
>
> +/* Dumping via VLAN netclient */
> +
> +struct DumpNetClient {
> +    NetClientState nc;
> +    DumpState ds;
> +};
> +typedef struct DumpNetClient DumpNetClient;
> +
> +static ssize_t dumpclient_receive(NetClientState *nc, const uint8_t *buf,
> +                                  size_t size)
> +{
> +    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
> +    struct iovec iov = {
> +        .iov_base = (void *)buf,
> +        .iov_len = size
> +    };
> +
> +    return dump_receive_iov(&dc->ds, &iov, 1);
> +}
> +
> +static ssize_t dumpclient_receive_iov(NetClientState *nc,
> +                                      const struct iovec *iov, int cnt)
> +{
> +    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
> +
> +    return dump_receive_iov(&dc->ds, iov, cnt);
> +}
> +
> +static void dumpclient_cleanup(NetClientState *nc)
> +{
> +    DumpNetClient *dc = DO_UPCAST(DumpNetClient, nc, nc);
> +
> +    dump_cleanup(&dc->ds);
> +}
> +
> +static NetClientInfo net_dump_info = {
> +    .type = NET_CLIENT_OPTIONS_KIND_DUMP,
> +    .size = sizeof(DumpNetClient),
> +    .receive = dumpclient_receive,
> +    .receive_iov = dumpclient_receive_iov,
> +    .cleanup = dumpclient_cleanup,
> +};
> +
>   int net_init_dump(const NetClientOptions *opts, const char *name,
>                     NetClientState *peer, Error **errp)
>   {
> @@ -162,6 +184,7 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
>       char def_file[128];
>       const NetdevDumpOptions *dump;
>       NetClientState *nc;
> +    DumpNetClient *dnc;
>
>       assert(opts->kind == NET_CLIENT_OPTIONS_KIND_DUMP);
>       dump = opts->dump;
> @@ -195,7 +218,8 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
>       snprintf(nc->info_str, sizeof(nc->info_str),
>                "dump to %s (len=%d)", file, len);
>
> -    rc = net_dump_state_init(DO_UPCAST(DumpState, nc, nc), file, len, errp);
> +    dnc = DO_UPCAST(DumpNetClient, nc, nc);
> +    rc = net_dump_state_init(&dnc->ds, file, len, errp);
>       if (rc) {
>           qemu_del_net_client(nc);
>       }
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter Thomas Huth
@ 2015-10-14  2:42   ` Yang Hongyang
  0 siblings, 0 replies; 11+ messages in thread
From: Yang Hongyang @ 2015-10-14  2:42 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel, jasowang; +Cc: armbru, stefanha, mst



On 10/13/2015 06:40 PM, Thomas Huth wrote:
> Use the net-filter infrastructure to provide the dumping
> functions for netdev devices, too.
>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Reviewed-by: Yang Hongyang <yanghy@cn.fujitsu.com>


> ---
>   net/dump.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>   vl.c       |   7 +++-
>   2 files changed, 134 insertions(+), 2 deletions(-)
>
> diff --git a/net/dump.c b/net/dump.c
> index e3e82bd..dd0555f 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -28,7 +28,8 @@
>   #include "qemu/iov.h"
>   #include "qemu/log.h"
>   #include "qemu/timer.h"
> -#include "hub.h"
> +#include "qapi/visitor.h"
> +#include "net/filter.h"
>
>   typedef struct DumpState {
>       int64_t start_ts;
> @@ -225,3 +226,129 @@ int net_init_dump(const NetClientOptions *opts, const char *name,
>       }
>       return rc;
>   }
> +
> +/* Dumping via filter */
> +
> +#define TYPE_FILTER_DUMP "filter-dump"
> +
> +#define FILTER_DUMP(obj) \
> +    OBJECT_CHECK(NetFilterDumpState, (obj), TYPE_FILTER_DUMP)
> +
> +struct NetFilterDumpState {
> +    NetFilterState nfs;
> +    DumpState ds;
> +    char *filename;
> +    uint32_t maxlen;
> +};
> +typedef struct NetFilterDumpState NetFilterDumpState;
> +
> +static ssize_t filter_dump_receive_iov(NetFilterState *nf, NetClientState *sndr,
> +                                       unsigned flags, const struct iovec *iov,
> +                                       int iovcnt, NetPacketSent *sent_cb)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(nf);
> +
> +    dump_receive_iov(&nfds->ds, iov, iovcnt);
> +    return 0;
> +}
> +
> +static void filter_dump_cleanup(NetFilterState *nf)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(nf);
> +
> +    dump_cleanup(&nfds->ds);
> +}
> +
> +static void filter_dump_setup(NetFilterState *nf, Error **errp)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(nf);
> +
> +    if (!nfds->filename) {
> +        error_setg(errp, "dump filter needs 'file' property set!");
> +        return;
> +    }
> +
> +    net_dump_state_init(&nfds->ds, nfds->filename, nfds->maxlen, errp);
> +}
> +
> +static void filter_dump_get_maxlen(Object *obj, Visitor *v, void *opaque,
> +                                   const char *name, Error **errp)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(obj);
> +    uint32_t value = nfds->maxlen;
> +
> +    visit_type_uint32(v, &value, name, errp);
> +}
> +
> +static void filter_dump_set_maxlen(Object *obj, Visitor *v, void *opaque,
> +                                   const char *name, Error **errp)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(obj);
> +    Error *local_err = NULL;
> +    uint32_t value;
> +
> +    visit_type_uint32(v, &value, name, &local_err);
> +    if (local_err) {
> +        goto out;
> +    }
> +    if (value == 0) {
> +        error_setg(&local_err, "Property '%s.%s' doesn't take value '%u'",
> +                   object_get_typename(obj), name, value);
> +        goto out;
> +    }
> +    nfds->maxlen = value;
> +
> +out:
> +    error_propagate(errp, local_err);
> +}
> +
> +static char *file_dump_get_filename(Object *obj, Error **errp)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(obj);
> +
> +    return g_strdup(nfds->filename);
> +}
> +
> +static void file_dump_set_filename(Object *obj, const char *value, Error **errp)
> +{
> +   NetFilterDumpState *nfds = FILTER_DUMP(obj);
> +
> +    g_free(nfds->filename);
> +    nfds->filename = g_strdup(value);
> +}
> +
> +static void filter_dump_instance_init(Object *obj)
> +{
> +    NetFilterDumpState *nfds = FILTER_DUMP(obj);
> +
> +    nfds->maxlen = 65536;
> +
> +    object_property_add(obj, "maxlen", "int", filter_dump_get_maxlen,
> +                        filter_dump_set_maxlen, NULL, NULL, NULL);
> +    object_property_add_str(obj, "file", file_dump_get_filename,
> +                            file_dump_set_filename, NULL);
> +}
> +
> +static void filter_dump_class_init(ObjectClass *oc, void *data)
> +{
> +    NetFilterClass *nfc = NETFILTER_CLASS(oc);
> +
> +    nfc->setup = filter_dump_setup;
> +    nfc->cleanup = filter_dump_cleanup;
> +    nfc->receive_iov = filter_dump_receive_iov;
> +}
> +
> +static const TypeInfo filter_dump_info = {
> +    .name = TYPE_FILTER_DUMP,
> +    .parent = TYPE_NETFILTER,
> +    .class_init = filter_dump_class_init,
> +    .instance_init = filter_dump_instance_init,
> +    .instance_size = sizeof(NetFilterDumpState),
> +};
> +
> +static void filter_dump_register_types(void)
> +{
> +    type_register_static(&filter_dump_info);
> +}
> +
> +type_init(filter_dump_register_types);
> diff --git a/vl.c b/vl.c
> index 7c806a2..b54a800 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2748,7 +2748,12 @@ static bool object_create_initial(const char *type)
>           return false;
>       }
>
> -    if (g_str_equal(type, "filter-buffer")) {
> +    /*
> +     * return false for concrete netfilters since
> +     * they depend on netdevs already existing
> +     */
> +    if (g_str_equal(type, "filter-buffer") ||
> +        g_str_equal(type, "filter-dump")) {
>           return false;
>       }
>
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter
  2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
                   ` (4 preceding siblings ...)
  2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 5/5] options: Add documentation for filter-dump Thomas Huth
@ 2015-10-20  4:35 ` Jason Wang
  5 siblings, 0 replies; 11+ messages in thread
From: Jason Wang @ 2015-10-20  4:35 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel; +Cc: yanghy, armbru, stefanha, mst



On 10/13/2015 06:39 PM, Thomas Huth wrote:
> The "-net dump" option only works with the "-net" option. So far, it
> is not possible to dump network traffic with the "-netdev" option yet.
> This patch series now fixes this ugliness by enabling dumping for the
> netdev devices via the new netfilter infrastructure from Yang Hongyang.
> The dumping filter can be used like this for example:
>
>  ppc64-softmmu/qemu-system-ppc64 -device virtio-net,netdev=mynet \
>      -netdev user,id=mynet,tftp=/tmp/tftp,bootfile=zImage \
>      -object filter-dump,id=f0,netdev=mynet,file=/tmp/dumpfile.dat
>
> Changes in v2:
> - Only rebased to master branch (to suit the final version of the
>   netfilter patches that are now merged into master)
>
> Thomas Huth (5):
>   net/dump: Add support for receive_iov function
>   net/dump: Rework net-dump init functions
>   net/dump: Separate the NetClientState from the DumpState
>   net/dump: Provide the dumping facility as a net filter
>   options: Add documentation for filter-dump
>
>  net/dump.c      | 228 ++++++++++++++++++++++++++++++++++++++++++++++++--------
>  qemu-options.hx |   8 ++
>  vl.c            |   7 +-
>  3 files changed, 212 insertions(+), 31 deletions(-)
>

Applied in https://github.com/jasowang/qemu/commits/net

Thanks.

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

end of thread, other threads:[~2015-10-20  4:35 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-13 10:39 [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Thomas Huth
2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 1/5] net/dump: Add support for receive_iov function Thomas Huth
2015-10-14  2:13   ` Yang Hongyang
2015-10-13 10:39 ` [Qemu-devel] [PATCH v2 2/5] net/dump: Rework net-dump init functions Thomas Huth
2015-10-14  2:17   ` Yang Hongyang
2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 3/5] net/dump: Separate the NetClientState from the DumpState Thomas Huth
2015-10-14  2:23   ` Yang Hongyang
2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 4/5] net/dump: Provide the dumping facility as a net-filter Thomas Huth
2015-10-14  2:42   ` Yang Hongyang
2015-10-13 10:40 ` [Qemu-devel] [PATCH v2 5/5] options: Add documentation for filter-dump Thomas Huth
2015-10-20  4:35 ` [Qemu-devel] [PATCH v2 0/5] Network traffic dumping via netfilter Jason Wang

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.