* [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter
@ 2015-08-04 8:30 Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 01/11] net: add a new object netfilter Yang Hongyang
` (10 more replies)
0 siblings, 11 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
This patch add a new object netfilter, capture all network packets.
Also implement a netbuffer based on this object.
the "buffer" netfilter could be used by VM FT solutions like
MicroCheckpointing, to buffer/release packets. Or to simulate
packet delay.
You can also get the series from:
https://github.com/macrosheep/qemu/tree/netfilter-v4
Usage:
-netdev tap,id=bn0
-netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
-device e1000,netdev=bn0
dynamically add/remove netfilters:
netfilter_add buffer,id=f0,netdev=bn0,chain=in,interval=1000
netfilter_del f0
NOTE:
interval's scale is microsecond.
chain is optional, and is one of in|out|all, default is "all".
"in" means this filter will receive packets sent to the @netdev
"out" means this filter will receive packets sent from the @netdev
"all" means this filter will receive packets both sent to/from
the @netdev
TODO:
- multiqueue support
- dump
v4:
- get rid of struct Filter
- squash the 4th patch into patch 2
- fix qemu_netfilter_pass_to_next_iov
- get rid of bh (buffer filter)
- release the packet to next filter instead of to receiver (buffer filter)
v3:
- add an api to pass the packet to next filter
- remove netfilters when delete netdev
- add qtest testcases for netfilter
- addressed comments from Jason
v2:
- add a chain option to netfilter object
- move the hook place earlier, before net_queue_send
- drop the unused api in buffer filter
- squash buffer filter patches into one
- remove receive() api from netfilter, only receive_iov() is enough
- addressed comments from Jason&Thomas
v1:
initial patch.
Yang Hongyang (11):
net: add a new object netfilter
init/cleanup of netfilter object
netfilter: add netfilter_{add|del} commands
net: delete netfilter object when delete netdev
netfilter: hook packets before net queue send
netfilter: add an API to pass the packet to next filter
net/queue: export qemu_net_queue_append_iov
move out net queue structs define
netfilter: add a netbuffer filter
filter/buffer: update command description and help
tests: add test cases for netfilter object
hmp-commands.hx | 30 +++++
hmp.c | 29 +++++
hmp.h | 4 +
include/net/filter.h | 69 ++++++++++++
include/net/net.h | 1 +
include/net/queue.h | 26 +++++
include/qemu/typedefs.h | 1 +
include/sysemu/sysemu.h | 1 +
monitor.c | 33 ++++++
net/Makefile.objs | 2 +
net/filter-buffer.c | 120 ++++++++++++++++++++
net/filter.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++
net/filters.h | 17 +++
net/net.c | 81 ++++++++++++-
net/queue.c | 31 +----
qapi-schema.json | 100 +++++++++++++++++
qemu-options.hx | 4 +
qmp-commands.hx | 57 ++++++++++
tests/.gitignore | 1 +
tests/Makefile | 2 +
tests/test-netfilter.c | 194 ++++++++++++++++++++++++++++++++
vl.c | 13 +++
22 files changed, 1083 insertions(+), 26 deletions(-)
create mode 100644 include/net/filter.h
create mode 100644 net/filter-buffer.c
create mode 100644 net/filter.c
create mode 100644 net/filters.h
create mode 100644 tests/test-netfilter.c
--
1.9.1
^ permalink raw reply [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 01/11] net: add a new object netfilter
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object Yang Hongyang
` (9 subsequent siblings)
10 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Paolo Bonzini, Yang Hongyang
Add the framework for a new netfilter object and a new
-netfilter CLI option as a basis for the following patches.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Eric Blake <eblake@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
include/net/filter.h | 15 +++++++++++++++
include/sysemu/sysemu.h | 1 +
net/Makefile.objs | 1 +
net/filter.c | 27 +++++++++++++++++++++++++++
qemu-options.hx | 1 +
vl.c | 13 +++++++++++++
6 files changed, 58 insertions(+)
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..4242ded
--- /dev/null
+++ b/include/net/filter.h
@@ -0,0 +1,15 @@
+/*
+ * 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"
+
+int net_init_filters(void);
+
+#endif /* QEMU_NET_FILTER_H */
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 44570d1..15d6d00 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -212,6 +212,7 @@ extern QemuOptsList qemu_chardev_opts;
extern QemuOptsList qemu_device_opts;
extern QemuOptsList qemu_netdev_opts;
extern QemuOptsList qemu_net_opts;
+extern QemuOptsList qemu_netfilter_opts;
extern QemuOptsList qemu_global_opts;
extern QemuOptsList qemu_mon_opts;
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/filter.c b/net/filter.c
new file mode 100644
index 0000000..4e40f08
--- /dev/null
+++ b/net/filter.c
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+#include "qemu-common.h"
+#include "net/filter.h"
+
+int net_init_filters(void)
+{
+ return 0;
+}
+
+QemuOptsList qemu_netfilter_opts = {
+ .name = "netfilter",
+ .implied_opt_name = "type",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_netfilter_opts.head),
+ .desc = {
+ /*
+ * no elements => accept any params
+ * validation will happen later
+ */
+ { /* end of list */ }
+ },
+};
diff --git a/qemu-options.hx b/qemu-options.hx
index 77f5853..0d52d02 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1575,6 +1575,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
"socket][,vlan=n][,option][,option][,...]\n"
" old way to initialize a host network interface\n"
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
+DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter, "", QEMU_ARCH_ALL)
STEXI
@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
@findex -net
diff --git a/vl.c b/vl.c
index 0adbbd6..3b70371 100644
--- a/vl.c
+++ b/vl.c
@@ -75,6 +75,7 @@ int main(int argc, char **argv)
#include "monitor/qdev.h"
#include "sysemu/bt.h"
#include "net/net.h"
+#include "net/filter.h"
#include "net/slirp.h"
#include "monitor/monitor.h"
#include "ui/console.h"
@@ -2998,6 +2999,7 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_device_opts);
qemu_add_opts(&qemu_netdev_opts);
qemu_add_opts(&qemu_net_opts);
+ qemu_add_opts(&qemu_netfilter_opts);
qemu_add_opts(&qemu_rtc_opts);
qemu_add_opts(&qemu_global_opts);
qemu_add_opts(&qemu_mon_opts);
@@ -3284,6 +3286,13 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
break;
+ case QEMU_OPTION_netfilter:
+ opts = qemu_opts_parse_noisily(qemu_find_opts("netfilter"),
+ optarg, true);
+ if (!opts) {
+ exit(1);
+ }
+ break;
#ifdef CONFIG_LIBISCSI
case QEMU_OPTION_iscsi:
opts = qemu_opts_parse_noisily(qemu_find_opts("iscsi"),
@@ -4413,6 +4422,10 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ if (net_init_filters() < 0) {
+ exit(1);
+ }
+
#ifdef CONFIG_TPM
if (tpm_init() < 0) {
exit(1);
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 01/11] net: add a new object netfilter Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:07 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 03/11] netfilter: add netfilter_{add|del} commands Yang Hongyang
` (8 subsequent siblings)
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
QTAILQ_ENTRY global_list but used by filter layer, so that we can
manage all filters together.
QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
in this queue.
This is mostly the same with init/cleanup of netdev object.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
include/net/filter.h | 39 +++++++++++++
include/net/net.h | 1 +
include/qemu/typedefs.h | 1 +
net/filter.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net.c | 1 +
qapi-schema.json | 37 ++++++++++++
6 files changed, 226 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index 4242ded..9aafe08 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -9,7 +9,46 @@
#define QEMU_NET_FILTER_H
#include "qemu-common.h"
+#include "qemu/typedefs.h"
+
+/* the netfilter chain */
+enum {
+ NET_FILTER_IN,
+ NET_FILTER_OUT,
+ NET_FILTER_ALL,
+};
+
+typedef void (FilterCleanup) (NetFilterState *);
+/*
+ * Return:
+ * 0: finished handling the packet, we should continue
+ * size: filter stolen this packet, we stop pass this packet further
+ */
+typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState *sender,
+ unsigned flags, const struct iovec *, int);
+
+typedef struct NetFilterInfo {
+ NetFilterOptionsKind type;
+ size_t size;
+ FilterCleanup *cleanup;
+ FilterReceiveIOV *receive_iov;
+} NetFilterInfo;
+
+struct NetFilterState {
+ NetFilterInfo *info;
+ char *model;
+ char *name;
+ NetClientState *netdev;
+ int chain;
+ QTAILQ_ENTRY(NetFilterState) global_list;
+ QTAILQ_ENTRY(NetFilterState) next;
+};
int net_init_filters(void);
+NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
+ NetClientState *netdev,
+ const char *model,
+ const char *name,
+ int chain);
#endif /* QEMU_NET_FILTER_H */
diff --git a/include/net/net.h b/include/net/net.h
index 6a6cbef..36e5fab 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -92,6 +92,7 @@ struct NetClientState {
NetClientDestructor *destructor;
unsigned int queue_index;
unsigned rxfilter_notify_enabled:1;
+ QTAILQ_HEAD(, NetFilterState) filters;
};
typedef struct NICState {
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 6fdcbcd..2f75109 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -45,6 +45,7 @@ typedef struct Monitor Monitor;
typedef struct MouseTransformInfo MouseTransformInfo;
typedef struct MSIMessage MSIMessage;
typedef struct NetClientState NetClientState;
+typedef struct NetFilterState NetFilterState;
typedef struct NICInfo NICInfo;
typedef struct PcGuestInfo PcGuestInfo;
typedef struct PCIBridge PCIBridge;
diff --git a/net/filter.c b/net/filter.c
index 4e40f08..d85eec5 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -6,10 +6,157 @@
*/
#include "qemu-common.h"
+#include "qapi-visit.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
+#include "qapi-visit.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/dealloc-visitor.h"
+#include "qemu/config-file.h"
+
#include "net/filter.h"
+#include "net/net.h"
+
+static QTAILQ_HEAD(, NetFilterState) net_filters;
+
+NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
+ NetClientState *netdev,
+ const char *model,
+ const char *name,
+ int chain)
+{
+ NetFilterState *nf;
+
+ assert(info->size >= sizeof(NetFilterState));
+ assert(info->receive_iov);
+
+ nf = g_malloc0(info->size);
+ nf->info = info;
+ nf->model = g_strdup(model);
+ nf->name = g_strdup(name);
+ nf->netdev = netdev;
+ nf->chain = chain;
+ QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
+ QTAILQ_INSERT_TAIL(&netdev->filters, nf, next);
+
+ return nf;
+}
+
+static inline void qemu_cleanup_net_filter(NetFilterState *nf)
+{
+ QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
+ QTAILQ_REMOVE(&net_filters, nf, global_list);
+
+ if (nf->info->cleanup) {
+ nf->info->cleanup(nf);
+ }
+
+ g_free(nf->name);
+ g_free(nf->model);
+ g_free(nf);
+}
+
+typedef int (NetFilterInit)(const NetFilterOptions *opts,
+ const char *name, int chain,
+ NetClientState *netdev, Error **errp);
+
+static
+NetFilterInit * const net_filter_init_fun[NET_FILTER_OPTIONS_KIND_MAX] = {
+};
+
+static int net_filter_init1(const NetFilter *netfilter, Error **errp)
+{
+ NetClientState *netdev = NULL;
+ NetClientState *ncs[MAX_QUEUE_NUM];
+ const char *name = netfilter->id;
+ const char *netdev_id = netfilter->netdev;
+ const char *chain_str = NULL;
+ const NetFilterOptions *opts = netfilter->opts;
+ int chain, queues;
+
+ if (!net_filter_init_fun[opts->kind]) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+ "a net filter type");
+ return -1;
+ }
+
+ if (netfilter->has_chain) {
+ chain_str = netfilter->chain;
+ if (!strcmp(chain_str, "in")) {
+ chain = NET_FILTER_IN;
+ } else if (!strcmp(chain_str, "out")) {
+ chain = NET_FILTER_OUT;
+ } else if (!strcmp(chain_str, "all")) {
+ chain = NET_FILTER_ALL;
+ } else {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "chain",
+ "netfilter chain (in/out/all)");
+ return -1;
+ }
+ } else {
+ /* default */
+ chain = NET_FILTER_ALL;
+ }
+
+ queues = qemu_find_net_clients_except(netdev_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, QERR_INVALID_PARAMETER_VALUE, "netdev",
+ "a network backend id");
+ return -1;
+ }
+
+ netdev = ncs[0];
+
+ if (net_filter_init_fun[opts->kind](opts, name, chain, netdev, errp) < 0) {
+ if (errp && !*errp) {
+ error_setg(errp, QERR_DEVICE_INIT_FAILED,
+ NetFilterOptionsKind_lookup[opts->kind]);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+static int net_init_filter(void *dummy, QemuOpts *opts, Error **errp)
+{
+ NetFilter *object = NULL;
+ Error *err = NULL;
+ int ret = -1;
+ OptsVisitor *ov = opts_visitor_new(opts);
+
+ visit_type_NetFilter(opts_get_visitor(ov), &object, NULL, &err);
+ opts_visitor_cleanup(ov);
+
+ if (!err) {
+ ret = net_filter_init1(object, &err);
+ }
+
+ if (object) {
+ QapiDeallocVisitor *dv = qapi_dealloc_visitor_new();
+
+ visit_type_NetFilter(qapi_dealloc_get_visitor(dv), &object, NULL, NULL);
+ qapi_dealloc_visitor_cleanup(dv);
+ }
+
+ error_propagate(errp, err);
+ return ret;
+}
int net_init_filters(void)
{
+ QTAILQ_INIT(&net_filters);
+
+ if (qemu_opts_foreach(qemu_find_opts("netfilter"),
+ net_init_filter, NULL, NULL)) {
+ return -1;
+ }
+
return 0;
}
diff --git a/net/net.c b/net/net.c
index 28a5597..d9b70cd 100644
--- a/net/net.c
+++ b/net/net.c
@@ -287,6 +287,7 @@ static void qemu_net_client_setup(NetClientState *nc,
nc->incoming_queue = qemu_new_net_queue(nc);
nc->destructor = destructor;
+ QTAILQ_INIT(&nc->filters);
}
NetClientState *qemu_new_net_client(NetClientInfo *info,
diff --git a/qapi-schema.json b/qapi-schema.json
index 4342a08..d7fb578 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2537,6 +2537,43 @@
'opts': 'NetClientOptions' } }
##
+# @NetFilterOptions
+#
+# A discriminated record of network filters.
+#
+# Since 2.5
+#
+##
+{ 'union': 'NetFilterOptions',
+ 'data': { } }
+
+##
+# @NetFilter
+#
+# Captures the packets of a network backend.
+#
+# @id: identifier for monitor commands
+#
+# @netdev: the network backend it attached to
+#
+# @chain: #optional accept "in","out","all", if not specified, default is "all"
+# "in" means this filter will receive packets sent to the @netdev
+# "out" means this filter will receive packets sent from the @netdev
+# "all" means this filter will receive packets both sent to/from
+# the @netdev
+#
+# @opts: filter type specific properties
+#
+# Since 2.5
+##
+{ 'struct': 'NetFilter',
+ 'data': {
+ 'id': 'str',
+ 'netdev': 'str',
+ '*chain': 'str',
+ 'opts': 'NetFilterOptions' } }
+
+##
# @InetSocketAddress
#
# Captures a socket address or address range in the Internet namespace.
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 03/11] netfilter: add netfilter_{add|del} commands
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 01/11] net: add a new object netfilter Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev Yang Hongyang
` (7 subsequent siblings)
10 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
Markus Armbruster, mrhines, Luiz Capitulino, stefanha,
Yang Hongyang
add netfilter_{add|del} commands
This is mostly the same with netdev_{add|del} commands.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Luiz Capitulino <lcapitulino@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
CC: Eric Blake <eblake@redhat.com>
---
hmp-commands.hx | 30 +++++++++++++++++++++
hmp.c | 29 ++++++++++++++++++++
hmp.h | 4 +++
include/net/filter.h | 2 ++
monitor.c | 33 +++++++++++++++++++++++
net/filter.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++-
qapi-schema.json | 47 ++++++++++++++++++++++++++++++++
qmp-commands.hx | 57 +++++++++++++++++++++++++++++++++++++++
8 files changed, 277 insertions(+), 1 deletion(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index d3b7932..902e2d1 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1253,6 +1253,36 @@ Remove host network device.
ETEXI
{
+ .name = "netfilter_add",
+ .args_type = "netfilter:O",
+ .params = "[type],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
+ .help = "add netfilter",
+ .mhandler.cmd = hmp_netfilter_add,
+ .command_completion = netfilter_add_completion,
+ },
+
+STEXI
+@item netfilter_add
+@findex netfilter_add
+Add netfilter.
+ETEXI
+
+ {
+ .name = "netfilter_del",
+ .args_type = "id:s",
+ .params = "id",
+ .help = "remove netfilter",
+ .mhandler.cmd = hmp_netfilter_del,
+ .command_completion = netfilter_del_completion,
+ },
+
+STEXI
+@item netfilter_del
+@findex netfilter_del
+Remove netfilter.
+ETEXI
+
+ {
.name = "object_add",
.args_type = "object:O",
.params = "[qom-type=]type,id=str[,prop=value][,...]",
diff --git a/hmp.c b/hmp.c
index dcc66f1..09e3cda 100644
--- a/hmp.c
+++ b/hmp.c
@@ -15,6 +15,7 @@
#include "hmp.h"
#include "net/net.h"
+#include "net/filter.h"
#include "net/eth.h"
#include "sysemu/char.h"
#include "sysemu/block-backend.h"
@@ -1599,6 +1600,34 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &err);
}
+void hmp_netfilter_add(Monitor *mon, const QDict *qdict)
+{
+ Error *err = NULL;
+ QemuOpts *opts;
+
+ opts = qemu_opts_from_qdict(qemu_find_opts("netfilter"), qdict, &err);
+ if (err) {
+ goto out;
+ }
+
+ netfilter_add(opts, &err);
+ if (err) {
+ qemu_opts_del(opts);
+ }
+
+out:
+ hmp_handle_error(mon, &err);
+}
+
+void hmp_netfilter_del(Monitor *mon, const QDict *qdict)
+{
+ const char *id = qdict_get_str(qdict, "id");
+ Error *err = NULL;
+
+ qmp_netfilter_del(id, &err);
+ hmp_handle_error(mon, &err);
+}
+
void hmp_object_add(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
diff --git a/hmp.h b/hmp.h
index 0cf4f2a..a21dbbb 100644
--- a/hmp.h
+++ b/hmp.h
@@ -85,6 +85,8 @@ void hmp_device_del(Monitor *mon, const QDict *qdict);
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
void hmp_netdev_add(Monitor *mon, const QDict *qdict);
void hmp_netdev_del(Monitor *mon, const QDict *qdict);
+void hmp_netfilter_add(Monitor *mon, const QDict *qdict);
+void hmp_netfilter_del(Monitor *mon, const QDict *qdict);
void hmp_getfd(Monitor *mon, const QDict *qdict);
void hmp_closefd(Monitor *mon, const QDict *qdict);
void hmp_sendkey(Monitor *mon, const QDict *qdict);
@@ -112,6 +114,8 @@ void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str);
void set_link_completion(ReadLineState *rs, int nb_args, const char *str);
void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str);
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str);
+void netfilter_add_completion(ReadLineState *rs, int nb_args, const char *str);
+void netfilter_del_completion(ReadLineState *rs, int nb_args, const char *str);
void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str);
void watchdog_action_completion(ReadLineState *rs, int nb_args,
const char *str);
diff --git a/include/net/filter.h b/include/net/filter.h
index 9aafe08..8eff85a 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -50,5 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
const char *model,
const char *name,
int chain);
+void netfilter_add(QemuOpts *opts, Error **errp);
+void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
#endif /* QEMU_NET_FILTER_H */
diff --git a/monitor.c b/monitor.c
index aeea2b5..d6b8f24 100644
--- a/monitor.c
+++ b/monitor.c
@@ -31,6 +31,7 @@
#include "hw/loader.h"
#include "exec/gdbstub.h"
#include "net/net.h"
+#include "net/filter.h"
#include "net/slirp.h"
#include "sysemu/char.h"
#include "ui/qemu-spice.h"
@@ -4193,6 +4194,21 @@ void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
}
}
+void netfilter_add_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ size_t len;
+ int i;
+
+ if (nb_args != 2) {
+ return;
+ }
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ for (i = 0; NetFilterOptionsKind_lookup[i]; i++) {
+ add_completion_option(rs, str, NetFilterOptionsKind_lookup[i]);
+ }
+}
+
void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
{
GSList *list, *elt;
@@ -4429,6 +4445,23 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
}
}
+void netfilter_del_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+ int len;
+ QemuOpts *opts;
+
+ if (nb_args != 2) {
+ return;
+ }
+
+ len = strlen(str);
+ readline_set_completion_index(rs, len);
+ opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), str);
+ if (opts) {
+ readline_add_completion(rs, str);
+ }
+}
+
void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
{
int i;
diff --git a/net/filter.c b/net/filter.c
index d85eec5..54a5c06 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -13,6 +13,7 @@
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
#include "qemu/config-file.h"
+#include "qmp-commands.h"
#include "net/filter.h"
#include "net/net.h"
@@ -42,7 +43,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
return nf;
}
-static inline void qemu_cleanup_net_filter(NetFilterState *nf)
+static void qemu_cleanup_net_filter(NetFilterState *nf)
{
QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
QTAILQ_REMOVE(&net_filters, nf, global_list);
@@ -56,6 +57,79 @@ static inline void qemu_cleanup_net_filter(NetFilterState *nf)
g_free(nf);
}
+static void qemu_del_net_filter(NetFilterState *nf)
+{
+ /* handle multi queue? */
+ qemu_cleanup_net_filter(nf);
+}
+
+static NetFilterState *qemu_find_netfilter(const char *id)
+{
+ NetFilterState *nf;
+
+ QTAILQ_FOREACH(nf, &net_filters, global_list) {
+ if (!strcmp(nf->name, id)) {
+ return nf;
+ }
+ }
+
+ return NULL;
+}
+
+static int net_init_filter(void *dummy, QemuOpts *opts, Error **errp);
+void netfilter_add(QemuOpts *opts, Error **errp)
+{
+ net_init_filter(NULL, opts, errp);
+}
+
+void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp)
+{
+ Error *local_err = NULL;
+ QemuOptsList *opts_list;
+ QemuOpts *opts;
+
+ opts_list = qemu_find_opts_err("netfilter", &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
+ netfilter_add(opts, &local_err);
+ if (local_err) {
+ qemu_opts_del(opts);
+ goto out;
+ }
+
+out:
+ error_propagate(errp, local_err);
+}
+
+void qmp_netfilter_del(const char *id, Error **errp)
+{
+ NetFilterState *nf;
+ QemuOpts *opts;
+
+ nf = qemu_find_netfilter(id);
+ if (!nf) {
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "Device '%s' not found", id);
+ return;
+ }
+
+ opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), id);
+ if (!opts) {
+ error_setg(errp, "Device '%s' is not a netfilter", id);
+ return;
+ }
+
+ qemu_del_net_filter(nf);
+ qemu_opts_del(opts);
+}
+
typedef int (NetFilterInit)(const NetFilterOptions *opts,
const char *name, int chain,
NetClientState *netdev, Error **errp);
diff --git a/qapi-schema.json b/qapi-schema.json
index d7fb578..9d97c21 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2537,6 +2537,53 @@
'opts': 'NetClientOptions' } }
##
+# @netfilter_add:
+#
+# Add a netfilter.
+#
+# @type: the type of netfilter.
+#
+# @id: the name of the new netfilter.
+#
+# @netdev: the name of the netdev which this filter will be attached to.
+#
+# @chain: #optional accept "in","out","all", if not specified, default is "all"
+# "in" means this filter will receive packets sent to the @netdev
+# "out" means this filter will receive packets sent from the @netdev
+# "all" means this filter will receive packets both sent to/from
+# the @netdev
+#
+# @props: #optional a list of properties to be passed to the netfilter in
+# the format of 'name=value'
+#
+# Since: 2.5
+#
+# Returns: Nothing on success
+# If @type is not a valid netfilter, DeviceNotFound
+##
+{ 'command': 'netfilter_add',
+ 'data': {
+ 'type': 'str',
+ 'id': 'str',
+ 'netdev': 'str',
+ '*chain': 'str',
+ '*props': '**'}, 'gen': false }
+
+##
+# @netfilter_del:
+#
+# Remove a netfilter.
+#
+# @id: the name of the netfilter to remove
+#
+# Returns: Nothing on success
+# If @id is not a valid netfilter, DeviceNotFound
+#
+# Since: 2.5
+##
+{ 'command': 'netfilter_del', 'data': {'id': 'str'} }
+
+##
# @NetFilterOptions
#
# A discriminated record of network filters.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ba630b1..4f0dc98 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -926,6 +926,63 @@ Example:
EQMP
{
+ .name = "netfilter_add",
+ .args_type = "netfilter:O",
+ .mhandler.cmd_new = qmp_netfilter_add,
+ },
+
+SQMP
+netfilter_add
+----------
+
+Add netfilter.
+
+Arguments:
+
+- "type": the filter type (json-string)
+- "id": the netfilter's ID, must be unique (json-string)
+- "netdev": the netdev's ID which this filter will be attached to(json-string)
+- filter options
+
+Example:
+
+-> { "execute": "netfilter_add",
+ "arguments": { "type": "type", "id": "nf0",
+ "netdev": "bn",
+ "chain": "in" } }
+<- { "return": {} }
+
+Note: The supported filter options are the same ones supported by the
+ '-netfilter' command-line argument, which are listed in the '-help'
+ output or QEMU's manual
+
+EQMP
+
+ {
+ .name = "netfilter_del",
+ .args_type = "id:s",
+ .mhandler.cmd_new = qmp_marshal_input_netfilter_del,
+ },
+
+SQMP
+netfilter_del
+----------
+
+Remove netfilter.
+
+Arguments:
+
+- "id": the netfilter's ID, must be unique (json-string)
+
+Example:
+
+-> { "execute": "netfilter_del", "arguments": { "id": "nf0" } }
+<- { "return": {} }
+
+
+EQMP
+
+ {
.name = "object-add",
.args_type = "qom-type:s,id:s,props:q?",
.mhandler.cmd_new = qmp_object_add,
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (2 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 03/11] netfilter: add netfilter_{add|del} commands Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:09 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send Yang Hongyang
` (6 subsequent siblings)
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
When we delete the netdev, we also delete the netfilter object
attached to it, because if the netdev is removed, the filters
which attached to it is useless.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
include/net/filter.h | 1 +
net/filter.c | 2 +-
net/net.c | 14 ++++++++++++++
3 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/include/net/filter.h b/include/net/filter.h
index 8eff85a..c146be2 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -50,6 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
const char *model,
const char *name,
int chain);
+void qemu_del_net_filter(NetFilterState *nf);
void netfilter_add(QemuOpts *opts, Error **errp);
void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
diff --git a/net/filter.c b/net/filter.c
index 54a5c06..24ec4e1 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -57,7 +57,7 @@ static void qemu_cleanup_net_filter(NetFilterState *nf)
g_free(nf);
}
-static void qemu_del_net_filter(NetFilterState *nf)
+void qemu_del_net_filter(NetFilterState *nf)
{
/* handle multi queue? */
qemu_cleanup_net_filter(nf);
diff --git a/net/net.c b/net/net.c
index d9b70cd..03b2296 100644
--- a/net/net.c
+++ b/net/net.c
@@ -28,6 +28,7 @@
#include "hub.h"
#include "net/slirp.h"
#include "net/eth.h"
+#include "net/filter.h"
#include "util.h"
#include "monitor/monitor.h"
@@ -385,6 +386,8 @@ void qemu_del_net_client(NetClientState *nc)
{
NetClientState *ncs[MAX_QUEUE_NUM];
int queues, i;
+ NetFilterState *nf, *next;
+ QemuOpts *opts;
assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
@@ -396,6 +399,17 @@ void qemu_del_net_client(NetClientState *nc)
MAX_QUEUE_NUM);
assert(queues != 0);
+ /*
+ * we delete/free the netfilter object attached to this netdev
+ * multiqueue netfilter is not supported now, so only delete
+ * nc->filters is enough.
+ */
+ QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
+ opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), nf->name);
+ qemu_del_net_filter(nf);
+ qemu_opts_del(opts);
+ }
+
/* 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) {
NICState *nic = qemu_get_nic(nc->peer);
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (3 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:13 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter Yang Hongyang
` (5 subsequent siblings)
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
Capture packets that will be sent.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
net/net.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 65 insertions(+), 1 deletion(-)
diff --git a/net/net.c b/net/net.c
index 03b2296..efccd56 100644
--- a/net/net.c
+++ b/net/net.c
@@ -569,6 +569,42 @@ int qemu_can_send_packet(NetClientState *sender)
return 1;
}
+static ssize_t filter_receive_iov(NetClientState *nc, int chain,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt)
+{
+ ssize_t ret = 0;
+ NetFilterState *nf = NULL;
+ ssize_t size = iov_size(iov, iovcnt);
+
+ QTAILQ_FOREACH(nf, &nc->filters, next) {
+ if (nf->chain == chain || nf->chain == NET_FILTER_ALL) {
+ ret = nf->info->receive_iov(nf, sender, flags, iov, iovcnt);
+ if (ret == size) {
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t filter_receive(NetClientState *nc, int chain,
+ NetClientState *sender,
+ unsigned flags,
+ const uint8_t *data,
+ size_t size)
+{
+ struct iovec iov = {
+ .iov_base = (void *)data,
+ .iov_len = size
+ };
+
+ return filter_receive_iov(nc, chain, sender, flags, &iov, 1);
+}
+
ssize_t qemu_deliver_packet(NetClientState *sender,
unsigned flags,
const uint8_t *data,
@@ -640,6 +676,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
NetPacketSent *sent_cb)
{
NetQueue *queue;
+ int ret;
#ifdef DEBUG_NET
printf("qemu_send_packet_async:\n");
@@ -650,6 +687,18 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
return size;
}
+ /* Let filters handle the packet first */
+ ret = filter_receive(sender, NET_FILTER_OUT, sender, flags, buf, size);
+ if (ret == size) {
+ return size;
+ }
+
+ ret = filter_receive(sender->peer, NET_FILTER_IN,
+ sender, flags, buf, size);
+ if (ret == size) {
+ return size;
+ }
+
queue = sender->peer->incoming_queue;
return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
@@ -720,9 +769,24 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
NetPacketSent *sent_cb)
{
NetQueue *queue;
+ int size = iov_size(iov, iovcnt);
+ int ret;
if (sender->link_down || !sender->peer) {
- return iov_size(iov, iovcnt);
+ return size;
+ }
+
+ /* Let filters handle the packet first */
+ ret = filter_receive_iov(sender, NET_FILTER_OUT,
+ sender, QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt);
+ if (ret == size) {
+ return size;
+ }
+
+ ret = filter_receive_iov(sender->peer, NET_FILTER_IN,
+ sender, QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt);
+ if (ret == size) {
+ return size;
}
queue = sender->peer->incoming_queue;
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (4 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:16 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 07/11] net/queue: export qemu_net_queue_append_iov Yang Hongyang
` (4 subsequent siblings)
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
add an API qemu_netfilter_pass_to_next_iov() to pass the packet
to next filter, and a wrapper qemu_netfilter_pass_to_next().
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
include/net/filter.h | 12 ++++++++++++
net/filter.c | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index c146be2..867d5aa 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -54,4 +54,16 @@ void qemu_del_net_filter(NetFilterState *nf);
void netfilter_add(QemuOpts *opts, Error **errp);
void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
+/* pass the packet to the next filter */
+void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt);
+void qemu_netfilter_pass_to_next(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const uint8_t *data,
+ size_t size);
+
#endif /* QEMU_NET_FILTER_H */
diff --git a/net/filter.c b/net/filter.c
index 24ec4e1..166b851 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -14,9 +14,11 @@
#include "qapi/dealloc-visitor.h"
#include "qemu/config-file.h"
#include "qmp-commands.h"
+#include "qemu/iov.h"
#include "net/filter.h"
#include "net/net.h"
+#include "net/queue.h"
static QTAILQ_HEAD(, NetFilterState) net_filters;
@@ -130,6 +132,47 @@ void qmp_netfilter_del(const char *id, Error **errp)
qemu_opts_del(opts);
}
+void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt)
+{
+ int ret = 0;
+ ssize_t size = iov_size(iov, iovcnt);
+ NetFilterState *next = QTAILQ_NEXT(nf, next);
+
+ while (next) {
+ if (next->chain == nf->chain || next->chain == NET_FILTER_ALL) {
+ ret = next->info->receive_iov(next, sender, flags, iov, iovcnt);
+ if (ret == size) {
+ return;
+ }
+ }
+ next = QTAILQ_NEXT(next, next);
+ }
+
+ /* we have gone through all filters, pass it to receiver */
+ if (sender && sender->peer) {
+ qemu_net_queue_send_iov(sender->peer->incoming_queue, sender, flags,
+ iov, iovcnt, NULL);
+ }
+}
+
+void qemu_netfilter_pass_to_next(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const uint8_t *data,
+ size_t size)
+{
+ struct iovec iov = {
+ .iov_base = (void *)data,
+ .iov_len = size
+ };
+
+ return qemu_netfilter_pass_to_next_iov(nf, sender, flags, &iov, 1);
+}
+
typedef int (NetFilterInit)(const NetFilterOptions *opts,
const char *name, int chain,
NetClientState *netdev, Error **errp);
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 07/11] net/queue: export qemu_net_queue_append_iov
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (5 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 08/11] move out net queue structs define Yang Hongyang
` (3 subsequent siblings)
10 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, 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..f10fab0 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_iov(NetQueue *queue,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ 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..c34a3e0 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -110,12 +110,12 @@ static void qemu_net_queue_append(NetQueue *queue,
QTAILQ_INSERT_TAIL(&queue->packets, packet, entry);
}
-static void qemu_net_queue_append_iov(NetQueue *queue,
- NetClientState *sender,
- unsigned flags,
- const struct iovec *iov,
- int iovcnt,
- NetPacketSent *sent_cb)
+void qemu_net_queue_append_iov(NetQueue *queue,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
{
NetPacket *packet;
size_t max_len = 0;
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 08/11] move out net queue structs define
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (6 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 07/11] net/queue: export qemu_net_queue_append_iov Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter Yang Hongyang
` (2 subsequent siblings)
10 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, 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 f10fab0..e139cc7 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 c34a3e0..428fdd6 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] 37+ messages in thread
* [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (7 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 08/11] move out net queue structs define Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:21 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 11/11] tests: add test cases for netfilter object Yang Hongyang
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
This filter is to buffer/release packets, this feature can be used
when using MicroCheckpointing, or other Remus like VM FT solutions, you
can also use it to simulate the network delay.
It has an interval option, if supplied, this filter will release
packets by interval.
Usage:
-netdev tap,id=bn0
-netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
NOTE:
the scale of interval is microsecond.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
v4: remove bh
pass the packet to next filter instead of receiver
v3: check packet's sender and sender->peer when flush it
---
net/Makefile.objs | 1 +
net/filter-buffer.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
net/filter.c | 2 +
net/filters.h | 17 ++++++++
qapi-schema.json | 18 +++++++-
5 files changed, 157 insertions(+), 1 deletion(-)
create mode 100644 net/filter-buffer.c
create mode 100644 net/filters.h
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/filter-buffer.c b/net/filter-buffer.c
new file mode 100644
index 0000000..fd467db
--- /dev/null
+++ b/net/filter-buffer.c
@@ -0,0 +1,120 @@
+/*
+ * 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/filter.h"
+#include "net/queue.h"
+#include "filters.h"
+#include "qemu-common.h"
+#include "qemu/timer.h"
+#include "qemu/iov.h"
+
+typedef struct FILTERBUFFERState {
+ NetFilterState nf;
+ NetQueue *incoming_queue;
+ int64_t interval;
+ QEMUTimer release_timer;
+} FILTERBUFFERState;
+
+static void packet_send_completed(NetClientState *nc, ssize_t len)
+{
+ return;
+}
+
+static void filter_buffer_flush(NetFilterState *nf)
+{
+ FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
+ NetQueue *queue = s->incoming_queue;
+ NetPacket *packet;
+
+ while (queue && !QTAILQ_EMPTY(&queue->packets)) {
+ packet = QTAILQ_FIRST(&queue->packets);
+ QTAILQ_REMOVE(&queue->packets, packet, entry);
+ queue->nq_count--;
+
+ if (packet->sender && packet->sender->peer) {
+ qemu_netfilter_pass_to_next(nf, packet->sender, packet->flags,
+ packet->data, packet->size);
+ }
+
+ /*
+ * now that we pass the packet to next filter, we don't care the
+ * reture value here, because the filter layer or other filter
+ * will take care of this packet
+ */
+ g_free(packet);
+ }
+}
+
+static void filter_buffer_release_timer(void *opaque)
+{
+ FILTERBUFFERState *s = opaque;
+ filter_buffer_flush(&s->nf);
+ timer_mod(&s->release_timer,
+ qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+}
+
+/* filter APIs */
+static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt)
+{
+ FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
+ NetQueue *queue = s->incoming_queue;
+
+ qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
+ packet_send_completed);
+ return iov_size(iov, iovcnt);
+}
+
+static void filter_buffer_cleanup(NetFilterState *nf)
+{
+ FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
+
+ if (s->interval) {
+ timer_del(&s->release_timer);
+ }
+
+ /* flush packets */
+ filter_buffer_flush(nf);
+ g_free(s->incoming_queue);
+ return;
+}
+
+static NetFilterInfo net_filter_buffer_info = {
+ .type = NET_FILTER_OPTIONS_KIND_BUFFER,
+ .size = sizeof(FILTERBUFFERState),
+ .receive_iov = filter_buffer_receive_iov,
+ .cleanup = filter_buffer_cleanup,
+};
+
+int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
+ int chain, NetClientState *netdev, Error **errp)
+{
+ NetFilterState *nf;
+ FILTERBUFFERState *s;
+ const NetFilterBufferOptions *bufferopt;
+
+ assert(opts->kind == NET_FILTER_OPTIONS_KIND_BUFFER);
+ bufferopt = opts->buffer;
+
+ nf = qemu_new_net_filter(&net_filter_buffer_info,
+ netdev, "buffer", name, chain);
+ s = DO_UPCAST(FILTERBUFFERState, nf, nf);
+ s->incoming_queue = qemu_new_net_queue(nf);
+ s->interval = bufferopt->has_interval ? bufferopt->interval : 0;
+ if (s->interval) {
+ timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
+ filter_buffer_release_timer, s);
+ timer_mod(&s->release_timer,
+ qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+ }
+
+ return 0;
+}
diff --git a/net/filter.c b/net/filter.c
index 166b851..02f3e76 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -19,6 +19,7 @@
#include "net/filter.h"
#include "net/net.h"
#include "net/queue.h"
+#include "filters.h"
static QTAILQ_HEAD(, NetFilterState) net_filters;
@@ -179,6 +180,7 @@ typedef int (NetFilterInit)(const NetFilterOptions *opts,
static
NetFilterInit * const net_filter_init_fun[NET_FILTER_OPTIONS_KIND_MAX] = {
+ [NET_FILTER_OPTIONS_KIND_BUFFER] = net_init_filter_buffer,
};
static int net_filter_init1(const NetFilter *netfilter, Error **errp)
diff --git a/net/filters.h b/net/filters.h
new file mode 100644
index 0000000..3b546db
--- /dev/null
+++ b/net/filters.h
@@ -0,0 +1,17 @@
+/*
+ * 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_FILTERS_H
+#define QEMU_NET_FILTERS_H
+
+#include "net/net.h"
+#include "net/filter.h"
+
+int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
+ int chain, NetClientState *netdev, Error **errp);
+
+#endif /* QEMU_NET_FILTERS_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index 9d97c21..e51bb59 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2584,6 +2584,21 @@
{ 'command': 'netfilter_del', 'data': {'id': 'str'} }
##
+# @NetFilterBufferOptions
+#
+# a netbuffer filter for network backend.
+#
+# @interval: #optional release packets by interval, if no interval supplied,
+# will release packets when filter_buffer_release_all been called.
+# scale: microsecond
+#
+# Since 2.5
+##
+{ 'struct': 'NetFilterBufferOptions',
+ 'data': {
+ '*interval': 'int64' } }
+
+##
# @NetFilterOptions
#
# A discriminated record of network filters.
@@ -2592,7 +2607,8 @@
#
##
{ 'union': 'NetFilterOptions',
- 'data': { } }
+ 'data': {
+ 'buffer': 'NetFilterBufferOptions'} }
##
# @NetFilter
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (8 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
2015-08-06 7:22 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 11/11] tests: add test cases for netfilter object Yang Hongyang
10 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
Markus Armbruster, mrhines, Luiz Capitulino, stefanha,
Yang Hongyang
now that we have a buffer netfilter, update the command
description and help.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Luiz Capitulino <lcapitulino@redhat.com>
CC: Markus Armbruster <armbru@redhat.com>
---
hmp-commands.hx | 2 +-
qemu-options.hx | 5 ++++-
qmp-commands.hx | 2 +-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 902e2d1..63177a8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1255,7 +1255,7 @@ ETEXI
{
.name = "netfilter_add",
.args_type = "netfilter:O",
- .params = "[type],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
+ .params = "[buffer],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
.help = "add netfilter",
.mhandler.cmd = hmp_netfilter_add,
.command_completion = netfilter_add_completion,
diff --git a/qemu-options.hx b/qemu-options.hx
index 0d52d02..eeaf2a1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1575,7 +1575,10 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
"socket][,vlan=n][,option][,option][,...]\n"
" old way to initialize a host network interface\n"
" (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
-DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter, "", QEMU_ARCH_ALL)
+DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter,
+ "-netfilter buffer,id=str,netdev=str[,chain=in|out|all,interval=n]\n"
+ " buffer netdev in/out packets. if interval provided, will release\n"
+ " packets by interval. interval scale: microsecond\n", QEMU_ARCH_ALL)
STEXI
@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
@findex -net
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4f0dc98..9419a6f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -947,7 +947,7 @@ Arguments:
Example:
-> { "execute": "netfilter_add",
- "arguments": { "type": "type", "id": "nf0",
+ "arguments": { "type": "buffer", "id": "nf0",
"netdev": "bn",
"chain": "in" } }
<- { "return": {} }
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [Qemu-devel] [PATCH v4 11/11] tests: add test cases for netfilter object
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
` (9 preceding siblings ...)
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help Yang Hongyang
@ 2015-08-04 8:30 ` Yang Hongyang
10 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-04 8:30 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, eddie.dong,
mrhines, stefanha, Yang Hongyang
Using qtest qmp interface to implement following cases:
1) add/remove netfilter
2) add a netfilter then delete the netdev
3) add/remove more than one netfilters
4) add more than one netfilters and then delete the netdev
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
tests/.gitignore | 1 +
tests/Makefile | 2 +
tests/test-netfilter.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 197 insertions(+)
create mode 100644 tests/test-netfilter.c
diff --git a/tests/.gitignore b/tests/.gitignore
index ccc92e4..395962b 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -41,5 +41,6 @@ test-vmstate
test-write-threshold
test-x86-cpuid
test-xbzrle
+test-netfilter
*-test
qapi-schema/*.test.*
diff --git a/tests/Makefile b/tests/Makefile
index 7494582..e39c7e6 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -185,6 +185,7 @@ check-qtest-i386-y += tests/pc-cpu-test$(EXESUF)
check-qtest-i386-y += tests/q35-test$(EXESUF)
gcov-files-i386-y += hw/pci-host/q35.c
check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF)
+check-qtest-i386-y += tests/test-netfilter$(EXESUF)
check-qtest-x86_64-y = $(check-qtest-i386-y)
gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -409,6 +410,7 @@ tests/vhost-user-test$(EXESUF): tests/vhost-user-test.o qemu-char.o qemu-timer.o
tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_helper.o
tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o libqemuutil.a libqemustub.a
tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(block-obj-y) libqemuutil.a libqemustub.a
+tests/test-netfilter$(EXESUF): tests/test-netfilter.o $(qtest-obj-y)
ifeq ($(CONFIG_POSIX),y)
LIBS += -lutil
diff --git a/tests/test-netfilter.c b/tests/test-netfilter.c
new file mode 100644
index 0000000..acbea4c
--- /dev/null
+++ b/tests/test-netfilter.c
@@ -0,0 +1,194 @@
+/*
+ * QTest testcase for netfilter
+ *
+ * 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 <glib.h>
+#include "libqtest.h"
+
+/* add a netfilter to a netdev and then remove it */
+static void add_one_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f0\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netfilter_del\","
+ " \"arguments\": {"
+ " \"id\": \"qtest-f0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add a netfilter to a netdev and then remove the netdev */
+static void remove_netdev_with_one_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f0\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netdev_del\","
+ " \"arguments\": {"
+ " \"id\": \"qtest-bn0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ /* add back the netdev */
+ response = qmp("{\"execute\": \"netdev_add\","
+ " \"arguments\": {"
+ " \"type\": \"user\","
+ " \"id\": \"qtest-bn0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove them */
+static void add_multi_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f0\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f1\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netfilter_del\","
+ " \"arguments\": {"
+ " \"id\": \"qtest-f0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netfilter_del\","
+ " \"arguments\": {"
+ " \"id\": \"qtest-f1\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove the netdev */
+static void remove_netdev_with_multi_netfilter(void)
+{
+ QDict *response;
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f0\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netfilter_add\","
+ " \"arguments\": {"
+ " \"type\": \"buffer\","
+ " \"id\": \"qtest-f1\","
+ " \"netdev\": \"qtest-bn0\","
+ " \"chain\": \"in\","
+ " \"interval\": \"1000\""
+ "}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{\"execute\": \"netdev_del\","
+ " \"arguments\": {"
+ " \"id\": \"qtest-bn0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ /* add back the netdev */
+ response = qmp("{\"execute\": \"netdev_add\","
+ " \"arguments\": {"
+ " \"type\": \"user\","
+ " \"id\": \"qtest-bn0\""
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ qtest_add_func("/netfilter/addremove_one", add_one_netfilter);
+ qtest_add_func("/netfilter/remove_netdev_one",
+ remove_netdev_with_one_netfilter);
+ qtest_add_func("/netfilter/addremove_multi", add_multi_netfilter);
+ qtest_add_func("/netfilter/remove_netdev_multi",
+ remove_netdev_with_multi_netfilter);
+
+ qtest_start("-netdev user,id=qtest-bn0 -device e1000,netdev=qtest-bn0");
+ ret = g_test_run();
+
+ qtest_end();
+
+ return ret;
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object Yang Hongyang
@ 2015-08-06 7:07 ` Jason Wang
2015-08-06 7:22 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:07 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> QTAILQ_ENTRY global_list but used by filter layer, so that we can
> manage all filters together.
> QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
> in this queue.
> This is mostly the same with init/cleanup of netdev object.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> include/net/filter.h | 39 +++++++++++++
> include/net/net.h | 1 +
> include/qemu/typedefs.h | 1 +
> net/filter.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
> net/net.c | 1 +
> qapi-schema.json | 37 ++++++++++++
> 6 files changed, 226 insertions(+)
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 4242ded..9aafe08 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -9,7 +9,46 @@
> #define QEMU_NET_FILTER_H
>
> #include "qemu-common.h"
> +#include "qemu/typedefs.h"
> +
> +/* the netfilter chain */
> +enum {
> + NET_FILTER_IN,
> + NET_FILTER_OUT,
> + NET_FILTER_ALL,
> +};
> +
> +typedef void (FilterCleanup) (NetFilterState *);
> +/*
> + * Return:
> + * 0: finished handling the packet, we should continue
> + * size: filter stolen this packet, we stop pass this packet further
> + */
> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState *sender,
> + unsigned flags, const struct iovec *, int);
Please name all parameters.
> +
> +typedef struct NetFilterInfo {
> + NetFilterOptionsKind type;
> + size_t size;
> + FilterCleanup *cleanup;
> + FilterReceiveIOV *receive_iov;
> +} NetFilterInfo;
> +
> +struct NetFilterState {
> + NetFilterInfo *info;
> + char *model;
Looks like model is never used?
[...]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev Yang Hongyang
@ 2015-08-06 7:09 ` Jason Wang
2015-08-06 7:22 ` Yang Hongyang
2015-08-06 8:44 ` Yang Hongyang
0 siblings, 2 replies; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:09 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> When we delete the netdev, we also delete the netfilter object
> attached to it, because if the netdev is removed, the filters
> which attached to it is useless.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Please squash this into patch 3. (otherwise you're fixing a bug
introduced by patch 3).
> ---
> include/net/filter.h | 1 +
> net/filter.c | 2 +-
> net/net.c | 14 ++++++++++++++
> 3 files changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 8eff85a..c146be2 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -50,6 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
> const char *model,
> const char *name,
> int chain);
> +void qemu_del_net_filter(NetFilterState *nf);
> void netfilter_add(QemuOpts *opts, Error **errp);
> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>
> diff --git a/net/filter.c b/net/filter.c
> index 54a5c06..24ec4e1 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -57,7 +57,7 @@ static void qemu_cleanup_net_filter(NetFilterState *nf)
> g_free(nf);
> }
>
> -static void qemu_del_net_filter(NetFilterState *nf)
> +void qemu_del_net_filter(NetFilterState *nf)
> {
> /* handle multi queue? */
> qemu_cleanup_net_filter(nf);
> diff --git a/net/net.c b/net/net.c
> index d9b70cd..03b2296 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -28,6 +28,7 @@
> #include "hub.h"
> #include "net/slirp.h"
> #include "net/eth.h"
> +#include "net/filter.h"
> #include "util.h"
>
> #include "monitor/monitor.h"
> @@ -385,6 +386,8 @@ void qemu_del_net_client(NetClientState *nc)
> {
> NetClientState *ncs[MAX_QUEUE_NUM];
> int queues, i;
> + NetFilterState *nf, *next;
> + QemuOpts *opts;
>
> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>
> @@ -396,6 +399,17 @@ void qemu_del_net_client(NetClientState *nc)
> MAX_QUEUE_NUM);
> assert(queues != 0);
>
> + /*
> + * we delete/free the netfilter object attached to this netdev
> + * multiqueue netfilter is not supported now, so only delete
> + * nc->filters is enough.
> + */
The comment is not correct since for multiqueue, each NetClientState is
a queue. I think you can just remove above.
> + QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
> + opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), nf->name);
> + qemu_del_net_filter(nf);
> + qemu_opts_del(opts);
> + }
> +
> /* 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) {
> NICState *nic = qemu_get_nic(nc->peer);
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send Yang Hongyang
@ 2015-08-06 7:13 ` Jason Wang
2015-08-06 7:28 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:13 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> Capture packets that will be sent.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> net/net.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/net/net.c b/net/net.c
> index 03b2296..efccd56 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -569,6 +569,42 @@ int qemu_can_send_packet(NetClientState *sender)
> return 1;
> }
>
> +static ssize_t filter_receive_iov(NetClientState *nc, int chain,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt)
> +{
> + ssize_t ret = 0;
> + NetFilterState *nf = NULL;
> + ssize_t size = iov_size(iov, iovcnt);
> +
> + QTAILQ_FOREACH(nf, &nc->filters, next) {
> + if (nf->chain == chain || nf->chain == NET_FILTER_ALL) {
> + ret = nf->info->receive_iov(nf, sender, flags, iov, iovcnt);
> + if (ret == size) {
> + return ret;
> + }
> + }
> + }
> +
> + return ret;
> +}
> +
> +static ssize_t filter_receive(NetClientState *nc, int chain,
> + NetClientState *sender,
> + unsigned flags,
> + const uint8_t *data,
> + size_t size)
> +{
> + struct iovec iov = {
> + .iov_base = (void *)data,
> + .iov_len = size
> + };
> +
> + return filter_receive_iov(nc, chain, sender, flags, &iov, 1);
> +}
> +
> ssize_t qemu_deliver_packet(NetClientState *sender,
> unsigned flags,
> const uint8_t *data,
> @@ -640,6 +676,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
> NetPacketSent *sent_cb)
> {
> NetQueue *queue;
> + int ret;
>
> #ifdef DEBUG_NET
> printf("qemu_send_packet_async:\n");
> @@ -650,6 +687,18 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
> return size;
> }
>
> + /* Let filters handle the packet first */
> + ret = filter_receive(sender, NET_FILTER_OUT, sender, flags, buf, size);
> + if (ret == size) {
> + return size;
> + }
> +
> + ret = filter_receive(sender->peer, NET_FILTER_IN,
> + sender, flags, buf, size);
> + if (ret == size) {
> + return size;
> + }
I think we can just trust the return value of filter_receive(), no need
to check it against iov_size.
Also sent_cb was lost track if the packet was held by filter which seems
wrong.
[...]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter Yang Hongyang
@ 2015-08-06 7:16 ` Jason Wang
2015-08-06 7:29 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:16 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> add an API qemu_netfilter_pass_to_next_iov() to pass the packet
> to next filter, and a wrapper qemu_netfilter_pass_to_next().
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> include/net/filter.h | 12 ++++++++++++
> net/filter.c | 43 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 55 insertions(+)
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> index c146be2..867d5aa 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -54,4 +54,16 @@ void qemu_del_net_filter(NetFilterState *nf);
> void netfilter_add(QemuOpts *opts, Error **errp);
> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>
> +/* pass the packet to the next filter */
> +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt);
> +void qemu_netfilter_pass_to_next(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const uint8_t *data,
> + size_t size);
sender, flags, data and size were all could be inferred from packet. How
about just have a packet parameter?
> +
> #endif /* QEMU_NET_FILTER_H */
> diff --git a/net/filter.c b/net/filter.c
> index 24ec4e1..166b851 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -14,9 +14,11 @@
> #include "qapi/dealloc-visitor.h"
> #include "qemu/config-file.h"
> #include "qmp-commands.h"
> +#include "qemu/iov.h"
>
> #include "net/filter.h"
> #include "net/net.h"
> +#include "net/queue.h"
>
> static QTAILQ_HEAD(, NetFilterState) net_filters;
>
> @@ -130,6 +132,47 @@ void qmp_netfilter_del(const char *id, Error **errp)
> qemu_opts_del(opts);
> }
>
> +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt)
> +{
> + int ret = 0;
> + ssize_t size = iov_size(iov, iovcnt);
> + NetFilterState *next = QTAILQ_NEXT(nf, next);
> +
> + while (next) {
> + if (next->chain == nf->chain || next->chain == NET_FILTER_ALL) {
> + ret = next->info->receive_iov(next, sender, flags, iov, iovcnt);
> + if (ret == size) {
> + return;
> + }
> + }
> + next = QTAILQ_NEXT(next, next);
> + }
> +
> + /* we have gone through all filters, pass it to receiver */
> + if (sender && sender->peer) {
> + qemu_net_queue_send_iov(sender->peer->incoming_queue, sender, flags,
> + iov, iovcnt, NULL);
> + }
> +}
> +
> +void qemu_netfilter_pass_to_next(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const uint8_t *data,
> + size_t size)
> +{
> + struct iovec iov = {
> + .iov_base = (void *)data,
> + .iov_len = size
> + };
> +
> + return qemu_netfilter_pass_to_next_iov(nf, sender, flags, &iov, 1);
> +}
> +
> typedef int (NetFilterInit)(const NetFilterOptions *opts,
> const char *name, int chain,
> NetClientState *netdev, Error **errp);
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-08-06 7:21 ` Jason Wang
2015-08-06 8:19 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:21 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> This filter is to buffer/release packets, this feature can be used
> when using MicroCheckpointing, or other Remus like VM FT solutions, you
> can also use it to simulate the network delay.
> It has an interval option, if supplied, this filter will release
> packets by interval.
>
> Usage:
> -netdev tap,id=bn0
> -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
>
> NOTE:
> the scale of interval is microsecond.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> v4: remove bh
> pass the packet to next filter instead of receiver
> v3: check packet's sender and sender->peer when flush it
> ---
> net/Makefile.objs | 1 +
> net/filter-buffer.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> net/filter.c | 2 +
> net/filters.h | 17 ++++++++
> qapi-schema.json | 18 +++++++-
> 5 files changed, 157 insertions(+), 1 deletion(-)
> create mode 100644 net/filter-buffer.c
> create mode 100644 net/filters.h
>
> 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/filter-buffer.c b/net/filter-buffer.c
> new file mode 100644
> index 0000000..fd467db
> --- /dev/null
> +++ b/net/filter-buffer.c
> @@ -0,0 +1,120 @@
> +/*
> + * 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/filter.h"
> +#include "net/queue.h"
> +#include "filters.h"
> +#include "qemu-common.h"
> +#include "qemu/timer.h"
> +#include "qemu/iov.h"
> +
> +typedef struct FILTERBUFFERState {
> + NetFilterState nf;
> + NetQueue *incoming_queue;
> + int64_t interval;
Can interval be negative? If not please uint. And not sure you really
need a 64 bit integer, if not, please use uint32_t.
> + QEMUTimer release_timer;
> +} FILTERBUFFERState;
Filter buffer is not abbreviation. So better name it as FilterBufferState.
> +
> +static void packet_send_completed(NetClientState *nc, ssize_t len)
> +{
> + return;
> +}
Why need a dummy sent cb?
> +
> +static void filter_buffer_flush(NetFilterState *nf)
> +{
> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
> + NetQueue *queue = s->incoming_queue;
> + NetPacket *packet;
> +
> + while (queue && !QTAILQ_EMPTY(&queue->packets)) {
> + packet = QTAILQ_FIRST(&queue->packets);
> + QTAILQ_REMOVE(&queue->packets, packet, entry);
> + queue->nq_count--;
> +
> + if (packet->sender && packet->sender->peer) {
> + qemu_netfilter_pass_to_next(nf, packet->sender, packet->flags,
> + packet->data, packet->size);
> + }
> +
> + /*
> + * now that we pass the packet to next filter, we don't care the
> + * reture value here, because the filter layer or other filter
> + * will take care of this packet
> + */
> + g_free(packet);
This seems wrong, since packet could be queued into incoming queue.
Doing this may cause use after free.
> + }
> +}
> +
> +static void filter_buffer_release_timer(void *opaque)
> +{
> + FILTERBUFFERState *s = opaque;
> + filter_buffer_flush(&s->nf);
> + timer_mod(&s->release_timer,
> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
> +}
> +
> +/* filter APIs */
> +static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt)
> +{
> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
> + NetQueue *queue = s->incoming_queue;
> +
> + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
> + packet_send_completed);
> + return iov_size(iov, iovcnt);
So if interval is zero, packet will be blocked forever and memory will
be exhausted.
> +}
> +
> +static void filter_buffer_cleanup(NetFilterState *nf)
> +{
> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
> +
> + if (s->interval) {
> + timer_del(&s->release_timer);
> + }
> +
> + /* flush packets */
> + filter_buffer_flush(nf);
> + g_free(s->incoming_queue);
> + return;
> +}
> +
> +static NetFilterInfo net_filter_buffer_info = {
> + .type = NET_FILTER_OPTIONS_KIND_BUFFER,
> + .size = sizeof(FILTERBUFFERState),
> + .receive_iov = filter_buffer_receive_iov,
> + .cleanup = filter_buffer_cleanup,
> +};
> +
> +int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
> + int chain, NetClientState *netdev, Error **errp)
> +{
> + NetFilterState *nf;
> + FILTERBUFFERState *s;
> + const NetFilterBufferOptions *bufferopt;
> +
> + assert(opts->kind == NET_FILTER_OPTIONS_KIND_BUFFER);
> + bufferopt = opts->buffer;
> +
> + nf = qemu_new_net_filter(&net_filter_buffer_info,
> + netdev, "buffer", name, chain);
> + s = DO_UPCAST(FILTERBUFFERState, nf, nf);
> + s->incoming_queue = qemu_new_net_queue(nf);
> + s->interval = bufferopt->has_interval ? bufferopt->interval : 0;
> + if (s->interval) {
> + timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
> + filter_buffer_release_timer, s);
> + timer_mod(&s->release_timer,
> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
> + }
> +
> + return 0;
> +}
> diff --git a/net/filter.c b/net/filter.c
> index 166b851..02f3e76 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -19,6 +19,7 @@
> #include "net/filter.h"
> #include "net/net.h"
> #include "net/queue.h"
> +#include "filters.h"
>
> static QTAILQ_HEAD(, NetFilterState) net_filters;
>
> @@ -179,6 +180,7 @@ typedef int (NetFilterInit)(const NetFilterOptions *opts,
>
> static
> NetFilterInit * const net_filter_init_fun[NET_FILTER_OPTIONS_KIND_MAX] = {
> + [NET_FILTER_OPTIONS_KIND_BUFFER] = net_init_filter_buffer,
> };
>
> static int net_filter_init1(const NetFilter *netfilter, Error **errp)
> diff --git a/net/filters.h b/net/filters.h
> new file mode 100644
> index 0000000..3b546db
> --- /dev/null
> +++ b/net/filters.h
> @@ -0,0 +1,17 @@
> +/*
> + * 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_FILTERS_H
> +#define QEMU_NET_FILTERS_H
> +
> +#include "net/net.h"
> +#include "net/filter.h"
> +
> +int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
> + int chain, NetClientState *netdev, Error **errp);
> +
> +#endif /* QEMU_NET_FILTERS_H */
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 9d97c21..e51bb59 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2584,6 +2584,21 @@
> { 'command': 'netfilter_del', 'data': {'id': 'str'} }
>
> ##
> +# @NetFilterBufferOptions
> +#
> +# a netbuffer filter for network backend.
> +#
> +# @interval: #optional release packets by interval, if no interval supplied,
> +# will release packets when filter_buffer_release_all been called.
> +# scale: microsecond
> +#
> +# Since 2.5
> +##
> +{ 'struct': 'NetFilterBufferOptions',
> + 'data': {
> + '*interval': 'int64' } }
> +
> +##
> # @NetFilterOptions
> #
> # A discriminated record of network filters.
> @@ -2592,7 +2607,8 @@
> #
> ##
> { 'union': 'NetFilterOptions',
> - 'data': { } }
> + 'data': {
> + 'buffer': 'NetFilterBufferOptions'} }
>
> ##
> # @NetFilter
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help Yang Hongyang
@ 2015-08-06 7:22 ` Jason Wang
2015-08-06 7:31 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:22 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong,
Markus Armbruster, mrhines, Luiz Capitulino, stefanha
On 08/04/2015 04:30 PM, Yang Hongyang wrote:
> now that we have a buffer netfilter, update the command
> description and help.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> CC: Luiz Capitulino <lcapitulino@redhat.com>
> CC: Markus Armbruster <armbru@redhat.com>
> ---
> hmp-commands.hx | 2 +-
> qemu-options.hx | 5 ++++-
> qmp-commands.hx | 2 +-
> 3 files changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index 902e2d1..63177a8 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1255,7 +1255,7 @@ ETEXI
> {
> .name = "netfilter_add",
> .args_type = "netfilter:O",
> - .params = "[type],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
> + .params = "[buffer],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
Looks like chain is mandatory in patch 2.
> .help = "add netfilter",
> .mhandler.cmd = hmp_netfilter_add,
> .command_completion = netfilter_add_completion,
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 0d52d02..eeaf2a1 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1575,7 +1575,10 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
> "socket][,vlan=n][,option][,option][,...]\n"
> " old way to initialize a host network interface\n"
> " (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
> -DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter, "", QEMU_ARCH_ALL)
> +DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter,
> + "-netfilter buffer,id=str,netdev=str[,chain=in|out|all,interval=n]\n"
> + " buffer netdev in/out packets. if interval provided, will release\n"
> + " packets by interval. interval scale: microsecond\n", QEMU_ARCH_ALL)
> STEXI
> @item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
> @findex -net
> diff --git a/qmp-commands.hx b/qmp-commands.hx
> index 4f0dc98..9419a6f 100644
> --- a/qmp-commands.hx
> +++ b/qmp-commands.hx
> @@ -947,7 +947,7 @@ Arguments:
> Example:
>
> -> { "execute": "netfilter_add",
> - "arguments": { "type": "type", "id": "nf0",
> + "arguments": { "type": "buffer", "id": "nf0",
> "netdev": "bn",
> "chain": "in" } }
> <- { "return": {} }
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:07 ` Jason Wang
@ 2015-08-06 7:22 ` Yang Hongyang
2015-08-06 7:29 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:22 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:07 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>> manage all filters together.
>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
>> in this queue.
>> This is mostly the same with init/cleanup of netdev object.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> ---
>> include/net/filter.h | 39 +++++++++++++
>> include/net/net.h | 1 +
>> include/qemu/typedefs.h | 1 +
>> net/filter.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++
>> net/net.c | 1 +
>> qapi-schema.json | 37 ++++++++++++
>> 6 files changed, 226 insertions(+)
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> index 4242ded..9aafe08 100644
>> --- a/include/net/filter.h
>> +++ b/include/net/filter.h
>> @@ -9,7 +9,46 @@
>> #define QEMU_NET_FILTER_H
>>
>> #include "qemu-common.h"
>> +#include "qemu/typedefs.h"
>> +
>> +/* the netfilter chain */
>> +enum {
>> + NET_FILTER_IN,
>> + NET_FILTER_OUT,
>> + NET_FILTER_ALL,
>> +};
>> +
>> +typedef void (FilterCleanup) (NetFilterState *);
>> +/*
>> + * Return:
>> + * 0: finished handling the packet, we should continue
>> + * size: filter stolen this packet, we stop pass this packet further
>> + */
>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState *sender,
>> + unsigned flags, const struct iovec *, int);
>
> Please name all parameters.
Ok, thanks.
>
>> +
>> +typedef struct NetFilterInfo {
>> + NetFilterOptionsKind type;
>> + size_t size;
>> + FilterCleanup *cleanup;
>> + FilterReceiveIOV *receive_iov;
>> +} NetFilterInfo;
>> +
>> +struct NetFilterState {
>> + NetFilterInfo *info;
>> + char *model;
>
> Looks like model is never used?
It can be used when we want to find filters by model. For example,
when we need to find all "buffer" filter, and release all buffered
packets.
>
> [...]
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev
2015-08-06 7:09 ` Jason Wang
@ 2015-08-06 7:22 ` Yang Hongyang
2015-08-06 8:44 ` Yang Hongyang
1 sibling, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:22 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:09 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> When we delete the netdev, we also delete the netfilter object
>> attached to it, because if the netdev is removed, the filters
>> which attached to it is useless.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>
> Please squash this into patch 3. (otherwise you're fixing a bug
> introduced by patch 3).
Will do, thanks.
>
>> ---
>> include/net/filter.h | 1 +
>> net/filter.c | 2 +-
>> net/net.c | 14 ++++++++++++++
>> 3 files changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> index 8eff85a..c146be2 100644
>> --- a/include/net/filter.h
>> +++ b/include/net/filter.h
>> @@ -50,6 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
>> const char *model,
>> const char *name,
>> int chain);
>> +void qemu_del_net_filter(NetFilterState *nf);
>> void netfilter_add(QemuOpts *opts, Error **errp);
>> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>>
>> diff --git a/net/filter.c b/net/filter.c
>> index 54a5c06..24ec4e1 100644
>> --- a/net/filter.c
>> +++ b/net/filter.c
>> @@ -57,7 +57,7 @@ static void qemu_cleanup_net_filter(NetFilterState *nf)
>> g_free(nf);
>> }
>>
>> -static void qemu_del_net_filter(NetFilterState *nf)
>> +void qemu_del_net_filter(NetFilterState *nf)
>> {
>> /* handle multi queue? */
>> qemu_cleanup_net_filter(nf);
>> diff --git a/net/net.c b/net/net.c
>> index d9b70cd..03b2296 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -28,6 +28,7 @@
>> #include "hub.h"
>> #include "net/slirp.h"
>> #include "net/eth.h"
>> +#include "net/filter.h"
>> #include "util.h"
>>
>> #include "monitor/monitor.h"
>> @@ -385,6 +386,8 @@ void qemu_del_net_client(NetClientState *nc)
>> {
>> NetClientState *ncs[MAX_QUEUE_NUM];
>> int queues, i;
>> + NetFilterState *nf, *next;
>> + QemuOpts *opts;
>>
>> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>>
>> @@ -396,6 +399,17 @@ void qemu_del_net_client(NetClientState *nc)
>> MAX_QUEUE_NUM);
>> assert(queues != 0);
>>
>> + /*
>> + * we delete/free the netfilter object attached to this netdev
>> + * multiqueue netfilter is not supported now, so only delete
>> + * nc->filters is enough.
>> + */
>
> The comment is not correct since for multiqueue, each NetClientState is
> a queue. I think you can just remove above.
Will remove it in the next version, thanks.
>
>> + QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
>> + opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), nf->name);
>> + qemu_del_net_filter(nf);
>> + qemu_opts_del(opts);
>> + }
>> +
>> /* 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) {
>> NICState *nic = qemu_get_nic(nc->peer);
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send
2015-08-06 7:13 ` Jason Wang
@ 2015-08-06 7:28 ` Yang Hongyang
2015-08-06 7:37 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:28 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:13 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> Capture packets that will be sent.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> ---
>> net/net.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 65 insertions(+), 1 deletion(-)
>>
>> diff --git a/net/net.c b/net/net.c
>> index 03b2296..efccd56 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -569,6 +569,42 @@ int qemu_can_send_packet(NetClientState *sender)
>> return 1;
>> }
>>
>> +static ssize_t filter_receive_iov(NetClientState *nc, int chain,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt)
>> +{
>> + ssize_t ret = 0;
>> + NetFilterState *nf = NULL;
>> + ssize_t size = iov_size(iov, iovcnt);
>> +
>> + QTAILQ_FOREACH(nf, &nc->filters, next) {
>> + if (nf->chain == chain || nf->chain == NET_FILTER_ALL) {
>> + ret = nf->info->receive_iov(nf, sender, flags, iov, iovcnt);
>> + if (ret == size) {
>> + return ret;
>> + }
>> + }
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +static ssize_t filter_receive(NetClientState *nc, int chain,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const uint8_t *data,
>> + size_t size)
>> +{
>> + struct iovec iov = {
>> + .iov_base = (void *)data,
>> + .iov_len = size
>> + };
>> +
>> + return filter_receive_iov(nc, chain, sender, flags, &iov, 1);
>> +}
>> +
>> ssize_t qemu_deliver_packet(NetClientState *sender,
>> unsigned flags,
>> const uint8_t *data,
>> @@ -640,6 +676,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
>> NetPacketSent *sent_cb)
>> {
>> NetQueue *queue;
>> + int ret;
>>
>> #ifdef DEBUG_NET
>> printf("qemu_send_packet_async:\n");
>> @@ -650,6 +687,18 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
>> return size;
>> }
>>
>> + /* Let filters handle the packet first */
>> + ret = filter_receive(sender, NET_FILTER_OUT, sender, flags, buf, size);
>> + if (ret == size) {
>> + return size;
>> + }
>> +
>> + ret = filter_receive(sender->peer, NET_FILTER_IN,
>> + sender, flags, buf, size);
>> + if (ret == size) {
>> + return size;
>> + }
>
> I think we can just trust the return value of filter_receive(), no need
> to check it against iov_size.
You mean:
if (ret)
return ret;
? We need to check ret however.
>
> Also sent_cb was lost track if the packet was held by filter which seems
> wrong.
So we need to extend the params of filter's receive_iov API, add a sent_cb
param. BTW, it seems that sent_cb will only been called when packet is
queueed and then sent, if the packet being sent directly sent_cb won't
be called? am I right? or I missed somthing from the code...
>
> [...]
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:22 ` Yang Hongyang
@ 2015-08-06 7:29 ` Jason Wang
2015-08-06 7:35 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:29 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:22 PM, Yang Hongyang wrote:
> On 08/06/2015 03:07 PM, Jason Wang wrote:
>>
>>
>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>>> manage all filters together.
>>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific
>>> netdev is
>>> in this queue.
>>> This is mostly the same with init/cleanup of netdev object.
>>>
>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>> ---
>>> include/net/filter.h | 39 +++++++++++++
>>> include/net/net.h | 1 +
>>> include/qemu/typedefs.h | 1 +
>>> net/filter.c | 147
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>> net/net.c | 1 +
>>> qapi-schema.json | 37 ++++++++++++
>>> 6 files changed, 226 insertions(+)
>>>
>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>> index 4242ded..9aafe08 100644
>>> --- a/include/net/filter.h
>>> +++ b/include/net/filter.h
>>> @@ -9,7 +9,46 @@
>>> #define QEMU_NET_FILTER_H
>>>
>>> #include "qemu-common.h"
>>> +#include "qemu/typedefs.h"
>>> +
>>> +/* the netfilter chain */
>>> +enum {
>>> + NET_FILTER_IN,
>>> + NET_FILTER_OUT,
>>> + NET_FILTER_ALL,
>>> +};
>>> +
>>> +typedef void (FilterCleanup) (NetFilterState *);
>>> +/*
>>> + * Return:
>>> + * 0: finished handling the packet, we should continue
>>> + * size: filter stolen this packet, we stop pass this packet further
>>> + */
>>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState
>>> *sender,
>>> + unsigned flags, const struct
>>> iovec *, int);
>>
>> Please name all parameters.
>
> Ok, thanks.
>
>>
>>> +
>>> +typedef struct NetFilterInfo {
>>> + NetFilterOptionsKind type;
>>> + size_t size;
>>> + FilterCleanup *cleanup;
>>> + FilterReceiveIOV *receive_iov;
>>> +} NetFilterInfo;
>>> +
>>> +struct NetFilterState {
>>> + NetFilterInfo *info;
>>> + char *model;
>>
>> Looks like model is never used?
>
> It can be used when we want to find filters by model. For example,
> when we need to find all "buffer" filter, and release all buffered
> packets.
But this is not implemented in this series. And I don't get why you need
a such command. Management should keep track of this.
>
>>
>> [...]
>> .
>>
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter
2015-08-06 7:16 ` Jason Wang
@ 2015-08-06 7:29 ` Yang Hongyang
0 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:29 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:16 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> add an API qemu_netfilter_pass_to_next_iov() to pass the packet
>> to next filter, and a wrapper qemu_netfilter_pass_to_next().
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> ---
>> include/net/filter.h | 12 ++++++++++++
>> net/filter.c | 43 +++++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 55 insertions(+)
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> index c146be2..867d5aa 100644
>> --- a/include/net/filter.h
>> +++ b/include/net/filter.h
>> @@ -54,4 +54,16 @@ void qemu_del_net_filter(NetFilterState *nf);
>> void netfilter_add(QemuOpts *opts, Error **errp);
>> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>>
>> +/* pass the packet to the next filter */
>> +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt);
>> +void qemu_netfilter_pass_to_next(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const uint8_t *data,
>> + size_t size);
>
> sender, flags, data and size were all could be inferred from packet. How
> about just have a packet parameter?
Sure we can, good idea, thank you.
>
>> +
>> #endif /* QEMU_NET_FILTER_H */
>> diff --git a/net/filter.c b/net/filter.c
>> index 24ec4e1..166b851 100644
>> --- a/net/filter.c
>> +++ b/net/filter.c
>> @@ -14,9 +14,11 @@
>> #include "qapi/dealloc-visitor.h"
>> #include "qemu/config-file.h"
>> #include "qmp-commands.h"
>> +#include "qemu/iov.h"
>>
>> #include "net/filter.h"
>> #include "net/net.h"
>> +#include "net/queue.h"
>>
>> static QTAILQ_HEAD(, NetFilterState) net_filters;
>>
>> @@ -130,6 +132,47 @@ void qmp_netfilter_del(const char *id, Error **errp)
>> qemu_opts_del(opts);
>> }
>>
>> +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt)
>> +{
>> + int ret = 0;
>> + ssize_t size = iov_size(iov, iovcnt);
>> + NetFilterState *next = QTAILQ_NEXT(nf, next);
>> +
>> + while (next) {
>> + if (next->chain == nf->chain || next->chain == NET_FILTER_ALL) {
>> + ret = next->info->receive_iov(next, sender, flags, iov, iovcnt);
>> + if (ret == size) {
>> + return;
>> + }
>> + }
>> + next = QTAILQ_NEXT(next, next);
>> + }
>> +
>> + /* we have gone through all filters, pass it to receiver */
>> + if (sender && sender->peer) {
>> + qemu_net_queue_send_iov(sender->peer->incoming_queue, sender, flags,
>> + iov, iovcnt, NULL);
>> + }
>> +}
>> +
>> +void qemu_netfilter_pass_to_next(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const uint8_t *data,
>> + size_t size)
>> +{
>> + struct iovec iov = {
>> + .iov_base = (void *)data,
>> + .iov_len = size
>> + };
>> +
>> + return qemu_netfilter_pass_to_next_iov(nf, sender, flags, &iov, 1);
>> +}
>> +
>> typedef int (NetFilterInit)(const NetFilterOptions *opts,
>> const char *name, int chain,
>> NetClientState *netdev, Error **errp);
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help
2015-08-06 7:22 ` Jason Wang
@ 2015-08-06 7:31 ` Yang Hongyang
2015-08-06 7:39 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:31 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong,
Markus Armbruster, mrhines, Luiz Capitulino, stefanha
On 08/06/2015 03:22 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> now that we have a buffer netfilter, update the command
>> description and help.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> CC: Luiz Capitulino <lcapitulino@redhat.com>
>> CC: Markus Armbruster <armbru@redhat.com>
>> ---
>> hmp-commands.hx | 2 +-
>> qemu-options.hx | 5 ++++-
>> qmp-commands.hx | 2 +-
>> 3 files changed, 6 insertions(+), 3 deletions(-)
>>
>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>> index 902e2d1..63177a8 100644
>> --- a/hmp-commands.hx
>> +++ b/hmp-commands.hx
>> @@ -1255,7 +1255,7 @@ ETEXI
>> {
>> .name = "netfilter_add",
>> .args_type = "netfilter:O",
>> - .params = "[type],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
>> + .params = "[buffer],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
>
> Looks like chain is mandatory in patch 2.
It is optional, default is "all".
>
>> .help = "add netfilter",
>> .mhandler.cmd = hmp_netfilter_add,
>> .command_completion = netfilter_add_completion,
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 0d52d02..eeaf2a1 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -1575,7 +1575,10 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
>> "socket][,vlan=n][,option][,option][,...]\n"
>> " old way to initialize a host network interface\n"
>> " (use the -netdev option if possible instead)\n", QEMU_ARCH_ALL)
>> -DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter, "", QEMU_ARCH_ALL)
>> +DEF("netfilter", HAS_ARG, QEMU_OPTION_netfilter,
>> + "-netfilter buffer,id=str,netdev=str[,chain=in|out|all,interval=n]\n"
>> + " buffer netdev in/out packets. if interval provided, will release\n"
>> + " packets by interval. interval scale: microsecond\n", QEMU_ARCH_ALL)
>> STEXI
>> @item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}]
>> @findex -net
>> diff --git a/qmp-commands.hx b/qmp-commands.hx
>> index 4f0dc98..9419a6f 100644
>> --- a/qmp-commands.hx
>> +++ b/qmp-commands.hx
>> @@ -947,7 +947,7 @@ Arguments:
>> Example:
>>
>> -> { "execute": "netfilter_add",
>> - "arguments": { "type": "type", "id": "nf0",
>> + "arguments": { "type": "buffer", "id": "nf0",
>> "netdev": "bn",
>> "chain": "in" } }
>> <- { "return": {} }
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:29 ` Jason Wang
@ 2015-08-06 7:35 ` Yang Hongyang
2015-08-06 7:43 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:35 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:29 PM, Jason Wang wrote:
>
>
> On 08/06/2015 03:22 PM, Yang Hongyang wrote:
>> On 08/06/2015 03:07 PM, Jason Wang wrote:
>>>
>>>
>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>>>> manage all filters together.
>>>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific
>>>> netdev is
>>>> in this queue.
>>>> This is mostly the same with init/cleanup of netdev object.
>>>>
>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>> ---
>>>> include/net/filter.h | 39 +++++++++++++
>>>> include/net/net.h | 1 +
>>>> include/qemu/typedefs.h | 1 +
>>>> net/filter.c | 147
>>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>> net/net.c | 1 +
>>>> qapi-schema.json | 37 ++++++++++++
>>>> 6 files changed, 226 insertions(+)
>>>>
>>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>>> index 4242ded..9aafe08 100644
>>>> --- a/include/net/filter.h
>>>> +++ b/include/net/filter.h
>>>> @@ -9,7 +9,46 @@
>>>> #define QEMU_NET_FILTER_H
>>>>
>>>> #include "qemu-common.h"
>>>> +#include "qemu/typedefs.h"
>>>> +
>>>> +/* the netfilter chain */
>>>> +enum {
>>>> + NET_FILTER_IN,
>>>> + NET_FILTER_OUT,
>>>> + NET_FILTER_ALL,
>>>> +};
>>>> +
>>>> +typedef void (FilterCleanup) (NetFilterState *);
>>>> +/*
>>>> + * Return:
>>>> + * 0: finished handling the packet, we should continue
>>>> + * size: filter stolen this packet, we stop pass this packet further
>>>> + */
>>>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState
>>>> *sender,
>>>> + unsigned flags, const struct
>>>> iovec *, int);
>>>
>>> Please name all parameters.
>>
>> Ok, thanks.
>>
>>>
>>>> +
>>>> +typedef struct NetFilterInfo {
>>>> + NetFilterOptionsKind type;
>>>> + size_t size;
>>>> + FilterCleanup *cleanup;
>>>> + FilterReceiveIOV *receive_iov;
>>>> +} NetFilterInfo;
>>>> +
>>>> +struct NetFilterState {
>>>> + NetFilterInfo *info;
>>>> + char *model;
>>>
>>> Looks like model is never used?
>>
>> It can be used when we want to find filters by model. For example,
>> when we need to find all "buffer" filter, and release all buffered
>> packets.
>
> But this is not implemented in this series.
true.
> And I don't get why you need
> a such command. Management should keep track of this.
There's a patch in v1 which introduce an API use this, and I dropped that
because there's no user currently, but that API I suppose to be used
by MC or COLO which can do periodic checkpoint, to release packets.
the API is filter_buffer_release_all() IIRC...
>
>>
>>>
>>> [...]
>>> .
>>>
>>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send
2015-08-06 7:28 ` Yang Hongyang
@ 2015-08-06 7:37 ` Jason Wang
2015-08-06 7:58 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:37 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:28 PM, Yang Hongyang wrote:
>
>
> On 08/06/2015 03:13 PM, Jason Wang wrote:
>>
>>
>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>> Capture packets that will be sent.
>>>
>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>> ---
>>> net/net.c | 66
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>> 1 file changed, 65 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/net/net.c b/net/net.c
>>> index 03b2296..efccd56 100644
>>> --- a/net/net.c
>>> +++ b/net/net.c
>>> @@ -569,6 +569,42 @@ int qemu_can_send_packet(NetClientState *sender)
>>> return 1;
>>> }
>>>
>>> +static ssize_t filter_receive_iov(NetClientState *nc, int chain,
>>> + NetClientState *sender,
>>> + unsigned flags,
>>> + const struct iovec *iov,
>>> + int iovcnt)
>>> +{
>>> + ssize_t ret = 0;
>>> + NetFilterState *nf = NULL;
>>> + ssize_t size = iov_size(iov, iovcnt);
>>> +
>>> + QTAILQ_FOREACH(nf, &nc->filters, next) {
>>> + if (nf->chain == chain || nf->chain == NET_FILTER_ALL) {
>>> + ret = nf->info->receive_iov(nf, sender, flags, iov,
>>> iovcnt);
>>> + if (ret == size) {
>>> + return ret;
>>> + }
>>> + }
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +static ssize_t filter_receive(NetClientState *nc, int chain,
>>> + NetClientState *sender,
>>> + unsigned flags,
>>> + const uint8_t *data,
>>> + size_t size)
>>> +{
>>> + struct iovec iov = {
>>> + .iov_base = (void *)data,
>>> + .iov_len = size
>>> + };
>>> +
>>> + return filter_receive_iov(nc, chain, sender, flags, &iov, 1);
>>> +}
>>> +
>>> ssize_t qemu_deliver_packet(NetClientState *sender,
>>> unsigned flags,
>>> const uint8_t *data,
>>> @@ -640,6 +676,7 @@ static ssize_t
>>> qemu_send_packet_async_with_flags(NetClientState *sender,
>>> NetPacketSent
>>> *sent_cb)
>>> {
>>> NetQueue *queue;
>>> + int ret;
>>>
>>> #ifdef DEBUG_NET
>>> printf("qemu_send_packet_async:\n");
>>> @@ -650,6 +687,18 @@ static ssize_t
>>> qemu_send_packet_async_with_flags(NetClientState *sender,
>>> return size;
>>> }
>>>
>>> + /* Let filters handle the packet first */
>>> + ret = filter_receive(sender, NET_FILTER_OUT, sender, flags,
>>> buf, size);
>>> + if (ret == size) {
>>> + return size;
>>> + }
>>> +
>>> + ret = filter_receive(sender->peer, NET_FILTER_IN,
>>> + sender, flags, buf, size);
>>> + if (ret == size) {
>>> + return size;
>>> + }
>>
>> I think we can just trust the return value of filter_receive(), no need
>> to check it against iov_size.
>
> You mean:
> if (ret)
> return ret;
> ? We need to check ret however.
Yes, but the problem is you check it against size. What if
filter_receive() returns a value which is greater than 0 but smaller
than size. If this could not happen, probably no need to check. Not a
must but better to change this.
>
>>
>> Also sent_cb was lost track if the packet was held by filter which seems
>> wrong.
>
> So we need to extend the params of filter's receive_iov API, add a
> sent_cb
> param.
Yes.
> BTW, it seems that sent_cb will only been called when packet is
> queueed and then sent, if the packet being sent directly sent_cb won't
> be called? am I right? or I missed somthing from the code...
Yes, but if for some reason it couldn't. Sent cb is usually used to let
main loop to re-poll network backend.
>
>>
>> [...]
>> .
>>
>
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help
2015-08-06 7:31 ` Yang Hongyang
@ 2015-08-06 7:39 ` Jason Wang
0 siblings, 0 replies; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:39 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong,
Markus Armbruster, mrhines, Luiz Capitulino, stefanha
On 08/06/2015 03:31 PM, Yang Hongyang wrote:
>
>
> On 08/06/2015 03:22 PM, Jason Wang wrote:
>>
>>
>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>> now that we have a buffer netfilter, update the command
>>> description and help.
>>>
>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>> CC: Luiz Capitulino <lcapitulino@redhat.com>
>>> CC: Markus Armbruster <armbru@redhat.com>
>>> ---
>>> hmp-commands.hx | 2 +-
>>> qemu-options.hx | 5 ++++-
>>> qmp-commands.hx | 2 +-
>>> 3 files changed, 6 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/hmp-commands.hx b/hmp-commands.hx
>>> index 902e2d1..63177a8 100644
>>> --- a/hmp-commands.hx
>>> +++ b/hmp-commands.hx
>>> @@ -1255,7 +1255,7 @@ ETEXI
>>> {
>>> .name = "netfilter_add",
>>> .args_type = "netfilter:O",
>>> - .params =
>>> "[type],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
>>> + .params =
>>> "[buffer],id=str,netdev=str[,chain=in|out|all,prop=value][,...]",
>>
>> Looks like chain is mandatory in patch 2.
>
> It is optional, default is "all".
Right, I see.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:35 ` Yang Hongyang
@ 2015-08-06 7:43 ` Jason Wang
2015-08-06 7:50 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:43 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:35 PM, Yang Hongyang wrote:
> On 08/06/2015 03:29 PM, Jason Wang wrote:
>>
>>
>> On 08/06/2015 03:22 PM, Yang Hongyang wrote:
>>> On 08/06/2015 03:07 PM, Jason Wang wrote:
>>>>
>>>>
>>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>>>>> manage all filters together.
>>>>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific
>>>>> netdev is
>>>>> in this queue.
>>>>> This is mostly the same with init/cleanup of netdev object.
>>>>>
>>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>>> ---
>>>>> include/net/filter.h | 39 +++++++++++++
>>>>> include/net/net.h | 1 +
>>>>> include/qemu/typedefs.h | 1 +
>>>>> net/filter.c | 147
>>>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>>> net/net.c | 1 +
>>>>> qapi-schema.json | 37 ++++++++++++
>>>>> 6 files changed, 226 insertions(+)
>>>>>
>>>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>>>> index 4242ded..9aafe08 100644
>>>>> --- a/include/net/filter.h
>>>>> +++ b/include/net/filter.h
>>>>> @@ -9,7 +9,46 @@
>>>>> #define QEMU_NET_FILTER_H
>>>>>
>>>>> #include "qemu-common.h"
>>>>> +#include "qemu/typedefs.h"
>>>>> +
>>>>> +/* the netfilter chain */
>>>>> +enum {
>>>>> + NET_FILTER_IN,
>>>>> + NET_FILTER_OUT,
>>>>> + NET_FILTER_ALL,
>>>>> +};
>>>>> +
>>>>> +typedef void (FilterCleanup) (NetFilterState *);
>>>>> +/*
>>>>> + * Return:
>>>>> + * 0: finished handling the packet, we should continue
>>>>> + * size: filter stolen this packet, we stop pass this packet
>>>>> further
>>>>> + */
>>>>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState
>>>>> *sender,
>>>>> + unsigned flags, const struct
>>>>> iovec *, int);
>>>>
>>>> Please name all parameters.
>>>
>>> Ok, thanks.
>>>
>>>>
>>>>> +
>>>>> +typedef struct NetFilterInfo {
>>>>> + NetFilterOptionsKind type;
>>>>> + size_t size;
>>>>> + FilterCleanup *cleanup;
>>>>> + FilterReceiveIOV *receive_iov;
>>>>> +} NetFilterInfo;
>>>>> +
>>>>> +struct NetFilterState {
>>>>> + NetFilterInfo *info;
>>>>> + char *model;
>>>>
>>>> Looks like model is never used?
>>>
>>> It can be used when we want to find filters by model. For example,
>>> when we need to find all "buffer" filter, and release all buffered
>>> packets.
>>
>> But this is not implemented in this series.
>
> true.
>
>> And I don't get why you need
>> a such command. Management should keep track of this.
>
> There's a patch in v1 which introduce an API use this, and I dropped that
> because there's no user currently, but that API I suppose to be used
> by MC or COLO which can do periodic checkpoint, to release packets.
> the API is filter_buffer_release_all() IIRC...
I see, let's start with simple case to make review and merging easier.
You can re-introduce them when it has real users.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:43 ` Jason Wang
@ 2015-08-06 7:50 ` Yang Hongyang
2015-08-06 7:53 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:50 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:43 PM, Jason Wang wrote:
> On 08/06/2015 03:35 PM, Yang Hongyang wrote:
>> On 08/06/2015 03:29 PM, Jason Wang wrote:
>>>
>>>
>>> On 08/06/2015 03:22 PM, Yang Hongyang wrote:
>>>> On 08/06/2015 03:07 PM, Jason Wang wrote:
>>>>>
>>>>>
>>>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>>>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>>>>>> manage all filters together.
>>>>>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific
>>>>>> netdev is
>>>>>> in this queue.
>>>>>> This is mostly the same with init/cleanup of netdev object.
>>>>>>
>>>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>>>> ---
>>>>>> include/net/filter.h | 39 +++++++++++++
>>>>>> include/net/net.h | 1 +
>>>>>> include/qemu/typedefs.h | 1 +
>>>>>> net/filter.c | 147
>>>>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>>>> net/net.c | 1 +
>>>>>> qapi-schema.json | 37 ++++++++++++
>>>>>> 6 files changed, 226 insertions(+)
>>>>>>
>>>>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>>>>> index 4242ded..9aafe08 100644
>>>>>> --- a/include/net/filter.h
>>>>>> +++ b/include/net/filter.h
>>>>>> @@ -9,7 +9,46 @@
>>>>>> #define QEMU_NET_FILTER_H
>>>>>>
>>>>>> #include "qemu-common.h"
>>>>>> +#include "qemu/typedefs.h"
>>>>>> +
>>>>>> +/* the netfilter chain */
>>>>>> +enum {
>>>>>> + NET_FILTER_IN,
>>>>>> + NET_FILTER_OUT,
>>>>>> + NET_FILTER_ALL,
>>>>>> +};
>>>>>> +
>>>>>> +typedef void (FilterCleanup) (NetFilterState *);
>>>>>> +/*
>>>>>> + * Return:
>>>>>> + * 0: finished handling the packet, we should continue
>>>>>> + * size: filter stolen this packet, we stop pass this packet
>>>>>> further
>>>>>> + */
>>>>>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *, NetClientState
>>>>>> *sender,
>>>>>> + unsigned flags, const struct
>>>>>> iovec *, int);
>>>>>
>>>>> Please name all parameters.
>>>>
>>>> Ok, thanks.
>>>>
>>>>>
>>>>>> +
>>>>>> +typedef struct NetFilterInfo {
>>>>>> + NetFilterOptionsKind type;
>>>>>> + size_t size;
>>>>>> + FilterCleanup *cleanup;
>>>>>> + FilterReceiveIOV *receive_iov;
>>>>>> +} NetFilterInfo;
>>>>>> +
>>>>>> +struct NetFilterState {
>>>>>> + NetFilterInfo *info;
>>>>>> + char *model;
>>>>>
>>>>> Looks like model is never used?
>>>>
>>>> It can be used when we want to find filters by model. For example,
>>>> when we need to find all "buffer" filter, and release all buffered
>>>> packets.
>>>
>>> But this is not implemented in this series.
>>
>> true.
>>
>>> And I don't get why you need
>>> a such command. Management should keep track of this.
>>
>> There's a patch in v1 which introduce an API use this, and I dropped that
>> because there's no user currently, but that API I suppose to be used
>> by MC or COLO which can do periodic checkpoint, to release packets.
>> the API is filter_buffer_release_all() IIRC...
>
> I see, let's start with simple case to make review and merging easier.
> You can re-introduce them when it has real users.
So do I need to remove model also?
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object
2015-08-06 7:50 ` Yang Hongyang
@ 2015-08-06 7:53 ` Jason Wang
0 siblings, 0 replies; 37+ messages in thread
From: Jason Wang @ 2015-08-06 7:53 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:50 PM, Yang Hongyang wrote:
> On 08/06/2015 03:43 PM, Jason Wang wrote:
>> On 08/06/2015 03:35 PM, Yang Hongyang wrote:
>>> On 08/06/2015 03:29 PM, Jason Wang wrote:
>>>>
>>>>
>>>> On 08/06/2015 03:22 PM, Yang Hongyang wrote:
>>>>> On 08/06/2015 03:07 PM, Jason Wang wrote:
>>>>>>
>>>>>>
>>>>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>>>>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>>>>>>> manage all filters together.
>>>>>>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific
>>>>>>> netdev is
>>>>>>> in this queue.
>>>>>>> This is mostly the same with init/cleanup of netdev object.
>>>>>>>
>>>>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>>>>> ---
>>>>>>> include/net/filter.h | 39 +++++++++++++
>>>>>>> include/net/net.h | 1 +
>>>>>>> include/qemu/typedefs.h | 1 +
>>>>>>> net/filter.c | 147
>>>>>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>>>>> net/net.c | 1 +
>>>>>>> qapi-schema.json | 37 ++++++++++++
>>>>>>> 6 files changed, 226 insertions(+)
>>>>>>>
>>>>>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>>>>>> index 4242ded..9aafe08 100644
>>>>>>> --- a/include/net/filter.h
>>>>>>> +++ b/include/net/filter.h
>>>>>>> @@ -9,7 +9,46 @@
>>>>>>> #define QEMU_NET_FILTER_H
>>>>>>>
>>>>>>> #include "qemu-common.h"
>>>>>>> +#include "qemu/typedefs.h"
>>>>>>> +
>>>>>>> +/* the netfilter chain */
>>>>>>> +enum {
>>>>>>> + NET_FILTER_IN,
>>>>>>> + NET_FILTER_OUT,
>>>>>>> + NET_FILTER_ALL,
>>>>>>> +};
>>>>>>> +
>>>>>>> +typedef void (FilterCleanup) (NetFilterState *);
>>>>>>> +/*
>>>>>>> + * Return:
>>>>>>> + * 0: finished handling the packet, we should continue
>>>>>>> + * size: filter stolen this packet, we stop pass this packet
>>>>>>> further
>>>>>>> + */
>>>>>>> +typedef ssize_t (FilterReceiveIOV)(NetFilterState *,
>>>>>>> NetClientState
>>>>>>> *sender,
>>>>>>> + unsigned flags, const struct
>>>>>>> iovec *, int);
>>>>>>
>>>>>> Please name all parameters.
>>>>>
>>>>> Ok, thanks.
>>>>>
>>>>>>
>>>>>>> +
>>>>>>> +typedef struct NetFilterInfo {
>>>>>>> + NetFilterOptionsKind type;
>>>>>>> + size_t size;
>>>>>>> + FilterCleanup *cleanup;
>>>>>>> + FilterReceiveIOV *receive_iov;
>>>>>>> +} NetFilterInfo;
>>>>>>> +
>>>>>>> +struct NetFilterState {
>>>>>>> + NetFilterInfo *info;
>>>>>>> + char *model;
>>>>>>
>>>>>> Looks like model is never used?
>>>>>
>>>>> It can be used when we want to find filters by model. For example,
>>>>> when we need to find all "buffer" filter, and release all buffered
>>>>> packets.
>>>>
>>>> But this is not implemented in this series.
>>>
>>> true.
>>>
>>>> And I don't get why you need
>>>> a such command. Management should keep track of this.
>>>
>>> There's a patch in v1 which introduce an API use this, and I dropped
>>> that
>>> because there's no user currently, but that API I suppose to be used
>>> by MC or COLO which can do periodic checkpoint, to release packets.
>>> the API is filter_buffer_release_all() IIRC...
>>
>> I see, let's start with simple case to make review and merging easier.
>> You can re-introduce them when it has real users.
>
> So do I need to remove model also?
Yes, please.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send
2015-08-06 7:37 ` Jason Wang
@ 2015-08-06 7:58 ` Yang Hongyang
0 siblings, 0 replies; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 7:58 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:37 PM, Jason Wang wrote:
>
>
> On 08/06/2015 03:28 PM, Yang Hongyang wrote:
>>
>>
>> On 08/06/2015 03:13 PM, Jason Wang wrote:
>>>
>>>
>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>> Capture packets that will be sent.
>>>>
>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>> ---
>>>> net/net.c | 66
>>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>>> 1 file changed, 65 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/net/net.c b/net/net.c
>>>> index 03b2296..efccd56 100644
>>>> --- a/net/net.c
>>>> +++ b/net/net.c
>>>> @@ -569,6 +569,42 @@ int qemu_can_send_packet(NetClientState *sender)
>>>> return 1;
>>>> }
>>>>
>>>> +static ssize_t filter_receive_iov(NetClientState *nc, int chain,
>>>> + NetClientState *sender,
>>>> + unsigned flags,
>>>> + const struct iovec *iov,
>>>> + int iovcnt)
>>>> +{
>>>> + ssize_t ret = 0;
>>>> + NetFilterState *nf = NULL;
>>>> + ssize_t size = iov_size(iov, iovcnt);
>>>> +
>>>> + QTAILQ_FOREACH(nf, &nc->filters, next) {
>>>> + if (nf->chain == chain || nf->chain == NET_FILTER_ALL) {
>>>> + ret = nf->info->receive_iov(nf, sender, flags, iov,
>>>> iovcnt);
>>>> + if (ret == size) {
>>>> + return ret;
>>>> + }
>>>> + }
>>>> + }
>>>> +
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static ssize_t filter_receive(NetClientState *nc, int chain,
>>>> + NetClientState *sender,
>>>> + unsigned flags,
>>>> + const uint8_t *data,
>>>> + size_t size)
>>>> +{
>>>> + struct iovec iov = {
>>>> + .iov_base = (void *)data,
>>>> + .iov_len = size
>>>> + };
>>>> +
>>>> + return filter_receive_iov(nc, chain, sender, flags, &iov, 1);
>>>> +}
>>>> +
>>>> ssize_t qemu_deliver_packet(NetClientState *sender,
>>>> unsigned flags,
>>>> const uint8_t *data,
>>>> @@ -640,6 +676,7 @@ static ssize_t
>>>> qemu_send_packet_async_with_flags(NetClientState *sender,
>>>> NetPacketSent
>>>> *sent_cb)
>>>> {
>>>> NetQueue *queue;
>>>> + int ret;
>>>>
>>>> #ifdef DEBUG_NET
>>>> printf("qemu_send_packet_async:\n");
>>>> @@ -650,6 +687,18 @@ static ssize_t
>>>> qemu_send_packet_async_with_flags(NetClientState *sender,
>>>> return size;
>>>> }
>>>>
>>>> + /* Let filters handle the packet first */
>>>> + ret = filter_receive(sender, NET_FILTER_OUT, sender, flags,
>>>> buf, size);
>>>> + if (ret == size) {
>>>> + return size;
>>>> + }
>>>> +
>>>> + ret = filter_receive(sender->peer, NET_FILTER_IN,
>>>> + sender, flags, buf, size);
>>>> + if (ret == size) {
>>>> + return size;
>>>> + }
>>>
>>> I think we can just trust the return value of filter_receive(), no need
>>> to check it against iov_size.
>>
>> You mean:
>> if (ret)
>> return ret;
>> ? We need to check ret however.
>
> Yes, but the problem is you check it against size. What if
> filter_receive() returns a value which is greater than 0 but smaller
> than size. If this could not happen, probably no need to check. Not a
> must but better to change this.
Ok, will fix, thank you.
>
>>
>>>
>>> Also sent_cb was lost track if the packet was held by filter which seems
>>> wrong.
>>
>> So we need to extend the params of filter's receive_iov API, add a
>> sent_cb
>> param.
>
> Yes.
>
>> BTW, it seems that sent_cb will only been called when packet is
>> queueed and then sent, if the packet being sent directly sent_cb won't
>> be called? am I right? or I missed somthing from the code...
>
> Yes, but if for some reason it couldn't. Sent cb is usually used to let
> main loop to re-poll network backend.
Yes, this matches what I saw. It is kind of strange though, a provided
sent_cb won't be called when a packet been sent directly...
>
>>
>>>
>>> [...]
>>> .
>>>
>>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-06 7:21 ` Jason Wang
@ 2015-08-06 8:19 ` Yang Hongyang
2015-08-06 9:09 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 8:19 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:21 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> This filter is to buffer/release packets, this feature can be used
>> when using MicroCheckpointing, or other Remus like VM FT solutions, you
>> can also use it to simulate the network delay.
>> It has an interval option, if supplied, this filter will release
>> packets by interval.
>>
>> Usage:
>> -netdev tap,id=bn0
>> -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>
>> NOTE:
>> the scale of interval is microsecond.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> ---
>> v4: remove bh
>> pass the packet to next filter instead of receiver
>> v3: check packet's sender and sender->peer when flush it
>> ---
>> net/Makefile.objs | 1 +
>> net/filter-buffer.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> net/filter.c | 2 +
>> net/filters.h | 17 ++++++++
>> qapi-schema.json | 18 +++++++-
>> 5 files changed, 157 insertions(+), 1 deletion(-)
>> create mode 100644 net/filter-buffer.c
>> create mode 100644 net/filters.h
>>
>> 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/filter-buffer.c b/net/filter-buffer.c
>> new file mode 100644
>> index 0000000..fd467db
>> --- /dev/null
>> +++ b/net/filter-buffer.c
>> @@ -0,0 +1,120 @@
>> +/*
>> + * 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/filter.h"
>> +#include "net/queue.h"
>> +#include "filters.h"
>> +#include "qemu-common.h"
>> +#include "qemu/timer.h"
>> +#include "qemu/iov.h"
>> +
>> +typedef struct FILTERBUFFERState {
>> + NetFilterState nf;
>> + NetQueue *incoming_queue;
>> + int64_t interval;
>
> Can interval be negative?
No.
> If not please uint. And not sure you really
> need a 64 bit integer, if not, please use uint32_t.
Ok, will use uint32_t instead.
>
>> + QEMUTimer release_timer;
>> +} FILTERBUFFERState;
>
> Filter buffer is not abbreviation. So better name it as FilterBufferState.
Ok, thanks.
>
>> +
>> +static void packet_send_completed(NetClientState *nc, ssize_t len)
>> +{
>> + return;
>> +}
>
> Why need a dummy sent cb?
Need to work around with queue_append, if there's no sent_cb, queue_append
will simply drop the packet...Even we provide a sent_cb param to receive_iov,
this dummy might still be needed because sent_cb might be null.
>
>> +
>> +static void filter_buffer_flush(NetFilterState *nf)
>> +{
>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>> + NetQueue *queue = s->incoming_queue;
>> + NetPacket *packet;
>> +
>> + while (queue && !QTAILQ_EMPTY(&queue->packets)) {
>> + packet = QTAILQ_FIRST(&queue->packets);
>> + QTAILQ_REMOVE(&queue->packets, packet, entry);
>> + queue->nq_count--;
>> +
>> + if (packet->sender && packet->sender->peer) {
>> + qemu_netfilter_pass_to_next(nf, packet->sender, packet->flags,
>> + packet->data, packet->size);
>> + }
>> +
>> + /*
>> + * now that we pass the packet to next filter, we don't care the
>> + * reture value here, because the filter layer or other filter
>> + * will take care of this packet
>> + */
>> + g_free(packet);
>
> This seems wrong, since packet could be queued into incoming queue.
> Doing this may cause use after free.
The incoming queue will make a copy of packet data when queued a packet.
So I think it's ok to free this packet here...because this packet is
alloced by this filter when calling qemu_net_queue_append_iov.
>
>> + }
>> +}
>> +
>> +static void filter_buffer_release_timer(void *opaque)
>> +{
>> + FILTERBUFFERState *s = opaque;
>> + filter_buffer_flush(&s->nf);
>> + timer_mod(&s->release_timer,
>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>> +}
>> +
>> +/* filter APIs */
>> +static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt)
>> +{
>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>> + NetQueue *queue = s->incoming_queue;
>> +
>> + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
>> + packet_send_completed);
>> + return iov_size(iov, iovcnt);
>
> So if interval is zero, packet will be blocked forever and memory will
> be exhausted.
Yes, but this supposed to be used by FT solutions, so it will
be released periodically. Currently only used with interval makes sense.
>
>> +}
>> +
>> +static void filter_buffer_cleanup(NetFilterState *nf)
>> +{
>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>> +
>> + if (s->interval) {
>> + timer_del(&s->release_timer);
>> + }
>> +
>> + /* flush packets */
>> + filter_buffer_flush(nf);
>> + g_free(s->incoming_queue);
>> + return;
>> +}
>> +
>> +static NetFilterInfo net_filter_buffer_info = {
>> + .type = NET_FILTER_OPTIONS_KIND_BUFFER,
>> + .size = sizeof(FILTERBUFFERState),
>> + .receive_iov = filter_buffer_receive_iov,
>> + .cleanup = filter_buffer_cleanup,
>> +};
>> +
>> +int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
>> + int chain, NetClientState *netdev, Error **errp)
>> +{
>> + NetFilterState *nf;
>> + FILTERBUFFERState *s;
>> + const NetFilterBufferOptions *bufferopt;
>> +
>> + assert(opts->kind == NET_FILTER_OPTIONS_KIND_BUFFER);
>> + bufferopt = opts->buffer;
>> +
>> + nf = qemu_new_net_filter(&net_filter_buffer_info,
>> + netdev, "buffer", name, chain);
>> + s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>> + s->incoming_queue = qemu_new_net_queue(nf);
>> + s->interval = bufferopt->has_interval ? bufferopt->interval : 0;
>> + if (s->interval) {
>> + timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
>> + filter_buffer_release_timer, s);
>> + timer_mod(&s->release_timer,
>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>> + }
>> +
>> + return 0;
>> +}
>> diff --git a/net/filter.c b/net/filter.c
>> index 166b851..02f3e76 100644
>> --- a/net/filter.c
>> +++ b/net/filter.c
>> @@ -19,6 +19,7 @@
>> #include "net/filter.h"
>> #include "net/net.h"
>> #include "net/queue.h"
>> +#include "filters.h"
>>
>> static QTAILQ_HEAD(, NetFilterState) net_filters;
>>
>> @@ -179,6 +180,7 @@ typedef int (NetFilterInit)(const NetFilterOptions *opts,
>>
>> static
>> NetFilterInit * const net_filter_init_fun[NET_FILTER_OPTIONS_KIND_MAX] = {
>> + [NET_FILTER_OPTIONS_KIND_BUFFER] = net_init_filter_buffer,
>> };
>>
>> static int net_filter_init1(const NetFilter *netfilter, Error **errp)
>> diff --git a/net/filters.h b/net/filters.h
>> new file mode 100644
>> index 0000000..3b546db
>> --- /dev/null
>> +++ b/net/filters.h
>> @@ -0,0 +1,17 @@
>> +/*
>> + * 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_FILTERS_H
>> +#define QEMU_NET_FILTERS_H
>> +
>> +#include "net/net.h"
>> +#include "net/filter.h"
>> +
>> +int net_init_filter_buffer(const NetFilterOptions *opts, const char *name,
>> + int chain, NetClientState *netdev, Error **errp);
>> +
>> +#endif /* QEMU_NET_FILTERS_H */
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 9d97c21..e51bb59 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2584,6 +2584,21 @@
>> { 'command': 'netfilter_del', 'data': {'id': 'str'} }
>>
>> ##
>> +# @NetFilterBufferOptions
>> +#
>> +# a netbuffer filter for network backend.
>> +#
>> +# @interval: #optional release packets by interval, if no interval supplied,
>> +# will release packets when filter_buffer_release_all been called.
>> +# scale: microsecond
>> +#
>> +# Since 2.5
>> +##
>> +{ 'struct': 'NetFilterBufferOptions',
>> + 'data': {
>> + '*interval': 'int64' } }
>> +
>> +##
>> # @NetFilterOptions
>> #
>> # A discriminated record of network filters.
>> @@ -2592,7 +2607,8 @@
>> #
>> ##
>> { 'union': 'NetFilterOptions',
>> - 'data': { } }
>> + 'data': {
>> + 'buffer': 'NetFilterBufferOptions'} }
>>
>> ##
>> # @NetFilter
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev
2015-08-06 7:09 ` Jason Wang
2015-08-06 7:22 ` Yang Hongyang
@ 2015-08-06 8:44 ` Yang Hongyang
2015-08-06 9:14 ` Jason Wang
1 sibling, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 8:44 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 03:09 PM, Jason Wang wrote:
>
>
> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>> When we delete the netdev, we also delete the netfilter object
>> attached to it, because if the netdev is removed, the filters
>> which attached to it is useless.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>
> Please squash this into patch 3. (otherwise you're fixing a bug
> introduced by patch 3).
>
>> ---
>> include/net/filter.h | 1 +
>> net/filter.c | 2 +-
>> net/net.c | 14 ++++++++++++++
>> 3 files changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> index 8eff85a..c146be2 100644
>> --- a/include/net/filter.h
>> +++ b/include/net/filter.h
>> @@ -50,6 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info,
>> const char *model,
>> const char *name,
>> int chain);
>> +void qemu_del_net_filter(NetFilterState *nf);
>> void netfilter_add(QemuOpts *opts, Error **errp);
>> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>>
>> diff --git a/net/filter.c b/net/filter.c
>> index 54a5c06..24ec4e1 100644
>> --- a/net/filter.c
>> +++ b/net/filter.c
>> @@ -57,7 +57,7 @@ static void qemu_cleanup_net_filter(NetFilterState *nf)
>> g_free(nf);
>> }
>>
>> -static void qemu_del_net_filter(NetFilterState *nf)
>> +void qemu_del_net_filter(NetFilterState *nf)
>> {
>> /* handle multi queue? */
>> qemu_cleanup_net_filter(nf);
>> diff --git a/net/net.c b/net/net.c
>> index d9b70cd..03b2296 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -28,6 +28,7 @@
>> #include "hub.h"
>> #include "net/slirp.h"
>> #include "net/eth.h"
>> +#include "net/filter.h"
>> #include "util.h"
>>
>> #include "monitor/monitor.h"
>> @@ -385,6 +386,8 @@ void qemu_del_net_client(NetClientState *nc)
>> {
>> NetClientState *ncs[MAX_QUEUE_NUM];
>> int queues, i;
>> + NetFilterState *nf, *next;
>> + QemuOpts *opts;
>>
>> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>>
>> @@ -396,6 +399,17 @@ void qemu_del_net_client(NetClientState *nc)
>> MAX_QUEUE_NUM);
>> assert(queues != 0);
>>
>> + /*
>> + * we delete/free the netfilter object attached to this netdev
>> + * multiqueue netfilter is not supported now, so only delete
>> + * nc->filters is enough.
>> + */
>
> The comment is not correct since for multiqueue, each NetClientState is
> a queue. I think you can just remove above.
But in this function qemu_del_net_client(), it will find all ncs with the
same name (which I thought is multiqueue), and then delete those netclients.
is it ok to move this chunk to qemu_cleanup_net_client()? because in
qemu_cleanup_net_client(), we don't need to deal with multiqueue.
>
>> + QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
>> + opts = qemu_opts_find(qemu_find_opts_err("netfilter", NULL), nf->name);
>> + qemu_del_net_filter(nf);
>> + qemu_opts_del(opts);
>> + }
>> +
>> /* 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) {
>> NICState *nic = qemu_get_nic(nc->peer);
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-06 8:19 ` Yang Hongyang
@ 2015-08-06 9:09 ` Jason Wang
2015-08-06 9:23 ` Yang Hongyang
0 siblings, 1 reply; 37+ messages in thread
From: Jason Wang @ 2015-08-06 9:09 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 04:19 PM, Yang Hongyang wrote:
>
>
> On 08/06/2015 03:21 PM, Jason Wang wrote:
>>
>>
>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>> This filter is to buffer/release packets, this feature can be used
>>> when using MicroCheckpointing, or other Remus like VM FT solutions, you
>>> can also use it to simulate the network delay.
>>> It has an interval option, if supplied, this filter will release
>>> packets by interval.
>>>
>>> Usage:
>>> -netdev tap,id=bn0
>>> -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>>
>>> NOTE:
>>> the scale of interval is microsecond.
>>>
>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>> ---
>>> v4: remove bh
>>> pass the packet to next filter instead of receiver
>>> v3: check packet's sender and sender->peer when flush it
>>> ---
>>> net/Makefile.objs | 1 +
>>> net/filter-buffer.c | 120
>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> net/filter.c | 2 +
>>> net/filters.h | 17 ++++++++
>>> qapi-schema.json | 18 +++++++-
>>> 5 files changed, 157 insertions(+), 1 deletion(-)
>>> create mode 100644 net/filter-buffer.c
>>> create mode 100644 net/filters.h
>>>
>>> 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/filter-buffer.c b/net/filter-buffer.c
>>> new file mode 100644
>>> index 0000000..fd467db
>>> --- /dev/null
>>> +++ b/net/filter-buffer.c
>>> @@ -0,0 +1,120 @@
>>> +/*
>>> + * 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/filter.h"
>>> +#include "net/queue.h"
>>> +#include "filters.h"
>>> +#include "qemu-common.h"
>>> +#include "qemu/timer.h"
>>> +#include "qemu/iov.h"
>>> +
>>> +typedef struct FILTERBUFFERState {
>>> + NetFilterState nf;
>>> + NetQueue *incoming_queue;
>>> + int64_t interval;
>>
>> Can interval be negative?
>
> No.
>
>> If not please uint. And not sure you really
>> need a 64 bit integer, if not, please use uint32_t.
>
> Ok, will use uint32_t instead.
>
>>
>>> + QEMUTimer release_timer;
>>> +} FILTERBUFFERState;
>>
>> Filter buffer is not abbreviation. So better name it as
>> FilterBufferState.
>
> Ok, thanks.
>
>>
>>> +
>>> +static void packet_send_completed(NetClientState *nc, ssize_t len)
>>> +{
>>> + return;
>>> +}
>>
>> Why need a dummy sent cb?
>
> Need to work around with queue_append, if there's no sent_cb,
> queue_append
> will simply drop the packet...Even we provide a sent_cb param to
> receive_iov,
> this dummy might still be needed because sent_cb might be null.
Dropping happens only when the number of queued packet exceeds queue
limitation and no sent_cb. Isn't this just what we want? And like we've
discussed, we need track packet->sent_cb so it was not a problem?
>
>>
>>> +
>>> +static void filter_buffer_flush(NetFilterState *nf)
>>> +{
>>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>>> + NetQueue *queue = s->incoming_queue;
>>> + NetPacket *packet;
>>> +
>>> + while (queue && !QTAILQ_EMPTY(&queue->packets)) {
>>> + packet = QTAILQ_FIRST(&queue->packets);
>>> + QTAILQ_REMOVE(&queue->packets, packet, entry);
>>> + queue->nq_count--;
>>> +
>>> + if (packet->sender && packet->sender->peer) {
>>> + qemu_netfilter_pass_to_next(nf, packet->sender,
>>> packet->flags,
>>> + packet->data, packet->size);
>>> + }
>>> +
>>> + /*
>>> + * now that we pass the packet to next filter, we don't
>>> care the
>>> + * reture value here, because the filter layer or other filter
>>> + * will take care of this packet
>>> + */
>>> + g_free(packet);
>>
>> This seems wrong, since packet could be queued into incoming queue.
>> Doing this may cause use after free.
>
> The incoming queue will make a copy of packet data when queued a packet.
> So I think it's ok to free this packet here...because this packet is
> alloced by this filter when calling qemu_net_queue_append_iov.
>
You're right. I see.
>>
>>> + }
>>> +}
>>> +
>>> +static void filter_buffer_release_timer(void *opaque)
>>> +{
>>> + FILTERBUFFERState *s = opaque;
>>> + filter_buffer_flush(&s->nf);
>>> + timer_mod(&s->release_timer,
>>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>>> +}
>>> +
>>> +/* filter APIs */
>>> +static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>>> + NetClientState *sender,
>>> + unsigned flags,
>>> + const struct iovec *iov,
>>> + int iovcnt)
>>> +{
>>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>>> + NetQueue *queue = s->incoming_queue;
>>> +
>>> + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
>>> + packet_send_completed);
>>> + return iov_size(iov, iovcnt);
>>
>> So if interval is zero, packet will be blocked forever and memory will
>> be exhausted.
>
> Yes, but this supposed to be used by FT solutions, so it will
> be released periodically. Currently only used with interval makes sense.
>
Then you need terminate the initialization when interval is zero.
[...]
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev
2015-08-06 8:44 ` Yang Hongyang
@ 2015-08-06 9:14 ` Jason Wang
0 siblings, 0 replies; 37+ messages in thread
From: Jason Wang @ 2015-08-06 9:14 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 04:44 PM, Yang Hongyang wrote:
>
>
> On 08/06/2015 03:09 PM, Jason Wang wrote:
>>
>>
>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>> When we delete the netdev, we also delete the netfilter object
>>> attached to it, because if the netdev is removed, the filters
>>> which attached to it is useless.
>>>
>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>
>> Please squash this into patch 3. (otherwise you're fixing a bug
>> introduced by patch 3).
>>
>>> ---
>>> include/net/filter.h | 1 +
>>> net/filter.c | 2 +-
>>> net/net.c | 14 ++++++++++++++
>>> 3 files changed, 16 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/include/net/filter.h b/include/net/filter.h
>>> index 8eff85a..c146be2 100644
>>> --- a/include/net/filter.h
>>> +++ b/include/net/filter.h
>>> @@ -50,6 +50,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo
>>> *info,
>>> const char *model,
>>> const char *name,
>>> int chain);
>>> +void qemu_del_net_filter(NetFilterState *nf);
>>> void netfilter_add(QemuOpts *opts, Error **errp);
>>> void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp);
>>>
>>> diff --git a/net/filter.c b/net/filter.c
>>> index 54a5c06..24ec4e1 100644
>>> --- a/net/filter.c
>>> +++ b/net/filter.c
>>> @@ -57,7 +57,7 @@ static void qemu_cleanup_net_filter(NetFilterState
>>> *nf)
>>> g_free(nf);
>>> }
>>>
>>> -static void qemu_del_net_filter(NetFilterState *nf)
>>> +void qemu_del_net_filter(NetFilterState *nf)
>>> {
>>> /* handle multi queue? */
>>> qemu_cleanup_net_filter(nf);
>>> diff --git a/net/net.c b/net/net.c
>>> index d9b70cd..03b2296 100644
>>> --- a/net/net.c
>>> +++ b/net/net.c
>>> @@ -28,6 +28,7 @@
>>> #include "hub.h"
>>> #include "net/slirp.h"
>>> #include "net/eth.h"
>>> +#include "net/filter.h"
>>> #include "util.h"
>>>
>>> #include "monitor/monitor.h"
>>> @@ -385,6 +386,8 @@ void qemu_del_net_client(NetClientState *nc)
>>> {
>>> NetClientState *ncs[MAX_QUEUE_NUM];
>>> int queues, i;
>>> + NetFilterState *nf, *next;
>>> + QemuOpts *opts;
>>>
>>> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>>>
>>> @@ -396,6 +399,17 @@ void qemu_del_net_client(NetClientState *nc)
>>> MAX_QUEUE_NUM);
>>> assert(queues != 0);
>>>
>>> + /*
>>> + * we delete/free the netfilter object attached to this netdev
>>> + * multiqueue netfilter is not supported now, so only delete
>>> + * nc->filters is enough.
>>> + */
>>
>> The comment is not correct since for multiqueue, each NetClientState is
>> a queue. I think you can just remove above.
>
> But in this function qemu_del_net_client(), it will find all ncs with the
> same name (which I thought is multiqueue), and then delete those
> netclients.
>
Right.
> is it ok to move this chunk to qemu_cleanup_net_client()? because in
> qemu_cleanup_net_client(), we don't need to deal with multiqueue.
Yes, looks good.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-06 9:09 ` Jason Wang
@ 2015-08-06 9:23 ` Yang Hongyang
2015-08-06 9:35 ` Jason Wang
0 siblings, 1 reply; 37+ messages in thread
From: Yang Hongyang @ 2015-08-06 9:23 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 05:09 PM, Jason Wang wrote:
>
>
> On 08/06/2015 04:19 PM, Yang Hongyang wrote:
>>
>>
>> On 08/06/2015 03:21 PM, Jason Wang wrote:
>>>
>>>
>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>> This filter is to buffer/release packets, this feature can be used
>>>> when using MicroCheckpointing, or other Remus like VM FT solutions, you
>>>> can also use it to simulate the network delay.
>>>> It has an interval option, if supplied, this filter will release
>>>> packets by interval.
>>>>
>>>> Usage:
>>>> -netdev tap,id=bn0
>>>> -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>>>
>>>> NOTE:
>>>> the scale of interval is microsecond.
>>>>
>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>> ---
>>>> v4: remove bh
>>>> pass the packet to next filter instead of receiver
>>>> v3: check packet's sender and sender->peer when flush it
>>>> ---
>>>> net/Makefile.objs | 1 +
>>>> net/filter-buffer.c | 120
>>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>>> net/filter.c | 2 +
>>>> net/filters.h | 17 ++++++++
>>>> qapi-schema.json | 18 +++++++-
>>>> 5 files changed, 157 insertions(+), 1 deletion(-)
>>>> create mode 100644 net/filter-buffer.c
>>>> create mode 100644 net/filters.h
>>>>
>>>> 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/filter-buffer.c b/net/filter-buffer.c
>>>> new file mode 100644
>>>> index 0000000..fd467db
>>>> --- /dev/null
>>>> +++ b/net/filter-buffer.c
>>>> @@ -0,0 +1,120 @@
>>>> +/*
>>>> + * 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/filter.h"
>>>> +#include "net/queue.h"
>>>> +#include "filters.h"
>>>> +#include "qemu-common.h"
>>>> +#include "qemu/timer.h"
>>>> +#include "qemu/iov.h"
>>>> +
>>>> +typedef struct FILTERBUFFERState {
>>>> + NetFilterState nf;
>>>> + NetQueue *incoming_queue;
>>>> + int64_t interval;
>>>
>>> Can interval be negative?
>>
>> No.
>>
>>> If not please uint. And not sure you really
>>> need a 64 bit integer, if not, please use uint32_t.
>>
>> Ok, will use uint32_t instead.
>>
>>>
>>>> + QEMUTimer release_timer;
>>>> +} FILTERBUFFERState;
>>>
>>> Filter buffer is not abbreviation. So better name it as
>>> FilterBufferState.
>>
>> Ok, thanks.
>>
>>>
>>>> +
>>>> +static void packet_send_completed(NetClientState *nc, ssize_t len)
>>>> +{
>>>> + return;
>>>> +}
>>>
>>> Why need a dummy sent cb?
>>
>> Need to work around with queue_append, if there's no sent_cb,
>> queue_append
>> will simply drop the packet...Even we provide a sent_cb param to
>> receive_iov,
>> this dummy might still be needed because sent_cb might be null.
>
> Dropping happens only when the number of queued packet exceeds queue
> limitation and no sent_cb. Isn't this just what we want?
Yes, you are right.
> And like we've
> discussed, we need track packet->sent_cb so it was not a problem?
Ok, we can drop this dummy callback, thank you.
>
>>
>>>
>>>> +
>>>> +static void filter_buffer_flush(NetFilterState *nf)
>>>> +{
>>>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>>>> + NetQueue *queue = s->incoming_queue;
>>>> + NetPacket *packet;
>>>> +
>>>> + while (queue && !QTAILQ_EMPTY(&queue->packets)) {
>>>> + packet = QTAILQ_FIRST(&queue->packets);
>>>> + QTAILQ_REMOVE(&queue->packets, packet, entry);
>>>> + queue->nq_count--;
>>>> +
>>>> + if (packet->sender && packet->sender->peer) {
>>>> + qemu_netfilter_pass_to_next(nf, packet->sender,
>>>> packet->flags,
>>>> + packet->data, packet->size);
>>>> + }
>>>> +
>>>> + /*
>>>> + * now that we pass the packet to next filter, we don't
>>>> care the
>>>> + * reture value here, because the filter layer or other filter
>>>> + * will take care of this packet
>>>> + */
>>>> + g_free(packet);
>>>
>>> This seems wrong, since packet could be queued into incoming queue.
>>> Doing this may cause use after free.
>>
>> The incoming queue will make a copy of packet data when queued a packet.
>> So I think it's ok to free this packet here...because this packet is
>> alloced by this filter when calling qemu_net_queue_append_iov.
>>
>
> You're right. I see.
>
>>>
>>>> + }
>>>> +}
>>>> +
>>>> +static void filter_buffer_release_timer(void *opaque)
>>>> +{
>>>> + FILTERBUFFERState *s = opaque;
>>>> + filter_buffer_flush(&s->nf);
>>>> + timer_mod(&s->release_timer,
>>>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>>>> +}
>>>> +
>>>> +/* filter APIs */
>>>> +static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>>>> + NetClientState *sender,
>>>> + unsigned flags,
>>>> + const struct iovec *iov,
>>>> + int iovcnt)
>>>> +{
>>>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>>>> + NetQueue *queue = s->incoming_queue;
>>>> +
>>>> + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
>>>> + packet_send_completed);
>>>> + return iov_size(iov, iovcnt);
>>>
>>> So if interval is zero, packet will be blocked forever and memory will
>>> be exhausted.
>>
>> Yes, but this supposed to be used by FT solutions, so it will
>> be released periodically. Currently only used with interval makes sense.
>>
>
> Then you need terminate the initialization when interval is zero.
Ok, but I'd like to also write a comment with it to mention when there're
users, the interval check can be dropped.
>
> [...]
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter
2015-08-06 9:23 ` Yang Hongyang
@ 2015-08-06 9:35 ` Jason Wang
0 siblings, 0 replies; 37+ messages in thread
From: Jason Wang @ 2015-08-06 9:35 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, eddie.dong, mrhines,
stefanha
On 08/06/2015 05:23 PM, Yang Hongyang wrote:
>
>
> On 08/06/2015 05:09 PM, Jason Wang wrote:
>>
>>
>> On 08/06/2015 04:19 PM, Yang Hongyang wrote:
>>>
>>>
>>> On 08/06/2015 03:21 PM, Jason Wang wrote:
>>>>
>>>>
>>>> On 08/04/2015 04:30 PM, Yang Hongyang wrote:
>>>>> This filter is to buffer/release packets, this feature can be used
>>>>> when using MicroCheckpointing, or other Remus like VM FT
>>>>> solutions, you
>>>>> can also use it to simulate the network delay.
>>>>> It has an interval option, if supplied, this filter will release
>>>>> packets by interval.
>>>>>
>>>>> Usage:
>>>>> -netdev tap,id=bn0
>>>>> -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>>>>
>>>>> NOTE:
>>>>> the scale of interval is microsecond.
>>>>>
>>>>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>>>>> ---
>>>>> v4: remove bh
>>>>> pass the packet to next filter instead of receiver
>>>>> v3: check packet's sender and sender->peer when flush it
>>>>> ---
>>>>>
[...]
>>>>>>>
>>>>>>>> + }
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static void filter_buffer_release_timer(void *opaque)
>>>>>>>> +{
>>>>>>>> + FILTERBUFFERState *s = opaque;
>>>>>>>> + filter_buffer_flush(&s->nf);
>>>>>>>> + timer_mod(&s->release_timer,
>>>>>>>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) +
>>>>>>>> s->interval);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/* filter APIs */
>>>>>>>> +static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
>>>>>>>> + NetClientState *sender,
>>>>>>>> + unsigned flags,
>>>>>>>> + const struct iovec *iov,
>>>>>>>> + int iovcnt)
>>>>>>>> +{
>>>>>>>> + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf);
>>>>>>>> + NetQueue *queue = s->incoming_queue;
>>>>>>>> +
>>>>>>>> + qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt,
>>>>>>>> + packet_send_completed);
>>>>>>>> + return iov_size(iov, iovcnt);
>>>>>>>
>>>>>>> So if interval is zero, packet will be blocked forever and
>>>>>>> memory will
>>>>>>> be exhausted.
>>>>>>
>>>>>> Yes, but this supposed to be used by FT solutions, so it will
>>>>>> be released periodically. Currently only used with interval makes
>>>>>> sense.
>>>>>>
>>>>>
>>>>> Then you need terminate the initialization when interval is zero.
>
> Ok, but I'd like to also write a comment with it to mention when there're
> users, the interval check can be dropped.
Ok.
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2015-08-06 9:35 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-04 8:30 [Qemu-devel] [PATCH v4 00/11] For QEMU 2.5: Add a netfilter object and netbuffer filter Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 01/11] net: add a new object netfilter Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 02/11] init/cleanup of netfilter object Yang Hongyang
2015-08-06 7:07 ` Jason Wang
2015-08-06 7:22 ` Yang Hongyang
2015-08-06 7:29 ` Jason Wang
2015-08-06 7:35 ` Yang Hongyang
2015-08-06 7:43 ` Jason Wang
2015-08-06 7:50 ` Yang Hongyang
2015-08-06 7:53 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 03/11] netfilter: add netfilter_{add|del} commands Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 04/11] net: delete netfilter object when delete netdev Yang Hongyang
2015-08-06 7:09 ` Jason Wang
2015-08-06 7:22 ` Yang Hongyang
2015-08-06 8:44 ` Yang Hongyang
2015-08-06 9:14 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 05/11] netfilter: hook packets before net queue send Yang Hongyang
2015-08-06 7:13 ` Jason Wang
2015-08-06 7:28 ` Yang Hongyang
2015-08-06 7:37 ` Jason Wang
2015-08-06 7:58 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 06/11] netfilter: add an API to pass the packet to next filter Yang Hongyang
2015-08-06 7:16 ` Jason Wang
2015-08-06 7:29 ` Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 07/11] net/queue: export qemu_net_queue_append_iov Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 08/11] move out net queue structs define Yang Hongyang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 09/11] netfilter: add a netbuffer filter Yang Hongyang
2015-08-06 7:21 ` Jason Wang
2015-08-06 8:19 ` Yang Hongyang
2015-08-06 9:09 ` Jason Wang
2015-08-06 9:23 ` Yang Hongyang
2015-08-06 9:35 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 10/11] filter/buffer: update command description and help Yang Hongyang
2015-08-06 7:22 ` Jason Wang
2015-08-06 7:31 ` Yang Hongyang
2015-08-06 7:39 ` Jason Wang
2015-08-04 8:30 ` [Qemu-devel] [PATCH v4 11/11] tests: add test cases for netfilter object Yang Hongyang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).