From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50572) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtbAB-00076W-1j for qemu-devel@nongnu.org; Tue, 03 Nov 2015 07:58:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZtbA7-0001bf-Eb for qemu-devel@nongnu.org; Tue, 03 Nov 2015 07:58:10 -0500 Received: from mr213139.mail.yeah.net ([223.252.213.139]:40942) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtbA2-0001Xq-Mr for qemu-devel@nongnu.org; Tue, 03 Nov 2015 07:58:07 -0500 References: <1446551816-15768-1-git-send-email-zhang.zhanghailiang@huawei.com> <1446551816-15768-36-git-send-email-zhang.zhanghailiang@huawei.com> From: Yang Hongyang Message-ID: <5638AF42.3080507@easystack.cn> Date: Tue, 3 Nov 2015 20:57:38 +0800 MIME-Version: 1.0 In-Reply-To: <1446551816-15768-36-git-send-email-zhang.zhanghailiang@huawei.com> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH COLO-Frame v10 35/38] netfilter: Introduce a API to automatically add filter-buffer for each netdev List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: zhanghailiang , qemu-devel@nongnu.org Cc: lizhijian@cn.fujitsu.com, quintela@redhat.com, Jason Wang , yunhong.jiang@intel.com, eddie.dong@intel.com, peter.huangpeng@huawei.com, dgilbert@redhat.com, arei.gonglei@huawei.com, stefanha@redhat.com, amit.shah@redhat.com On 2015=E5=B9=B411=E6=9C=8803=E6=97=A5 19:56, zhanghailiang wrote: > Signed-off-by: zhanghailiang > Cc: Jason Wang > --- > v10: new patch > --- > include/net/filter.h | 1 + > include/net/net.h | 3 ++ > net/filter-buffer.c | 84 +++++++++++++++++++++++++++++++++++++++++++= +++++++++ > net/net.c | 20 +++++++++++++ > 4 files changed, 108 insertions(+) > > diff --git a/include/net/filter.h b/include/net/filter.h > index 4499d60..b0954ba 100644 > --- a/include/net/filter.h > +++ b/include/net/filter.h > @@ -75,5 +75,6 @@ ssize_t qemu_netfilter_pass_to_next(NetClientState *s= ender, > void *opaque); > void filter_buffer_release_all(void); > void filter_buffer_del_all_timers(void); > +void qemu_auto_add_filter_buffer(NetFilterDirection direction, Error *= *errp); > > #endif /* QEMU_NET_FILTER_H */ > diff --git a/include/net/net.h b/include/net/net.h > index 5c65c45..e32bd90 100644 > --- a/include/net/net.h > +++ b/include/net/net.h > @@ -129,6 +129,9 @@ typedef void (*qemu_netfilter_foreach)(NetFilterSta= te *nf, void *opaque, > Error **errp); > void qemu_foreach_netfilter(qemu_netfilter_foreach func, void *opaque= , > Error **errp); > +typedef void (*qemu_netdev_foreach)(NetClientState *nc, void *opaque, > + Error **errp); > +void qemu_foreach_netdev(qemu_netdev_foreach func, void *opaque, Error= **errp); > int qemu_can_send_packet(NetClientState *nc); > ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov= , > int iovcnt); > diff --git a/net/filter-buffer.c b/net/filter-buffer.c > index 05313de..0dc1efb 100644 > --- a/net/filter-buffer.c > +++ b/net/filter-buffer.c > @@ -15,6 +15,11 @@ > #include "qapi-visit.h" > #include "qom/object.h" > #include "net/net.h" > +#include "qapi/qmp/qdict.h" > +#include "qapi/qmp-output-visitor.h" > +#include "qapi/qmp-input-visitor.h" > +#include "monitor/monitor.h" > + > > #define TYPE_FILTER_BUFFER "filter-buffer" > > @@ -185,6 +190,85 @@ void filter_buffer_del_all_timers(void) > qemu_foreach_netfilter(filter_buffer_del_timer, NULL, NULL); > } > > +static void netdev_add_filter_buffer(NetClientState *nc, void *opaque, > + Error **errp) > +{ > + NetFilterState *nf; > + bool found =3D false; > + > + QTAILQ_FOREACH(nf, &nc->filters, next) { > + if (!strcmp(object_get_typename(OBJECT(nf)), TYPE_FILTER_BUFFE= R)) { > + found =3D true; What if a filter-buffer already attached to a netdev, but has interval set? Is this API really necessary? > + break; > + } > + } > + > + if (!found) { > + QmpOutputVisitor *qov; > + QmpInputVisitor *qiv; > + Visitor *ov, *iv; > + QObject *obj =3D NULL; > + QDict *qdict; > + void *dummy =3D NULL; > + char *id =3D g_strdup_printf("%s-%s.0", nc->name, TYPE_FILTER_= BUFFER); > + char *queue =3D (char *) opaque; > + bool auto_add =3D true; > + Error *err =3D NULL; > + > + qov =3D qmp_output_visitor_new(); > + ov =3D qmp_output_get_visitor(qov); > + visit_start_struct(ov, &dummy, NULL, NULL, 0, &err); > + if (err) { > + goto out; > + } > + visit_type_str(ov, &nc->name, "netdev", &err); > + if (err) { > + goto out; > + } > + visit_type_str(ov, &queue, "queue", &err); > + if (err) { > + goto out; > + } > + visit_type_bool(ov, &auto_add, "auto", &err); > + if (err) { > + goto out; > + } > + visit_end_struct(ov, &err); > + if (err) { > + goto out; > + } > + obj =3D qmp_output_get_qobject(qov); > + g_assert(obj !=3D NULL); > + qdict =3D qobject_to_qdict(obj); > + qmp_output_visitor_cleanup(qov); > + > + qiv =3D qmp_input_visitor_new(obj); > + iv =3D qmp_input_get_visitor(qiv); > + object_add(TYPE_FILTER_BUFFER, id, qdict, iv, &err); > + qmp_input_visitor_cleanup(qiv); > + qobject_decref(obj); > +out: > + g_free(id); > + if (err) { > + error_propagate(errp, err); > + } > + } > +} > +/* > +* This will be used by COLO or MC FT, for which they will need > +* to buffer all the packets of all VM's net devices, Here we check > +* and automatically add netfilter for netdev that doesn't attach any b= uffer > +* netfilter. > +*/ > +void qemu_auto_add_filter_buffer(NetFilterDirection direction, Error *= *errp) > +{ > + char *queue =3D g_strdup(NetFilterDirection_lookup[direction]); > + > + qemu_foreach_netdev(netdev_add_filter_buffer, queue, > + errp); > + g_free(queue); > +} > + > static void filter_buffer_init(Object *obj) > { > object_property_add(obj, "interval", "int", > diff --git a/net/net.c b/net/net.c > index a333b01..4fbe0af 100644 > --- a/net/net.c > +++ b/net/net.c > @@ -283,6 +283,26 @@ void qemu_foreach_netfilter(qemu_netfilter_foreach= func, void *opaque, > } > } > > +void qemu_foreach_netdev(qemu_netdev_foreach func, void *opaque, Error= **errp) > +{ > + NetClientState *nc; > + > + QTAILQ_FOREACH(nc, &net_clients, next) { > + if (nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_NIC) { > + continue; > + } > + if (func) { > + Error *local_err =3D NULL; > + > + func(nc, opaque, &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + return; > + } > + } > + } > +} > + > static void qemu_net_client_destructor(NetClientState *nc) > { > g_free(nc); > --=20 Thanks, Yang