qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v9 09/10] netfilter: add a netbuffer filter


From: Yang Hongyang
Subject: [Qemu-devel] [PATCH v9 09/10] netfilter: add a netbuffer filter
Date: Tue, 1 Sep 2015 17:06:22 +0800

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.
The dummy filter is replaced by this filter.

Usage:
 -netdev tap,id=bn0
 -netfilter buffer,id=f0,netdev=bn0,chain=in,interval=1000

NOTE:
 the scale of interval is microsecond.

Signed-off-by: Yang Hongyang <address@hidden>
---
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 | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 net/filter.c        |   3 +-
 net/filters.h       |  10 +----
 qapi-schema.json    |  20 ++++++---
 5 files changed, 143 insertions(+), 16 deletions(-)
 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..93f31c6
--- /dev/null
+++ b/net/filter-buffer.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include "net/filter.h"
+#include "net/queue.h"
+#include "filters.h"
+#include "qemu-common.h"
+#include "qemu/timer.h"
+#include "qemu/iov.h"
+#include "qapi/qmp/qerror.h"
+
+typedef struct FilterBufferState {
+    NetFilterState nf;
+    NetQueue *incoming_queue;
+    uint32_t interval;
+    QEMUTimer release_timer;
+} FilterBufferState;
+
+static void filter_buffer_flush(NetFilterState *nf)
+{
+    FilterBufferState *s = DO_UPCAST(FilterBufferState, nf, nf);
+    NetQueue *queue = s->incoming_queue;
+    NetPacket *packet, *next;
+
+    QTAILQ_FOREACH_SAFE(packet, &queue->packets, entry, next) {
+        QTAILQ_REMOVE(&queue->packets, packet, entry);
+        queue->nq_count--;
+
+        if (packet->sender && packet->sender->peer) {
+            qemu_netfilter_pass_to_next(nf, packet);
+        }
+
+        /*
+         * now that we have passed the packet to next filter (or there's
+         * no receiver). If it's queued by receiver's incoming_queue, there
+         * will be a copy of the packet->data, so simply free this packet
+         * now.
+         */
+        g_free(packet);
+    }
+}
+
+static void filter_buffer_release_timer(void *opaque)
+{
+    FilterBufferState *s = opaque;
+    filter_buffer_flush(&s->nf);
+    timer_mod(&s->release_timer,
+              qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+}
+
+/* filter APIs */
+static ssize_t filter_buffer_receive_iov(NetFilterState *nf,
+                                         NetClientState *sender,
+                                         unsigned flags,
+                                         const struct iovec *iov,
+                                         int iovcnt,
+                                         NetPacketSent *sent_cb)
+{
+    FilterBufferState *s = DO_UPCAST(FilterBufferState, nf, nf);
+    NetQueue *queue = s->incoming_queue;
+
+    qemu_net_queue_append_iov(queue, sender, flags, iov, iovcnt, sent_cb);
+    return iov_size(iov, iovcnt);
+}
+
+static void filter_buffer_cleanup(NetFilterState *nf)
+{
+    FilterBufferState *s = DO_UPCAST(FilterBufferState, nf, nf);
+
+    if (s->interval) {
+        timer_del(&s->release_timer);
+    }
+
+    /* flush packets */
+    filter_buffer_flush(nf);
+    g_free(s->incoming_queue);
+    return;
+}
+
+static NetFilterInfo net_filter_buffer_info = {
+    .type = NET_FILTER_TYPE_BUFFER,
+    .size = sizeof(FilterBufferState),
+    .receive_iov = filter_buffer_receive_iov,
+    .cleanup = filter_buffer_cleanup,
+};
+
+int net_init_filter_buffer(const NetFilter *netfilter, const char *name,
+                           int chain, NetClientState *netdev, Error **errp)
+{
+    NetFilterState *nf;
+    FilterBufferState *s;
+    const NetFilterBufferOptions *bufferopt;
+    int interval;
+
+    assert(netfilter->kind == NET_FILTER_TYPE_BUFFER);
+    bufferopt = netfilter->buffer;
+    interval = bufferopt->has_interval ? bufferopt->interval : 0;
+    /*
+     * this check should be dropped when there're VM FT solutions like MC
+     * or COLO use this filter to release packets on demand.
+     */
+    if (!interval) {
+        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "interval",
+                   "a non-zero interval");
+        return -1;
+    }
+
+    nf = qemu_new_net_filter(&net_filter_buffer_info, netdev, name, chain);
+    s = DO_UPCAST(FilterBufferState, nf, nf);
+    s->incoming_queue = qemu_new_net_queue(nf);
+    s->interval = interval;
+    if (s->interval) {
+        timer_init_us(&s->release_timer, QEMU_CLOCK_VIRTUAL,
+                      filter_buffer_release_timer, s);
+        timer_mod(&s->release_timer,
+                  qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
+    }
+
+    return 0;
+}
diff --git a/net/filter.c b/net/filter.c
index 570813c..12d52e5 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -21,6 +21,7 @@
 #include "net/vhost_net.h"
 #include "filters.h"
 #include "net/queue.h"
+#include "filters.h"
 
 static QTAILQ_HEAD(, NetFilterState) net_filters;
 
@@ -214,7 +215,7 @@ typedef int (NetFilterInit)(const NetFilter *netfilter,
 
 static
 NetFilterInit * const net_filter_init_fun[NET_FILTER_TYPE_MAX] = {
-    [NET_FILTER_TYPE_DUMMY] = net_init_filter_dummy,
+    [NET_FILTER_TYPE_BUFFER] = net_init_filter_buffer,
 };
 
 static int net_filter_init1(const NetFilter *netfilter, Error **errp)
diff --git a/net/filters.h b/net/filters.h
index 7c1f30d..8dd9970 100644
--- a/net/filters.h
+++ b/net/filters.h
@@ -11,13 +11,7 @@
 #include "net/net.h"
 #include "net/filter.h"
 
-int net_init_filter_dummy(const NetFilter *netfilter, const char *name,
-                          int chain, NetClientState *netdev, Error **errp);
-
-int net_init_filter_dummy(const NetFilter *netfilter, const char *name,
-                          int chain, NetClientState *netdev, Error **errp)
-{
-    return 0;
-}
+int net_init_filter_buffer(const NetFilter *netfilter, const char *name,
+                           int chain, NetClientState *netdev, Error **errp);
 
 #endif /* QEMU_NET_FILTERS_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index d961ac8..0e8dc17 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2566,14 +2566,20 @@
 { 'command': 'netfilter-del', 'data': {'id': 'str'} }
 
 ##
-# @NetFilterDummyOptions:
+# @NetFilterBufferOptions
 #
-# An dummy filter for network backend
+# a netbuffer filter for network backend.
 #
-# Since: 2.5
+# @interval: #optional release packets by interval, if no interval supplied,
+#            packets will be buffered forever unless internal APIs been called
+#            to release the packets or filter been removed. Use with caution.
+#            scale: microsecond
+#
+# Since 2.5
 ##
-{ 'struct': 'NetFilterDummyOptions',
-  'data': { } }
+{ 'struct': 'NetFilterBufferOptions',
+  'data': {
+    '*interval':     'uint32' } }
 
 ##
 # @NetFilterType:
@@ -2583,7 +2589,7 @@
 # Since: 2.5
 ##
 { 'enum': 'NetFilterType',
-  'data': ['dummy'] }
+  'data': ['buffer'] }
 
 ##
 # @NetFilterBase
@@ -2623,7 +2629,7 @@
   'base': 'NetFilterBase',
   'discriminator': 'type',
   'data': {
-    'dummy': 'NetFilterDummyOptions' } }
+    'buffer': 'NetFilterBufferOptions' } }
 
 ##
 # @InetSocketAddress
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]