[ovs-dev] [PATCH ovs V3 23/25] dpctl: Add an option to dump only certain kinds of flows
Roi Dayan
roid at mellanox.com
Wed Feb 8 15:29:36 UTC 2017
From: Paul Blakey <paulb at mellanox.com>
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 <paulb at mellanox.com>
Reviewed-by: Roi Dayan <roid at mellanox.com>
---
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 a9eb25f..1b830e0 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) {
@@ -1674,6 +1708,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 < max_flows && 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;
--
2.7.4
More information about the dev
mailing list