[ovs-dev] [PATCH] ofp: ensure that l2 is set in ofpmp_reserve()

Simon Horman horms at verge.net.au
Tue Feb 12 08:19:38 UTC 2013


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 <horms at verge.net.au>
---
 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




More information about the dev mailing list