New functions put_openflow() and put_openflow_xid().
authorBen Pfaff <blp@nicira.com>
Thu, 18 Dec 2008 22:01:35 +0000 (14:01 -0800)
committerBen Pfaff <blp@nicira.com>
Thu, 18 Dec 2008 22:01:39 +0000 (14:01 -0800)
lib/vconn.c
lib/vconn.h

index 41c1eefacdb646d61012aedfa1770a115d6f3991..bfd7b3f1ff5fbf0d7a43fbdc37c9afbc2f866124 100644 (file)
@@ -743,35 +743,94 @@ pvconn_wait(struct pvconn *pvconn)
     (pvconn->class->wait)(pvconn);
 }
 
-/* Allocates and returns the first byte of a buffer 'openflow_len' bytes long,
- * containing an OpenFlow header with the given 'type' and a random transaction
- * id.  Stores the new buffer in '*bufferp'.  The caller must free the buffer
- * when it is no longer needed. */
+/* XXX we should really use consecutive xids to avoid probabilistic
+ * failures. */
+static inline uint32_t
+alloc_xid(void)
+{
+    return random_uint32();
+}
+
+/* Allocates and stores in '*bufferp' a new ofpbuf with a size of
+ * 'openflow_len', starting with an OpenFlow header with the given 'type' and
+ * an arbitrary transaction id.  Allocated bytes beyond the header, if any, are
+ * zeroed.
+ *
+ * The caller is responsible for freeing '*bufferp' when it is no longer
+ * needed.
+ *
+ * The OpenFlow header length is initially set to 'openflow_len'; if the
+ * message is later extended, the length should be updated with
+ * update_openflow_length() before sending.
+ *
+ * Returns the header. */
 void *
-make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **bufferp) 
+make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **bufferp)
 {
-    return make_openflow_xid(openflow_len, type, random_uint32(), bufferp);
+    *bufferp = ofpbuf_new(openflow_len);
+    return put_openflow_xid(openflow_len, type, alloc_xid(), *bufferp);
 }
 
-/* Allocates and returns the first byte of a buffer 'openflow_len' bytes long,
- * containing an OpenFlow header with the given 'type' and transaction id
- * 'xid'.  Stores the new buffer in '*bufferp'.  The caller must free the
- * buffer when it is no longer needed. */
+/* Allocates and stores in '*bufferp' a new ofpbuf with a size of
+ * 'openflow_len', starting with an OpenFlow header with the given 'type' and
+ * transaction id 'xid'.  Allocated bytes beyond the header, if any, are
+ * zeroed.
+ *
+ * The caller is responsible for freeing '*bufferp' when it is no longer
+ * needed.
+ *
+ * The OpenFlow header length is initially set to 'openflow_len'; if the
+ * message is later extended, the length should be updated with
+ * update_openflow_length() before sending.
+ *
+ * Returns the header. */
 void *
 make_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
                   struct ofpbuf **bufferp)
 {
-    struct ofpbuf *buffer;
+    *bufferp = ofpbuf_new(openflow_len);
+    return put_openflow_xid(openflow_len, type, xid, *bufferp);
+}
+
+/* Appends 'openflow_len' bytes to 'buffer', starting with an OpenFlow header
+ * with the given 'type' and an arbitrary transaction id.  Allocated bytes
+ * beyond the header, if any, are zeroed.
+ *
+ * The OpenFlow header length is initially set to 'openflow_len'; if the
+ * message is later extended, the length should be updated with
+ * update_openflow_length() before sending.
+ *
+ * Returns the header. */
+void *
+put_openflow(size_t openflow_len, uint8_t type, struct ofpbuf *buffer)
+{
+    return put_openflow_xid(openflow_len, type, alloc_xid(), buffer);
+}
+
+/* Appends 'openflow_len' bytes to 'buffer', starting with an OpenFlow header
+ * with the given 'type' and an transaction id 'xid'.  Allocated bytes beyond
+ * the header, if any, are zeroed.
+ *
+ * The OpenFlow header length is initially set to 'openflow_len'; if the
+ * message is later extended, the length should be updated with
+ * update_openflow_length() before sending.
+ *
+ * Returns the header. */
+void *
+put_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
+                 struct ofpbuf *buffer)
+{
     struct ofp_header *oh;
 
     assert(openflow_len >= sizeof *oh);
     assert(openflow_len <= UINT16_MAX);
-    buffer = *bufferp = ofpbuf_new(openflow_len);
-    oh = ofpbuf_put_zeros(buffer, openflow_len);
+
+    oh = ofpbuf_put_uninit(buffer, openflow_len);
     oh->version = OFP_VERSION;
     oh->type = type;
     oh->length = htons(openflow_len);
     oh->xid = xid;
+    memset(oh + 1, 0, openflow_len - sizeof *oh);
     return oh;
 }
 
@@ -791,7 +850,7 @@ make_add_flow(const struct flow *flow, uint32_t buffer_id,
     struct ofp_flow_mod *ofm;
     size_t size = sizeof *ofm + actions_len;
     struct ofpbuf *out = ofpbuf_new(size);
-    ofm = ofpbuf_put_zeros(out, size);
+    ofm = ofpbuf_put_zeros(out, sizeof *ofm);
     ofm->header.version = OFP_VERSION;
     ofm->header.type = OFPT_FLOW_MOD;
     ofm->header.length = htons(size);
@@ -819,10 +878,9 @@ make_add_simple_flow(const struct flow *flow,
                      uint16_t idle_timeout)
 {
     struct ofp_action_output *oao;
-    struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout, 
-            sizeof *oao);
-    struct ofp_flow_mod *ofm = buffer->data;
-    oao = (struct ofp_action_output *)&ofm->actions[0];
+    struct ofpbuf *buffer = make_add_flow(flow, buffer_id, idle_timeout,
+            sizeof oao);
+    oao = ofpbuf_put_zeros(buffer, sizeof *oao);
     oao->type = htons(OFPAT_OUTPUT);
     oao->len = htons(sizeof *oao);
     oao->port = htons(out_port);
index a01d93db52e33553b72e237b4d38dee8d6613277..9261e640c380fbac233abcb232b33e6c7168a74d 100644 (file)
@@ -82,6 +82,9 @@ void pvconn_wait(struct pvconn *);
 void *make_openflow(size_t openflow_len, uint8_t type, struct ofpbuf **);
 void *make_openflow_xid(size_t openflow_len, uint8_t type,
                         uint32_t xid, struct ofpbuf **);
+void *put_openflow(size_t openflow_len, uint8_t type, struct ofpbuf *);
+void *put_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid,
+                       struct ofpbuf *);
 void update_openflow_length(struct ofpbuf *);
 struct ofpbuf *make_add_flow(const struct flow *, uint32_t buffer_id,
                              uint16_t max_idle, size_t actions_len);