Ensure that the buffer returned by ofpmp_reserve() has buf->l2 set as this may be required by nxm_reg_load_to_nxast() when generating the reply to an stats request
This problem was observed when dumping a large number of flows with set_field actions using ovs-ofctl dump-flows. Signed-off-by: Simon Horman <[email protected]> --- lib/ofp-msgs.c | 3 +-- lib/ofpbuf.c | 24 ++++++++++++++---------- lib/ofpbuf.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/ofp-msgs.c b/lib/ofp-msgs.c index 47d7615..7b31fe6 100644 --- a/lib/ofp-msgs.c +++ b/lib/ofp-msgs.c @@ -832,8 +832,7 @@ ofpmp_reserve(struct list *replies, size_t len) ofphdrs_decode_assert(&hdrs, msg->data, msg->size); hdrs_len = ofphdrs_len(&hdrs); - next = ofpbuf_new(MAX(1024, hdrs_len + len)); - ofpbuf_put(next, msg->data, hdrs_len); + next = ofpbuf_clone_with_headroom(msg, hdrs_len, MAX(len, 1024)); list_push_back(replies, &next->list_node); *ofpmp_flags__(msg->data) |= htons(OFPSF_REPLY_MORE); diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c index fd10da3..e17c744 100644 --- a/lib/ofpbuf.c +++ b/lib/ofpbuf.c @@ -158,34 +158,38 @@ ofpbuf_new_with_headroom(size_t size, size_t headroom) struct ofpbuf * ofpbuf_clone(const struct ofpbuf *buffer) { - return ofpbuf_clone_with_headroom(buffer, 0); + return ofpbuf_clone_with_headroom(buffer, buffer->size, 0); } -/* Creates and returns a new ofpbuf whose data are copied from 'buffer'. The - * returned ofpbuf will additionally have 'headroom' bytes of headroom. */ +/* Creates and returns a new ofpbuf whose 'size' bytes of data are copied from + * 'buffer'. The returned ofpbuf will additionally have 'headroom' bytes + * of headroom. */ struct ofpbuf * -ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom) +ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t size, + size_t headroom) { struct ofpbuf *new_buffer; uintptr_t data_delta; - new_buffer = ofpbuf_clone_data_with_headroom(buffer->data, buffer->size, + size = MIN(size, buffer->size); + + new_buffer = ofpbuf_clone_data_with_headroom(buffer->data, size, headroom); data_delta = (char *) new_buffer->data - (char *) buffer->data; - if (buffer->l2) { + if (buffer->l2 && (char *) buffer->l2 - (char *) buffer->data < size) { new_buffer->l2 = (char *) buffer->l2 + data_delta; } - if (buffer->l2_5) { + if (buffer->l2_5 && (char *) buffer->l2_5 - (char *) buffer->data < size) { new_buffer->l2_5 = (char *) buffer->l2_5 + data_delta; } - if (buffer->l3) { + if (buffer->l3 && (char *) buffer->l3 - (char *) buffer->data < size) { new_buffer->l3 = (char *) buffer->l3 + data_delta; } - if (buffer->l4) { + if (buffer->l4 && (char *) buffer->l4 - (char *) buffer->data < size) { new_buffer->l4 = (char *) buffer->l4 + data_delta; } - if (buffer->l7) { + if (buffer->l7 && (char *) buffer->l7 - (char *) buffer->data < size) { new_buffer->l7 = (char *) buffer->l7 + data_delta; } diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h index bae3c0a..3aad3e1 100644 --- a/lib/ofpbuf.h +++ b/lib/ofpbuf.h @@ -69,7 +69,7 @@ void ofpbuf_reinit(struct ofpbuf *, size_t); struct ofpbuf *ofpbuf_new(size_t); struct ofpbuf *ofpbuf_new_with_headroom(size_t, size_t headroom); struct ofpbuf *ofpbuf_clone(const struct ofpbuf *); -struct ofpbuf *ofpbuf_clone_with_headroom(const struct ofpbuf *, +struct ofpbuf *ofpbuf_clone_with_headroom(const struct ofpbuf *, size_t size, size_t headroom); struct ofpbuf *ofpbuf_clone_data(const void *, size_t); struct ofpbuf *ofpbuf_clone_data_with_headroom(const void *, size_t, -- 1.7.10.4 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
