bridge: Move tunnel_egress_iface to status column.
[sliver-openvswitch.git] / lib / ofpbuf.c
index e9ad400..91ea363 100644 (file)
@@ -36,10 +36,21 @@ ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated)
     b->allocated = allocated;
     b->size = 0;
     b->l2 = b->l3 = b->l4 = b->l7 = NULL;
-    b->next = NULL;
+    list_poison(&b->list_node);
     b->private_p = NULL;
 }
 
+/* Initializes 'b' as an ofpbuf whose data starts at 'data' and continues for
+ * 'size' bytes.  This is appropriate for an ofpbuf that will be used to
+ * inspect existing data, without moving it around or reallocating it, and
+ * generally without modifying it at all. */
+void
+ofpbuf_use_const(struct ofpbuf *b, const void *data, size_t size)
+{
+    ofpbuf_use(b, (void *) data, size);
+    b->size = size;
+}
+
 /* Initializes 'b' as an empty ofpbuf with an initial capacity of 'size'
  * bytes. */
 void
@@ -50,7 +61,7 @@ ofpbuf_init(struct ofpbuf *b, size_t size)
 
 /* Frees memory that 'b' points to. */
 void
-ofpbuf_uninit(struct ofpbuf *b) 
+ofpbuf_uninit(struct ofpbuf *b)
 {
     if (b) {
         free(b->base);
@@ -75,12 +86,32 @@ ofpbuf_new(size_t size)
     return b;
 }
 
+/* Creates and returns a new ofpbuf with an initial capacity of 'size +
+ * headroom' bytes, reserving the first 'headroom' bytes as headroom. */
+struct ofpbuf *
+ofpbuf_new_with_headroom(size_t size, size_t headroom)
+{
+    struct ofpbuf *b = ofpbuf_new(size + headroom);
+    ofpbuf_reserve(b, headroom);
+    return b;
+}
+
 struct ofpbuf *
 ofpbuf_clone(const struct ofpbuf *buffer)
 {
     return ofpbuf_clone_data(buffer->data, buffer->size);
 }
 
+/* Creates and returns a new ofpbuf whose 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)
+{
+    struct ofpbuf *b = ofpbuf_new_with_headroom(buffer->size, headroom);
+    ofpbuf_put(b, buffer->data, buffer->size);
+    return b;
+}
+
 struct ofpbuf *
 ofpbuf_clone_data(const void *data, size_t size)
 {
@@ -91,7 +122,7 @@ ofpbuf_clone_data(const void *data, size_t size)
 
 /* Frees memory that 'b' points to, as well as 'b' itself. */
 void
-ofpbuf_delete(struct ofpbuf *b) 
+ofpbuf_delete(struct ofpbuf *b)
 {
     if (b) {
         ofpbuf_uninit(b);
@@ -153,7 +184,7 @@ ofpbuf_resize_tailroom__(struct ofpbuf *b, size_t new_tailroom)
  * reallocating and copying its data if necessary.  Its headroom, if any, is
  * preserved. */
 void
-ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size) 
+ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size)
 {
     if (size > ofpbuf_tailroom(b)) {
         ofpbuf_resize_tailroom__(b, MAX(size, 64));
@@ -161,7 +192,7 @@ ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size)
 }
 
 void
-ofpbuf_prealloc_headroom(struct ofpbuf *b, size_t size) 
+ofpbuf_prealloc_headroom(struct ofpbuf *b, size_t size)
 {
     assert(size <= ofpbuf_headroom(b));
 }
@@ -180,7 +211,7 @@ ofpbuf_trim(struct ofpbuf *b)
  * copying its data if necessary.  Returns a pointer to the first byte of the
  * new data, which is left uninitialized. */
 void *
-ofpbuf_put_uninit(struct ofpbuf *b, size_t size) 
+ofpbuf_put_uninit(struct ofpbuf *b, size_t size)
 {
     void *p;
     ofpbuf_prealloc_tailroom(b, size);
@@ -204,17 +235,44 @@ ofpbuf_put_zeros(struct ofpbuf *b, size_t size)
  * is reallocated and copied if necessary.  Returns a pointer to the first
  * byte of the data's location in the ofpbuf. */
 void *
-ofpbuf_put(struct ofpbuf *b, const void *p, size_t size) 
+ofpbuf_put(struct ofpbuf *b, const void *p, size_t size)
 {
     void *dst = ofpbuf_put_uninit(b, size);
     memcpy(dst, p, size);
     return dst;
 }
 
+/* Parses as many pairs of hex digits as possible (possibly separated by
+ * spaces) from the beginning of 's', appending bytes for their values to 'b'.
+ * Returns the first character of 's' that is not the first of a pair of hex
+ * digits.  If 'n' is nonnull, stores the number of bytes added to 'b' in
+ * '*n'. */
+char *
+ofpbuf_put_hex(struct ofpbuf *b, const char *s, size_t *n)
+{
+    size_t initial_size = b->size;
+    for (;;) {
+        uint8_t byte;
+        bool ok;
+
+        s += strspn(s, " ");
+        byte = hexits_value(s, 2, &ok);
+        if (!ok) {
+            if (n) {
+                *n = b->size - initial_size;
+            }
+            return (char *) s;
+        }
+
+        ofpbuf_put(b, &byte, 1);
+        s += 2;
+    }
+}
+
 /* Reserves 'size' bytes of headroom so that they can be later allocated with
  * ofpbuf_push_uninit() without reallocating the ofpbuf. */
 void
-ofpbuf_reserve(struct ofpbuf *b, size_t size) 
+ofpbuf_reserve(struct ofpbuf *b, size_t size)
 {
     assert(!b->size);
     ofpbuf_prealloc_tailroom(b, size);
@@ -222,7 +280,7 @@ ofpbuf_reserve(struct ofpbuf *b, size_t size)
 }
 
 void *
-ofpbuf_push_uninit(struct ofpbuf *b, size_t size) 
+ofpbuf_push_uninit(struct ofpbuf *b, size_t size)
 {
     ofpbuf_prealloc_headroom(b, size);
     b->data = (char*)b->data - size;
@@ -242,7 +300,7 @@ ofpbuf_push_zeros(struct ofpbuf *b, size_t size)
 }
 
 void *
-ofpbuf_push(struct ofpbuf *b, const void *p, size_t size) 
+ofpbuf_push(struct ofpbuf *b, const void *p, size_t size)
 {
     void *dst = ofpbuf_push_uninit(b, size);
     memcpy(dst, p, size);
@@ -252,7 +310,7 @@ ofpbuf_push(struct ofpbuf *b, const void *p, size_t size)
 /* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to
  * byte 'offset'.  Otherwise, returns a null pointer. */
 void *
-ofpbuf_at(const struct ofpbuf *b, size_t offset, size_t size) 
+ofpbuf_at(const struct ofpbuf *b, size_t offset, size_t size)
 {
     return offset + size <= b->size ? (char *) b->data + offset : NULL;
 }
@@ -260,7 +318,7 @@ ofpbuf_at(const struct ofpbuf *b, size_t offset, size_t size)
 /* Returns a pointer to byte 'offset' in 'b', which must contain at least
  * 'offset + size' bytes of data. */
 void *
-ofpbuf_at_assert(const struct ofpbuf *b, size_t offset, size_t size) 
+ofpbuf_at_assert(const struct ofpbuf *b, size_t offset, size_t size)
 {
     assert(offset + size <= b->size);
     return ((char *) b->data) + offset;
@@ -268,7 +326,7 @@ ofpbuf_at_assert(const struct ofpbuf *b, size_t offset, size_t size)
 
 /* Returns the byte following the last byte of data in use in 'b'. */
 void *
-ofpbuf_tail(const struct ofpbuf *b) 
+ofpbuf_tail(const struct ofpbuf *b)
 {
     return (char *) b->data + b->size;
 }
@@ -276,14 +334,14 @@ ofpbuf_tail(const struct ofpbuf *b)
 /* Returns the byte following the last byte allocated for use (but not
  * necessarily in use) by 'b'. */
 void *
-ofpbuf_end(const struct ofpbuf *b) 
+ofpbuf_end(const struct ofpbuf *b)
 {
     return (char *) b->base + b->allocated;
 }
 
 /* Clears any data from 'b'. */
 void
-ofpbuf_clear(struct ofpbuf *b) 
+ofpbuf_clear(struct ofpbuf *b)
 {
     b->data = b->base;
     b->size = 0;
@@ -292,7 +350,7 @@ ofpbuf_clear(struct ofpbuf *b)
 /* Removes 'size' bytes from the head end of 'b', which must contain at least
  * 'size' bytes of data.  Returns the first byte of data removed. */
 void *
-ofpbuf_pull(struct ofpbuf *b, size_t size) 
+ofpbuf_pull(struct ofpbuf *b, size_t size)
 {
     void *data = b->data;
     assert(b->size >= size);
@@ -305,7 +363,7 @@ ofpbuf_pull(struct ofpbuf *b, size_t size)
  * head end of 'b' and returns the first byte removed.  Otherwise, returns a
  * null pointer without modifying 'b'. */
 void *
-ofpbuf_try_pull(struct ofpbuf *b, size_t size) 
+ofpbuf_try_pull(struct ofpbuf *b, size_t size)
 {
     return b->size >= size ? ofpbuf_pull(b, size) : NULL;
 }
@@ -324,3 +382,16 @@ ofpbuf_to_string(const struct ofpbuf *b, size_t maxbytes)
     ds_put_hex_dump(&s, b->data, MIN(b->size, maxbytes), 0, false);
     return ds_cstr(&s);
 }
+
+/* Removes each of the "struct ofpbuf"s on 'list' from the list and frees
+ * them.  */
+void
+ofpbuf_list_delete(struct list *list)
+{
+    struct ofpbuf *b, *next;
+
+    LIST_FOR_EACH_SAFE (b, next, list_node, list) {
+        list_remove(&b->list_node);
+        ofpbuf_delete(b);
+    }
+}