+ const uint8_t *old_base = b->base;
+ size_t old_headroom = ofpbuf_headroom(b);
+ size_t old_tailroom = ofpbuf_tailroom(b);
+ size_t copy_headroom = MIN(old_headroom, new_headroom);
+ size_t copy_tailroom = MIN(old_tailroom, new_tailroom);
+
+ memcpy(&new_base[new_headroom - copy_headroom],
+ &old_base[old_headroom - copy_headroom],
+ copy_headroom + b->size + copy_tailroom);
+}
+
+/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom'
+ * bytes of headroom and tailroom, respectively. */
+static void
+ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom)
+{
+ void *new_base, *new_data;
+ size_t new_allocated;
+
+ new_allocated = new_headroom + b->size + new_tailroom;
+
+ switch (b->source) {
+ case OFPBUF_MALLOC:
+ if (new_headroom == ofpbuf_headroom(b)) {
+ new_base = xrealloc(b->base, new_allocated);
+ } else {
+ new_base = xmalloc(new_allocated);
+ ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
+ free(b->base);
+ }
+ break;
+
+ case OFPBUF_STACK:
+ NOT_REACHED();
+
+ default:
+ NOT_REACHED();
+ }
+
+ b->allocated = new_allocated;
+ b->base = new_base;
+
+ new_data = (char *) new_base + new_headroom;
+ if (b->data != new_data) {
+ uintptr_t data_delta = (char *) new_data - (char *) b->data;
+ b->data = new_data;