ofproto: Improve resolution of flow stats and removed messages (OpenFlow 1.0)
authorJustin Pettit <jpettit@nicira.com>
Tue, 19 Jan 2010 23:35:02 +0000 (15:35 -0800)
committerJustin Pettit <jpettit@nicira.com>
Sat, 23 Jan 2010 02:08:05 +0000 (18:08 -0800)
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
lib/ofp-print.c
ofproto/ofproto.c

index b655acf..654682d 100644 (file)
@@ -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 {
index 706cd58..0d06178 100644 (file)
@@ -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);
index ea97cb6..5d61b70 100644 (file)
@@ -2546,6 +2546,9 @@ 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;
+    uint32_t msec = tdiff - (sec * 1000);
 
     if (rule_is_hidden(rule) || !rule_has_out_port(rule, cbdata->out_port)) {
         return;
@@ -2561,7 +2564,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(msec * 1000000);
     ofs->cookie = rule->flow_cookie;
     ofs->priority = htons(rule->cr.priority);
     ofs->idle_timeout = htons(rule->idle_timeout);
@@ -3300,13 +3304,17 @@ 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;
+    uint32_t msec = tdiff - (sec * 1000);
 
     ofr = make_openflow(sizeof *ofr, OFPT_FLOW_REMOVED, &buf);
     flow_to_match(&rule->cr.flow, rule->cr.wc.wildcards, &ofr->match);
     ofr->cookie = 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(msec * 1000000);
     ofr->idle_timeout = htons(rule->idle_timeout);
     ofr->packet_count = htonll(rule->packet_count);
     ofr->byte_count = htonll(rule->byte_count);