/* Reserves 'size' bytes of headroom so that they can be later allocated with * dp_packet_push_uninit() without reallocating the dp_packet. */ void dp_packet_reserve(struct dp_packet *b, size_t size) { ovs_assert(!dp_packet_size(b)); dp_packet_prealloc_tailroom(b, size); dp_packet_set_data(b, (char*)dp_packet_data(b) + size); }
/* Prefixes 'size' bytes to the head end of 'b', reallocating and copying its * data if necessary. Returns a pointer to the first byte of the data's * location in the dp_packet. The new data is left uninitialized. */ void * dp_packet_push_uninit(struct dp_packet *b, size_t size) { dp_packet_prealloc_headroom(b, size); dp_packet_set_data(b, (char*)dp_packet_data(b) - size); dp_packet_set_size(b, dp_packet_size(b) + size); return dp_packet_data(b); }
/* Reserves 'headroom' bytes at the head and 'tailroom' at the end so that * they can be later allocated with dp_packet_push_uninit() or * dp_packet_put_uninit() without reallocating the dp_packet. */ void dp_packet_reserve_with_tailroom(struct dp_packet *b, size_t headroom, size_t tailroom) { ovs_assert(!dp_packet_size(b)); dp_packet_prealloc_tailroom(b, headroom + tailroom); dp_packet_set_data(b, (char*)dp_packet_data(b) + headroom); }
static void dp_packet_use__(struct dp_packet *b, void *base, size_t allocated, enum dp_packet_source source) { dp_packet_set_base(b, base); dp_packet_set_data(b, base); dp_packet_set_size(b, 0); dp_packet_init__(b, allocated, source); }
/* Shifts all of the data within the allocated space in 'b' by 'delta' bytes. * For example, a 'delta' of 1 would cause each byte of data to move one byte * forward (from address 'p' to 'p+1'), and a 'delta' of -1 would cause each * byte to move one byte backward (from 'p' to 'p-1'). */ void dp_packet_shift(struct dp_packet *b, int delta) { ovs_assert(delta > 0 ? delta <= dp_packet_tailroom(b) : delta < 0 ? -delta <= dp_packet_headroom(b) : true); if (delta != 0) { char *dst = (char *) dp_packet_data(b) + delta; memmove(dst, dp_packet_data(b), dp_packet_size(b)); dp_packet_set_data(b, dst); } }
/* Reallocates 'b' so that it has exactly 'new_headroom' and 'new_tailroom' * bytes of headroom and tailroom, respectively. */ static void dp_packet_resize__(struct dp_packet *b, size_t new_headroom, size_t new_tailroom) { void *new_base, *new_data; size_t new_allocated; new_allocated = new_headroom + dp_packet_size(b) + new_tailroom; switch (b->source) { case DPBUF_DPDK: OVS_NOT_REACHED(); case DPBUF_MALLOC: if (new_headroom == dp_packet_headroom(b)) { new_base = xrealloc(dp_packet_base(b), new_allocated); } else { new_base = xmalloc(new_allocated); dp_packet_copy__(b, new_base, new_headroom, new_tailroom); free(dp_packet_base(b)); } break; case DPBUF_STACK: OVS_NOT_REACHED(); case DPBUF_STUB: b->source = DPBUF_MALLOC; new_base = xmalloc(new_allocated); dp_packet_copy__(b, new_base, new_headroom, new_tailroom); break; default: OVS_NOT_REACHED(); } b->allocated = new_allocated; dp_packet_set_base(b, new_base); new_data = (char *) new_base + new_headroom; if (dp_packet_data(b) != new_data) { if (b->frame) { uintptr_t data_delta = (char *) new_data - (char *) dp_packet_data(b); b->frame = (char *) b->frame + data_delta; } dp_packet_set_data(b, new_data); } }
/* Returns the data in 'b' as a block of malloc()'d memory and frees the buffer * within 'b'. (If 'b' itself was dynamically allocated, e.g. with * dp_packet_new(), then it should still be freed with, e.g., dp_packet_delete().) */ void * dp_packet_steal_data(struct dp_packet *b) { void *p; ovs_assert(b->source != DPBUF_DPDK); if (b->source == DPBUF_MALLOC && dp_packet_data(b) == dp_packet_base(b)) { p = dp_packet_data(b); } else { p = xmemdup(dp_packet_data(b), dp_packet_size(b)); if (b->source == DPBUF_MALLOC) { free(dp_packet_base(b)); } } dp_packet_set_base(b, NULL); dp_packet_set_data(b, NULL); return p; }