summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavi Teitz <gavi@mellanox.com>2018-08-10 11:30:08 +0300
committerSimon Horman <simon.horman@netronome.com>2018-09-13 16:56:25 +0200
commita692410af0f71f89ef3b4c4b89b039d23cdfedb3 (patch)
tree7a6a7a41109be039d8a9b8f19332aee0c8977a16
parent0d6b401cf60d10809e4644105cf47c44b4bdc4ab (diff)
downloadopenvswitch-a692410af0f71f89ef3b4c4b89b039d23cdfedb3.tar.gz
dpctl: Expand the flow dump type filter
Added new types to the flow dump filter, and allowed multiple filter types to be passed at once, as a comma separated list. The new types added are: * tc - specifies flows handled by the tc dp * non-offloaded - specifies flows not offloaded to the HW * all - specifies flows of all types The type list is now fully parsed by the dpctl, and a new struct was added to dpif which enables dpctl to define which types of dumps to provide, rather than passing the type string and having dpif parse it. Signed-off-by: Gavi Teitz <gavi@mellanox.com> Acked-by: Roi Dayan <roid@mellanox.com> Signed-off-by: Simon Horman <simon.horman@netronome.com>
-rw-r--r--lib/dpctl.c112
-rw-r--r--lib/dpctl.man14
-rw-r--r--lib/dpif-netdev.c2
-rw-r--r--lib/dpif-netlink.c45
-rw-r--r--lib/dpif-provider.h8
-rw-r--r--lib/dpif.c5
-rw-r--r--lib/dpif.h7
7 files changed, 128 insertions, 65 deletions
diff --git a/lib/dpctl.c b/lib/dpctl.c
index 2f8498f47..58800872e 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -837,18 +837,85 @@ format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
format_odp_actions(ds, f->actions, f->actions_len, ports);
}
-static char *supported_dump_types[] = {
- "offloaded",
- "ovs",
+struct dump_types {
+ bool ovs;
+ bool tc;
+ bool offloaded;
+ bool non_offloaded;
};
+static void
+enable_all_dump_types(struct dump_types *dump_types)
+{
+ dump_types->ovs = true;
+ dump_types->tc = true;
+ dump_types->offloaded = true;
+ dump_types->non_offloaded = true;
+}
+
+static int
+populate_dump_types(char *types_list, struct dump_types *dump_types,
+ struct dpctl_params *dpctl_p)
+{
+ if (!types_list) {
+ enable_all_dump_types(dump_types);
+ return 0;
+ }
+
+ char *current_type;
+
+ while (types_list && types_list[0] != '\0') {
+ current_type = types_list;
+ size_t type_len = strcspn(current_type, ",");
+
+ types_list += type_len + (types_list[type_len] != '\0');
+ current_type[type_len] = '\0';
+
+ if (!strcmp(current_type, "ovs")) {
+ dump_types->ovs = true;
+ } else if (!strcmp(current_type, "tc")) {
+ dump_types->tc = true;
+ } else if (!strcmp(current_type, "offloaded")) {
+ dump_types->offloaded = true;
+ } else if (!strcmp(current_type, "non-offloaded")) {
+ dump_types->non_offloaded = true;
+ } else if (!strcmp(current_type, "all")) {
+ enable_all_dump_types(dump_types);
+ } else {
+ dpctl_error(dpctl_p, EINVAL, "Failed to parse type (%s)",
+ current_type);
+ return EINVAL;
+ }
+ }
+ return 0;
+}
+
+static void
+determine_dpif_flow_dump_types(struct dump_types *dump_types,
+ struct dpif_flow_dump_types *dpif_dump_types)
+{
+ dpif_dump_types->ovs_flows = dump_types->ovs || dump_types->non_offloaded;
+ dpif_dump_types->netdev_flows = dump_types->tc || dump_types->offloaded
+ || dump_types->non_offloaded;
+}
+
static bool
-flow_passes_type_filter(const struct dpif_flow *f, char *type)
+flow_passes_type_filter(const struct dpif_flow *f,
+ struct dump_types *dump_types)
{
- if (!strcmp(type, "offloaded")) {
- return f->attrs.offloaded;
+ if (dump_types->ovs && !strcmp(f->attrs.dp_layer, "ovs")) {
+ return true;
+ }
+ if (dump_types->tc && !strcmp(f->attrs.dp_layer, "tc")) {
+ return true;
+ }
+ if (dump_types->offloaded && f->attrs.offloaded) {
+ return true;
+ }
+ if (dump_types->non_offloaded && !(f->attrs.offloaded)) {
+ return true;
}
- return true;
+ return false;
}
static struct hmap *
@@ -888,9 +955,11 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
struct ds ds;
char *filter = NULL;
- char *type = NULL;
struct flow flow_filter;
struct flow_wildcards wc_filter;
+ char *types_list = NULL;
+ struct dump_types dump_types;
+ struct dpif_flow_dump_types dpif_dump_types;
struct dpif_flow_dump_thread *flow_dump_thread;
struct dpif_flow_dump *flow_dump;
@@ -903,8 +972,8 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
lastargc = argc;
if (!strncmp(argv[argc - 1], "filter=", 7) && !filter) {
filter = xstrdup(argv[--argc] + 7);
- } else if (!strncmp(argv[argc - 1], "type=", 5) && !type) {
- type = xstrdup(argv[--argc] + 5);
+ } else if (!strncmp(argv[argc - 1], "type=", 5) && !types_list) {
+ types_list = xstrdup(argv[--argc] + 5);
}
}
@@ -937,19 +1006,12 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
}
}
- if (type) {
- error = EINVAL;
- for (int i = 0; i < ARRAY_SIZE(supported_dump_types); i++) {
- if (!strcmp(supported_dump_types[i], type)) {
- error = 0;
- break;
- }
- }
- if (error) {
- dpctl_error(dpctl_p, error, "Failed to parse type (%s)", type);
- goto out_free;
- }
+ memset(&dump_types, 0, sizeof dump_types);
+ error = populate_dump_types(types_list, &dump_types, dpctl_p);
+ if (error) {
+ goto out_free;
}
+ determine_dpif_flow_dump_types(&dump_types, &dpif_dump_types);
/* Make sure that these values are different. PMD_ID_NULL means that the
* pmd is unspecified (e.g. because the datapath doesn't have different
@@ -959,7 +1021,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
ds_init(&ds);
memset(&f, 0, sizeof f);
- flow_dump = dpif_flow_dump_create(dpif, false, (type ? type : "dpctl"));
+ flow_dump = dpif_flow_dump_create(dpif, false, &dpif_dump_types);
flow_dump_thread = dpif_flow_dump_thread_create(flow_dump);
while (dpif_flow_dump_next(flow_dump_thread, &f, 1)) {
if (filter) {
@@ -995,7 +1057,7 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
}
pmd_id = f.pmd_id;
}
- if (!type || flow_passes_type_filter(&f, type)) {
+ if (flow_passes_type_filter(&f, &dump_types)) {
format_dpif_flow(&ds, &f, portno_names, dpctl_p);
dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
}
@@ -1013,7 +1075,7 @@ out_dpifclose:
dpif_close(dpif);
out_free:
free(filter);
- free(type);
+ free(types_list);
return error;
}
diff --git a/lib/dpctl.man b/lib/dpctl.man
index 68274d808..9b13e0d6f 100644
--- a/lib/dpctl.man
+++ b/lib/dpctl.man
@@ -118,10 +118,16 @@ The \fIfilter\fR is also useful to match wildcarded fields in the datapath
flow. As an example, \fBfilter='tcp,tp_src=100'\fR will match the
datapath flow containing '\fBtcp(src=80/0xff00,dst=8080/0xff)\fR'.
.IP
-If \fBtype=\fItype\fR is specified, only displays flows of a specific type.
-\fItype\fR can be \fBoffloaded\fR to display only rules offloaded to the HW
-or \fBovs\fR to display only rules from the OVS tables.
-By default all rules are displayed.
+If \fBtype=\fItype\fR is specified, only displays flows of the specified types.
+\fItype\fR is a comma separated list, which can contain any of the following:
+.
+ \fBovs\fR - displays flows handled in the ovs dp
+ \fBtc\fR - displays flows handled in the tc dp
+ \fBoffloaded\fR - displays flows offloaded to the HW
+ \fBnon-offloaded\fR - displays flows not offloaded to the HW
+ \fBall\fR - displays all the types of flows
+.IP
+By default all the types of flows are displayed.
.
.IP "\*(DX\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR"
.TP
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index eb862f3f8..9fb82ccd4 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -3491,7 +3491,7 @@ 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,
- char *type OVS_UNUSED)
+ struct dpif_flow_dump_types *types OVS_UNUSED)
{
struct dpif_netdev_flow_dump *dump;
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index e6d5a6ec5..3f52962ec 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -1465,16 +1465,6 @@ dpif_netlink_init_flow_del(struct dpif_netlink *dpif,
del->ufid, del->terse, request);
}
-enum {
- DUMP_OVS_FLOWS_BIT = 0,
- DUMP_NETDEV_FLOWS_BIT = 1,
-};
-
-enum {
- DUMP_OVS_FLOWS = (1 << DUMP_OVS_FLOWS_BIT),
- DUMP_NETDEV_FLOWS = (1 << DUMP_NETDEV_FLOWS_BIT),
-};
-
struct dpif_netlink_flow_dump {
struct dpif_flow_dump up;
struct nl_dump nl_dump;
@@ -1483,7 +1473,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 */
+ struct dpif_flow_dump_types types; /* Type of dump */
};
static struct dpif_netlink_flow_dump *
@@ -1498,7 +1488,7 @@ start_netdev_dump(const struct dpif *dpif_,
{
ovs_mutex_init(&dump->netdev_lock);
- if (!(dump->type & DUMP_NETDEV_FLOWS)) {
+ if (!(dump->types.netdev_flows)) {
dump->netdev_dumps_num = 0;
dump->netdev_dumps = NULL;
return;
@@ -1512,24 +1502,21 @@ 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_is_flow_api_enabled() && !str)
- || (str && (!strcmp(str, "offloaded") || !strcmp(str, "dpctl")))) {
- type |= DUMP_NETDEV_FLOWS;
+static void
+dpif_netlink_populate_flow_dump_types(struct dpif_netlink_flow_dump *dump,
+ struct dpif_flow_dump_types *types)
+{
+ if (!types) {
+ dump->types.ovs_flows = true;
+ dump->types.netdev_flows = true;
+ } else {
+ memcpy(&dump->types, types, sizeof *types);
}
-
- return type;
}
static struct dpif_flow_dump *
dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse,
- char *type)
+ struct dpif_flow_dump_types *types)
{
const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_);
struct dpif_netlink_flow_dump *dump;
@@ -1539,9 +1526,9 @@ dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse,
dump = xmalloc(sizeof *dump);
dpif_flow_dump_init(&dump->up, dpif_);
- dump->type = dpif_netlink_get_dump_type(type);
+ dpif_netlink_populate_flow_dump_types(dump, types);
- if (dump->type & DUMP_OVS_FLOWS) {
+ if (dump->types.ovs_flows) {
dpif_netlink_flow_init(&request);
request.cmd = OVS_FLOW_CMD_GET;
request.dp_ifindex = dpif->dp_ifindex;
@@ -1568,7 +1555,7 @@ dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_)
unsigned int nl_status = 0;
int dump_status;
- if (dump->type & DUMP_OVS_FLOWS) {
+ if (dump->types.ovs_flows) {
nl_status = nl_dump_done(&dump->nl_dump);
}
@@ -1804,7 +1791,7 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
}
}
- if (!(dump->type & DUMP_OVS_FLOWS)) {
+ if (!(dump->types.ovs_flows)) {
return n_flows;
}
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 873b6e3d4..debdafc42 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -284,9 +284,11 @@ struct dpif_class {
* If 'terse' is true, then only UID and statistics will
* 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, char *type);
+ * If 'types' isn't null, dumps only the flows of the passed types. */
+ struct dpif_flow_dump *(*flow_dump_create)(
+ const struct dpif *dpif,
+ bool terse,
+ struct dpif_flow_dump_types *types);
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 d799f972c..85cf9000e 100644
--- a/lib/dpif.c
+++ b/lib/dpif.c
@@ -1080,9 +1080,10 @@ 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, char *type)
+dpif_flow_dump_create(const struct dpif *dpif, bool terse,
+ struct dpif_flow_dump_types *types)
{
- return dpif->dpif_class->flow_dump_create(dpif, terse, type);
+ return dpif->dpif_class->flow_dump_create(dpif, terse, types);
}
/* Destroys 'dump', which must have been created with dpif_flow_dump_create().
diff --git a/lib/dpif.h b/lib/dpif.h
index bbdc3eb6c..8fdfe5f00 100644
--- a/lib/dpif.h
+++ b/lib/dpif.h
@@ -512,6 +512,11 @@ struct dpif_flow_attrs {
const char *dp_layer; /* DP layer the flow is handled in. */
};
+struct dpif_flow_dump_types {
+ bool ovs_flows;
+ bool netdev_flows;
+};
+
void dpif_flow_stats_extract(const struct flow *, const struct dp_packet *packet,
long long int used, struct dpif_flow_stats *);
void dpif_flow_stats_format(const struct dpif_flow_stats *, struct ds *);
@@ -573,7 +578,7 @@ 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,
- char *type);
+ struct dpif_flow_dump_types *);
int dpif_flow_dump_destroy(struct dpif_flow_dump *);
struct dpif_flow_dump_thread *dpif_flow_dump_thread_create(