[ovs-dev] [PATCH] vswitchd: Dump QoS with appctl.
Ethan Jackson
ethan at nicira.com
Mon Mar 14 23:49:26 UTC 2011
The source of truth for QoS statistics on a given interface is tc.
Unfortunately, output from tc can be a little bit confusing and
does not follow the same data model as OVS. This commit adds a
"qos/show" appctl command which gives friendlier output.
---
vswitchd/bridge.c | 113 ++++++++++++++++++++++++++++++++++++++++++++
vswitchd/ovs-vswitchd.8.in | 3 +
2 files changed, 116 insertions(+), 0 deletions(-)
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 1558d3b..dc9ca53 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -281,6 +281,7 @@ static struct iface *bridge_get_local_iface(struct bridge *);
static uint64_t dpid_from_hash(const void *, size_t nbytes);
static unixctl_cb_func bridge_unixctl_fdb_show;
+static unixctl_cb_func qos_unixctl_show;
static void lacp_run(struct bridge *);
static void lacp_wait(struct bridge *);
@@ -314,6 +315,7 @@ static struct iface *iface_create(struct port *port,
const struct ovsrec_interface *if_cfg);
static void iface_destroy(struct iface *);
static struct iface *iface_lookup(const struct bridge *, const char *name);
+static struct iface *iface_find(const char *name);
static struct iface *iface_from_dp_ifidx(const struct bridge *,
uint16_t dp_ifidx);
static void iface_set_mac(struct iface *);
@@ -362,6 +364,7 @@ bridge_init(const char *remote)
/* Register unixctl commands. */
unixctl_command_register("fdb/show", bridge_unixctl_fdb_show, NULL);
+ unixctl_command_register("qos/show", qos_unixctl_show, NULL);
unixctl_command_register("bridge/dump-flows", bridge_unixctl_dump_flows,
NULL);
unixctl_command_register("bridge/reconnect", bridge_unixctl_reconnect,
@@ -1567,6 +1570,101 @@ bridge_unixctl_fdb_show(struct unixctl_conn *conn,
ds_destroy(&ds);
}
+/* QoS unixctl user interface functions. */
+
+struct qos_unixctl_show_cbdata {
+ struct ds *ds;
+ struct iface *iface;
+};
+
+static void
+qos_unixctl_show_cb(unsigned int queue_id,
+ const struct shash *details,
+ void *aux)
+{
+ struct qos_unixctl_show_cbdata *data = aux;
+ struct ds *ds = data->ds;
+ struct iface *iface = data->iface;
+ struct netdev_queue_stats stats;
+ struct shash_node *node;
+ int error;
+
+ ds_put_cstr(ds, "\n");
+ if (queue_id) {
+ ds_put_format(ds, "Queue %u:\n", queue_id);
+ } else {
+ ds_put_cstr(ds, "Default:\n");
+ }
+
+ SHASH_FOR_EACH (node, details) {
+ ds_put_format(ds, "\t%s: %s\n", node->name, (char *)node->data);
+ }
+
+ error = netdev_get_queue_stats(iface->netdev, queue_id, &stats);
+ if (!error) {
+ if (stats.tx_packets != UINT64_MAX) {
+ ds_put_format(ds, "\ttx_packets: %"PRIu64"\n", stats.tx_packets);
+ }
+
+ if (stats.tx_bytes != UINT64_MAX) {
+ ds_put_format(ds, "\ttx_bytes: %"PRIu64"\n", stats.tx_bytes);
+ }
+
+ if (stats.tx_errors != UINT64_MAX) {
+ ds_put_format(ds, "\ttx_errors: %"PRIu64"\n", stats.tx_errors);
+ }
+ } else {
+ VLOG_WARN("Failed to get statistics for queue %u: %s",
+ queue_id, strerror(error));
+ }
+}
+
+static void
+qos_unixctl_show(struct unixctl_conn *conn,
+ const char *args, void *aux OVS_UNUSED)
+{
+ struct ds ds = DS_EMPTY_INITIALIZER;
+ struct shash sh = SHASH_INITIALIZER(&sh);
+ struct iface *iface;
+ const char *type;
+ struct shash_node *node;
+ struct qos_unixctl_show_cbdata data;
+ int error;
+
+ iface = iface_find(args);
+ if (!iface) {
+ unixctl_command_reply(conn, 501, "no such interface");
+ return;
+ }
+
+ netdev_get_qos(iface->netdev, &type, &sh);
+
+ if (*type != '\0') {
+ ds_put_format(&ds, "QoS: %s %s\n", iface->name, type);
+
+ SHASH_FOR_EACH (node, &sh) {
+ ds_put_format(&ds, "%s: %s\n", node->name, (char *)node->data);
+ }
+
+ data.ds = &ds;
+ data.iface = iface;
+ error = netdev_dump_queues(iface->netdev, qos_unixctl_show_cb, &data);
+
+ if (error > 0) {
+ VLOG_WARN("failed to dump queues: %s", strerror(error));
+ ds_put_cstr(&ds, "errors occured during query. "
+ "Results may not be accurate.\n");
+ }
+ unixctl_command_reply(conn, 200, ds_cstr(&ds));
+ } else {
+ ds_put_format(&ds, "QoS not configured on %s\n", iface->name);
+ unixctl_command_reply(conn, 501, ds_cstr(&ds));
+ }
+
+ shash_destroy_free_data(&sh);
+ ds_destroy(&ds);
+}
+
/* Bridge reconfiguration functions. */
static struct bridge *
bridge_create(const struct ovsrec_bridge *br_cfg)
@@ -4760,6 +4858,21 @@ iface_lookup(const struct bridge *br, const char *name)
}
static struct iface *
+iface_find(const char *name)
+{
+ const struct bridge *br;
+
+ LIST_FOR_EACH (br, node, &all_bridges) {
+ struct iface *iface = iface_lookup(br, name);
+
+ if (iface) {
+ return iface;
+ }
+ }
+ return NULL;
+}
+
+static struct iface *
iface_from_dp_ifidx(const struct bridge *br, uint16_t dp_ifidx)
{
struct iface *iface;
diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
index f0badf0..225936c 100644
--- a/vswitchd/ovs-vswitchd.8.in
+++ b/vswitchd/ovs-vswitchd.8.in
@@ -113,6 +113,9 @@ how to configure Open vSwitch.
.SS "GENERAL COMMANDS"
.IP "\fBexit\fR"
Causes \fBovs\-vswitchd\fR to gracefully terminate.
+.IP "\fBqos/show\fR \fIinterface\fR"
+Queries the kernel for Quality of Service configuration and statistics
+associated with the given \fIinterface\fR.
.SS "BRIDGE COMMANDS"
These commands manage bridges.
.IP "\fBfdb/show\fR \fIbridge\fR"
--
1.7.4.1
More information about the dev
mailing list