From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55525) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZL3Sp-0003Wr-Kl for qemu-devel@nongnu.org; Fri, 31 Jul 2015 02:06:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZL3Sl-0002pq-0O for qemu-devel@nongnu.org; Fri, 31 Jul 2015 02:06:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59727) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZL3Sk-0002pQ-Q5 for qemu-devel@nongnu.org; Fri, 31 Jul 2015 02:06:34 -0400 Message-ID: <55BB1062.8000901@redhat.com> Date: Fri, 31 Jul 2015 14:06:26 +0800 From: Jason Wang MIME-Version: 1.0 References: <1438316014-8369-1-git-send-email-yanghy@cn.fujitsu.com> <1438316014-8369-6-git-send-email-yanghy@cn.fujitsu.com> In-Reply-To: <1438316014-8369-6-git-send-email-yanghy@cn.fujitsu.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH v2 5/9] netfilter: hook packets before net queue send List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Yang Hongyang , qemu-devel@nongnu.org Cc: thuth@redhat.com, zhang.zhanghailiang@huawei.com, lizhijian@cn.fujitsu.com, mrhines@linux.vnet.ibm.com, stefanha@redhat.com On 07/31/2015 12:13 PM, Yang Hongyang wrote: > Capture packets that will be sent. > > Signed-off-by: Yang Hongyang > --- > 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;