* [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
@ 2015-09-09 7:24 Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 01/10] qmp: delete qemu opts when delete an object Yang Hongyang
` (10 more replies)
0 siblings, 11 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
This patch add an netfilter abstract object, captures all network packets
on associated netdev. Also implement a concrete filter buffer based on
this abstract 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-v10
Usage:
-netdev tap,id=bn0
-device e1000,netdev=bn0
-object filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
dynamically add/remove netfilters:
object_add filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
object_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
v10:
- Reimplemented using QOM (suggested by stefan)
- Do not export NetQueue internals (suggested by stefan)
- see individual patch for detail
v9:
- squash command description and help to patch 1&3
- qapi changes according to Markus&Eric's comments
- see individual patch for detail
v8:
- some minor fixes according to Thomas's comments
- rebased to the latest master branch
v7:
- print filter info when execute 'info network'
- addressed Jason's comments
v6:
- add multiqueue support, please see individual patch for detail
v5:
- add a sent_cb param to filter receive_iov api
- squash the 4th patch into patch 3
- remove dummy sent_cb (buffer filter)
- addressed Jason's other comments, see individual patches for detail
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 (10):
qmp: delete qemu opts when delete an object
init/cleanup of netfilter object
netfilter: hook packets before net queue send
net: merge qemu_deliver_packet and qemu_deliver_packet_iov
net/queue: introduce NetQueueDeliverFunc
netfilter: add an API to pass the packet to next filter
netfilter: print filter info associate with the netdev
net/queue: export qemu_net_queue_append_iov
netfilter: add a netbuffer filter
tests: add test cases for netfilter object
include/net/filter.h | 68 ++++++++++++++++
include/net/net.h | 6 +-
include/net/queue.h | 20 ++++-
include/qemu/typedefs.h | 1 +
net/Makefile.objs | 2 +
net/filter-buffer.c | 169 ++++++++++++++++++++++++++++++++++++++
net/filter.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net.c | 116 ++++++++++++++++++++------
net/queue.c | 24 ++++--
qapi-schema.json | 18 ++++
qemu-options.hx | 18 ++++
qmp.c | 4 +
tests/.gitignore | 1 +
tests/Makefile | 2 +
tests/test-netfilter.c | 200 +++++++++++++++++++++++++++++++++++++++++++++
vl.c | 18 ++--
16 files changed, 833 insertions(+), 47 deletions(-)
create mode 100644 include/net/filter.h
create mode 100644 net/filter-buffer.c
create mode 100644 net/filter.c
create mode 100644 tests/test-netfilter.c
--
1.9.1
^ permalink raw reply [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 01/10] qmp: delete qemu opts when delete an object
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object Yang Hongyang
` (9 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
When delete an object, we need to delete the associated qemu opts,
otherwise, we can not add another object with the same name using
object_add.
The case happens when we start qemu with:
-object xxx,id=aa
then we delete this object with:
object_del aa
then add the object with:
object_add xxx,id=aa
QEMU will return error with Duplicate ID error.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
qmp.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/qmp.c b/qmp.c
index 403805a..c6b85dd 100644
--- a/qmp.c
+++ b/qmp.c
@@ -680,6 +680,7 @@ void qmp_object_del(const char *id, Error **errp)
{
Object *container;
Object *obj;
+ QemuOpts *opts;
container = object_get_objects_root();
obj = object_resolve_path_component(container, id);
@@ -693,6 +694,9 @@ void qmp_object_del(const char *id, Error **errp)
return;
}
object_unparent(obj);
+
+ opts = qemu_opts_find(qemu_find_opts_err("object", NULL), id);
+ qemu_opts_del(opts);
}
MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 01/10] qmp: delete qemu opts when delete an object Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-14 8:54 ` Daniel P. Berrange
2015-09-16 9:28 ` Jason Wang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 03/10] netfilter: hook packets before net queue send Yang Hongyang
` (8 subsequent siblings)
10 siblings, 2 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
Add a netfilter object based on QOM.
A netfilter is attached to a netdev, captures all network packets
that pass through the netdev. When we delete the netdev, we also
delete the netfilter object attached to it, because if the netdev is
removed, the filter which attached to it is useless.
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.
Also init delayed object after net_init_clients, because netfilters need
to be initialized after net clients initialized.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
v10: use QOM for netfilter
v9: use flat union instead of simple union in QAPI schema
v8: include vhost_net header
v7: add check for vhost
fix error propagate bug
v6: add multiqueue support (net_filter_init1)
v5: remove model from NetFilterState
add a sent_cb param to receive_iov API
---
include/net/filter.h | 60 +++++++++++++++++++
include/net/net.h | 1 +
include/qemu/typedefs.h | 1 +
net/Makefile.objs | 1 +
net/filter.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net.c | 6 ++
qapi-schema.json | 18 ++++++
vl.c | 13 ++--
8 files changed, 247 insertions(+), 6 deletions(-)
create mode 100644 include/net/filter.h
create mode 100644 net/filter.c
diff --git a/include/net/filter.h b/include/net/filter.h
new file mode 100644
index 0000000..4557cb9
--- /dev/null
+++ b/include/net/filter.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef QEMU_NET_FILTER_H
+#define QEMU_NET_FILTER_H
+
+#include "qom/object.h"
+#include "qemu-common.h"
+#include "qemu/typedefs.h"
+#include "net/queue.h"
+
+#define TYPE_NETFILTER "netfilter"
+#define NETFILTER(obj) \
+ OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER)
+#define NETFILTER_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER)
+#define NETFILTER_CLASS(klass) \
+ OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
+
+typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
+typedef void (FilterCleanup) (NetFilterState *nf);
+/*
+ * 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 *nc,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb);
+
+typedef struct NetFilterClass {
+ ObjectClass parent_class;
+
+ FilterSetup *setup;
+ FilterCleanup *cleanup;
+ FilterReceiveIOV *receive_iov;
+} NetFilterClass;
+
+
+struct NetFilterState {
+ /* private */
+ Object parent;
+
+ /* protected */
+ char *netdev_id;
+ NetClientState *netdev;
+ NetFilterChain chain;
+ QTAILQ_ENTRY(NetFilterState) global_list;
+ QTAILQ_ENTRY(NetFilterState) next;
+};
+
+#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 f8a9dd6..2c0648f 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/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..5192c6d
--- /dev/null
+++ b/net/filter.c
@@ -0,0 +1,153 @@
+/*
+ * 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 "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+#include "qemu/error-report.h"
+
+#include "net/filter.h"
+#include "net/net.h"
+#include "net/vhost_net.h"
+#include "qom/object_interfaces.h"
+
+static QTAILQ_HEAD(, NetFilterState) net_filters;
+
+static char *netfilter_get_netdev_id(Object *obj, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ return g_strdup(nf->netdev_id);
+}
+
+static void netfilter_set_netdev_id(Object *obj, const char *str, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+
+ nf->netdev_id = g_strdup(str);
+}
+
+static int netfilter_get_chain(Object *obj, Error **errp G_GNUC_UNUSED)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ return nf->chain;
+}
+
+static void netfilter_set_chain(Object *obj, int chain, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ nf->chain = chain;
+}
+
+static void netfilter_init(Object *obj)
+{
+ QTAILQ_INIT(&net_filters);
+ object_property_add_str(obj, "netdev",
+ netfilter_get_netdev_id, netfilter_set_netdev_id,
+ NULL);
+ object_property_add_enum(obj, "chain", "NetFilterChain",
+ NetFilterChain_lookup,
+ netfilter_get_chain, netfilter_set_chain,
+ NULL);
+}
+
+static void netfilter_cleanup(Object *obj)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
+
+ if (nfc->cleanup) {
+ nfc->cleanup(nf);
+ }
+
+ if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
+ QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
+ }
+ if (!QTAILQ_EMPTY(&net_filters)) {
+ QTAILQ_REMOVE(&net_filters, nf, global_list);
+ }
+
+ g_free(nf->netdev_id);
+}
+
+static void netfilter_complete(UserCreatable *uc, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(uc);
+ NetClientState *ncs[MAX_QUEUE_NUM];
+ NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
+ int queues;
+ Error *local_err = NULL;
+
+ if (!nf->netdev_id) {
+ error_setg(errp, "Parameter 'netdev' is required");
+ return;
+ }
+
+ queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
+ NET_CLIENT_OPTIONS_KIND_NIC,
+ MAX_QUEUE_NUM);
+ if (queues < 1) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
+ "a network backend id");
+ return;
+ } else if (queues > 1) {
+ error_setg(errp, "Multi queue is not supported");
+ return;
+ }
+
+ if (get_vhost_net(ncs[0])) {
+ error_setg(errp, "Vhost is not supported");
+ return;
+ }
+
+ nf->netdev = ncs[0];
+
+ if (nfc->setup) {
+ nfc->setup(nf, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+ QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
+ QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
+}
+
+static bool netfilter_can_be_deleted(UserCreatable *uc, Error **errp)
+{
+ return true;
+}
+
+static void netfilter_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+ ucc->complete = netfilter_complete;
+ ucc->can_be_deleted = netfilter_can_be_deleted;
+}
+
+static const TypeInfo netfilter_info = {
+ .name = TYPE_NETFILTER,
+ .parent = TYPE_OBJECT,
+ .abstract = true,
+ .class_size = sizeof(NetFilterClass),
+ .class_init = netfilter_class_init,
+ .instance_size = sizeof(NetFilterState),
+ .instance_init = netfilter_init,
+ .instance_finalize = netfilter_cleanup,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
+};
+
+static void register_types(void)
+{
+ type_register_static(&netfilter_info);
+}
+
+type_init(register_types);
diff --git a/net/net.c b/net/net.c
index 28a5597..d6d4db8 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,
@@ -384,6 +385,7 @@ void qemu_del_net_client(NetClientState *nc)
{
NetClientState *ncs[MAX_QUEUE_NUM];
int queues, i;
+ NetFilterState *nf, *next;
assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
@@ -395,6 +397,10 @@ void qemu_del_net_client(NetClientState *nc)
MAX_QUEUE_NUM);
assert(queues != 0);
+ QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
+ object_unparent(OBJECT(nf));
+ }
+
/* 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);
diff --git a/qapi-schema.json b/qapi-schema.json
index 67fef37..068e89e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2551,6 +2551,24 @@
'opts': 'NetClientOptions' } }
##
+# @NetFilterChain
+#
+# netfilter chain, a netfilter is attached to a netdev, captures the
+# network packets of the netdev.
+#
+# @all: the filter will receive packets both sent to/from the netdev, this
+# is the default chain.
+#
+# @in: the filter will receive packets sent to the netdev.
+#
+# @out: the filter will receive packets sent from the netdev.
+#
+# Since 2.5
+##
+{ 'enum': 'NetFilterChain',
+ 'data': [ 'all', 'in', 'out' ] }
+
+##
# @InetSocketAddress
#
# Captures a socket address or address range in the Internet namespace.
diff --git a/vl.c b/vl.c
index 584ca88..672f8b2 100644
--- a/vl.c
+++ b/vl.c
@@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
if (g_str_equal(type, "rng-egd")) {
return false;
}
+ /* TODO: reture false for concrete netfilters */
return true;
}
@@ -4302,12 +4303,6 @@ int main(int argc, char **argv, char **envp)
exit(0);
}
- if (qemu_opts_foreach(qemu_find_opts("object"),
- object_create,
- object_create_delayed, NULL)) {
- exit(1);
- }
-
machine_opts = qemu_get_machine_opts();
if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
NULL)) {
@@ -4413,6 +4408,12 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ if (qemu_opts_foreach(qemu_find_opts("object"),
+ object_create,
+ object_create_delayed, NULL)) {
+ exit(1);
+ }
+
#ifdef CONFIG_TPM
if (tpm_init() < 0) {
exit(1);
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 03/10] netfilter: hook packets before net queue send
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 01/10] qmp: delete qemu opts when delete an object Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
` (7 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
Capture packets that will be sent.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
v10: adjust due to QOM
v5: do not check ret against iov_size
pass sent_cb to filters
---
net/net.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
diff --git a/net/net.c b/net/net.c
index d6d4db8..1f46ad0 100644
--- a/net/net.c
+++ b/net/net.c
@@ -44,6 +44,7 @@
#include "qapi/opts-visitor.h"
#include "qapi/dealloc-visitor.h"
#include "sysemu/sysemu.h"
+#include "net/filter.h"
/* Net bridge is currently not supported for W32. */
#if !defined(_WIN32)
@@ -560,6 +561,44 @@ int qemu_can_send_packet(NetClientState *sender)
return 1;
}
+static ssize_t filter_receive_iov(NetClientState *nc, NetFilterChain chain,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
+{
+ ssize_t ret = 0;
+ NetFilterState *nf = NULL;
+
+ QTAILQ_FOREACH(nf, &nc->filters, next) {
+ if (nf->chain == chain || nf->chain == NET_FILTER_CHAIN_ALL) {
+ ret = NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
+ nf, sender, flags, iov, iovcnt, sent_cb);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t filter_receive(NetClientState *nc, NetFilterChain chain,
+ NetClientState *sender,
+ unsigned flags,
+ const uint8_t *data,
+ size_t size,
+ NetPacketSent *sent_cb)
+{
+ struct iovec iov = {
+ .iov_base = (void *)data,
+ .iov_len = size
+ };
+
+ return filter_receive_iov(nc, chain, sender, flags, &iov, 1, sent_cb);
+}
+
ssize_t qemu_deliver_packet(NetClientState *sender,
unsigned flags,
const uint8_t *data,
@@ -631,6 +670,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");
@@ -641,6 +681,19 @@ 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_CHAIN_OUT,
+ sender, flags, buf, size, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
+ ret = filter_receive(sender->peer, NET_FILTER_CHAIN_IN,
+ sender, flags, buf, size, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
queue = sender->peer->incoming_queue;
return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
@@ -711,11 +764,25 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
NetPacketSent *sent_cb)
{
NetQueue *queue;
+ int ret;
if (sender->link_down || !sender->peer) {
return iov_size(iov, iovcnt);
}
+ /* Let filters handle the packet first */
+ ret = filter_receive_iov(sender, NET_FILTER_CHAIN_OUT, sender,
+ QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
+ ret = filter_receive_iov(sender->peer, NET_FILTER_CHAIN_IN, sender,
+ QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
queue = sender->peer->incoming_queue;
return qemu_net_queue_send_iov(queue, sender,
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (2 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 03/10] netfilter: hook packets before net queue send Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
` (6 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
qemu_deliver_packet_iov already have the compat delivery, we
can drop qemu_deliver_packet.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
include/net/net.h | 5 -----
net/net.c | 40 +++++++---------------------------------
net/queue.c | 6 +++++-
3 files changed, 12 insertions(+), 39 deletions(-)
diff --git a/include/net/net.h b/include/net/net.h
index 36e5fab..7af3e15 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -152,11 +152,6 @@ void qemu_check_nic_model(NICInfo *nd, const char *model);
int qemu_find_nic_model(NICInfo *nd, const char * const *models,
const char *default_model);
-ssize_t qemu_deliver_packet(NetClientState *sender,
- unsigned flags,
- const uint8_t *data,
- size_t size,
- void *opaque);
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
unsigned flags,
const struct iovec *iov,
diff --git a/net/net.c b/net/net.c
index 1f46ad0..db43445 100644
--- a/net/net.c
+++ b/net/net.c
@@ -599,36 +599,6 @@ static ssize_t filter_receive(NetClientState *nc, NetFilterChain chain,
return filter_receive_iov(nc, chain, sender, flags, &iov, 1, sent_cb);
}
-ssize_t qemu_deliver_packet(NetClientState *sender,
- unsigned flags,
- const uint8_t *data,
- size_t size,
- void *opaque)
-{
- NetClientState *nc = opaque;
- ssize_t ret;
-
- if (nc->link_down) {
- return size;
- }
-
- if (nc->receive_disabled) {
- return 0;
- }
-
- if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
- ret = nc->info->receive_raw(nc, data, size);
- } else {
- ret = nc->info->receive(nc, data, size);
- }
-
- if (ret == 0) {
- nc->receive_disabled = 1;
- }
-
- return ret;
-}
-
void qemu_purge_queued_packets(NetClientState *nc)
{
if (!nc->peer) {
@@ -719,14 +689,18 @@ ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
}
static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
- int iovcnt)
+ int iovcnt, unsigned flags)
{
uint8_t buffer[NET_BUFSIZE];
size_t offset;
offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
- return nc->info->receive(nc, buffer, offset);
+ if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
+ return nc->info->receive_raw(nc, buffer, offset);
+ } else {
+ return nc->info->receive(nc, buffer, offset);
+ }
}
ssize_t qemu_deliver_packet_iov(NetClientState *sender,
@@ -749,7 +723,7 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
if (nc->info->receive_iov) {
ret = nc->info->receive_iov(nc, iov, iovcnt);
} else {
- ret = nc_sendv_compat(nc, iov, iovcnt);
+ ret = nc_sendv_compat(nc, iov, iovcnt, flags);
}
if (ret == 0) {
diff --git a/net/queue.c b/net/queue.c
index ebbe2bb..cf8db3a 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -152,9 +152,13 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue,
size_t size)
{
ssize_t ret = -1;
+ struct iovec iov = {
+ .iov_base = (void *)data,
+ .iov_len = size
+ };
queue->delivering = 1;
- ret = qemu_deliver_packet(sender, flags, data, size, queue->opaque);
+ ret = qemu_deliver_packet_iov(sender, flags, &iov, 1, queue->opaque);
queue->delivering = 0;
return ret;
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 05/10] net/queue: introduce NetQueueDeliverFunc
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (3 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
` (5 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
net/queue.c has logic to send/queue/flush packets but a
qemu_deliver_packet_iov() call is hardcoded. Abstract this
func so that we can use our own deliver function in netfilter.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
---
include/net/queue.h | 13 ++++++++++++-
net/net.c | 2 +-
net/queue.c | 8 +++++---
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/include/net/queue.h b/include/net/queue.h
index fc02b33..b4a7183 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -34,7 +34,18 @@ typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
#define QEMU_NET_PACKET_FLAG_NONE 0
#define QEMU_NET_PACKET_FLAG_RAW (1<<0)
-NetQueue *qemu_new_net_queue(void *opaque);
+/* Returns:
+ * >0 - success
+ * 0 - queue packet for future redelivery
+ * <0 - failure (discard packet)
+ */
+typedef ssize_t (NetQueueDeliverFunc)(NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ void *opaque);
+
+NetQueue *qemu_new_net_queue(NetQueueDeliverFunc *deliver, void *opaque);
void qemu_del_net_queue(NetQueue *queue);
diff --git a/net/net.c b/net/net.c
index db43445..112f334 100644
--- a/net/net.c
+++ b/net/net.c
@@ -286,7 +286,7 @@ static void qemu_net_client_setup(NetClientState *nc,
}
QTAILQ_INSERT_TAIL(&net_clients, nc, next);
- nc->incoming_queue = qemu_new_net_queue(nc);
+ nc->incoming_queue = qemu_new_net_queue(qemu_deliver_packet_iov, nc);
nc->destructor = destructor;
QTAILQ_INIT(&nc->filters);
}
diff --git a/net/queue.c b/net/queue.c
index cf8db3a..16dddf0 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -52,13 +52,14 @@ struct NetQueue {
void *opaque;
uint32_t nq_maxlen;
uint32_t nq_count;
+ NetQueueDeliverFunc *deliver;
QTAILQ_HEAD(packets, NetPacket) packets;
unsigned delivering : 1;
};
-NetQueue *qemu_new_net_queue(void *opaque)
+NetQueue *qemu_new_net_queue(NetQueueDeliverFunc *deliver, void *opaque)
{
NetQueue *queue;
@@ -67,6 +68,7 @@ NetQueue *qemu_new_net_queue(void *opaque)
queue->opaque = opaque;
queue->nq_maxlen = 10000;
queue->nq_count = 0;
+ queue->deliver = deliver;
QTAILQ_INIT(&queue->packets);
@@ -158,7 +160,7 @@ static ssize_t qemu_net_queue_deliver(NetQueue *queue,
};
queue->delivering = 1;
- ret = qemu_deliver_packet_iov(sender, flags, &iov, 1, queue->opaque);
+ ret = queue->deliver(sender, flags, &iov, 1, queue->opaque);
queue->delivering = 0;
return ret;
@@ -173,7 +175,7 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
ssize_t ret = -1;
queue->delivering = 1;
- ret = qemu_deliver_packet_iov(sender, flags, iov, iovcnt, queue->opaque);
+ ret = queue->deliver(sender, flags, iov, iovcnt, queue->opaque);
queue->delivering = 0;
return ret;
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (4 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-16 9:29 ` Jason Wang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
` (4 subsequent siblings)
10 siblings, 1 reply; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
add an API qemu_netfilter_pass_to_next() to pass the packet
to next filter.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
---
v10: adjust as a NetQueueDeliverFunc
v9: fix a bug when curr filter chain is all
v5: fold params to NetPacket struct
---
include/net/filter.h | 7 ++++++
net/filter.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index 4557cb9..ed2bb66 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -57,4 +57,11 @@ struct NetFilterState {
QTAILQ_ENTRY(NetFilterState) next;
};
+/* pass the packet to the next filter */
+ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ void *opaque);
+
#endif /* QEMU_NET_FILTER_H */
diff --git a/net/filter.c b/net/filter.c
index 5192c6d..086f271 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -14,9 +14,69 @@
#include "net/net.h"
#include "net/vhost_net.h"
#include "qom/object_interfaces.h"
+#include "qemu/iov.h"
static QTAILQ_HEAD(, NetFilterState) net_filters;
+ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ void *opaque)
+{
+ int ret = 0;
+ int chain;
+ NetFilterState *nf = opaque;
+ NetFilterState *next = QTAILQ_NEXT(nf, next);
+
+ if (!sender || !sender->peer) {
+ /* no receiver, or sender been deleted, no need to pass it further */
+ goto out;
+ }
+
+ if (nf->chain == NET_FILTER_CHAIN_ALL) {
+ if (sender == nf->netdev) {
+ /* This packet is sent by netdev itself */
+ chain = NET_FILTER_CHAIN_OUT;
+ } else {
+ chain = NET_FILTER_CHAIN_IN;
+ }
+ } else {
+ chain = nf->chain;
+ }
+
+ while (next) {
+ if (next->chain == chain || next->chain == NET_FILTER_CHAIN_ALL) {
+ /*
+ * if qemu_netfilter_pass_to_next been called, means that
+ * the packet has been hold by filter and has already retured size
+ * to the sender, so sent_cb shouldn't be called later, just
+ * pass NULL to next.
+ */
+ ret = NETFILTER_GET_CLASS(OBJECT(next))->receive_iov(
+ next, sender, flags, iov, iovcnt, NULL);
+ if (ret) {
+ return ret;
+ }
+ }
+ next = QTAILQ_NEXT(next, next);
+ }
+
+ /*
+ * We have gone through all filters, pass it to receiver.
+ * Do the valid check again incase sender or receiver been
+ * deleted while we go through filters.
+ */
+ if (sender && sender->peer) {
+ return qemu_net_queue_send_iov(sender->peer->incoming_queue,
+ sender, flags, iov, iovcnt, NULL);
+ }
+
+out:
+ /* no receiver, or sender been deleted */
+ return iov_size(iov, iovcnt);
+}
+
static char *netfilter_get_netdev_id(Object *obj, Error **errp)
{
NetFilterState *nf = NETFILTER(obj);
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 07/10] netfilter: print filter info associate with the netdev
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (5 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
` (3 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru,
Yang Hongyang, stefanha, Yang Hongyang
From: Yang Hongyang <burnef@gmail.com>
When execute "info network", print filter info also.
add a info_str member to NetFilterState, store specific filters
info.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
v10: add a info_str member to NetFilterState
v9: tiny cleanup according to Tomas's comment.
v7: initial patch
---
include/net/filter.h | 1 +
net/net.c | 17 +++++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index ed2bb66..c0b9f0a 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -53,6 +53,7 @@ struct NetFilterState {
char *netdev_id;
NetClientState *netdev;
NetFilterChain chain;
+ char info_str[256];
QTAILQ_ENTRY(NetFilterState) global_list;
QTAILQ_ENTRY(NetFilterState) next;
};
diff --git a/net/net.c b/net/net.c
index 112f334..d39ca1c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1172,10 +1172,27 @@ void qmp_netdev_del(const char *id, Error **errp)
void print_net_client(Monitor *mon, NetClientState *nc)
{
+ NetFilterState *nf;
+
monitor_printf(mon, "%s: index=%d,type=%s,%s\n", nc->name,
nc->queue_index,
NetClientOptionsKind_lookup[nc->info->type],
nc->info_str);
+ if (!QTAILQ_EMPTY(&nc->filters)) {
+ monitor_printf(mon, "filters:\n");
+ }
+ QTAILQ_FOREACH(nf, &nc->filters, next) {
+ monitor_printf(mon, " - %s: type=%s,netdev=%s,chain=%s",
+ object_get_canonical_path_component(OBJECT(nf)),
+ object_get_typename(OBJECT(nf)),
+ nf->netdev->name,
+ NetFilterChain_lookup[nf->chain]);
+ if (strlen(nf->info_str)) {
+ monitor_printf(mon, ",%s\n", nf->info_str);
+ } else {
+ monitor_printf(mon, "\n");
+ }
+ }
}
RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 08/10] net/queue: export qemu_net_queue_append_iov
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (6 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter Yang Hongyang
` (2 subsequent siblings)
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
This will be used by buffer filter implementation later to
queue packets.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Reviewed-by: Thomas Huth <thuth@redhat.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 b4a7183..5469fdb 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -47,6 +47,13 @@ typedef ssize_t (NetQueueDeliverFunc)(NetClientState *sender,
NetQueue *qemu_new_net_queue(NetQueueDeliverFunc *deliver, 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 16dddf0..de8b9d3 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -112,12 +112,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] 28+ messages in thread
* [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (7 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-14 9:04 ` Daniel P. Berrange
2015-09-16 9:42 ` Jason Wang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 10/10] tests: add test cases for netfilter object Yang Hongyang
2015-09-14 5:09 ` [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
10 siblings, 2 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, 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
-object filter-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>
---
v10: use NetQueue flush api to flush packets
sent_cb can not be called when we already return size
v9: adjustment due to the qapi change
v7: use QTAILQ_FOREACH_SAFE() when flush packets
v6: move the interval check earlier and some comment adjust
v5: remove dummy sent_cb
change interval type from int64 to uint32
check interval!=0 when initialise
rename FILTERBUFFERState to FilterBufferState
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 | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-options.hx | 18 ++++++
vl.c | 7 ++-
4 files changed, 194 insertions(+), 1 deletion(-)
create mode 100644 net/filter-buffer.c
diff --git a/net/Makefile.objs b/net/Makefile.objs
index 914aec0..5fa2f97 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -14,3 +14,4 @@ common-obj-$(CONFIG_SLIRP) += slirp.o
common-obj-$(CONFIG_VDE) += vde.o
common-obj-$(CONFIG_NETMAP) += netmap.o
common-obj-y += filter.o
+common-obj-y += filter-buffer.o
diff --git a/net/filter-buffer.c b/net/filter-buffer.c
new file mode 100644
index 0000000..26698d9
--- /dev/null
+++ b/net/filter-buffer.c
@@ -0,0 +1,169 @@
+/*
+ * 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 "qemu-common.h"
+#include "qemu/timer.h"
+#include "qemu/iov.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi-visit.h"
+#include "qom/object.h"
+
+#define TYPE_FILTER_BUFFER "filter-buffer"
+
+#define FILTER_BUFFER(obj) \
+ OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
+
+typedef struct FilterBufferState {
+ NetFilterState parent_obj;
+
+ NetQueue *incoming_queue;
+ uint32_t interval;
+ QEMUTimer release_timer;
+} FilterBufferState;
+
+static void filter_buffer_flush(NetFilterState *nf)
+{
+ FilterBufferState *s = FILTER_BUFFER(nf);
+
+ if (!qemu_net_queue_flush(s->incoming_queue)) {
+ /* Unable to empty the queue, purge remaining packets */
+ qemu_net_queue_purge(s->incoming_queue, nf->netdev);
+ }
+}
+
+static void filter_buffer_release_timer(void *opaque)
+{
+ NetFilterState *nf = opaque;
+ FilterBufferState *s = FILTER_BUFFER(nf);
+ filter_buffer_flush(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,
+ NetPacketSent *sent_cb)
+{
+ FilterBufferState *s = FILTER_BUFFER(nf);
+
+ /*
+ * we return size when buffer a packet, the sender will take it as
+ * a already sent packet, so sent_cb should not be called later
+ */
+ qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
+ iov, iovcnt, NULL);
+ return iov_size(iov, iovcnt);
+}
+
+static void filter_buffer_cleanup(NetFilterState *nf)
+{
+ FilterBufferState *s = FILTER_BUFFER(nf);
+
+ if (s->interval) {
+ timer_del(&s->release_timer);
+ }
+
+ /* flush packets */
+ if (s->incoming_queue) {
+ filter_buffer_flush(nf);
+ g_free(s->incoming_queue);
+ }
+}
+
+static void filter_buffer_setup(NetFilterState *nf, Error **errp)
+{
+ FilterBufferState *s = FILTER_BUFFER(nf);
+
+ /*
+ * this check should be dropped when there're VM FT solutions like MC
+ * or COLO use this filter to release packets on demand.
+ */
+ if (!s->interval) {
+ error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "interval",
+ "a non-zero interval");
+ return;
+ }
+
+ s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
+ if (s->interval) {
+ timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
+ filter_buffer_release_timer, nf);
+ timer_mod(&s->release_timer,
+ qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+ snprintf(nf->info_str, sizeof(nf->info_str),
+ "interval=%d", s->interval);
+ }
+}
+
+static void filter_buffer_class_init(ObjectClass *oc, void *data)
+{
+ NetFilterClass *nfc = NETFILTER_CLASS(oc);
+
+ nfc->setup = filter_buffer_setup;
+ nfc->cleanup = filter_buffer_cleanup;
+ nfc->receive_iov = filter_buffer_receive_iov;
+}
+
+static void filter_buffer_get_interval(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ FilterBufferState *s = FILTER_BUFFER(obj);
+ uint32_t value = s->interval;
+
+ visit_type_uint32(v, &value, name, errp);
+}
+
+static void filter_buffer_set_interval(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
+{
+ FilterBufferState *s = FILTER_BUFFER(obj);
+ Error *local_err = NULL;
+ uint32_t value;
+
+ visit_type_uint32(v, &value, name, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ if (!value) {
+ error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
+ PRIu32 "'", object_get_typename(obj), name, value);
+ goto out;
+ }
+ s->interval = value;
+
+out:
+ error_propagate(errp, local_err);
+}
+
+static void filter_buffer_init(Object *obj)
+{
+ object_property_add(obj, "interval", "int",
+ filter_buffer_get_interval,
+ filter_buffer_set_interval, NULL, NULL, NULL);
+}
+
+static const TypeInfo filter_buffer_info = {
+ .name = TYPE_FILTER_BUFFER,
+ .parent = TYPE_NETFILTER,
+ .class_init = filter_buffer_class_init,
+ .instance_init = filter_buffer_init,
+ .instance_size = sizeof(FilterBufferState),
+};
+
+static void register_types(void)
+{
+ type_register_static(&filter_buffer_info);
+}
+
+type_init(register_types);
diff --git a/qemu-options.hx b/qemu-options.hx
index efce775..1dc2680 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3568,6 +3568,24 @@ the @option{virtio-rng} device. The @option{chardev} parameter is
the unique ID of a character device backend that provides the connection
to the RNG daemon.
+@item -object filter-buffer,id=@var{id},netdev=@var{netdevid}[,chain=@var{all|in|out}][,interval=@var{t}]
+
+Buffer network packets on netdev @var{netdevid}.
+If interval @var{t} provided, will release packets by interval.
+Interval scale: microsecond.
+
+If interval @var{t} not provided, you have to make sure the packets can be
+released, either by manually remove this filter or call the release buffer API,
+otherwise, the packets will be buffered forever. Use with caution.
+
+chain @var{all|in|out} is an option that can be applied to any netfilter, default is @option{all}.
+
+@option{all} means this filter will receive packets both sent to/from the netdev
+
+@option{in} means this filter will receive packets sent to the netdev
+
+@option{out} means this filter will receive packets sent from the netdev
+
@end table
ETEXI
diff --git a/vl.c b/vl.c
index 672f8b2..30196e4 100644
--- a/vl.c
+++ b/vl.c
@@ -2783,7 +2783,12 @@ static bool object_create_initial(const char *type)
if (g_str_equal(type, "rng-egd")) {
return false;
}
- /* TODO: reture false for concrete netfilters */
+
+ /* reture false for concrete netfilters */
+ if (g_str_equal(type, "filter-buffer")) {
+ return false;
+ }
+
return true;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [Qemu-devel] [PATCH v10 10/10] tests: add test cases for netfilter object
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (8 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-09-09 7:24 ` Yang Hongyang
2015-09-14 5:09 ` [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
10 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-09 7:24 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, 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>
---
v10: qmp command based on qom change
v9: qmp command change due to the qapi change
---
tests/.gitignore | 1 +
tests/Makefile | 2 +
tests/test-netfilter.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 203 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 34c6136..85015f2 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))
@@ -416,6 +417,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..e114545
--- /dev/null
+++ b/tests/test-netfilter.c
@@ -0,0 +1,200 @@
+/*
+ * 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': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'chain': 'in',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-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': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " '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': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'chain': 'in',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f1',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'chain': 'in',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-del',"
+ " 'arguments': {"
+ " 'id': 'qtest-f0'"
+ "}}");
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-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': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f0',"
+ " 'props': {"
+ " 'netdev': 'qtest-bn0',"
+ " 'chain': 'in',"
+ " 'interval': 1000"
+ "}}}");
+
+ g_assert(response);
+ g_assert(!qdict_haskey(response, "error"));
+ QDECREF(response);
+
+ response = qmp("{'execute': 'object-add',"
+ " 'arguments': {"
+ " 'qom-type': 'filter-buffer',"
+ " 'id': 'qtest-f1',"
+ " 'props': {"
+ " '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] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (9 preceding siblings ...)
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 10/10] tests: add test cases for netfilter object Yang Hongyang
@ 2015-09-14 5:09 ` Yang Hongyang
2015-09-14 5:22 ` Jason Wang
2015-09-14 9:05 ` Daniel P. Berrange
10 siblings, 2 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-14 5:09 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha
Hi Stefan,Jason,
I've convert this series to base on QOM, and introducing NetQueue apis
instead of using Netqueue internals as Stefan suggested. Could you please take a
look at it?
Most of the details have been reviewed by Jason, and the whole filter logic
isn't changed.
One missing feature compared to previous versions is the multiqueue support,
however, I've already implemented it, before sending it out, I need to get as
many review comments as possible on this series, and addressing it, in order to
reduce the iter round...And multiqueue support can be sent later as a seperate
series if the base can go in first. If there has to be another few rounds, I
will include multiqueue patches.
Thanks in advance.
On 09/09/2015 03:24 PM, Yang Hongyang wrote:
> This patch add an netfilter abstract object, captures all network packets
> on associated netdev. Also implement a concrete filter buffer based on
> this abstract 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-v10
>
> Usage:
> -netdev tap,id=bn0
> -device e1000,netdev=bn0
> -object filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
>
> dynamically add/remove netfilters:
> object_add filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
> object_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
>
> v10:
> - Reimplemented using QOM (suggested by stefan)
> - Do not export NetQueue internals (suggested by stefan)
> - see individual patch for detail
>
> v9:
> - squash command description and help to patch 1&3
> - qapi changes according to Markus&Eric's comments
> - see individual patch for detail
>
> v8:
> - some minor fixes according to Thomas's comments
> - rebased to the latest master branch
>
> v7:
> - print filter info when execute 'info network'
> - addressed Jason's comments
>
> v6:
> - add multiqueue support, please see individual patch for detail
>
> v5:
> - add a sent_cb param to filter receive_iov api
> - squash the 4th patch into patch 3
> - remove dummy sent_cb (buffer filter)
> - addressed Jason's other comments, see individual patches for detail
>
> 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 (10):
> qmp: delete qemu opts when delete an object
> init/cleanup of netfilter object
> netfilter: hook packets before net queue send
> net: merge qemu_deliver_packet and qemu_deliver_packet_iov
> net/queue: introduce NetQueueDeliverFunc
> netfilter: add an API to pass the packet to next filter
> netfilter: print filter info associate with the netdev
> net/queue: export qemu_net_queue_append_iov
> netfilter: add a netbuffer filter
> tests: add test cases for netfilter object
>
> include/net/filter.h | 68 ++++++++++++++++
> include/net/net.h | 6 +-
> include/net/queue.h | 20 ++++-
> include/qemu/typedefs.h | 1 +
> net/Makefile.objs | 2 +
> net/filter-buffer.c | 169 ++++++++++++++++++++++++++++++++++++++
> net/filter.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++
> net/net.c | 116 ++++++++++++++++++++------
> net/queue.c | 24 ++++--
> qapi-schema.json | 18 ++++
> qemu-options.hx | 18 ++++
> qmp.c | 4 +
> tests/.gitignore | 1 +
> tests/Makefile | 2 +
> tests/test-netfilter.c | 200 +++++++++++++++++++++++++++++++++++++++++++++
> vl.c | 18 ++--
> 16 files changed, 833 insertions(+), 47 deletions(-)
> create mode 100644 include/net/filter.h
> create mode 100644 net/filter-buffer.c
> create mode 100644 net/filter.c
> create mode 100644 tests/test-netfilter.c
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-14 5:09 ` [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
@ 2015-09-14 5:22 ` Jason Wang
2015-09-14 5:36 ` Yang Hongyang
2015-09-14 9:05 ` Daniel P. Berrange
1 sibling, 1 reply; 28+ messages in thread
From: Jason Wang @ 2015-09-14 5:22 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, stefanha, zhang.zhanghailiang, lizhijian, armbru
On 09/14/2015 01:09 PM, Yang Hongyang wrote:
> Hi Stefan,Jason,
>
> I've convert this series to base on QOM, and introducing NetQueue apis
> instead of using Netqueue internals as Stefan suggested. Could you
> please take a
> look at it?
Will go through this in next few days.
> Most of the details have been reviewed by Jason, and the whole filter
> logic
> isn't changed.
> One missing feature compared to previous versions is the multiqueue
> support,
> however, I've already implemented it, before sending it out, I need to
> get as
> many review comments as possible on this series, and addressing it, in
> order to
> reduce the iter round...And multiqueue support can be sent later as a
> seperate
> series if the base can go in first. If there has to be another few
> rounds, I
> will include multiqueue patches.
Sounds good. There's one more thing which may be implemented. I'd expect
a unit test for buffer filter. (This could be done by a separate patch
on top).
Thanks
>
> Thanks in advance.
>
> On 09/09/2015 03:24 PM, Yang Hongyang wrote:
>> This patch add an netfilter abstract object, captures all network
>> packets
>> on associated netdev. Also implement a concrete filter buffer based on
>> this abstract 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-v10
>>
>> Usage:
>> -netdev tap,id=bn0
>> -device e1000,netdev=bn0
>> -object filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>
>> dynamically add/remove netfilters:
>> object_add filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
>> object_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
>>
>> v10:
>> - Reimplemented using QOM (suggested by stefan)
>> - Do not export NetQueue internals (suggested by stefan)
>> - see individual patch for detail
>>
>> v9:
>> - squash command description and help to patch 1&3
>> - qapi changes according to Markus&Eric's comments
>> - see individual patch for detail
>>
>> v8:
>> - some minor fixes according to Thomas's comments
>> - rebased to the latest master branch
>>
>> v7:
>> - print filter info when execute 'info network'
>> - addressed Jason's comments
>>
>> v6:
>> - add multiqueue support, please see individual patch for detail
>>
>> v5:
>> - add a sent_cb param to filter receive_iov api
>> - squash the 4th patch into patch 3
>> - remove dummy sent_cb (buffer filter)
>> - addressed Jason's other comments, see individual patches for detail
>>
>> 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 (10):
>> qmp: delete qemu opts when delete an object
>> init/cleanup of netfilter object
>> netfilter: hook packets before net queue send
>> net: merge qemu_deliver_packet and qemu_deliver_packet_iov
>> net/queue: introduce NetQueueDeliverFunc
>> netfilter: add an API to pass the packet to next filter
>> netfilter: print filter info associate with the netdev
>> net/queue: export qemu_net_queue_append_iov
>> netfilter: add a netbuffer filter
>> tests: add test cases for netfilter object
>>
>> include/net/filter.h | 68 ++++++++++++++++
>> include/net/net.h | 6 +-
>> include/net/queue.h | 20 ++++-
>> include/qemu/typedefs.h | 1 +
>> net/Makefile.objs | 2 +
>> net/filter-buffer.c | 169 ++++++++++++++++++++++++++++++++++++++
>> net/filter.c | 213
>> ++++++++++++++++++++++++++++++++++++++++++++++++
>> net/net.c | 116 ++++++++++++++++++++------
>> net/queue.c | 24 ++++--
>> qapi-schema.json | 18 ++++
>> qemu-options.hx | 18 ++++
>> qmp.c | 4 +
>> tests/.gitignore | 1 +
>> tests/Makefile | 2 +
>> tests/test-netfilter.c | 200
>> +++++++++++++++++++++++++++++++++++++++++++++
>> vl.c | 18 ++--
>> 16 files changed, 833 insertions(+), 47 deletions(-)
>> create mode 100644 include/net/filter.h
>> create mode 100644 net/filter-buffer.c
>> create mode 100644 net/filter.c
>> create mode 100644 tests/test-netfilter.c
>>
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-14 5:22 ` Jason Wang
@ 2015-09-14 5:36 ` Yang Hongyang
2015-09-16 9:48 ` Jason Wang
0 siblings, 1 reply; 28+ messages in thread
From: Yang Hongyang @ 2015-09-14 5:36 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, stefanha, zhang.zhanghailiang, lizhijian, armbru
On 09/14/2015 01:22 PM, Jason Wang wrote:
>
>
> On 09/14/2015 01:09 PM, Yang Hongyang wrote:
>> Hi Stefan,Jason,
>>
>> I've convert this series to base on QOM, and introducing NetQueue apis
>> instead of using Netqueue internals as Stefan suggested. Could you
>> please take a
>> look at it?
>
> Will go through this in next few days.
Thanks a lot.
>
>> Most of the details have been reviewed by Jason, and the whole filter
>> logic
>> isn't changed.
>> One missing feature compared to previous versions is the multiqueue
>> support,
>> however, I've already implemented it, before sending it out, I need to
>> get as
>> many review comments as possible on this series, and addressing it, in
>> order to
>> reduce the iter round...And multiqueue support can be sent later as a
>> seperate
>> series if the base can go in first. If there has to be another few
>> rounds, I
>> will include multiqueue patches.
>
> Sounds good. There's one more thing which may be implemented. I'd expect
> a unit test for buffer filter. (This could be done by a separate patch
> on top).
The 10th patch "tests: add test cases for netfilter object" might contains
basic tests on buffer filter using qmp, the netfilter object is an abstract
object, so in order to test it, we must use a concrete filter as the buffer
filter.
>
> Thanks
>
>>
>> Thanks in advance.
>>
>> On 09/09/2015 03:24 PM, Yang Hongyang wrote:
>>> This patch add an netfilter abstract object, captures all network
>>> packets
>>> on associated netdev. Also implement a concrete filter buffer based on
>>> this abstract 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-v10
>>>
>>> Usage:
>>> -netdev tap,id=bn0
>>> -device e1000,netdev=bn0
>>> -object filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>>
>>> dynamically add/remove netfilters:
>>> object_add filter-buffer,id=f0,netdev=bn0,chain=in,interval=1000
>>> object_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
>>>
>>> v10:
>>> - Reimplemented using QOM (suggested by stefan)
>>> - Do not export NetQueue internals (suggested by stefan)
>>> - see individual patch for detail
>>>
>>> v9:
>>> - squash command description and help to patch 1&3
>>> - qapi changes according to Markus&Eric's comments
>>> - see individual patch for detail
>>>
>>> v8:
>>> - some minor fixes according to Thomas's comments
>>> - rebased to the latest master branch
>>>
>>> v7:
>>> - print filter info when execute 'info network'
>>> - addressed Jason's comments
>>>
>>> v6:
>>> - add multiqueue support, please see individual patch for detail
>>>
>>> v5:
>>> - add a sent_cb param to filter receive_iov api
>>> - squash the 4th patch into patch 3
>>> - remove dummy sent_cb (buffer filter)
>>> - addressed Jason's other comments, see individual patches for detail
>>>
>>> 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 (10):
>>> qmp: delete qemu opts when delete an object
>>> init/cleanup of netfilter object
>>> netfilter: hook packets before net queue send
>>> net: merge qemu_deliver_packet and qemu_deliver_packet_iov
>>> net/queue: introduce NetQueueDeliverFunc
>>> netfilter: add an API to pass the packet to next filter
>>> netfilter: print filter info associate with the netdev
>>> net/queue: export qemu_net_queue_append_iov
>>> netfilter: add a netbuffer filter
>>> tests: add test cases for netfilter object
>>>
>>> include/net/filter.h | 68 ++++++++++++++++
>>> include/net/net.h | 6 +-
>>> include/net/queue.h | 20 ++++-
>>> include/qemu/typedefs.h | 1 +
>>> net/Makefile.objs | 2 +
>>> net/filter-buffer.c | 169 ++++++++++++++++++++++++++++++++++++++
>>> net/filter.c | 213
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>> net/net.c | 116 ++++++++++++++++++++------
>>> net/queue.c | 24 ++++--
>>> qapi-schema.json | 18 ++++
>>> qemu-options.hx | 18 ++++
>>> qmp.c | 4 +
>>> tests/.gitignore | 1 +
>>> tests/Makefile | 2 +
>>> tests/test-netfilter.c | 200
>>> +++++++++++++++++++++++++++++++++++++++++++++
>>> vl.c | 18 ++--
>>> 16 files changed, 833 insertions(+), 47 deletions(-)
>>> create mode 100644 include/net/filter.h
>>> create mode 100644 net/filter-buffer.c
>>> create mode 100644 net/filter.c
>>> create mode 100644 tests/test-netfilter.c
>>>
>>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object Yang Hongyang
@ 2015-09-14 8:54 ` Daniel P. Berrange
2015-09-14 8:56 ` Daniel P. Berrange
2015-09-14 9:05 ` Yang Hongyang
2015-09-16 9:28 ` Jason Wang
1 sibling, 2 replies; 28+ messages in thread
From: Daniel P. Berrange @ 2015-09-14 8:54 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
armbru, stefanha
On Wed, Sep 09, 2015 at 03:24:33PM +0800, Yang Hongyang wrote:
> Add a netfilter object based on QOM.
>
> A netfilter is attached to a netdev, captures all network packets
> that pass through the netdev. When we delete the netdev, we also
> delete the netfilter object attached to it, because if the netdev is
> removed, the filter which attached to it is useless.
>
> 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.
>
> Also init delayed object after net_init_clients, because netfilters need
> to be initialized after net clients initialized.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> diff --git a/net/filter.c b/net/filter.c
> new file mode 100644
> index 0000000..5192c6d
> --- /dev/null
> +++ b/net/filter.c
> +static void netfilter_init(Object *obj)
> +{
> + QTAILQ_INIT(&net_filters);
> + object_property_add_str(obj, "netdev",
> + netfilter_get_netdev_id, netfilter_set_netdev_id,
> + NULL);
> + object_property_add_enum(obj, "chain", "NetFilterChain",
> + NetFilterChain_lookup,
> + netfilter_get_chain, netfilter_set_chain,
> + NULL);
> +}
> +
> +static void netfilter_cleanup(Object *obj)
Nit-pick, it is preferable to name methods to match the class callback
they're registered against, so if you have to re-spin a v11 plesae
rename this to netfilter_finalize.
> +{
> + NetFilterState *nf = NETFILTER(obj);
> + NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
> +
> + if (nfc->cleanup) {
> + nfc->cleanup(nf);
> + }
> +
> + if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
> + QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
> + }
> + if (!QTAILQ_EMPTY(&net_filters)) {
> + QTAILQ_REMOVE(&net_filters, nf, global_list);
> + }
> +
> + g_free(nf->netdev_id);
> +}
> +
> +static void netfilter_complete(UserCreatable *uc, Error **errp)
> +{
> + NetFilterState *nf = NETFILTER(uc);
> + NetClientState *ncs[MAX_QUEUE_NUM];
> + NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
> + int queues;
> + Error *local_err = NULL;
> +
> + if (!nf->netdev_id) {
> + error_setg(errp, "Parameter 'netdev' is required");
> + return;
> + }
> +
> + queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
> + NET_CLIENT_OPTIONS_KIND_NIC,
> + MAX_QUEUE_NUM);
> + if (queues < 1) {
> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
> + "a network backend id");
> + return;
> + } else if (queues > 1) {
> + error_setg(errp, "Multi queue is not supported");
> + return;
> + }
> +
> + if (get_vhost_net(ncs[0])) {
> + error_setg(errp, "Vhost is not supported");
> + return;
> + }
> +
> + nf->netdev = ncs[0];
> +
> + if (nfc->setup) {
> + nfc->setup(nf, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + }
> + QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
> + QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
> +}
> +
> +static bool netfilter_can_be_deleted(UserCreatable *uc, Error **errp)
> +{
> + return true;
> +}
You can just leave out the netfilter_can_be_deleted() method if you are
only going to return "true", since that's the default semantics.
> +static void netfilter_class_init(ObjectClass *oc, void *data)
> +{
> + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
> +
> + ucc->complete = netfilter_complete;
> + ucc->can_be_deleted = netfilter_can_be_deleted;
> +}
> +
> +static const TypeInfo netfilter_info = {
> + .name = TYPE_NETFILTER,
> + .parent = TYPE_OBJECT,
> + .abstract = true,
> + .class_size = sizeof(NetFilterClass),
> + .class_init = netfilter_class_init,
> + .instance_size = sizeof(NetFilterState),
> + .instance_init = netfilter_init,
> + .instance_finalize = netfilter_cleanup,
> + .interfaces = (InterfaceInfo[]) {
> + { TYPE_USER_CREATABLE },
> + { }
> + }
> +};
> +
> +static void register_types(void)
> +{
> + type_register_static(&netfilter_info);
> +}
> +
> +type_init(register_types);
> diff --git a/vl.c b/vl.c
> index 584ca88..672f8b2 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
> if (g_str_equal(type, "rng-egd")) {
> return false;
> }
> + /* TODO: reture false for concrete netfilters */
> return true;
> }
Don't you want to be adding your object type here, alongside rng-egd
since IIRC, you said it needed to be created later
> @@ -4302,12 +4303,6 @@ int main(int argc, char **argv, char **envp)
> exit(0);
> }
>
> - if (qemu_opts_foreach(qemu_find_opts("object"),
> - object_create,
> - object_create_delayed, NULL)) {
> - exit(1);
> - }
> -
> machine_opts = qemu_get_machine_opts();
> if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
> NULL)) {
> @@ -4413,6 +4408,12 @@ int main(int argc, char **argv, char **envp)
> exit(1);
> }
>
> + if (qemu_opts_foreach(qemu_find_opts("object"),
> + object_create,
> + object_create_delayed, NULL)) {
> + exit(1);
> + }
> +
> #ifdef CONFIG_TPM
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-14 8:54 ` Daniel P. Berrange
@ 2015-09-14 8:56 ` Daniel P. Berrange
2015-09-14 9:05 ` Yang Hongyang
1 sibling, 0 replies; 28+ messages in thread
From: Daniel P. Berrange @ 2015-09-14 8:56 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru,
qemu-devel, stefanha
On Mon, Sep 14, 2015 at 09:54:42AM +0100, Daniel P. Berrange wrote:
> On Wed, Sep 09, 2015 at 03:24:33PM +0800, Yang Hongyang wrote:
> > Add a netfilter object based on QOM.
> >
> > A netfilter is attached to a netdev, captures all network packets
> > that pass through the netdev. When we delete the netdev, we also
> > delete the netfilter object attached to it, because if the netdev is
> > removed, the filter which attached to it is useless.
> >
> > 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.
> >
> > Also init delayed object after net_init_clients, because netfilters need
> > to be initialized after net clients initialized.
> >
> > Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> > diff --git a/vl.c b/vl.c
> > index 584ca88..672f8b2 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
> > if (g_str_equal(type, "rng-egd")) {
> > return false;
> > }
> > + /* TODO: reture false for concrete netfilters */
> > return true;
> > }
>
> Don't you want to be adding your object type here, alongside rng-egd
> since IIRC, you said it needed to be created later
Oh ignore this comment, I forgot this particular object is just an
abstract base
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-09-14 9:04 ` Daniel P. Berrange
2015-09-14 9:53 ` Yang Hongyang
2015-09-16 9:42 ` Jason Wang
1 sibling, 1 reply; 28+ messages in thread
From: Daniel P. Berrange @ 2015-09-14 9:04 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
armbru, stefanha
On Wed, Sep 09, 2015 at 03:24:40PM +0800, 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
> -object filter-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>
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> new file mode 100644
> index 0000000..26698d9
> --- /dev/null
> +++ b/net/filter-buffer.c
> @@ -0,0 +1,169 @@
> +/*
> + * 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 "qemu-common.h"
> +#include "qemu/timer.h"
> +#include "qemu/iov.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qapi-visit.h"
> +#include "qom/object.h"
> +
> +#define TYPE_FILTER_BUFFER "filter-buffer"
> +
> +#define FILTER_BUFFER(obj) \
> + OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
> +
> +typedef struct FilterBufferState {
> + NetFilterState parent_obj;
> +
> + NetQueue *incoming_queue;
> + uint32_t interval;
> + QEMUTimer release_timer;
> +} FilterBufferState;
> +
> +static void filter_buffer_flush(NetFilterState *nf)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + if (!qemu_net_queue_flush(s->incoming_queue)) {
> + /* Unable to empty the queue, purge remaining packets */
> + qemu_net_queue_purge(s->incoming_queue, nf->netdev);
> + }
> +}
> +
> +static void filter_buffer_release_timer(void *opaque)
> +{
> + NetFilterState *nf = opaque;
> + FilterBufferState *s = FILTER_BUFFER(nf);
> + filter_buffer_flush(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,
> + NetPacketSent *sent_cb)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + /*
> + * we return size when buffer a packet, the sender will take it as
> + * a already sent packet, so sent_cb should not be called later
> + */
> + qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
> + iov, iovcnt, NULL);
> + return iov_size(iov, iovcnt);
> +}
> +
> +static void filter_buffer_cleanup(NetFilterState *nf)
Same comment about s/cleanup/finalize/
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + if (s->interval) {
> + timer_del(&s->release_timer);
> + }
> +
> + /* flush packets */
> + if (s->incoming_queue) {
> + filter_buffer_flush(nf);
> + g_free(s->incoming_queue);
> + }
> +}
> diff --git a/vl.c b/vl.c
> index 672f8b2..30196e4 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2783,7 +2783,12 @@ static bool object_create_initial(const char *type)
> if (g_str_equal(type, "rng-egd")) {
> return false;
> }
> - /* TODO: reture false for concrete netfilters */
Oh, I missed the typo in your earlier patch - s/reture/return/
> +
> + /* reture false for concrete netfilters */
And again in the line you changed here.
> + if (g_str_equal(type, "filter-buffer")) {
> + return false;
> + }
> +
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-14 5:09 ` [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-09-14 5:22 ` Jason Wang
@ 2015-09-14 9:05 ` Daniel P. Berrange
2015-09-14 9:14 ` Yang Hongyang
1 sibling, 1 reply; 28+ messages in thread
From: Daniel P. Berrange @ 2015-09-14 9:05 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
armbru, stefanha
On Mon, Sep 14, 2015 at 01:09:25PM +0800, Yang Hongyang wrote:
> Hi Stefan,Jason,
>
> I've convert this series to base on QOM, and introducing NetQueue apis
> instead of using Netqueue internals as Stefan suggested. Could you please take a
> look at it?
I won't look at the actual net filtering stuff since that's not my area
of expertize. I looked at the QOM related patches and that stuff all looks
good to me, with a few small nitpicks.
> Most of the details have been reviewed by Jason, and the whole filter logic
> isn't changed.
> One missing feature compared to previous versions is the multiqueue support,
> however, I've already implemented it, before sending it out, I need to get as
> many review comments as possible on this series, and addressing it, in order to
> reduce the iter round...And multiqueue support can be sent later as a seperate
> series if the base can go in first. If there has to be another few rounds, I
> will include multiqueue patches.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-14 8:54 ` Daniel P. Berrange
2015-09-14 8:56 ` Daniel P. Berrange
@ 2015-09-14 9:05 ` Yang Hongyang
1 sibling, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-14 9:05 UTC (permalink / raw)
To: Daniel P. Berrange
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
armbru, stefanha
On 09/14/2015 04:54 PM, Daniel P. Berrange wrote:
> On Wed, Sep 09, 2015 at 03:24:33PM +0800, Yang Hongyang wrote:
>> Add a netfilter object based on QOM.
>>
>> A netfilter is attached to a netdev, captures all network packets
>> that pass through the netdev. When we delete the netdev, we also
>> delete the netfilter object attached to it, because if the netdev is
>> removed, the filter which attached to it is useless.
>>
>> 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.
>>
>> Also init delayed object after net_init_clients, because netfilters need
>> to be initialized after net clients initialized.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>
>> diff --git a/net/filter.c b/net/filter.c
>> new file mode 100644
>> index 0000000..5192c6d
>> --- /dev/null
>> +++ b/net/filter.c
>
>> +static void netfilter_init(Object *obj)
>> +{
>> + QTAILQ_INIT(&net_filters);
>> + object_property_add_str(obj, "netdev",
>> + netfilter_get_netdev_id, netfilter_set_netdev_id,
>> + NULL);
>> + object_property_add_enum(obj, "chain", "NetFilterChain",
>> + NetFilterChain_lookup,
>> + netfilter_get_chain, netfilter_set_chain,
>> + NULL);
>> +}
>> +
>> +static void netfilter_cleanup(Object *obj)
>
> Nit-pick, it is preferable to name methods to match the class callback
> they're registered against, so if you have to re-spin a v11 plesae
> rename this to netfilter_finalize.
Sure, thanks!
>
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> + NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
>> +
>> + if (nfc->cleanup) {
>> + nfc->cleanup(nf);
>> + }
>> +
>> + if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
>> + QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
>> + }
>> + if (!QTAILQ_EMPTY(&net_filters)) {
>> + QTAILQ_REMOVE(&net_filters, nf, global_list);
>> + }
>> +
>> + g_free(nf->netdev_id);
>> +}
>> +
>> +static void netfilter_complete(UserCreatable *uc, Error **errp)
>> +{
>> + NetFilterState *nf = NETFILTER(uc);
>> + NetClientState *ncs[MAX_QUEUE_NUM];
>> + NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
>> + int queues;
>> + Error *local_err = NULL;
>> +
>> + if (!nf->netdev_id) {
>> + error_setg(errp, "Parameter 'netdev' is required");
>> + return;
>> + }
>> +
>> + queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
>> + NET_CLIENT_OPTIONS_KIND_NIC,
>> + MAX_QUEUE_NUM);
>> + if (queues < 1) {
>> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
>> + "a network backend id");
>> + return;
>> + } else if (queues > 1) {
>> + error_setg(errp, "Multi queue is not supported");
>> + return;
>> + }
>> +
>> + if (get_vhost_net(ncs[0])) {
>> + error_setg(errp, "Vhost is not supported");
>> + return;
>> + }
>> +
>> + nf->netdev = ncs[0];
>> +
>> + if (nfc->setup) {
>> + nfc->setup(nf, &local_err);
>> + if (local_err) {
>> + error_propagate(errp, local_err);
>> + return;
>> + }
>> + }
>> + QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
>> + QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
>> +}
>> +
>> +static bool netfilter_can_be_deleted(UserCreatable *uc, Error **errp)
>> +{
>> + return true;
>> +}
>
> You can just leave out the netfilter_can_be_deleted() method if you are
> only going to return "true", since that's the default semantics.
Ok, thanks.
>
>
>> +static void netfilter_class_init(ObjectClass *oc, void *data)
>> +{
>> + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
>> +
>> + ucc->complete = netfilter_complete;
>> + ucc->can_be_deleted = netfilter_can_be_deleted;
>> +}
>> +
>> +static const TypeInfo netfilter_info = {
>> + .name = TYPE_NETFILTER,
>> + .parent = TYPE_OBJECT,
>> + .abstract = true,
>> + .class_size = sizeof(NetFilterClass),
>> + .class_init = netfilter_class_init,
>> + .instance_size = sizeof(NetFilterState),
>> + .instance_init = netfilter_init,
>> + .instance_finalize = netfilter_cleanup,
>> + .interfaces = (InterfaceInfo[]) {
>> + { TYPE_USER_CREATABLE },
>> + { }
>> + }
>> +};
>> +
>> +static void register_types(void)
>> +{
>> + type_register_static(&netfilter_info);
>> +}
>> +
>> +type_init(register_types);
>> diff --git a/vl.c b/vl.c
>> index 584ca88..672f8b2 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
>> if (g_str_equal(type, "rng-egd")) {
>> return false;
>> }
>> + /* TODO: reture false for concrete netfilters */
>> return true;
>> }
>
> Don't you want to be adding your object type here, alongside rng-egd
> since IIRC, you said it needed to be created later
Yes, when there's concrete filters, we need to add them here. that's
why I leave a TODO here.
Thank you for the review!
>
>> @@ -4302,12 +4303,6 @@ int main(int argc, char **argv, char **envp)
>> exit(0);
>> }
>>
>> - if (qemu_opts_foreach(qemu_find_opts("object"),
>> - object_create,
>> - object_create_delayed, NULL)) {
>> - exit(1);
>> - }
>> -
>> machine_opts = qemu_get_machine_opts();
>> if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
>> NULL)) {
>> @@ -4413,6 +4408,12 @@ int main(int argc, char **argv, char **envp)
>> exit(1);
>> }
>>
>> + if (qemu_opts_foreach(qemu_find_opts("object"),
>> + object_create,
>> + object_create_delayed, NULL)) {
>> + exit(1);
>> + }
>> +
>> #ifdef CONFIG_TPM
>
> Regards,
> Daniel
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-14 9:05 ` Daniel P. Berrange
@ 2015-09-14 9:14 ` Yang Hongyang
0 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-14 9:14 UTC (permalink / raw)
To: Daniel P. Berrange
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
armbru, stefanha
On 09/14/2015 05:05 PM, Daniel P. Berrange wrote:
> On Mon, Sep 14, 2015 at 01:09:25PM +0800, Yang Hongyang wrote:
>> Hi Stefan,Jason,
>>
>> I've convert this series to base on QOM, and introducing NetQueue apis
>> instead of using Netqueue internals as Stefan suggested. Could you please take a
>> look at it?
>
> I won't look at the actual net filtering stuff since that's not my area
> of expertize. I looked at the QOM related patches and that stuff all looks
> good to me, with a few small nitpicks.
Tanks!
>
>> Most of the details have been reviewed by Jason, and the whole filter logic
>> isn't changed.
>> One missing feature compared to previous versions is the multiqueue support,
>> however, I've already implemented it, before sending it out, I need to get as
>> many review comments as possible on this series, and addressing it, in order to
>> reduce the iter round...And multiqueue support can be sent later as a seperate
>> series if the base can go in first. If there has to be another few rounds, I
>> will include multiqueue patches.
>
>
> Regards,
> Daniel
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter
2015-09-14 9:04 ` Daniel P. Berrange
@ 2015-09-14 9:53 ` Yang Hongyang
0 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-14 9:53 UTC (permalink / raw)
To: qemu-devel
On 09/14/2015 05:04 PM, Daniel P. Berrange wrote:
> On Wed, Sep 09, 2015 at 03:24:40PM +0800, 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
>> -object filter-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>
>
>> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
>> new file mode 100644
>> index 0000000..26698d9
>> --- /dev/null
>> +++ b/net/filter-buffer.c
>> @@ -0,0 +1,169 @@
>> +/*
>> + * 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 "qemu-common.h"
>> +#include "qemu/timer.h"
>> +#include "qemu/iov.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qapi-visit.h"
>> +#include "qom/object.h"
>> +
>> +#define TYPE_FILTER_BUFFER "filter-buffer"
>> +
>> +#define FILTER_BUFFER(obj) \
>> + OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
>> +
>> +typedef struct FilterBufferState {
>> + NetFilterState parent_obj;
>> +
>> + NetQueue *incoming_queue;
>> + uint32_t interval;
>> + QEMUTimer release_timer;
>> +} FilterBufferState;
>> +
>> +static void filter_buffer_flush(NetFilterState *nf)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + if (!qemu_net_queue_flush(s->incoming_queue)) {
>> + /* Unable to empty the queue, purge remaining packets */
>> + qemu_net_queue_purge(s->incoming_queue, nf->netdev);
>> + }
>> +}
>> +
>> +static void filter_buffer_release_timer(void *opaque)
>> +{
>> + NetFilterState *nf = opaque;
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> + filter_buffer_flush(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,
>> + NetPacketSent *sent_cb)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + /*
>> + * we return size when buffer a packet, the sender will take it as
>> + * a already sent packet, so sent_cb should not be called later
>> + */
>> + qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
>> + iov, iovcnt, NULL);
>> + return iov_size(iov, iovcnt);
>> +}
>> +
>> +static void filter_buffer_cleanup(NetFilterState *nf)
>
> Same comment about s/cleanup/finalize/
This is not the .instance_finalize func, although it is called
in netfilter_finalize, it is a cleanup virtual method in the
filter class:
include/net/filter.h
39 typedef struct NetFilterClass {
40 ObjectClass parent_class;
41
42 FilterSetup *setup;
43 FilterCleanup *cleanup;
44 FilterReceiveIOV *receive_iov;
45 } NetFilterClass;
>
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + if (s->interval) {
>> + timer_del(&s->release_timer);
>> + }
>> +
>> + /* flush packets */
>> + if (s->incoming_queue) {
>> + filter_buffer_flush(nf);
>> + g_free(s->incoming_queue);
>> + }
>> +}
>
>> diff --git a/vl.c b/vl.c
>> index 672f8b2..30196e4 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2783,7 +2783,12 @@ static bool object_create_initial(const char *type)
>> if (g_str_equal(type, "rng-egd")) {
>> return false;
>> }
>> - /* TODO: reture false for concrete netfilters */
>
> Oh, I missed the typo in your earlier patch - s/reture/return/
>
>> +
>> + /* reture false for concrete netfilters */
>
> And again in the line you changed here.
All fixed as well as your comments in patch 2, thank you.
>
>> + if (g_str_equal(type, "filter-buffer")) {
>> + return false;
>> + }
>> +
>
>
> Regards,
> Daniel
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object Yang Hongyang
2015-09-14 8:54 ` Daniel P. Berrange
@ 2015-09-16 9:28 ` Jason Wang
2015-09-16 11:11 ` Yang Hongyang
1 sibling, 1 reply; 28+ messages in thread
From: Jason Wang @ 2015-09-16 9:28 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, stefanha, zhang.zhanghailiang, lizhijian, armbru
On 09/09/2015 03:24 PM, Yang Hongyang wrote:
> Add a netfilter object based on QOM.
>
> A netfilter is attached to a netdev, captures all network packets
> that pass through the netdev. When we delete the netdev, we also
> delete the netfilter object attached to it, because if the netdev is
> removed, the filter which attached to it is useless.
>
> QTAILQ_ENTRY global_list but used by filter layer, so that we can
> manage all filters together.
This list is not used in this series. Maybe you could either remove it
or document its future usage.
> QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
> in this queue.
>
> Also init delayed object after net_init_clients, because netfilters need
> to be initialized after net clients initialized.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> ---
> v10: use QOM for netfilter
> v9: use flat union instead of simple union in QAPI schema
> v8: include vhost_net header
> v7: add check for vhost
> fix error propagate bug
> v6: add multiqueue support (net_filter_init1)
> v5: remove model from NetFilterState
> add a sent_cb param to receive_iov API
> ---
> include/net/filter.h | 60 +++++++++++++++++++
> include/net/net.h | 1 +
> include/qemu/typedefs.h | 1 +
> net/Makefile.objs | 1 +
> net/filter.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++
> net/net.c | 6 ++
> qapi-schema.json | 18 ++++++
> vl.c | 13 ++--
> 8 files changed, 247 insertions(+), 6 deletions(-)
> create mode 100644 include/net/filter.h
> create mode 100644 net/filter.c
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> new file mode 100644
> index 0000000..4557cb9
> --- /dev/null
> +++ b/include/net/filter.h
> @@ -0,0 +1,60 @@
> +/*
> + * 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.
> + */
> +
> +#ifndef QEMU_NET_FILTER_H
> +#define QEMU_NET_FILTER_H
> +
> +#include "qom/object.h"
> +#include "qemu-common.h"
> +#include "qemu/typedefs.h"
> +#include "net/queue.h"
> +
> +#define TYPE_NETFILTER "netfilter"
> +#define NETFILTER(obj) \
> + OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER)
> +#define NETFILTER_GET_CLASS(obj) \
> + OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER)
> +#define NETFILTER_CLASS(klass) \
> + OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
> +
> +typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
> +typedef void (FilterCleanup) (NetFilterState *nf);
> +/*
> + * 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 *nc,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt,
> + NetPacketSent *sent_cb);
> +
> +typedef struct NetFilterClass {
> + ObjectClass parent_class;
> +
> + FilterSetup *setup;
> + FilterCleanup *cleanup;
> + FilterReceiveIOV *receive_iov;
> +} NetFilterClass;
> +
> +
> +struct NetFilterState {
> + /* private */
> + Object parent;
> +
> + /* protected */
> + char *netdev_id;
> + NetClientState *netdev;
> + NetFilterChain chain;
> + QTAILQ_ENTRY(NetFilterState) global_list;
> + QTAILQ_ENTRY(NetFilterState) next;
> +};
> +
> +#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 f8a9dd6..2c0648f 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/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..5192c6d
> --- /dev/null
> +++ b/net/filter.c
> @@ -0,0 +1,153 @@
> +/*
> + * 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 "qemu-common.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qemu/error-report.h"
> +
> +#include "net/filter.h"
> +#include "net/net.h"
> +#include "net/vhost_net.h"
> +#include "qom/object_interfaces.h"
> +
> +static QTAILQ_HEAD(, NetFilterState) net_filters;
> +
> +static char *netfilter_get_netdev_id(Object *obj, Error **errp)
> +{
> + NetFilterState *nf = NETFILTER(obj);
> +
> + return g_strdup(nf->netdev_id);
> +}
> +
> +static void netfilter_set_netdev_id(Object *obj, const char *str, Error **errp)
> +{
> + NetFilterState *nf = NETFILTER(obj);
> +
> + nf->netdev_id = g_strdup(str);
> +}
> +
> +static int netfilter_get_chain(Object *obj, Error **errp G_GNUC_UNUSED)
> +{
> + NetFilterState *nf = NETFILTER(obj);
> + return nf->chain;
> +}
> +
> +static void netfilter_set_chain(Object *obj, int chain, Error **errp)
> +{
> + NetFilterState *nf = NETFILTER(obj);
> + nf->chain = chain;
> +}
> +
> +static void netfilter_init(Object *obj)
> +{
> + QTAILQ_INIT(&net_filters);
> + object_property_add_str(obj, "netdev",
> + netfilter_get_netdev_id, netfilter_set_netdev_id,
> + NULL);
> + object_property_add_enum(obj, "chain", "NetFilterChain",
> + NetFilterChain_lookup,
> + netfilter_get_chain, netfilter_set_chain,
> + NULL);
> +}
> +
> +static void netfilter_cleanup(Object *obj)
> +{
> + NetFilterState *nf = NETFILTER(obj);
> + NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
> +
> + if (nfc->cleanup) {
> + nfc->cleanup(nf);
> + }
> +
> + if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
> + QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
> + }
> + if (!QTAILQ_EMPTY(&net_filters)) {
> + QTAILQ_REMOVE(&net_filters, nf, global_list);
> + }
> +
> + g_free(nf->netdev_id);
> +}
> +
> +static void netfilter_complete(UserCreatable *uc, Error **errp)
> +{
> + NetFilterState *nf = NETFILTER(uc);
> + NetClientState *ncs[MAX_QUEUE_NUM];
> + NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
> + int queues;
> + Error *local_err = NULL;
> +
> + if (!nf->netdev_id) {
> + error_setg(errp, "Parameter 'netdev' is required");
> + return;
> + }
> +
> + queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
> + NET_CLIENT_OPTIONS_KIND_NIC,
> + MAX_QUEUE_NUM);
> + if (queues < 1) {
> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
> + "a network backend id");
> + return;
> + } else if (queues > 1) {
> + error_setg(errp, "Multi queue is not supported");
> + return;
> + }
> +
> + if (get_vhost_net(ncs[0])) {
> + error_setg(errp, "Vhost is not supported");
> + return;
> + }
> +
> + nf->netdev = ncs[0];
> +
> + if (nfc->setup) {
> + nfc->setup(nf, &local_err);
> + if (local_err) {
> + error_propagate(errp, local_err);
> + return;
> + }
> + }
> + QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
> + QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
> +}
> +
> +static bool netfilter_can_be_deleted(UserCreatable *uc, Error **errp)
> +{
> + return true;
> +}
> +
> +static void netfilter_class_init(ObjectClass *oc, void *data)
> +{
> + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
> +
> + ucc->complete = netfilter_complete;
> + ucc->can_be_deleted = netfilter_can_be_deleted;
> +}
> +
> +static const TypeInfo netfilter_info = {
> + .name = TYPE_NETFILTER,
> + .parent = TYPE_OBJECT,
> + .abstract = true,
> + .class_size = sizeof(NetFilterClass),
> + .class_init = netfilter_class_init,
> + .instance_size = sizeof(NetFilterState),
> + .instance_init = netfilter_init,
> + .instance_finalize = netfilter_cleanup,
> + .interfaces = (InterfaceInfo[]) {
> + { TYPE_USER_CREATABLE },
> + { }
> + }
> +};
> +
> +static void register_types(void)
> +{
> + type_register_static(&netfilter_info);
> +}
> +
> +type_init(register_types);
> diff --git a/net/net.c b/net/net.c
> index 28a5597..d6d4db8 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,
> @@ -384,6 +385,7 @@ void qemu_del_net_client(NetClientState *nc)
> {
> NetClientState *ncs[MAX_QUEUE_NUM];
> int queues, i;
> + NetFilterState *nf, *next;
>
> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>
> @@ -395,6 +397,10 @@ void qemu_del_net_client(NetClientState *nc)
> MAX_QUEUE_NUM);
> assert(queues != 0);
>
> + QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
> + object_unparent(OBJECT(nf));
> + }
> +
> /* 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);
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 67fef37..068e89e 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2551,6 +2551,24 @@
> 'opts': 'NetClientOptions' } }
>
> ##
> +# @NetFilterChain
> +#
> +# netfilter chain, a netfilter is attached to a netdev, captures the
> +# network packets of the netdev.
> +#
> +# @all: the filter will receive packets both sent to/from the netdev, this
> +# is the default chain.
> +#
> +# @in: the filter will receive packets sent to the netdev.
> +#
> +# @out: the filter will receive packets sent from the netdev.
> +#
> +# Since 2.5
> +##
> +{ 'enum': 'NetFilterChain',
> + 'data': [ 'all', 'in', 'out' ] }
> +
> +##
> # @InetSocketAddress
> #
> # Captures a socket address or address range in the Internet namespace.
> diff --git a/vl.c b/vl.c
> index 584ca88..672f8b2 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
> if (g_str_equal(type, "rng-egd")) {
> return false;
> }
> + /* TODO: reture false for concrete netfilters */
> return true;
> }
>
> @@ -4302,12 +4303,6 @@ int main(int argc, char **argv, char **envp)
> exit(0);
> }
>
> - if (qemu_opts_foreach(qemu_find_opts("object"),
> - object_create,
> - object_create_delayed, NULL)) {
> - exit(1);
> - }
> -
> machine_opts = qemu_get_machine_opts();
> if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
> NULL)) {
> @@ -4413,6 +4408,12 @@ int main(int argc, char **argv, char **envp)
> exit(1);
> }
>
> + if (qemu_opts_foreach(qemu_find_opts("object"),
> + object_create,
> + object_create_delayed, NULL)) {
> + exit(1);
> + }
> +
> #ifdef CONFIG_TPM
> if (tpm_init() < 0) {
> exit(1);
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
@ 2015-09-16 9:29 ` Jason Wang
0 siblings, 0 replies; 28+ messages in thread
From: Jason Wang @ 2015-09-16 9:29 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, lizhijian, armbru, stefanha, zhang.zhanghailiang
On 09/09/2015 03:24 PM, Yang Hongyang wrote:
> add an API qemu_netfilter_pass_to_next() to pass the packet
> to next filter.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> ---
> v10: adjust as a NetQueueDeliverFunc
> v9: fix a bug when curr filter chain is all
> v5: fold params to NetPacket struct
> ---
> include/net/filter.h | 7 ++++++
> net/filter.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 67 insertions(+)
>
> diff --git a/include/net/filter.h b/include/net/filter.h
> index 4557cb9..ed2bb66 100644
> --- a/include/net/filter.h
> +++ b/include/net/filter.h
> @@ -57,4 +57,11 @@ struct NetFilterState {
> QTAILQ_ENTRY(NetFilterState) next;
> };
>
> +/* pass the packet to the next filter */
> +ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt,
> + void *opaque);
> +
> #endif /* QEMU_NET_FILTER_H */
> diff --git a/net/filter.c b/net/filter.c
> index 5192c6d..086f271 100644
> --- a/net/filter.c
> +++ b/net/filter.c
> @@ -14,9 +14,69 @@
> #include "net/net.h"
> #include "net/vhost_net.h"
> #include "qom/object_interfaces.h"
> +#include "qemu/iov.h"
>
> static QTAILQ_HEAD(, NetFilterState) net_filters;
>
> +ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt,
> + void *opaque)
> +{
> + int ret = 0;
> + int chain;
> + NetFilterState *nf = opaque;
> + NetFilterState *next = QTAILQ_NEXT(nf, next);
> +
> + if (!sender || !sender->peer) {
> + /* no receiver, or sender been deleted, no need to pass it further */
> + goto out;
> + }
> +
> + if (nf->chain == NET_FILTER_CHAIN_ALL) {
> + if (sender == nf->netdev) {
> + /* This packet is sent by netdev itself */
> + chain = NET_FILTER_CHAIN_OUT;
> + } else {
> + chain = NET_FILTER_CHAIN_IN;
> + }
> + } else {
> + chain = nf->chain;
> + }
> +
> + while (next) {
> + if (next->chain == chain || next->chain == NET_FILTER_CHAIN_ALL) {
> + /*
> + * if qemu_netfilter_pass_to_next been called, means that
> + * the packet has been hold by filter and has already retured size
> + * to the sender, so sent_cb shouldn't be called later, just
> + * pass NULL to next.
> + */
> + ret = NETFILTER_GET_CLASS(OBJECT(next))->receive_iov(
> + next, sender, flags, iov, iovcnt, NULL);
> + if (ret) {
> + return ret;
> + }
> + }
> + next = QTAILQ_NEXT(next, next);
> + }
Nitpick:
Kind of codes duplication with filter_receive(). May consider to unify
them it you want to send next version.
> +
> + /*
> + * We have gone through all filters, pass it to receiver.
> + * Do the valid check again incase sender or receiver been
> + * deleted while we go through filters.
> + */
> + if (sender && sender->peer) {
> + return qemu_net_queue_send_iov(sender->peer->incoming_queue,
> + sender, flags, iov, iovcnt, NULL);
> + }
> +
> +out:
> + /* no receiver, or sender been deleted */
> + return iov_size(iov, iovcnt);
> +}
> +
> static char *netfilter_get_netdev_id(Object *obj, Error **errp)
> {
> NetFilterState *nf = NETFILTER(obj);
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter Yang Hongyang
2015-09-14 9:04 ` Daniel P. Berrange
@ 2015-09-16 9:42 ` Jason Wang
2015-09-16 11:19 ` Yang Hongyang
1 sibling, 1 reply; 28+ messages in thread
From: Jason Wang @ 2015-09-16 9:42 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: thuth, lizhijian, armbru, stefanha, zhang.zhanghailiang
On 09/09/2015 03:24 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
> -object filter-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>
> ---
> v10: use NetQueue flush api to flush packets
> sent_cb can not be called when we already return size
> v9: adjustment due to the qapi change
> v7: use QTAILQ_FOREACH_SAFE() when flush packets
> v6: move the interval check earlier and some comment adjust
> v5: remove dummy sent_cb
> change interval type from int64 to uint32
> check interval!=0 when initialise
> rename FILTERBUFFERState to FilterBufferState
> 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 | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> qemu-options.hx | 18 ++++++
> vl.c | 7 ++-
> 4 files changed, 194 insertions(+), 1 deletion(-)
> create mode 100644 net/filter-buffer.c
>
> diff --git a/net/Makefile.objs b/net/Makefile.objs
> index 914aec0..5fa2f97 100644
> --- a/net/Makefile.objs
> +++ b/net/Makefile.objs
> @@ -14,3 +14,4 @@ common-obj-$(CONFIG_SLIRP) += slirp.o
> common-obj-$(CONFIG_VDE) += vde.o
> common-obj-$(CONFIG_NETMAP) += netmap.o
> common-obj-y += filter.o
> +common-obj-y += filter-buffer.o
> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
> new file mode 100644
> index 0000000..26698d9
> --- /dev/null
> +++ b/net/filter-buffer.c
> @@ -0,0 +1,169 @@
> +/*
> + * 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 "qemu-common.h"
> +#include "qemu/timer.h"
> +#include "qemu/iov.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qapi-visit.h"
> +#include "qom/object.h"
> +
> +#define TYPE_FILTER_BUFFER "filter-buffer"
> +
> +#define FILTER_BUFFER(obj) \
> + OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
> +
> +typedef struct FilterBufferState {
> + NetFilterState parent_obj;
> +
> + NetQueue *incoming_queue;
> + uint32_t interval;
> + QEMUTimer release_timer;
> +} FilterBufferState;
> +
> +static void filter_buffer_flush(NetFilterState *nf)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + if (!qemu_net_queue_flush(s->incoming_queue)) {
> + /* Unable to empty the queue, purge remaining packets */
> + qemu_net_queue_purge(s->incoming_queue, nf->netdev);
> + }
> +}
> +
> +static void filter_buffer_release_timer(void *opaque)
> +{
> + NetFilterState *nf = opaque;
> + FilterBufferState *s = FILTER_BUFFER(nf);
> + filter_buffer_flush(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,
> + NetPacketSent *sent_cb)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + /*
> + * we return size when buffer a packet, the sender will take it as
> + * a already sent packet, so sent_cb should not be called later
> + */
> + qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
> + iov, iovcnt, NULL);
> + return iov_size(iov, iovcnt);
Then a small issue here is, even if guest can't receive packet for some
reasons. Filter can still accept packet until its internal queue is
full. May consider to solve this in the future.
> +}
> +
> +static void filter_buffer_cleanup(NetFilterState *nf)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + if (s->interval) {
> + timer_del(&s->release_timer);
> + }
> +
> + /* flush packets */
> + if (s->incoming_queue) {
> + filter_buffer_flush(nf);
> + g_free(s->incoming_queue);
> + }
> +}
> +
> +static void filter_buffer_setup(NetFilterState *nf, Error **errp)
> +{
> + FilterBufferState *s = FILTER_BUFFER(nf);
> +
> + /*
> + * this check should be dropped when there're VM FT solutions like MC
> + * or COLO use this filter to release packets on demand.
> + */
> + if (!s->interval) {
> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "interval",
> + "a non-zero interval");
> + return;
> + }
> +
> + s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
> + if (s->interval) {
> + timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
> + filter_buffer_release_timer, nf);
> + timer_mod(&s->release_timer,
> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
> + snprintf(nf->info_str, sizeof(nf->info_str),
> + "interval=%d", s->interval);
> + }
> +}
> +
> +static void filter_buffer_class_init(ObjectClass *oc, void *data)
> +{
> + NetFilterClass *nfc = NETFILTER_CLASS(oc);
> +
> + nfc->setup = filter_buffer_setup;
> + nfc->cleanup = filter_buffer_cleanup;
> + nfc->receive_iov = filter_buffer_receive_iov;
> +}
> +
> +static void filter_buffer_get_interval(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + FilterBufferState *s = FILTER_BUFFER(obj);
> + uint32_t value = s->interval;
> +
> + visit_type_uint32(v, &value, name, errp);
> +}
> +
> +static void filter_buffer_set_interval(Object *obj, Visitor *v, void *opaque,
> + const char *name, Error **errp)
> +{
> + FilterBufferState *s = FILTER_BUFFER(obj);
> + Error *local_err = NULL;
> + uint32_t value;
> +
> + visit_type_uint32(v, &value, name, &local_err);
> + if (local_err) {
> + goto out;
> + }
> + if (!value) {
> + error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
> + PRIu32 "'", object_get_typename(obj), name, value);
> + goto out;
> + }
> + s->interval = value;
> +
> +out:
> + error_propagate(errp, local_err);
> +}
> +
> +static void filter_buffer_init(Object *obj)
> +{
> + object_property_add(obj, "interval", "int",
> + filter_buffer_get_interval,
> + filter_buffer_set_interval, NULL, NULL, NULL);
> +}
> +
> +static const TypeInfo filter_buffer_info = {
> + .name = TYPE_FILTER_BUFFER,
> + .parent = TYPE_NETFILTER,
> + .class_init = filter_buffer_class_init,
> + .instance_init = filter_buffer_init,
> + .instance_size = sizeof(FilterBufferState),
> +};
> +
> +static void register_types(void)
> +{
> + type_register_static(&filter_buffer_info);
> +}
> +
> +type_init(register_types);
> diff --git a/qemu-options.hx b/qemu-options.hx
> index efce775..1dc2680 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3568,6 +3568,24 @@ the @option{virtio-rng} device. The @option{chardev} parameter is
> the unique ID of a character device backend that provides the connection
> to the RNG daemon.
>
> +@item -object filter-buffer,id=@var{id},netdev=@var{netdevid}[,chain=@var{all|in|out}][,interval=@var{t}]
> +
> +Buffer network packets on netdev @var{netdevid}.
> +If interval @var{t} provided, will release packets by interval.
> +Interval scale: microsecond.
> +
> +If interval @var{t} not provided, you have to make sure the packets can be
> +released, either by manually remove this filter or call the release buffer API,
> +otherwise, the packets will be buffered forever. Use with caution.
> +
> +chain @var{all|in|out} is an option that can be applied to any netfilter, default is @option{all}.
> +
> +@option{all} means this filter will receive packets both sent to/from the netdev
> +
> +@option{in} means this filter will receive packets sent to the netdev
> +
> +@option{out} means this filter will receive packets sent from the netdev
> +
> @end table
>
> ETEXI
> diff --git a/vl.c b/vl.c
> index 672f8b2..30196e4 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2783,7 +2783,12 @@ static bool object_create_initial(const char *type)
> if (g_str_equal(type, "rng-egd")) {
> return false;
> }
> - /* TODO: reture false for concrete netfilters */
> +
> + /* reture false for concrete netfilters */
> + if (g_str_equal(type, "filter-buffer")) {
> + return false;
> + }
> +
> return true;
> }
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-14 5:36 ` Yang Hongyang
@ 2015-09-16 9:48 ` Jason Wang
2015-09-16 11:22 ` Yang Hongyang
0 siblings, 1 reply; 28+ messages in thread
From: Jason Wang @ 2015-09-16 9:48 UTC (permalink / raw)
To: Yang Hongyang, qemu-devel
Cc: lizhijian, thuth, zhang.zhanghailiang, stefanha, armbru
On 09/14/2015 01:36 PM, Yang Hongyang wrote:
>
>
> On 09/14/2015 01:22 PM, Jason Wang wrote:
>>
>>
>> On 09/14/2015 01:09 PM, Yang Hongyang wrote:
>>> Hi Stefan,Jason,
>>>
>>> I've convert this series to base on QOM, and introducing NetQueue apis
>>> instead of using Netqueue internals as Stefan suggested. Could you
>>> please take a
>>> look at it?
>>
>> Will go through this in next few days.
>
> Thanks a lot.
Looks good to me overall. Just have small nitpicks, see individual
replies for details. If you want to send V11, may be worth to consider
them. (But not a requirement).
Thanks
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object
2015-09-16 9:28 ` Jason Wang
@ 2015-09-16 11:11 ` Yang Hongyang
0 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-16 11:11 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, stefanha, zhang.zhanghailiang, lizhijian, armbru
On 09/16/2015 05:28 PM, Jason Wang wrote:
>
>
> On 09/09/2015 03:24 PM, Yang Hongyang wrote:
>> Add a netfilter object based on QOM.
>>
>> A netfilter is attached to a netdev, captures all network packets
>> that pass through the netdev. When we delete the netdev, we also
>> delete the netfilter object attached to it, because if the netdev is
>> removed, the filter which attached to it is useless.
>>
>> QTAILQ_ENTRY global_list but used by filter layer, so that we can
>> manage all filters together.
>
> This list is not used in this series. Maybe you could either remove it
> or document its future usage.
It could be used for find filters with certain type or name. Maybe will remove
it in the next version, add back when we need it, thanks!
>
>> QTAILQ_ENTRY next used by netdev, filter belongs to the specific netdev is
>> in this queue.
>>
>> Also init delayed object after net_init_clients, because netfilters need
>> to be initialized after net clients initialized.
>>
>> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
>> ---
>> v10: use QOM for netfilter
>> v9: use flat union instead of simple union in QAPI schema
>> v8: include vhost_net header
>> v7: add check for vhost
>> fix error propagate bug
>> v6: add multiqueue support (net_filter_init1)
>> v5: remove model from NetFilterState
>> add a sent_cb param to receive_iov API
>> ---
>> include/net/filter.h | 60 +++++++++++++++++++
>> include/net/net.h | 1 +
>> include/qemu/typedefs.h | 1 +
>> net/Makefile.objs | 1 +
>> net/filter.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++
>> net/net.c | 6 ++
>> qapi-schema.json | 18 ++++++
>> vl.c | 13 ++--
>> 8 files changed, 247 insertions(+), 6 deletions(-)
>> create mode 100644 include/net/filter.h
>> create mode 100644 net/filter.c
>>
>> diff --git a/include/net/filter.h b/include/net/filter.h
>> new file mode 100644
>> index 0000000..4557cb9
>> --- /dev/null
>> +++ b/include/net/filter.h
>> @@ -0,0 +1,60 @@
>> +/*
>> + * 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.
>> + */
>> +
>> +#ifndef QEMU_NET_FILTER_H
>> +#define QEMU_NET_FILTER_H
>> +
>> +#include "qom/object.h"
>> +#include "qemu-common.h"
>> +#include "qemu/typedefs.h"
>> +#include "net/queue.h"
>> +
>> +#define TYPE_NETFILTER "netfilter"
>> +#define NETFILTER(obj) \
>> + OBJECT_CHECK(NetFilterState, (obj), TYPE_NETFILTER)
>> +#define NETFILTER_GET_CLASS(obj) \
>> + OBJECT_GET_CLASS(NetFilterClass, (obj), TYPE_NETFILTER)
>> +#define NETFILTER_CLASS(klass) \
>> + OBJECT_CLASS_CHECK(NetFilterClass, (klass), TYPE_NETFILTER)
>> +
>> +typedef void (FilterSetup) (NetFilterState *nf, Error **errp);
>> +typedef void (FilterCleanup) (NetFilterState *nf);
>> +/*
>> + * 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 *nc,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt,
>> + NetPacketSent *sent_cb);
>> +
>> +typedef struct NetFilterClass {
>> + ObjectClass parent_class;
>> +
>> + FilterSetup *setup;
>> + FilterCleanup *cleanup;
>> + FilterReceiveIOV *receive_iov;
>> +} NetFilterClass;
>> +
>> +
>> +struct NetFilterState {
>> + /* private */
>> + Object parent;
>> +
>> + /* protected */
>> + char *netdev_id;
>> + NetClientState *netdev;
>> + NetFilterChain chain;
>> + QTAILQ_ENTRY(NetFilterState) global_list;
>> + QTAILQ_ENTRY(NetFilterState) next;
>> +};
>> +
>> +#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 f8a9dd6..2c0648f 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/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..5192c6d
>> --- /dev/null
>> +++ b/net/filter.c
>> @@ -0,0 +1,153 @@
>> +/*
>> + * 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 "qemu-common.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qemu/error-report.h"
>> +
>> +#include "net/filter.h"
>> +#include "net/net.h"
>> +#include "net/vhost_net.h"
>> +#include "qom/object_interfaces.h"
>> +
>> +static QTAILQ_HEAD(, NetFilterState) net_filters;
>> +
>> +static char *netfilter_get_netdev_id(Object *obj, Error **errp)
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> +
>> + return g_strdup(nf->netdev_id);
>> +}
>> +
>> +static void netfilter_set_netdev_id(Object *obj, const char *str, Error **errp)
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> +
>> + nf->netdev_id = g_strdup(str);
>> +}
>> +
>> +static int netfilter_get_chain(Object *obj, Error **errp G_GNUC_UNUSED)
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> + return nf->chain;
>> +}
>> +
>> +static void netfilter_set_chain(Object *obj, int chain, Error **errp)
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> + nf->chain = chain;
>> +}
>> +
>> +static void netfilter_init(Object *obj)
>> +{
>> + QTAILQ_INIT(&net_filters);
>> + object_property_add_str(obj, "netdev",
>> + netfilter_get_netdev_id, netfilter_set_netdev_id,
>> + NULL);
>> + object_property_add_enum(obj, "chain", "NetFilterChain",
>> + NetFilterChain_lookup,
>> + netfilter_get_chain, netfilter_set_chain,
>> + NULL);
>> +}
>> +
>> +static void netfilter_cleanup(Object *obj)
>> +{
>> + NetFilterState *nf = NETFILTER(obj);
>> + NetFilterClass *nfc = NETFILTER_GET_CLASS(obj);
>> +
>> + if (nfc->cleanup) {
>> + nfc->cleanup(nf);
>> + }
>> +
>> + if (nf->netdev && !QTAILQ_EMPTY(&nf->netdev->filters)) {
>> + QTAILQ_REMOVE(&nf->netdev->filters, nf, next);
>> + }
>> + if (!QTAILQ_EMPTY(&net_filters)) {
>> + QTAILQ_REMOVE(&net_filters, nf, global_list);
>> + }
>> +
>> + g_free(nf->netdev_id);
>> +}
>> +
>> +static void netfilter_complete(UserCreatable *uc, Error **errp)
>> +{
>> + NetFilterState *nf = NETFILTER(uc);
>> + NetClientState *ncs[MAX_QUEUE_NUM];
>> + NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
>> + int queues;
>> + Error *local_err = NULL;
>> +
>> + if (!nf->netdev_id) {
>> + error_setg(errp, "Parameter 'netdev' is required");
>> + return;
>> + }
>> +
>> + queues = qemu_find_net_clients_except(nf->netdev_id, ncs,
>> + NET_CLIENT_OPTIONS_KIND_NIC,
>> + MAX_QUEUE_NUM);
>> + if (queues < 1) {
>> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "netdev",
>> + "a network backend id");
>> + return;
>> + } else if (queues > 1) {
>> + error_setg(errp, "Multi queue is not supported");
>> + return;
>> + }
>> +
>> + if (get_vhost_net(ncs[0])) {
>> + error_setg(errp, "Vhost is not supported");
>> + return;
>> + }
>> +
>> + nf->netdev = ncs[0];
>> +
>> + if (nfc->setup) {
>> + nfc->setup(nf, &local_err);
>> + if (local_err) {
>> + error_propagate(errp, local_err);
>> + return;
>> + }
>> + }
>> + QTAILQ_INSERT_TAIL(&net_filters, nf, global_list);
>> + QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
>> +}
>> +
>> +static bool netfilter_can_be_deleted(UserCreatable *uc, Error **errp)
>> +{
>> + return true;
>> +}
>> +
>> +static void netfilter_class_init(ObjectClass *oc, void *data)
>> +{
>> + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
>> +
>> + ucc->complete = netfilter_complete;
>> + ucc->can_be_deleted = netfilter_can_be_deleted;
>> +}
>> +
>> +static const TypeInfo netfilter_info = {
>> + .name = TYPE_NETFILTER,
>> + .parent = TYPE_OBJECT,
>> + .abstract = true,
>> + .class_size = sizeof(NetFilterClass),
>> + .class_init = netfilter_class_init,
>> + .instance_size = sizeof(NetFilterState),
>> + .instance_init = netfilter_init,
>> + .instance_finalize = netfilter_cleanup,
>> + .interfaces = (InterfaceInfo[]) {
>> + { TYPE_USER_CREATABLE },
>> + { }
>> + }
>> +};
>> +
>> +static void register_types(void)
>> +{
>> + type_register_static(&netfilter_info);
>> +}
>> +
>> +type_init(register_types);
>> diff --git a/net/net.c b/net/net.c
>> index 28a5597..d6d4db8 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,
>> @@ -384,6 +385,7 @@ void qemu_del_net_client(NetClientState *nc)
>> {
>> NetClientState *ncs[MAX_QUEUE_NUM];
>> int queues, i;
>> + NetFilterState *nf, *next;
>>
>> assert(nc->info->type != NET_CLIENT_OPTIONS_KIND_NIC);
>>
>> @@ -395,6 +397,10 @@ void qemu_del_net_client(NetClientState *nc)
>> MAX_QUEUE_NUM);
>> assert(queues != 0);
>>
>> + QTAILQ_FOREACH_SAFE(nf, &nc->filters, next, next) {
>> + object_unparent(OBJECT(nf));
>> + }
>> +
>> /* 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);
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 67fef37..068e89e 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2551,6 +2551,24 @@
>> 'opts': 'NetClientOptions' } }
>>
>> ##
>> +# @NetFilterChain
>> +#
>> +# netfilter chain, a netfilter is attached to a netdev, captures the
>> +# network packets of the netdev.
>> +#
>> +# @all: the filter will receive packets both sent to/from the netdev, this
>> +# is the default chain.
>> +#
>> +# @in: the filter will receive packets sent to the netdev.
>> +#
>> +# @out: the filter will receive packets sent from the netdev.
>> +#
>> +# Since 2.5
>> +##
>> +{ 'enum': 'NetFilterChain',
>> + 'data': [ 'all', 'in', 'out' ] }
>> +
>> +##
>> # @InetSocketAddress
>> #
>> # Captures a socket address or address range in the Internet namespace.
>> diff --git a/vl.c b/vl.c
>> index 584ca88..672f8b2 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2783,6 +2783,7 @@ static bool object_create_initial(const char *type)
>> if (g_str_equal(type, "rng-egd")) {
>> return false;
>> }
>> + /* TODO: reture false for concrete netfilters */
>> return true;
>> }
>>
>> @@ -4302,12 +4303,6 @@ int main(int argc, char **argv, char **envp)
>> exit(0);
>> }
>>
>> - if (qemu_opts_foreach(qemu_find_opts("object"),
>> - object_create,
>> - object_create_delayed, NULL)) {
>> - exit(1);
>> - }
>> -
>> machine_opts = qemu_get_machine_opts();
>> if (qemu_opt_foreach(machine_opts, machine_set_property, current_machine,
>> NULL)) {
>> @@ -4413,6 +4408,12 @@ int main(int argc, char **argv, char **envp)
>> exit(1);
>> }
>>
>> + if (qemu_opts_foreach(qemu_find_opts("object"),
>> + object_create,
>> + object_create_delayed, NULL)) {
>> + exit(1);
>> + }
>> +
>> #ifdef CONFIG_TPM
>> if (tpm_init() < 0) {
>> exit(1);
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter
2015-09-16 9:42 ` Jason Wang
@ 2015-09-16 11:19 ` Yang Hongyang
0 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-16 11:19 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: thuth, lizhijian, armbru, stefanha, zhang.zhanghailiang
On 09/16/2015 05:42 PM, Jason Wang wrote:
>
>
> On 09/09/2015 03:24 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
>> -object filter-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>
>> ---
>> v10: use NetQueue flush api to flush packets
>> sent_cb can not be called when we already return size
>> v9: adjustment due to the qapi change
>> v7: use QTAILQ_FOREACH_SAFE() when flush packets
>> v6: move the interval check earlier and some comment adjust
>> v5: remove dummy sent_cb
>> change interval type from int64 to uint32
>> check interval!=0 when initialise
>> rename FILTERBUFFERState to FilterBufferState
>> 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 | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> qemu-options.hx | 18 ++++++
>> vl.c | 7 ++-
>> 4 files changed, 194 insertions(+), 1 deletion(-)
>> create mode 100644 net/filter-buffer.c
>>
>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>> index 914aec0..5fa2f97 100644
>> --- a/net/Makefile.objs
>> +++ b/net/Makefile.objs
>> @@ -14,3 +14,4 @@ common-obj-$(CONFIG_SLIRP) += slirp.o
>> common-obj-$(CONFIG_VDE) += vde.o
>> common-obj-$(CONFIG_NETMAP) += netmap.o
>> common-obj-y += filter.o
>> +common-obj-y += filter-buffer.o
>> diff --git a/net/filter-buffer.c b/net/filter-buffer.c
>> new file mode 100644
>> index 0000000..26698d9
>> --- /dev/null
>> +++ b/net/filter-buffer.c
>> @@ -0,0 +1,169 @@
>> +/*
>> + * 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 "qemu-common.h"
>> +#include "qemu/timer.h"
>> +#include "qemu/iov.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qapi-visit.h"
>> +#include "qom/object.h"
>> +
>> +#define TYPE_FILTER_BUFFER "filter-buffer"
>> +
>> +#define FILTER_BUFFER(obj) \
>> + OBJECT_CHECK(FilterBufferState, (obj), TYPE_FILTER_BUFFER)
>> +
>> +typedef struct FilterBufferState {
>> + NetFilterState parent_obj;
>> +
>> + NetQueue *incoming_queue;
>> + uint32_t interval;
>> + QEMUTimer release_timer;
>> +} FilterBufferState;
>> +
>> +static void filter_buffer_flush(NetFilterState *nf)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + if (!qemu_net_queue_flush(s->incoming_queue)) {
>> + /* Unable to empty the queue, purge remaining packets */
>> + qemu_net_queue_purge(s->incoming_queue, nf->netdev);
>> + }
>> +}
>> +
>> +static void filter_buffer_release_timer(void *opaque)
>> +{
>> + NetFilterState *nf = opaque;
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> + filter_buffer_flush(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,
>> + NetPacketSent *sent_cb)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + /*
>> + * we return size when buffer a packet, the sender will take it as
>> + * a already sent packet, so sent_cb should not be called later
>> + */
>> + qemu_net_queue_append_iov(s->incoming_queue, sender, flags,
>> + iov, iovcnt, NULL);
>> + return iov_size(iov, iovcnt);
>
> Then a small issue here is, even if guest can't receive packet for some
> reasons. Filter can still accept packet until its internal queue is
> full. May consider to solve this in the future.
Sure, will add your comment above into the code comment as a FIXME, thank you!
>
>> +}
>> +
>> +static void filter_buffer_cleanup(NetFilterState *nf)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + if (s->interval) {
>> + timer_del(&s->release_timer);
>> + }
>> +
>> + /* flush packets */
>> + if (s->incoming_queue) {
>> + filter_buffer_flush(nf);
>> + g_free(s->incoming_queue);
>> + }
>> +}
>> +
>> +static void filter_buffer_setup(NetFilterState *nf, Error **errp)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(nf);
>> +
>> + /*
>> + * this check should be dropped when there're VM FT solutions like MC
>> + * or COLO use this filter to release packets on demand.
>> + */
>> + if (!s->interval) {
>> + error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "interval",
>> + "a non-zero interval");
>> + return;
>> + }
>> +
>> + s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
>> + if (s->interval) {
>> + timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
>> + filter_buffer_release_timer, nf);
>> + timer_mod(&s->release_timer,
>> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
>> + snprintf(nf->info_str, sizeof(nf->info_str),
>> + "interval=%d", s->interval);
>> + }
>> +}
>> +
>> +static void filter_buffer_class_init(ObjectClass *oc, void *data)
>> +{
>> + NetFilterClass *nfc = NETFILTER_CLASS(oc);
>> +
>> + nfc->setup = filter_buffer_setup;
>> + nfc->cleanup = filter_buffer_cleanup;
>> + nfc->receive_iov = filter_buffer_receive_iov;
>> +}
>> +
>> +static void filter_buffer_get_interval(Object *obj, Visitor *v, void *opaque,
>> + const char *name, Error **errp)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(obj);
>> + uint32_t value = s->interval;
>> +
>> + visit_type_uint32(v, &value, name, errp);
>> +}
>> +
>> +static void filter_buffer_set_interval(Object *obj, Visitor *v, void *opaque,
>> + const char *name, Error **errp)
>> +{
>> + FilterBufferState *s = FILTER_BUFFER(obj);
>> + Error *local_err = NULL;
>> + uint32_t value;
>> +
>> + visit_type_uint32(v, &value, name, &local_err);
>> + if (local_err) {
>> + goto out;
>> + }
>> + if (!value) {
>> + error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
>> + PRIu32 "'", object_get_typename(obj), name, value);
>> + goto out;
>> + }
>> + s->interval = value;
>> +
>> +out:
>> + error_propagate(errp, local_err);
>> +}
>> +
>> +static void filter_buffer_init(Object *obj)
>> +{
>> + object_property_add(obj, "interval", "int",
>> + filter_buffer_get_interval,
>> + filter_buffer_set_interval, NULL, NULL, NULL);
>> +}
>> +
>> +static const TypeInfo filter_buffer_info = {
>> + .name = TYPE_FILTER_BUFFER,
>> + .parent = TYPE_NETFILTER,
>> + .class_init = filter_buffer_class_init,
>> + .instance_init = filter_buffer_init,
>> + .instance_size = sizeof(FilterBufferState),
>> +};
>> +
>> +static void register_types(void)
>> +{
>> + type_register_static(&filter_buffer_info);
>> +}
>> +
>> +type_init(register_types);
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index efce775..1dc2680 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -3568,6 +3568,24 @@ the @option{virtio-rng} device. The @option{chardev} parameter is
>> the unique ID of a character device backend that provides the connection
>> to the RNG daemon.
>>
>> +@item -object filter-buffer,id=@var{id},netdev=@var{netdevid}[,chain=@var{all|in|out}][,interval=@var{t}]
>> +
>> +Buffer network packets on netdev @var{netdevid}.
>> +If interval @var{t} provided, will release packets by interval.
>> +Interval scale: microsecond.
>> +
>> +If interval @var{t} not provided, you have to make sure the packets can be
>> +released, either by manually remove this filter or call the release buffer API,
>> +otherwise, the packets will be buffered forever. Use with caution.
>> +
>> +chain @var{all|in|out} is an option that can be applied to any netfilter, default is @option{all}.
>> +
>> +@option{all} means this filter will receive packets both sent to/from the netdev
>> +
>> +@option{in} means this filter will receive packets sent to the netdev
>> +
>> +@option{out} means this filter will receive packets sent from the netdev
>> +
>> @end table
>>
>> ETEXI
>> diff --git a/vl.c b/vl.c
>> index 672f8b2..30196e4 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2783,7 +2783,12 @@ static bool object_create_initial(const char *type)
>> if (g_str_equal(type, "rng-egd")) {
>> return false;
>> }
>> - /* TODO: reture false for concrete netfilters */
>> +
>> + /* reture false for concrete netfilters */
>> + if (g_str_equal(type, "filter-buffer")) {
>> + return false;
>> + }
>> +
>> return true;
>> }
>>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter
2015-09-16 9:48 ` Jason Wang
@ 2015-09-16 11:22 ` Yang Hongyang
0 siblings, 0 replies; 28+ messages in thread
From: Yang Hongyang @ 2015-09-16 11:22 UTC (permalink / raw)
To: Jason Wang, qemu-devel
Cc: lizhijian, thuth, zhang.zhanghailiang, stefanha, armbru
On 09/16/2015 05:48 PM, Jason Wang wrote:
>
>
> On 09/14/2015 01:36 PM, Yang Hongyang wrote:
>>
>>
>> On 09/14/2015 01:22 PM, Jason Wang wrote:
>>>
>>>
>>> On 09/14/2015 01:09 PM, Yang Hongyang wrote:
>>>> Hi Stefan,Jason,
>>>>
>>>> I've convert this series to base on QOM, and introducing NetQueue apis
>>>> instead of using Netqueue internals as Stefan suggested. Could you
>>>> please take a
>>>> look at it?
>>>
>>> Will go through this in next few days.
>>
>> Thanks a lot.
>
> Looks good to me overall. Just have small nitpicks, see individual
> replies for details. If you want to send V11, may be worth to consider
> them. (But not a requirement).
Thanks a lot for the review, will send a V11 address them and with multiqueue
support as additional patches together.
>
> Thanks
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2015-09-16 11:22 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-09 7:24 [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 01/10] qmp: delete qemu opts when delete an object Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 02/10] init/cleanup of netfilter object Yang Hongyang
2015-09-14 8:54 ` Daniel P. Berrange
2015-09-14 8:56 ` Daniel P. Berrange
2015-09-14 9:05 ` Yang Hongyang
2015-09-16 9:28 ` Jason Wang
2015-09-16 11:11 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 03/10] netfilter: hook packets before net queue send Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
2015-09-16 9:29 ` Jason Wang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 09/10] netfilter: add a netbuffer filter Yang Hongyang
2015-09-14 9:04 ` Daniel P. Berrange
2015-09-14 9:53 ` Yang Hongyang
2015-09-16 9:42 ` Jason Wang
2015-09-16 11:19 ` Yang Hongyang
2015-09-09 7:24 ` [Qemu-devel] [PATCH v10 10/10] tests: add test cases for netfilter object Yang Hongyang
2015-09-14 5:09 ` [Qemu-devel] [PATCH v10 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-09-14 5:22 ` Jason Wang
2015-09-14 5:36 ` Yang Hongyang
2015-09-16 9:48 ` Jason Wang
2015-09-16 11:22 ` Yang Hongyang
2015-09-14 9:05 ` Daniel P. Berrange
2015-09-14 9:14 ` 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).