ofp-util: Make put_stats__() public as ofputil_put_stats_header().
[sliver-openvswitch.git] / lib / ofp-util.c
index 834bb62..cd26143 100644 (file)
@@ -171,7 +171,8 @@ ofputil_cls_rule_from_ofp10_match(const struct ofp10_match *match,
     rule->flow.nw_proto = match->nw_proto;
 
     /* Translate VLANs. */
-    if (!(ofpfw & OFPFW10_DL_VLAN) && match->dl_vlan == htons(OFP_VLAN_NONE)) {
+    if (!(ofpfw & OFPFW10_DL_VLAN) &&
+        match->dl_vlan == htons(OFP10_VLAN_NONE)) {
         /* Match only packets without 802.1Q header.
          *
          * When OFPFW10_DL_VLAN_PCP is wildcarded, this is obviously correct.
@@ -232,7 +233,7 @@ ofputil_cls_rule_to_ofp10_match(const struct cls_rule *rule,
         ofpfw |= OFPFW10_DL_VLAN | OFPFW10_DL_VLAN_PCP;
     } else if (rule->wc.vlan_tci_mask & htons(VLAN_CFI)
                && !(rule->flow.vlan_tci & htons(VLAN_CFI))) {
-        match->dl_vlan = htons(OFP_VLAN_NONE);
+        match->dl_vlan = htons(OFP10_VLAN_NONE);
     } else {
         if (!(rule->wc.vlan_tci_mask & htons(VLAN_VID_MASK))) {
             ofpfw |= OFPFW10_DL_VLAN;
@@ -2144,7 +2145,11 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
     if (osm->type == htons(OFPST_FLOW)) {
         struct ofp_flow_stats *ofs;
 
-        ofs = ofpbuf_put_uninit(reply, sizeof *ofs);
+        ofpbuf_put_uninit(reply, sizeof *ofs);
+        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
+
+        ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
+        ofs->length = htons(reply->size - start_ofs);
         ofs->table_id = fs->table_id;
         ofs->pad = 0;
         ofputil_cls_rule_to_ofp10_match(&fs->rule, &ofs->match);
@@ -2159,14 +2164,16 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
                            htonll(unknown_to_zero(fs->packet_count)));
         put_32aligned_be64(&ofs->byte_count,
                            htonll(unknown_to_zero(fs->byte_count)));
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
-
-        ofs = ofpbuf_at_assert(reply, start_ofs, sizeof *ofs);
-        ofs->length = htons(reply->size - start_ofs);
     } else if (osm->type == htons(OFPST_VENDOR)) {
         struct nx_flow_stats *nfs;
+        int match_len;
+
+        ofpbuf_put_uninit(reply, sizeof *nfs);
+        match_len = nx_put_match(reply, false, &fs->rule, 0, 0);
+        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
 
-        nfs = ofpbuf_put_uninit(reply, sizeof *nfs);
+        nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
+        nfs->length = htons(reply->size - start_ofs);
         nfs->table_id = fs->table_id;
         nfs->pad = 0;
         nfs->duration_sec = htonl(fs->duration_sec);
@@ -2180,14 +2187,10 @@ ofputil_append_flow_stats_reply(const struct ofputil_flow_stats *fs,
         nfs->hard_age = htons(fs->hard_age < 0 ? 0
                               : fs->hard_age < UINT16_MAX ? fs->hard_age + 1
                               : UINT16_MAX);
-        nfs->match_len = htons(nx_put_match(reply, false, &fs->rule, 0, 0));
+        nfs->match_len = htons(match_len);
         nfs->cookie = fs->cookie;
         nfs->packet_count = htonll(fs->packet_count);
         nfs->byte_count = htonll(fs->byte_count);
-        ofpacts_put_openflow10(fs->ofpacts, fs->ofpacts_len, reply);
-
-        nfs = ofpbuf_at_assert(reply, start_ofs, sizeof *nfs);
-        nfs->length = htons(reply->size - start_ofs);
     } else {
         NOT_REACHED();
     }
@@ -3265,10 +3268,10 @@ update_openflow_length(struct ofpbuf *buffer)
     oh->length = htons(buffer->size);
 }
 
-static void
-put_stats__(ovs_be32 xid, uint8_t ofp_type,
-            ovs_be16 ofpst_type, ovs_be32 nxst_subtype,
-            struct ofpbuf *msg)
+void
+ofputil_put_stats_header(ovs_be32 xid, uint8_t ofp_type,
+                         ovs_be16 ofpst_type, ovs_be32 nxst_subtype,
+                         struct ofpbuf *msg)
 {
     if (ofpst_type == htons(OFPST_VENDOR)) {
         struct nicira_stats_msg *nsm;
@@ -3301,8 +3304,8 @@ ofputil_make_stats_request(size_t openflow_len, uint16_t ofpst_type,
     struct ofpbuf *msg;
 
     msg = *bufferp = ofpbuf_new(openflow_len);
-    put_stats__(alloc_xid(), OFPT10_STATS_REQUEST,
-                htons(ofpst_type), htonl(nxst_subtype), msg);
+    ofputil_put_stats_header(alloc_xid(), OFPT10_STATS_REQUEST,
+                             htons(ofpst_type), htonl(nxst_subtype), msg);
     ofpbuf_padto(msg, openflow_len);
 
     return msg->data;
@@ -3311,13 +3314,16 @@ ofputil_make_stats_request(size_t openflow_len, uint16_t ofpst_type,
 static void
 put_stats_reply__(const struct ofp_stats_msg *request, struct ofpbuf *msg)
 {
+    ovs_be32 nxst_subtype;
+
     assert(request->header.type == OFPT10_STATS_REQUEST ||
            request->header.type == OFPT10_STATS_REPLY);
-    put_stats__(request->header.xid, OFPT10_STATS_REPLY, request->type,
-                (request->type != htons(OFPST_VENDOR)
-                 ? htonl(0)
-                 : ((const struct nicira_stats_msg *) request)->subtype),
-                msg);
+
+    nxst_subtype = (request->type != htons(OFPST_VENDOR)
+                    ? htonl(0)
+                    : ((const struct nicira_stats_msg *) request)->subtype);
+    ofputil_put_stats_header(request->header.xid, OFPT10_STATS_REPLY,
+                             request->type, nxst_subtype, msg);
 }
 
 /* Creates a statistics reply message with total length 'openflow_len'
@@ -3391,6 +3397,16 @@ ofputil_append_stats_reply(size_t len, struct list *replies)
     return ofpbuf_put_uninit(ofputil_reserve_stats_reply(len, replies), len);
 }
 
+/* Sometimes, when composing stats replies, it's difficult to predict how long
+ * an individual reply chunk will be before actually encoding it into the reply
+ * buffer.  This function allows easy handling of this case: just encode the
+ * reply, then use this function to break the message into two pieces if it
+ * exceeds the OpenFlow message limit.
+ *
+ * In detail, if the final stats message in 'replies' is too long for OpenFlow,
+ * this function breaks it into two separate stats replies, the first one with
+ * the first 'start_ofs' bytes, the second one containing the bytes from that
+ * offset onward. */
 void
 ofputil_postappend_stats_reply(size_t start_ofs, struct list *replies)
 {