[ovs-dev] [PATCH] Define UINT64_MAX as "unknown" in Open vSwitch specific interfaces.
Ben Pfaff
blp at nicira.com
Fri May 27 22:16:59 UTC 2011
Some hardware supports reporting packet or byte counters but not both, so
OVS has to be prepared for that.
Suggested-by: Justin Pettit <jpettit at nicira.com>
---
This patch applies after the async-flow-mod changes (currently pushed
to the "next" branch).
include/openflow/nicira-ext.h | 12 ++++++------
lib/ofp-util.c | 26 ++++++++++++++++++++------
lib/ofp-util.h | 12 ++++++------
ofproto/ofproto.c | 22 ++++++++++++++++++++--
ofproto/private.h | 3 ++-
5 files changed, 54 insertions(+), 21 deletions(-)
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 9107928..eb76f28 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -1293,8 +1293,8 @@ struct nx_flow_stats {
ovs_be16 match_len; /* Length of nx_match. */
uint8_t pad2[4]; /* Align to 64 bits. */
ovs_be64 cookie; /* Opaque controller-issued identifier. */
- ovs_be64 packet_count; /* Number of packets in flow. */
- ovs_be64 byte_count; /* Number of bytes in flow. */
+ ovs_be64 packet_count; /* Number of packets, UINT64_MAX if unknown. */
+ ovs_be64 byte_count; /* Number of bytes, UINT64_MAX if unknown. */
/* Followed by:
* - Exactly match_len (possibly 0) bytes containing the nx_match, then
* - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of
@@ -1329,10 +1329,10 @@ OFP_ASSERT(sizeof(struct nx_aggregate_stats_request) == 32);
* OFPST_AGGREGATE reply). */
struct nx_aggregate_stats_reply {
struct nicira_stats_msg nsm;
- ovs_be64 packet_count; /* Number of packets in flows. */
- ovs_be64 byte_count; /* Number of bytes in flows. */
- ovs_be32 flow_count; /* Number of flows. */
- uint8_t pad[4]; /* Align to 64 bits. */
+ ovs_be64 packet_count; /* Number of packets, UINT64_MAX if unknown. */
+ ovs_be64 byte_count; /* Number of bytes, UINT64_MAX if unknown. */
+ ovs_be32 flow_count; /* Number of flows. */
+ uint8_t pad[4]; /* Align to 64 bits. */
};
OFP_ASSERT(sizeof(struct nx_aggregate_stats_reply) == 48);
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index e72c47a..7f2ac16 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -1270,6 +1270,16 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
return 0;
}
+/* Returns 'count' unchanged except that UINT64_MAX becomes 0.
+ *
+ * We use this in situations where OVS internally uses UINT64_MAX to mean
+ * "value unknown" but OpenFlow 1.0 does not define any unknown value. */
+static uint64_t
+unknown_to_zero(uint64_t count)
+{
+ return count != UINT64_MAX ? count : 0;
+}
+
/* Appends an OFPST_FLOW or NXST_FLOW reply that contains the data in 'fs' to
* those already present in the list of ofpbufs in 'replies'. 'replies' should
* have been initialized with ofputil_start_stats_reply(). */
@@ -1297,8 +1307,10 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
ofs->idle_timeout = htons(fs->idle_timeout);
ofs->hard_timeout = htons(fs->hard_timeout);
memset(ofs->pad2, 0, sizeof ofs->pad2);
- put_32aligned_be64(&ofs->packet_count, htonll(fs->packet_count));
- put_32aligned_be64(&ofs->byte_count, htonll(fs->byte_count));
+ put_32aligned_be64(&ofs->packet_count,
+ htonll(unknown_to_zero(fs->packet_count)));
+ put_32aligned_be64(&ofs->byte_count,
+ htonll(unknown_to_zero(fs->byte_count)));
memcpy(ofs->actions, fs->actions, act_len);
} else if (osm->type == htons(OFPST_VENDOR)) {
struct nx_flow_stats *nfs;
@@ -1342,8 +1354,10 @@ ofputil_encode_aggregate_stats_reply(
struct ofp_aggregate_stats_reply *asr;
asr = ofputil_make_stats_reply(sizeof *asr, request, &msg);
- put_32aligned_be64(&asr->packet_count, htonll(stats->packet_count));
- put_32aligned_be64(&asr->byte_count, htonll(stats->byte_count));
+ put_32aligned_be64(&asr->packet_count,
+ htonll(unknown_to_zero(stats->packet_count)));
+ put_32aligned_be64(&asr->byte_count,
+ htonll(unknown_to_zero(stats->byte_count)));
asr->flow_count = htonl(stats->flow_count);
} else if (request->type == htons(OFPST_VENDOR)) {
struct nx_aggregate_stats_reply *nasr;
@@ -1437,8 +1451,8 @@ ofputil_encode_flow_removed(const struct ofputil_flow_removed *fr,
ofr->duration_sec = htonl(fr->duration_sec);
ofr->duration_nsec = htonl(fr->duration_nsec);
ofr->idle_timeout = htons(fr->idle_timeout);
- ofr->packet_count = htonll(fr->packet_count);
- ofr->byte_count = htonll(fr->byte_count);
+ ofr->packet_count = htonll(unknown_to_zero(fr->packet_count));
+ ofr->byte_count = htonll(unknown_to_zero(fr->byte_count));
} else if (flow_format == NXFF_NXM) {
struct nx_flow_removed *nfr;
int match_len;
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index e35fc46..26fa78b 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -161,8 +161,8 @@ struct ofputil_flow_stats {
uint32_t duration_nsec;
uint16_t idle_timeout;
uint16_t hard_timeout;
- uint64_t packet_count;
- uint64_t byte_count;
+ uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */
+ uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */
union ofp_action *actions;
size_t n_actions;
};
@@ -174,8 +174,8 @@ void ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *,
/* Aggregate stats reply, independent of flow format. */
struct ofputil_aggregate_stats {
- uint64_t packet_count;
- uint64_t byte_count;
+ uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */
+ uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */
uint32_t flow_count;
};
@@ -191,8 +191,8 @@ struct ofputil_flow_removed {
uint32_t duration_sec;
uint32_t duration_nsec;
uint16_t idle_timeout;
- uint64_t packet_count;
- uint64_t byte_count;
+ uint64_t packet_count; /* Packet count, UINT64_MAX if unknown. */
+ uint64_t byte_count; /* Byte count, UINT64_MAX if unknown. */
};
int ofputil_decode_flow_removed(struct ofputil_flow_removed *,
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 90c93c4..99cef8f 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -1964,6 +1964,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
struct flow_stats_request request;
struct ofputil_aggregate_stats stats;
+ bool unknown_packets, unknown_bytes;
struct ofpbuf *reply;
struct list rules;
struct rule *rule;
@@ -1981,6 +1982,7 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
}
memset(&stats, 0, sizeof stats);
+ unknown_packets = unknown_bytes = false;
LIST_FOR_EACH (rule, ofproto_node, &rules) {
uint64_t packet_count;
uint64_t byte_count;
@@ -1988,10 +1990,26 @@ handle_aggregate_stats_request(struct ofconn *ofconn,
ofproto->ofproto_class->rule_get_stats(rule, &packet_count,
&byte_count);
- stats.packet_count += packet_count;
- stats.byte_count += byte_count;
+ if (packet_count == UINT64_MAX) {
+ unknown_packets = true;
+ } else {
+ stats.packet_count += packet_count;
+ }
+
+ if (byte_count == UINT64_MAX) {
+ unknown_bytes = true;
+ } else {
+ stats.byte_count += byte_count;
+ }
+
stats.flow_count++;
}
+ if (unknown_packets) {
+ stats.packet_count = UINT64_MAX;
+ }
+ if (unknown_bytes) {
+ stats.byte_count = UINT64_MAX;
+ }
reply = ofputil_encode_aggregate_stats_reply(&stats, osm);
ofconn_send_reply(ofconn, reply);
diff --git a/ofproto/private.h b/ofproto/private.h
index 17166d4..0b12824 100644
--- a/ofproto/private.h
+++ b/ofproto/private.h
@@ -672,7 +672,8 @@ struct ofproto_class {
/* Obtains statistics for 'rule', storing the number of packets that have
* matched it in '*packet_count' and the number of bytes in those packets
- * in '*byte_count'. */
+ * in '*byte_count'. UINT64_MAX indicates that the packet count or byte
+ * count is unknown. */
void (*rule_get_stats)(struct rule *rule, uint64_t *packet_count,
uint64_t *byte_count);
--
1.7.4.4
More information about the dev
mailing list