Improve the command interface so that it sends back acks or errors.
[sliver-openvswitch.git] / lib / vconn.c
index 13e096a..96b85e8 100644 (file)
@@ -552,45 +552,56 @@ vconn_recv_block(struct vconn *vconn, struct ofpbuf **msgp)
     return retval;
 }
 
-/* Sends 'request' to 'vconn' and blocks until it receives a reply with a
- * matching transaction ID.  Returns 0 if successful, in which case the reply
- * is stored in '*replyp' for the caller to examine and free.  Otherwise
- * returns a positive errno value, or EOF, and sets '*replyp' to null.
+/* Waits until a message with a transaction ID matching 'xid' is recived on
+ * 'vconn'.  Returns 0 if successful, in which case the reply is stored in
+ * '*replyp' for the caller to examine and free.  Otherwise returns a positive
+ * errno value, or EOF, and sets '*replyp' to null.
  *
  * 'request' is always destroyed, regardless of the return value. */
 int
-vconn_transact(struct vconn *vconn, struct ofpbuf *request,
-               struct ofpbuf **replyp)
+vconn_recv_xid(struct vconn *vconn, uint32_t xid, struct ofpbuf **replyp)
 {
-    uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
-    int error;
-
-    *replyp = NULL;
-    error = vconn_send_block(vconn, request);
-    if (error) {
-        ofpbuf_delete(request);
-        return error;
-    }
     for (;;) {
         uint32_t recv_xid;
         struct ofpbuf *reply;
+        int error;
 
         error = vconn_recv_block(vconn, &reply);
         if (error) {
+            *replyp = NULL;
             return error;
         }
         recv_xid = ((struct ofp_header *) reply->data)->xid;
-        if (send_xid == recv_xid) {
+        if (xid == recv_xid) {
             *replyp = reply;
             return 0;
         }
 
         VLOG_DBG_RL(&rl, "%s: received reply with xid %08"PRIx32" != expected "
-                    "%08"PRIx32, vconn->name, recv_xid, send_xid);
+                    "%08"PRIx32, vconn->name, recv_xid, xid);
         ofpbuf_delete(reply);
     }
 }
 
+/* Sends 'request' to 'vconn' and blocks until it receives a reply with a
+ * matching transaction ID.  Returns 0 if successful, in which case the reply
+ * is stored in '*replyp' for the caller to examine and free.  Otherwise
+ * returns a positive errno value, or EOF, and sets '*replyp' to null.
+ *
+ * 'request' is always destroyed, regardless of the return value. */
+int
+vconn_transact(struct vconn *vconn, struct ofpbuf *request,
+               struct ofpbuf **replyp)
+{
+    uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
+    int error;
+
+    *replyp = NULL;
+    error = vconn_send_block(vconn, request);
+    ofpbuf_delete(request);
+    return error ? error : vconn_recv_xid(vconn, send_xid, replyp);
+}
+
 void
 vconn_wait(struct vconn *vconn, enum vconn_wait_type wait)
 {