From: Ben Pfaff Date: Thu, 18 Dec 2008 22:01:35 +0000 (-0800) Subject: New functions put_openflow() and put_openflow_xid(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=733d8297c45ba4fe554a1278eadd6d60b358c0e2;p=openvswitch New functions put_openflow() and put_openflow_xid(). --- diff --git a/lib/vconn.c b/lib/vconn.c index 41c1eefa..bfd7b3f1 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -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); diff --git a/lib/vconn.h b/lib/vconn.h index a01d93db..9261e640 100644 --- a/lib/vconn.h +++ b/lib/vconn.h @@ -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);