All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
@ 2015-07-24 10:55 Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 1/9] netdev: Add a net filter Yang Hongyang
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

This patch add a net filter between network backend and NIC devices.
All packets will pass by this filter.
Also implement a netbuffer plugin for example, the netbuffer plugin
could be used by VM FT solutions like Macrocheckpointing,
to buffer/release packets.
Based on this, dump plugin could be easily implemented.

I've done some simple tests on this series,
backend, tap,user
NIC, e1000,virtio-net

There's still some missing functions to be done, I've posted this
early in order to gain more comments, thank you!

TODO:
  multiqueue support.

                +--------------+       +-------------+
  +----------+  |    filter    |       |frontend(NIC)|
  |      peer+-->              |       |             |
  | network  <--+backend       <-------+ peer        |
  | backend  |  |         peer +------->             |
  +----------+  +--------------+       +-------------+

Usage:
  -netdev tap,id=bn0  # you can use whatever backend as needed
  -netdev filter,id=f0,backend=bn0
  -netdev filter-<plugin>,id=p0,filter=f0
  -device e1000,netdev=f0
NOTE:
  You can attach multiple plugins to the filter, dynamically add/remove
filter and filter-<plugin>.

The netbuffer plugin:
Usage:
  -netdev tap,id=bn0  # you can use whatever backend as needed
  -netdev filter,id=f0,backend=bn0
  -netdev filter-buffer,id=p0,filter=f0
  -device e1000,netdev=f0

Will supply a public API to release the buffer. But there's no
callers currently.
To test this feature, it's quite simple, just use
netdev_add filter-buffer,id=p0,filter=f0
to buffer packets,
netdev_del p0
will release packets.

You can also implement whatever plugin you needed based on this filter.

Yang Hongyang (9):
  netdev: Add a net filter
  virtio-net: add filter support
  filter: remove plugins when remove filter
  filter: remove filter before remove network backend
  filter: add netbuffer plugin
  introduce qemu_find_net_clients_by_model
  net/queue: export qemu_net_queue_append
  move out net queue structs define
  add a public api to release buffer

 hw/net/virtio-net.c  |  17 ++-
 include/net/filter.h |  21 ++++
 include/net/net.h    |   5 +
 include/net/queue.h  |  26 ++++
 net/Makefile.objs    |   2 +
 net/clients.h        |   6 +
 net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
 net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
 net/net.c            |  51 +++++++-
 net/queue.c          |  31 +----
 qapi-schema.json     |  40 ++++++-
 11 files changed, 679 insertions(+), 36 deletions(-)
 create mode 100644 include/net/filter.h
 create mode 100644 net/filter-buffer.c
 create mode 100644 net/filter.c

-- 
1.9.1

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

