datapaths are displayed. Otherwise, \fBovs\-dpctl\fR displays information
about all configured datapaths.
.
-.IP "\fBdump\-flows \fIdp\fR"
+.IP "\fBdump\-flows\fR [\fIdp\fR]"
Prints to the console all flow entries in datapath \fIdp\fR's
-flow table.
+flow table. If \fIdp\fR is not specified and exactly one datapath
+exists, the flows for that datapath will be printed.
.IP
This command is primarily useful for debugging Open vSwitch. The flow
table entries that it displays are not
OpenFlow flow entries. Instead, they are different and considerably
simpler flows maintained by the Open vSwitch kernel module. If you wish
to see the OpenFlow flow entries, use \fBovs\-ofctl dump\-flows\fR.
-.IP "\fBdel\-flows \fIdp\fR"
-Deletes all flow entries from datapath \fIdp\fR's flow table.
+.
+.IP "\fBdel\-flows\fR [\fIdp\fR]"
+Deletes all flow entries from datapath \fIdp\fR's flow table. If
+\fIdp\fR is not specified and exactly one datapath exists, the flows for
+that datapath will be deleted.
.IP
This command is primarily useful for debugging Open vSwitch. As
discussed in \fBdump\-flows\fR, these entries are
return retval;
}
+/* Retrieve the name of the datapath if exactly one exists. The caller
+ * is responsible for freeing the returned string. If there is not one
+ * datapath, aborts with an error message. */
+static char *
+get_one_dp(void)
+{
+ struct sset types;
+ const char *type;
+ char *dp_name = NULL;
+ size_t count = 0;
+
+ sset_init(&types);
+ dp_enumerate_types(&types);
+ SSET_FOR_EACH (type, &types) {
+ struct sset names;
+
+ sset_init(&names);
+ if (!dp_enumerate_names(type, &names)) {
+ count += sset_count(&names);
+ if (!dp_name && count == 1) {
+ dp_name = xasprintf("%s@%s", type, SSET_FIRST(&names));
+ }
+ }
+ sset_destroy(&names);
+ }
+ sset_destroy(&types);
+
+ if (!count) {
+ ovs_fatal(0, "no datapaths exist");
+ } else if (count > 1) {
+ ovs_fatal(0, "multiple datapaths, specify one");
+ }
+
+ return dp_name;
+}
+
static int
parsed_dpif_open(const char *arg_, bool create, struct dpif **dpifp)
{
}
static void
-dpctl_dump_flows(int argc OVS_UNUSED, char *argv[])
+dpctl_dump_flows(int argc, char *argv[])
{
const struct dpif_flow_stats *stats;
const struct nlattr *actions;
struct dpif *dpif;
size_t key_len;
struct ds ds;
+ char *name;
- run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
+ name = (argc == 2) ? xstrdup(argv[1]) : get_one_dp();
+ run(parsed_dpif_open(name, false, &dpif), "opening datapath");
+ free(name);
ds_init(&ds);
dpif_flow_dump_start(&dump, dpif);
}
static void
-dpctl_del_flows(int argc OVS_UNUSED, char *argv[])
+dpctl_del_flows(int argc, char *argv[])
{
struct dpif *dpif;
+ char *name;
+
+ name = (argc == 2) ? xstrdup(argv[1]) : get_one_dp();
+ run(parsed_dpif_open(name, false, &dpif), "opening datapath");
+ free(name);
- run(parsed_dpif_open(argv[1], false, &dpif), "opening datapath");
run(dpif_flow_flush(dpif), "deleting all flows");
dpif_close(dpif);
}
{ "set-if", 2, INT_MAX, dpctl_set_if },
{ "dump-dps", 0, 0, dpctl_dump_dps },
{ "show", 0, INT_MAX, dpctl_show },
- { "dump-flows", 1, 1, dpctl_dump_flows },
- { "del-flows", 1, 1, dpctl_del_flows },
+ { "dump-flows", 0, 1, dpctl_dump_flows },
+ { "del-flows", 0, 1, dpctl_del_flows },
{ "help", 0, INT_MAX, dpctl_help },
/* Undocumented commands for testing. */