On 07/31/2015 12:13 PM, Yang Hongyang wrote: > Capture packets that will be sent. > > Signed-off-by: Yang Hongyang <yan...@cn.fujitsu.com> > --- > include/net/filter.h | 8 +++++++ > net/filter.c | 1 + > net/net.c | 67 > +++++++++++++++++++++++++++++++++++++++++++++++++++- > 3 files changed, 75 insertions(+), 1 deletion(-) > > diff --git a/include/net/filter.h b/include/net/filter.h > index 1b6f896..93579c1 100644 > --- a/include/net/filter.h > +++ b/include/net/filter.h > @@ -19,11 +19,19 @@ enum { > }; > > typedef void (FilterCleanup) (NetFilterState *); > +/* > + * 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 *, NetClientState *sender, > + unsigned flags, const struct iovec *, > int); > > typedef struct NetFilterInfo { > NetFilterOptionsKind type; > size_t size; > FilterCleanup *cleanup; > + FilterReceiveIOV *receive_iov;
Please move this to patch 2. > } NetFilterInfo; > > struct NetFilterState { > diff --git a/net/filter.c b/net/filter.c > index b3a2285..1ae9344 100644 > --- a/net/filter.c > +++ b/net/filter.c > @@ -29,6 +29,7 @@ NetFilterState *qemu_new_net_filter(NetFilterInfo *info, > NetFilterState *nf; > > assert(info->size >= sizeof(NetFilterState)); > + assert(info->receive_iov); > > nf = g_malloc0(info->size); > nf->info = info; > diff --git a/net/net.c b/net/net.c > index 22748e0..b55d934 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -24,6 +24,7 @@ > #include "config-host.h" > > #include "net/net.h" > +#include "net/filter.h" > #include "clients.h" > #include "hub.h" > #include "net/slirp.h" > @@ -592,6 +593,42 @@ int qemu_can_send_packet(NetClientState *sender) > return 1; > } > > +static ssize_t filter_receive_iov(NetClientState *nc, int chain, > + NetClientState *sender, > + unsigned flags, > + const struct iovec *iov, > + int iovcnt) { > + ssize_t ret = 0; > + Filter *filter = NULL; > + NetFilterState *nf = NULL; > + ssize_t size = iov_size(iov, iovcnt); > + > + QTAILQ_FOREACH(filter, &nc->filters, next) { > + nf = filter->nf; > + if (nf->chain == chain || nf->chain == NET_FILTER_ALL) { > + ret = nf->info->receive_iov(nf, sender, flags, iov, iovcnt); > + if (ret == size) { > + return ret; > + } > + } > + } So if a packet is being stolen or blocked by one filter, it could only be flushed to destination? I think we need an API to flush it into next filter. > + > + return ret; > +} > + > +static ssize_t filter_receive(NetClientState *nc, int chain, > + NetClientState *sender, > + unsigned flags, > + const uint8_t *data, > + size_t size) { > + struct iovec iov = { > + .iov_base = (void *)data, > + .iov_len = size > + }; > + > + return filter_receive_iov(nc, chain, sender, flags, &iov, 1); > +} > + > ssize_t qemu_deliver_packet(NetClientState *sender, > unsigned flags, > const uint8_t *data, > @@ -663,6 +700,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"); > @@ -673,6 +711,18 @@ 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_OUT, sender, flags, buf, size); > + if (ret == size) { > + return size; > + } > + > + ret = filter_receive(sender->peer, NET_FILTER_IN, > + sender, flags, buf, size); > + if (ret == size) { > + return size; > + } > + > queue = sender->peer->incoming_queue; > > return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb); > @@ -743,9 +793,24 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender, > NetPacketSent *sent_cb) > { > NetQueue *queue; > + int size = iov_size(iov, iovcnt); > + int ret; > > if (sender->link_down || !sender->peer) { > - return iov_size(iov, iovcnt); > + return size; > + } > + > + /* Let filters handle the packet first */ > + ret = filter_receive_iov(sender, NET_FILTER_OUT, > + sender, QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt); > + if (ret == size) { > + return size; > + } > + > + ret = filter_receive_iov(sender->peer, NET_FILTER_IN, > + sender, QEMU_NET_PACKET_FLAG_NONE, iov, iovcnt); > + if (ret == size) { > + return size; > } > > queue = sender->peer->incoming_queue;