]> git.proxmox.com Git - ovs.git/blame - lib/ofpbuf.c
ofpbuf: Abstract 'l2' pointer and document usage conventions.
[ovs.git] / lib / ofpbuf.c
CommitLineData
064af421 1/*
125638eb 2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
064af421 3 *
a14bc59f
BP
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
064af421 7 *
a14bc59f
BP
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
064af421
BP
15 */
16
17#include <config.h>
18#include "ofpbuf.h"
064af421
BP
19#include <stdlib.h>
20#include <string.h>
0ab8e15f 21#include "dynamic-string.h"
8a9562d2 22#include "netdev-dpdk.h"
064af421
BP
23#include "util.h"
24
d8a59e89
PS
25static void
26ofpbuf_init__(struct ofpbuf *b, size_t allocated, enum ofpbuf_source source)
27{
28 b->allocated = allocated;
29 b->source = source;
cf3b7538 30 b->frame = NULL;
d8a59e89
PS
31 b->l2_5_ofs = b->l3_ofs = b->l4_ofs = UINT16_MAX;
32 list_poison(&b->list_node);
33}
34
31ac1e59
BP
35static void
36ofpbuf_use__(struct ofpbuf *b, void *base, size_t allocated,
37 enum ofpbuf_source source)
064af421 38{
1f317cb5
PS
39 ofpbuf_set_base(b, base);
40 ofpbuf_set_data(b, base);
41 ofpbuf_set_size(b, 0);
42
d8a59e89 43 ofpbuf_init__(b, allocated, source);
064af421
BP
44}
45
31ac1e59
BP
46/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
47 * memory starting at 'base'. 'base' should be the first byte of a region
48 * obtained from malloc(). It will be freed (with free()) if 'b' is resized or
49 * freed. */
50void
51ofpbuf_use(struct ofpbuf *b, void *base, size_t allocated)
52{
53 ofpbuf_use__(b, base, allocated, OFPBUF_MALLOC);
54}
55
56/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
57 * memory starting at 'base'. 'base' should point to a buffer on the stack.
cca408da
BP
58 * (Nothing actually relies on 'base' being allocated on the stack. It could
59 * be static or malloc()'d memory. But stack space is the most common use
60 * case.)
31ac1e59
BP
61 *
62 * 'base' should be appropriately aligned. Using an array of uint32_t or
63 * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
125638eb 64 * for 32- or 64-bit data.
31ac1e59 65 *
cca408da
BP
66 * An ofpbuf operation that requires reallocating data will assert-fail if this
67 * function was used to initialize it. Thus, one need not call ofpbuf_uninit()
68 * on an ofpbuf initialized by this function (though doing so is harmless),
69 * because it is guaranteed that 'b' does not own any heap-allocated memory. */
31ac1e59
BP
70void
71ofpbuf_use_stack(struct ofpbuf *b, void *base, size_t allocated)
72{
73 ofpbuf_use__(b, base, allocated, OFPBUF_STACK);
74}
75
cca408da
BP
76/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
77 * memory starting at 'base'. 'base' should point to a buffer on the stack.
78 * (Nothing actually relies on 'base' being allocated on the stack. It could
be9fa766 79 * be static or malloc()'d memory. But stack space is the most common use
cca408da
BP
80 * case.)
81 *
82 * 'base' should be appropriately aligned. Using an array of uint32_t or
83 * uint64_t for the buffer is a reasonable way to ensure appropriate alignment
125638eb 84 * for 32- or 64-bit data.
cca408da
BP
85 *
86 * An ofpbuf operation that requires reallocating data will copy the provided
87 * buffer into a malloc()'d buffer. Thus, it is wise to call ofpbuf_uninit()
88 * on an ofpbuf initialized by this function, so that if it expanded into the
89 * heap, that memory is freed. */
90void
91ofpbuf_use_stub(struct ofpbuf *b, void *base, size_t allocated)
92{
93 ofpbuf_use__(b, base, allocated, OFPBUF_STUB);
94}
95
0bc9407d
BP
96/* Initializes 'b' as an ofpbuf whose data starts at 'data' and continues for
97 * 'size' bytes. This is appropriate for an ofpbuf that will be used to
98 * inspect existing data, without moving it around or reallocating it, and
31ac1e59
BP
99 * generally without modifying it at all.
100 *
101 * An ofpbuf operation that requires reallocating data will assert-fail if this
102 * function was used to initialize it. */
0bc9407d
BP
103void
104ofpbuf_use_const(struct ofpbuf *b, const void *data, size_t size)
105{
ebc56baa 106 ofpbuf_use__(b, CONST_CAST(void *, data), size, OFPBUF_STACK);
1f317cb5 107 ofpbuf_set_size(b, size);
0bc9407d
BP
108}
109
d8a59e89
PS
110/* Initializes 'b' as an empty ofpbuf that contains the 'allocated' bytes of
111 * memory starting at 'base'. DPDK allocated ofpbuf and *data is allocated
112 * from one continous memory region, so in memory data start right after
113 * ofpbuf. Therefore there is special method to free this type of
114 * buffer. ofpbuf base, data and size are initialized by dpdk rcv() so no
115 * need to initialize those fields. */
116void
117ofpbuf_init_dpdk(struct ofpbuf *b, size_t allocated)
118{
119 ofpbuf_init__(b, allocated, OFPBUF_DPDK);
120}
121
064af421
BP
122/* Initializes 'b' as an empty ofpbuf with an initial capacity of 'size'
123 * bytes. */
124void
125ofpbuf_init(struct ofpbuf *b, size_t size)
126{
127 ofpbuf_use(b, size ? xmalloc(size) : NULL, size);
128}
129
130/* Frees memory that 'b' points to. */
131void
d295e8e9 132ofpbuf_uninit(struct ofpbuf *b)
064af421 133{
8a9562d2
PS
134 if (b) {
135 if (b->source == OFPBUF_MALLOC) {
1f317cb5 136 free(ofpbuf_base(b));
8a9562d2 137 }
b3cd9f9d 138 ovs_assert(b->source != OFPBUF_DPDK);
064af421
BP
139 }
140}
141
142/* Frees memory that 'b' points to and allocates a new ofpbuf */
143void
144ofpbuf_reinit(struct ofpbuf *b, size_t size)
145{
146 ofpbuf_uninit(b);
147 ofpbuf_init(b, size);
148}
149
150/* Creates and returns a new ofpbuf with an initial capacity of 'size'
151 * bytes. */
152struct ofpbuf *
153ofpbuf_new(size_t size)
154{
155 struct ofpbuf *b = xmalloc(sizeof *b);
156 ofpbuf_init(b, size);
157 return b;
158}
159
68efcbec
BP
160/* Creates and returns a new ofpbuf with an initial capacity of 'size +
161 * headroom' bytes, reserving the first 'headroom' bytes as headroom. */
162struct ofpbuf *
163ofpbuf_new_with_headroom(size_t size, size_t headroom)
164{
165 struct ofpbuf *b = ofpbuf_new(size + headroom);
166 ofpbuf_reserve(b, headroom);
167 return b;
168}
169
a46c577a 170/* Creates and returns a new ofpbuf that initially contains a copy of the
1f317cb5 171 * 'ofpbuf_size(buffer)' bytes of data starting at 'buffer->data' with no headroom or
a46c577a 172 * tailroom. */
064af421
BP
173struct ofpbuf *
174ofpbuf_clone(const struct ofpbuf *buffer)
175{
6aa728e0 176 return ofpbuf_clone_with_headroom(buffer, 0);
064af421
BP
177}
178
68efcbec
BP
179/* Creates and returns a new ofpbuf whose data are copied from 'buffer'. The
180 * returned ofpbuf will additionally have 'headroom' bytes of headroom. */
181struct ofpbuf *
182ofpbuf_clone_with_headroom(const struct ofpbuf *buffer, size_t headroom)
183{
6aa728e0 184 struct ofpbuf *new_buffer;
6aa728e0 185
1f317cb5
PS
186 new_buffer = ofpbuf_clone_data_with_headroom(ofpbuf_data(buffer),
187 ofpbuf_size(buffer),
6aa728e0 188 headroom);
cf3b7538
JR
189 if (buffer->frame) {
190 uintptr_t data_delta
191 = (char *)ofpbuf_data(new_buffer) - (char *)ofpbuf_data(buffer);
437d0d22 192
cf3b7538 193 new_buffer->frame = (char *) buffer->frame + data_delta;
6aa728e0 194 }
437d0d22
JR
195 new_buffer->l2_5_ofs = buffer->l2_5_ofs;
196 new_buffer->l3_ofs = buffer->l3_ofs;
197 new_buffer->l4_ofs = buffer->l4_ofs;
6aa728e0
EJ
198
199 return new_buffer;
68efcbec
BP
200}
201
a46c577a
BP
202/* Creates and returns a new ofpbuf that initially contains a copy of the
203 * 'size' bytes of data starting at 'data' with no headroom or tailroom. */
064af421
BP
204struct ofpbuf *
205ofpbuf_clone_data(const void *data, size_t size)
206{
a46c577a
BP
207 return ofpbuf_clone_data_with_headroom(data, size, 0);
208}
209
210/* Creates and returns a new ofpbuf that initially contains 'headroom' bytes of
211 * headroom followed by a copy of the 'size' bytes of data starting at
212 * 'data'. */
213struct ofpbuf *
214ofpbuf_clone_data_with_headroom(const void *data, size_t size, size_t headroom)
215{
216 struct ofpbuf *b = ofpbuf_new_with_headroom(size, headroom);
064af421
BP
217 ofpbuf_put(b, data, size);
218 return b;
219}
220
1f5cbaa3 221static void
0dce369b
BP
222ofpbuf_copy__(struct ofpbuf *b, uint8_t *new_base,
223 size_t new_headroom, size_t new_tailroom)
064af421 224{
1f317cb5 225 const uint8_t *old_base = ofpbuf_base(b);
0dce369b
BP
226 size_t old_headroom = ofpbuf_headroom(b);
227 size_t old_tailroom = ofpbuf_tailroom(b);
228 size_t copy_headroom = MIN(old_headroom, new_headroom);
229 size_t copy_tailroom = MIN(old_tailroom, new_tailroom);
230
231 memcpy(&new_base[new_headroom - copy_headroom],
232 &old_base[old_headroom - copy_headroom],
1f317cb5 233 copy_headroom + ofpbuf_size(b) + copy_tailroom);
064af421
BP
234}
235
0dce369b
BP
236/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom'
237 * bytes of headroom and tailroom, respectively. */
1f5cbaa3 238static void
0dce369b 239ofpbuf_resize__(struct ofpbuf *b, size_t new_headroom, size_t new_tailroom)
1f5cbaa3 240{
0dce369b 241 void *new_base, *new_data;
31ac1e59 242 size_t new_allocated;
31ac1e59 243
1f317cb5 244 new_allocated = new_headroom + ofpbuf_size(b) + new_tailroom;
31ac1e59
BP
245
246 switch (b->source) {
20ebd771
PS
247 case OFPBUF_DPDK:
248 OVS_NOT_REACHED();
249
31ac1e59 250 case OFPBUF_MALLOC:
0dce369b 251 if (new_headroom == ofpbuf_headroom(b)) {
1f317cb5 252 new_base = xrealloc(ofpbuf_base(b), new_allocated);
0dce369b
BP
253 } else {
254 new_base = xmalloc(new_allocated);
255 ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
1f317cb5 256 free(ofpbuf_base(b));
0dce369b 257 }
31ac1e59
BP
258 break;
259
260 case OFPBUF_STACK:
428b2edd 261 OVS_NOT_REACHED();
31ac1e59 262
cca408da
BP
263 case OFPBUF_STUB:
264 b->source = OFPBUF_MALLOC;
265 new_base = xmalloc(new_allocated);
266 ofpbuf_copy__(b, new_base, new_headroom, new_tailroom);
267 break;
268
31ac1e59 269 default:
428b2edd 270 OVS_NOT_REACHED();
31ac1e59
BP
271 }
272
273 b->allocated = new_allocated;
1f317cb5 274 ofpbuf_set_base(b, new_base);
0dce369b
BP
275
276 new_data = (char *) new_base + new_headroom;
1f317cb5 277 if (ofpbuf_data(b) != new_data) {
cf3b7538
JR
278 if (b->frame) {
279 uintptr_t data_delta = (char *) new_data - (char *) ofpbuf_data(b);
437d0d22 280
cf3b7538 281 b->frame = (char *) b->frame + data_delta;
0dce369b 282 }
cf3b7538 283 ofpbuf_set_data(b, new_data);
0dce369b 284 }
1f5cbaa3
BP
285}
286
287/* Ensures that 'b' has room for at least 'size' bytes at its tail end,
288 * reallocating and copying its data if necessary. Its headroom, if any, is
289 * preserved. */
290void
d295e8e9 291ofpbuf_prealloc_tailroom(struct ofpbuf *b, size_t size)
1f5cbaa3
BP
292{
293 if (size > ofpbuf_tailroom(b)) {
0dce369b 294 ofpbuf_resize__(b, ofpbuf_headroom(b), MAX(size, 64));
1f5cbaa3
BP
295 }
296}
297
0dce369b
BP
298/* Ensures that 'b' has room for at least 'size' bytes at its head,
299 * reallocating and copying its data if necessary. Its tailroom, if any, is
300 * preserved. */
064af421 301void
d295e8e9 302ofpbuf_prealloc_headroom(struct ofpbuf *b, size_t size)
064af421 303{
0dce369b
BP
304 if (size > ofpbuf_headroom(b)) {
305 ofpbuf_resize__(b, MAX(size, 64), ofpbuf_tailroom(b));
306 }
064af421
BP
307}
308
1f5cbaa3 309/* Trims the size of 'b' to fit its actual content, reducing its tailroom to
31ac1e59
BP
310 * 0. Its headroom, if any, is preserved.
311 *
312 * Buffers not obtained from malloc() are not resized, since that wouldn't save
313 * any memory. */
064af421
BP
314void
315ofpbuf_trim(struct ofpbuf *b)
316{
20ebd771
PS
317 ovs_assert(b->source != OFPBUF_DPDK);
318
0dce369b
BP
319 if (b->source == OFPBUF_MALLOC
320 && (ofpbuf_headroom(b) || ofpbuf_tailroom(b))) {
321 ofpbuf_resize__(b, 0, 0);
064af421
BP
322 }
323}
324
63f2140a
BP
325/* If 'b' is shorter than 'length' bytes, pads its tail out with zeros to that
326 * length. */
327void
328ofpbuf_padto(struct ofpbuf *b, size_t length)
329{
1f317cb5
PS
330 if (ofpbuf_size(b) < length) {
331 ofpbuf_put_zeros(b, length - ofpbuf_size(b));
63f2140a
BP
332 }
333}
334
b2348f6d
BP
335/* Shifts all of the data within the allocated space in 'b' by 'delta' bytes.
336 * For example, a 'delta' of 1 would cause each byte of data to move one byte
337 * forward (from address 'p' to 'p+1'), and a 'delta' of -1 would cause each
338 * byte to move one byte backward (from 'p' to 'p-1'). */
339void
340ofpbuf_shift(struct ofpbuf *b, int delta)
341{
342 ovs_assert(delta > 0 ? delta <= ofpbuf_tailroom(b)
343 : delta < 0 ? -delta <= ofpbuf_headroom(b)
344 : true);
345
346 if (delta != 0) {
1f317cb5
PS
347 char *dst = (char *) ofpbuf_data(b) + delta;
348 memmove(dst, ofpbuf_data(b), ofpbuf_size(b));
349 ofpbuf_set_data(b, dst);
b2348f6d
BP
350 }
351}
352
064af421
BP
353/* Appends 'size' bytes of data to the tail end of 'b', reallocating and
354 * copying its data if necessary. Returns a pointer to the first byte of the
355 * new data, which is left uninitialized. */
356void *
d295e8e9 357ofpbuf_put_uninit(struct ofpbuf *b, size_t size)
064af421
BP
358{
359 void *p;
360 ofpbuf_prealloc_tailroom(b, size);
361 p = ofpbuf_tail(b);
1f317cb5 362 ofpbuf_set_size(b, ofpbuf_size(b) + size);
064af421
BP
363 return p;
364}
365
366/* Appends 'size' zeroed bytes to the tail end of 'b'. Data in 'b' is
367 * reallocated and copied if necessary. Returns a pointer to the first byte of
368 * the data's location in the ofpbuf. */
369void *
370ofpbuf_put_zeros(struct ofpbuf *b, size_t size)
371{
372 void *dst = ofpbuf_put_uninit(b, size);
373 memset(dst, 0, size);
374 return dst;
375}
376
377/* Appends the 'size' bytes of data in 'p' to the tail end of 'b'. Data in 'b'
378 * is reallocated and copied if necessary. Returns a pointer to the first
379 * byte of the data's location in the ofpbuf. */
380void *
d295e8e9 381ofpbuf_put(struct ofpbuf *b, const void *p, size_t size)
064af421
BP
382{
383 void *dst = ofpbuf_put_uninit(b, size);
384 memcpy(dst, p, size);
385 return dst;
386}
387
78090f63
BP
388/* Parses as many pairs of hex digits as possible (possibly separated by
389 * spaces) from the beginning of 's', appending bytes for their values to 'b'.
390 * Returns the first character of 's' that is not the first of a pair of hex
391 * digits. If 'n' is nonnull, stores the number of bytes added to 'b' in
392 * '*n'. */
393char *
394ofpbuf_put_hex(struct ofpbuf *b, const char *s, size_t *n)
395{
1f317cb5 396 size_t initial_size = ofpbuf_size(b);
78090f63
BP
397 for (;;) {
398 uint8_t byte;
399 bool ok;
400
1a8def8e 401 s += strspn(s, " \t\r\n");
78090f63
BP
402 byte = hexits_value(s, 2, &ok);
403 if (!ok) {
404 if (n) {
1f317cb5 405 *n = ofpbuf_size(b) - initial_size;
78090f63 406 }
ebc56baa 407 return CONST_CAST(char *, s);
78090f63
BP
408 }
409
410 ofpbuf_put(b, &byte, 1);
411 s += 2;
412 }
413}
414
064af421
BP
415/* Reserves 'size' bytes of headroom so that they can be later allocated with
416 * ofpbuf_push_uninit() without reallocating the ofpbuf. */
417void
d295e8e9 418ofpbuf_reserve(struct ofpbuf *b, size_t size)
064af421 419{
1f317cb5 420 ovs_assert(!ofpbuf_size(b));
064af421 421 ofpbuf_prealloc_tailroom(b, size);
1f317cb5 422 ofpbuf_set_data(b, (char*)ofpbuf_data(b) + size);
064af421
BP
423}
424
da546e07
JR
425/* Reserves 'size' bytes of headroom so that they can be later allocated with
426 * ofpbuf_push_uninit() without reallocating the ofpbuf. */
427void
428ofpbuf_reserve_with_tailroom(struct ofpbuf *b, size_t headroom,
429 size_t tailroom)
430{
1f317cb5 431 ovs_assert(!ofpbuf_size(b));
da546e07 432 ofpbuf_prealloc_tailroom(b, headroom + tailroom);
1f317cb5 433 ofpbuf_set_data(b, (char*)ofpbuf_data(b) + headroom);
da546e07
JR
434}
435
0dce369b
BP
436/* Prefixes 'size' bytes to the head end of 'b', reallocating and copying its
437 * data if necessary. Returns a pointer to the first byte of the data's
438 * location in the ofpbuf. The new data is left uninitialized. */
064af421 439void *
d295e8e9 440ofpbuf_push_uninit(struct ofpbuf *b, size_t size)
064af421
BP
441{
442 ofpbuf_prealloc_headroom(b, size);
1f317cb5
PS
443 ofpbuf_set_data(b, (char*)ofpbuf_data(b) - size);
444 ofpbuf_set_size(b, ofpbuf_size(b) + size);
445 return ofpbuf_data(b);
064af421
BP
446}
447
0dce369b
BP
448/* Prefixes 'size' zeroed bytes to the head end of 'b', reallocating and
449 * copying its data if necessary. Returns a pointer to the first byte of the
450 * data's location in the ofpbuf. */
30f07f1a
BP
451void *
452ofpbuf_push_zeros(struct ofpbuf *b, size_t size)
453{
454 void *dst = ofpbuf_push_uninit(b, size);
455 memset(dst, 0, size);
456 return dst;
457}
458
0dce369b
BP
459/* Copies the 'size' bytes starting at 'p' to the head end of 'b', reallocating
460 * and copying its data if necessary. Returns a pointer to the first byte of
461 * the data's location in the ofpbuf. */
064af421 462void *
d295e8e9 463ofpbuf_push(struct ofpbuf *b, const void *p, size_t size)
064af421
BP
464{
465 void *dst = ofpbuf_push_uninit(b, size);
466 memcpy(dst, p, size);
467 return dst;
468}
469
933369b1
BP
470/* Returns the data in 'b' as a block of malloc()'d memory and frees the buffer
471 * within 'b'. (If 'b' itself was dynamically allocated, e.g. with
472 * ofpbuf_new(), then it should still be freed with, e.g., ofpbuf_delete().) */
473void *
474ofpbuf_steal_data(struct ofpbuf *b)
475{
476 void *p;
20ebd771
PS
477 ovs_assert(b->source != OFPBUF_DPDK);
478
1f317cb5
PS
479 if (b->source == OFPBUF_MALLOC && ofpbuf_data(b) == ofpbuf_base(b)) {
480 p = ofpbuf_data(b);
933369b1 481 } else {
1f317cb5 482 p = xmemdup(ofpbuf_data(b), ofpbuf_size(b));
933369b1 483 if (b->source == OFPBUF_MALLOC) {
1f317cb5 484 free(ofpbuf_base(b));
933369b1
BP
485 }
486 }
1f317cb5
PS
487 ofpbuf_set_base(b, NULL);
488 ofpbuf_set_data(b, NULL);
933369b1
BP
489 return p;
490}
491
0ab8e15f
BP
492/* Returns a string that describes some of 'b''s metadata plus a hex dump of up
493 * to 'maxbytes' from the start of the buffer. */
494char *
495ofpbuf_to_string(const struct ofpbuf *b, size_t maxbytes)
496{
497 struct ds s;
498
499 ds_init(&s);
437d0d22 500 ds_put_format(&s, "size=%"PRIu32", allocated=%"PRIu32", head=%"PRIuSIZE", tail=%"PRIuSIZE"\n",
1f317cb5 501 ofpbuf_size(b), b->allocated,
0ab8e15f 502 ofpbuf_headroom(b), ofpbuf_tailroom(b));
1f317cb5 503 ds_put_hex_dump(&s, ofpbuf_data(b), MIN(ofpbuf_size(b), maxbytes), 0, false);
0ab8e15f
BP
504 return ds_cstr(&s);
505}
b3907fbc
BP
506
507/* Removes each of the "struct ofpbuf"s on 'list' from the list and frees
508 * them. */
509void
510ofpbuf_list_delete(struct list *list)
511{
512 struct ofpbuf *b, *next;
513
514 LIST_FOR_EACH_SAFE (b, next, list_node, list) {
515 list_remove(&b->list_node);
516 ofpbuf_delete(b);
517 }
518}
437d0d22
JR
519
520static inline void
521ofpbuf_adjust_layer_offset(uint16_t *offset, int increment)
522{
523 if (*offset != UINT16_MAX) {
524 *offset += increment;
525 }
526}
527
528/* Adjust the size of the l2_5 portion of the ofpbuf, updating the l2
529 * pointer and the layer offsets. The caller is responsible for
530 * modifying the contents. */
531void *
532ofpbuf_resize_l2_5(struct ofpbuf *b, int increment)
533{
534 if (increment >= 0) {
535 ofpbuf_push_uninit(b, increment);
536 } else {
537 ofpbuf_pull(b, -increment);
538 }
539
cf3b7538 540 b->frame = ofpbuf_data(b);
437d0d22
JR
541 /* Adjust layer offsets after l2_5. */
542 ofpbuf_adjust_layer_offset(&b->l3_ofs, increment);
543 ofpbuf_adjust_layer_offset(&b->l4_ofs, increment);
544
cf3b7538 545 return b->frame;
437d0d22
JR
546}
547
548/* Adjust the size of the l2 portion of the ofpbuf, updating the l2
549 * pointer and the layer offsets. The caller is responsible for
550 * modifying the contents. */
551void *
552ofpbuf_resize_l2(struct ofpbuf *b, int increment)
553{
554 ofpbuf_resize_l2_5(b, increment);
555 ofpbuf_adjust_layer_offset(&b->l2_5_ofs, increment);
cf3b7538 556 return b->frame;
437d0d22 557}