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: Zhang Chen <zhangchen.f...@cn.fujitsu.com>
Signed-off-by: Wen Congyang <we...@cn.fujitsu.com>
---
net/Makefile.objs | 1 +
net/filter-redirector.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++
qemu-options.hx | 8 ++
vl.c | 3 +-
4 files changed, 227 insertions(+), 1 deletion(-)
create mode 100644 net/filter-redirector.c
diff --git a/net/Makefile.objs b/net/Makefile.objs
index b7c22fd..8af9932 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -16,3 +16,4 @@ common-obj-$(CONFIG_NETMAP) += netmap.o
common-obj-y += filter.o
common-obj-y += filter-buffer.o
common-obj-y += filter-mirror.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..d0eb76d
--- /dev/null
+++ b/net/filter-redirector.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Copyright (c) 2016 Intel Corporation
+ *
+ * Author: Zhang Chen <zhangchen.f...@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-traffic.h"
+
+#define FILTER_REDIRECTOR(obj) \
+ OBJECT_CHECK(TrafficState, (obj), TYPE_FILTER_REDIRECTOR)
+
+#define TYPE_FILTER_REDIRECTOR "filter-redirector"
+#define REDIRECT_HEADER_LEN sizeof(uint32_t)
+
+static int filter_redirector_send(NetFilterState *nf,
+ const struct iovec *iov,
+ int iovcnt)
+{
+ return filter_traffic_send(nf, iov, iovcnt);
+}
+
+static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
+{
+ TrafficState *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);
+ } else {
+ return 0;
+ }
+}
+
+static void filter_redirector_cleanup(NetFilterState *nf)
+{
+ TrafficState *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;
+ TrafficState *s = FILTER_REDIRECTOR(nf);
+ uint32_t len;
+ int ret = 0;
+ uint8_t *recv_buf;
+ int offset = size;
+
+ while (offset < REDIRECT_HEADER_LEN) {
+ ret = s->chr_in->chr_sync_read(s->chr_in, (uint8_t *)buf + offset,
+ REDIRECT_HEADER_LEN - offset);
+ if (ret == -1 && errno == EAGAIN) {
+ g_usleep(100);
+ }
+ offset += ret;