On 03/02/2016 02:31 PM, Jason Wang wrote:

On 02/29/2016 08:23 PM, Zhang Chen wrote:
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
                       filter------> guest
As we've discussed, the actual destination should depend on "queue"
parameter. E.g if queue = rx, the destination should be netdev not guest.

OK, I will fix it in V3


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;
Why not use qemu_chr_fe_read_all() here?

And what's better, instead of busy waiting/reading. You can save the
partial packet in a temporary buffer, and do not forward it after it has
been completely received.


OK, will fix in V3

Thanks
zhangchen

+    }
+
+    memcpy(&len, buf, sizeof(len));
+    len = ntohl(len);
+
+    if (len > 0 && len < NET_BUFSIZE) {
+        recv_buf = g_malloc(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);
As I replied in last version. Sender should be chose depending on
'queues'. When 'queue=rx' sender should be be netdev's peer.



.


--
Thanks
zhangchen




Reply via email to