New functions for iterating through flow stats replies.
authorBen Pfaff <blp@nicira.com>
Wed, 24 Dec 2008 23:10:48 +0000 (15:10 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 26 Dec 2008 21:27:23 +0000 (13:27 -0800)
lib/learning-switch.c
lib/vconn.c
lib/vconn.h

index 5c6ca4e0ac03764d46bdf63aa221da50a2f342c7..6abacb5b07a31942a128c054d7ebce1a21b6aec6 100644 (file)
@@ -630,52 +630,18 @@ static void
 process_stats_reply(struct lswitch *sw, struct rconn *rconn, void *osr_)
 {
     struct ofp_stats_reply *osr = osr_;
-    const uint8_t *body = osr->body;
-    const uint8_t *pos = body;
-    size_t body_len;
+    struct flow_stats_iterator i;
+    const struct ofp_flow_stats *fs;
 
     if (sw->last_query == LLONG_MIN
         || osr->type != htons(OFPST_FLOW)
         || osr->header.xid != sw->query_xid) {
         return;
     }
-    body_len = (ntohs(osr->header.length)
-                - offsetof(struct ofp_stats_reply, body));
-    for (;;) {
-        const struct ofp_flow_stats *fs;
-        ptrdiff_t bytes_left = body + body_len - pos;
-        size_t length;
-
-        if (bytes_left < sizeof *fs) {
-            if (bytes_left != 0) {
-                VLOG_WARN_RL(&rl, "%012llx: %td leftover bytes in flow "
-                             "stats reply", sw->datapath_id, bytes_left);
-            }
-            break;
-        }
-
-        fs = (const void *) pos;
-        length = ntohs(fs->length);
-        if (length < sizeof *fs) {
-            VLOG_WARN_RL(&rl, "%012llx: flow stats length %zu is shorter than "
-                         "min %zu", sw->datapath_id, length, sizeof *fs);
-            break;
-        } else if (length > bytes_left) {
-            VLOG_WARN_RL(&rl, "%012llx: flow stats length %zu but only %td "
-                         "bytes left", sw->datapath_id, length, bytes_left);
-            break;
-        } else if ((length - sizeof *fs) % sizeof fs->actions[0]) {
-            VLOG_WARN_RL(&rl, "%012llx: flow stats length %zu has %zu bytes "
-                         "left over in final action", sw->datapath_id, length,
-                         (length - sizeof *fs) % sizeof fs->actions[0]);
-            break;
-        }
-
+    for (fs = flow_stats_first(&i, osr); fs; fs = flow_stats_next(&i)) {
         sw->n_flows++;
         process_flow_stats(sw, rconn, fs);
-
-        pos += length;
-     }
+    }
     if (!(osr->flags & htons(OFPSF_REPLY_MORE))) {
         VLOG_DBG("%012llx: Deleted %d of %d received flows to "
                  "implement STP, %d because of no-recv, %d because of "
index bfd7b3f1ff5fbf0d7a43fbdc37c9afbc2f866124..4361734ce1edff21cb2ed02b3a25bcd377faa91a 100644 (file)
@@ -1047,6 +1047,51 @@ check_ofp_message_array(const struct ofp_header *msg, uint8_t type,
     return 0;
 }
 
+const struct ofp_flow_stats *
+flow_stats_first(struct flow_stats_iterator *iter,
+                 const struct ofp_stats_reply *osr)
+{
+    iter->pos = osr->body;
+    iter->end = osr->body + (ntohs(osr->header.length) + sizeof *osr);
+    return flow_stats_next(iter);
+}
+
+const struct ofp_flow_stats *
+flow_stats_next(struct flow_stats_iterator *iter)
+{
+    static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
+    ptrdiff_t bytes_left = iter->end - iter->pos;
+    const struct ofp_flow_stats *fs;
+    size_t length;
+
+    if (bytes_left < sizeof *fs) {
+        if (bytes_left != 0) {
+            VLOG_WARN_RL(&rl, "%td leftover bytes in flow stats reply",
+                         bytes_left);
+        }
+        return NULL;
+    }
+
+    fs = (const void *) iter->pos;
+    length = ntohs(fs->length);
+    if (length < sizeof *fs) {
+        VLOG_WARN_RL(&rl, "flow stats length %zu is shorter than min %zu",
+        length, sizeof *fs);
+        return NULL;
+    } else if (length > bytes_left) {
+        VLOG_WARN_RL(&rl, "flow stats length %zu but only %td bytes left",
+                     length, bytes_left);
+        return NULL;
+    } else if ((length - sizeof *fs) % sizeof fs->actions[0]) {
+        VLOG_WARN_RL(&rl, "flow stats length %zu has %zu bytes "
+                     "left over in final action", length,
+                     (length - sizeof *fs) % sizeof fs->actions[0]);
+        return NULL;
+    }
+    iter->pos += length;
+    return fs;
+}
+
 void
 vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
            uint32_t ip, const char *name, bool reconnectable)
index 9261e640c380fbac233abcb232b33e6c7168a74d..c5123f9703369f5b5c47ce7fedb8c39ce6c1e8c0 100644 (file)
@@ -41,6 +41,7 @@
 struct ofpbuf;
 struct flow;
 struct ofp_header;
+struct ofp_stats_reply;
 struct pvconn;
 struct vconn;
 
@@ -102,4 +103,11 @@ int check_ofp_message_array(const struct ofp_header *, uint8_t type,
                             size_t size, size_t array_elt_size,
                             size_t *n_array_elts);
 
+struct flow_stats_iterator {
+    const uint8_t *pos, *end;
+};
+const struct ofp_flow_stats *flow_stats_first(struct flow_stats_iterator *,
+                                              const struct ofp_stats_reply *);
+const struct ofp_flow_stats *flow_stats_next(struct flow_stats_iterator *);
+
 #endif /* vconn.h */