I may be misreading the code, but nl_sock_transact_multiple__() seems incorrect to me. It seems possible to me that we would swap tmp_reply for one of the replies in 'transactions'. Since tmp_reply is (potentially) stack allocated, this could cause problems.
In a couple of places in netlink-socket %d is used instead of %zu for a sizeof in a format string. Ethan On Mon, Apr 16, 2012 at 17:18, Ben Pfaff <b...@nicira.com> wrote: > Typically an nl_sock client can stack-allocate the buffer for receiving > a Netlink message, which provides a performance boost. > > Signed-off-by: Ben Pfaff <b...@nicira.com> > --- > lib/dpif-linux.c | 25 ++++- > lib/netlink-notifier.c | 10 +- > lib/netlink-socket.c | 260 > +++++++++++++++++++++++++--------------------- > lib/netlink-socket.h | 20 +++-- > utilities/nlmon.c | 14 +-- > vswitchd/ovs-brcompatd.c | 49 ++++----- > 6 files changed, 208 insertions(+), 170 deletions(-) > > diff --git a/lib/dpif-linux.c b/lib/dpif-linux.c > index 94526f5..a2908cf 100644 > --- a/lib/dpif-linux.c > +++ b/lib/dpif-linux.c > @@ -823,8 +823,12 @@ dpif_linux_operate__(struct dpif *dpif_, struct dpif_op > **ops, size_t n_ops) > > struct op_auxdata { > struct nl_transaction txn; > + > struct ofpbuf request; > uint64_t request_stub[1024 / 8]; > + > + struct ofpbuf reply; > + uint64_t reply_stub[1024 / 8]; > } auxes[MAX_OPS]; > > struct nl_transaction *txnsp[MAX_OPS]; > @@ -843,12 +847,16 @@ dpif_linux_operate__(struct dpif *dpif_, struct dpif_op > **ops, size_t n_ops) > aux->request_stub, sizeof aux->request_stub); > aux->txn.request = &aux->request; > > + ofpbuf_use_stub(&aux->reply, aux->reply_stub, sizeof > aux->reply_stub); > + aux->txn.reply = NULL; > + > switch (op->type) { > case DPIF_OP_FLOW_PUT: > put = &op->u.flow_put; > dpif_linux_init_flow_put(dpif_, put, &flow); > if (put->stats) { > flow.nlmsg_flags |= NLM_F_ECHO; > + aux->txn.reply = &aux->reply; > } > dpif_linux_flow_to_ofpbuf(&flow, &aux->request); > break; > @@ -858,6 +866,7 @@ dpif_linux_operate__(struct dpif *dpif_, struct dpif_op > **ops, size_t n_ops) > dpif_linux_init_flow_del(dpif_, del, &flow); > if (del->stats) { > flow.nlmsg_flags |= NLM_F_ECHO; > + aux->txn.reply = &aux->reply; > } > dpif_linux_flow_to_ofpbuf(&flow, &aux->request); > break; > @@ -879,6 +888,7 @@ dpif_linux_operate__(struct dpif *dpif_, struct dpif_op > **ops, size_t n_ops) > nl_sock_transact_multiple(genl_sock, txnsp, n_ops); > > for (i = 0; i < n_ops; i++) { > + struct op_auxdata *aux = &auxes[i]; > struct nl_transaction *txn = &auxes[i].txn; > struct dpif_op *op = ops[i]; > struct dpif_flow_put *put; > @@ -918,8 +928,8 @@ dpif_linux_operate__(struct dpif *dpif_, struct dpif_op > **ops, size_t n_ops) > NOT_REACHED(); > } > > - ofpbuf_uninit(txn->request); > - ofpbuf_delete(txn->reply); > + ofpbuf_uninit(&aux->request); > + ofpbuf_uninit(&aux->reply); > } > } > > @@ -1121,10 +1131,13 @@ dpif_linux_recv(struct dpif *dpif_, struct > dpif_upcall *upcall) > return EAGAIN; > } > > - error = nl_sock_recv(upcall_sock, &buf, false); > - if (error == EAGAIN) { > - break; > - } else if (error) { > + buf = ofpbuf_new(2048); > + error = nl_sock_recv(upcall_sock, buf, false); > + if (error) { > + ofpbuf_delete(buf); > + if (error == EAGAIN) { > + break; > + } > return error; > } > > diff --git a/lib/netlink-notifier.c b/lib/netlink-notifier.c > index 9446488..7ef3d6c 100644 > --- a/lib/netlink-notifier.c > +++ b/lib/netlink-notifier.c > @@ -1,5 +1,5 @@ > /* > - * Copyright (c) 2009, 2010, 2011 Nicira Networks. > + * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -164,18 +164,20 @@ nln_run(struct nln *nln) > > nln->has_run = true; > for (;;) { > - struct ofpbuf *buf; > + uint64_t buf_stub[4096 / 8]; > + struct ofpbuf buf; > int error; > > + ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); > error = nl_sock_recv(nln->notify_sock, &buf, false); > if (!error) { > - if (nln->parse(buf, nln->change)) { > + if (nln->parse(&buf, nln->change)) { > nln_report(nln, nln->change); > } else { > VLOG_WARN_RL(&rl, "received bad netlink message"); > nln_report(nln, NULL); > } > - ofpbuf_delete(buf); > + ofpbuf_uninit(&buf); > } else if (error == EAGAIN) { > return; > } else { > diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c > index 90734c7..ab09dbc 100644 > --- a/lib/netlink-socket.c > +++ b/lib/netlink-socket.c > @@ -300,32 +300,26 @@ STRESS_OPTION( > 5, 1, -1, 100); > > static int > -nl_sock_recv__(struct nl_sock *sock, struct ofpbuf **bufp, bool wait) > +nl_sock_recv__(struct nl_sock *sock, struct ofpbuf *buf, bool wait) > { > - /* We can't accurately predict the size of the data to be received. Most > - * received data will fit in a 2 kB buffer, so we allocate that much > space. > - * In case the data is actually bigger than that, we make available > enough > - * additional space to allow Netlink messages to be up to 64 kB long (a > - * reasonable figure since that's the maximum length of a Netlink > - * attribute). */ > - enum { MAX_SIZE = 65536 }; > - enum { HEAD_SIZE = 2048 }; > - enum { TAIL_SIZE = MAX_SIZE - HEAD_SIZE }; > - > + /* We can't accurately predict the size of the data to be received. The > + * caller is supposed to have allocated enough space in 'buf' to handle > the > + * "typical" case. To handle exceptions, we make available enough space > in > + * 'tail' to allow Netlink messages to be up to 64 kB long (a reasonable > + * figure since that's the maximum length of a Netlink attribute). */ > struct nlmsghdr *nlmsghdr; > - uint8_t tail[TAIL_SIZE]; > + uint8_t tail[65536]; > struct iovec iov[2]; > - struct ofpbuf *buf; > struct msghdr msg; > ssize_t retval; > > - *bufp = NULL; > + assert(buf->allocated >= sizeof *nlmsghdr); > + ofpbuf_clear(buf); > > - buf = ofpbuf_new(HEAD_SIZE); > - iov[0].iov_base = buf->data; > - iov[0].iov_len = HEAD_SIZE; > + iov[0].iov_base = buf->base; > + iov[0].iov_len = buf->allocated; > iov[1].iov_base = tail; > - iov[1].iov_len = TAIL_SIZE; > + iov[1].iov_len = sizeof tail; > > memset(&msg, 0, sizeof msg); > msg.msg_iov = iov; > @@ -342,77 +336,65 @@ nl_sock_recv__(struct nl_sock *sock, struct ofpbuf > **bufp, bool wait) > * the kernel tried to send to us. */ > COVERAGE_INC(netlink_overflow); > } > - ofpbuf_delete(buf); > return error; > } > > if (msg.msg_flags & MSG_TRUNC) { > - VLOG_ERR_RL(&rl, "truncated message (longer than %d bytes)", > MAX_SIZE); > - ofpbuf_delete(buf); > + VLOG_ERR_RL(&rl, "truncated message (longer than %d bytes)", > + sizeof tail); > return E2BIG; > } > > - ofpbuf_put_uninit(buf, MIN(retval, HEAD_SIZE)); > - if (retval > HEAD_SIZE) { > - COVERAGE_INC(netlink_recv_jumbo); > - ofpbuf_put(buf, tail, retval - HEAD_SIZE); > - } > - > nlmsghdr = buf->data; > if (retval < sizeof *nlmsghdr > || nlmsghdr->nlmsg_len < sizeof *nlmsghdr > || nlmsghdr->nlmsg_len > retval) { > VLOG_ERR_RL(&rl, "received invalid nlmsg (%zd bytes < %d)", > - retval, NLMSG_HDRLEN); > - ofpbuf_delete(buf); > + retval, sizeof *nlmsghdr); > return EPROTO; > } > > if (STRESS(netlink_overflow)) { > - ofpbuf_delete(buf); > return ENOBUFS; > } > > - *bufp = buf; > + buf->size = MIN(retval, buf->allocated); > + if (retval > buf->allocated) { > + COVERAGE_INC(netlink_recv_jumbo); > + ofpbuf_put(buf, tail, retval - buf->allocated); > + } > + > log_nlmsg(__func__, 0, buf->data, buf->size, sock->protocol); > COVERAGE_INC(netlink_received); > > return 0; > } > > -/* Tries to receive a netlink message from the kernel on 'sock'. If > - * successful, stores the received message into '*bufp' and returns 0. The > - * caller is responsible for destroying the message with ofpbuf_delete(). On > - * failure, returns a positive errno value and stores a null pointer into > - * '*bufp'. > +/* Tries to receive a Netlink message from the kernel on 'sock' into 'buf'. > If > + * 'wait' is true, waits for a message to be ready. Otherwise, fails with > + * EAGAIN if the 'sock' receive buffer is empty. > + * > + * The caller must have initialized 'buf' with an allocation of at least > + * NLMSG_HDRLEN bytes. For best performance, the caller should allocate > enough > + * space for a "typical" message. > + * > + * On success, returns 0 and replaces 'buf''s previous content by the > received > + * message. This function expands 'buf''s allocated memory, as necessary, to > + * hold the actual size of the received message. > * > - * If 'wait' is true, nl_sock_recv waits for a message to be ready; > otherwise, > - * returns EAGAIN if the 'sock' receive buffer is empty. */ > + * On failure, returns a positive errno value and clears 'buf' to zero > length. > + * 'buf' retains its previous memory allocation. > + * > + * Regardless of success or failure, this function resets 'buf''s headroom to > + * 0. */ > int > -nl_sock_recv(struct nl_sock *sock, struct ofpbuf **bufp, bool wait) > +nl_sock_recv(struct nl_sock *sock, struct ofpbuf *buf, bool wait) > { > int error = nl_sock_cow__(sock); > if (error) { > return error; > } > - return nl_sock_recv__(sock, bufp, wait); > -} > - > -static int > -find_nl_transaction_by_seq(struct nl_transaction **transactions, size_t n, > - uint32_t seq) > -{ > - int i; > - > - for (i = 0; i < n; i++) { > - struct nl_transaction *t = transactions[i]; > - > - if (seq == nl_msg_nlmsghdr(t->request)->nlmsg_seq) { > - return i; > - } > - } > - > - return -1; > + return nl_sock_recv__(sock, buf, wait); > } > > static void > @@ -422,8 +404,12 @@ nl_sock_record_errors__(struct nl_transaction > **transactions, size_t n, > size_t i; > > for (i = 0; i < n; i++) { > - transactions[i]->error = error; > - transactions[i]->reply = NULL; > + struct nl_transaction *txn = transactions[i]; > + > + txn->error = error; > + if (txn->reply) { > + ofpbuf_clear(txn->reply); > + } > } > } > > @@ -432,21 +418,28 @@ nl_sock_transact_multiple__(struct nl_sock *sock, > struct nl_transaction **transactions, size_t n, > size_t *done) > { > + uint64_t tmp_reply_stub[1024 / 8]; > + struct nl_transaction tmp_txn; > + struct ofpbuf tmp_reply; > + > + uint32_t base_seq; > struct iovec iovs[MAX_IOVS]; > struct msghdr msg; > int error; > int i; > > + base_seq = nl_sock_allocate_seq(sock, n); > *done = 0; > for (i = 0; i < n; i++) { > - struct ofpbuf *request = transactions[i]->request; > - struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(request); > + struct nl_transaction *txn = transactions[i]; > + struct nlmsghdr *nlmsg = nl_msg_nlmsghdr(txn->request); > > - nlmsg->nlmsg_len = request->size; > + nlmsg->nlmsg_len = txn->request->size; > + nlmsg->nlmsg_seq = base_seq + i; > nlmsg->nlmsg_pid = sock->pid; > > - iovs[i].iov_base = request->data; > - iovs[i].iov_len = request->size; > + iovs[i].iov_base = txn->request->data; > + iovs[i].iov_len = txn->request->size; > } > > memset(&msg, 0, sizeof msg); > @@ -457,9 +450,9 @@ nl_sock_transact_multiple__(struct nl_sock *sock, > } while (error == EINTR); > > for (i = 0; i < n; i++) { > - struct ofpbuf *request = transactions[i]->request; > + struct nl_transaction *txn = transactions[i]; > > - log_nlmsg(__func__, error, request->data, request->size, > + log_nlmsg(__func__, error, txn->request->data, txn->request->size, > sock->protocol); > } > if (!error) { > @@ -470,62 +463,93 @@ nl_sock_transact_multiple__(struct nl_sock *sock, > return error; > } > > + ofpbuf_use_stub(&tmp_reply, tmp_reply_stub, sizeof tmp_reply_stub); > + tmp_txn.request = NULL; > + tmp_txn.reply = &tmp_reply; > + tmp_txn.error = 0; > while (n > 0) { > - struct ofpbuf *reply; > + struct nl_transaction *buf_txn, *txn; > + uint32_t seq; > + > + /* Find a transaction whose buffer we can use for receiving a reply. > + * If no such transaction is left, use tmp_txn. */ > + buf_txn = &tmp_txn; > + for (i = 0; i < n; i++) { > + if (transactions[i]->reply) { > + buf_txn = transactions[i]; > + break; > + } > + } > > - error = nl_sock_recv__(sock, &reply, false); > - if (error == EAGAIN) { > - nl_sock_record_errors__(transactions, n, 0); > - *done += n; > - return 0; > - } else if (error) { > - return error; > + /* Receive a reply. */ > + error = nl_sock_recv__(sock, buf_txn->reply, false); > + if (error) { > + if (error == EAGAIN) { > + nl_sock_record_errors__(transactions, n, 0); > + *done += n; > + error = 0; > + } > + break; > } > > - i = find_nl_transaction_by_seq(transactions, n, > - nl_msg_nlmsghdr(reply)->nlmsg_seq); > - if (i < 0) { > - VLOG_DBG_RL(&rl, "ignoring unexpected seq %#"PRIx32, > - nl_msg_nlmsghdr(reply)->nlmsg_seq); > - ofpbuf_delete(reply); > + /* Match the reply up with a transaction. */ > + seq = nl_msg_nlmsghdr(buf_txn->reply)->nlmsg_seq; > + if (seq < base_seq || seq >= base_seq + n) { > + VLOG_DBG_RL(&rl, "ignoring unexpected seq %#"PRIx32, seq); > continue; > } > + i = seq - base_seq; > + txn = transactions[i]; > > - nl_sock_record_errors__(transactions, i, 0); > - if (nl_msg_nlmsgerr(reply, &error)) { > - transactions[i]->reply = NULL; > - transactions[i]->error = error; > - if (error) { > + /* Fill in the results for 'txn'. */ > + if (nl_msg_nlmsgerr(buf_txn->reply, &txn->error)) { > + if (txn->reply) { > + ofpbuf_clear(txn->reply); > + } > + if (txn->error) { > VLOG_DBG_RL(&rl, "received NAK error=%d (%s)", > - error, strerror(error)); > + error, strerror(txn->error)); > } > - ofpbuf_delete(reply); > } else { > - transactions[i]->reply = reply; > - transactions[i]->error = 0; > + txn->error = 0; > + if (txn->reply && txn != buf_txn) { > + /* Swap buffers. */ > + struct ofpbuf *reply = buf_txn->reply; > + buf_txn->reply = txn->reply; > + txn->reply = reply; > + } > } > > + /* Fill in the results for transactions before 'txn'. (We have to do > + * this after the results for 'txn' itself because of the buffer swap > + * above.) */ > + nl_sock_record_errors__(transactions, i, 0); > + > + /* Advance. */ > *done += i + 1; > transactions += i + 1; > n -= i + 1; > + base_seq += i + 1; > } > + ofpbuf_uninit(&tmp_reply); > > - return 0; > + return error; > } > > -/* Sends the 'request' member of the 'n' transactions in 'transactions' to > the > - * kernel, in order, and waits for responses to all of them. Fills in the > +/* Sends the 'request' member of the 'n' transactions in 'transactions' on > + * 'sock', in order, and receives responses to all of them. Fills in the > * 'error' member of each transaction with 0 if it was successful, otherwise > - * with a positive errno value. 'reply' will be NULL on error or if the > - * transaction was successful but had no reply beyond an indication of > success. > - * For a successful transaction that did have a more detailed reply, 'reply' > - * will be set to the reply message. > + * with a positive errno value. If 'reply' is nonnull, then it will be > filled > + * with the reply if the message receives a detailed reply. In other cases, > + * i.e. where the request failed or had no reply beyond an indication of > + * success, 'reply' will be cleared if it is nonnull. > * > * The caller is responsible for destroying each request and reply, and the > * transactions array itself. > * > * Before sending each message, this function will finalize nlmsg_len in each > - * 'request' to match the ofpbuf's size, and set nlmsg_pid to 'sock''s pid. > + * 'request' to match the ofpbuf's size, set nlmsg_pid to 'sock''s pid, and > + * initialize nlmsg_seq. > * > * Bare Netlink is an unreliable transport protocol. This function layers > * reliable delivery and reply semantics on top of bare Netlink. See > @@ -640,13 +664,20 @@ nl_sock_transact(struct nl_sock *sock, const struct > ofpbuf *request, > struct nl_transaction transaction; > > transaction.request = (struct ofpbuf *) request; > + transaction.reply = replyp ? ofpbuf_new(1024) : NULL; > transactionp = &transaction; > + > nl_sock_transact_multiple(sock, &transactionp, 1); > + > if (replyp) { > - *replyp = transaction.reply; > - } else { > - ofpbuf_delete(transaction.reply); > + if (transaction.error) { > + ofpbuf_delete(transaction.reply); > + *replyp = NULL; > + } else { > + *replyp = transaction.reply; > + } > } > + > return transaction.error; > } > > @@ -724,7 +755,7 @@ void > nl_dump_start(struct nl_dump *dump, > struct nl_sock *sock, const struct ofpbuf *request) > { > - dump->buffer = NULL; > + ofpbuf_init(&dump->buffer, 4096); > if (sock->dump) { > /* 'sock' already has an ongoing dump. Clone the socket because > * Netlink only allows one dump at a time. */ > @@ -745,26 +776,24 @@ nl_dump_start(struct nl_dump *dump, > > /* Helper function for nl_dump_next(). */ > static int > -nl_dump_recv(struct nl_dump *dump, struct ofpbuf **bufferp) > +nl_dump_recv(struct nl_dump *dump) > { > struct nlmsghdr *nlmsghdr; > - struct ofpbuf *buffer; > int retval; > > - retval = nl_sock_recv__(dump->sock, bufferp, true); > + retval = nl_sock_recv__(dump->sock, &dump->buffer, true); > if (retval) { > return retval == EINTR ? EAGAIN : retval; > } > - buffer = *bufferp; > > - nlmsghdr = nl_msg_nlmsghdr(buffer); > + nlmsghdr = nl_msg_nlmsghdr(&dump->buffer); > if (dump->seq != nlmsghdr->nlmsg_seq) { > VLOG_DBG_RL(&rl, "ignoring seq %#"PRIx32" != expected %#"PRIx32, > nlmsghdr->nlmsg_seq, dump->seq); > return EAGAIN; > } > > - if (nl_msg_nlmsgerr(buffer, &retval)) { > + if (nl_msg_nlmsgerr(&dump->buffer, &retval)) { > VLOG_INFO_RL(&rl, "netlink dump request error (%s)", > strerror(retval)); > return retval && retval != EAGAIN ? retval : EPROTO; > @@ -796,15 +825,10 @@ nl_dump_next(struct nl_dump *dump, struct ofpbuf *reply) > return false; > } > > - if (dump->buffer && !dump->buffer->size) { > - ofpbuf_delete(dump->buffer); > - dump->buffer = NULL; > - } > - while (!dump->buffer) { > - int retval = nl_dump_recv(dump, &dump->buffer); > + while (!dump->buffer.size) { > + int retval = nl_dump_recv(dump); > if (retval) { > - ofpbuf_delete(dump->buffer); > - dump->buffer = NULL; > + ofpbuf_clear(&dump->buffer); > if (retval != EAGAIN) { > dump->status = retval; > return false; > @@ -812,7 +836,7 @@ nl_dump_next(struct nl_dump *dump, struct ofpbuf *reply) > } > } > > - nlmsghdr = nl_msg_next(dump->buffer, reply); > + nlmsghdr = nl_msg_next(&dump->buffer, reply); > if (!nlmsghdr) { > VLOG_WARN_RL(&rl, "netlink dump reply contains message fragment"); > dump->status = EPROTO; > @@ -847,7 +871,7 @@ nl_dump_done(struct nl_dump *dump) > nl_sock_destroy(dump->sock); > } > } > - ofpbuf_delete(dump->buffer); > + ofpbuf_uninit(&dump->buffer); > return dump->status == EOF ? 0 : dump->status; > } > > @@ -1187,5 +1211,3 @@ log_nlmsg(const char *function, int error, > VLOG_DBG_RL(&rl, "%s (%s): %s", function, strerror(error), nlmsg); > free(nlmsg); > } > - > - > diff --git a/lib/netlink-socket.h b/lib/netlink-socket.h > index 9d288bd..0232616 100644 > --- a/lib/netlink-socket.h > +++ b/lib/netlink-socket.h > @@ -1,5 +1,5 @@ > /* > - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. > + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks. > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -35,8 +35,8 @@ > #include <stdbool.h> > #include <stddef.h> > #include <stdint.h> > +#include "ofpbuf.h" > > -struct ofpbuf; > struct nl_sock; > > #ifndef HAVE_NETLINK > @@ -52,9 +52,9 @@ int nl_sock_join_mcgroup(struct nl_sock *, unsigned int > multicast_group); > int nl_sock_leave_mcgroup(struct nl_sock *, unsigned int multicast_group); > > int nl_sock_send(struct nl_sock *, const struct ofpbuf *, bool wait); > -int nl_sock_recv(struct nl_sock *, struct ofpbuf **, bool wait); > +int nl_sock_recv(struct nl_sock *, struct ofpbuf *, bool wait); > int nl_sock_transact(struct nl_sock *, const struct ofpbuf *request, > - struct ofpbuf **reply); > + struct ofpbuf **replyp); > > int nl_sock_drain(struct nl_sock *); > > @@ -68,8 +68,14 @@ struct nl_transaction { > /* Filled in by client. */ > struct ofpbuf *request; /* Request to send. */ > > - /* Filled in by nl_sock_transact_batch(). */ > - struct ofpbuf *reply; /* Reply (NULL if reply was an error code). > */ > + /* The client must initialize 'reply' to one of: > + * > + * - NULL, if it does not care to examine the reply. > + * > + * - Otherwise, to an ofpbuf with a memory allocation of at least > + * NLMSG_HDRLEN bytes. > + */ > + struct ofpbuf *reply; /* Reply (empty if reply was an error code). > */ > int error; /* Positive errno value, 0 if no error. */ > }; > > @@ -80,7 +86,7 @@ void nl_sock_transact_multiple(struct nl_sock *, > struct nl_dump { > struct nl_sock *sock; /* Socket being dumped. */ > uint32_t seq; /* Expected nlmsg_seq for replies. */ > - struct ofpbuf *buffer; /* Receive buffer currently being iterated. > */ > + struct ofpbuf buffer; /* Receive buffer currently being iterated. > */ > int status; /* 0=OK, EOF=done, or positive errno value. */ > }; > > diff --git a/utilities/nlmon.c b/utilities/nlmon.c > index 1b2f1e2..e6cf023 100644 > --- a/utilities/nlmon.c > +++ b/utilities/nlmon.c > @@ -39,7 +39,9 @@ static const struct nl_policy rtnlgrp_link_policy[] = { > int > main(int argc OVS_UNUSED, char *argv[]) > { > + uint64_t buf_stub[4096 / 64]; > struct nl_sock *sock; > + struct ofpbuf buf; > int error; > > set_program_name(argv[0]); > @@ -55,9 +57,8 @@ main(int argc OVS_UNUSED, char *argv[]) > ovs_fatal(error, "could not join RTNLGRP_LINK multicast group"); > } > > + ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); > for (;;) { > - struct ofpbuf *buf; > - > error = nl_sock_recv(sock, &buf, false); > if (error == EAGAIN) { > /* Nothing to do. */ > @@ -95,19 +96,17 @@ main(int argc OVS_UNUSED, char *argv[]) > struct ifinfomsg *iim; > int i; > > - nlh = ofpbuf_at(buf, 0, NLMSG_HDRLEN); > - iim = ofpbuf_at(buf, NLMSG_HDRLEN, sizeof *iim); > + nlh = ofpbuf_at(&buf, 0, NLMSG_HDRLEN); > + iim = ofpbuf_at(&buf, NLMSG_HDRLEN, sizeof *iim); > if (!iim) { > ovs_error(0, "received bad rtnl message (no ifinfomsg)"); > - ofpbuf_delete(buf); > continue; > } > > - if (!nl_policy_parse(buf, NLMSG_HDRLEN + sizeof(struct > ifinfomsg), > + if (!nl_policy_parse(&buf, NLMSG_HDRLEN + sizeof(struct > ifinfomsg), > rtnlgrp_link_policy, > attrs, ARRAY_SIZE(rtnlgrp_link_policy))) { > ovs_error(0, "received bad rtnl message (policy)"); > - ofpbuf_delete(buf); > continue; > } > printf("netdev %s changed (%s):\n", > @@ -132,7 +131,6 @@ main(int argc OVS_UNUSED, char *argv[]) > } > printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname); > } > - ofpbuf_delete(buf); > } > > nl_sock_wait(sock, POLLIN); > diff --git a/vswitchd/ovs-brcompatd.c b/vswitchd/ovs-brcompatd.c > index 18a6708..8b1ad5d 100644 > --- a/vswitchd/ovs-brcompatd.c > +++ b/vswitchd/ovs-brcompatd.c > @@ -1,4 +1,4 @@ > -/* Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks > +/* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira Networks > * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > @@ -654,56 +654,53 @@ handle_get_ports_cmd(struct ofpbuf *buffer) > return 0; > } > > -static struct ofpbuf * > -brc_recv_update__(void) > +static bool > +brc_recv_update__(struct ofpbuf *buffer) > { > for (;;) { > - struct ofpbuf *buffer; > - int retval; > - > - retval = nl_sock_recv(brc_sock, &buffer, false); > + int retval = nl_sock_recv(brc_sock, buffer, false); > switch (retval) { > case 0: > if (nl_msg_nlmsgerr(buffer, NULL) > || nl_msg_nlmsghdr(buffer)->nlmsg_type == NLMSG_DONE) { > break; > } > - return buffer; > + return true; > > case ENOBUFS: > break; > > case EAGAIN: > - return NULL; > + return false; > > default: > VLOG_WARN_RL(&rl, "brc_recv_update: %s", strerror(retval)); > - return NULL; > + return false; > } > - ofpbuf_delete(buffer); > } > } > > static void > brc_recv_update(void) > { > - struct ofpbuf *buffer; > struct genlmsghdr *genlmsghdr; > + uint64_t buffer_stub[1024 / 8]; > + struct ofpbuf buffer; > > - buffer = brc_recv_update__(); > - if (!buffer) { > - return; > + ofpbuf_use_stub(&buffer, buffer_stub, sizeof buffer_stub); > + if (!brc_recv_update__(&buffer)) { > + goto error; > } > > - genlmsghdr = nl_msg_genlmsghdr(buffer); > + genlmsghdr = nl_msg_genlmsghdr(&buffer); > if (!genlmsghdr) { > VLOG_WARN_RL(&rl, "received packet too short for generic NetLink"); > goto error; > } > > - if (nl_msg_nlmsghdr(buffer)->nlmsg_type != brc_family) { > + if (nl_msg_nlmsghdr(&buffer)->nlmsg_type != brc_family) { > VLOG_DBG_RL(&rl, "received type (%"PRIu16") != brcompat family (%d)", > - nl_msg_nlmsghdr(buffer)->nlmsg_type, brc_family); > + nl_msg_nlmsghdr(&buffer)->nlmsg_type, brc_family); > goto error; > } > > @@ -729,31 +726,31 @@ brc_recv_update(void) > > switch (genlmsghdr->cmd) { > case BRC_GENL_C_DP_ADD: > - handle_bridge_cmd(buffer, true); > + handle_bridge_cmd(&buffer, true); > break; > > case BRC_GENL_C_DP_DEL: > - handle_bridge_cmd(buffer, false); > + handle_bridge_cmd(&buffer, false); > break; > > case BRC_GENL_C_PORT_ADD: > - handle_port_cmd(buffer, true); > + handle_port_cmd(&buffer, true); > break; > > case BRC_GENL_C_PORT_DEL: > - handle_port_cmd(buffer, false); > + handle_port_cmd(&buffer, false); > break; > > case BRC_GENL_C_FDB_QUERY: > - handle_fdb_query_cmd(buffer); > + handle_fdb_query_cmd(&buffer); > break; > > case BRC_GENL_C_GET_BRIDGES: > - handle_get_bridges_cmd(buffer); > + handle_get_bridges_cmd(&buffer); > break; > > case BRC_GENL_C_GET_PORTS: > - handle_get_ports_cmd(buffer); > + handle_get_ports_cmd(&buffer); > break; > > default: > @@ -763,7 +760,7 @@ brc_recv_update(void) > } > > error: > - ofpbuf_delete(buffer); > + ofpbuf_uninit(&buffer); > } > > static void > -- > 1.7.9 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev