This patch add a net filter between network backend and NIC devices.
All packets will pass by this filter.
TODO:
multiqueue support.
+--+ +-+
+--+ |filter| |frontend(NIC)|
| peer+--> | | |
| network <--+backend <---+ peer|
| backend | | peer +---> |
+--+ +--+ +-+
Usage:
-netdev tap,id=bn0 # you can use whatever backend as needed
-netdev filter,id=f0,backend=bn0
-netdev filter-,id=p0,filter=f0
-device e1000,netdev=f0
NOTE:
You can attach multiple plugins to the filter, dynamically add/remove
filter and filter-.
A filter without plugin supplied will do nothing except pass by all
packets, a plugin like dump for example, will dump all packets into a
file. Or other plugins like a netbuffer plugin, will simply buffer the
packets, release the packets when needed.
You can also implement whatever plugin you needed based on this filter.
Signed-off-by: Yang Hongyang
---
include/net/filter.h | 18 +++
include/net/net.h| 3 +
net/Makefile.objs| 1 +
net/clients.h| 3 +
net/filter.c | 317 +++
net/net.c| 20 +++-
qapi-schema.json | 22 +++-
7 files changed, 377 insertions(+), 7 deletions(-)
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 000..44ba10f
--- /dev/null
+++ b/include/net/filter.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ *
+ * 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 "qemu-common.h"
+//#include "qapi-types.h"
+
+NetClientState *filter_backend(NetClientState *nc);
+int filter_add_plugin(NetClientState *nc, NetClientState *plugin);
+int filter_del_plugin(NetClientState *nc, NetClientState *plugin);
+
+#endif /* QEMU_NET_FILTER_H */
diff --git a/include/net/net.h b/include/net/net.h
index 6a6cbef..250f365 100644
--- a/include/net/net.h
+++ b/include/net/net.h
@@ -45,6 +45,8 @@ typedef void (NetPoll)(NetClientState *, bool enable);
typedef int (NetCanReceive)(NetClientState *);
typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
+typedef ssize_t (NetReceiveFilter)(NetClientState *, NetClientState *,
+ unsigned, const uint8_t *, size_t);
typedef void (NetCleanup) (NetClientState *);
typedef void (LinkStatusChanged)(NetClientState *);
typedef void (NetClientDestructor)(NetClientState *);
@@ -64,6 +66,7 @@ typedef struct NetClientInfo {
NetReceive *receive;
NetReceive *receive_raw;
NetReceiveIOV *receive_iov;
+NetReceiveFilter *receive_filter;
NetCanReceive *can_receive;
NetCleanup *cleanup;
LinkStatusChanged *link_status_changed;
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/clients.h b/net/clients.h
index d47530e..bcfb34b 100644
--- a/net/clients.h
+++ b/net/clients.h
@@ -62,4 +62,7 @@ int net_init_netmap(const NetClientOptions *opts, const char
*name,
int net_init_vhost_user(const NetClientOptions *opts, const char *name,
NetClientState *peer, Error **errp);
+int net_init_filter(const NetClientOptions *opts, const char *name,
+NetClientState *peer, Error **errp);
+
#endif /* QEMU_NET_CLIENTS_H */
diff --git a/net/filter.c b/net/filter.c
new file mode 100644
index 000..89ee830
--- /dev/null
+++ b/net/filter.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang
+ *
+ * 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/net.h"
+#include "clients.h"
+#include "qemu-common.h"
+#include "qemu/error-report.h"
+#include "net/filter.h"
+
+typedef struct FilterPlugin FilterPlugin;
+struct FilterPlugin {
+QLIST_ENTRY(FilterPlugin) next;
+NetClientState *plugin;
+};
+
+typedef struct FILTERState {
+NetClientState nc;
+NetClientState *backend;
+QLIST_HEAD(, FilterPlugin) plugins;
+} FILTERState;
+
+static ssize_t filter_receive(NetClientState *nc, NetClientState *sender,
+ unsigned flags, const uint8_t *data, size_t size)
+{
+FILTERState *s = DO_UPCAST(FILTERState, nc, nc);
+NetClientState *backend = s->backend;
+N