On 01/26/2016 01:00 PM, Li Zhijian wrote: > Previously, if we attach more than filters for one netdev, IN/OUT traffic pass > through filters in a same order. > ingress: netdev ->filter1 ->filter2 ->...filter[n] ->emulated device > egress: emulated device ->filter1 ->filter2 ->...filter[n] ->netdev. > > But some scenes, we hope filters handle the egress traffic in a reverse order. > For example, in colo-proxy (will be implemented later), we have a redirector > filter and a colo-rewriter filter, we need the filter behavior like that: > ingress(->)/egress(<-): chardev<->redirector<->colo-rewriter<->emulated device > > After this changes, egress traffic always pass through filters in a reverse > order. > > Signed-off-by: Wen Congyang <we...@cn.fujitsu.com> > Signed-off-by: Li Zhijian <lizhij...@cn.fujitsu.com> > Reviewed-by: Yang Hongyang <hongyang.y...@easystack.cn>
Applied with minor tweaks on commit log: https://github.com/jasowang/qemu/commit/ec96442e398191f84aab824180aa83cd5eda0010 and use: QTAILQ_HEAD(NetFilterHead, NetFilterState) filters; instead. Thanks > --- > include/net/net.h | 4 +++- > net/filter.c | 21 +++++++++++++++++++-- > net/net.c | 20 +++++++++++++++----- > 3 files changed, 37 insertions(+), 8 deletions(-) > > diff --git a/include/net/net.h b/include/net/net.h > index 7af3e15..1d807cc 100644 > --- a/include/net/net.h > +++ b/include/net/net.h > @@ -79,6 +79,8 @@ typedef struct NetClientInfo { > SetVnetBE *set_vnet_be; > } NetClientInfo; > > +QTAILQ_HEAD(NetFilterHead, NetFilterState); > + > struct NetClientState { > NetClientInfo *info; > int link_down; > @@ -92,7 +94,7 @@ struct NetClientState { > NetClientDestructor *destructor; > unsigned int queue_index; > unsigned rxfilter_notify_enabled:1; > - QTAILQ_HEAD(, NetFilterState) filters; > + struct NetFilterHead filters; > }; > > typedef struct NICState { > diff --git a/net/filter.c b/net/filter.c > index 5d90f83..17a8398 100644 > --- a/net/filter.c > +++ b/net/filter.c > @@ -34,6 +34,22 @@ ssize_t qemu_netfilter_receive(NetFilterState *nf, > return 0; > } > > +static NetFilterState *netfilter_next(NetFilterState *nf, > + NetFilterDirection dir) > +{ > + NetFilterState *next; > + > + if (dir == NET_FILTER_DIRECTION_TX) { > + /* forward walk through filters */ > + next = QTAILQ_NEXT(nf, next); > + } else { > + /* reverse order */ > + next = QTAILQ_PREV(nf, NetFilterHead, next); > + } > + > + return next; > +} > + > ssize_t qemu_netfilter_pass_to_next(NetClientState *sender, > unsigned flags, > const struct iovec *iov, > @@ -43,7 +59,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender, > int ret = 0; > int direction; > NetFilterState *nf = opaque; > - NetFilterState *next = QTAILQ_NEXT(nf, next); > + NetFilterState *next = NULL; > > if (!sender || !sender->peer) { > /* no receiver, or sender been deleted, no need to pass it further */ > @@ -61,6 +77,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender, > direction = nf->direction; > } > > + next = netfilter_next(nf, direction); > while (next) { > /* > * if qemu_netfilter_pass_to_next been called, means that > @@ -73,7 +90,7 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *sender, > if (ret) { > return ret; > } > - next = QTAILQ_NEXT(next, next); > + next = netfilter_next(next, direction); > } > > /* > diff --git a/net/net.c b/net/net.c > index 87dd356..c929c41 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -580,11 +580,21 @@ static ssize_t filter_receive_iov(NetClientState *nc, > 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; > + if (direction == NET_FILTER_DIRECTION_TX) { > + QTAILQ_FOREACH(nf, &nc->filters, next) { > + ret = qemu_netfilter_receive(nf, direction, sender, flags, iov, > + iovcnt, sent_cb); > + if (ret) { > + return ret; > + } > + } > + } else { > + QTAILQ_FOREACH_REVERSE(nf, &nc->filters, NetFilterHead, next) { > + ret = qemu_netfilter_receive(nf, direction, sender, flags, iov, > + iovcnt, sent_cb); > + if (ret) { > + return ret; > + } > } > } >