From: Ben Pfaff Date: Fri, 27 May 2011 22:16:08 +0000 (-0700) Subject: Define UINT64_MAX as "unknown" in Open vSwitch specific interfaces. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e9d0469fcaa30f4de0209392a1329b4c52d8d63;p=openvswitch Define UINT64_MAX as "unknown" in Open vSwitch specific interfaces. Some hardware supports reporting packet or byte counters but not both, so OVS has to be prepared for that. Suggested-by: Justin Pettit --- diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index e0bd4167..da80ad91 100644 --- a/include/openflow/nicira-ext.h +++ b/include/openflow/nicira-ext.h @@ -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); diff --git a/lib/ofp-util.c b/lib/ofp-util.c index 37eb073e..8721b191 100644 --- a/lib/ofp-util.c +++ b/lib/ofp-util.c @@ -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; diff --git a/lib/ofp-util.h b/lib/ofp-util.h index 0190caaf..f7490a6e 100644 --- a/lib/ofp-util.h +++ b/lib/ofp-util.h @@ -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 *, diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index ff5cb014..27c370e2 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -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); diff --git a/ofproto/private.h b/ofproto/private.h index 1dca46ec..41487e7d 100644 --- a/ofproto/private.h +++ b/ofproto/private.h @@ -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);