* [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter
@ 2015-10-07 3:52 Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 01/10] vl.c: init delayed object after net_init_clients Yang Hongyang
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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-v12
Usage:
-netdev tap,id=bn0
-device e1000,netdev=bn0
-object filter-buffer,id=f0,netdev=bn0,queue=rx,interval=1000
dynamically add/remove netfilters:
object_add filter-buffer,id=f0,netdev=bn0,queue=rx,interval=1000
object_del f0
NOTE:
interval is in microseconds and can't be omiited.
queue is optional, and is one of rx|tx|all, default is "all". See
enum NetFilterDirection for detail.
v13:
- Address Markus's comments.
v12:
- Address Markus's comments.
- Rebased to the latest master.
v11:
- address Jason&Daniel's comments
- add multiqueue support, the last 2 patches
- rebased to the latest master
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):
vl.c: init delayed object after net_init_clients
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 | 77 ++++++++++++++++
include/net/net.h | 6 +-
include/net/queue.h | 20 ++++-
include/qemu/typedefs.h | 1 +
net/Makefile.objs | 2 +
net/filter-buffer.c | 186 ++++++++++++++++++++++++++++++++++++++
net/filter.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net.c | 121 +++++++++++++++++++------
net/queue.c | 24 +++--
qapi-schema.json | 20 +++++
qemu-options.hx | 17 ++++
tests/.gitignore | 1 +
tests/Makefile | 2 +
tests/test-netfilter.c | 200 +++++++++++++++++++++++++++++++++++++++++
vl.c | 17 ++--
15 files changed, 878 insertions(+), 49 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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 01/10] vl.c: init delayed object after net_init_clients
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object Yang Hongyang
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
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>
---
vl.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/vl.c b/vl.c
index f2bd8d2..366f38f 100644
--- a/vl.c
+++ b/vl.c
@@ -2767,6 +2767,7 @@ static bool object_create_initial(const char *type)
if (g_str_equal(type, "rng-egd")) {
return false;
}
+ /* TODO: implement netfilters */
return true;
}
@@ -4286,12 +4287,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)) {
@@ -4397,6 +4392,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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 01/10] vl.c: init delayed object after net_init_clients Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 13:19 ` Markus Armbruster
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 03/10] netfilter: hook packets before net queue send Yang Hongyang
` (7 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
---
include/net/filter.h | 61 +++++++++++++++++++++
include/net/net.h | 1 +
include/qemu/typedefs.h | 1 +
net/Makefile.objs | 1 +
net/filter.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++
net/net.c | 7 +++
qapi-schema.json | 20 +++++++
7 files changed, 229 insertions(+)
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..be27dee
--- /dev/null
+++ b/include/net/filter.h
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+ /* optional */
+ FilterSetup *setup;
+ FilterCleanup *cleanup;
+ /* mandatory */
+ FilterReceiveIOV *receive_iov;
+} NetFilterClass;
+
+
+struct NetFilterState {
+ /* private */
+ Object parent;
+
+ /* protected */
+ char *netdev_id;
+ NetClientState *netdev;
+ NetFilterDirection direction;
+ 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 3a835ff..ee1ce1d 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..d406259
--- /dev/null
+++ b/net/filter.c
@@ -0,0 +1,138 @@
+/*
+ * 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 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_direction(Object *obj, Error **errp G_GNUC_UNUSED)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ return nf->direction;
+}
+
+static void netfilter_set_direction(Object *obj, int direction, Error **errp)
+{
+ NetFilterState *nf = NETFILTER(obj);
+ nf->direction = direction;
+}
+
+static void netfilter_init(Object *obj)
+{
+ object_property_add_str(obj, "netdev",
+ netfilter_get_netdev_id, netfilter_set_netdev_id,
+ NULL);
+ object_property_add_enum(obj, "queue", "NetFilterDirection",
+ NetFilterDirection_lookup,
+ netfilter_get_direction, netfilter_set_direction,
+ NULL);
+}
+
+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, "multiqueue 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(&nf->netdev->filters, nf, next);
+}
+
+static void netfilter_finalize(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);
+ }
+}
+
+static void netfilter_class_init(ObjectClass *oc, void *data)
+{
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+ ucc->complete = netfilter_complete;
+}
+
+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_finalize,
+ .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..033f4f3 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)
@@ -287,6 +288,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 +386,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 +398,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 8b0520c..a386605 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2588,6 +2588,26 @@
'opts': 'NetClientOptions' } }
##
+# @NetFilterDirection
+#
+# Indicates whether a netfilter is attached to a netdev's transmit queue or
+# receive queue or both.
+#
+# @all: the filter is attached both to the receive and the transmit
+# queue of the netdev (default).
+#
+# @rx: the filter is attached to the receive queue of the netdev,
+# where it will receive packets sent to the netdev.
+#
+# @tx: the filter is attached to the transmit queue of the netdev,
+# where it will receive packets sent by the netdev.
+#
+# Since 2.5
+##
+{ 'enum': 'NetFilterDirection',
+ 'data': [ 'all', 'rx', 'tx' ] }
+
+##
# @InetSocketAddress
#
# Captures a socket address or address range in the Internet namespace.
--
1.9.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v13 03/10] netfilter: hook packets before net queue send
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 01/10] vl.c: init delayed object after net_init_clients Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
include/net/filter.h | 8 +++++++
net/filter.c | 17 ++++++++++++++
net/net.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index be27dee..db035b6 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -58,4 +58,12 @@ struct NetFilterState {
QTAILQ_ENTRY(NetFilterState) next;
};
+ssize_t qemu_netfilter_receive(NetFilterState *nf,
+ NetFilterDirection direction,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb);
+
#endif /* QEMU_NET_FILTER_H */
diff --git a/net/filter.c b/net/filter.c
index d406259..147c57f 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -15,6 +15,23 @@
#include "net/vhost_net.h"
#include "qom/object_interfaces.h"
+ssize_t qemu_netfilter_receive(NetFilterState *nf,
+ NetFilterDirection direction,
+ NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ NetPacketSent *sent_cb)
+{
+ if (nf->direction == direction ||
+ nf->direction == NET_FILTER_DIRECTION_ALL) {
+ return NETFILTER_GET_CLASS(OBJECT(nf))->receive_iov(
+ nf, sender, flags, iov, iovcnt, sent_cb);
+ }
+
+ return 0;
+}
+
static char *netfilter_get_netdev_id(Object *obj, Error **errp)
{
NetFilterState *nf = NETFILTER(obj);
diff --git a/net/net.c b/net/net.c
index 033f4f3..e27643d 100644
--- a/net/net.c
+++ b/net/net.c
@@ -561,6 +561,44 @@ int qemu_can_send_packet(NetClientState *sender)
return 1;
}
+static ssize_t filter_receive_iov(NetClientState *nc,
+ NetFilterDirection direction,
+ 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) {
+ ret = qemu_netfilter_receive(nf, direction, sender, flags, iov,
+ iovcnt, sent_cb);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static ssize_t filter_receive(NetClientState *nc,
+ NetFilterDirection direction,
+ 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, direction, sender, flags, &iov, 1, sent_cb);
+}
+
ssize_t qemu_deliver_packet(NetClientState *sender,
unsigned flags,
const uint8_t *data,
@@ -632,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");
@@ -642,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_DIRECTION_TX,
+ sender, flags, buf, size, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
+ ret = filter_receive(sender->peer, NET_FILTER_DIRECTION_RX,
+ 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);
@@ -712,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_DIRECTION_TX, sender,
+ QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt, sent_cb);
+ if (ret) {
+ return ret;
+ }
+
+ ret = filter_receive_iov(sender->peer, NET_FILTER_DIRECTION_RX, 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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (2 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 03/10] netfilter: hook packets before net queue send Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
include/net/net.h | 5 -----
net/net.c | 51 ++++++++++++++++-----------------------------------
net/queue.c | 6 +++++-
3 files changed, 21 insertions(+), 41 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 e27643d..2f939f9 100644
--- a/net/net.c
+++ b/net/net.c
@@ -599,36 +599,6 @@ static ssize_t filter_receive(NetClientState *nc,
return filter_receive_iov(nc, direction, 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,25 @@ 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];
+ uint8_t buf[NET_BUFSIZE];
+ uint8_t *buffer;
size_t offset;
- offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
+ if (iovcnt == 1) {
+ buffer = iov[0].iov_base;
+ offset = iov[0].iov_len;
+ } else {
+ buffer = buf;
+ 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 +730,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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 05/10] net/queue: introduce NetQueueDeliverFunc
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (3 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@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 2f939f9..c0ebb13 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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 06/10] netfilter: add an API to pass the packet to next filter
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (4 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
include/net/filter.h | 7 +++++++
net/filter.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index db035b6..5639976 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -66,4 +66,11 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
int iovcnt,
NetPacketSent *sent_cb);
+/* 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 147c57f..5d5022f 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -14,6 +14,7 @@
#include "net/net.h"
#include "net/vhost_net.h"
#include "qom/object_interfaces.h"
+#include "qemu/iov.h"
ssize_t qemu_netfilter_receive(NetFilterState *nf,
NetFilterDirection direction,
@@ -32,6 +33,63 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf,
return 0;
}
+ssize_t qemu_netfilter_pass_to_next(NetClientState *sender,
+ unsigned flags,
+ const struct iovec *iov,
+ int iovcnt,
+ void *opaque)
+{
+ int ret = 0;
+ int direction;
+ 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->direction == NET_FILTER_DIRECTION_ALL) {
+ if (sender == nf->netdev) {
+ /* This packet is sent by netdev itself */
+ direction = NET_FILTER_DIRECTION_TX;
+ } else {
+ direction = NET_FILTER_DIRECTION_RX;
+ }
+ } else {
+ direction = nf->direction;
+ }
+
+ while (next) {
+ /*
+ * 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 = qemu_netfilter_receive(next, direction, 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) {
+ 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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 07/10] netfilter: print filter info associate with the netdev
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (5 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
` (2 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
include/net/filter.h | 1 +
net/filter.c | 20 ++++++++++++++++++++
net/net.c | 11 +++++++++++
3 files changed, 32 insertions(+)
diff --git a/include/net/filter.h b/include/net/filter.h
index 5639976..2deda36 100644
--- a/include/net/filter.h
+++ b/include/net/filter.h
@@ -55,6 +55,7 @@ struct NetFilterState {
char *netdev_id;
NetClientState *netdev;
NetFilterDirection direction;
+ char info_str[256];
QTAILQ_ENTRY(NetFilterState) next;
};
diff --git a/net/filter.c b/net/filter.c
index 5d5022f..326f2b5 100644
--- a/net/filter.c
+++ b/net/filter.c
@@ -15,6 +15,7 @@
#include "net/vhost_net.h"
#include "qom/object_interfaces.h"
#include "qemu/iov.h"
+#include "qapi/string-output-visitor.h"
ssize_t qemu_netfilter_receive(NetFilterState *nf,
NetFilterDirection direction,
@@ -134,6 +135,9 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
NetFilterClass *nfc = NETFILTER_GET_CLASS(uc);
int queues;
Error *local_err = NULL;
+ char *str, *info;
+ ObjectProperty *prop;
+ StringOutputVisitor *ov;
if (!nf->netdev_id) {
error_setg(errp, "Parameter 'netdev' is required");
@@ -167,6 +171,22 @@ static void netfilter_complete(UserCreatable *uc, Error **errp)
}
}
QTAILQ_INSERT_TAIL(&nf->netdev->filters, nf, next);
+
+ /* generate info str */
+ QTAILQ_FOREACH(prop, &OBJECT(nf)->properties, node) {
+ if (!strcmp(prop->name, "type")) {
+ continue;
+ }
+ ov = string_output_visitor_new(false);
+ object_property_get(OBJECT(nf), string_output_get_visitor(ov),
+ prop->name, errp);
+ str = string_output_get_string(ov);
+ string_output_visitor_cleanup(ov);
+ info = g_strdup_printf(",%s=%s", prop->name, str);
+ g_strlcat(nf->info_str, info, sizeof(nf->info_str));
+ g_free(str);
+ g_free(info);
+ }
}
static void netfilter_finalize(Object *obj)
diff --git a/net/net.c b/net/net.c
index c0ebb13..39af893 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1179,10 +1179,21 @@ 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%s\n",
+ object_get_canonical_path_component(OBJECT(nf)),
+ object_get_typename(OBJECT(nf)),
+ nf->info_str);
+ }
}
RxFilterInfoList *qmp_query_rx_filter(bool has_name, const char *name,
--
1.9.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v13 08/10] net/queue: export qemu_net_queue_append_iov
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (6 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 10/10] tests: add test cases for netfilter object Yang Hongyang
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@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] 13+ messages in thread
* [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (7 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
2015-10-07 13:25 ` Markus Armbruster
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 10/10] tests: add test cases for netfilter object Yang Hongyang
9 siblings, 1 reply; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 UTC (permalink / raw)
To: qemu-devel
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, armbru, stefanha,
Yang Hongyang
This filter is to buffer/release packets. Can be used when using
MicroCheckpointing or other Remus like VM FT solutions.
You can also use it to simulate network delay.
Usage:
-netdev tap,id=bn0
-object filter-buffer,id=f0,netdev=bn0,queue=rx,interval=1000
NOTE:
Interval is in microseconds, it can't be omitted currently, and can't be 0.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
net/Makefile.objs | 1 +
net/filter-buffer.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-options.hx | 17 +++++
vl.c | 6 +-
4 files changed, 209 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..336bdcc
--- /dev/null
+++ b/net/filter-buffer.c
@@ -0,0 +1,186 @@
+/*
+ * 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);
+
+ /*
+ * Note: filter_buffer_flush() drops packets that can't be sent
+ * TODO: We should leave them queued. But currently there's no way
+ * for the next filter or recivier to notify us that it can receive
+ * more packets.
+ */
+ filter_buffer_flush(nf);
+ /* Timer rearmed to fire again in s->interval microseconds. */
+ 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.
+ *
+ * FIXME: Even if the guest can't receive packets for some reasons,
+ * the filter can still accept packets until its internal queue is full.
+ * For example:
+ * For some reason, receiver could not receive more packets
+ * (.can_receive() returns zero). Without a filter, at most one packet
+ * will be queued in incoming queue and sender's poll will be disabled
+ * unit its sent_cb() was called. With a filter, it will keep receiving
+ * the packets without caring about the receiver. This is suboptimal.
+ * May need more thoughts (e.g keeping sent_cb).
+ */
+ 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);
+
+ /*
+ * We may want to accept zero interval when 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 armed to fire in s->interval microseconds. */
+ timer_mod(&s->release_timer,
+ qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 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' requires a positive value",
+ object_get_typename(obj), name);
+ 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 328404c..2485b94 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3643,6 +3643,23 @@ in PEM format, in filenames @var{ca-cert.pem}, @var{ca-crl.pem} (optional),
@var{server-cert.pem} (only servers), @var{server-key.pem} (only servers),
@var{client-cert.pem} (only clients), and @var{client-key.pem} (only clients).
+@item -object filter-buffer,id=@var{id},netdev=@var{netdevid},interval=@var{t}[,queue=@var{all|rx|tx}]
+
+Interval @var{t} can't be 0, this filter batches the packet delivery: all
+packets arriving in a given interval on netdev @var{netdevid} are delayed
+until the end of the interval. Interval is in microseconds.
+
+queue @var{all|rx|tx} is an option that can be applied to any netfilter.
+
+@option{all}: the filter is attached both to the receive and the transmit
+ queue of the netdev (default).
+
+@option{rx}: the filter is attached to the receive queue of the netdev,
+ where it will receive packets sent to the netdev.
+
+@option{tx}: the filter is attached to the transmit queue of the netdev,
+ where it will receive packets sent by the netdev.
+
@end table
ETEXI
diff --git a/vl.c b/vl.c
index 366f38f..c9b4f49 100644
--- a/vl.c
+++ b/vl.c
@@ -2767,7 +2767,11 @@ static bool object_create_initial(const char *type)
if (g_str_equal(type, "rng-egd")) {
return false;
}
- /* TODO: implement netfilters */
+
+ if (g_str_equal(type, "filter-buffer")) {
+ return false;
+ }
+
return true;
}
--
1.9.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v13 10/10] tests: add test cases for netfilter object
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
` (8 preceding siblings ...)
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-10-07 3:52 ` Yang Hongyang
9 siblings, 0 replies; 13+ messages in thread
From: Yang Hongyang @ 2015-10-07 3:52 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>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
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 a607bdd..65496aa 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -49,5 +49,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 e6474ba..78d5d0a 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -191,6 +191,7 @@ gcov-files-i386-y += hw/pci-host/q35.c
ifeq ($(CONFIG_VHOST_NET),y)
check-qtest-i386-$(CONFIG_LINUX) += tests/vhost-user-test$(EXESUF)
endif
+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))
@@ -437,6 +438,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 $(test-util-obj-y)
tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
+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..303deb7
--- /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',"
+ " 'queue': 'rx',"
+ " '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',"
+ " 'queue': 'rx',"
+ " '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',"
+ " 'queue': 'rx',"
+ " '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',"
+ " 'queue': 'rx',"
+ " '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',"
+ " 'queue': 'rx',"
+ " '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',"
+ " 'queue': 'rx',"
+ " '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] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object Yang Hongyang
@ 2015-10-07 13:19 ` Markus Armbruster
0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2015-10-07 13:19 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
stefanha
Yang Hongyang <yanghy@cn.fujitsu.com> writes:
> 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.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter Yang Hongyang
@ 2015-10-07 13:25 ` Markus Armbruster
0 siblings, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2015-10-07 13:25 UTC (permalink / raw)
To: Yang Hongyang
Cc: thuth, zhang.zhanghailiang, lizhijian, jasowang, qemu-devel,
stefanha
Yang Hongyang <yanghy@cn.fujitsu.com> writes:
> This filter is to buffer/release packets. Can be used when using
> MicroCheckpointing or other Remus like VM FT solutions.
> You can also use it to simulate network delay.
Would be nice to mention this doesn't actually delay individual packets.
Perhaps
You can also use it to crudely simulate network delay. Doesn't
actually delay individual packets, but batches them together, which
is a delay of sorts.
Could be touched up on commit.
>
> Usage:
> -netdev tap,id=bn0
> -object filter-buffer,id=f0,netdev=bn0,queue=rx,interval=1000
>
> NOTE:
> Interval is in microseconds, it can't be omitted currently, and can't be 0.
>
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> net/Makefile.objs | 1 +
> net/filter-buffer.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> qemu-options.hx | 17 +++++
> vl.c | 6 +-
> 4 files changed, 209 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..336bdcc
> --- /dev/null
> +++ b/net/filter-buffer.c
> @@ -0,0 +1,186 @@
> +/*
> + * 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);
> +
> + /*
> + * Note: filter_buffer_flush() drops packets that can't be sent
> + * TODO: We should leave them queued. But currently there's no way
> + * for the next filter or recivier to notify us that it can receive
You faithfully pasted my typo: it's receiver, not recivier. Could be
touched up on commit.
> + * more packets.
> + */
> + filter_buffer_flush(nf);
> + /* Timer rearmed to fire again in s->interval microseconds. */
> + timer_mod(&s->release_timer,
> + qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + s->interval);
> +}
[...]
Preferably with these touch-ups:
Reviewed-by: Markus Armbruster <armbru@redhat.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2015-10-07 13:25 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-07 3:52 [Qemu-devel] [PATCH v13 00/10] Add a netfilter object and netbuffer filter Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 01/10] vl.c: init delayed object after net_init_clients Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 02/10] init/cleanup of netfilter object Yang Hongyang
2015-10-07 13:19 ` Markus Armbruster
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 03/10] netfilter: hook packets before net queue send Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 04/10] net: merge qemu_deliver_packet and qemu_deliver_packet_iov Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 05/10] net/queue: introduce NetQueueDeliverFunc Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 06/10] netfilter: add an API to pass the packet to next filter Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 07/10] netfilter: print filter info associate with the netdev Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 08/10] net/queue: export qemu_net_queue_append_iov Yang Hongyang
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 09/10] netfilter: add a netbuffer filter Yang Hongyang
2015-10-07 13:25 ` Markus Armbruster
2015-10-07 3:52 ` [Qemu-devel] [PATCH v13 10/10] tests: add test cases for netfilter object 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).