[ovs-dev] [PATCH 4/8] ofproto: Improve resolution of flow stats and removed messages (OpenFlow 1.0)

Justin Pettit jpettit at nicira.com
Fri Jan 22 09:09:09 UTC 2010


OpenFlow 1.0 increases the resolution of flow stats and flow removed messages
from seconds to (potentially) nanoseconds.  The spec stats that only
millisecond granularity is required, so that's all we provide at this
time.  Increasing to nanoseconds would require more significant code
change and would not provide an appreciable improvement in real world
use.

NOTE: OVS at this point is not wire-compatible with OpenFlow 1.0 until
the final commit in this OpenFlow 1.0 set.
---
 include/openflow/openflow.h |   14 +++++++++-----
 lib/ofp-print.c             |   15 ++++++++++-----
 ofproto/ofproto.c           |   10 ++++++++--
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/include/openflow/openflow.h b/include/openflow/openflow.h
index b655acf..654682d 100644
--- a/include/openflow/openflow.h
+++ b/include/openflow/openflow.h
@@ -583,9 +583,11 @@ struct ofp_flow_removed {
     uint8_t reason;           /* One of OFPRR_*. */
     uint8_t pad[1];           /* Align to 32-bits. */
 
-    uint32_t duration;        /* Time flow was alive in seconds. */
+    uint32_t duration_sec;    /* Time flow was alive in seconds. */
+    uint32_t duration_nsec;   /* Time flow was alive in nanoseconds beyond 
+                                 duration_sec. */
     uint16_t idle_timeout;    /* Idle timeout from original flow mod. */
-    uint8_t pad2[6];          /* Align to 64-bits. */
+    uint8_t pad2[2];          /* Align to 64-bits. */
     uint64_t packet_count;    
     uint64_t byte_count;
 };
@@ -752,18 +754,20 @@ struct ofp_flow_stats {
     uint8_t table_id;         /* ID of table flow came from. */
     uint8_t pad;
     struct ofp_match match;   /* Description of fields. */
-    uint32_t duration;        /* Time flow has been alive in seconds. */
+    uint32_t duration_sec;    /* Time flow has been alive in seconds. */
+    uint32_t duration_nsec;   /* Time flow has been alive in nanoseconds
+                                 beyond duration_sec. */
     uint16_t priority;        /* Priority of the entry. Only meaningful
                                  when this is not an exact-match entry. */
     uint16_t idle_timeout;    /* Number of seconds idle before expiration. */
     uint16_t hard_timeout;    /* Number of seconds before expiration. */
-    uint8_t pad2[2];          /* Align to 64 bits. */
+    uint8_t pad2[6];          /* Align to 64 bits. */
     uint64_t cookie;          /* Opaque controller-issued identifier. */
     uint64_t packet_count;    /* Number of packets in flow. */
     uint64_t byte_count;      /* Number of bytes in flow. */
     struct ofp_action_header actions[0]; /* Actions. */
 };
-OFP_ASSERT(sizeof(struct ofp_flow_stats) == 80);
+OFP_ASSERT(sizeof(struct ofp_flow_stats) == 88);
 
 /* Body for ofp_stats_request of type OFPST_AGGREGATE. */
 struct ofp_aggregate_stats_request {
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 706cd58..0d06178 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -775,11 +775,13 @@ ofp_print_flow_removed(struct ds *string, const void *oh, size_t len UNUSED,
         break;
     }
     ds_put_format(string, 
-         " cookie%"PRIx64" pri%"PRIu16" secs%"PRIu32" idle%"PRIu16
-         " pkts%"PRIu64" bytes%"PRIu64"\n", ntohll(ofr->cookie),
+         " cookie%"PRIx64" pri%"PRIu16" secs%"PRIu32" nsecs%"PRIu32
+         " idle%"PRIu16" pkts%"PRIu64" bytes%"PRIu64"\n", 
+         ntohll(ofr->cookie),
          ofr->match.wildcards ? ntohs(ofr->priority) : (uint16_t)-1,
-         ntohl(ofr->duration), ntohs(ofr->idle_timeout),
-         ntohll(ofr->packet_count), ntohll(ofr->byte_count));
+         ntohl(ofr->duration_sec), ntohl(ofr->duration_nsec),
+         ntohs(ofr->idle_timeout), ntohll(ofr->packet_count), 
+         ntohll(ofr->byte_count));
 }
 
 static void
@@ -991,7 +993,10 @@ ofp_flow_stats_reply(struct ds *string, const void *body_, size_t len,
         }
 
         ds_put_format(string, "  cookie=%"PRIu64"s, ", ntohll(fs->cookie));
-        ds_put_format(string, "duration=%"PRIu32"s, ", ntohl(fs->duration));
+        ds_put_format(string, "duration_sec=%"PRIu32"s, ", 
+                    ntohl(fs->duration_sec));
+        ds_put_format(string, "duration_nsec=%"PRIu32"s, ", 
+                    ntohl(fs->duration_nsec));
         ds_put_format(string, "table_id=%"PRIu8", ", fs->table_id);
         ds_put_format(string, "priority=%"PRIu16", ", 
                     fs->match.wildcards ? ntohs(fs->priority) : (uint16_t)-1);
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index f274656..531fe97 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -2545,6 +2545,8 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     struct ofp_flow_stats *ofs;
     uint64_t packet_count, byte_count;
     size_t act_len, len;
+    long long int tdiff = time_msec() - rule->created;
+    uint32_t sec = tdiff / 1000;
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, cbdata->out_port)) {
         return;
@@ -2560,7 +2562,8 @@ flow_stats_cb(struct cls_rule *rule_, void *cbdata_)
     ofs->table_id = rule->cr.wc.wildcards ? TABLEID_CLASSIFIER : TABLEID_HASH;
     ofs->pad = 0;
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofs->match);
-    ofs->duration = htonl((time_msec() - rule->created) / 1000);
+    ofs->duration_sec = htonl(sec);
+    ofs->duration_nsec = htonl((tdiff - (sec * 1000)) * 1000000);
     ofs->cookie = htonll(rule->flow_cookie);
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -3299,13 +3302,16 @@ compose_flow_removed(const struct rule *rule, long long int now, uint8_t reason)
     struct ofp_flow_removed *ofr;
     struct ofpbuf *buf;
     long long int last_used = rule->used ? now - rule->used : 0;
+    long long int tdiff = time_msec() - rule->created - last_used;
+    uint32_t sec = tdiff / 1000;
 
     ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofr->match);
     ofr->cookie = htonll(rule->flow_cookie);
     ofr->priority = htons(rule->cr.priority);
     ofr->reason = reason;
-    ofr->duration = htonl((now - rule->created - last_used) / 1000);
+    ofr->duration_sec = htonl(sec);
+    ofr->duration_nsec = htonl((tdiff - (sec * 1000)) * 1000000);
     ofr->idle_timeout = htons(rule->idle_timeout);
     ofr->packet_count = htonll(rule->packet_count);
     ofr->byte_count = htonll(rule->byte_count);
-- 
1.5.5





More information about the dev mailing list