From: Ben Pfaff Date: Wed, 24 Dec 2008 23:10:48 +0000 (-0800) Subject: New functions for iterating through flow stats replies. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c1e22de7c183f5edd21307002e3981527e13a0e;p=openvswitch New functions for iterating through flow stats replies. --- diff --git a/lib/learning-switch.c b/lib/learning-switch.c index 5c6ca4e0..6abacb5b 100644 --- a/lib/learning-switch.c +++ b/lib/learning-switch.c @@ -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 " diff --git a/lib/vconn.c b/lib/vconn.c index bfd7b3f1..4361734c 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -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) diff --git a/lib/vconn.h b/lib/vconn.h index 9261e640..c5123f97 100644 --- a/lib/vconn.h +++ b/lib/vconn.h @@ -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 */