From patchwork Mon Mar 13 13:37:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roi Dayan X-Patchwork-Id: 738159 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vhfLg2ZPbz9s0Z for ; Tue, 14 Mar 2017 00:47:23 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 29D88C31; Mon, 13 Mar 2017 13:38:15 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp2.linuxfoundation.org (smtp2.linux-foundation.org [172.17.192.36]) by mail.linuxfoundation.org (Postfix) with ESMTPS id DCE57BC5 for ; Mon, 13 Mar 2017 13:38:13 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by smtp2.linuxfoundation.org (Postfix) with ESMTP id 94DDE1DDD9 for ; Mon, 13 Mar 2017 13:38:12 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from roid@mellanox.com) with ESMTPS (AES256-SHA encrypted); 13 Mar 2017 15:38:08 +0200 Received: from r-vnc05.mtr.labs.mlnx (r-vnc05.mtr.labs.mlnx [10.208.0.115]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id v2DDbJZQ028197; Mon, 13 Mar 2017 15:37:23 +0200 From: Roi Dayan To: dev@openvswitch.org Date: Mon, 13 Mar 2017 15:37:11 +0200 Message-Id: <1489412234-30916-22-git-send-email-roid@mellanox.com> X-Mailer: git-send-email 1.8.4.3 In-Reply-To: <1489412234-30916-1-git-send-email-roid@mellanox.com> References: <1489412234-30916-1-git-send-email-roid@mellanox.com> X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp2.linux-foundation.org Cc: Shahar Klein , Hadar Hen Zion , Rony Efraim , Jiri Pirko , Marcelo Ricardo Leitner , Simon Horman , Or Gerlitz , Andy Gospodarek Subject: [ovs-dev] [PATCH ovs V4 21/24] dpctl: Add an option to dump only certain kinds of flows X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org From: Paul Blakey Usage: # to dump all datapath flows (default): ovs-dpctl dump-flows # to dump only flows that in kernel datapath: ovs-dpctl dump-flows type=ovs # to dump only flows that are offloaded: ovs-dpctl dump-flows type=offloaded Signed-off-by: Paul Blakey Reviewed-by: Roi Dayan --- lib/dpctl.c | 21 ++++++++++---- lib/dpif-netdev.c | 3 +- lib/dpif-netlink.c | 62 +++++++++++++++++++++++++++++++++-------- lib/dpif-provider.h | 6 ++- lib/dpif.c | 4 +- lib/dpif.h | 3 +- ofproto/ofproto-dpif-upcall.c | 3 +- ofproto/ofproto-dpif.c | 2 +- 8 files changed, 78 insertions(+), 26 deletions(-) diff --git a/lib/dpctl.c b/lib/dpctl.c index 23837ce..59e2cd3 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -762,6 +762,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) char *name; char *filter = NULL; + char *type = NULL; struct flow flow_filter; struct flow_wildcards wc_filter; @@ -774,22 +775,29 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) struct dpif_flow_dump *flow_dump; struct dpif_flow f; int pmd_id = PMD_ID_NULL; + int lastargc = 0; int error; - if (argc > 1 && !strncmp(argv[argc - 1], "filter=", 7)) { - filter = xstrdup(argv[--argc] + 7); + while (argc > 1 && lastargc != argc) { + lastargc = argc; + if (!strncmp(argv[argc - 1], "filter=", 7)) { + filter = xstrdup(argv[--argc] + 7); + } else if (!strncmp(argv[argc - 1], "type=", 5)) { + type = xstrdup(argv[--argc] + 5); + } } + name = (argc == 2) ? xstrdup(argv[1]) : get_one_dp(dpctl_p); if (!name) { error = EINVAL; - goto out_freefilter; + goto out_free; } error = parsed_dpif_open(name, false, &dpif); free(name); if (error) { dpctl_error(dpctl_p, error, "opening datapath"); - goto out_freefilter; + goto out_free; } @@ -818,7 +826,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p) BUILD_ASSERT(PMD_ID_NULL != NON_PMD_CORE_ID); ds_init(&ds); - flow_dump = dpif_flow_dump_create(dpif, false); + flow_dump = dpif_flow_dump_create(dpif, false, (type ? type : "dpctl")); flow_dump_thread = dpif_flow_dump_thread_create(flow_dump); while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) { if (filter) { @@ -870,8 +878,9 @@ out_dpifclose: simap_destroy(&names_portno); hmap_destroy(&portno_names); dpif_close(dpif); -out_freefilter: +out_free: free(filter); + free(type); return error; } diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 0be5db5..d76ecb8 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -2502,7 +2502,8 @@ dpif_netdev_flow_dump_cast(struct dpif_flow_dump *dump) } static struct dpif_flow_dump * -dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse) +dpif_netdev_flow_dump_create(const struct dpif *dpif_, bool terse, + char *type OVS_UNUSED) { struct dpif_netdev_flow_dump *dump; diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 6157484..2f2002e 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -1371,6 +1371,16 @@ dpif_netlink_init_flow_del(struct dpif_netlink *dpif, del->ufid, del->terse, request); } +enum { + DUMP_OVS_FLOWS_BIT = 0, + DUMP_OFFLOADED_FLOWS_BIT = 1, +}; + +enum { + DUMP_OVS_FLOWS = (1 << DUMP_OVS_FLOWS_BIT), + DUMP_OFFLOADED_FLOWS = (1 << DUMP_OFFLOADED_FLOWS_BIT), +}; + struct dpif_netlink_flow_dump { struct dpif_flow_dump up; struct nl_dump nl_dump; @@ -1379,6 +1389,7 @@ struct dpif_netlink_flow_dump { int netdev_dumps_num; /* Number of netdev_flow_dumps */ struct ovs_mutex netdev_lock; /* Guards the following. */ int netdev_current_dump OVS_GUARDED; /* Shared current dump */ + int type; /* Type of dump */ }; static struct dpif_netlink_flow_dump * @@ -1393,7 +1404,7 @@ start_netdev_dump(const struct dpif *dpif_, { ovs_mutex_init(&dump->netdev_lock); - if (!netdev_flow_api_enabled) { + if (!(dump->type & DUMP_OFFLOADED_FLOWS)) { dump->netdev_dumps_num = 0; dump->netdev_dumps = NULL; return; @@ -1407,8 +1418,24 @@ start_netdev_dump(const struct dpif *dpif_, ovs_mutex_unlock(&dump->netdev_lock); } +static int +dpif_netlink_get_dump_type(char *str) { + int type = 0; + + if (!str || !strcmp(str, "ovs") || !strcmp(str, "dpctl")) { + type |= DUMP_OVS_FLOWS; + } + if ((netdev_flow_api_enabled && !str) + || (str && (!strcmp(str, "offloaded") || !strcmp(str, "dpctl")))) { + type |= DUMP_OFFLOADED_FLOWS; + } + + return type; +} + static struct dpif_flow_dump * -dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse) +dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse, + char *type) { const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); struct dpif_netlink_flow_dump *dump; @@ -1418,16 +1445,20 @@ dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse) dump = xmalloc(sizeof *dump); dpif_flow_dump_init(&dump->up, dpif_); - dpif_netlink_flow_init(&request); - request.cmd = OVS_FLOW_CMD_GET; - request.dp_ifindex = dpif->dp_ifindex; - request.ufid_present = false; - request.ufid_terse = terse; + dump->type = dpif_netlink_get_dump_type(type); - buf = ofpbuf_new(1024); - dpif_netlink_flow_to_ofpbuf(&request, buf); - nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf); - ofpbuf_delete(buf); + if (dump->type & DUMP_OVS_FLOWS) { + dpif_netlink_flow_init(&request); + request.cmd = OVS_FLOW_CMD_GET; + request.dp_ifindex = dpif->dp_ifindex; + request.ufid_present = false; + request.ufid_terse = terse; + + buf = ofpbuf_new(1024); + dpif_netlink_flow_to_ofpbuf(&request, buf); + nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf); + ofpbuf_delete(buf); + } atomic_init(&dump->status, 0); dump->up.terse = terse; @@ -1440,9 +1471,12 @@ static int dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_) { struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_); - unsigned int nl_status = nl_dump_done(&dump->nl_dump); + unsigned int nl_status = 0; int dump_status; + if (dump->type & DUMP_OVS_FLOWS) { + nl_status = nl_dump_done(&dump->nl_dump); + } for (int i = 0; i < dump->netdev_dumps_num; i++) { int err = netdev_flow_dump_destroy(dump->netdev_dumps[i]); if (err != 0 && err != EOPNOTSUPP) { @@ -1673,6 +1707,10 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_, } } + if (!(dump->type & DUMP_OVS_FLOWS)) { + return n_flows; + } + while (!n_flows || (n_flows < flow_limit && thread->nl_flows.size)) { struct dpif_netlink_flow datapath_flow; diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index a0dc1ef..d1750d9 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -281,9 +281,11 @@ struct dpif_class { * dpif_flow_dump_thread_init(), respectively. * * If 'terse' is true, then only UID and statistics will - * be returned in the dump. Otherwise, all fields will be returned. */ + * be returned in the dump. Otherwise, all fields will be returned. + * + * If 'type' isn't null, dumps only the flows of the given type. */ struct dpif_flow_dump *(*flow_dump_create)(const struct dpif *dpif, - bool terse); + bool terse, char *type); int (*flow_dump_destroy)(struct dpif_flow_dump *dump); struct dpif_flow_dump_thread *(*flow_dump_thread_create)( diff --git a/lib/dpif.c b/lib/dpif.c index d4e4c0a..b9cd97c 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1047,9 +1047,9 @@ dpif_flow_del(struct dpif *dpif, * This function always successfully returns a dpif_flow_dump. Error * reporting is deferred to dpif_flow_dump_destroy(). */ struct dpif_flow_dump * -dpif_flow_dump_create(const struct dpif *dpif, bool terse) +dpif_flow_dump_create(const struct dpif *dpif, bool terse, char *type) { - return dpif->dpif_class->flow_dump_create(dpif, terse); + return dpif->dpif_class->flow_dump_create(dpif, terse, type); } /* Destroys 'dump', which must have been created with dpif_flow_dump_create(). diff --git a/lib/dpif.h b/lib/dpif.h index 44cbe95..fcda5ab 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -567,7 +567,8 @@ int dpif_flow_get(struct dpif *, * * All error reporting is deferred to the call to dpif_flow_dump_destroy(). */ -struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *, bool terse); +struct dpif_flow_dump *dpif_flow_dump_create(const struct dpif *, bool terse, + char *type); int dpif_flow_dump_destroy(struct dpif_flow_dump *); struct dpif_flow_dump_thread *dpif_flow_dump_thread_create( diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 660383f..bc3b1fc 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -885,7 +885,8 @@ udpif_revalidator(void *arg) bool terse_dump; terse_dump = udpif_use_ufid(udpif); - udpif->dump = dpif_flow_dump_create(udpif->dpif, terse_dump); + udpif->dump = dpif_flow_dump_create(udpif->dpif, terse_dump, + NULL); } } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 4007a3a..93664c9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -4950,7 +4950,7 @@ ofproto_unixctl_dpif_dump_flows(struct unixctl_conn *conn, } ds_init(&ds); - flow_dump = dpif_flow_dump_create(ofproto->backer->dpif, false); + flow_dump = dpif_flow_dump_create(ofproto->backer->dpif, false, NULL); flow_dump_thread = dpif_flow_dump_thread_create(flow_dump); while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) { struct flow flow;