Drop rconn's responsibility for limiting the tx queue.
[sliver-openvswitch.git] / lib / buffer.c
index 1a988d4..47600e6 100644 (file)
@@ -1,24 +1,37 @@
-/* Copyright (C) 2007 Board of Trustees, Leland Stanford Jr. University.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ * 
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ * 
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
  */
 
+#include <config.h>
 #include "buffer.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -38,8 +51,9 @@ buffer_use(struct buffer *b, void *base, size_t allocated)
     b->base = b->data = base;
     b->allocated = allocated;
     b->size = 0;
-    b->l2 = b->l3 = b->l4 = NULL;
+    b->l2 = b->l3 = b->l4 = b->l7 = NULL;
     b->next = NULL;
+    b->private = NULL;
 }
 
 /* Initializes 'b' as a buffer with an initial capacity of 'size' bytes. */
@@ -116,7 +130,7 @@ buffer_tailroom(struct buffer *b)
 /* Ensures that 'b' has room for at least 'size' bytes at its tail end,
  * reallocating and copying its data if necessary. */
 void
-buffer_reserve_tailroom(struct buffer *b, size_t size) 
+buffer_prealloc_tailroom(struct buffer *b, size_t size) 
 {
     if (size > buffer_tailroom(b)) {
         size_t new_allocated = b->allocated + MAX(size, 64);
@@ -136,11 +150,14 @@ buffer_reserve_tailroom(struct buffer *b, size_t size)
         if (b->l4) {
             b->l4 += base_delta;
         }
+        if (b->l7) {
+            b->l7 += base_delta;
+        }
     }
 }
 
 void
-buffer_reserve_headroom(struct buffer *b, size_t size) 
+buffer_prealloc_headroom(struct buffer *b, size_t size) 
 {
     assert(size <= buffer_headroom(b));
 }
@@ -152,31 +169,52 @@ void *
 buffer_put_uninit(struct buffer *b, size_t size) 
 {
     void *p;
-    buffer_reserve_tailroom(b, size);
+    buffer_prealloc_tailroom(b, size);
     p = buffer_tail(b);
     b->size += size;
     return p;
 }
 
 /* Appends the 'size' bytes of data in 'p' to the tail end of 'b'.  Data in 'b'
- * is reallocated and copied if necessary. */
-void
+ * is reallocated and copied if necessary.  Returns a pointer to the first
+ * byte of the data's location in the buffer. */
+void *
 buffer_put(struct buffer *b, const void *p, size_t size) 
 {
-    memcpy(buffer_put_uninit(b, size), p, size);
+    void *dst = buffer_put_uninit(b, size);
+    memcpy(dst, p, size);
+    return dst;
+}
+
+/* Reserves 'size' bytes of headroom so that they can be later allocated with
+ * buffer_push_uninit() without reallocating the buffer. */
+void
+buffer_reserve(struct buffer *b, size_t size) 
+{
+    assert(!b->size);
+    buffer_prealloc_tailroom(b, size);
+    b->data += size;
 }
 
 void *
 buffer_push_uninit(struct buffer *b, size_t size) 
 {
-    buffer_reserve_headroom(b, size);
+    buffer_prealloc_headroom(b, size);
     b->data -= size;
     b->size += size;
     return b->data;
 }
 
+void *
+buffer_push(struct buffer *b, const void *p, size_t size) 
+{
+    void *dst = buffer_push_uninit(b, size);
+    memcpy(dst, p, size);
+    return dst;
+}
+
 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
- * byte 'offset'.  Otherwise, returns a null pointers. */
+ * byte 'offset'.  Otherwise, returns a null pointer. */
 void *
 buffer_at(const struct buffer *b, size_t offset, size_t size) 
 {
@@ -216,12 +254,22 @@ buffer_clear(struct buffer *b)
 }
 
 /* Removes 'size' bytes from the head end of 'b', which must contain at least
- * 'size' bytes of data. */
-void
+ * 'size' bytes of data.  Returns the first byte of data removed. */
+void *
 buffer_pull(struct buffer *b, size_t size) 
 {
+    void *data = b->data;
     assert(b->size >= size);
     b->data += size;
     b->size -= size;
+    return data;
 }
 
+/* If 'b' has at least 'size' bytes of data, removes that many bytes from the
+ * head end of 'b' and returns the first byte removed.  Otherwise, returns a
+ * null pointer without modifying 'b'. */
+void *
+buffer_try_pull(struct buffer *b, size_t size) 
+{
+    return b->size >= size ? buffer_pull(b, size) : NULL;
+}