From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57121) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtbSJ-0003Y0-P0 for qemu-devel@nongnu.org; Tue, 03 Nov 2015 08:17:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZtbSE-00079N-Rg for qemu-devel@nongnu.org; Tue, 03 Nov 2015 08:16:55 -0500 Received: from szxga01-in.huawei.com ([58.251.152.64]:59787) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZtbSD-00078U-8Q for qemu-devel@nongnu.org; Tue, 03 Nov 2015 08:16:50 -0500 References: <1446551816-15768-1-git-send-email-zhang.zhanghailiang@huawei.com> <1446551816-15768-36-git-send-email-zhang.zhanghailiang@huawei.com> <5638AF42.3080507@easystack.cn> From: zhanghailiang Message-ID: <5638B3A5.8070104@huawei.com> Date: Tue, 3 Nov 2015 21:16:21 +0800 MIME-Version: 1.0 In-Reply-To: <5638AF42.3080507@easystack.cn> Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 8bit 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: Yang Hongyang , 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/11/3 20:57, Yang Hongyang wrote: > > > On 2015年11月03日 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 *sender, >> 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)(NetFilterState *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 = false; >> + >> + QTAILQ_FOREACH(nf, &nc->filters, next) { >> + if (!strcmp(object_get_typename(OBJECT(nf)), TYPE_FILTER_BUFFER)) { >> + found = true; > > What if a filter-buffer already attached to a netdev, but has interval > set? > Is this API really necessary? > We will jump this netdev, but remove its filter-buffer timer. Meanwhile, we will release the packets all together in colo checkpoint process. Besides, we should resume the timer after exit COLO. (We didn't do this in this version). I don't know if it is a good idea to automatically add filter-buffer for the device that not configured with it. But it is really reduce the complexity of testing. >> + break; >> + } >> + } >> + >> + if (!found) { >> + QmpOutputVisitor *qov; >> + QmpInputVisitor *qiv; >> + Visitor *ov, *iv; >> + QObject *obj = NULL; >> + QDict *qdict; >> + void *dummy = NULL; >> + char *id = g_strdup_printf("%s-%s.0", nc->name, TYPE_FILTER_BUFFER); >> + char *queue = (char *) opaque; >> + bool auto_add = true; >> + Error *err = NULL; >> + >> + qov = qmp_output_visitor_new(); >> + ov = 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 = qmp_output_get_qobject(qov); >> + g_assert(obj != NULL); >> + qdict = qobject_to_qdict(obj); >> + qmp_output_visitor_cleanup(qov); >> + >> + qiv = qmp_input_visitor_new(obj); >> + iv = 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 buffer >> +* netfilter. >> +*/ >> +void qemu_auto_add_filter_buffer(NetFilterDirection direction, Error **errp) >> +{ >> + char *queue = 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 == NET_CLIENT_OPTIONS_KIND_NIC) { >> + continue; >> + } >> + if (func) { >> + Error *local_err = 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); >> >