vconn: Add new function vconn_transact() and use it to simplify dpctl.c.
authorBen Pfaff <blp@nicira.com>
Fri, 18 Jul 2008 21:16:38 +0000 (14:16 -0700)
committerBen Pfaff <blp@nicira.com>
Fri, 18 Jul 2008 21:16:38 +0000 (14:16 -0700)
include/vconn.h
lib/vconn.c
utilities/dpctl.c

index c870b13f1adde4dd61aed2a67c786a7f2e6859bd..8dc35f0c9f25d83ebe9821ea2877016650bbf300 100644 (file)
@@ -61,6 +61,7 @@ int vconn_connect(struct vconn *);
 int vconn_accept(struct vconn *, struct vconn **);
 int vconn_recv(struct vconn *, struct buffer **);
 int vconn_send(struct vconn *, struct buffer *);
+int vconn_transact(struct vconn *, struct buffer *, struct buffer **);
 
 int vconn_open_block(const char *name, struct vconn **);
 int vconn_send_block(struct vconn *, struct buffer *);
index f75f816d65d816bdd53f74f19d2939d665c4e7e2..f0615d4380688222d737020c84ddd0b9edb70943 100644 (file)
@@ -34,6 +34,7 @@
 #include "vconn.h"
 #include <assert.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <netinet/in.h>
 #include <poll.h>
 #include <stdlib.h>
@@ -331,6 +332,45 @@ vconn_recv_block(struct vconn *vconn, struct buffer **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.
+ *
+ * 'request' is always destroyed, regardless of the return value. */
+int
+vconn_transact(struct vconn *vconn, struct buffer *request,
+               struct buffer **replyp)
+{
+    uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
+    int error;
+
+    *replyp = NULL;
+    error = vconn_send_block(vconn, request);
+    if (error) {
+        buffer_delete(request);
+        return error;
+    }
+    for (;;) {
+        uint32_t recv_xid;
+        struct buffer *reply;
+
+        error = vconn_recv_block(vconn, &reply);
+        if (error) {
+            return error;
+        }
+        recv_xid = ((struct ofp_header *) reply->data)->xid;
+        if (send_xid == recv_xid) {
+            *replyp = reply;
+            return 0;
+        }
+
+        VLOG_DBG("received reply with xid %08"PRIx32" != expected %08"PRIx32,
+                 recv_xid, send_xid);
+        buffer_delete(reply);
+    }
+}
+
 void
 vconn_wait(struct vconn *vconn, enum vconn_wait_type wait)
 {
index def02ec77e90902dd5d9e65443d752f754f8ea87..7cdb324c9625aa3e5ae005b022b8391a1d35b6be 100644 (file)
@@ -322,28 +322,6 @@ send_openflow_buffer(struct vconn *vconn, struct buffer *buffer)
     run(vconn_send_block(vconn, buffer), "failed to send packet to switch");
 }
 
-static struct buffer *
-transact_openflow(struct vconn *vconn, struct buffer *request)
-{
-    uint32_t send_xid = ((struct ofp_header *) request->data)->xid;
-
-    send_openflow_buffer(vconn, request);
-    for (;;) {
-        uint32_t recv_xid;
-        struct buffer *reply;
-
-        run(vconn_recv_block(vconn, &reply), "OpenFlow packet receive failed");
-        recv_xid = ((struct ofp_header *) reply->data)->xid;
-        if (send_xid == recv_xid) {
-            return reply;
-        }
-
-        VLOG_DBG("received reply with xid %08"PRIx32" != expected %08"PRIx32,
-                 recv_xid, send_xid);
-        buffer_delete(reply);
-    }
-}
-
 static void
 dump_transaction(const char *vconn_name, struct buffer *request)
 {
@@ -352,7 +330,7 @@ dump_transaction(const char *vconn_name, struct buffer *request)
 
     update_openflow_length(request);
     run(vconn_open_block(vconn_name, &vconn), "connecting to %s", vconn_name);
-    reply = transact_openflow(vconn, request);
+    run(vconn_transact(vconn, request, &reply), "talking to %s", vconn_name);
     ofp_print(stdout, reply->data, reply->size, 1);
     vconn_close(vconn);
 }
@@ -788,7 +766,7 @@ do_probe(int argc, char *argv[])
 
     make_openflow(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, &request);
     run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
-    reply = transact_openflow(vconn, request);
+    run(vconn_transact(vconn, request, &reply), "talking to %s", argv[1]);
     if (reply->size != request->size) {
         fatal(0, "reply does not match request");
     }
@@ -820,7 +798,7 @@ do_ping(int argc, char *argv[])
         random_bytes(rq_hdr + 1, payload);
 
         gettimeofday(&start, NULL);
-        reply = transact_openflow(vconn, buffer_clone(request));
+        run(vconn_transact(vconn, buffer_clone(request), &reply), "transact");
         gettimeofday(&end, NULL);
 
         rpy_hdr = reply->data;
@@ -868,12 +846,13 @@ do_benchmark(int argc, char *argv[])
     run(vconn_open_block(argv[1], &vconn), "connecting to %s", argv[1]);
     gettimeofday(&start, NULL);
     for (i = 0; i < count; i++) {
-        struct buffer *request;
+        struct buffer *request, *reply;
         struct ofp_header *rq_hdr;
 
         rq_hdr = make_openflow(message_size, OFPT_ECHO_REQUEST, &request);
         memset(rq_hdr + 1, 0, payload_size);
-        buffer_delete(transact_openflow(vconn, request));
+        run(vconn_transact(vconn, request, &reply), "transact");
+        buffer_delete(reply);
     }
     gettimeofday(&end, NULL);
     vconn_close(vconn);