add an API qemu_netfilter_pass_to_next_iov() to pass the packet to next filter, and a wrapper qemu_netfilter_pass_to_next().
Signed-off-by: Yang Hongyang <yan...@cn.fujitsu.com> --- include/net/filter.h | 12 ++++++++++++ net/filter.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/net/filter.h b/include/net/filter.h index c146be2..867d5aa 100644 --- a/include/net/filter.h +++ b/include/net/filter.h @@ -54,4 +54,16 @@ void qemu_del_net_filter(NetFilterState *nf); void netfilter_add(QemuOpts *opts, Error **errp); void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp); +/* pass the packet to the next filter */ +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf, + NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt); +void qemu_netfilter_pass_to_next(NetFilterState *nf, + NetClientState *sender, + unsigned flags, + const uint8_t *data, + size_t size); + #endif /* QEMU_NET_FILTER_H */ diff --git a/net/filter.c b/net/filter.c index 24ec4e1..166b851 100644 --- a/net/filter.c +++ b/net/filter.c @@ -14,9 +14,11 @@ #include "qapi/dealloc-visitor.h" #include "qemu/config-file.h" #include "qmp-commands.h" +#include "qemu/iov.h" #include "net/filter.h" #include "net/net.h" +#include "net/queue.h" static QTAILQ_HEAD(, NetFilterState) net_filters; @@ -130,6 +132,47 @@ void qmp_netfilter_del(const char *id, Error **errp) qemu_opts_del(opts); } +void qemu_netfilter_pass_to_next_iov(NetFilterState *nf, + NetClientState *sender, + unsigned flags, + const struct iovec *iov, + int iovcnt) +{ + int ret = 0; + ssize_t size = iov_size(iov, iovcnt); + NetFilterState *next = QTAILQ_NEXT(nf, next); + + while (next) { + if (next->chain == nf->chain || next->chain == NET_FILTER_ALL) { + ret = next->info->receive_iov(next, sender, flags, iov, iovcnt); + if (ret == size) { + return; + } + } + next = QTAILQ_NEXT(next, next); + } + + /* we have gone through all filters, pass it to receiver */ + if (sender && sender->peer) { + qemu_net_queue_send_iov(sender->peer->incoming_queue, sender, flags, + iov, iovcnt, NULL); + } +} + +void qemu_netfilter_pass_to_next(NetFilterState *nf, + NetClientState *sender, + unsigned flags, + const uint8_t *data, + size_t size) +{ + struct iovec iov = { + .iov_base = (void *)data, + .iov_len = size + }; + + return qemu_netfilter_pass_to_next_iov(nf, sender, flags, &iov, 1); +} + typedef int (NetFilterInit)(const NetFilterOptions *opts, const char *name, int chain, NetClientState *netdev, Error **errp); -- 1.9.1