From 326f142fa014252fb0788c80266ef1bea772e7c5 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 13 Mar 2009 16:03:42 -0700 Subject: [PATCH] dpctl: Add dp-dump-flows, dp-dump-groups commands. These should make it easier to debug datapath-related problems. --- utilities/dpctl.8.in | 20 ++++++++++++ utilities/dpctl.c | 78 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/utilities/dpctl.8.in b/utilities/dpctl.8.in index bf62c7b3..e421aa25 100644 --- a/utilities/dpctl.8.in +++ b/utilities/dpctl.8.in @@ -100,6 +100,26 @@ If one or more datapaths are specified, information on only those 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 diff --git a/utilities/dpctl.c b/utilities/dpctl.c index 053e8e0a..f66f9219 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -48,8 +48,10 @@ #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" @@ -215,6 +217,8 @@ usage(void) " 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" @@ -465,10 +469,24 @@ static void 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); @@ -518,6 +536,64 @@ do_show_dp(const struct settings *s UNUSED, int argc UNUSED, char *argv[]) } } +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); +} /* Generic commands. */ @@ -1526,6 +1602,8 @@ static struct command all_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 }, -- 2.30.2