datapaths are displayed. Otherwise, \fBdpctl\fR displays information
about all configured datapaths.
+.IP "\fBdp-dump-flows \fIdp\fR"
+Prints to the console all flow entries in datapath \fIdp\fR's
+flow table.
+
+This command is primarily useful for debugging the OpenFlow reference
+implementation. The flow table entries that it displays are not
+OpenFlow flow entries. Instead, they are different and considerably
+simpler flows maintained by the datapaths used by the OpenFlow
+reference implementation.
+
+.IP "\fBdp-dump-groups \fIdp\fR"
+Prints to the console the sets of port groups maintained by datapath
+\fIdp\fR. Ordinarily there are at least 2 port groups in a datapath
+that \fBsecchan\fR or \fBvswitch\fR is controlling: group 0 contains
+all ports except those disabled by STP, and group 1 contains all
+ports. Additional groups might be used in the future.
+
+This command is primarily useful for debugging the OpenFlow reference
+implementation. OpenFlow does not have a concept of port groups.
+
.SS "OpenFlow Switch Management Commands"
These commands allow \fBdpctl\fR to monitor and administer an OpenFlow
#include "command-line.h"
#include "compiler.h"
#include "dpif.h"
+#include "dynamic-string.h"
#include "netdev.h"
#include "netlink.h"
+#include "odp-util.h"
#include "ofp-print.h"
#include "ofpbuf.h"
#include "openflow/nicira-ext.h"
" delif DP IFACE... delete each IFACE from DP\n"
" showdp show basic info on all datapaths\n"
" showdp DP... show basic info on each DP\n"
+ " dp-dump-flows DP display flows in DP\n"
+ " dp-dump-groups DP display port groups in DP\n"
"\nFor OpenFlow switches:\n"
" show SWITCH show OpenFlow information\n"
" status SWITCH [KEY] report statistics (about KEY)\n"
show_dpif(struct dpif *dpif)
{
struct odp_port *ports;
+ struct odp_stats stats;
size_t n_ports;
size_t i;
printf("dp%u:\n", dpif_id(dpif));
+ if (!dpif_get_dp_stats(dpif, &stats)) {
+ printf("\tflows: cur:%"PRIu32", soft-max:%"PRIu32", "
+ "hard-max:%"PRIu32"\n",
+ stats.n_flows, stats.cur_capacity, stats.max_capacity);
+ printf("\tports: cur:%"PRIu32", max:%"PRIu32"\n",
+ stats.n_ports, stats.max_ports);
+ printf("\tgroups: max:%"PRIu16"\n", stats.max_groups);
+ printf("\tlookups: frags:%"PRIu64", hit:%"PRIu64", missed:%"PRIu64", "
+ "lost:%"PRIu64"\n",
+ stats.n_frags, stats.n_hit, stats.n_missed, stats.n_lost);
+ printf("\tqueues: max-miss:%"PRIu16", max-action:%"PRIu16"\n",
+ stats.max_miss_queue, stats.max_action_queue);
+ }
query_ports(dpif, &ports, &n_ports);
for (i = 0; i < n_ports; i++) {
printf("\tport %u: %s\n", ports[i].port, ports[i].devname);
}
}
+static void
+do_dp_dump_flows(const struct settings *s UNUSED,
+ int argc UNUSED, char *argv[])
+{
+ struct odp_flow *flows;
+ struct dpif dpif;
+ size_t n_flows;
+ struct ds ds;
+ size_t i;
+
+ run(dpif_open(argv[1], &dpif), "opening datapath");
+ run(dpif_flow_list_all(&dpif, &flows, &n_flows), "listing all flows");
+
+ ds_init(&ds);
+ for (i = 0; i < n_flows; i++) {
+ struct odp_flow *f = &flows[i];
+ enum { MAX_ACTIONS = 4096 / sizeof(union odp_action) };
+ union odp_action actions[MAX_ACTIONS];
+
+ f->actions = actions;
+ f->n_actions = MAX_ACTIONS;
+ dpif_flow_query(&dpif, f);
+
+ ds_clear(&ds);
+ format_odp_flow(&ds, f);
+ printf("%s\n", ds_cstr(&ds));
+ }
+ ds_destroy(&ds);
+ dpif_close(&dpif);
+}
+
+static void
+do_dp_dump_groups(const struct settings *s UNUSED,
+ int argc UNUSED, char *argv[])
+{
+ struct odp_stats stats;
+ struct dpif dpif;
+ unsigned int i;
+
+ run(dpif_open(argv[1], &dpif), "opening datapath");
+ run(dpif_get_dp_stats(&dpif, &stats), "get datapath stats");
+ for (i = 0; i < stats.max_groups; i++) {
+ uint16_t ports[UINT16_MAX];
+ size_t n_ports;
+
+ if (!dpif_port_group_get(&dpif, i, ports,
+ ARRAY_SIZE(ports), &n_ports) && n_ports) {
+ size_t j;
+
+ printf("group %u:", i);
+ for (j = 0; j < n_ports; j++) {
+ printf(" %"PRIu16, ports[j]);
+ }
+ printf("\n");
+ }
+ }
+ dpif_close(&dpif);
+}
\f
/* Generic commands. */
{ "get-idx", 1, 1, do_get_idx },
{ "get-name", 1, 1, do_get_name },
{ "showdp", 0, INT_MAX, do_show_dp },
+ { "dp-dump-flows", 1, 1, do_dp_dump_flows },
+ { "dp-dump-groups", 1, 1, do_dp_dump_groups },
#endif
{ "show", 1, 1, do_show },