From 018f1525ed26ad4872350105e066b6b1eac5e867 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 23 Jun 2010 11:02:46 -0700 Subject: [PATCH] bridge: Implement basic periodic update of interface statistics. --- vswitchd/bridge.c | 79 ++++++++++++++++++++++++++++++++++++ vswitchd/vswitch.ovsschema | 8 +++- vswitchd/vswitch.xml | 83 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 1 deletion(-) diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e4e582ca..3768eb9c 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -186,6 +186,11 @@ static struct list all_bridges = LIST_INITIALIZER(&all_bridges); /* OVSDB IDL used to obtain configuration. */ static struct ovsdb_idl *idl; +/* Each time this timer expires, the bridge fetches statistics for every + * interface and pushes them into the database. */ +#define IFACE_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ +static long long int iface_stats_timer = LLONG_MIN; + static struct bridge *bridge_create(const struct ovsrec_bridge *br_cfg); static void bridge_destroy(struct bridge *); static struct bridge *bridge_lookup(const char *name); @@ -286,6 +291,8 @@ bridge_configure_once(const struct ovsrec_open_vswitch *cfg) } already_configured_once = true; + iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL; + /* Get all the configured bridges' names from 'cfg' into 'bridge_names'. */ svec_init(&bridge_names); for (i = 0; i < cfg->n_bridges; i++) { @@ -1049,6 +1056,53 @@ dpid_from_hash(const void *data, size_t n) return eth_addr_to_uint64(hash); } +static void +iface_refresh_stats(struct iface *iface) +{ + struct iface_stat { + char *name; + int offset; + }; + static const struct iface_stat iface_stats[] = { + { "rx_packets", offsetof(struct netdev_stats, rx_packets) }, + { "tx_packets", offsetof(struct netdev_stats, tx_packets) }, + { "rx_bytes", offsetof(struct netdev_stats, rx_bytes) }, + { "tx_bytes", offsetof(struct netdev_stats, tx_bytes) }, + { "rx_dropped", offsetof(struct netdev_stats, rx_dropped) }, + { "tx_dropped", offsetof(struct netdev_stats, tx_dropped) }, + { "rx_errors", offsetof(struct netdev_stats, rx_errors) }, + { "tx_errors", offsetof(struct netdev_stats, tx_errors) }, + { "rx_frame_err", offsetof(struct netdev_stats, rx_frame_errors) }, + { "rx_over_err", offsetof(struct netdev_stats, rx_over_errors) }, + { "rx_crc_err", offsetof(struct netdev_stats, rx_crc_errors) }, + { "collisions", offsetof(struct netdev_stats, collisions) }, + }; + enum { N_STATS = ARRAY_SIZE(iface_stats) }; + const struct iface_stat *s; + + char *keys[N_STATS]; + int64_t values[N_STATS]; + int n; + + struct netdev_stats stats; + + /* Intentionally ignore return value, since errors will set 'stats' to + * all-1s, and we will deal with that correctly below. */ + netdev_get_stats(iface->netdev, &stats); + + n = 0; + for (s = iface_stats; s < &iface_stats[N_STATS]; s++) { + uint64_t value = *(uint64_t *) (((char *) &stats) + s->offset); + if (value != UINT64_MAX) { + keys[n] = s->name; + values[n] = value; + n++; + } + } + + ovsrec_interface_set_statistics(iface->cfg, keys, values, n); +} + void bridge_run(void) { @@ -1087,6 +1141,30 @@ bridge_run(void) bridge_reconfigure(&null_cfg); } } + + /* Refresh interface stats if necessary. */ + if (time_msec() >= iface_stats_timer) { + struct ovsdb_idl_txn *txn; + + txn = ovsdb_idl_txn_create(idl); + LIST_FOR_EACH (br, struct bridge, node, &all_bridges) { + size_t i; + + for (i = 0; i < br->n_ports; i++) { + struct port *port = br->ports[i]; + size_t j; + + for (j = 0; j < port->n_ifaces; j++) { + struct iface *iface = port->ifaces[j]; + iface_refresh_stats(iface); + } + } + } + ovsdb_idl_txn_commit(txn); + ovsdb_idl_txn_destroy(txn); /* XXX */ + + iface_stats_timer = time_msec() + IFACE_STATS_INTERVAL; + } } void @@ -1104,6 +1182,7 @@ bridge_wait(void) bond_wait(br); } ovsdb_idl_wait(idl); + poll_timer_wait_until(iface_stats_timer); } /* Forces 'br' to revalidate all of its flows. This is appropriate when 'br''s diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 8b6fb8ba..b38463b0 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -27,7 +27,10 @@ "type": {"key": "string", "value": {"type": "uuid", "refTable": "Capability"}, - "min": 0, "max": "unlimited"}}}, + "min": 0, "max": "unlimited"}}, + "statistics": { + "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, + "ephemeral": true}}, "maxRows": 1}, "Capability": { "columns": { @@ -130,6 +133,9 @@ "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "ofport": { "type": {"key": "integer", "min": 0, "max": 1}, + "ephemeral": true}, + "statistics": { + "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, "ephemeral": true}}}, "QoS": { "columns": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 0a3a6c23..b93a8db2 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -64,6 +64,26 @@ capability categories and the meaning of associated records. + + +

+ Key-value pairs that report statistics about a running Open_vSwitch + daemon. The current implementation updates these counters + periodically. In the future, we plan to, instead, update them only + when they are queried (e.g. using an OVSDB select + operation) and perhaps at other times, but not on any regular + periodic basis.

+

+ The currently defined key-value pairs are listed below. Some Open + vSwitch implementations may not support some statistics, in which + case those key-value pairs are omitted.

+
+
load-average
+
+ System load average multiplied by 100 and rounded to the nearest + integer.
+
+
@@ -529,6 +549,69 @@ field in the VIF record for this interface. + + +

+ Key-value pairs that report interface statistics. The current + implementation updates these counters periodically. In the future, + we plan to, instead, update them when an interface is created, when + they are queried (e.g. using an OVSDB select operation), + and just before an interface is deleted due to virtual interface + hot-unplug or VM shutdown, and perhaps at other times, but not on any + regular periodic basis.

+

+ The currently defined key-value pairs are listed below. These are + the same statistics reported by OpenFlow in its struct + ofp_port_stats structure. If an interface does not support a + given statistic, then that pair is omitted.

+
    +
  • + Successful transmit and receive counters: +
    +
    rx_packets
    +
    Number of received packets.
    +
    rx_bytes
    +
    Number of received bytes.
    +
    tx_packets
    +
    Number of transmitted packets.
    +
    tx_bytes
    +
    Number of transmitted bytes.
    +
    +
  • +
  • + Receive errors: +
    +
    rx_dropped
    +
    Number of packets dropped by RX.
    +
    rx_frame_err
    +
    Number of frame alignment errors.
    +
    rx_over_err
    +
    Number of packets with RX overrun.
    +
    rx_crc_err
    +
    Number of CRC errors.
    +
    rx_errors
    +
    + Total number of receive errors, greater than or equal + to the sum of the above. +
    +
    +
  • +
  • + Transmit errors: +
    +
    tx_dropped
    +
    Number of packets dropped by TX.
    +
    collisions
    +
    Number of collisions.
    +
    tx_errors
    +
    + Total number of transmit errors, greater + than or equal to the sum of the above. +
    +
    +
  • +
+
-- 2.30.2