add a public api filter_buffer_release_all to release all buffered packets. also introduce qemu_find_netfilters_by_model to find all buffer filters.
Signed-off-by: Yang Hongyang <yan...@cn.fujitsu.com> --- include/net/filter.h | 5 +++++ net/filter-buffer.c | 41 +++++++++++++++++++++++++++++++++++++++++ net/filter.c | 18 ++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/include/net/filter.h b/include/net/filter.h index 5292563..798b5b2 100644 --- a/include/net/filter.h +++ b/include/net/filter.h @@ -50,5 +50,10 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info, const char *name); void netfilter_add(QemuOpts *opts, Error **errp); void qmp_netfilter_add(QDict *qdict, QObject **ret, Error **errp); +int qemu_find_netfilters_by_model(const char *model, NetFilterState **nfs, + int max); + +/* netbuffer filter */ +void filter_buffer_release_all(void); #endif /* QEMU_NET_FILTER_H */ diff --git a/net/filter-buffer.c b/net/filter-buffer.c index 628e66f..8bac73b 100644 --- a/net/filter-buffer.c +++ b/net/filter-buffer.c @@ -11,12 +11,14 @@ #include "filters.h" #include "qemu-common.h" #include "qemu/error-report.h" +#include "qemu/main-loop.h" typedef struct FILTERBUFFERState { NetFilterState nf; NetClientState dummy; /* used to send buffered packets */ NetQueue *incoming_queue; NetQueue *inflight_queue; + QEMUBH *flush_bh; } FILTERBUFFERState; static void packet_send_completed(NetClientState *nc, ssize_t len) @@ -56,6 +58,27 @@ static void filter_buffer_flush(NetFilterState *nf) } } +static void filter_buffer_flush_bh(void *opaque) +{ + FILTERBUFFERState *s = opaque; + NetFilterState *nf = &s->nf; + filter_buffer_flush(nf); +} + +static void filter_buffer_release_one(NetFilterState *nf) +{ + FILTERBUFFERState *s = DO_UPCAST(FILTERBUFFERState, nf, nf); + + /* flush inflight packets */ + if (s->inflight_queue) { + filter_buffer_flush(nf); + } + + s->inflight_queue = s->incoming_queue; + s->incoming_queue = qemu_new_net_queue(nf); + qemu_bh_schedule(s->flush_bh); +} + /* filter APIs */ static ssize_t filter_buffer_receive(NetFilterState *nf, NetClientState *sender, @@ -93,6 +116,10 @@ static void filter_buffer_cleanup(NetFilterState *nf) s->incoming_queue = NULL; filter_buffer_flush(nf); + if (s->flush_bh) { + qemu_bh_delete(s->flush_bh); + s->flush_bh = NULL; + } return; } @@ -122,6 +149,20 @@ int net_init_filter_buffer(const NetFilterOptions *opts, const char *name, */ s->dummy.peer = netdev; s->incoming_queue = qemu_new_net_queue(nf); + s->flush_bh = qemu_bh_new(filter_buffer_flush_bh, s); return 0; } + +/* public APIs */ +void filter_buffer_release_all(void) +{ + NetFilterState *nfs[MAX_QUEUE_NUM]; + int queues, i; + + queues = qemu_find_netfilters_by_model("buffer", nfs, MAX_QUEUE_NUM); + + for (i = 0; i < queues; i++) { + filter_buffer_release_one(nfs[i]); + } +} diff --git a/net/filter.c b/net/filter.c index e741e2a..b9a6216 100644 --- a/net/filter.c +++ b/net/filter.c @@ -93,6 +93,24 @@ static NetFilterState *qemu_find_netfilter(const char *id) return NULL; } +int qemu_find_netfilters_by_model(const char *model, NetFilterState **nfs, + int max) +{ + NetFilterState *nf; + int ret = 0; + + QTAILQ_FOREACH(nf, &net_filters, next) { + if (!strcmp(nf->model, model)) { + if (ret < max) { + nfs[ret] = nf; + } + ret++; + } + } + + return ret; +} + static int net_init_filter(void *dummy, QemuOpts *opts, Error **errp); void netfilter_add(QemuOpts *opts, Error **errp) { -- 1.9.1