* [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
@ 2016-02-05 6:50 Zhang Chen
2016-02-18 2:41 ` Jason Wang
0 siblings, 1 reply; 8+ messages in thread
From: Zhang Chen @ 2016-02-05 6:50 UTC (permalink / raw)
To: qemu devel, Jason Wang
Cc: Li Zhijian, Gui jianfeng, eddie.dong, zhanghailiang,
Dr. David Alan Gilbert, Zhang Chen, Yang Hongyang
From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
Filter-redirector is a netfilter plugin.
It gives qemu the ability to redirect net packet.
redirector can redirect filter's net packet to outdev.
and redirect indev's packet to filter.
filter
+
|
|
redirector |
+-------------------------+
| | |
| | |
| | |
indev +----------------+ +----------------> outdev
| | |
| | |
| | |
+-------------------------+
|
|
v
filter
usage:
-netdev tap,id=hn0
-chardev socket,id=s0,host=ip_primary,port=X,server,nowait
-chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
-filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1
Signed-off-by: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
net/Makefile.objs | 1 +
net/filter-redirector.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
qemu-options.hx | 6 ++
vl.c | 3 +-
4 files changed, 254 insertions(+), 1 deletion(-)
create mode 100644 net/filter-redirector.c
diff --git a/net/Makefile.objs b/net/Makefile.objs
index 5fa2f97..f4290a5 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
common-obj-$(CONFIG_NETMAP) += netmap.o
common-obj-y += filter.o
common-obj-y += filter-buffer.o
+common-obj-y += filter-redirector.o
diff --git a/net/filter-redirector.c b/net/filter-redirector.c
new file mode 100644
index 0000000..364e463
--- /dev/null
+++ b/net/filter-redirector.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Author: Zhang Chen <zhangchen.fnst@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/net.h"
+#include "qemu-common.h"
+#include "qapi/qmp/qerror.h"
+#include "qapi-visit.h"
+#include "qom/object.h"
+#include "qemu/main-loop.h"
+#include "qemu/error-report.h"
+#include "trace.h"
+#include "sysemu/char.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+
+#define FILTER_REDIRECTOR(obj) \
+ OBJECT_CHECK(RedirectorState, (obj), TYPE_FILTER_REDIRECTOR)
+
+#define TYPE_FILTER_REDIRECTOR "filter-redirector"
+#define REDIRECT_HEADER_LEN sizeof(uint32_t)
+
+typedef struct RedirectorState {
+ NetFilterState parent_obj;
+ NetQueue *incoming_queue;/* guest normal net queue */
+ char *indev;
+ char *outdev;
+ CharDriverState *chr_in;
+ CharDriverState *chr_out;
+} RedirectorState;
+
+static ssize_t filter_redirector_send(NetFilterState *nf,
+ const struct iovec *iov,
+ int iovcnt)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(nf);
+ ssize_t ret = 0;
+ ssize_t size = 0;
+ uint32_t len = 0;
+ char *buf;
+
+ size = iov_size(iov, iovcnt);
+ len = htonl(size);
+ if (!size) {
+ return 0;
+ }
+
+ buf = g_malloc0(size);
+ iov_to_buf(iov, iovcnt, 0, buf, size);
+ ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)&len, sizeof(len));
+ if (ret < 0) {
+ g_free(buf);
+ return ret;
+ }
+
+ ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)buf, size);
+ g_free(buf);
+ return ret;
+}
+
+static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(nf);
+ ssize_t ret = 0;
+
+ if (s->chr_out) {
+ ret = filter_redirector_send(nf, iov, iovcnt);
+ if (ret < 0) {
+ error_report("filter_redirector_send failed");
+ }
+ }
+ return iov_size(iov, iovcnt);
+}
+
+static void filter_redirector_cleanup(NetFilterState *nf)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(nf);
+
+ if (s->chr_in) {
+ qemu_chr_fe_release(s->chr_in);
+ }
+ if (s->chr_out) {
+ qemu_chr_fe_release(s->chr_out);
+ }
+}
+
+static int redirector_chr_can_read(void *opaque)
+{
+ return REDIRECT_HEADER_LEN;
+}
+
+static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
+{
+ NetFilterState *nf = opaque;
+ RedirectorState *s = FILTER_REDIRECTOR(nf);
+ uint32_t len;
+ ssize_t ret = 0;
+ uint8_t *recv_buf;
+
+ if (size != REDIRECT_HEADER_LEN) {
+ // FIXME: do something else
+ error_report("packet is corruption, drop it");
+ return;
+ }
+ memcpy(&len, buf, sizeof(len));
+ len = ntohl(len);
+
+ if (len > 0 && len < NET_BUFSIZE) {
+ recv_buf = g_malloc0(len);
+ ret = qemu_chr_fe_read_all(s->chr_in, recv_buf, len);
+ if (ret != len) {
+ error_report("filter-redirector recv buf failed");
+ g_free(recv_buf);
+ return;
+ }
+
+ ret = qemu_net_queue_send(s->incoming_queue, nf->netdev,
+ 0, (const uint8_t *)recv_buf, len, NULL);
+ g_free(recv_buf);
+ if (ret < 0) {
+ error_report("filter-redirector out to guest failed");
+ }
+ } else {
+ error_report("filter-redirector recv len failed");
+ }
+}
+
+static void filter_redirector_setup(NetFilterState *nf, Error **errp)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(nf);
+
+ if (!s->indev && !s->outdev) {
+ error_setg(errp, "filter redirector needs 'indev' or "
+ "'outdev' at least one property set");
+ return;
+ }
+
+ if (s->indev) {
+ s->chr_in = qemu_chr_find(s->indev);
+ if (s->chr_in == NULL) {
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "IN Device '%s' not found", s->indev);
+ return;
+ }
+
+ qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
+ redirector_chr_read, NULL, nf);
+ }
+
+ if (s->outdev) {
+ s->chr_out = qemu_chr_find(s->outdev);
+ if (s->chr_out == NULL) {
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
+ "OUT Device '%s' not found", s->outdev);
+ return;
+ }
+ }
+ s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
+}
+
+static void filter_redirector_class_init(ObjectClass *oc, void *data)
+{
+ NetFilterClass *nfc = NETFILTER_CLASS(oc);
+
+ nfc->setup = filter_redirector_setup;
+ nfc->cleanup = filter_redirector_cleanup;
+ nfc->receive_iov = filter_redirector_receive_iov;
+}
+
+static char *filter_redirector_get_indev(Object *obj, Error **errp)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(obj);
+
+ return g_strdup(s->indev);
+}
+
+static void
+filter_redirector_set_indev(Object *obj, const char *value, Error **errp)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(obj);
+
+ g_free(s->indev);
+ s->indev = g_strdup(value);
+}
+
+static char *filter_redirector_get_outdev(Object *obj, Error **errp)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(obj);
+
+ return g_strdup(s->outdev);
+}
+
+static void
+filter_redirector_set_outdev(Object *obj, const char *value, Error **errp)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(obj);
+
+ g_free(s->outdev);
+ s->outdev = g_strdup(value);
+}
+
+static void filter_redirector_init(Object *obj)
+{
+ object_property_add_str(obj, "indev", filter_redirector_get_indev,
+ filter_redirector_set_indev, NULL);
+ object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
+ filter_redirector_set_outdev, NULL);
+}
+
+static void filter_redirector_fini(Object *obj)
+{
+ RedirectorState *s = FILTER_REDIRECTOR(obj);
+
+ g_free(s->indev);
+ g_free(s->outdev);
+}
+
+static const TypeInfo filter_redirector_info = {
+ .name = TYPE_FILTER_REDIRECTOR,
+ .parent = TYPE_NETFILTER,
+ .class_init = filter_redirector_class_init,
+ .instance_init = filter_redirector_init,
+ .instance_finalize = filter_redirector_fini,
+ .instance_size = sizeof(RedirectorState),
+};
+
+static void register_types(void)
+{
+ type_register_static(&filter_redirector_info);
+}
+
+type_init(register_types);
diff --git a/qemu-options.hx b/qemu-options.hx
index f31a240..1f796ed 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3745,6 +3745,12 @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
@option{tx}: the filter is attached to the transmit queue of the netdev,
where it will receive packets sent by the netdev.
+@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
+
+filter-redirector on netdev @var{netdevid},redirector can redirect filter's net packet to outdev.
+and redirect indev's packet to filter.
+queue @var{all|rx|tx} is an option that can be applied to filter-redirector.
+
@item -object filter-dump,id=@var{id},netdev=@var{dev},file=@var{filename}][,maxlen=@var{len}]
Dump the network traffic on netdev @var{dev} to the file specified by
diff --git a/vl.c b/vl.c
index f043009..4a9a9a0 100644
--- a/vl.c
+++ b/vl.c
@@ -2801,7 +2801,8 @@ static bool object_create_initial(const char *type)
* they depend on netdevs already existing
*/
if (g_str_equal(type, "filter-buffer") ||
- g_str_equal(type, "filter-dump")) {
+ g_str_equal(type, "filter-dump") ||
+ g_str_equal(type, "filter-redirector")) {
return false;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-05 6:50 [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector Zhang Chen
@ 2016-02-18 2:41 ` Jason Wang
2016-02-18 7:50 ` Zhang Chen
0 siblings, 1 reply; 8+ messages in thread
From: Jason Wang @ 2016-02-18 2:41 UTC (permalink / raw)
To: Zhang Chen, qemu devel
Cc: Li Zhijian, Gui jianfeng, eddie.dong, zhanghailiang,
Dr. David Alan Gilbert, Yang Hongyang
On 02/05/2016 02:50 PM, Zhang Chen wrote:
> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>
> Filter-redirector is a netfilter plugin.
> It gives qemu the ability to redirect net packet.
> redirector can redirect filter's net packet to outdev.
> and redirect indev's packet to filter.
>
> filter
> +
> |
> |
> redirector |
> +-------------------------+
> | | |
> | | |
> | | |
> indev +----------------+ +----------------> outdev
> | | |
> | | |
> | | |
> +-------------------------+
> |
> |
> v
> filter
>
> usage:
>
> -netdev tap,id=hn0
> -chardev socket,id=s0,host=ip_primary,port=X,server,nowait
> -chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1
>
> Signed-off-by: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> ---
Thanks a lot for the patch. Like mirror, let's design a unit-test for
this. And what's more, is there any chance to unify the codes? (At least
parts of the codes could be reused).
> net/Makefile.objs | 1 +
> net/filter-redirector.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
> qemu-options.hx | 6 ++
> vl.c | 3 +-
> 4 files changed, 254 insertions(+), 1 deletion(-)
> create mode 100644 net/filter-redirector.c
>
> diff --git a/net/Makefile.objs b/net/Makefile.objs
> index 5fa2f97..f4290a5 100644
> --- a/net/Makefile.objs
> +++ b/net/Makefile.objs
> @@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
> common-obj-$(CONFIG_NETMAP) += netmap.o
> common-obj-y += filter.o
> common-obj-y += filter-buffer.o
> +common-obj-y += filter-redirector.o
> diff --git a/net/filter-redirector.c b/net/filter-redirector.c
> new file mode 100644
> index 0000000..364e463
> --- /dev/null
> +++ b/net/filter-redirector.c
> @@ -0,0 +1,245 @@
> +/*
> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
> + * Copyright (c) 2016 FUJITSU LIMITED
> + * Copyright (c) 2016 Intel Corporation
> + *
> + * Author: Zhang Chen <zhangchen.fnst@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/net.h"
> +#include "qemu-common.h"
> +#include "qapi/qmp/qerror.h"
> +#include "qapi-visit.h"
> +#include "qom/object.h"
> +#include "qemu/main-loop.h"
> +#include "qemu/error-report.h"
> +#include "trace.h"
> +#include "sysemu/char.h"
> +#include "qemu/iov.h"
> +#include "qemu/sockets.h"
> +
> +#define FILTER_REDIRECTOR(obj) \
> + OBJECT_CHECK(RedirectorState, (obj), TYPE_FILTER_REDIRECTOR)
> +
> +#define TYPE_FILTER_REDIRECTOR "filter-redirector"
> +#define REDIRECT_HEADER_LEN sizeof(uint32_t)
> +
> +typedef struct RedirectorState {
> + NetFilterState parent_obj;
> + NetQueue *incoming_queue;/* guest normal net queue */
The comment looks unless and maybe even wrong when queue=rx?
> + char *indev;
> + char *outdev;
> + CharDriverState *chr_in;
> + CharDriverState *chr_out;
> +} RedirectorState;
> +
> +static ssize_t filter_redirector_send(NetFilterState *nf,
> + const struct iovec *iov,
> + int iovcnt)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(nf);
> + ssize_t ret = 0;
> + ssize_t size = 0;
> + uint32_t len = 0;
> + char *buf;
> +
> + size = iov_size(iov, iovcnt);
> + len = htonl(size);
> + if (!size) {
> + return 0;
> + }
> +
> + buf = g_malloc0(size);
> + iov_to_buf(iov, iovcnt, 0, buf, size);
> + ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)&len, sizeof(len));
> + if (ret < 0) {
Similar to mirror, need check the return value against sizeof(len). And
the code could be simplified with something like:
goto out;
...
out:
g_free(buf);
return ret;
And you can see another advantages of unifying the codes here, avoid
duplicating bugx/fixes.
> + g_free(buf);
> + return ret;
> + }
> +
> + ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)buf, size);
> + g_free(buf);
> + return ret;
> +}
> +
> +static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
> + NetClientState *sender,
> + unsigned flags,
> + const struct iovec *iov,
> + int iovcnt,
> + NetPacketSent *sent_cb)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(nf);
> + ssize_t ret = 0;
> +
> + if (s->chr_out) {
> + ret = filter_redirector_send(nf, iov, iovcnt);
> + if (ret < 0) {
> + error_report("filter_redirector_send failed");
> + }
> + }
> + return iov_size(iov, iovcnt);
> +}
> +
> +static void filter_redirector_cleanup(NetFilterState *nf)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(nf);
> +
> + if (s->chr_in) {
> + qemu_chr_fe_release(s->chr_in);
release but no claim?
> + }
> + if (s->chr_out) {
> + qemu_chr_fe_release(s->chr_out);
> + }
> +}
> +
> +static int redirector_chr_can_read(void *opaque)
> +{
> + return REDIRECT_HEADER_LEN;
> +}
> +
> +static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
> +{
> + NetFilterState *nf = opaque;
> + RedirectorState *s = FILTER_REDIRECTOR(nf);
> + uint32_t len;
> + ssize_t ret = 0;
> + uint8_t *recv_buf;
> +
> + if (size != REDIRECT_HEADER_LEN) {
> + // FIXME: do something else
This is not packet corruption since I believe you want tcp socket here
which is doing byte stream. Need some logic to prepare to wait for all
the bytes for length is received.
Though sub-optimal (since it uses usleep() which may block iothread),
maybe you could just do a for simplicity:
qemu_chr_fe_read_all(s->chr_in, recv_buf, sizeof(len));
If you wish, you can have a look at socket backend (net_socket_send) who
has a better solution for this.
> + error_report("packet is corruption, drop it");
> + return;
> + }
> + memcpy(&len, buf, sizeof(len));
> + len = ntohl(len);
> +
> + if (len > 0 && len < NET_BUFSIZE) {
> + recv_buf = g_malloc0(len);
Looks like g_malloc() is sufficient here.
> + ret = qemu_chr_fe_read_all(s->chr_in, recv_buf, len);
> + if (ret != len) {
> + error_report("filter-redirector recv buf failed");
> + g_free(recv_buf);
> + return;
> + }
> +
> + ret = qemu_net_queue_send(s->incoming_queue, nf->netdev,
> + 0, (const uint8_t *)recv_buf, len, NULL);
> + g_free(recv_buf);
> + if (ret < 0) {
> + error_report("filter-redirector out to guest failed");
"guest" is inaccurate here, what if queue=rx?
> + }
> + } else {
> + error_report("filter-redirector recv len failed");
> + }
> +}
> +
> +static void filter_redirector_setup(NetFilterState *nf, Error **errp)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(nf);
> +
> + if (!s->indev && !s->outdev) {
> + error_setg(errp, "filter redirector needs 'indev' or "
> + "'outdev' at least one property set");
> + return;
> + }
> +
> + if (s->indev) {
> + s->chr_in = qemu_chr_find(s->indev);
> + if (s->chr_in == NULL) {
> + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
> + "IN Device '%s' not found", s->indev);
> + return;
> + }
> +
> + qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
> + redirector_chr_read, NULL, nf);
> + }
> +
> + if (s->outdev) {
> + s->chr_out = qemu_chr_find(s->outdev);
> + if (s->chr_out == NULL) {
> + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
> + "OUT Device '%s' not found", s->outdev);
> + return;
> + }
> + }
> + s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
> +}
> +
> +static void filter_redirector_class_init(ObjectClass *oc, void *data)
> +{
> + NetFilterClass *nfc = NETFILTER_CLASS(oc);
> +
> + nfc->setup = filter_redirector_setup;
> + nfc->cleanup = filter_redirector_cleanup;
> + nfc->receive_iov = filter_redirector_receive_iov;
> +}
> +
> +static char *filter_redirector_get_indev(Object *obj, Error **errp)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(obj);
> +
> + return g_strdup(s->indev);
> +}
> +
> +static void
> +filter_redirector_set_indev(Object *obj, const char *value, Error **errp)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(obj);
> +
> + g_free(s->indev);
> + s->indev = g_strdup(value);
> +}
> +
> +static char *filter_redirector_get_outdev(Object *obj, Error **errp)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(obj);
> +
> + return g_strdup(s->outdev);
> +}
> +
> +static void
> +filter_redirector_set_outdev(Object *obj, const char *value, Error **errp)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(obj);
> +
> + g_free(s->outdev);
> + s->outdev = g_strdup(value);
> +}
> +
> +static void filter_redirector_init(Object *obj)
> +{
> + object_property_add_str(obj, "indev", filter_redirector_get_indev,
> + filter_redirector_set_indev, NULL);
> + object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
> + filter_redirector_set_outdev, NULL);
> +}
> +
> +static void filter_redirector_fini(Object *obj)
> +{
> + RedirectorState *s = FILTER_REDIRECTOR(obj);
> +
> + g_free(s->indev);
> + g_free(s->outdev);
> +}
> +
> +static const TypeInfo filter_redirector_info = {
> + .name = TYPE_FILTER_REDIRECTOR,
> + .parent = TYPE_NETFILTER,
> + .class_init = filter_redirector_class_init,
> + .instance_init = filter_redirector_init,
> + .instance_finalize = filter_redirector_fini,
> + .instance_size = sizeof(RedirectorState),
> +};
> +
> +static void register_types(void)
> +{
> + type_register_static(&filter_redirector_info);
> +}
> +
> +type_init(register_types);
> diff --git a/qemu-options.hx b/qemu-options.hx
> index f31a240..1f796ed 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3745,6 +3745,12 @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
> @option{tx}: the filter is attached to the transmit queue of the netdev,
> where it will receive packets sent by the netdev.
>
> +@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
> +
> +filter-redirector on netdev @var{netdevid},redirector can redirect filter's net packet to outdev.
> +and redirect indev's packet to filter.
Exceeds 80 characters limit. And need more work. e.g:
- Need to differs outdev id from indev id.
- Need to clarify at least one of outdev and indev needs to be set
- We're in fact redirect packet between chardev and netdev's queue (not
filter).
> +queue @var{all|rx|tx} is an option that can be applied to filter-redirector.
This line is unnecessary, we've already had
"
queue @var{all|rx|tx} is an option that can be applied to any netfilter.
"
> +
> @item -object filter-dump,id=@var{id},netdev=@var{dev},file=@var{filename}][,maxlen=@var{len}]
>
> Dump the network traffic on netdev @var{dev} to the file specified by
> diff --git a/vl.c b/vl.c
> index f043009..4a9a9a0 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2801,7 +2801,8 @@ static bool object_create_initial(const char *type)
> * they depend on netdevs already existing
> */
> if (g_str_equal(type, "filter-buffer") ||
> - g_str_equal(type, "filter-dump")) {
> + g_str_equal(type, "filter-dump") ||
> + g_str_equal(type, "filter-redirector")) {
> return false;
> }
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-18 2:41 ` Jason Wang
@ 2016-02-18 7:50 ` Zhang Chen
2016-02-24 3:39 ` Jason Wang
0 siblings, 1 reply; 8+ messages in thread
From: Zhang Chen @ 2016-02-18 7:50 UTC (permalink / raw)
To: Jason Wang, qemu devel
Cc: Li Zhijian, Gui jianfeng, eddie.dong, zhanghailiang,
Dr. David Alan Gilbert, Yang Hongyang
On 02/18/2016 10:41 AM, Jason Wang wrote:
>
> On 02/05/2016 02:50 PM, Zhang Chen wrote:
>> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>
>> Filter-redirector is a netfilter plugin.
>> It gives qemu the ability to redirect net packet.
>> redirector can redirect filter's net packet to outdev.
>> and redirect indev's packet to filter.
>>
>> filter
>> +
>> |
>> |
>> redirector |
>> +-------------------------+
>> | | |
>> | | |
>> | | |
>> indev +----------------+ +----------------> outdev
>> | | |
>> | | |
>> | | |
>> +-------------------------+
>> |
>> |
>> v
>> filter
v
change it to filter ........ filter ...... guest
It's may more clearly expressed.
>> usage:
>>
>> -netdev tap,id=hn0
>> -chardev socket,id=s0,host=ip_primary,port=X,server,nowait
>> -chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
>> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1
>>
>> Signed-off-by: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>> ---
> Thanks a lot for the patch. Like mirror, let's design a unit-test for
> this. And what's more, is there any chance to unify the codes? (At least
> parts of the codes could be reused).
We can make filter-redirector based on filter-mirror.
if you want to use redirector ,you must open mirror before.
like this:
-netdev tap,id=hn0
-chardev socket,id=mirror0,host=ip_primary,port=X,server,nowait
-filter-mirror,id=m0,netdev=hn0,queue=tx/rx/all,redirector=on,outdev=mirror0
-filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0
How about this?
>> net/Makefile.objs | 1 +
>> net/filter-redirector.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++
>> qemu-options.hx | 6 ++
>> vl.c | 3 +-
>> 4 files changed, 254 insertions(+), 1 deletion(-)
>> create mode 100644 net/filter-redirector.c
>>
>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>> index 5fa2f97..f4290a5 100644
>> --- a/net/Makefile.objs
>> +++ b/net/Makefile.objs
>> @@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
>> common-obj-$(CONFIG_NETMAP) += netmap.o
>> common-obj-y += filter.o
>> common-obj-y += filter-buffer.o
>> +common-obj-y += filter-redirector.o
>> diff --git a/net/filter-redirector.c b/net/filter-redirector.c
>> new file mode 100644
>> index 0000000..364e463
>> --- /dev/null
>> +++ b/net/filter-redirector.c
>> @@ -0,0 +1,245 @@
>> +/*
>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>> + * Copyright (c) 2016 FUJITSU LIMITED
>> + * Copyright (c) 2016 Intel Corporation
>> + *
>> + * Author: Zhang Chen <zhangchen.fnst@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/net.h"
>> +#include "qemu-common.h"
>> +#include "qapi/qmp/qerror.h"
>> +#include "qapi-visit.h"
>> +#include "qom/object.h"
>> +#include "qemu/main-loop.h"
>> +#include "qemu/error-report.h"
>> +#include "trace.h"
>> +#include "sysemu/char.h"
>> +#include "qemu/iov.h"
>> +#include "qemu/sockets.h"
>> +
>> +#define FILTER_REDIRECTOR(obj) \
>> + OBJECT_CHECK(RedirectorState, (obj), TYPE_FILTER_REDIRECTOR)
>> +
>> +#define TYPE_FILTER_REDIRECTOR "filter-redirector"
>> +#define REDIRECT_HEADER_LEN sizeof(uint32_t)
>> +
>> +typedef struct RedirectorState {
>> + NetFilterState parent_obj;
>> + NetQueue *incoming_queue;/* guest normal net queue */
> The comment looks unless and maybe even wrong when queue=rx?
We design redirector that indev's data always be passed to guest finally.
so, It's no relation between the queue=rx/tx/all. just related to indev
= xxx.
we need incoming_queue to inject packet from indev.
>> + char *indev;
>> + char *outdev;
>> + CharDriverState *chr_in;
>> + CharDriverState *chr_out;
>> +} RedirectorState;
>> +
>> +static ssize_t filter_redirector_send(NetFilterState *nf,
>> + const struct iovec *iov,
>> + int iovcnt)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(nf);
>> + ssize_t ret = 0;
>> + ssize_t size = 0;
>> + uint32_t len = 0;
>> + char *buf;
>> +
>> + size = iov_size(iov, iovcnt);
>> + len = htonl(size);
>> + if (!size) {
>> + return 0;
>> + }
>> +
>> + buf = g_malloc0(size);
>> + iov_to_buf(iov, iovcnt, 0, buf, size);
>> + ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)&len, sizeof(len));
>> + if (ret < 0) {
> Similar to mirror, need check the return value against sizeof(len). And
> the code could be simplified with something like:
>
> goto out;
>
> ...
>
> out:
> g_free(buf);
> return ret;
>
> And you can see another advantages of unifying the codes here, avoid
> duplicating bugx/fixes.
Thanks , I will fix it in next version.
>> + g_free(buf);
>> + return ret;
>> + }
>> +
>> + ret = qemu_chr_fe_write_all(s->chr_out, (uint8_t *)buf, size);
>> + g_free(buf);
>> + return ret;
>> +}
>> +
>> +static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
>> + NetClientState *sender,
>> + unsigned flags,
>> + const struct iovec *iov,
>> + int iovcnt,
>> + NetPacketSent *sent_cb)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(nf);
>> + ssize_t ret = 0;
>> +
>> + if (s->chr_out) {
>> + ret = filter_redirector_send(nf, iov, iovcnt);
>> + if (ret < 0) {
>> + error_report("filter_redirector_send failed");
>> + }
>> + }
>> + return iov_size(iov, iovcnt);
>> +}
>> +
>> +static void filter_redirector_cleanup(NetFilterState *nf)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(nf);
>> +
>> + if (s->chr_in) {
>> + qemu_chr_fe_release(s->chr_in);
> release but no claim?
will fix it in next version.
>> + }
>> + if (s->chr_out) {
>> + qemu_chr_fe_release(s->chr_out);
>> + }
>> +}
>> +
>> +static int redirector_chr_can_read(void *opaque)
>> +{
>> + return REDIRECT_HEADER_LEN;
>> +}
>> +
>> +static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
>> +{
>> + NetFilterState *nf = opaque;
>> + RedirectorState *s = FILTER_REDIRECTOR(nf);
>> + uint32_t len;
>> + ssize_t ret = 0;
>> + uint8_t *recv_buf;
>> +
>> + if (size != REDIRECT_HEADER_LEN) {
>> + // FIXME: do something else
> This is not packet corruption since I believe you want tcp socket here
> which is doing byte stream. Need some logic to prepare to wait for all
> the bytes for length is received.
>
> Though sub-optimal (since it uses usleep() which may block iothread),
> maybe you could just do a for simplicity:
>
> qemu_chr_fe_read_all(s->chr_in, recv_buf, sizeof(len));
>
> If you wish, you can have a look at socket backend (net_socket_send) who
> has a better solution for this.
Get it~
I will fix it in next version.
>> + error_report("packet is corruption, drop it");
>> + return;
>> + }
>> + memcpy(&len, buf, sizeof(len));
>> + len = ntohl(len);
>> +
>> + if (len > 0 && len < NET_BUFSIZE) {
>> + recv_buf = g_malloc0(len);
> Looks like g_malloc() is sufficient here.
OK, will fix it in next version.
>
>> + ret = qemu_chr_fe_read_all(s->chr_in, recv_buf, len);
>> + if (ret != len) {
>> + error_report("filter-redirector recv buf failed");
>> + g_free(recv_buf);
>> + return;
>> + }
>> +
>> + ret = qemu_net_queue_send(s->incoming_queue, nf->netdev,
>> + 0, (const uint8_t *)recv_buf, len, NULL);
>> + g_free(recv_buf);
>> + if (ret < 0) {
>> + error_report("filter-redirector out to guest failed");
> "guest" is inaccurate here, what if queue=rx?
indev is not influenced by queue=rx/tx/all, so it always redirect to guest.
>
>> + }
>> + } else {
>> + error_report("filter-redirector recv len failed");
>> + }
>> +}
>> +
>> +static void filter_redirector_setup(NetFilterState *nf, Error **errp)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(nf);
>> +
>> + if (!s->indev && !s->outdev) {
>> + error_setg(errp, "filter redirector needs 'indev' or "
>> + "'outdev' at least one property set");
>> + return;
>> + }
>> +
>> + if (s->indev) {
>> + s->chr_in = qemu_chr_find(s->indev);
>> + if (s->chr_in == NULL) {
>> + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
>> + "IN Device '%s' not found", s->indev);
>> + return;
>> + }
>> +
>> + qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
>> + redirector_chr_read, NULL, nf);
>> + }
>> +
>> + if (s->outdev) {
>> + s->chr_out = qemu_chr_find(s->outdev);
>> + if (s->chr_out == NULL) {
>> + error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
>> + "OUT Device '%s' not found", s->outdev);
>> + return;
>> + }
>> + }
>> + s->incoming_queue = qemu_new_net_queue(qemu_netfilter_pass_to_next, nf);
>> +}
>> +
>> +static void filter_redirector_class_init(ObjectClass *oc, void *data)
>> +{
>> + NetFilterClass *nfc = NETFILTER_CLASS(oc);
>> +
>> + nfc->setup = filter_redirector_setup;
>> + nfc->cleanup = filter_redirector_cleanup;
>> + nfc->receive_iov = filter_redirector_receive_iov;
>> +}
>> +
>> +static char *filter_redirector_get_indev(Object *obj, Error **errp)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(obj);
>> +
>> + return g_strdup(s->indev);
>> +}
>> +
>> +static void
>> +filter_redirector_set_indev(Object *obj, const char *value, Error **errp)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(obj);
>> +
>> + g_free(s->indev);
>> + s->indev = g_strdup(value);
>> +}
>> +
>> +static char *filter_redirector_get_outdev(Object *obj, Error **errp)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(obj);
>> +
>> + return g_strdup(s->outdev);
>> +}
>> +
>> +static void
>> +filter_redirector_set_outdev(Object *obj, const char *value, Error **errp)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(obj);
>> +
>> + g_free(s->outdev);
>> + s->outdev = g_strdup(value);
>> +}
>> +
>> +static void filter_redirector_init(Object *obj)
>> +{
>> + object_property_add_str(obj, "indev", filter_redirector_get_indev,
>> + filter_redirector_set_indev, NULL);
>> + object_property_add_str(obj, "outdev", filter_redirector_get_outdev,
>> + filter_redirector_set_outdev, NULL);
>> +}
>> +
>> +static void filter_redirector_fini(Object *obj)
>> +{
>> + RedirectorState *s = FILTER_REDIRECTOR(obj);
>> +
>> + g_free(s->indev);
>> + g_free(s->outdev);
>> +}
>> +
>> +static const TypeInfo filter_redirector_info = {
>> + .name = TYPE_FILTER_REDIRECTOR,
>> + .parent = TYPE_NETFILTER,
>> + .class_init = filter_redirector_class_init,
>> + .instance_init = filter_redirector_init,
>> + .instance_finalize = filter_redirector_fini,
>> + .instance_size = sizeof(RedirectorState),
>> +};
>> +
>> +static void register_types(void)
>> +{
>> + type_register_static(&filter_redirector_info);
>> +}
>> +
>> +type_init(register_types);
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index f31a240..1f796ed 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -3745,6 +3745,12 @@ queue @var{all|rx|tx} is an option that can be applied to any netfilter.
>> @option{tx}: the filter is attached to the transmit queue of the netdev,
>> where it will receive packets sent by the netdev.
>>
>> +@item -object filter-redirector,id=@var{id},netdev=@var{netdevid},indev=@var{chardevid},outdev=@var{chardevid}[,queue=@var{all|rx|tx}]
>> +
>> +filter-redirector on netdev @var{netdevid},redirector can redirect filter's net packet to outdev.
>> +and redirect indev's packet to filter.
> Exceeds 80 characters limit. And need more work. e.g:
>
> - Need to differs outdev id from indev id.
> - Need to clarify at least one of outdev and indev needs to be set
> - We're in fact redirect packet between chardev and netdev's queue (not
> filter).
OK, I will add that comments in next version.
>> +queue @var{all|rx|tx} is an option that can be applied to filter-redirector.
> This line is unnecessary, we've already had
>
> "
> queue @var{all|rx|tx} is an option that can be applied to any netfilter.
> "
OK, I will remove it.
Thanks
zhangchen
>> +
>> @item -object filter-dump,id=@var{id},netdev=@var{dev},file=@var{filename}][,maxlen=@var{len}]
>>
>> Dump the network traffic on netdev @var{dev} to the file specified by
>> diff --git a/vl.c b/vl.c
>> index f043009..4a9a9a0 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -2801,7 +2801,8 @@ static bool object_create_initial(const char *type)
>> * they depend on netdevs already existing
>> */
>> if (g_str_equal(type, "filter-buffer") ||
>> - g_str_equal(type, "filter-dump")) {
>> + g_str_equal(type, "filter-dump") ||
>> + g_str_equal(type, "filter-redirector")) {
>> return false;
>> }
>>
>
>
> .
>
--
Thanks
zhangchen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-18 7:50 ` Zhang Chen
@ 2016-02-24 3:39 ` Jason Wang
2016-02-24 9:03 ` Zhang Chen
0 siblings, 1 reply; 8+ messages in thread
From: Jason Wang @ 2016-02-24 3:39 UTC (permalink / raw)
To: Zhang Chen, qemu devel
Cc: zhanghailiang, Li Zhijian, Gui jianfeng, eddie.dong,
Dr. David Alan Gilbert, Yang Hongyang
On 02/18/2016 03:50 PM, Zhang Chen wrote:
>
>
> On 02/18/2016 10:41 AM, Jason Wang wrote:
>>
>> On 02/05/2016 02:50 PM, Zhang Chen wrote:
>>> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>>
>>> Filter-redirector is a netfilter plugin.
>>> It gives qemu the ability to redirect net packet.
>>> redirector can redirect filter's net packet to outdev.
>>> and redirect indev's packet to filter.
>>>
>>> filter
>>> +
>>> |
>>> |
>>> redirector |
>>> +-------------------------+
>>> | | |
>>> | | |
>>> | | |
>>> indev +----------------+ +----------------> outdev
>>> | | |
>>> | | |
>>> | | |
>>> +-------------------------+
>>> |
>>> |
>>> v
>>> filter
>
> v
>
> change it to filter ........ filter ...... guest
> It's may more clearly expressed.
>
>>> usage:
>>>
>>> -netdev tap,id=hn0
>>> -chardev socket,id=s0,host=ip_primary,port=X,server,nowait
>>> -chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
>>> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1
>>>
>>> Signed-off-by: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>>> ---
>> Thanks a lot for the patch. Like mirror, let's design a unit-test for
>> this. And what's more, is there any chance to unify the codes? (At least
>> parts of the codes could be reused).
>
> We can make filter-redirector based on filter-mirror.
> if you want to use redirector ,you must open mirror before.
> like this:
>
> -netdev tap,id=hn0
> -chardev socket,id=mirror0,host=ip_primary,port=X,server,nowait
> -filter-mirror,id=m0,netdev=hn0,queue=tx/rx/all,redirector=on,outdev=mirror0
>
> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0
>
> How about this?
This looks like a burden for user who just want to use redirector. Maybe
we can do :
- Still two type of filters but sharing a single state.
- Using a internal flag to differ mirrors from redirectors?
>
>
>>> net/Makefile.objs | 1 +
>>> net/filter-redirector.c | 245
>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>> qemu-options.hx | 6 ++
>>> vl.c | 3 +-
>>> 4 files changed, 254 insertions(+), 1 deletion(-)
>>> create mode 100644 net/filter-redirector.c
>>>
>>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>>> index 5fa2f97..f4290a5 100644
>>> --- a/net/Makefile.objs
>>> +++ b/net/Makefile.objs
>>> @@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
>>> common-obj-$(CONFIG_NETMAP) += netmap.o
>>> common-obj-y += filter.o
>>> common-obj-y += filter-buffer.o
>>> +common-obj-y += filter-redirector.o
>>> diff --git a/net/filter-redirector.c b/net/filter-redirector.c
>>> new file mode 100644
>>> index 0000000..364e463
>>> --- /dev/null
>>> +++ b/net/filter-redirector.c
>>> @@ -0,0 +1,245 @@
>>> +/*
>>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>>> + * Copyright (c) 2016 FUJITSU LIMITED
>>> + * Copyright (c) 2016 Intel Corporation
>>> + *
>>> + * Author: Zhang Chen <zhangchen.fnst@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/net.h"
>>> +#include "qemu-common.h"
>>> +#include "qapi/qmp/qerror.h"
>>> +#include "qapi-visit.h"
>>> +#include "qom/object.h"
>>> +#include "qemu/main-loop.h"
>>> +#include "qemu/error-report.h"
>>> +#include "trace.h"
>>> +#include "sysemu/char.h"
>>> +#include "qemu/iov.h"
>>> +#include "qemu/sockets.h"
>>> +
>>> +#define FILTER_REDIRECTOR(obj) \
>>> + OBJECT_CHECK(RedirectorState, (obj), TYPE_FILTER_REDIRECTOR)
>>> +
>>> +#define TYPE_FILTER_REDIRECTOR "filter-redirector"
>>> +#define REDIRECT_HEADER_LEN sizeof(uint32_t)
>>> +
>>> +typedef struct RedirectorState {
>>> + NetFilterState parent_obj;
>>> + NetQueue *incoming_queue;/* guest normal net queue */
>> The comment looks unless and maybe even wrong when queue=rx?
>
> We design redirector that indev's data always be passed to guest finally.
> so, It's no relation between the queue=rx/tx/all. just related to
> indev = xxx.
> we need incoming_queue to inject packet from indev.
So what happens if queue=rx or you want to forbid queue=rx for redirector?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-24 3:39 ` Jason Wang
@ 2016-02-24 9:03 ` Zhang Chen
2016-02-29 7:11 ` Jason Wang
0 siblings, 1 reply; 8+ messages in thread
From: Zhang Chen @ 2016-02-24 9:03 UTC (permalink / raw)
To: Jason Wang, qemu devel
Cc: zhanghailiang, Li Zhijian, Gui jianfeng, eddie.dong,
Dr. David Alan Gilbert, Yang Hongyang
On 02/24/2016 11:39 AM, Jason Wang wrote:
>
> On 02/18/2016 03:50 PM, Zhang Chen wrote:
>>
>> On 02/18/2016 10:41 AM, Jason Wang wrote:
>>> On 02/05/2016 02:50 PM, Zhang Chen wrote:
>>>> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>>>
>>>> Filter-redirector is a netfilter plugin.
>>>> It gives qemu the ability to redirect net packet.
>>>> redirector can redirect filter's net packet to outdev.
>>>> and redirect indev's packet to filter.
>>>>
>>>> filter
>>>> +
>>>> |
>>>> |
>>>> redirector |
>>>> +-------------------------+
>>>> | | |
>>>> | | |
>>>> | | |
>>>> indev +----------------+ +----------------> outdev
>>>> | | |
>>>> | | |
>>>> | | |
>>>> +-------------------------+
>>>> |
>>>> |
>>>> v
>>>> filter
>> v
>>
>> change it to filter ........ filter ...... guest
>> It's may more clearly expressed.
>>
>>>> usage:
>>>>
>>>> -netdev tap,id=hn0
>>>> -chardev socket,id=s0,host=ip_primary,port=X,server,nowait
>>>> -chardev socket,id=s1,host=ip_primary,port=Y,server,nowait
>>>> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0,outdev=s1
>>>>
>>>> Signed-off-by: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>>>> ---
>>> Thanks a lot for the patch. Like mirror, let's design a unit-test for
>>> this. And what's more, is there any chance to unify the codes? (At least
>>> parts of the codes could be reused).
>> We can make filter-redirector based on filter-mirror.
>> if you want to use redirector ,you must open mirror before.
>> like this:
>>
>> -netdev tap,id=hn0
>> -chardev socket,id=mirror0,host=ip_primary,port=X,server,nowait
>> -filter-mirror,id=m0,netdev=hn0,queue=tx/rx/all,redirector=on,outdev=mirror0
>>
>> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,indev=s0
>>
>> How about this?
> This looks like a burden for user who just want to use redirector. Maybe
> we can do :
>
> - Still two type of filters but sharing a single state.
> - Using a internal flag to differ mirrors from redirectors?
Good idea~ I will change it in next version.
>
>>
>>>> net/Makefile.objs | 1 +
>>>> net/filter-redirector.c | 245
>>>> ++++++++++++++++++++++++++++++++++++++++++++++++
>>>> qemu-options.hx | 6 ++
>>>> vl.c | 3 +-
>>>> 4 files changed, 254 insertions(+), 1 deletion(-)
>>>> create mode 100644 net/filter-redirector.c
>>>>
>>>> diff --git a/net/Makefile.objs b/net/Makefile.objs
>>>> index 5fa2f97..f4290a5 100644
>>>> --- a/net/Makefile.objs
>>>> +++ b/net/Makefile.objs
>>>> @@ -15,3 +15,4 @@ common-obj-$(CONFIG_VDE) += vde.o
>>>> common-obj-$(CONFIG_NETMAP) += netmap.o
>>>> common-obj-y += filter.o
>>>> common-obj-y += filter-buffer.o
>>>> +common-obj-y += filter-redirector.o
>>>> diff --git a/net/filter-redirector.c b/net/filter-redirector.c
>>>> new file mode 100644
>>>> index 0000000..364e463
>>>> --- /dev/null
>>>> +++ b/net/filter-redirector.c
>>>> @@ -0,0 +1,245 @@
>>>> +/*
>>>> + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
>>>> + * Copyright (c) 2016 FUJITSU LIMITED
>>>> + * Copyright (c) 2016 Intel Corporation
>>>> + *
>>>> + * Author: Zhang Chen <zhangchen.fnst@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/net.h"
>>>> +#include "qemu-common.h"
>>>> +#include "qapi/qmp/qerror.h"
>>>> +#include "qapi-visit.h"
>>>> +#include "qom/object.h"
>>>> +#include "qemu/main-loop.h"
>>>> +#include "qemu/error-report.h"
>>>> +#include "trace.h"
>>>> +#include "sysemu/char.h"
>>>> +#include "qemu/iov.h"
>>>> +#include "qemu/sockets.h"
>>>> +
>>>> +#define FILTER_REDIRECTOR(obj) \
>>>> + OBJECT_CHECK(RedirectorState, (obj), TYPE_FILTER_REDIRECTOR)
>>>> +
>>>> +#define TYPE_FILTER_REDIRECTOR "filter-redirector"
>>>> +#define REDIRECT_HEADER_LEN sizeof(uint32_t)
>>>> +
>>>> +typedef struct RedirectorState {
>>>> + NetFilterState parent_obj;
>>>> + NetQueue *incoming_queue;/* guest normal net queue */
>>> The comment looks unless and maybe even wrong when queue=rx?
>> We design redirector that indev's data always be passed to guest finally.
>> so, It's no relation between the queue=rx/tx/all. just related to
>> indev = xxx.
>> we need incoming_queue to inject packet from indev.
> So what happens if queue=rx or you want to forbid queue=rx for redirector?
>
If queue=rx, filter-redirector will get the packet that guest send, then
redirect
to outdev(if none, do nothing). but queue=rx/tx/all not related to
indev. please
look the flow chart below. queue=xxx just work for one way(filter->outdev).
filter
+
|
|
redirector |
+-------------------------+
| | |
| | |
| | |
indev +----------------+ +----------------> outdev
| | |
| | |
| | |
+-------------------------+
|
|
v
filter
|
|
v
filter ........ filter ...... guest
>
> .
>
--
Thanks
zhangchen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-24 9:03 ` Zhang Chen
@ 2016-02-29 7:11 ` Jason Wang
2016-02-29 12:33 ` Zhang Chen
0 siblings, 1 reply; 8+ messages in thread
From: Jason Wang @ 2016-02-29 7:11 UTC (permalink / raw)
To: Zhang Chen, qemu devel
Cc: zhanghailiang, Li Zhijian, Gui jianfeng, eddie.dong,
Dr. David Alan Gilbert, Yang Hongyang
On 02/24/2016 05:03 PM, Zhang Chen wrote:
>
> If queue=rx, filter-redirector will get the packet that guest send,
> then redirect
> to outdev(if none, do nothing). but queue=rx/tx/all not related to
> indev. please
> look the flow chart below. queue=xxx just work for one
> way(filter->outdev).
>
> filter
> +
> |
> |
> redirector |
> +-------------------------+
> | | |
> | | |
> | | |
> indev +----------------+ +----------------> outdev
> | | |
> | | |
> | | |
> +-------------------------+
> |
> |
> v
> filter
>
> |
>
> |
>
> v
> filter ........ filter ...... guest
>
This looks a violation on the assumption of current filter behavior.
Each filter should only talk to the 'next' or 'prev' filter on the chain
(depends on the direction) or netdev when queue=rx or netdev's peer when
queue=tx.
And in fact there's subtle differences with your patch:
When queue='all' since you force nf->netdev as sender, direction is
NET_FILTER_DIRECTION_TX, the packet will be passed to 'next' filter on
the chain.
When queue='rx', direction is NET_FILTER_DIRECTION_RX, the packet will
be pass to 'prev' filter on the chain.
So as you can see, 'all' is ambiguous here. I think we should keep
current behavior by redirecting traffic to netdev when queue='rx'. For
queue='all', maybe we need redirect the traffic to both netdev and
netdev's peer.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-29 7:11 ` Jason Wang
@ 2016-02-29 12:33 ` Zhang Chen
2016-03-02 5:41 ` Jason Wang
0 siblings, 1 reply; 8+ messages in thread
From: Zhang Chen @ 2016-02-29 12:33 UTC (permalink / raw)
To: Jason Wang, qemu devel
Cc: zhanghailiang, Li Zhijian, Gui jianfeng, eddie.dong,
Dr. David Alan Gilbert, Yang Hongyang
On 02/29/2016 03:11 PM, Jason Wang wrote:
>
> On 02/24/2016 05:03 PM, Zhang Chen wrote:
>> If queue=rx, filter-redirector will get the packet that guest send,
>> then redirect
>> to outdev(if none, do nothing). but queue=rx/tx/all not related to
>> indev. please
>> look the flow chart below. queue=xxx just work for one
>> way(filter->outdev).
>>
>> filter
>> +
>> |
>> |
>> redirector |
>> +-------------------------+
>> | | |
>> | | |
>> | | |
>> indev +----------------+ +----------------> outdev
>> | | |
>> | | |
>> | | |
>> +-------------------------+
>> |
>> |
>> v
>> filter
>>
>> |
>>
>> |
>>
>> v
>> filter ........ filter ...... guest
>>
> This looks a violation on the assumption of current filter behavior.
> Each filter should only talk to the 'next' or 'prev' filter on the chain
> (depends on the direction) or netdev when queue=rx or netdev's peer when
> queue=tx.
>
> And in fact there's subtle differences with your patch:
>
> When queue='all' since you force nf->netdev as sender, direction is
> NET_FILTER_DIRECTION_TX, the packet will be passed to 'next' filter on
> the chain.
> When queue='rx', direction is NET_FILTER_DIRECTION_RX, the packet will
> be pass to 'prev' filter on the chain.
>
> So as you can see, 'all' is ambiguous here. I think we should keep
> current behavior by redirecting traffic to netdev when queue='rx'. For
> queue='all', maybe we need redirect the traffic to both netdev and
> netdev's peer.
>
>
OK, I will change usage to :
-filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,outdev=s1,indev=s0,in_direction=tx/rx
How about this?
I will fix it in V3.
Thanks
zhangchen
>
>
> .
>
--
Thanks
zhangchen
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector
2016-02-29 12:33 ` Zhang Chen
@ 2016-03-02 5:41 ` Jason Wang
0 siblings, 0 replies; 8+ messages in thread
From: Jason Wang @ 2016-03-02 5:41 UTC (permalink / raw)
To: Zhang Chen, qemu devel
Cc: zhanghailiang, Li Zhijian, Gui jianfeng, eddie.dong,
Dr. David Alan Gilbert, Yang Hongyang
On 02/29/2016 08:33 PM, Zhang Chen wrote:
>
>
> On 02/29/2016 03:11 PM, Jason Wang wrote:
>>
>> On 02/24/2016 05:03 PM, Zhang Chen wrote:
>>> If queue=rx, filter-redirector will get the packet that guest send,
>>> then redirect
>>> to outdev(if none, do nothing). but queue=rx/tx/all not related to
>>> indev. please
>>> look the flow chart below. queue=xxx just work for one
>>> way(filter->outdev).
>>>
>>> filter
>>> +
>>> |
>>> |
>>> redirector |
>>> +-------------------------+
>>> | | |
>>> | | |
>>> | | |
>>> indev +----------------+ +----------------> outdev
>>> | | |
>>> | | |
>>> | | |
>>> +-------------------------+
>>> |
>>> |
>>> v
>>> filter
>>>
>>> |
>>>
>>> |
>>>
>>> v
>>> filter ........ filter ...... guest
>>>
>> This looks a violation on the assumption of current filter behavior.
>> Each filter should only talk to the 'next' or 'prev' filter on the chain
>> (depends on the direction) or netdev when queue=rx or netdev's peer when
>> queue=tx.
>>
>> And in fact there's subtle differences with your patch:
>>
>> When queue='all' since you force nf->netdev as sender, direction is
>> NET_FILTER_DIRECTION_TX, the packet will be passed to 'next' filter on
>> the chain.
>> When queue='rx', direction is NET_FILTER_DIRECTION_RX, the packet will
>> be pass to 'prev' filter on the chain.
>>
>> So as you can see, 'all' is ambiguous here. I think we should keep
>> current behavior by redirecting traffic to netdev when queue='rx'. For
>> queue='all', maybe we need redirect the traffic to both netdev and
>> netdev's peer.
>>
>>
>
> OK, I will change usage to :
>
> -filter-redirector,id=r0,netdev=hn0,queue=tx/rx/all,outdev=s1,indev=s0,in_direction=tx/rx
>
> How about this?
Looks like in_direction complicates the issue and is unnecessary. In
fact, it could be achieved by having another redirector.
>
> I will fix it in V3.
>
> Thanks
> zhangchen
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2016-03-02 5:42 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-05 6:50 [Qemu-devel] [PATCH] net/filter-redirector:Add filter-redirector Zhang Chen
2016-02-18 2:41 ` Jason Wang
2016-02-18 7:50 ` Zhang Chen
2016-02-24 3:39 ` Jason Wang
2016-02-24 9:03 ` Zhang Chen
2016-02-29 7:11 ` Jason Wang
2016-02-29 12:33 ` Zhang Chen
2016-03-02 5:41 ` Jason Wang
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.