From 1297ff43df635c9c45cc45940729e5bea7d0b089 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 18 Jul 2008 14:16:38 -0700 Subject: [PATCH] vconn: Add new function vconn_transact() and use it to simplify dpctl.c. --- include/vconn.h | 1 + lib/vconn.c | 40 ++++++++++++++++++++++++++++++++++++++++ utilities/dpctl.c | 33 ++++++--------------------------- 3 files changed, 47 insertions(+), 27 deletions(-) diff --git a/include/vconn.h b/include/vconn.h index c870b13f..8dc35f0c 100644 --- a/include/vconn.h +++ b/include/vconn.h @@ -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 *); diff --git a/lib/vconn.c b/lib/vconn.c index f75f816d..f0615d43 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -34,6 +34,7 @@ #include "vconn.h" #include #include +#include #include #include #include @@ -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) { diff --git a/utilities/dpctl.c b/utilities/dpctl.c index def02ec7..7cdb324c 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -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); -- 2.30.2