Define UINT64_MAX as "unknown" in Open vSwitch specific interfaces.
authorBen Pfaff <blp@nicira.com>
Fri, 27 May 2011 22:16:08 +0000 (15:16 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 14 Jun 2011 18:21:52 +0000 (11:21 -0700)
Some hardware supports reporting packet or byte counters but not both, so
OVS has to be prepared for that.

Suggested-by: Justin Pettit <jpettit@nicira.com>
include/openflow/nicira-ext.h
lib/ofp-util.c
lib/ofp-util.h
ofproto/ofproto.c
ofproto/private.h

index e0bd416..da80ad9 100644 (file)
@@ -1271,8 +1271,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
@@ -1307,10 +1307,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);
 
index 37eb073..8721b19 100644 (file)
@@ -1231,6 +1231,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(). */
@@ -1258,8 +1268,10 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
         ofs->hard_timeout = htons(fs->hard_timeout);
         memset(ofs->pad2, 0, sizeof ofs->pad2);
         put_32aligned_be64(&ofs->cookie, fs->cookie);
-        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;
@@ -1303,8 +1315,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;
@@ -1398,8 +1412,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;
index 0190caa..f7490a6 100644 (file)
@@ -163,8 +163,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;
 };
@@ -176,8 +176,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;
 };
 
@@ -193,8 +193,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 *,
index ff5cb01..27c370e 100644 (file)
@@ -1990,6 +1990,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;
@@ -2007,6 +2008,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;
@@ -2014,10 +2016,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);
index 1dca46e..41487e7 100644 (file)
@@ -690,7 +690,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);