From: Ben Pfaff Date: Fri, 18 Jul 2008 21:08:18 +0000 (-0700) Subject: vconn: Add utility functions make_openflow() and update_openflow_length(). X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=4d90ee6aef909d1a982164694d9e5902035730bf;p=sliver-openvswitch.git vconn: Add utility functions make_openflow() and update_openflow_length(). Use these functions to simplify code that creates and sends OpenFlow packets. --- diff --git a/include/vconn.h b/include/vconn.h index e536c9a3c..c870b13f1 100644 --- a/include/vconn.h +++ b/include/vconn.h @@ -35,6 +35,7 @@ #define VCONN_H 1 #include +#include #include struct buffer; @@ -77,6 +78,10 @@ void vconn_accept_wait(struct vconn *); void vconn_recv_wait(struct vconn *); void vconn_send_wait(struct vconn *); +void *make_openflow(size_t openflow_len, uint8_t type, struct buffer **); +void *make_openflow_xid(size_t openflow_len, uint8_t type, + uint32_t xid, struct buffer **); +void update_openflow_length(struct buffer *); struct buffer *make_add_simple_flow(const struct flow *, uint32_t buffer_id, uint16_t out_port, uint16_t max_idle); diff --git a/lib/vconn.c b/lib/vconn.c index 94b4572d9..f75f816d6 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -43,6 +43,7 @@ #include "ofp-print.h" #include "openflow.h" #include "poll-loop.h" +#include "random.h" #include "util.h" #define THIS_MODULE VLM_vconn @@ -376,6 +377,48 @@ vconn_send_wait(struct vconn *vconn) vconn_wait(vconn, WAIT_SEND); } +/* 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. */ +void * +make_openflow(size_t openflow_len, uint8_t type, struct buffer **bufferp) +{ + return make_openflow_xid(openflow_len, type, random_uint32(), 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. */ +void * +make_openflow_xid(size_t openflow_len, uint8_t type, uint32_t xid, + struct buffer **bufferp) +{ + struct buffer *buffer; + struct ofp_header *oh; + + assert(openflow_len >= sizeof *oh); + assert(openflow_len <= UINT16_MAX); + buffer = *bufferp = buffer_new(openflow_len); + oh = buffer_put_uninit(buffer, openflow_len); + memset(oh, 0, openflow_len); + oh->version = OFP_VERSION; + oh->type = type; + oh->length = htons(openflow_len); + oh->xid = xid; + return oh; +} + +/* Updates the 'length' field of the OpenFlow message in 'buffer' to + * 'buffer->size'. */ +void +update_openflow_length(struct buffer *buffer) +{ + struct ofp_header *oh = buffer_at_assert(buffer, 0, sizeof *oh); + oh->length = htons(buffer->size); +} + struct buffer * make_add_simple_flow(const struct flow *flow, uint32_t buffer_id, uint16_t out_port, uint16_t max_idle) diff --git a/switch/datapath.c b/switch/datapath.c index 12af77b8b..fb688af60 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -563,19 +563,11 @@ dp_output_port(struct datapath *dp, struct buffer *buffer, } static void * -alloc_openflow_buffer(struct datapath *dp, size_t openflow_len, uint8_t type, - const struct sender *sender, struct buffer **bufferp) +make_openflow_reply(size_t openflow_len, uint8_t type, + const struct sender *sender, struct buffer **bufferp) { - struct buffer *buffer; - struct ofp_header *oh; - - buffer = *bufferp = buffer_new(openflow_len); - oh = buffer_put_uninit(buffer, openflow_len); - oh->version = OFP_VERSION; - oh->type = type; - oh->length = 0; /* Filled in by send_openflow_buffer(). */ - oh->xid = sender ? sender->xid : 0; - return oh; + return make_openflow_xid(openflow_len, type, sender ? sender->xid : 0, + bufferp); } static int @@ -584,12 +576,9 @@ send_openflow_buffer(struct datapath *dp, struct buffer *buffer, { struct remote *remote = sender ? sender->remote : dp->controller; struct rconn *rconn = remote->rconn; - struct ofp_header *oh; int retval; - oh = buffer_at_assert(buffer, 0, sizeof *oh); - oh->length = htons(buffer->size); - + update_openflow_length(buffer); retval = rconn_send(rconn, buffer); if (retval) { VLOG_WARN("send to %s failed: %s", @@ -652,8 +641,8 @@ dp_send_features_reply(struct datapath *dp, const struct sender *sender) struct ofp_switch_features *ofr; struct sw_port *p; - ofr = alloc_openflow_buffer(dp, sizeof *ofr, OFPT_FEATURES_REPLY, - sender, &buffer); + ofr = make_openflow_reply(sizeof *ofr, OFPT_FEATURES_REPLY, + sender, &buffer); ofr->datapath_id = htonll(dp->id); ofr->n_exact = htonl(2 * TABLE_HASH_MAX_FLOWS); ofr->n_compression = 0; /* Not supported */ @@ -691,8 +680,7 @@ send_port_status(struct sw_port *p, uint8_t status) { struct buffer *buffer; struct ofp_port_status *ops; - ops = alloc_openflow_buffer(p->dp, sizeof *ops, OFPT_PORT_STATUS, NULL, - &buffer); + ops = make_openflow_xid(sizeof *ops, OFPT_PORT_STATUS, 0, &buffer); ops->reason = status; memset(ops->pad, 0, sizeof ops->pad); fill_port_desc(p->dp, p, &ops->desc); @@ -705,8 +693,7 @@ send_flow_expired(struct datapath *dp, struct sw_flow *flow) { struct buffer *buffer; struct ofp_flow_expired *ofe; - ofe = alloc_openflow_buffer(dp, sizeof *ofe, OFPT_FLOW_EXPIRED, NULL, - &buffer); + ofe = make_openflow_xid(sizeof *ofe, OFPT_FLOW_EXPIRED, 0, &buffer); flow_fill_match(&ofe->match, &flow->key); memset(ofe->pad, 0, sizeof ofe->pad); @@ -724,8 +711,8 @@ dp_send_error_msg(struct datapath *dp, const struct sender *sender, { struct buffer *buffer; struct ofp_error_msg *oem; - oem = alloc_openflow_buffer(dp, sizeof(*oem)+len, OFPT_ERROR_MSG, - sender, &buffer); + oem = make_openflow_reply(sizeof(*oem)+len, OFPT_ERROR_MSG, + sender, &buffer); oem->type = htons(type); oem->code = htons(code); memcpy(oem->data, data, len); @@ -967,8 +954,8 @@ recv_get_config_request(struct datapath *dp, const struct sender *sender, struct buffer *buffer; struct ofp_switch_config *osc; - osc = alloc_openflow_buffer(dp, sizeof *osc, OFPT_GET_CONFIG_REPLY, - sender, &buffer); + osc = make_openflow_reply(sizeof *osc, OFPT_GET_CONFIG_REPLY, + sender, &buffer); assert(sizeof *osc == sizeof dp->config); memcpy(((char *)osc) + sizeof osc->header, @@ -1382,8 +1369,8 @@ stats_dump(struct datapath *dp, void *cb_) return 0; } - osr = alloc_openflow_buffer(dp, sizeof *osr, OFPT_STATS_REPLY, &cb->sender, - &buffer); + osr = make_openflow_reply(sizeof *osr, OFPT_STATS_REPLY, &cb->sender, + &buffer); osr->type = htons(cb->s - stats); osr->flags = 0; diff --git a/utilities/dpctl.c b/utilities/dpctl.c index cc3fc5467..def02ec77 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -304,29 +304,12 @@ static void do_monitor(int argc UNUSED, char *argv[]) /* Generic commands. */ -static void * -alloc_openflow_buffer(size_t openflow_len, uint8_t type, - struct buffer **bufferp) -{ - struct buffer *buffer; - struct ofp_header *oh; - - buffer = *bufferp = buffer_new(openflow_len); - oh = buffer_put_uninit(buffer, openflow_len); - memset(oh, 0, openflow_len); - oh->version = OFP_VERSION; - oh->type = type; - oh->length = 0; - oh->xid = random_uint32(); - return oh; -} - static void * alloc_stats_request(size_t body_len, uint16_t type, struct buffer **bufferp) { struct ofp_stats_request *rq; - rq = alloc_openflow_buffer((offsetof(struct ofp_stats_request, body) - + body_len), OFPT_STATS_REQUEST, bufferp); + rq = make_openflow((offsetof(struct ofp_stats_request, body) + + body_len), OFPT_STATS_REQUEST, bufferp); rq->type = htons(type); rq->flags = htons(0); return rq->body; @@ -335,11 +318,7 @@ alloc_stats_request(size_t body_len, uint16_t type, struct buffer **bufferp) static void send_openflow_buffer(struct vconn *vconn, struct buffer *buffer) { - struct ofp_header *oh; - - oh = buffer_at_assert(buffer, 0, sizeof *oh); - oh->length = htons(buffer->size); - + update_openflow_length(buffer); run(vconn_send_block(vconn, buffer), "failed to send packet to switch"); } @@ -371,6 +350,7 @@ dump_transaction(const char *vconn_name, struct buffer *request) struct vconn *vconn; struct buffer *reply; + update_openflow_length(request); run(vconn_open_block(vconn_name, &vconn), "connecting to %s", vconn_name); reply = transact_openflow(vconn, request); ofp_print(stdout, reply->data, reply->size, 1); @@ -381,7 +361,7 @@ static void dump_trivial_transaction(const char *vconn_name, uint8_t request_type) { struct buffer *request; - alloc_openflow_buffer(sizeof(struct ofp_header), request_type, &request); + make_openflow(sizeof(struct ofp_header), request_type, &request); dump_transaction(vconn_name, request); } @@ -697,7 +677,7 @@ static void do_add_flow(int argc, char *argv[]) /* Parse and send. */ size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS); - ofm = alloc_openflow_buffer(size, OFPT_FLOW_MOD, &buffer); + ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); str_to_flow(argv[2], &ofm->match, &ofm->actions[0], &n_actions, NULL, &priority, &max_idle); ofm->command = htons(OFPFC_ADD); @@ -748,9 +728,9 @@ static void do_add_flows(int argc, char *argv[]) /* Parse and send. */ size = sizeof *ofm + (sizeof ofm->actions[0] * MAX_ADD_ACTS); - ofm = alloc_openflow_buffer(size, OFPT_FLOW_MOD, &buffer); + ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); str_to_flow(line, &ofm->match, &ofm->actions[0], &n_actions, - NULL, &priority, &max_idle); + NULL, &priority, &max_idle); ofm->command = htons(OFPFC_ADD); ofm->max_idle = htons(max_idle); ofm->buffer_id = htonl(UINT32_MAX); @@ -779,9 +759,9 @@ static void do_del_flows(int argc, char *argv[]) /* Parse and send. */ size = sizeof *ofm; - ofm = alloc_openflow_buffer(size, OFPT_FLOW_MOD, &buffer); + ofm = make_openflow(size, OFPT_FLOW_MOD, &buffer); str_to_flow(argc > 2 ? argv[2] : "", &ofm->match, NULL, 0, NULL, - &priority, NULL); + &priority, NULL); ofm->command = htons(OFPFC_DELETE); ofm->max_idle = htons(0); ofm->buffer_id = htonl(UINT32_MAX); @@ -806,8 +786,7 @@ do_probe(int argc, char *argv[]) struct vconn *vconn; struct buffer *reply; - alloc_openflow_buffer(sizeof(struct ofp_header), OFPT_ECHO_REQUEST, - &request); + 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); if (reply->size != request->size) { @@ -836,8 +815,8 @@ do_ping(int argc, char *argv[]) struct buffer *request, *reply; struct ofp_header *rq_hdr, *rpy_hdr; - rq_hdr = alloc_openflow_buffer(sizeof(struct ofp_header) + payload, - OFPT_ECHO_REQUEST, &request); + rq_hdr = make_openflow(sizeof(struct ofp_header) + payload, + OFPT_ECHO_REQUEST, &request); random_bytes(rq_hdr + 1, payload); gettimeofday(&start, NULL); @@ -892,8 +871,7 @@ do_benchmark(int argc, char *argv[]) struct buffer *request; struct ofp_header *rq_hdr; - rq_hdr = alloc_openflow_buffer(message_size, OFPT_ECHO_REQUEST, - &request); + rq_hdr = make_openflow(message_size, OFPT_ECHO_REQUEST, &request); memset(rq_hdr + 1, 0, payload_size); buffer_delete(transact_openflow(vconn, request)); }