* [Qemu-devel] [PATCH 1/9] netdev: Add a net filter
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-27 12:38   ` Thomas Huth
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 2/9] virtio-net: add filter support Yang Hongyang
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

This patch add a net filter between network backend and NIC devices.
All packets will pass by this filter.
TODO:
  multiqueue support.

                +--------------+       +-------------+
  +----------+  |    filter    |       |frontend(NIC)|
  |      peer+-->              |       |             |
  | network  <--+backend       <-------+ peer        |
  | backend  |  |         peer +------->             |
  +----------+  +--------------+       +-------------+

Usage:
  -netdev tap,id=bn0  # you can use whatever backend as needed
  -netdev filter,id=f0,backend=bn0
  -netdev filter-<plugin>,id=p0,filter=f0
  -device e1000,netdev=f0
NOTE:
  You can attach multiple plugins to the filter, dynamically add/remove
filter and filter-<plugin>.
  A filter without plugin supplied will do nothing except pass by all
packets, a plugin like dump for example, will dump all packets into a
file. Or other plugins like a netbuffer plugin, will simply buffer the
packets, release the packets when needed.
  You can also implement whatever plugin you needed based on this filter.

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 include/net/filter.h |  18 +++
 include/net/net.h    |   3 +
 net/Makefile.objs    |   1 +
 net/clients.h        |   3 +
 net/filter.c         | 317 +++++++++++++++++++++++++++++++++++++++++++++++++++
 net/net.c            |  20 +++-
 qapi-schema.json     |  22 +++-
 7 files changed, 377 insertions(+), 7 deletions(-)
 create mode 100644 include/net/filter.h
 create mode 100644 net/filter.c

diff --git a/include/net/filter.h b/include/net/filter.h
new file mode 100644
index 0000000..44ba10f
--- /dev/null
+++ b/include/net/filter.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_NET_FILTER_H
+#define QEMU_NET_FILTER_H
+
+#include "qemu-common.h"
+//#include "qapi-types.h"
+
+NetClientState *filter_backend(NetClientState *nc);
+int filter_add_plugin(NetClientState *nc, NetClientState *plugin);
+int filter_del_plugin(NetClientState *nc, NetClientState *plugin);
+
+#endif /* QEMU_NET_FILTER_H */
diff --git a/include/net/net.h b/include/net/net.h
index 6a6cbef..250f365 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -45,6 +45,8 @@ typedef void (NetPoll)(NetClientState *, bool enable);
 typedef int (NetCanReceive)(NetClientState *);
 typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
 typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
+typedef ssize_t (NetReceiveFilter)(NetClientState *, NetClientState *,
+                                   unsigned, const uint8_t *, size_t);
 typedef void (NetCleanup) (NetClientState *);
 typedef void (LinkStatusChanged)(NetClientState *);
 typedef void (NetClientDestructor)(NetClientState *);
@@ -64,6 +66,7 @@ typedef struct NetClientInfo {
     NetReceive *receive;
     NetReceive *receive_raw;
     NetReceiveIOV *receive_iov;
+    NetReceiveFilter *receive_filter;
     NetCanReceive *can_receive;
     NetCleanup *cleanup;
     LinkStatusChanged *link_status_changed;
diff --git a/net/Makefile.objs b/net/Makefile.objs
index ec19cb3..914aec0 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -13,3 +13,4 @@ common-obj-$(CONFIG_HAIKU) += tap-haiku.o
 common-obj-$(CONFIG_SLIRP) += slirp.o
 common-obj-$(CONFIG_VDE) += vde.o
 common-obj-$(CONFIG_NETMAP) += netmap.o
+common-obj-y += filter.o
diff --git a/net/clients.h b/net/clients.h
index d47530e..bcfb34b 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -62,4 +62,7 @@ int net_init_netmap(const NetClientOptions *opts, const char *name,
 int net_init_vhost_user(const NetClientOptions *opts, const char *name,
                         NetClientState *peer, Error **errp);
 
+int net_init_filter(const NetClientOptions *opts, const char *name,
+                    NetClientState *peer, Error **errp);
+
 #endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/filter.c b/net/filter.c
new file mode 100644
index 0000000..89ee830
--- /dev/null
+++ b/net/filter.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "net/net.h"
+#include "clients.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "net/filter.h"
+
+typedef struct FilterPlugin FilterPlugin;
+struct FilterPlugin {
+    QLIST_ENTRY(FilterPlugin) next;
+    NetClientState *plugin;
+};
+
+typedef struct FILTERState {
+    NetClientState nc;
+    NetClientState *backend;
+    QLIST_HEAD(, FilterPlugin) plugins;
+} FILTERState;
+
+static ssize_t filter_receive(NetClientState *nc, NetClientState *sender,
+                              unsigned flags, const uint8_t *data, size_t size)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+    NetClientState *plugin = NULL;
+    FilterPlugin *plug = NULL;
+    ssize_t ret;
+
+    /*
+     * let plugins handle the packet first, plugins return:
+     *   0: finished handling the packet, we should continue
+     *   size: plugin stolen this packet, we stop pass this
+     *         packet further
+     */
+    QLIST_FOREACH(plug, &s->plugins, next) {
+        plugin = plug->plugin;
+        ret = plugin->info->receive_filter(plugin, sender, flags, data, size);
+        if (ret == 0) {
+            continue;
+        } else if (ret == size) {
+            /* plugin will take care of this packet */
+            goto out;
+        }
+    }
+
+    if (sender->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
+        /*
+         * packet received from NIC, I'm a backend myself, so call receive
+         * directly
+         */
+        if (flags & QEMU_NET_PACKET_FLAG_RAW && backend->info->receive_raw) {
+            ret = backend->info->receive_raw(backend, data, size);
+        } else {
+            ret = backend->info->receive(backend, data, size);
+        }
+    } else {
+        /* packet received from backend, pass the packet to NIC */
+        if (flags & QEMU_NET_PACKET_FLAG_RAW) {
+            qemu_send_packet_raw(nc, data, size);
+        } else {
+            qemu_send_packet_async(nc, data, size, NULL);
+        }
+        /*
+         * packet been passed to NIC queue, we just return sucess for this
+         * deliver
+         */
+        ret = size;
+    }
+
+out:
+    return ret;
+}
+
+static void filter_cleanup(NetClientState *nc)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+
+    if (s->backend && nc->peer) {
+        qemu_flush_queued_packets(nc);
+        s->backend->peer = nc->peer;
+        nc->peer->peer = s->backend;
+    } else if (s->backend) {
+        qemu_flush_queued_packets(nc);
+        s->backend->peer = NULL;
+    } else if (nc->peer) {
+        nc->peer->peer = NULL;
+    }
+    nc->peer = NULL;
+
+    return;
+}
+
+static bool filter_has_ufo(NetClientState *nc)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->has_ufo) {
+        return false;
+    }
+
+    return backend->info->has_ufo(backend);
+}
+
+static bool filter_has_vnet_hdr(NetClientState *nc)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->has_vnet_hdr) {
+        return false;
+    }
+
+    return backend->info->has_vnet_hdr(backend);
+}
+
+static bool filter_has_vnet_hdr_len(NetClientState *nc, int len)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->has_vnet_hdr_len) {
+        return false;
+    }
+
+    return backend->info->has_vnet_hdr_len(backend, len);
+}
+
+static void filter_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->using_vnet_hdr) {
+        return;
+    }
+
+    backend->info->using_vnet_hdr(backend, using_vnet_hdr);
+}
+
+static void filter_set_offload(NetClientState *nc, int csum, int tso4,
+                               int tso6, int ecn, int ufo)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->set_offload) {
+        return;
+    }
+
+    backend->info->set_offload(backend, csum, tso4, tso6, ecn, ufo);
+}
+
+static void filter_set_vnet_hdr_len(NetClientState *nc, int len)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->set_vnet_hdr_len) {
+        return;
+    }
+
+    backend->info->set_vnet_hdr_len(backend, len);
+}
+
+static int filter_set_vnet_le(NetClientState *nc, bool is_le)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->set_vnet_le) {
+        return -ENOSYS;
+    }
+
+    return backend->info->set_vnet_le(backend, is_le);
+}
+
+static int filter_set_vnet_be(NetClientState *nc, bool is_be)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *backend = s->backend;
+
+    if (!backend->info->set_vnet_be) {
+        return -ENOSYS;
+    }
+
+    return backend->info->set_vnet_be(backend, is_be);
+}
+
+static NetClientInfo net_filter_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_FILTER,
+    .size = sizeof(FILTERState),
+    .receive_filter = filter_receive,
+    .cleanup = filter_cleanup,
+    .has_ufo = filter_has_ufo,
+    .has_vnet_hdr = filter_has_vnet_hdr,
+    .has_vnet_hdr_len = filter_has_vnet_hdr_len,
+    .using_vnet_hdr = filter_using_vnet_hdr,
+    .set_offload = filter_set_offload,
+    .set_vnet_hdr_len = filter_set_vnet_hdr_len,
+    .set_vnet_le = filter_set_vnet_le,
+    .set_vnet_be = filter_set_vnet_be,
+};
+
+int net_init_filter(const NetClientOptions *opts, const char *name,
+                    NetClientState *peer, Error **errp)
+{
+    NetClientState *nc;
+    NetClientState *ncs[MAX_QUEUE_NUM];
+    FILTERState *s;
+    const NetdevFilterOptions *filter;
+    char *backend_id = NULL;
+    NetClientState *backend;
+    int queues;
+
+    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_FILTER);
+    filter = opts->filter;
+    assert(filter->has_backend);
+
+    backend_id = filter->backend;
+    queues = qemu_find_net_clients_except(backend_id, ncs,
+                                          NET_CLIENT_OPTIONS_KIND_NIC,
+                                          MAX_QUEUE_NUM);
+    if (queues > 1) {
+        error_setg(errp, "multiqueues is not supported by now");
+        return -1;
+    } else if (queues < 1) {
+        error_setg(errp, "invalid backend name specified");
+        return -1;
+    }
+
+    backend = ncs[0];
+    if (backend->peer) {
+        switch (backend->peer->info->type) {
+        case NET_CLIENT_OPTIONS_KIND_FILTER:
+            error_setg(errp, "a filter already attached to the backend");
+            return -1;
+        case NET_CLIENT_OPTIONS_KIND_NIC:
+            /*
+             * We only support filter between NIC and network
+             * backend.
+             */
+            break;
+        default:
+            error_setg(errp, "not supported");
+            return -1;
+        }
+    }
+
+    nc = qemu_new_net_client(&net_filter_info, peer, "filter", name);
+    s = DO_UPCAST(FILTERState, nc, nc);
+    s->backend = backend;
+
+    /*               +--------------+       +-------------+
+     * +----------+  |    filter    |       |frontend(NIC)|
+     * |      peer+-->              |       |             |
+     * | network  <--+backend       <-------+ peer        |
+     * | backend  |  |         peer +------->             |
+     * +----------+  +--------------+       +-------------+
+     */
+    if (backend->peer) {
+        nc->peer = backend->peer;
+        nc->peer->peer = nc;
+        backend->peer = nc;
+        /*
+         * we need to flush backend incoming queue, because it is
+         * no longer used when filter inserted
+         */
+        qemu_flush_queued_packets(backend);
+    } else {
+        backend->peer = nc;
+    }
+
+    QLIST_INIT(&s->plugins);
+
+    return 0;
+}
+
+/* Public APIs */
+NetClientState *filter_backend(NetClientState *nc)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+
+    return s->backend;
+}
+
+int filter_add_plugin(NetClientState *nc, NetClientState *plugin)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    FilterPlugin *plug;
+
+    plug = g_malloc(sizeof(*plug));
+    plug->plugin = plugin;
+    QLIST_INSERT_HEAD(&s->plugins, plug, next);
+    return 0;
+}
+
+int filter_del_plugin(NetClientState *nc, NetClientState *plugin)
+{
+    FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    FilterPlugin *plug = NULL;
+
+    QLIST_FOREACH(plug, &s->plugins, next) {
+        if (plug->plugin == plugin)
+            break;
+    }
+    QLIST_REMOVE(plug, next);
+    g_free(plug);
+    return 0;
+}
diff --git a/net/net.c b/net/net.c
index 28a5597..c273981 100644
--- a/net/net.c
+++ b/net/net.c
@@ -57,6 +57,7 @@ const char *host_net_devices[] = {
     "tap",
     "socket",
     "dump",
+    "filter",
 #ifdef CONFIG_NET_BRIDGE
     "bridge",
 #endif
@@ -396,7 +397,8 @@ void qemu_del_net_client(NetClientState *nc)
     assert(queues != 0);
 
     /* If there is a peer NIC, delete and cleanup client, but do not free. */
-    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
+    if (nc->peer && nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_NIC
+        && nc->info->type != NET_CLIENT_OPTIONS_KIND_FILTER) {
         NICState *nic = qemu_get_nic(nc->peer);
         if (nic->peer_deleted) {
             return;
@@ -571,7 +573,9 @@ ssize_t qemu_deliver_packet(NetClientState *sender,
         return 0;
     }
 
-    if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
+    if (nc->info->receive_filter) {
+        ret = nc->info->receive_filter(nc, sender, flags, data, size);
+    } else if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
         ret = nc->info->receive_raw(nc, data, size);
     } else {
         ret = nc->info->receive(nc, data, size);
@@ -659,7 +663,8 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
                                              buf, size, NULL);
 }
 
-static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
+static ssize_t nc_sendv_compat(NetClientState *nc, NetClientState *sender,
+                               unsigned flags, const struct iovec *iov,
                                int iovcnt)
 {
     uint8_t buffer[NET_BUFSIZE];
@@ -667,7 +672,11 @@ static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
 
     offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
 
-    return nc->info->receive(nc, buffer, offset);
+    if (nc->info->receive_filter) {
+        return nc->info->receive_filter(nc, sender, flags, buffer, offset);
+    } else {
+        return nc->info->receive(nc, buffer, offset);
+    }
 }
 
 ssize_t qemu_deliver_packet_iov(NetClientState *sender,
@@ -690,7 +699,7 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
     if (nc->info->receive_iov) {
         ret = nc->info->receive_iov(nc, iov, iovcnt);
     } else {
-        ret = nc_sendv_compat(nc, iov, iovcnt);
+        ret = nc_sendv_compat(nc, sender, flags, iov, iovcnt);
     }
 
     if (ret == 0) {
@@ -886,6 +895,7 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
     const char *name,
     NetClientState *peer, Error **errp) = {
         [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,
+        [NET_CLIENT_OPTIONS_KIND_FILTER]    = net_init_filter,
 #ifdef CONFIG_SLIRP
         [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index a0a45f7..9244c88 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2063,7 +2063,7 @@
 # Add a network backend.
 #
 # @type: the type of network backend.  Current valid values are 'user', 'tap',
-#        'vde', 'socket', 'dump' and 'bridge'
+#        'vde', 'socket', 'dump' , 'bridge' and 'filter'
 #
 # @id: the name of the new network backend
 #
@@ -2474,6 +2474,23 @@
     '*vhostforce':    'bool' } }
 
 ##
+# @NetdevFilterOptions
+#
+# A net filter between network backend and NIC device
+#
+# @backend: the network backend.
+#
+# NOTE: used with filterplugin netdevs which provide filter rules.
+#       by default, if no filterplugin is supplied, the net filter will do
+#       nothing but pass all packets to network backend.
+#
+# Since 2.5
+##
+{ 'struct': 'NetdevFilterOptions',
+  'data': {
+    '*backend':       'str' } }
+
+##
 # @NetClientOptions
 #
 # A discriminated record of network device traits.
@@ -2496,7 +2513,8 @@
     'bridge':   'NetdevBridgeOptions',
     'hubport':  'NetdevHubPortOptions',
     'netmap':   'NetdevNetmapOptions',
-    'vhost-user': 'NetdevVhostUserOptions' } }
+    'vhost-user': 'NetdevVhostUserOptions',
+    'filter':   'NetdevFilterOptions'} }
 
 ##
 # @NetLegacy
-- 
1.9.1

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

* [Qemu-devel] [PATCH 2/9] virtio-net: add filter support
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 1/9] netdev: Add a net filter Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 3/9] filter: remove plugins when remove filter Yang Hongyang
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

virtio-net explicity check for tap device, aupport for tap
with filter attached.

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 hw/net/virtio-net.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 304d3dd..59e9707 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -16,6 +16,7 @@
 #include "net/net.h"
 #include "net/checksum.h"
 #include "net/tap.h"
+#include "net/filter.h"
 #include "qemu/error-report.h"
 #include "qemu/timer.h"
 #include "hw/virtio/virtio-net.h"
@@ -406,11 +407,15 @@ static int peer_attach(VirtIONet *n, int index)
         return 0;
     }
 
-    if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
+    if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_FILTER) {
+        nc = filter_backend(nc->peer);
+    }
+
+    if (nc->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
         return 0;
     }
 
-    return tap_enable(nc->peer);
+    return tap_enable(nc);
 }
 
 static int peer_detach(VirtIONet *n, int index)
@@ -421,11 +426,15 @@ static int peer_detach(VirtIONet *n, int index)
         return 0;
     }
 
-    if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
+    if (nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_FILTER) {
+        nc = filter_backend(nc->peer);
+    }
+
+    if (nc->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
         return 0;
     }
 
-    return tap_disable(nc->peer);
+    return tap_disable(nc);
 }
 
 static void virtio_net_set_queues(VirtIONet *n)
-- 
1.9.1

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

* [Qemu-devel] [PATCH 3/9] filter: remove plugins when remove filter
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 1/9] netdev: Add a net filter Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 2/9] virtio-net: add filter support Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 4/9] filter: remove filter before remove network backend Yang Hongyang
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 net/filter.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/net/filter.c b/net/filter.c
index 89ee830..7ef7bee 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -11,6 +11,7 @@
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "net/filter.h"
+#include "qemu/config-file.h"
 
 typedef struct FilterPlugin FilterPlugin;
 struct FilterPlugin {
@@ -81,6 +82,19 @@ out:
 static void filter_cleanup(NetClientState *nc)
 {
     FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+    NetClientState *plugin = NULL;
+    FilterPlugin *plug = NULL, *next = NULL;
+    QemuOpts *opts;
+
+    QLIST_FOREACH_SAFE(plug, &s->plugins, next, next) {
+        plugin = plug->plugin;
+        opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL),
+                              plugin->name);
+        assert(opts);
+
+        qemu_del_net_client(plugin);
+        qemu_opts_del(opts);
+    }
 
     if (s->backend && nc->peer) {
         qemu_flush_queued_packets(nc);
-- 
1.9.1

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

* [Qemu-devel] [PATCH 4/9] filter: remove filter before remove network backend
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (2 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 3/9] filter: remove plugins when remove filter Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 5/9] filter: add netbuffer plugin Yang Hongyang
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 net/net.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/net.c b/net/net.c
index c273981..321362f 100644
--- a/net/net.c
+++ b/net/net.c
@@ -385,9 +385,20 @@ void qemu_del_net_client(NetClientState *nc)
 {
     NetClientState *ncs[MAX_QUEUE_NUM];
     int queues, i;
+    QemuOpts *opts;
 
     assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
 
+    if (nc->peer &&
+        nc->peer->info->type == NET_CLIENT_OPTIONS_KIND_FILTER) {
+        opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL),
+                              nc->peer->name);
+        assert(opts);
+
+        qemu_del_net_client(nc->peer);
+        qemu_opts_del(opts);
+    }
+
     /* If the NetClientState belongs to a multiqueue backend, we will change all
      * other NetClientStates also.
      */
-- 
1.9.1

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

* [Qemu-devel] [PATCH 5/9] filter: add netbuffer plugin
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (3 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 4/9] filter: remove filter before remove network backend Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 6/9] introduce qemu_find_net_clients_by_model Yang Hongyang
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

This could be used by VM FT solutions like Macrocheckpointing,
to buffer/release packets.

Usage:
  -netdev tap,id=bn0  # you can use whatever backend as needed
  -netdev filter,id=f0,backend=bn0
  -netdev filter-buffer,id=p0,filter=f0
  -device e1000,netdev=f0

Will supply a public API to release the buffer. But there's no
callers currently.
To test this feature, it's quite simple, just use
netdev_add filter-buffer,id=p0,filter=f0
to buffer packets,
netdev_del p0
will release packets.

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 net/Makefile.objs   |  1 +
 net/clients.h       |  3 ++
 net/filter-buffer.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/net.c           |  2 ++
 qapi-schema.json    | 20 +++++++++++++-
 5 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 net/filter-buffer.c

diff --git a/net/Makefile.objs b/net/Makefile.objs
index 914aec0..5fa2f97 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -14,3 +14,4 @@ common-obj-$(CONFIG_SLIRP) += slirp.o
 common-obj-$(CONFIG_VDE) += vde.o
 common-obj-$(CONFIG_NETMAP) += netmap.o
 common-obj-y += filter.o
+common-obj-y += filter-buffer.o
diff --git a/net/clients.h b/net/clients.h
index bcfb34b..7cc60f2 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -65,4 +65,7 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
 int net_init_filter(const NetClientOptions *opts, const char *name,
                     NetClientState *peer, Error **errp);
 
+int net_init_filter_buffer(const NetClientOptions *opts, const char *name,
+                           NetClientState *peer, Error **errp);
+
 #endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
new file mode 100644
index 0000000..15ac903
--- /dev/null
+++ b/net/filter-buffer.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "net/net.h"
+#include "net/queue.h"
+#include "clients.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "net/filter.h"
+
+typedef struct FILTERBUFFERState {
+    NetClientState nc;
+    NetClientState *filter;
+    int interval;
+    NetQueue *inflight_queue;
+} FILTERBUFFERState;
+
+static ssize_t filter_buffer_receive(NetClientState *nc, NetClientState *sender,
+                              unsigned flags, const uint8_t *data, size_t size)
+{
+    NetQueue *queue = nc->incoming_queue;
+
+    if (sender->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
+        /* we only buffer guest output packets */
+        qemu_net_queue_append(queue, sender, flags, data, size, NULL);
+        /* Now that we have buffered the packet, return sucess */
+        return size;
+    }
+
+    return 0;
+}
+
+static void filter_buffer_cleanup(NetClientState *nc)
+{
+    FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+    filter_del_plugin(s->filter, nc);
+    return;
+}
+
+
+static NetClientInfo net_filter_buffer_info = {
+    .type = NET_CLIENT_OPTIONS_KIND_FILTER_BUFFER,
+    .size = sizeof(FILTERBUFFERState),
+    .receive_filter = filter_buffer_receive,
+    .cleanup = filter_buffer_cleanup,
+};
+
+int net_init_filter_buffer(const NetClientOptions *opts, const char *name,
+                           NetClientState *peer, Error **errp)
+{
+    NetClientState *nc;
+    FILTERBUFFERState *s;
+    const NetdevFilterBufferOptions *bufferopt;
+    char *filter_id = NULL;
+    NetClientState *filter;
+
+    assert(opts->kind == NET_CLIENT_OPTIONS_KIND_FILTER_BUFFER);
+    bufferopt = opts->filter_buffer;
+    assert(bufferopt->has_filter);
+
+    filter_id = bufferopt->filter;
+    filter = qemu_find_netdev(filter_id);
+    if (!filter) {
+        error_setg(errp, "invalid filter name specified");
+        return -1;
+    }
+
+    nc = qemu_new_net_client(&net_filter_buffer_info, peer, "filter_buffer", name);
+    s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+    s->filter = filter;
+    s->interval = bufferopt->has_interval ? bufferopt->interval : 0;
+    filter_add_plugin(filter, nc);
+
+    return 0;
+}
diff --git a/net/net.c b/net/net.c
index 321362f..856a0fe 100644
--- a/net/net.c
+++ b/net/net.c
@@ -58,6 +58,7 @@ const char *host_net_devices[] = {
     "socket",
     "dump",
     "filter",
+    "filter-buffer",
 #ifdef CONFIG_NET_BRIDGE
     "bridge",
 #endif
@@ -907,6 +908,7 @@ static int (* const net_client_init_fun[NET_CLIENT_OPTIONS_KIND_MAX])(
     NetClientState *peer, Error **errp) = {
         [NET_CLIENT_OPTIONS_KIND_NIC]       = net_init_nic,
         [NET_CLIENT_OPTIONS_KIND_FILTER]    = net_init_filter,
+        [NET_CLIENT_OPTIONS_KIND_FILTER_BUFFER] = net_init_filter_buffer,
 #ifdef CONFIG_SLIRP
         [NET_CLIENT_OPTIONS_KIND_USER]      = net_init_slirp,
 #endif
diff --git a/qapi-schema.json b/qapi-schema.json
index 9244c88..62cc54e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2491,6 +2491,23 @@
     '*backend':       'str' } }
 
 ##
+# @NetdevFilterBufferOptions
+#
+# A net filter buffer plugin
+#
+# @filter: the network filter this plugin attached to.
+#
+# @interval: #optional release packets by interval, if no interval supplied,
+#            will release packets when filter_buffer_release been called.
+#
+# Since 2.5
+##
+{ 'struct': 'NetdevFilterBufferOptions',
+  'data': {
+    '*filter':       'str',
+    '*interval':     'int32' } }
+
+##
 # @NetClientOptions
 #
 # A discriminated record of network device traits.
@@ -2514,7 +2531,8 @@
     'hubport':  'NetdevHubPortOptions',
     'netmap':   'NetdevNetmapOptions',
     'vhost-user': 'NetdevVhostUserOptions',
-    'filter':   'NetdevFilterOptions'} }
+    'filter':   'NetdevFilterOptions',
+    'filter-buffer': 'NetdevFilterBufferOptions' } }
 
 ##
 # @NetLegacy
-- 
1.9.1

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

* [Qemu-devel] [PATCH 6/9] introduce qemu_find_net_clients_by_model
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (4 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 5/9] filter: add netbuffer plugin Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 7/9] net/queue: export qemu_net_queue_append Yang Hongyang
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 include/net/net.h |  2 ++
 net/net.c         | 18 ++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/include/net/net.h b/include/net/net.h
index 250f365..10927e1 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -108,6 +108,8 @@ char *qemu_mac_strdup_printf(const uint8_t *macaddr);
 NetClientState *qemu_find_netdev(const char *id);
 int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
                                  NetClientOptionsKind type, int max);
+int qemu_find_net_clients_by_model(const char *model, NetClientState **ncs,
+                                   int max);
 NetClientState *qemu_new_net_client(NetClientInfo *info,
                                     NetClientState *peer,
                                     const char *model,
diff --git a/net/net.c b/net/net.c
index 856a0fe..7b62e52 100644
--- a/net/net.c
+++ b/net/net.c
@@ -780,6 +780,24 @@ int qemu_find_net_clients_except(const char *id, NetClientState **ncs,
     return ret;
 }
 
+int qemu_find_net_clients_by_model(const char *model, NetClientState **ncs,
+                                   int max)
+{
+    NetClientState *nc;
+    int ret = 0;
+
+    QTAILQ_FOREACH(nc, &net_clients, next) {
+        if (!strcmp(nc->model, model)) {
+            if (ret < max) {
+                ncs[ret] = nc;
+            }
+            ret++;
+        }
+    }
+
+    return ret;
+}
+
 static int nic_get_free_idx(void)
 {
     int index;
-- 
1.9.1

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

* [Qemu-devel] [PATCH 7/9] net/queue: export qemu_net_queue_append
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (5 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 6/9] introduce qemu_find_net_clients_by_model Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 8/9] move out net queue structs define Yang Hongyang
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 include/net/queue.h |  7 +++++++
 net/queue.c         | 12 ++++++------
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/include/net/queue.h b/include/net/queue.h
index fc02b33..fea6c51 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -36,6 +36,13 @@ typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
 
 NetQueue *qemu_new_net_queue(void *opaque);
 
+void qemu_net_queue_append(NetQueue *queue,
+                           NetClientState *sender,
+                           unsigned flags,
+                           const uint8_t *buf,
+                           size_t size,
+                           NetPacketSent *sent_cb);
+
 void qemu_del_net_queue(NetQueue *queue);
 
 ssize_t qemu_net_queue_send(NetQueue *queue,
diff --git a/net/queue.c b/net/queue.c
index ebbe2bb..3d733dc 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -87,12 +87,12 @@ void qemu_del_net_queue(NetQueue *queue)
     g_free(queue);
 }
 
-static void qemu_net_queue_append(NetQueue *queue,
-                                  NetClientState *sender,
-                                  unsigned flags,
-                                  const uint8_t *buf,
-                                  size_t size,
-                                  NetPacketSent *sent_cb)
+void qemu_net_queue_append(NetQueue *queue,
+                           NetClientState *sender,
+                           unsigned flags,
+                           const uint8_t *buf,
+                           size_t size,
+                           NetPacketSent *sent_cb)
 {
     NetPacket *packet;
 
-- 
1.9.1

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

* [Qemu-devel] [PATCH 8/9] move out net queue structs define
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (6 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 7/9] net/queue: export qemu_net_queue_append Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 9/9] add a public api to release buffer Yang Hongyang
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 include/net/queue.h | 19 +++++++++++++++++++
 net/queue.c         | 19 -------------------
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/include/net/queue.h b/include/net/queue.h
index fea6c51..3cdd669 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -31,6 +31,25 @@ typedef struct NetQueue NetQueue;
 
 typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
 
+struct NetPacket {
+    QTAILQ_ENTRY(NetPacket) entry;
+    NetClientState *sender;
+    unsigned flags;
+    int size;
+    NetPacketSent *sent_cb;
+    uint8_t data[0];
+};
+
+struct NetQueue {
+    void *opaque;
+    uint32_t nq_maxlen;
+    uint32_t nq_count;
+
+    QTAILQ_HEAD(packets, NetPacket) packets;
+
+    unsigned delivering : 1;
+};
+
 #define QEMU_NET_PACKET_FLAG_NONE  0
 #define QEMU_NET_PACKET_FLAG_RAW  (1<<0)
 
diff --git a/net/queue.c b/net/queue.c
index 3d733dc..2bab882 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -39,25 +39,6 @@
  * unbounded queueing.
  */
 
-struct NetPacket {
-    QTAILQ_ENTRY(NetPacket) entry;
-    NetClientState *sender;
-    unsigned flags;
-    int size;
-    NetPacketSent *sent_cb;
-    uint8_t data[0];
-};
-
-struct NetQueue {
-    void *opaque;
-    uint32_t nq_maxlen;
-    uint32_t nq_count;
-
-    QTAILQ_HEAD(packets, NetPacket) packets;
-
-    unsigned delivering : 1;
-};
-
 NetQueue *qemu_new_net_queue(void *opaque)
 {
     NetQueue *queue;
-- 
1.9.1

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

* [Qemu-devel] [PATCH 9/9] add a public api to release buffer
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (7 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 8/9] move out net queue structs define Yang Hongyang
@ 2015-07-24 10:55 ` Yang Hongyang
  2015-07-25  5:06 ` [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter zhanghailiang
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-24 10:55 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha, Yang Hongyang

Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
 include/net/filter.h |   3 ++
 net/filter-buffer.c  | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 109 insertions(+), 1 deletion(-)

diff --git a/include/net/filter.h b/include/net/filter.h
index 44ba10f..f640cf7 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -15,4 +15,7 @@ NetClientState *filter_backend(NetClientState *nc);
 int filter_add_plugin(NetClientState *nc, NetClientState *plugin);
 int filter_del_plugin(NetClientState *nc, NetClientState *plugin);
 
+/* filter buffer plugin */
+void filter_buffer_release_all(void);
+
 #endif /* QEMU_NET_FILTER_H */
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
index 15ac903..a32785d 100644
--- a/net/filter-buffer.c
+++ b/net/filter-buffer.c
@@ -12,14 +12,19 @@
 #include "qemu-common.h"
 #include "qemu/error-report.h"
 #include "net/filter.h"
+#include "qemu/main-loop.h"
 
 typedef struct FILTERBUFFERState {
     NetClientState nc;
     NetClientState *filter;
     int interval;
     NetQueue *inflight_queue;
+    QEMUBH *flush_bh;
 } FILTERBUFFERState;
 
+static void packet_send_completed(NetClientState *nc, ssize_t len);
+static void filter_buffer_flush(NetClientState *nc);
+
 static ssize_t filter_buffer_receive(NetClientState *nc, NetClientState *sender,
                               unsigned flags, const uint8_t *data, size_t size)
 {
@@ -27,7 +32,9 @@ static ssize_t filter_buffer_receive(NetClientState *nc, NetClientState *sender,
 
     if (sender->info->type == NET_CLIENT_OPTIONS_KIND_NIC) {
         /* we only buffer guest output packets */
-        qemu_net_queue_append(queue, sender, flags, data, size, NULL);
+        qemu_net_queue_append(queue, sender, flags, data, size,
+                              packet_send_completed);
+
         /* Now that we have buffered the packet, return sucess */
         return size;
     }
@@ -38,7 +45,23 @@ static ssize_t filter_buffer_receive(NetClientState *nc, NetClientState *sender,
 static void filter_buffer_cleanup(NetClientState *nc)
 {
     FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+
+    /* flush inflight packets */
+    if (s->inflight_queue) {
+        filter_buffer_flush(nc);
+    }
+
+    /* flush incoming packets */
+    s->inflight_queue = nc->incoming_queue;
+    nc->incoming_queue = NULL;
+    filter_buffer_flush(nc);
+
+    if (s->flush_bh) {
+        qemu_bh_delete(s->flush_bh);
+        s->flush_bh = NULL;
+    }
     filter_del_plugin(s->filter, nc);
+    nc->peer = NULL;
     return;
 }
 
@@ -50,6 +73,54 @@ static NetClientInfo net_filter_buffer_info = {
     .cleanup = filter_buffer_cleanup,
 };
 
+static void packet_send_completed(NetClientState *nc, ssize_t len)
+{
+    FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+    qemu_bh_schedule(s->flush_bh);
+}
+
+static void filter_buffer_flush(NetClientState *nc)
+{
+    FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+    NetQueue *queue = s->inflight_queue;
+    NetPacket *packet;
+    int ret;
+
+    while (queue && !QTAILQ_EMPTY(&queue->packets)) {
+        packet = QTAILQ_FIRST(&queue->packets);
+        QTAILQ_REMOVE(&queue->packets, packet, entry);
+        queue->nq_count--;
+
+        if (packet->flags & QEMU_NET_PACKET_FLAG_RAW) {
+            ret = qemu_send_packet_raw(nc, packet->data, packet->size);
+        } else {
+            ret = qemu_send_packet_async(nc, packet->data, packet->size,
+                                         packet->sent_cb);
+        }
+
+        if (ret == 0) {
+            queue->nq_count++;
+            QTAILQ_INSERT_HEAD(&queue->packets, packet, entry);
+            /* shedule out */
+            return;
+        }
+
+        g_free(packet);
+    }
+
+    if (QTAILQ_EMPTY(&queue->packets)) {
+        g_free(queue);
+        s->inflight_queue = NULL;
+    }
+}
+
+static void filter_buffer_flush_bh(void *opaque)
+{
+    FILTERBUFFERState *s = opaque;
+    NetClientState *nc = &s->nc;
+    filter_buffer_flush(nc);
+}
+
 int net_init_filter_buffer(const NetClientOptions *opts, const char *name,
                            NetClientState *peer, Error **errp)
 {
@@ -71,10 +142,44 @@ int net_init_filter_buffer(const NetClientOptions *opts, const char *name,
     }
 
     nc = qemu_new_net_client(&net_filter_buffer_info, peer, "filter_buffer", name);
+    /*
+     * we are buffering guest output packets, our buffered packets should be
+     * sent to real network backend, so our peer should be that backend
+     */
+    nc->peer = filter_backend(filter);
     s = DO_UPCAST(FILTERBUFFERState, nc, nc);
     s->filter = filter;
     s->interval = bufferopt->has_interval ? bufferopt->interval : 0;
+    s->flush_bh = qemu_bh_new(filter_buffer_flush_bh, s);
     filter_add_plugin(filter, nc);
 
     return 0;
 }
+
+static void filter_buffer_release_one(NetClientState *nc)
+{
+    FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nc, nc);
+
+    /* flush inflight packets */
+    if (s->inflight_queue) {
+        filter_buffer_flush(nc);
+    }
+
+    s->inflight_queue = nc->incoming_queue;
+    nc->incoming_queue = qemu_new_net_queue(nc);
+    qemu_bh_schedule(s->flush_bh);
+}
+
+/* public APIs */
+void filter_buffer_release_all(void)
+{
+    NetClientState *ncs[MAX_QUEUE_NUM];
+    int queues, i;
+
+    queues = qemu_find_net_clients_by_model("filter_buffer", ncs,
+                                            MAX_QUEUE_NUM);
+
+    for (i = 0; i < queues; i++) {
+        filter_buffer_release_one(ncs[i]);
+    }
+}
-- 
1.9.1

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (8 preceding siblings ...)
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 9/9] add a public api to release buffer Yang Hongyang
@ 2015-07-25  5:06 ` zhanghailiang
  2015-07-26 14:13   ` Yang Hongyang
  2015-07-27  4:53 ` Jason Wang
  2015-07-29 10:34 ` Yang Hongyang
  11 siblings, 1 reply; 19+ messages in thread
From: zhanghailiang @ 2015-07-25  5:06 UTC (permalink / raw)
  To: Yang Hongyang, qemu-devel
  Cc: thuth, jasowang, peter.huangpeng, mrhines, stefanha

On 2015/7/24 18:55, Yang Hongyang wrote:
> This patch add a net filter between network backend and NIC devices.
> All packets will pass by this filter.
> Also implement a netbuffer plugin for example, the netbuffer plugin
> could be used by VM FT solutions like Macrocheckpointing,
> to buffer/release packets.
> Based on this, dump plugin could be easily implemented.
>
> I've done some simple tests on this series,
> backend, tap,user
> NIC, e1000,virtio-net
>
> There's still some missing functions to be done, I've posted this
> early in order to gain more comments, thank you!
>
> TODO:
>    multiqueue support.
>
>                  +--------------+       +-------------+
>    +----------+  |    filter    |       |frontend(NIC)|
>    |      peer+-->              |       |             |
>    | network  <--+backend       <-------+ peer        |
>    | backend  |  |         peer +------->             |
>    +----------+  +--------------+       +-------------+
>
> Usage:
>    -netdev tap,id=bn0  # you can use whatever backend as needed
>    -netdev filter,id=f0,backend=bn0
>    -netdev filter-<plugin>,id=p0,filter=f0
>    -device e1000,netdev=f0

Have you considered Daniel's suggestion ? Using the bellow style:
   -netfilter id=f0,plugin=dump
   -netdev tap,id=bn0,filter=f0
   -device e1000,netdev=bn0

Considering the filter as a new 'netdev' seems to be unreasonable,
Whenever we add a new plugin, we have to add a new member to
'NetClientOptions', there will be lots of 'filter' objects in NetClientOptions
area. Besides when we want to describe a net device with several filter plugin for VM,
it will become like:
    -netdev tap,id=bn0
    -netdev filter,id=f0,backend=bn0
    -netdev filter-<plugin-0>,id=p0,filter=f0
    -netdev filter-<plugin-1>,id=p1,filter=f1
    ... ...
    -device e1000,netdev=f0
Which is a little verbose for 'netdev' option.
We'd better come to an agreement on the command line style for net filter :)

Cc: Daniel P. Berrange <berrange@redhat.com>

Thanks,
zhanghailiang

> NOTE:
>    You can attach multiple plugins to the filter, dynamically add/remove
> filter and filter-<plugin>.
>
> The netbuffer plugin:
> Usage:
>    -netdev tap,id=bn0  # you can use whatever backend as needed
>    -netdev filter,id=f0,backend=bn0
>    -netdev filter-buffer,id=p0,filter=f0
>    -device e1000,netdev=f0
>
> Will supply a public API to release the buffer. But there's no
> callers currently.
> To test this feature, it's quite simple, just use
> netdev_add filter-buffer,id=p0,filter=f0
> to buffer packets,
> netdev_del p0
> will release packets.
>
> You can also implement whatever plugin you needed based on this filter.
>
> Yang Hongyang (9):
>    netdev: Add a net filter
>    virtio-net: add filter support
>    filter: remove plugins when remove filter
>    filter: remove filter before remove network backend
>    filter: add netbuffer plugin
>    introduce qemu_find_net_clients_by_model
>    net/queue: export qemu_net_queue_append
>    move out net queue structs define
>    add a public api to release buffer
>
>   hw/net/virtio-net.c  |  17 ++-
>   include/net/filter.h |  21 ++++
>   include/net/net.h    |   5 +
>   include/net/queue.h  |  26 ++++
>   net/Makefile.objs    |   2 +
>   net/clients.h        |   6 +
>   net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
>   net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   net/net.c            |  51 +++++++-
>   net/queue.c          |  31 +----
>   qapi-schema.json     |  40 ++++++-
>   11 files changed, 679 insertions(+), 36 deletions(-)
>   create mode 100644 include/net/filter.h
>   create mode 100644 net/filter-buffer.c
>   create mode 100644 net/filter.c
>

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-25  5:06 ` [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter zhanghailiang
@ 2015-07-26 14:13   ` Yang Hongyang
  2015-07-27 10:32     ` Daniel P. Berrange
  0 siblings, 1 reply; 19+ messages in thread
From: Yang Hongyang @ 2015-07-26 14:13 UTC (permalink / raw)
  To: zhanghailiang, qemu-devel
  Cc: thuth, jasowang, peter.huangpeng, mrhines, stefanha

Thank you, and sorry to Daniel that I forgot to CC you...

On 07/25/2015 01:06 PM, zhanghailiang wrote:
[...]
>>
>>                  +--------------+       +-------------+
>>    +----------+  |    filter    |       |frontend(NIC)|
>>    |      peer+-->              |       |             |
>>    | network  <--+backend       <-------+ peer        |
>>    | backend  |  |         peer +------->             |
>>    +----------+  +--------------+       +-------------+
>>
>> Usage:
>>    -netdev tap,id=bn0  # you can use whatever backend as needed
>>    -netdev filter,id=f0,backend=bn0
>>    -netdev filter-<plugin>,id=p0,filter=f0
>>    -device e1000,netdev=f0
>
> Have you considered Daniel's suggestion ? Using the bellow style:

Yes, but by dig into the implementation, I think the current way is better,
here is the reason:

1. The flexibility to easily dynamically add/remove/change filters on the fly.
    This is what Daniel was worrying about (please correct me if I didn't
    get your point) I think I addressed his main concern on this series.
    And you can specify any param to the filter plugin under existing netdev
    design.

2. Reuse as many existing code as we can. think about doing a standalone object,
    add/remove filters will duplicate the existing netdev_add/netdev_del code.
    the filter plugin need to implement at lease 3 functions, init/cleanup and
    receive_filter, this is also duplicate the existing netdev design, we already
    have the architecture to init/cleanup/receive_filter, why not use it?

3. A filter is a backend in my design, so it is absolutely reasonable to
    implement it as a netdev and it is easy to implement it as a netdev, if
    you implement it as a standalone object, how do you integrate it to the
    backend? A filter plugin might be able to be a standalone object, but just
    as I said on #2, as long as we can archive our goal under the existing
    design, why duplicate it?

4. Current implementation don't affact the existing code too much, it is a
    bolt-on feature.

Overall, we reuse the existing design, implemented a flexible and extensible
net filter feature, so I think the current way is better.


>    -netfilter id=f0,plugin=dump
>    -netdev tap,id=bn0,filter=f0
>    -device e1000,netdev=bn0
>
> Considering the filter as a new 'netdev' seems to be unreasonable,
> Whenever we add a new plugin, we have to add a new member to
> 'NetClientOptions', there will be lots of 'filter' objects in NetClientOptions
> area.

Why can't we extend this struct? I don't see any problem with this. Doing the
other way is just to extend another struct.

  Besides when we want to describe a net device with several filter plugin
> for VM,
> it will become like:
>     -netdev tap,id=bn0
>     -netdev filter,id=f0,backend=bn0
>     -netdev filter-<plugin-0>,id=p0,filter=f0
>     -netdev filter-<plugin-1>,id=p1,filter=f1
>     ... ...
>     -device e1000,netdev=f0
> Which is a little verbose for 'netdev' option.

It's just the name diffrence, using netfilter will be
-netfilter ... -netfilter ...

using plugin=xxx will make us hard to extend the plugin params under existing
netdev design thus will needs lots of extra effort to archive our goal, but we
already have a simple way, do we? and do note that Daniel's concern was based
on my initial RFC patch, which has a usage about "plugin=xxx", this series
is totally different.

> We'd better come to an agreement on the command line style for net filter :)

This is my opinion, Daniel, what do you think?

>
> Cc: Daniel P. Berrange <berrange@redhat.com>
>
> Thanks,
> zhanghailiang
>
>> NOTE:
>>    You can attach multiple plugins to the filter, dynamically add/remove
>> filter and filter-<plugin>.
>>
>> The netbuffer plugin:
>> Usage:
>>    -netdev tap,id=bn0  # you can use whatever backend as needed
>>    -netdev filter,id=f0,backend=bn0
>>    -netdev filter-buffer,id=p0,filter=f0
>>    -device e1000,netdev=f0
>>
>> Will supply a public API to release the buffer. But there's no
>> callers currently.
>> To test this feature, it's quite simple, just use
>> netdev_add filter-buffer,id=p0,filter=f0
>> to buffer packets,
>> netdev_del p0
>> will release packets.
>>
>> You can also implement whatever plugin you needed based on this filter.
>>
>> Yang Hongyang (9):
>>    netdev: Add a net filter
>>    virtio-net: add filter support
>>    filter: remove plugins when remove filter
>>    filter: remove filter before remove network backend
>>    filter: add netbuffer plugin
>>    introduce qemu_find_net_clients_by_model
>>    net/queue: export qemu_net_queue_append
>>    move out net queue structs define
>>    add a public api to release buffer
>>
>>   hw/net/virtio-net.c  |  17 ++-
>>   include/net/filter.h |  21 ++++
>>   include/net/net.h    |   5 +
>>   include/net/queue.h  |  26 ++++
>>   net/Makefile.objs    |   2 +
>>   net/clients.h        |   6 +
>>   net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
>>   net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   net/net.c            |  51 +++++++-
>>   net/queue.c          |  31 +----
>>   qapi-schema.json     |  40 ++++++-
>>   11 files changed, 679 insertions(+), 36 deletions(-)
>>   create mode 100644 include/net/filter.h
>>   create mode 100644 net/filter-buffer.c
>>   create mode 100644 net/filter.c
>>
>
>
> .
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (9 preceding siblings ...)
  2015-07-25  5:06 ` [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter zhanghailiang
@ 2015-07-27  4:53 ` Jason Wang
  2015-07-27  5:01   ` Yang Hongyang
  2015-07-29 10:34 ` Yang Hongyang
  11 siblings, 1 reply; 19+ messages in thread
From: Jason Wang @ 2015-07-27  4:53 UTC (permalink / raw)
  To: Yang Hongyang, qemu-devel; +Cc: thuth, mrhines, stefanha



On 07/24/2015 06:55 PM, Yang Hongyang wrote:
> This patch add a net filter between network backend and NIC devices.
> All packets will pass by this filter.
> Also implement a netbuffer plugin for example, the netbuffer plugin
> could be used by VM FT solutions like Macrocheckpointing,
> to buffer/release packets.
> Based on this, dump plugin could be easily implemented.
>
> I've done some simple tests on this series,
> backend, tap,user
> NIC, e1000,virtio-net
>
> There's still some missing functions to be done, I've posted this
> early in order to gain more comments, thank you!
>
> TODO:
>   multiqueue support.
>
>                 +--------------+       +-------------+
>   +----------+  |    filter    |       |frontend(NIC)|
>   |      peer+-->              |       |             |
>   | network  <--+backend       <-------+ peer        |
>   | backend  |  |         peer +------->             |
>   +----------+  +--------------+       +-------------+
>
> Usage:
>   -netdev tap,id=bn0  # you can use whatever backend as needed
>   -netdev filter,id=f0,backend=bn0
>   -netdev filter-<plugin>,id=p0,filter=f0
>   -device e1000,netdev=f0
> NOTE:
>   You can attach multiple plugins to the filter, dynamically add/remove
> filter and filter-<plugin>.
>
> The netbuffer plugin:
> Usage:
>   -netdev tap,id=bn0  # you can use whatever backend as needed
>   -netdev filter,id=f0,backend=bn0
>   -netdev filter-buffer,id=p0,filter=f0
>   -device e1000,netdev=f0
>
> Will supply a public API to release the buffer. But there's no
> callers currently.
> To test this feature, it's quite simple, just use
> netdev_add filter-buffer,id=p0,filter=f0
> to buffer packets,
> netdev_del p0
> will release packets.
>
> You can also implement whatever plugin you needed based on this filter.
>
> Yang Hongyang (9):
>   netdev: Add a net filter
>   virtio-net: add filter support
>   filter: remove plugins when remove filter
>   filter: remove filter before remove network backend
>   filter: add netbuffer plugin
>   introduce qemu_find_net_clients_by_model
>   net/queue: export qemu_net_queue_append
>   move out net queue structs define
>   add a public api to release buffer
>
>  hw/net/virtio-net.c  |  17 ++-
>  include/net/filter.h |  21 ++++
>  include/net/net.h    |   5 +
>  include/net/queue.h  |  26 ++++
>  net/Makefile.objs    |   2 +
>  net/clients.h        |   6 +
>  net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
>  net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  net/net.c            |  51 +++++++-
>  net/queue.c          |  31 +----
>  qapi-schema.json     |  40 ++++++-
>  11 files changed, 679 insertions(+), 36 deletions(-)
>  create mode 100644 include/net/filter.h
>  create mode 100644 net/filter-buffer.c
>  create mode 100644 net/filter.c
>

Hi:

Can you answer my question at
http://lists.gnu.org/archive/html/qemu-devel/2015-07/msg04653.html?

The main concern is why it must be a new kind of netdev?

Thanks

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-27  4:53 ` Jason Wang
@ 2015-07-27  5:01   ` Yang Hongyang
  0 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-27  5:01 UTC (permalink / raw)
  To: Jason Wang, qemu-devel; +Cc: thuth, mrhines, stefanha



On 07/27/2015 12:53 PM, Jason Wang wrote:
>
>
> On 07/24/2015 06:55 PM, Yang Hongyang wrote:
>> This patch add a net filter between network backend and NIC devices.
>> All packets will pass by this filter.
>> Also implement a netbuffer plugin for example, the netbuffer plugin
>> could be used by VM FT solutions like Macrocheckpointing,
>> to buffer/release packets.
>> Based on this, dump plugin could be easily implemented.
>>
>> I've done some simple tests on this series,
>> backend, tap,user
>> NIC, e1000,virtio-net
>>
>> There's still some missing functions to be done, I've posted this
>> early in order to gain more comments, thank you!
>>
>> TODO:
>>    multiqueue support.
>>
>>                  +--------------+       +-------------+
>>    +----------+  |    filter    |       |frontend(NIC)|
>>    |      peer+-->              |       |             |
>>    | network  <--+backend       <-------+ peer        |
>>    | backend  |  |         peer +------->             |
>>    +----------+  +--------------+       +-------------+
>>
>> Usage:
>>    -netdev tap,id=bn0  # you can use whatever backend as needed
>>    -netdev filter,id=f0,backend=bn0
>>    -netdev filter-<plugin>,id=p0,filter=f0
>>    -device e1000,netdev=f0
>> NOTE:
>>    You can attach multiple plugins to the filter, dynamically add/remove
>> filter and filter-<plugin>.
>>
>> The netbuffer plugin:
>> Usage:
>>    -netdev tap,id=bn0  # you can use whatever backend as needed
>>    -netdev filter,id=f0,backend=bn0
>>    -netdev filter-buffer,id=p0,filter=f0
>>    -device e1000,netdev=f0
>>
>> Will supply a public API to release the buffer. But there's no
>> callers currently.
>> To test this feature, it's quite simple, just use
>> netdev_add filter-buffer,id=p0,filter=f0
>> to buffer packets,
>> netdev_del p0
>> will release packets.
>>
>> You can also implement whatever plugin you needed based on this filter.
>>
>> Yang Hongyang (9):
>>    netdev: Add a net filter
>>    virtio-net: add filter support
>>    filter: remove plugins when remove filter
>>    filter: remove filter before remove network backend
>>    filter: add netbuffer plugin
>>    introduce qemu_find_net_clients_by_model
>>    net/queue: export qemu_net_queue_append
>>    move out net queue structs define
>>    add a public api to release buffer
>>
>>   hw/net/virtio-net.c  |  17 ++-
>>   include/net/filter.h |  21 ++++
>>   include/net/net.h    |   5 +
>>   include/net/queue.h  |  26 ++++
>>   net/Makefile.objs    |   2 +
>>   net/clients.h        |   6 +
>>   net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
>>   net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
>>   net/net.c            |  51 +++++++-
>>   net/queue.c          |  31 +----
>>   qapi-schema.json     |  40 ++++++-
>>   11 files changed, 679 insertions(+), 36 deletions(-)
>>   create mode 100644 include/net/filter.h
>>   create mode 100644 net/filter-buffer.c
>>   create mode 100644 net/filter.c
>>
>
> Hi:
>
> Can you answer my question at
> http://lists.gnu.org/archive/html/qemu-devel/2015-07/msg04653.html?
>
> The main concern is why it must be a new kind of netdev?

Sorry, I missed that one... will reply in that thread.

>
> Thanks
> .
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-26 14:13   ` Yang Hongyang
@ 2015-07-27 10:32     ` Daniel P. Berrange
  2015-07-27 13:23       ` Yang Hongyang
  0 siblings, 1 reply; 19+ messages in thread
From: Daniel P. Berrange @ 2015-07-27 10:32 UTC (permalink / raw)
  To: Yang Hongyang
  Cc: thuth, zhanghailiang, jasowang, peter.huangpeng, mrhines,
	qemu-devel, stefanha

On Sun, Jul 26, 2015 at 10:13:55PM +0800, Yang Hongyang wrote:
> Thank you, and sorry to Daniel that I forgot to CC you...
> 
> On 07/25/2015 01:06 PM, zhanghailiang wrote:
> [...]
> >>
> >>                 +--------------+       +-------------+
> >>   +----------+  |    filter    |       |frontend(NIC)|
> >>   |      peer+-->              |       |             |
> >>   | network  <--+backend       <-------+ peer        |
> >>   | backend  |  |         peer +------->             |
> >>   +----------+  +--------------+       +-------------+
> >>
> >>Usage:
> >>   -netdev tap,id=bn0  # you can use whatever backend as needed
> >>   -netdev filter,id=f0,backend=bn0
> >>   -netdev filter-<plugin>,id=p0,filter=f0
> >>   -device e1000,netdev=f0
> >
> >Have you considered Daniel's suggestion ? Using the bellow style:
> 
> Yes, but by dig into the implementation, I think the current way is better,
> here is the reason:
> 
> 1. The flexibility to easily dynamically add/remove/change filters on the fly.
>    This is what Daniel was worrying about (please correct me if I didn't
>    get your point) I think I addressed his main concern on this series.
>    And you can specify any param to the filter plugin under existing netdev
>    design.
> 
> 2. Reuse as many existing code as we can. think about doing a standalone object,
>    add/remove filters will duplicate the existing netdev_add/netdev_del code.
>    the filter plugin need to implement at lease 3 functions, init/cleanup and
>    receive_filter, this is also duplicate the existing netdev design, we already
>    have the architecture to init/cleanup/receive_filter, why not use it?
> 
> 3. A filter is a backend in my design, so it is absolutely reasonable to
>    implement it as a netdev and it is easy to implement it as a netdev, if
>    you implement it as a standalone object, how do you integrate it to the
>    backend? A filter plugin might be able to be a standalone object, but just
>    as I said on #2, as long as we can archive our goal under the existing
>    design, why duplicate it?
> 
> 4. Current implementation don't affact the existing code too much, it is a
>    bolt-on feature.
> 
> Overall, we reuse the existing design, implemented a flexible and extensible
> net filter feature, so I think the current way is better.
> 
> 
> >   -netfilter id=f0,plugin=dump
> >   -netdev tap,id=bn0,filter=f0
> >   -device e1000,netdev=bn0
> >
> >Considering the filter as a new 'netdev' seems to be unreasonable,
> >Whenever we add a new plugin, we have to add a new member to
> >'NetClientOptions', there will be lots of 'filter' objects in NetClientOptions
> >area.
> 
> Why can't we extend this struct? I don't see any problem with this. Doing the
> other way is just to extend another struct.
> 
>  Besides when we want to describe a net device with several filter plugin
> >for VM,
> >it will become like:
> >    -netdev tap,id=bn0
> >    -netdev filter,id=f0,backend=bn0
> >    -netdev filter-<plugin-0>,id=p0,filter=f0
> >    -netdev filter-<plugin-1>,id=p1,filter=f1
> >    ... ...
> >    -device e1000,netdev=f0
> >Which is a little verbose for 'netdev' option.
> 
> It's just the name diffrence, using netfilter will be
> -netfilter ... -netfilter ...
> 
> using plugin=xxx will make us hard to extend the plugin params under existing
> netdev design thus will needs lots of extra effort to archive our goal, but we
> already have a simple way, do we? and do note that Daniel's concern was based
> on my initial RFC patch, which has a usage about "plugin=xxx", this series
> is totally different.

The current -netdev / netdev_add/netdev_del interfaces have a fairly
static view of the world. If you just want to setup filters at the
time you setup the guest NIC that's fine, but if you want to be able
to dynamically change the filters that are used, without altering
the guest device or the real host backend, I think you're going to
run into problems using -netdev. eg consider you have a pre-exisiting
guest running and you want to add in a 'dump' filter to temporarily
record traffic to a file, without having any impact on guest
connectivity. I'm not seeing how you could achieve that with the
proposed netdev approach, because you'd basically have to delete the
existing NIC and add a new one from scratch.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

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

* Re: [Qemu-devel] [PATCH 1/9] netdev: Add a net filter
  2015-07-24 10:55 ` [Qemu-devel] [PATCH 1/9] netdev: Add a net filter Yang Hongyang
@ 2015-07-27 12:38   ` Thomas Huth
  2015-07-27 13:15     ` Yang Hongyang
  0 siblings, 1 reply; 19+ messages in thread
From: Thomas Huth @ 2015-07-27 12:38 UTC (permalink / raw)
  To: Yang Hongyang, qemu-devel; +Cc: jasowang, mrhines, stefanha

On 24/07/15 12:55, Yang Hongyang wrote:
> This patch add a net filter between network backend and NIC devices.
> All packets will pass by this filter.
> TODO:
>   multiqueue support.
> 
>                 +--------------+       +-------------+
>   +----------+  |    filter    |       |frontend(NIC)|
>   |      peer+-->              |       |             |
>   | network  <--+backend       <-------+ peer        |
>   | backend  |  |         peer +------->             |
>   +----------+  +--------------+       +-------------+
> 
> Usage:
>   -netdev tap,id=bn0  # you can use whatever backend as needed
>   -netdev filter,id=f0,backend=bn0
>   -netdev filter-<plugin>,id=p0,filter=f0
>   -device e1000,netdev=f0
> NOTE:
>   You can attach multiple plugins to the filter, dynamically add/remove
> filter and filter-<plugin>.
>   A filter without plugin supplied will do nothing except pass by all
> packets, a plugin like dump for example, will dump all packets into a
> file. Or other plugins like a netbuffer plugin, will simply buffer the
> packets, release the packets when needed.
>   You can also implement whatever plugin you needed based on this filter.
> 
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>

 Hi,

just a quick comment: Please make sure to check your patches with
scripts/checkpatch.pl first before sending them for review - at least
for this patch, the script complains:

ERROR: do not use C99 // comments
#59: FILE: include/net/filter.h:12:
+//#include "qapi-types.h"

WARNING: braces {} are necessary for all arms of this statement
#424: FILE: net/filter.c:311:
+        if (plug->plugin == plugin)
[...]

total: 1 errors, 1 warnings, 463 lines checked

 Thomas

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

* Re: [Qemu-devel] [PATCH 1/9] netdev: Add a net filter
  2015-07-27 12:38   ` Thomas Huth
@ 2015-07-27 13:15     ` Yang Hongyang
  0 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-27 13:15 UTC (permalink / raw)
  To: Thomas Huth, qemu-devel; +Cc: jasowang, mrhines, stefanha



On 07/27/2015 08:38 PM, Thomas Huth wrote:
> On 24/07/15 12:55, Yang Hongyang wrote:
>> This patch add a net filter between network backend and NIC devices.
>> All packets will pass by this filter.
>> TODO:
>>    multiqueue support.
>>
>>                  +--------------+       +-------------+
>>    +----------+  |    filter    |       |frontend(NIC)|
>>    |      peer+-->              |       |             |
>>    | network  <--+backend       <-------+ peer        |
>>    | backend  |  |         peer +------->             |
>>    +----------+  +--------------+       +-------------+
>>
>> Usage:
>>    -netdev tap,id=bn0  # you can use whatever backend as needed
>>    -netdev filter,id=f0,backend=bn0
>>    -netdev filter-<plugin>,id=p0,filter=f0
>>    -device e1000,netdev=f0
>> NOTE:
>>    You can attach multiple plugins to the filter, dynamically add/remove
>> filter and filter-<plugin>.
>>    A filter without plugin supplied will do nothing except pass by all
>> packets, a plugin like dump for example, will dump all packets into a
>> file. Or other plugins like a netbuffer plugin, will simply buffer the
>> packets, release the packets when needed.
>>    You can also implement whatever plugin you needed based on this filter.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>
>   Hi,
>
> just a quick comment: Please make sure to check your patches with
> scripts/checkpatch.pl first before sending them for review - at least
> for this patch, the script complains:
>
> ERROR: do not use C99 // comments
> #59: FILE: include/net/filter.h:12:
> +//#include "qapi-types.h"
>
> WARNING: braces {} are necessary for all arms of this statement
> #424: FILE: net/filter.c:311:
> +        if (plug->plugin == plugin)
> [...]
>
> total: 1 errors, 1 warnings, 463 lines checked

Sorry for not done so this time, will check next time.
Thank you!

>
>   Thomas
>
>
> .
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-27 10:32     ` Daniel P. Berrange
@ 2015-07-27 13:23       ` Yang Hongyang
  0 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-27 13:23 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: thuth, zhanghailiang, jasowang, peter.huangpeng, mrhines,
	qemu-devel, stefanha

Hi,

   Thank you for the comment!

On 07/27/2015 06:32 PM, Daniel P. Berrange wrote:
> On Sun, Jul 26, 2015 at 10:13:55PM +0800, Yang Hongyang wrote:
[...]
>>> Which is a little verbose for 'netdev' option.
>>
>> It's just the name diffrence, using netfilter will be
>> -netfilter ... -netfilter ...
>>
>> using plugin=xxx will make us hard to extend the plugin params under existing
>> netdev design thus will needs lots of extra effort to archive our goal, but we
>> already have a simple way, do we? and do note that Daniel's concern was based
>> on my initial RFC patch, which has a usage about "plugin=xxx", this series
>> is totally different.
>
> The current -netdev / netdev_add/netdev_del interfaces have a fairly
> static view of the world. If you just want to setup filters at the
> time you setup the guest NIC that's fine, but if you want to be able
> to dynamically change the filters that are used, without altering
> the guest device or the real host backend, I think you're going to
> run into problems using -netdev. eg consider you have a pre-exisiting
> guest running and you want to add in a 'dump' filter to temporarily
> record traffic to a file, without having any impact on guest
> connectivity. I'm not seeing how you could achieve that with the
> proposed netdev approach, because you'd basically have to delete the
> existing NIC and add a new one from scratch.

We will modify the NIC's peer when using netdev_add to add the filter.
The current netdev_add/netdev_del can be used while guest is running.
just to make sure netdev's init/cleanup can do the right thing.

>
> Regards,
> Daniel
>

-- 
Thanks,
Yang.

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

* Re: [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter
  2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
                   ` (10 preceding siblings ...)
  2015-07-27  4:53 ` Jason Wang
@ 2015-07-29 10:34 ` Yang Hongyang
  11 siblings, 0 replies; 19+ messages in thread
From: Yang Hongyang @ 2015-07-29 10:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: jasowang, mrhines, thuth, stefanha

Sorry, please ignore this patchset.
As me and Jason came to an agreement of another way of implementation.
refer to thread:
http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg05445.html

I will send another patchset later.

On 07/24/2015 06:55 PM, Yang Hongyang wrote:
> This patch add a net filter between network backend and NIC devices.
> All packets will pass by this filter.
> Also implement a netbuffer plugin for example, the netbuffer plugin
> could be used by VM FT solutions like Macrocheckpointing,
> to buffer/release packets.
> Based on this, dump plugin could be easily implemented.
>
> I've done some simple tests on this series,
> backend, tap,user
> NIC, e1000,virtio-net
>
> There's still some missing functions to be done, I've posted this
> early in order to gain more comments, thank you!
>
> TODO:
>    multiqueue support.
>
>                  +--------------+       +-------------+
>    +----------+  |    filter    |       |frontend(NIC)|
>    |      peer+-->              |       |             |
>    | network  <--+backend       <-------+ peer        |
>    | backend  |  |         peer +------->             |
>    +----------+  +--------------+       +-------------+
>
> Usage:
>    -netdev tap,id=bn0  # you can use whatever backend as needed
>    -netdev filter,id=f0,backend=bn0
>    -netdev filter-<plugin>,id=p0,filter=f0
>    -device e1000,netdev=f0
> NOTE:
>    You can attach multiple plugins to the filter, dynamically add/remove
> filter and filter-<plugin>.
>
> The netbuffer plugin:
> Usage:
>    -netdev tap,id=bn0  # you can use whatever backend as needed
>    -netdev filter,id=f0,backend=bn0
>    -netdev filter-buffer,id=p0,filter=f0
>    -device e1000,netdev=f0
>
> Will supply a public API to release the buffer. But there's no
> callers currently.
> To test this feature, it's quite simple, just use
> netdev_add filter-buffer,id=p0,filter=f0
> to buffer packets,
> netdev_del p0
> will release packets.
>
> You can also implement whatever plugin you needed based on this filter.
>
> Yang Hongyang (9):
>    netdev: Add a net filter
>    virtio-net: add filter support
>    filter: remove plugins when remove filter
>    filter: remove filter before remove network backend
>    filter: add netbuffer plugin
>    introduce qemu_find_net_clients_by_model
>    net/queue: export qemu_net_queue_append
>    move out net queue structs define
>    add a public api to release buffer
>
>   hw/net/virtio-net.c  |  17 ++-
>   include/net/filter.h |  21 ++++
>   include/net/net.h    |   5 +
>   include/net/queue.h  |  26 ++++
>   net/Makefile.objs    |   2 +
>   net/clients.h        |   6 +
>   net/filter-buffer.c  | 185 ++++++++++++++++++++++++++++
>   net/filter.c         | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++
>   net/net.c            |  51 +++++++-
>   net/queue.c          |  31 +----
>   qapi-schema.json     |  40 ++++++-
>   11 files changed, 679 insertions(+), 36 deletions(-)
>   create mode 100644 include/net/filter.h
>   create mode 100644 net/filter-buffer.c
>   create mode 100644 net/filter.c
>

-- 
Thanks,
Yang.

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

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

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-24 10:55 [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 1/9] netdev: Add a net filter Yang Hongyang
2015-07-27 12:38   ` Thomas Huth
2015-07-27 13:15     ` Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 2/9] virtio-net: add filter support Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 3/9] filter: remove plugins when remove filter Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 4/9] filter: remove filter before remove network backend Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 5/9] filter: add netbuffer plugin Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 6/9] introduce qemu_find_net_clients_by_model Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 7/9] net/queue: export qemu_net_queue_append Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 8/9] move out net queue structs define Yang Hongyang
2015-07-24 10:55 ` [Qemu-devel] [PATCH 9/9] add a public api to release buffer Yang Hongyang
2015-07-25  5:06 ` [Qemu-devel] [PATCH 0/9] For QEMU 2.5: Add a net filter and a netbuffer plugin based on the filter zhanghailiang
2015-07-26 14:13   ` Yang Hongyang
2015-07-27 10:32     ` Daniel P. Berrange
2015-07-27 13:23       ` Yang Hongyang
2015-07-27  4:53 ` Jason Wang
2015-07-27  5:01   ` Yang Hongyang
2015-07-29 10:34 ` Yang Hongyang

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.