summaryrefslogtreecommitdiff
path: root/utilities
diff options
context:
space:
mode:
authorGurucharan Shetty <gshetty@nicira.com>2013-10-13 12:44:20 -0700
committerGurucharan Shetty <gshetty@nicira.com>2013-10-17 09:57:23 -0700
commit5a0a5702555d22f9a4d86739455516723cd5ba08 (patch)
tree6784b5eebfc3eed07f08f6b886d112262f4e8de6 /utilities
parentaa0667bcdbe79074c8c55cc529f10570da5798cb (diff)
downloadopenvswitch-5a0a5702555d22f9a4d86739455516723cd5ba08.tar.gz
ovs-dpctl: Add a 'filter' option to match wildcarded 'dump-flows'.
With mega-flows, many flows in the kernel datapath are wildcarded. For someone that is debugging a system and wants to find a particular flow and its actions, it is a little hard to zero-in on the flow because some fields are wildcarded. With the filter='$filter' option, we can now filter on the o/p of 'ovs-dpctl dump-flows'. Signed-off-by: Gurucharan Shetty <gshetty@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'utilities')
-rw-r--r--utilities/ovs-dpctl.8.in10
-rw-r--r--utilities/ovs-dpctl.c47
2 files changed, 54 insertions, 3 deletions
diff --git a/utilities/ovs-dpctl.8.in b/utilities/ovs-dpctl.8.in
index 5c0157028..35d1be590 100644
--- a/utilities/ovs-dpctl.8.in
+++ b/utilities/ovs-dpctl.8.in
@@ -118,11 +118,19 @@ exactly one datapath exists, in which case that datapath is the
default. When multiple datapaths exist, then a datapath name is
required.
.
-.IP "[\fB\-m \fR| \fB\-\-more\fR] \fBdump\-flows\fR [\fIdp\fR]"
+.IP "[\fB\-m \fR| \fB\-\-more\fR] \fBdump\-flows\fR [\fIdp\fR] [\fBfilter=\fIfilter\fR]"
Prints to the console all flow entries in datapath \fIdp\fR's flow
table. Without \fB\-m\fR or \fB\-\-more\fR, output omits match fields
that a flow wildcards entirely; with \fB\-m\fR or \fB\-\-more\fR,
output includes all wildcarded fields.
+.IP
+If \fBfilter=\fIfilter\fR is specified, only displays the flows
+that match the \fIfilter\fR. \fIfilter\fR is a flow in the form similiar
+to that accepted by \fBovs\-ofctl\fR(8)'s \fBadd\-flow\fR command. (This is
+not an OpenFlow flow: besides other differences, it never contains wildcards.)
+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 "\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR"
.IQ "[\fB\-\-clear\fR] [\fB\-\-may-create\fR] [\fB\-s\fR | \fB\-\-statistics\fR] \fBmod\-flow\fR [\fIdp\fR] \fIflow actions\fR"
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index 4fb02dda4..e11e102e3 100644
--- a/utilities/ovs-dpctl.c
+++ b/utilities/ovs-dpctl.c
@@ -36,9 +36,11 @@
#include "dpif.h"
#include "dynamic-string.h"
#include "flow.h"
+#include "match.h"
#include "netdev.h"
#include "netlink.h"
#include "odp-util.h"
+#include "ofp-parse.h"
#include "ofpbuf.h"
#include "packets.h"
#include "shash.h"
@@ -746,20 +748,38 @@ dpctl_dump_flows(int argc, char *argv[])
struct dpif_port dpif_port;
struct dpif_port_dump port_dump;
struct hmap portno_names;
+ struct simap names_portno;
size_t actions_len;
struct dpif *dpif;
size_t key_len;
size_t mask_len;
struct ds ds;
- char *name;
+ char *name, *error, *filter = NULL;
+ struct flow flow_filter;
+ struct flow_wildcards wc_filter;
+ if (argc > 1 && !strncmp(argv[argc - 1], "filter=", 7)) {
+ filter = xstrdup(argv[--argc] + 7);
+ }
name = (argc == 2) ? xstrdup(argv[1]) : get_one_dp();
+
run(parsed_dpif_open(name, false, &dpif), "opening datapath");
free(name);
hmap_init(&portno_names);
+ simap_init(&names_portno);
DPIF_PORT_FOR_EACH (&dpif_port, &port_dump, dpif) {
odp_portno_names_set(&portno_names, dpif_port.port_no, dpif_port.name);
+ simap_put(&names_portno, dpif_port.name,
+ odp_to_u32(dpif_port.port_no));
+ }
+
+ if (filter) {
+ error = parse_ofp_exact_flow(&flow_filter, &wc_filter.masks, filter,
+ &names_portno);
+ if (error) {
+ ovs_fatal(0, "Failed to parse filter (%s)", error);
+ }
}
ds_init(&ds);
@@ -767,6 +787,26 @@ dpctl_dump_flows(int argc, char *argv[])
while (dpif_flow_dump_next(&flow_dump, &key, &key_len,
&mask, &mask_len,
&actions, &actions_len, &stats)) {
+ if (filter) {
+ struct flow flow;
+ struct flow_wildcards wc;
+ struct match match, match_filter;
+ struct minimatch minimatch;
+
+ odp_flow_key_to_flow(key, key_len, &flow);
+ odp_flow_key_to_mask(mask, mask_len, &wc.masks, &flow);
+ match_init(&match, &flow, &wc);
+
+ match_init(&match_filter, &flow_filter, &wc);
+ match_init(&match_filter, &match_filter.flow, &wc_filter);
+ minimatch_init(&minimatch, &match_filter);
+
+ if (!minimatch_matches_flow(&minimatch, &match.flow)) {
+ minimatch_destroy(&minimatch);
+ continue;
+ }
+ minimatch_destroy(&minimatch);
+ }
ds_clear(&ds);
odp_flow_format(key, key_len, mask, mask_len, &portno_names, &ds,
verbosity);
@@ -778,8 +818,11 @@ dpctl_dump_flows(int argc, char *argv[])
printf("%s\n", ds_cstr(&ds));
}
dpif_flow_dump_done(&flow_dump);
+
+ free(filter);
odp_portno_names_destroy(&portno_names);
hmap_destroy(&portno_names);
+ simap_destroy(&names_portno);
ds_destroy(&ds);
dpif_close(dpif);
}
@@ -1166,7 +1209,7 @@ static const struct command all_commands[] = {
{ "set-if", 2, INT_MAX, dpctl_set_if },
{ "dump-dps", 0, 0, dpctl_dump_dps },
{ "show", 0, INT_MAX, dpctl_show },
- { "dump-flows", 0, 1, dpctl_dump_flows },
+ { "dump-flows", 0, 2, dpctl_dump_flows },
{ "add-flow", 2, 3, dpctl_add_flow },
{ "mod-flow", 2, 3, dpctl_mod_flow },
{ "del-flow", 1, 2, dpctl_del_flow },