[ovs-dev] [PATCH v2 1/2] ofproto: Device stats should include packets generated by userspace/controller
Pravin B Shelar
pshelar at nicira.com
Thu Dec 8 20:53:33 UTC 2011
Fixed according to comments from Ben.
v1-v2:
- updated comments
- added UINT64_MAX check before updating stats
- removed memset from ofproto_port_get_stats()
--8<--------------------------cut here-------------------------->8--
Following patch account packets consumed and composed in userspace
as received on and transmitted from local port.
---
ofproto/ofproto-dpif.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
ofproto/ofproto-provider.h | 4 +++
ofproto/ofproto.c | 17 +++++++++++-
ofproto/ofproto.h | 3 ++
4 files changed, 86 insertions(+), 1 deletions(-)
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index bca9b8d..9e6b32f 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -508,6 +508,8 @@ struct ofproto_dpif {
struct list completions;
bool has_bundle_action; /* True when the first bundle action appears. */
+ struct netdev_stats stats; /* To account packets generated and consumed in
+ * userspace. */
/* Spanning tree. */
struct stp *stp;
@@ -2209,6 +2211,63 @@ port_del(struct ofproto *ofproto_, uint16_t ofp_port)
return error;
}
+static int
+port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+ int error;
+
+ error = netdev_get_stats(ofport->up.netdev, stats);
+
+ if (!error && ofport->odp_port == OVSP_LOCAL) {
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto);
+
+ /* ofproto->stats.tx_packets represents packets that we created
+ * internally and sent to some port (e.g. packets sent with
+ * send_packet()). Account for them as if they had come from
+ * OFPP_LOCAL and got forwarded. */
+
+ if (stats->rx_packets != UINT64_MAX) {
+ stats->rx_packets += ofproto->stats.tx_packets;
+ }
+
+ if (stats->rx_bytes != UINT64_MAX) {
+ stats->rx_bytes += ofproto->stats.tx_bytes;
+ }
+
+ /* ofproto->stats.rx_packets represents packets that were received on
+ * some port and we processed internally and dropped (e.g. STP).
+ * Account fro them as if they had been forwarded to OFPP_LOCAL. */
+
+ if (stats->tx_packets != UINT64_MAX) {
+ stats->tx_packets += ofproto->stats.rx_packets;
+ }
+
+ if (stats->tx_bytes != UINT64_MAX) {
+ stats->tx_bytes += ofproto->stats.rx_bytes;
+ }
+ }
+
+ return error;
+}
+
+/* Account packets for LOCAL port. */
+static void
+ofproto_update_local_port_stats(const struct ofproto *ofproto_,
+ size_t tx_size, size_t rx_size)
+{
+ struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
+
+ if (rx_size) {
+ ofproto->stats.rx_packets++;
+ ofproto->stats.rx_bytes += rx_size;
+ }
+ if (tx_size) {
+ ofproto->stats.tx_packets++;
+ ofproto->stats.tx_bytes += tx_size;
+ }
+}
+
struct port_dump_state {
struct dpif_port_dump dump;
bool done;
@@ -2580,6 +2639,8 @@ handle_miss_upcalls(struct ofproto_dpif *ofproto, struct dpif_upcall *upcalls,
/* Handle 802.1ag, LACP, and STP specially. */
if (process_special(ofproto, &flow, upcall->packet)) {
+ ofproto_update_local_port_stats(&ofproto->up,
+ 0, upcall->packet->size);
ofpbuf_delete(upcall->packet);
ofproto->n_matches++;
continue;
@@ -3926,6 +3987,7 @@ send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet)
VLOG_WARN_RL(&rl, "%s: failed to send packet on port %"PRIu32" (%s)",
ofproto->up.name, odp_port, strerror(error));
}
+ ofproto_update_local_port_stats(ofport->up.ofproto, packet->size, 0);
return error;
}
@@ -5903,6 +5965,7 @@ const struct ofproto_class ofproto_dpif_class = {
port_query_by_name,
port_add,
port_del,
+ port_get_stats,
port_dump_start,
port_dump_next,
port_dump_done,
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 6576069..6c8583e 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -494,6 +494,10 @@ struct ofproto_class {
* convenient. */
int (*port_del)(struct ofproto *ofproto, uint16_t ofp_port);
+ /* Get port stats */
+ int (*port_get_stats)(const struct ofport *port,
+ struct netdev_stats *stats);
+
/* Port iteration functions.
*
* The client might not be entirely in control of the ports within an
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index b81bd6b..b0a1a66 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1478,6 +1478,21 @@ ofproto_get_port(const struct ofproto *ofproto, uint16_t ofp_port)
return NULL;
}
+int
+ofproto_port_get_stats(const struct ofport *port, struct netdev_stats *stats)
+{
+ struct ofproto *ofproto = port->ofproto;
+ int error;
+
+ if (ofproto->ofproto_class->port_get_stats) {
+ error = ofproto->ofproto_class->port_get_stats(port, stats);
+ } else {
+ error = EOPNOTSUPP;
+ }
+
+ return error;
+}
+
static void
update_port(struct ofproto *ofproto, const char *name)
{
@@ -1950,7 +1965,7 @@ append_port_stat(struct ofport *port, struct list *replies)
/* Intentionally ignore return value, since errors will set
* 'stats' to all-1s, which is correct for OpenFlow, and
* netdev_get_stats() will log errors. */
- netdev_get_stats(port->netdev, &stats);
+ ofproto_port_get_stats(port, &stats);
ops = ofputil_append_stats_reply(sizeof *ops, replies);
ops->port_no = port->opp.port_no;
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index ccd8202..2d47878 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -37,7 +37,9 @@ struct cfm_settings;
struct cls_rule;
struct netdev;
struct ofproto;
+struct ofport;
struct shash;
+struct netdev_stats;
struct ofproto_controller_info {
bool is_connected;
@@ -187,6 +189,7 @@ int ofproto_port_dump_done(struct ofproto_port_dump *);
int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp);
int ofproto_port_del(struct ofproto *, uint16_t ofp_port);
+int ofproto_port_get_stats(const struct ofport *, struct netdev_stats *stats);
int ofproto_port_query_by_name(const struct ofproto *, const char *devname,
struct ofproto_port *);
--
1.7.1
More information about the dev
mailing list