From: Brian Brooks <brian.bro...@arm.com> Use a single pointer to next segment instead of an array of pointers. This reduces buffer metadata by ~140 bytes.
Signed-off-by: Brian Brooks <brian.bro...@arm.com> Signed-off-by: Honnappa Nagarahalli <honnappa.nagaraha...@arm.com> --- /** Email created from pull request 354 (brbrooks:caterpillar) ** https://github.com/Linaro/odp/pull/354 ** Patch: https://github.com/Linaro/odp/pull/354.patch ** Base sha: 4d17f8ae64aba0e6f24877be30f86ae5880cef7e ** Merge commit sha: 223d05c5b9ecf4986ec07a833a2630eafbbc3a4d **/ platform/linux-generic/buffer/generic.c | 4 +- .../linux-generic/include/odp_buffer_internal.h | 20 +- .../linux-generic/include/odp_packet_internal.h | 91 +- platform/linux-generic/odp_packet.c | 1452 ++++++-------------- platform/linux-generic/pktio/dpdk.c | 8 +- platform/linux-generic/pktio/ipc.c | 2 +- platform/linux-generic/pool/generic.c | 25 +- test/validation/api/packet/packet.c | 2 +- 8 files changed, 500 insertions(+), 1104 deletions(-) diff --git a/platform/linux-generic/buffer/generic.c b/platform/linux-generic/buffer/generic.c index cf99407cc..4406a10e9 100644 --- a/platform/linux-generic/buffer/generic.c +++ b/platform/linux-generic/buffer/generic.c @@ -31,7 +31,7 @@ static void *generic_buffer_addr(odp_buffer_t buf) { odp_buffer_hdr_t *hdr = buf_hdl_to_hdr(buf); - return hdr->seg[0].data; + return hdr->base_data; } static uint32_t generic_buffer_size(odp_buffer_t buf) @@ -61,7 +61,7 @@ int odp_buffer_snprint(char *str, uint32_t n, odp_buffer_t buf) " pool %" PRIu64 "\n", odp_pool_to_u64(pool->pool_hdl)); len += snprintf(&str[len], n - len, - " addr %p\n", hdr->seg[0].data); + " addr %p\n", hdr->base_data); len += snprintf(&str[len], n - len, " size %" PRIu32 "\n", hdr->size); len += snprintf(&str[len], n - len, diff --git a/platform/linux-generic/include/odp_buffer_internal.h b/platform/linux-generic/include/odp_buffer_internal.h index 514e24798..2fd00c694 100644 --- a/platform/linux-generic/include/odp_buffer_internal.h +++ b/platform/linux-generic/include/odp_buffer_internal.h @@ -35,12 +35,6 @@ extern "C" { #define BUFFER_BURST_SIZE CONFIG_BURST_SIZE -typedef struct seg_entry_t { - void *hdr; - uint8_t *data; - uint32_t len; -} seg_entry_t; - /* Common buffer header */ struct odp_buffer_hdr_t { @@ -53,26 +47,18 @@ struct odp_buffer_hdr_t { /* Pool type */ int8_t type; - /* Number of seg[] entries used */ - uint8_t num_seg; + /* Offset used to restore base_data */ + uint8_t pristine_offset; /* Next header which continues the segment list */ void *next_seg; - /* Last header of the segment list */ - void *last_seg; - - /* Initial buffer data pointer */ + /* Pointer to start of segment */ uint8_t *base_data; /* Pool pointer */ void *pool_ptr; - /* --- 40 bytes --- */ - - /* Segments */ - seg_entry_t seg[CONFIG_PACKET_SEGS_PER_HDR]; - #ifndef ODP_SCHEDULE_SCALABLE /* Burst counts */ uint8_t burst_num; diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 98d364a8d..8f381f097 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -20,6 +20,7 @@ extern "C" { #include <odp/api/align.h> #include <odp/api/debug.h> #include <odp_buffer_internal.h> +#include <odp_debug_internal.h> #include <odp_pool_internal.h> #include <odp_buffer_inlines.h> #include <odp/api/packet.h> @@ -159,9 +160,6 @@ typedef struct { uint8_t data[0]; } odp_packet_hdr_t; -/** - * Return the packet header - */ static inline odp_packet_hdr_t *packet_hdr(odp_packet_t pkt) { return (odp_packet_hdr_t *)(uintptr_t)pkt; @@ -182,58 +180,76 @@ static inline odp_packet_t packet_from_buf_hdr(odp_buffer_hdr_t *buf_hdr) return (odp_packet_t)(odp_packet_hdr_t *)buf_hdr; } -static inline seg_entry_t *seg_entry_last(odp_packet_hdr_t *hdr) +static inline odp_packet_hdr_t *packet_last_seg(odp_packet_hdr_t *pkt_hdr) { - odp_packet_hdr_t *last; - uint8_t last_seg; + int segcount = pkt_hdr->buf_hdr.segcount; + + if (odp_unlikely(segcount > 1)) { + while (--segcount) + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + } - last = hdr->buf_hdr.last_seg; - last_seg = last->buf_hdr.num_seg - 1; - return &last->buf_hdr.seg[last_seg]; + ODP_ASSERT(pkt_hdr->buf_hdr.next_seg == NULL); + + return pkt_hdr; } -/** - * Initialize packet - */ static inline void packet_init(odp_packet_hdr_t *pkt_hdr, uint32_t len) { pool_t *pool = pool_entry_from_hdl(pkt_hdr->buf_hdr.pool_hdl); - uint32_t seg_len; - int num = pkt_hdr->buf_hdr.segcount; - - if (odp_likely(CONFIG_PACKET_SEG_DISABLED || num == 1)) { - seg_len = len; - pkt_hdr->buf_hdr.seg[0].len = len; - } else { - seg_entry_t *last; + odp_packet_hdr_t *old_pkt_hdr = pkt_hdr; - seg_len = len - ((num - 1) * pool->seg_len); + pkt_hdr->frame_len = len; - /* Last segment data length */ - last = seg_entry_last(pkt_hdr); - last->len = seg_len; - } + pkt_hdr->headroom = CONFIG_PACKET_HEADROOM; + pkt_hdr->tailroom = CONFIG_PACKET_TAILROOM; + pkt_hdr->input = ODP_PKTIO_INVALID; pkt_hdr->p.input_flags.all = 0; pkt_hdr->p.output_flags.all = 0; pkt_hdr->p.error_flags.all = 0; - pkt_hdr->p.l2_offset = 0; pkt_hdr->p.l3_offset = ODP_PACKET_OFFSET_INVALID; pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; - /* - * Packet headroom is set from the pool's headroom - * Packet tailroom is rounded up to fill the last - * segment occupied by the allocated length. - */ - pkt_hdr->frame_len = len; - pkt_hdr->headroom = CONFIG_PACKET_HEADROOM; - pkt_hdr->tailroom = pool->seg_len - seg_len + CONFIG_PACKET_TAILROOM; - - pkt_hdr->input = ODP_PKTIO_INVALID; pkt_hdr->buf_hdr.event_subtype = ODP_EVENT_PACKET_BASIC; + /* Restore each segment's base_data and size fields */ + while (len > pool->seg_len) { + pkt_hdr->buf_hdr.base_data = + &pkt_hdr->data[pkt_hdr->buf_hdr.pristine_offset]; + pkt_hdr->buf_hdr.size = pool->seg_len; + + len -= pool->seg_len; + + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + } + pkt_hdr->buf_hdr.base_data = + &pkt_hdr->data[pkt_hdr->buf_hdr.pristine_offset]; + pkt_hdr->buf_hdr.size = len; + + old_pkt_hdr->tailroom += pool->seg_len - len; +} + +static inline void packet_init_segs(odp_packet_hdr_t *pkt_hdrs[], int num_seg) +{ + odp_packet_hdr_t *pkt_hdr = pkt_hdrs[0]; + + pkt_hdr->buf_hdr.segcount = num_seg; + + if (odp_unlikely(num_seg > 1)) { + for (int i = 1; i < num_seg; i++) { + pkt_hdr->buf_hdr.next_seg = pkt_hdrs[i]; + pkt_hdr = pkt_hdrs[i]; + } + } + + pkt_hdr->buf_hdr.next_seg = NULL; +} + +static inline uint32_t packet_buf_len(odp_packet_hdr_t *pkt_hdr) +{ + return pkt_hdr->buf_hdr.size + pkt_hdr->headroom + pkt_hdr->tailroom; } static inline void copy_packet_parser_metadata(odp_packet_hdr_t *src_hdr, @@ -253,11 +269,8 @@ static inline void copy_packet_cls_metadata(odp_packet_hdr_t *src_hdr, static inline void pull_tail(odp_packet_hdr_t *pkt_hdr, uint32_t len) { - seg_entry_t *last = seg_entry_last(pkt_hdr); - pkt_hdr->tailroom += len; pkt_hdr->frame_len -= len; - last->len -= len; } static inline uint32_t packet_len(odp_packet_hdr_t *pkt_hdr) diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index e0fc01b29..a9edbb9e1 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -27,8 +27,8 @@ /* Fill in packet header field offsets for inline functions */ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { - .data = offsetof(odp_packet_hdr_t, buf_hdr.seg[0].data), - .seg_len = offsetof(odp_packet_hdr_t, buf_hdr.seg[0].len), + .data = offsetof(odp_packet_hdr_t, buf_hdr.base_data), + .seg_len = offsetof(odp_packet_hdr_t, buf_hdr.size), .frame_len = offsetof(odp_packet_hdr_t, frame_len), .headroom = offsetof(odp_packet_hdr_t, headroom), .tailroom = offsetof(odp_packet_hdr_t, tailroom), @@ -40,275 +40,15 @@ const _odp_packet_inline_offset_t _odp_packet_inline ODP_ALIGNED_CACHE = { .flow_hash = offsetof(odp_packet_hdr_t, flow_hash), .timestamp = offsetof(odp_packet_hdr_t, timestamp), .input_flags = offsetof(odp_packet_hdr_t, p.input_flags) - }; #include <odp/visibility_end.h> -static inline odp_buffer_t buffer_handle(odp_packet_hdr_t *pkt_hdr) -{ - return (odp_buffer_t)pkt_hdr; -} - -static inline odp_packet_hdr_t *buf_to_packet_hdr(odp_buffer_t buf) +static odp_packet_hdr_t *buf_to_packet_hdr(odp_buffer_t buf) { return (odp_packet_hdr_t *)buf_hdl_to_hdr(buf); } -static inline seg_entry_t *seg_entry(odp_packet_hdr_t *hdr, - uint32_t seg_idx) -{ - uint32_t idx = 0; - uint8_t num_seg = hdr->buf_hdr.num_seg; - - while (odp_unlikely(idx + num_seg - 1 < seg_idx)) { - idx += num_seg; - hdr = hdr->buf_hdr.next_seg; - num_seg = hdr->buf_hdr.num_seg; - } - - idx = seg_idx - idx; - - return &hdr->buf_hdr.seg[idx]; -} - -static inline void seg_entry_find_idx(odp_packet_hdr_t **p_hdr, - uint8_t *p_idx, - uint32_t find_idx) -{ - odp_packet_hdr_t *hdr = *p_hdr; - uint32_t idx = 0; - uint8_t num_seg = hdr->buf_hdr.num_seg; - - while (odp_unlikely(idx + num_seg - 1 < find_idx)) { - idx += num_seg; - hdr = hdr->buf_hdr.next_seg; - num_seg = hdr->buf_hdr.num_seg; - } - - idx = find_idx - idx; - *p_hdr = hdr; - *p_idx = idx; -} - -/* Return pointer to the current segment entry and step cur_hdr / cur_idx - * forward. - */ -static inline seg_entry_t *seg_entry_next(odp_packet_hdr_t **cur_hdr, - uint8_t *cur_idx) -{ - odp_packet_hdr_t *hdr = *cur_hdr; - uint8_t idx = *cur_idx; - uint8_t num_seg = hdr->buf_hdr.num_seg; - - if (idx == num_seg - 1) { - *cur_hdr = hdr->buf_hdr.next_seg; - *cur_idx = 0; - } else { - *cur_idx = idx + 1; - } - - return &hdr->buf_hdr.seg[idx]; -} - -static inline void seg_entry_find_offset(odp_packet_hdr_t **p_hdr, - uint8_t *p_idx, - uint32_t *seg_offset, - uint32_t *seg_idx, - uint32_t offset) -{ - int i; - odp_packet_hdr_t *hdr, *cur_hdr; - uint8_t idx, cur_idx; - seg_entry_t *seg = NULL; - uint32_t seg_start = 0, seg_end = 0; - int seg_count; - - hdr = *p_hdr; - cur_hdr = hdr; - idx = 0; - cur_idx = 0; - seg_count = hdr->buf_hdr.segcount; - - for (i = 0; i < seg_count; i++) { - cur_hdr = hdr; - cur_idx = idx; - seg = seg_entry_next(&hdr, &idx); - seg_end += seg->len; - - if (odp_likely(offset < seg_end)) - break; - - seg_start = seg_end; - } - - *p_hdr = cur_hdr; - *p_idx = cur_idx; - *seg_offset = offset - seg_start; - *seg_idx = i; -} - -static inline uint32_t packet_seg_len(odp_packet_hdr_t *pkt_hdr, - uint32_t seg_idx) -{ - seg_entry_t *seg = seg_entry(pkt_hdr, seg_idx); - - return seg->len; -} - -static inline void *packet_seg_data(odp_packet_hdr_t *pkt_hdr, uint32_t seg_idx) -{ - seg_entry_t *seg = seg_entry(pkt_hdr, seg_idx); - - return seg->data; -} - -static inline uint16_t packet_last_seg(odp_packet_hdr_t *pkt_hdr) -{ - if (CONFIG_PACKET_SEG_DISABLED) - return 0; - else - return pkt_hdr->buf_hdr.segcount - 1; -} - -static inline uint32_t packet_first_seg_len(odp_packet_hdr_t *pkt_hdr) -{ - return pkt_hdr->buf_hdr.seg[0].len; -} - -static inline void *packet_data(odp_packet_hdr_t *pkt_hdr) -{ - return pkt_hdr->buf_hdr.seg[0].data; -} - -static inline void *packet_tail(odp_packet_hdr_t *pkt_hdr) -{ - seg_entry_t *last_seg = seg_entry_last(pkt_hdr); - - return last_seg->data + last_seg->len; -} - -static inline uint32_t seg_headroom(odp_packet_hdr_t *pkt_hdr, int seg_idx) -{ - seg_entry_t *seg = seg_entry(pkt_hdr, seg_idx); - odp_buffer_hdr_t *hdr = seg->hdr; - uint8_t *base = hdr->base_data; - uint8_t *head = seg->data; - - return CONFIG_PACKET_HEADROOM + (head - base); -} - -static inline uint32_t seg_tailroom(odp_packet_hdr_t *pkt_hdr, int seg_idx) -{ - seg_entry_t *seg = seg_entry(pkt_hdr, seg_idx); - - odp_buffer_hdr_t *hdr = seg->hdr; - uint8_t *tail = seg->data + seg->len; - - return hdr->buf_end - tail; -} - -static inline void push_head(odp_packet_hdr_t *pkt_hdr, uint32_t len) -{ - pkt_hdr->headroom -= len; - pkt_hdr->frame_len += len; - pkt_hdr->buf_hdr.seg[0].data -= len; - pkt_hdr->buf_hdr.seg[0].len += len; -} - -static inline void pull_head(odp_packet_hdr_t *pkt_hdr, uint32_t len) -{ - pkt_hdr->headroom += len; - pkt_hdr->frame_len -= len; - pkt_hdr->buf_hdr.seg[0].data += len; - pkt_hdr->buf_hdr.seg[0].len -= len; -} - -static inline void push_tail(odp_packet_hdr_t *pkt_hdr, uint32_t len) -{ - seg_entry_t *last_seg = seg_entry_last(pkt_hdr); - - pkt_hdr->tailroom -= len; - pkt_hdr->frame_len += len; - last_seg->len += len; -} - -/* Copy all metadata for segmentation modification. Segment data and lengths - * are not copied. */ -static inline void packet_seg_copy_md(odp_packet_hdr_t *dst, - odp_packet_hdr_t *src) -{ - dst->p = src->p; - - /* lengths are not copied: - * .frame_len - * .headroom - * .tailroom - */ - - dst->input = src->input; - dst->dst_queue = src->dst_queue; - dst->flow_hash = src->flow_hash; - dst->timestamp = src->timestamp; - - /* buffer header side packet metadata */ - dst->buf_hdr.buf_u64 = src->buf_hdr.buf_u64; - dst->buf_hdr.uarea_addr = src->buf_hdr.uarea_addr; - - /* segmentation data is not copied: - * buf_hdr.seg[] - * buf_hdr.segcount - * buf_hdr.num_seg - * buf_hdr.next_seg - * buf_hdr.last_seg - */ -} - -static inline void *packet_map(odp_packet_hdr_t *pkt_hdr, - uint32_t offset, uint32_t *seg_len, int *seg_idx) -{ - void *addr; - uint32_t len; - int seg_id = 0; - int seg_count = pkt_hdr->buf_hdr.segcount; - - if (odp_unlikely(offset >= pkt_hdr->frame_len)) - return NULL; - - if (odp_likely(CONFIG_PACKET_SEG_DISABLED || seg_count == 1)) { - addr = pkt_hdr->buf_hdr.seg[0].data + offset; - len = pkt_hdr->buf_hdr.seg[0].len - offset; - } else { - int i; - seg_entry_t *seg = NULL; - uint32_t seg_start = 0, seg_end = 0; - odp_packet_hdr_t *hdr = pkt_hdr; - uint8_t idx = 0; - - for (i = 0; i < seg_count; i++) { - seg = seg_entry_next(&hdr, &idx); - seg_end += seg->len; - - if (odp_likely(offset < seg_end)) - break; - - seg_start = seg_end; - } - - addr = seg->data + (offset - seg_start); - len = seg->len - (offset - seg_start); - seg_id = i; - } - - if (seg_len) - *seg_len = len; - - if (seg_idx) - *seg_idx = seg_id; - - return addr; -} - void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) { /* Reset parser metadata before new parse */ @@ -320,103 +60,7 @@ void packet_parse_reset(odp_packet_hdr_t *pkt_hdr) pkt_hdr->p.l4_offset = ODP_PACKET_OFFSET_INVALID; } -static inline void link_segments(odp_packet_hdr_t *pkt_hdr[], int num) -{ - int cur, i; - odp_packet_hdr_t *hdr; - odp_packet_hdr_t *head = pkt_hdr[0]; - uint32_t seg_len = pool_entry_from_hdl(head->buf_hdr.pool_hdl)->seg_len; - - cur = 0; - - while (1) { - hdr = pkt_hdr[cur]; - - for (i = 0; i < CONFIG_PACKET_SEGS_PER_HDR; i++) { - odp_buffer_hdr_t *buf_hdr; - - buf_hdr = &pkt_hdr[cur]->buf_hdr; - hdr->buf_hdr.seg[i].hdr = buf_hdr; - hdr->buf_hdr.seg[i].data = buf_hdr->base_data; - hdr->buf_hdr.seg[i].len = seg_len; - - /* init_segments() handles first seg ref_cnt init */ - if (ODP_DEBUG == 1 && cur > 0) { - uint32_t prev_ref = - odp_atomic_fetch_inc_u32( - &pkt_hdr[cur]->buf_hdr.ref_cnt); - - ODP_ASSERT(prev_ref == 0); - } - - cur++; - - if (cur == num) { - /* Last segment */ - hdr->buf_hdr.num_seg = i + 1; - hdr->buf_hdr.next_seg = NULL; - head->buf_hdr.last_seg = &hdr->buf_hdr; - return; - } - } - - hdr->buf_hdr.num_seg = CONFIG_PACKET_SEGS_PER_HDR; - hdr->buf_hdr.next_seg = pkt_hdr[cur]; - } -} - -static inline void init_segments(odp_packet_hdr_t *pkt_hdr[], int num) -{ - odp_packet_hdr_t *hdr; - uint32_t seg_len; - - /* First segment is the packet descriptor */ - hdr = pkt_hdr[0]; - seg_len = pool_entry_from_hdl(hdr->buf_hdr.pool_hdl)->seg_len; - - /* Defaults for single segment packet */ - hdr->buf_hdr.seg[0].data = hdr->buf_hdr.base_data; - hdr->buf_hdr.seg[0].len = seg_len; - - if (ODP_DEBUG == 1) { - uint32_t prev_ref = - odp_atomic_fetch_inc_u32(&hdr->buf_hdr.ref_cnt); - - ODP_ASSERT(prev_ref == 0); - } - - if (!CONFIG_PACKET_SEG_DISABLED) { - hdr->buf_hdr.segcount = num; - hdr->buf_hdr.num_seg = 1; - hdr->buf_hdr.next_seg = NULL; - hdr->buf_hdr.last_seg = &hdr->buf_hdr; - - /* Link segments */ - if (odp_unlikely(num > 1)) - link_segments(pkt_hdr, num); - } -} - -static inline void reset_seg(odp_packet_hdr_t *pkt_hdr, int first, int num) -{ - odp_packet_hdr_t *hdr = pkt_hdr; - void *base; - int i; - seg_entry_t *seg; - uint32_t seg_len = pool_entry_from_hdl(hdr->buf_hdr.pool_hdl)->seg_len; - uint8_t idx; - - seg_entry_find_idx(&hdr, &idx, first); - - for (i = 0; i < num; i++) { - base = hdr->buf_hdr.base_data; - seg = seg_entry_next(&hdr, &idx); - seg->len = seg_len; - seg->data = base; - } -} - -/* Calculate the number of segments */ +/* Calculate number of segments required for a packet of len 'seg_len' bytes. */ static inline int num_segments(uint32_t len, uint32_t seg_len) { int num; @@ -436,375 +80,255 @@ static inline int num_segments(uint32_t len, uint32_t seg_len) return num; } -static inline void add_all_segs(odp_packet_hdr_t *to, odp_packet_hdr_t *from) +/* Returns a pointer to the Nth (0-based) segment */ +static odp_packet_hdr_t *get_seg(odp_packet_hdr_t *pkt_hdr, uint32_t n) { - odp_packet_hdr_t *last = to->buf_hdr.last_seg; + uint16_t segcount = pkt_hdr->buf_hdr.segcount; + + ODP_ASSERT(n < segcount); + + if (odp_likely(CONFIG_PACKET_MAX_SEGS == 1 || segcount == 1)) + return pkt_hdr; - last->buf_hdr.next_seg = from; - to->buf_hdr.last_seg = from->buf_hdr.last_seg; - to->buf_hdr.segcount += from->buf_hdr.segcount; + while (n--) { + ODP_ASSERT(pkt_hdr->buf_hdr.next_seg); + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + } + + return pkt_hdr; } -static inline odp_packet_hdr_t *alloc_segments(pool_t *pool, int num) +/* + * Returns a pointer to the segment containing byte 'offset' as well as + * the number of segments and bytes skipped to get to the segment. + */ +static odp_packet_hdr_t *get_seg_at_offset(odp_packet_hdr_t *pkt_hdr, + uint32_t offset, + uint32_t *bytes_skipped, + uint32_t *segs_skipped) { - odp_packet_hdr_t *pkt_hdr[num]; - int ret; + uint32_t skipped_bytes = 0; + uint32_t skipped_segs = 0; - ret = buffer_alloc_multi(pool, (odp_buffer_hdr_t **)pkt_hdr, num); + ODP_ASSERT(offset < pkt_hdr->frame_len); - if (odp_unlikely(ret != num)) { - if (ret > 0) - buffer_free_multi((odp_buffer_hdr_t **)pkt_hdr, ret); + if (odp_unlikely(pkt_hdr->buf_hdr.segcount > 1)) { + while (offset >= pkt_hdr->buf_hdr.size) { + skipped_bytes += pkt_hdr->buf_hdr.size; + skipped_segs++; - return NULL; + offset -= pkt_hdr->buf_hdr.size; + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + ODP_ASSERT(pkt_hdr); + } } - init_segments(pkt_hdr, num); + if (bytes_skipped) + *bytes_skipped = skipped_bytes; + if (segs_skipped) + *segs_skipped = skipped_segs; - return pkt_hdr[0]; + return pkt_hdr; } -static inline odp_packet_hdr_t *add_segments(odp_packet_hdr_t *pkt_hdr, - pool_t *pool, uint32_t len, - int num, int head) +/* Link two segment chains together. Adjusts segcounts. */ +static void concat_seg(odp_packet_hdr_t *seg_a, odp_packet_hdr_t *seg_b) { - odp_packet_hdr_t *new_hdr; - uint32_t seg_len, offset; - - new_hdr = alloc_segments(pool, num); - - if (new_hdr == NULL) - return NULL; - - seg_len = len - ((num - 1) * pool->seg_len); - offset = pool->seg_len - seg_len; + odp_packet_hdr_t *seg_a_last = packet_last_seg(seg_a); - if (head) { - /* add into the head*/ - add_all_segs(new_hdr, pkt_hdr); + ODP_ASSERT(seg_a_last->buf_hdr.next_seg == NULL); + seg_a_last->buf_hdr.next_seg = seg_b; - /* adjust first segment length */ - new_hdr->buf_hdr.seg[0].data += offset; - new_hdr->buf_hdr.seg[0].len = seg_len; + ODP_ASSERT(seg_a->buf_hdr.segcount > 0); + ODP_ASSERT(seg_b->buf_hdr.segcount > 0); - packet_seg_copy_md(new_hdr, pkt_hdr); - new_hdr->frame_len = pkt_hdr->frame_len + len; - new_hdr->headroom = pool->headroom + offset; - new_hdr->tailroom = pkt_hdr->tailroom; + seg_a->buf_hdr.segcount += seg_b->buf_hdr.segcount; + seg_b->buf_hdr.segcount = 0; +} - pkt_hdr = new_hdr; - } else { - seg_entry_t *last_seg; +/* + * Returns a pointer to start of packet + 'offset' bytes and stores + * the remaining length of the resulting segment in 'seg_len' and the + * segment index in 'seg_idx'. + */ +static void *packet_map(odp_packet_hdr_t *pkt_hdr, uint32_t offset, + uint32_t *seg_len, int *seg_idx) +{ + uint32_t skipped_segs = 0; - /* add into the tail */ - add_all_segs(pkt_hdr, new_hdr); + if (odp_unlikely(offset >= pkt_hdr->frame_len)) + return NULL; - /* adjust last segment length */ - last_seg = seg_entry_last(pkt_hdr); - last_seg->len = seg_len; + if (odp_unlikely(pkt_hdr->buf_hdr.segcount > 1)) { + while (offset >= pkt_hdr->buf_hdr.size) { + skipped_segs++; - pkt_hdr->frame_len += len; - pkt_hdr->tailroom = pool->tailroom + offset; + offset -= pkt_hdr->buf_hdr.size; + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + } } - return pkt_hdr; -} - -static inline int seg_is_link(void *hdr) -{ - odp_packet_hdr_t *pkt_hdr = hdr; + if (seg_len) + *seg_len = pkt_hdr->buf_hdr.size - offset; + if (seg_idx) + *seg_idx = skipped_segs; - return pkt_hdr != pkt_hdr->buf_hdr.seg[0].hdr; + return pkt_hdr->buf_hdr.base_data + offset; } -static inline void buffer_ref_inc(odp_buffer_hdr_t *buf_hdr) +static void buffer_ref_inc(odp_buffer_hdr_t *buf_hdr) { - uint32_t ref_cnt = odp_atomic_load_u32(&buf_hdr->ref_cnt); - - /* First count increment after alloc */ - if (odp_likely(ref_cnt) == 0) - odp_atomic_store_u32(&buf_hdr->ref_cnt, 2); - else - odp_atomic_inc_u32(&buf_hdr->ref_cnt); + odp_atomic_inc_u32(&buf_hdr->ref_cnt); } -static inline uint32_t buffer_ref_dec(odp_buffer_hdr_t *buf_hdr) +static uint32_t buffer_ref_dec(odp_buffer_hdr_t *buf_hdr) { return odp_atomic_fetch_dec_u32(&buf_hdr->ref_cnt); } -static inline uint32_t buffer_ref(odp_buffer_hdr_t *buf_hdr) +static uint32_t buffer_ref(odp_buffer_hdr_t *buf_hdr) { return odp_atomic_load_u32(&buf_hdr->ref_cnt); } -static inline int is_multi_ref(uint32_t ref_cnt) +static int is_multi_ref(uint32_t ref_cnt) { - return (ref_cnt > 1); + return ref_cnt > 0; } -static inline void packet_ref_inc(odp_packet_hdr_t *pkt_hdr) +static void packet_ref_inc(odp_packet_hdr_t *pkt_hdr) { - seg_entry_t *seg; - int i; - int seg_count = pkt_hdr->buf_hdr.segcount; - odp_packet_hdr_t *hdr = pkt_hdr; - uint8_t idx = 0; - - for (i = 0; i < seg_count; i++) { - seg = seg_entry_next(&hdr, &idx); - buffer_ref_inc(seg->hdr); + while (pkt_hdr) { + buffer_ref_inc(&pkt_hdr->buf_hdr); + pkt_hdr = pkt_hdr->buf_hdr.next_seg; } } -static inline void packet_free_multi(odp_buffer_hdr_t *hdr[], int num) +/* Allocate 'num_pkt' packets of length 'len' bytes */ +static int packet_alloc(pool_t *pool, uint32_t len, int num_pkt, + odp_packet_t *pkts) { - int i; - uint32_t ref_cnt; - int num_ref = 0; + int segs_per_pkt = num_segments(len, pool->seg_len); + int num_buf = num_pkt * segs_per_pkt; + odp_packet_hdr_t *pkt_hdr[num_buf]; + int npkt = num_pkt; + int nbuf; - for (i = 0; i < num; i++) { - /* Zero when reference API has not been used */ - ref_cnt = buffer_ref(hdr[i]); + ODP_ASSERT(segs_per_pkt <= CONFIG_PACKET_MAX_SEGS); - if (odp_unlikely(ref_cnt)) { - ref_cnt = buffer_ref_dec(hdr[i]); + nbuf = buffer_alloc_multi(pool, (odp_buffer_hdr_t **)pkt_hdr, num_buf); - if (is_multi_ref(ref_cnt)) { - num_ref++; - continue; - } - } + /* If we did not get the total number of buffers we asked for, free any + * buffers near the end of the list that cannot be used to make a + * whole packet. */ + if (odp_unlikely(nbuf != num_buf)) { + int nfree; - /* Reset link header back to normal header */ - if (odp_unlikely(seg_is_link(hdr[i]))) - hdr[i]->seg[0].hdr = hdr[i]; + npkt = nbuf / segs_per_pkt; + nfree = nbuf - (npkt * segs_per_pkt); - /* Skip references and pack to be freed headers to array head */ - if (odp_unlikely(num_ref)) - hdr[i - num_ref] = hdr[i]; + if (nfree > 0) { + odp_buffer_hdr_t **p = + (odp_buffer_hdr_t **)&pkt_hdr[nbuf - nfree]; + buffer_free_multi(p, nfree); + } + } + + for (int i = 0; i < npkt; i++) { + packet_init_segs(&pkt_hdr[i * segs_per_pkt], segs_per_pkt); + packet_init(pkt_hdr[i * segs_per_pkt], len); + pkts[i] = (odp_packet_t)pkt_hdr[i * segs_per_pkt]; } - num -= num_ref; + for (int i = 0; i < nbuf; i++) { + ODP_ASSERT(((intptr_t)pkt_hdr[i]->buf_hdr.base_data - + (intptr_t)pkt_hdr[i]) <= + (int)(sizeof(odp_packet_hdr_t) + + pool->headroom + pool->align)); + } - if (odp_likely(num)) - buffer_free_multi(hdr, num); + return npkt; } -static inline void free_all_segments(odp_packet_hdr_t *pkt_hdr, int num) +int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, odp_packet_t pkt[], + int max_num) { - int i; - odp_buffer_hdr_t *buf_hdr[num + 1]; - - if (odp_likely(pkt_hdr->buf_hdr.num_seg == num)) { - for (i = 0; i < num; i++) - buf_hdr[i] = pkt_hdr->buf_hdr.seg[i].hdr; + return packet_alloc(pool_entry_from_hdl(pool_hdl), + len, max_num, pkt); +} - if (odp_unlikely(seg_is_link(pkt_hdr))) { - buf_hdr[num] = &pkt_hdr->buf_hdr; - num++; - } - } else { - seg_entry_t *seg; - odp_buffer_hdr_t *link_hdr[num]; - uint8_t idx = 0; - int links = 0; - - for (i = 0; i < num; i++) { - /* Free also link headers */ - if (odp_unlikely(idx == 0 && seg_is_link(pkt_hdr))) { - link_hdr[links] = &pkt_hdr->buf_hdr; - links++; - } +/* Free 'num' segments starting from segment 'n'. */ +static void packet_free_segs(odp_packet_hdr_t *pkt, uint32_t num, uint32_t n) +{ + odp_packet_hdr_t *pkt_hdr[num]; - seg = seg_entry_next(&pkt_hdr, &idx); - buf_hdr[i] = seg->hdr; - } + ODP_ASSERT(n < pkt->buf_hdr.segcount); + ODP_ASSERT(n + num <= pkt->buf_hdr.segcount); - if (odp_unlikely(links)) - packet_free_multi(link_hdr, links); + pkt = get_seg(pkt, n); + for (unsigned i = 0; i < num; i++) { + pkt_hdr[i] = pkt; + pkt = pkt->buf_hdr.next_seg; } - packet_free_multi(buf_hdr, num); -} - -static inline odp_packet_hdr_t *free_segments(odp_packet_hdr_t *pkt_hdr, - int num, uint32_t free_len, - uint32_t pull_len, int head) -{ - seg_entry_t *seg; - int i; - int num_remain = pkt_hdr->buf_hdr.segcount - num; - odp_packet_hdr_t *hdr = pkt_hdr; - odp_packet_hdr_t *last_hdr = pkt_hdr->buf_hdr.last_seg; - uint8_t idx; - uint8_t num_seg; - odp_buffer_hdr_t *buf_hdr[num]; - odp_buffer_hdr_t *link_hdr[num]; - odp_packet_hdr_t *tmp_hdr; - int links = 0; - - if (head) { - odp_packet_hdr_t *new_hdr; - - idx = 0; - for (i = 0; i < num; i++) { - tmp_hdr = hdr; - seg = seg_entry_next(&hdr, &idx); - buf_hdr[i] = seg->hdr; - - /* Free link headers, if those become empty */ - if (odp_unlikely(idx == 0 && seg_is_link(tmp_hdr))) { - link_hdr[links] = &tmp_hdr->buf_hdr; - links++; - } - } + buffer_free_multi((odp_buffer_hdr_t **)&pkt_hdr, num); +} - /* The first remaining header is the new packet descriptor. - * Copy remaining segments from the last to-be-removed header - * to the new header. */ - new_hdr = hdr->buf_hdr.seg[idx].hdr; - num_seg = hdr->buf_hdr.num_seg - idx; +static void packet_free(odp_packet_hdr_t *pkt_hdr) +{ + int segcount = pkt_hdr->buf_hdr.segcount; + uint32_t ref_cnt; - new_hdr->buf_hdr.next_seg = hdr->buf_hdr.next_seg; + ODP_ASSERT(segcount > 0); - if (hdr == last_hdr) - new_hdr->buf_hdr.last_seg = new_hdr; - else - new_hdr->buf_hdr.last_seg = last_hdr; + if (odp_likely(segcount == 1)) { + ref_cnt = buffer_ref((odp_buffer_hdr_t *)pkt_hdr); - new_hdr->buf_hdr.num_seg = num_seg; - new_hdr->buf_hdr.segcount = num_remain; + if (odp_unlikely(ref_cnt)) { + ref_cnt = buffer_ref_dec((odp_buffer_hdr_t *)pkt_hdr); - for (i = 0; i < num_seg; i++) { - seg = seg_entry_next(&hdr, &idx); - new_hdr->buf_hdr.seg[i] = *seg; + if (is_multi_ref(ref_cnt)) + return; } - packet_seg_copy_md(new_hdr, pkt_hdr); - - /* Tailroom not changed */ - new_hdr->tailroom = pkt_hdr->tailroom; - - /* Link header does not have headroom */ - if (seg_is_link(new_hdr)) - new_hdr->headroom = 0; - else - new_hdr->headroom = seg_headroom(new_hdr, 0); - - new_hdr->frame_len = pkt_hdr->frame_len - free_len; - - pull_head(new_hdr, pull_len); - - pkt_hdr = new_hdr; - - if (odp_unlikely(links)) - packet_free_multi(link_hdr, links); - - packet_free_multi(buf_hdr, num); + buffer_free_multi((odp_buffer_hdr_t **)&pkt_hdr, 1); } else { - /* Free last 'num' bufs. - * First, find the last remaining header. */ - seg_entry_find_idx(&hdr, &idx, num_remain - 1); - last_hdr = hdr; - num_seg = idx + 1; - - seg_entry_next(&hdr, &idx); - - for (i = 0; i < num; i++) { - tmp_hdr = hdr; - seg = seg_entry_next(&hdr, &idx); - buf_hdr[i] = seg->hdr; - - /* Free link headers, if those become empty */ - if (odp_unlikely(idx == 0 && seg_is_link(tmp_hdr))) { - link_hdr[links] = &tmp_hdr->buf_hdr; - links++; - } - } - - if (odp_unlikely(links)) - packet_free_multi(link_hdr, links); - - packet_free_multi(buf_hdr, num); - - /* Head segment remains, no need to copy or update majority - * of the metadata. */ - last_hdr->buf_hdr.num_seg = num_seg; - last_hdr->buf_hdr.next_seg = NULL; - - pkt_hdr->buf_hdr.last_seg = last_hdr; - pkt_hdr->buf_hdr.segcount = num_remain; - pkt_hdr->frame_len -= free_len; - pkt_hdr->tailroom = seg_tailroom(pkt_hdr, num_remain - 1); - - pull_tail(pkt_hdr, pull_len); - } + odp_packet_hdr_t *hdr[segcount]; + int num_ref = 0; - return pkt_hdr; -} - -static inline int packet_alloc(pool_t *pool, uint32_t len, int max_pkt, - int num_seg, odp_packet_t *pkt) -{ - int num_buf, i; - int num = max_pkt; - int max_buf = max_pkt * num_seg; - odp_packet_hdr_t *pkt_hdr[max_buf]; + for (int i = 0; i < segcount; i++) { + ref_cnt = buffer_ref((odp_buffer_hdr_t *)pkt_hdr); - num_buf = buffer_alloc_multi(pool, (odp_buffer_hdr_t **)pkt_hdr, - max_buf); + if (odp_unlikely(ref_cnt)) { + ref_cnt = buffer_ref_dec( + (odp_buffer_hdr_t *)pkt_hdr); - /* Failed to allocate all segments */ - if (odp_unlikely(num_buf != max_buf)) { - int num_free; + if (is_multi_ref(ref_cnt)) { + num_ref++; - num = num_buf / num_seg; - num_free = num_buf - (num * num_seg); + pkt_hdr = pkt_hdr->buf_hdr.next_seg; + continue; + } + } - if (num_free > 0) { - odp_buffer_hdr_t **p; + hdr[i - num_ref] = pkt_hdr; - p = (odp_buffer_hdr_t **)&pkt_hdr[num_buf - num_free]; - buffer_free_multi(p, num_free); + pkt_hdr = pkt_hdr->buf_hdr.next_seg; } + ODP_ASSERT(pkt_hdr == NULL); - if (num == 0) - return 0; - } - - for (i = 0; i < num; i++) { - odp_packet_hdr_t *hdr; - - /* First buffer is the packet descriptor */ - hdr = pkt_hdr[i * num_seg]; - pkt[i] = packet_handle(hdr); - init_segments(&pkt_hdr[i * num_seg], num_seg); - - packet_init(hdr, len); + if (segcount - num_ref) + buffer_free_multi((odp_buffer_hdr_t **)&hdr, + segcount - num_ref); } - - return num; -} - -int packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, - odp_packet_t pkt[], int max_num) -{ - pool_t *pool = pool_entry_from_hdl(pool_hdl); - int num, num_seg; - - num_seg = num_segments(len, pool->seg_len); - num = packet_alloc(pool, len, max_num, num_seg, pkt); - - return num; } odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) { pool_t *pool = pool_entry_from_hdl(pool_hdl); odp_packet_t pkt; - int num, num_seg; + int num; if (odp_unlikely(pool->params.type != ODP_POOL_PACKET)) { __odp_errno = EINVAL; @@ -814,8 +338,7 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) if (odp_unlikely(len > pool->max_len)) return ODP_PACKET_INVALID; - num_seg = num_segments(len, pool->seg_len); - num = packet_alloc(pool, len, 1, num_seg, &pkt); + num = packet_alloc(pool, len, 1, &pkt); if (odp_unlikely(num == 0)) return ODP_PACKET_INVALID; @@ -827,7 +350,6 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, odp_packet_t pkt[], int max_num) { pool_t *pool = pool_entry_from_hdl(pool_hdl); - int num, num_seg; if (odp_unlikely(pool->params.type != ODP_POOL_PACKET)) { __odp_errno = EINVAL; @@ -837,69 +359,18 @@ int odp_packet_alloc_multi(odp_pool_t pool_hdl, uint32_t len, if (odp_unlikely(len > pool->max_len)) return -1; - num_seg = num_segments(len, pool->seg_len); - num = packet_alloc(pool, len, max_num, num_seg, pkt); - - return num; + return packet_alloc(pool, len, max_num, pkt); } void odp_packet_free(odp_packet_t pkt) { - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - int num_seg = pkt_hdr->buf_hdr.segcount; - - ODP_ASSERT(buffer_ref(&pkt_hdr->buf_hdr) > 0); - - if (odp_likely(CONFIG_PACKET_SEG_DISABLED || num_seg == 1)) { - odp_buffer_hdr_t *buf_hdr[2]; - int num = 1; - - buf_hdr[0] = &pkt_hdr->buf_hdr; - - if (odp_unlikely(seg_is_link(pkt_hdr))) { - num = 2; - buf_hdr[1] = pkt_hdr->buf_hdr.seg[0].hdr; - } - - packet_free_multi(buf_hdr, num); - } else { - free_all_segments(pkt_hdr, num_seg); - } + packet_free(packet_hdr(pkt)); } void odp_packet_free_multi(const odp_packet_t pkt[], int num) { - odp_buffer_hdr_t *buf_hdr[num]; - odp_buffer_hdr_t *buf_hdr2[num]; - int i; - int links = 0; - int num_freed = 0; - - for (i = 0; i < num; i++) { - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt[i]); - int num_seg = pkt_hdr->buf_hdr.segcount; - - ODP_ASSERT(buffer_ref(&pkt_hdr->buf_hdr) > 0); - - if (odp_unlikely(num_seg > 1)) { - free_all_segments(pkt_hdr, num_seg); - num_freed++; - continue; - } - - if (odp_unlikely(seg_is_link(pkt_hdr))) { - buf_hdr2[links] = pkt_hdr->buf_hdr.seg[0].hdr; - links++; - } - - buf_hdr[i - num_freed] = &pkt_hdr->buf_hdr; - } - - if (odp_unlikely(links)) - packet_free_multi(buf_hdr2, links); - - if (odp_likely(num - num_freed)) - packet_free_multi(buf_hdr, num - num_freed); + for (int i = 0; i < num; i++) + packet_free(packet_hdr(pkt[i])); } int odp_packet_reset(odp_packet_t pkt, uint32_t len) @@ -911,8 +382,6 @@ int odp_packet_reset(odp_packet_t pkt, uint32_t len) if (odp_unlikely(len > (pool->seg_len * num))) return -1; - reset_seg(pkt_hdr, 0, num); - packet_init(pkt_hdr, len); return 0; @@ -931,28 +400,35 @@ odp_event_t odp_packet_to_event(odp_packet_t pkt) if (odp_unlikely(pkt == ODP_PACKET_INVALID)) return ODP_EVENT_INVALID; - return (odp_event_t)buffer_handle(packet_hdr(pkt)); + return (odp_event_t)packet_hdr(pkt); } -/* - * - * Pointers and lengths - * ******************************************************** - * - */ - uint32_t odp_packet_buf_len(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - return pkt_hdr->buf_hdr.size * pkt_hdr->buf_hdr.segcount; + return packet_buf_len(pkt_hdr) * pkt_hdr->buf_hdr.segcount; } void *odp_packet_tail(odp_packet_t pkt) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + odp_packet_hdr_t *seg = packet_last_seg(pkt_hdr); + + return seg->buf_hdr.buf_end - pkt_hdr->tailroom; +} + +void *odp_packet_offset(odp_packet_t pkt, uint32_t offset, uint32_t *len, + odp_packet_seg_t *seg) +{ + int seg_idx; + void *addr = packet_map( + (odp_packet_hdr_t *)(uintptr_t)pkt, offset, len, &seg_idx); + + if (addr != NULL && seg != NULL) + *seg = _odp_packet_seg_from_ndx(seg_idx); - return packet_tail(pkt_hdr); + return addr; } void *odp_packet_push_head(odp_packet_t pkt, uint32_t len) @@ -962,225 +438,261 @@ void *odp_packet_push_head(odp_packet_t pkt, uint32_t len) if (len > pkt_hdr->headroom) return NULL; - push_head(pkt_hdr, len); - return packet_data(pkt_hdr); + pkt_hdr->buf_hdr.base_data -= len; + pkt_hdr->buf_hdr.size += len; + + pkt_hdr->headroom -= len; + pkt_hdr->frame_len += len; + + return pkt_hdr->buf_hdr.base_data; } -int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, - void **data_ptr, uint32_t *seg_len) +void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len) { - odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt); - uint32_t frame_len = pkt_hdr->frame_len; - uint32_t headroom = pkt_hdr->headroom; - int ret = 0; + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (len > headroom) { - pool_t *pool = pkt_hdr->buf_hdr.pool_ptr; - int num; - void *ptr; + if (len > pkt_hdr->frame_len) + return NULL; - if (odp_unlikely((frame_len + len) > pool->max_len)) - return -1; + pkt_hdr->buf_hdr.base_data += len; + pkt_hdr->buf_hdr.size -= len; - num = num_segments(len - headroom, pool->seg_len); - push_head(pkt_hdr, headroom); - ptr = add_segments(pkt_hdr, pool, len - headroom, num, 1); + pkt_hdr->headroom += len; + pkt_hdr->frame_len -= len; - if (ptr == NULL) { - /* segment alloc failed, rollback changes */ - pull_head(pkt_hdr, headroom); - return -1; - } + return pkt_hdr->buf_hdr.base_data; +} - *pkt = packet_handle(ptr); - pkt_hdr = ptr; - } else { - push_head(pkt_hdr, len); - } +void *odp_packet_push_tail(odp_packet_t pkt, uint32_t len) +{ + odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + odp_packet_hdr_t *seg = packet_last_seg(pkt_hdr); + void *old_tail; - if (data_ptr) - *data_ptr = packet_data(pkt_hdr); + if (len > pkt_hdr->tailroom) + return NULL; - if (seg_len) - *seg_len = packet_first_seg_len(pkt_hdr); + old_tail = seg->buf_hdr.buf_end - pkt_hdr->tailroom; + + seg->buf_hdr.size += len; - return ret; + pkt_hdr->tailroom -= len; + pkt_hdr->frame_len += len; + + return old_tail; } -void *odp_packet_pull_head(odp_packet_t pkt, uint32_t len) +void *odp_packet_pull_tail(odp_packet_t pkt, uint32_t len) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); + odp_packet_hdr_t *seg = packet_last_seg(pkt_hdr); - if (len > pkt_hdr->frame_len) + if (len > seg->buf_hdr.size) return NULL; - pull_head(pkt_hdr, len); - return packet_data(pkt_hdr); + seg->buf_hdr.size -= len; + + pkt_hdr->tailroom += len; + pkt_hdr->frame_len -= len; + + return seg->buf_hdr.buf_end - pkt_hdr->tailroom; } -int odp_packet_trunc_head(odp_packet_t *pkt, uint32_t len, - void **data_ptr, uint32_t *seg_len_out) +/* Copy a subset of metadata fields from one packet to another. */ +static void packet_copy_md(odp_packet_hdr_t *dst, odp_packet_hdr_t *src) +{ + dst->p = src->p; + dst->input = src->input; + dst->dst_queue = src->dst_queue; + dst->flow_hash = src->flow_hash; + dst->timestamp = src->timestamp; + dst->buf_hdr.buf_u64 = src->buf_hdr.buf_u64; + dst->buf_hdr.uarea_addr = src->buf_hdr.uarea_addr; +} + +int odp_packet_extend_head(odp_packet_t *pkt, uint32_t len, + void **data_ptr, uint32_t *seg_len) { odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt); - uint32_t seg_len = packet_first_seg_len(pkt_hdr); + int rv; - if (len > pkt_hdr->frame_len) - return -1; + if (len <= pkt_hdr->headroom) { + if (odp_packet_push_head(*pkt, len) == NULL) + return -1; - if (len < seg_len) { - pull_head(pkt_hdr, len); - } else if (!CONFIG_PACKET_SEG_DISABLED) { - int num = 0; - uint32_t pull_len = 0; + if (data_ptr) + *data_ptr = pkt_hdr->buf_hdr.base_data; + if (seg_len) + *seg_len = pkt_hdr->buf_hdr.size; - while (seg_len <= len) { - pull_len = len - seg_len; - num++; - seg_len += packet_seg_len(pkt_hdr, num); - } + rv = 0; + } else { + pool_t *pool = pkt_hdr->buf_hdr.pool_ptr; + odp_packet_t head; - pkt_hdr = free_segments(pkt_hdr, num, len - pull_len, - pull_len, 1); - *pkt = packet_handle(pkt_hdr); - } + if (odp_unlikely(pkt_hdr->frame_len + len > pool->max_len)) + return -1; - if (data_ptr) - *data_ptr = packet_data(pkt_hdr); + pkt_hdr->frame_len += pkt_hdr->headroom; + pkt_hdr->buf_hdr.base_data -= pkt_hdr->headroom; + pkt_hdr->buf_hdr.size += pkt_hdr->headroom; - if (seg_len_out) - *seg_len_out = packet_first_seg_len(pkt_hdr); + if (packet_alloc(pool, len - pkt_hdr->headroom, 1, &head) != 1) + return -1; - return 0; + concat_seg((odp_packet_hdr_t *)(uintptr_t)head, pkt_hdr); + + packet_hdr(head)->frame_len += pkt_hdr->frame_len; + packet_hdr(head)->tailroom = pkt_hdr->tailroom; + + packet_copy_md(packet_hdr(head), pkt_hdr); + + if (data_ptr) + *data_ptr = packet_hdr(head)->buf_hdr.base_data; + if (seg_len) + *seg_len = packet_hdr(head)->buf_hdr.size; + + *pkt = head; + + rv = 1; + } + return rv; } -void *odp_packet_push_tail(odp_packet_t pkt, uint32_t len) +int odp_packet_trunc_head(odp_packet_t *pkt, uint32_t len, + void **data_ptr, uint32_t *seg_len) { - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - void *old_tail; + odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt); + int rv = -1; - if (len > pkt_hdr->tailroom) - return NULL; + if (len > pkt_hdr->frame_len) + return rv; - ODP_ASSERT(odp_packet_has_ref(pkt) == 0); + if (len < pkt_hdr->buf_hdr.size) { + if (odp_packet_pull_head(*pkt, len) == NULL) + return -1; - old_tail = packet_tail(pkt_hdr); - push_tail(pkt_hdr, len); + if (data_ptr) + *data_ptr = pkt_hdr->buf_hdr.base_data; + if (seg_len) + *seg_len = pkt_hdr->buf_hdr.size; - return old_tail; + rv = 0; + } else { + uint32_t bytes_skipped, segs_skipped; + odp_packet_hdr_t *head = get_seg_at_offset(pkt_hdr, len, + &bytes_skipped, + &segs_skipped); + ODP_ASSERT(bytes_skipped > 0); + ODP_ASSERT(segs_skipped > 0); + + packet_copy_md(head, pkt_hdr); + + head->buf_hdr.segcount = + pkt_hdr->buf_hdr.segcount - segs_skipped; + head->frame_len = pkt_hdr->frame_len - bytes_skipped; + head->headroom = 0; + head->tailroom = pkt_hdr->tailroom; + + packet_free_segs(pkt_hdr, segs_skipped, 0); + + if (odp_packet_pull_head( + (odp_packet_t)head, len - bytes_skipped) == NULL) + return -1; + + if (data_ptr) + *data_ptr = head->buf_hdr.base_data; + if (seg_len) + *seg_len = head->buf_hdr.size; + + *pkt = (odp_packet_t)head; + + rv = 1; + } + return rv; } int odp_packet_extend_tail(odp_packet_t *pkt, uint32_t len, void **data_ptr, uint32_t *seg_len_out) { odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt); - uint32_t frame_len = pkt_hdr->frame_len; - uint32_t tailroom = pkt_hdr->tailroom; - uint32_t tail_off = frame_len; - int ret = 0; - - ODP_ASSERT(odp_packet_has_ref(*pkt) == 0); + uint32_t old_frame_len = pkt_hdr->frame_len; + uint32_t seg_len = 0; + void *offset; - if (len > tailroom) { + if (len <= pkt_hdr->tailroom) { + if (odp_packet_push_tail(*pkt, len) == NULL) + return -1; + } else { pool_t *pool = pkt_hdr->buf_hdr.pool_ptr; - int num; - void *ptr; + odp_packet_hdr_t *seg; + odp_packet_t tail; - if (odp_unlikely((frame_len + len) > pool->max_len)) + if (odp_unlikely(pkt_hdr->frame_len + len > pool->max_len)) return -1; - num = num_segments(len - tailroom, pool->seg_len); - push_tail(pkt_hdr, tailroom); - ptr = add_segments(pkt_hdr, pool, len - tailroom, num, 0); + seg = packet_last_seg(pkt_hdr); + seg->buf_hdr.size += pkt_hdr->tailroom; - if (ptr == NULL) { - /* segment alloc failed, rollback changes */ - pull_tail(pkt_hdr, tailroom); + if (packet_alloc(pool, len - pkt_hdr->tailroom, 1, &tail) != 1) return -1; - } - } else { - push_tail(pkt_hdr, len); - } - - if (data_ptr) - *data_ptr = packet_map(pkt_hdr, tail_off, seg_len_out, NULL); - - return ret; -} -void *odp_packet_pull_tail(odp_packet_t pkt, uint32_t len) -{ - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - seg_entry_t *last_seg = seg_entry_last(pkt_hdr); + concat_seg(pkt_hdr, packet_hdr(tail)); - ODP_ASSERT(odp_packet_has_ref(pkt) == 0); + pkt_hdr->frame_len += len; + pkt_hdr->tailroom = packet_hdr(tail)->tailroom; + } - if (len > last_seg->len) - return NULL; + if (data_ptr || seg_len_out) + offset = packet_map(pkt_hdr, old_frame_len, &seg_len, NULL); - pull_tail(pkt_hdr, len); + if (data_ptr) + *data_ptr = offset; + if (seg_len_out) + *seg_len_out = seg_len; - return packet_tail(pkt_hdr); + return 0; } int odp_packet_trunc_tail(odp_packet_t *pkt, uint32_t len, void **tail_ptr, uint32_t *tailroom) { - int last; - uint32_t seg_len; - seg_entry_t *last_seg; odp_packet_hdr_t *pkt_hdr = packet_hdr(*pkt); + odp_packet_hdr_t *pkt_hdr_last = packet_last_seg(pkt_hdr); - if (len > pkt_hdr->frame_len) - return -1; + if (len <= pkt_hdr_last->buf_hdr.size) { + if (odp_packet_pull_tail(*pkt, len) == NULL) + return -1; + } else { + uint32_t bytes_skipped, segs_skipped; + odp_packet_hdr_t *last; + int last_size; + int num; - ODP_ASSERT(odp_packet_has_ref(*pkt) == 0); + last = get_seg_at_offset(pkt_hdr, pkt_hdr->frame_len - len, + &bytes_skipped, &segs_skipped); - last = packet_last_seg(pkt_hdr); - last_seg = seg_entry_last(pkt_hdr); - seg_len = last_seg->len; + num = pkt_hdr->buf_hdr.segcount - (segs_skipped + 1); + packet_free_segs(pkt_hdr, num, segs_skipped + 1); - if (len < seg_len) { - pull_tail(pkt_hdr, len); - } else if (!CONFIG_PACKET_SEG_DISABLED) { - int num = 0; - uint32_t pull_len = 0; + pkt_hdr->buf_hdr.segcount -= num; + last->buf_hdr.next_seg = NULL; - while (seg_len <= len) { - pull_len = len - seg_len; - num++; - seg_len += packet_seg_len(pkt_hdr, last - num); - } + pkt_hdr->frame_len -= len; - free_segments(pkt_hdr, num, len - pull_len, pull_len, 0); + last_size = pkt_hdr->frame_len - bytes_skipped; + pkt_hdr->tailroom = last->buf_hdr.size - last_size; + last->buf_hdr.size = last_size; } if (tail_ptr) - *tail_ptr = packet_tail(pkt_hdr); - + *tail_ptr = odp_packet_tail(*pkt); if (tailroom) *tailroom = pkt_hdr->tailroom; - return 0; -} - -void *odp_packet_offset(odp_packet_t pkt, uint32_t offset, uint32_t *len, - odp_packet_seg_t *seg) -{ - int seg_idx; - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - void *addr = packet_map(pkt_hdr, offset, len, &seg_idx); - - if (addr != NULL && seg != NULL) - *seg = _odp_packet_seg_from_ndx(seg_idx); - return addr; + return 0; } -/* - * - * Meta-data - * ******************************************************** - * - */ uint32_t odp_packet_user_area_size(odp_packet_t pkt) { pool_t *pool = pool_entry_from_hdl(odp_packet_pool(pkt)); @@ -1294,13 +806,6 @@ void odp_packet_ts_set(odp_packet_t pkt, odp_time_t timestamp) pkt_hdr->p.input_flags.timestamp = 1; } -/* - * - * Segment level - * ******************************************************** - * - */ - void *odp_packet_seg_data(odp_packet_t pkt, odp_packet_seg_t seg) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); @@ -1309,26 +814,21 @@ void *odp_packet_seg_data(odp_packet_t pkt, odp_packet_seg_t seg) pkt_hdr->buf_hdr.segcount)) return NULL; - return packet_seg_data(pkt_hdr, _odp_packet_seg_to_ndx(seg)); + pkt_hdr = get_seg(pkt_hdr, _odp_packet_seg_to_ndx(seg)); + + return pkt_hdr->buf_hdr.base_data; } uint32_t odp_packet_seg_data_len(odp_packet_t pkt, odp_packet_seg_t seg) { odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - if (odp_unlikely(_odp_packet_seg_to_ndx(seg) >= - pkt_hdr->buf_hdr.segcount)) - return 0; + ODP_ASSERT(_odp_packet_seg_to_ndx(seg) < pkt_hdr->buf_hdr.segcount); - return packet_seg_len(pkt_hdr, _odp_packet_seg_to_ndx(seg)); -} + pkt_hdr = get_seg(pkt_hdr, _odp_packet_seg_to_ndx(seg)); -/* - * - * Manipulation - * ******************************************************** - * - */ + return pkt_hdr->buf_hdr.size; +} int odp_packet_add_data(odp_packet_t *pkt_ptr, uint32_t offset, uint32_t len) { @@ -1402,8 +902,6 @@ int odp_packet_align(odp_packet_t *pkt, uint32_t offset, uint32_t len, if (align > ODP_CACHE_LINE_SIZE) return -1; - ODP_ASSERT(odp_packet_has_ref(*pkt) == 0); - if (seglen >= len) { misalign = align <= 1 ? 0 : ROUNDUP_ALIGN(uaddr, align) - uaddr; @@ -1441,8 +939,6 @@ int odp_packet_concat(odp_packet_t *dst, odp_packet_t src) uint32_t dst_len = dst_hdr->frame_len; uint32_t src_len = src_hdr->frame_len; - ODP_ASSERT(odp_packet_has_ref(*dst) == 0); - /* Do a copy if packets are from different pools. */ if (odp_unlikely(dst_pool != src_pool)) { if (odp_packet_extend_tail(dst, src_len, NULL, NULL) >= 0) { @@ -1457,7 +953,7 @@ int odp_packet_concat(odp_packet_t *dst, odp_packet_t src) return -1; } - add_all_segs(dst_hdr, src_hdr); + concat_seg(dst_hdr, src_hdr); dst_hdr->frame_len = dst_len + src_len; dst_hdr->tailroom = src_hdr->tailroom; @@ -1473,8 +969,6 @@ int odp_packet_split(odp_packet_t *pkt, uint32_t len, odp_packet_t *tail) if (len >= pktlen || tail == NULL) return -1; - ODP_ASSERT(odp_packet_has_ref(*pkt) == 0); - *tail = odp_packet_copy_part(*pkt, len, pktlen - len, odp_packet_pool(*pkt)); @@ -1484,13 +978,6 @@ int odp_packet_split(odp_packet_t *pkt, uint32_t len, odp_packet_t *tail) return odp_packet_trunc_tail(pkt, pktlen - len, NULL, NULL); } -/* - * - * Copy - * ******************************************************** - * - */ - odp_packet_t odp_packet_copy(odp_packet_t pkt, odp_pool_t pool) { odp_packet_hdr_t *srchdr = packet_hdr(pkt); @@ -1688,19 +1175,9 @@ int _odp_packet_cmp_data(odp_packet_t pkt, uint32_t offset, return 0; } -/* - * - * Debugging - * ******************************************************** - * - */ void odp_packet_print(odp_packet_t pkt) { - odp_packet_seg_t seg; - seg_entry_t *seg_entry; - odp_packet_hdr_t *seg_hdr; - uint8_t idx; - int max_len = 1024; + int max_len = 2048; char str[max_len]; int len = 0; int n = max_len - 1; @@ -1716,17 +1193,20 @@ void odp_packet_print(odp_packet_t pkt) len += snprintf(&str[len], n - len, " output_flags 0x%" PRIx32 "\n", hdr->p.output_flags.all); + len += snprintf(&str[len], n - len, + " uarea_addr 0x%p\n", + hdr->buf_hdr.uarea_addr); len += snprintf(&str[len], n - len, " l2_offset %" PRIu32 "\n", hdr->p.l2_offset); len += snprintf(&str[len], n - len, " l3_offset %" PRIu32 "\n", hdr->p.l3_offset); len += snprintf(&str[len], n - len, " l4_offset %" PRIu32 "\n", hdr->p.l4_offset); - len += snprintf(&str[len], n - len, - " frame_len %" PRIu32 "\n", hdr->frame_len); len += snprintf(&str[len], n - len, " input %" PRIu64 "\n", odp_pktio_to_u64(hdr->input)); + len += snprintf(&str[len], n - len, + " frame_len %" PRIu32 "\n", hdr->frame_len); len += snprintf(&str[len], n - len, " headroom %" PRIu32 "\n", odp_packet_headroom(pkt)); @@ -1736,37 +1216,23 @@ void odp_packet_print(odp_packet_t pkt) len += snprintf(&str[len], n - len, " num_segs %i\n", odp_packet_num_segs(pkt)); - seg_hdr = hdr; - idx = 0; - seg = odp_packet_first_seg(pkt); - - while (seg != ODP_PACKET_SEG_INVALID) { - odp_buffer_hdr_t *buf_hdr; - odp_packet_hdr_t *tmp_hdr; - - tmp_hdr = seg_hdr; - seg_entry = seg_entry_next(&seg_hdr, &idx); - buf_hdr = seg_entry->hdr; - + do { len += snprintf(&str[len], n - len, - " seg_len %-4" PRIu32 " seg_data %p ", - odp_packet_seg_data_len(pkt, seg), - odp_packet_seg_data(pkt, seg)); - len += snprintf(&str[len], n - len, "ref_cnt %u", - buffer_ref(buf_hdr)); - if (seg_is_link(tmp_hdr)) { - uint32_t ref; - - ref = buffer_ref(&tmp_hdr->buf_hdr); - len += snprintf(&str[len], n - len, "L(%u)\n", ref); - } else { - len += snprintf(&str[len], n - len, "\n"); - } + " %p ref_cnt=%u size=%-5u " + "base_data=%p buf_end=%p next_seg=%p\n", + hdr, + buffer_ref(&hdr->buf_hdr), + hdr->buf_hdr.size, + hdr->buf_hdr.base_data, + hdr->buf_hdr.buf_end, + hdr->buf_hdr.next_seg); - seg = odp_packet_next_seg(pkt, seg); - } + hdr = hdr->buf_hdr.next_seg; + } while (hdr); - ODP_PRINT("%s\n", str); + str[len] = '\0'; + + ODP_PRINT("\n%s\n", str); } void odp_packet_print_data(odp_packet_t pkt, uint32_t offset, @@ -1841,13 +1307,6 @@ int odp_packet_is_valid(odp_packet_t pkt) return 1; } -/* - * - * Internal Use Routines - * ******************************************************** - * - */ - int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt) { odp_packet_hdr_t *srchdr = packet_hdr(srcpkt); @@ -2220,11 +1679,11 @@ int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, odp_pktio_parser_layer_t layer) { - uint32_t seg_len = packet_first_seg_len(pkt_hdr); - void *base = packet_data(pkt_hdr); - - return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, - seg_len, layer); + return packet_parse_common(&pkt_hdr->p, + pkt_hdr->buf_hdr.base_data, + pkt_hdr->frame_len, + pkt_hdr->buf_hdr.size, + layer); } int packet_parse_l3_l4(odp_packet_hdr_t *pkt_hdr, @@ -2264,16 +1723,11 @@ odp_packet_t odp_packet_ref_static(odp_packet_t pkt) odp_packet_t odp_packet_ref(odp_packet_t pkt, uint32_t offset) { - odp_packet_t ref; - odp_packet_hdr_t *link_hdr; - odp_packet_hdr_t *next_hdr; odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - odp_packet_hdr_t *hdr = pkt_hdr; - seg_entry_t *seg; - uint32_t seg_idx = 0; - uint8_t idx = 0; - uint32_t seg_offset = 0; - int i, num_copy, segcount; + odp_packet_hdr_t *seg; + odp_packet_hdr_t *ref_hdr; + odp_packet_t ref; + uint32_t bytes_skipped, segs_skipped; uint32_t len; if (offset >= pkt_hdr->frame_len) { @@ -2281,73 +1735,33 @@ odp_packet_t odp_packet_ref(odp_packet_t pkt, uint32_t offset) return ODP_PACKET_INVALID; } - /* Allocate link segment */ - if (packet_alloc(pkt_hdr->buf_hdr.pool_ptr, 0, 1, 1, &ref) != 1) { + seg = get_seg_at_offset(pkt_hdr, offset, &bytes_skipped, &segs_skipped); + + if (packet_alloc(pkt_hdr->buf_hdr.pool_ptr, 0, 1, &ref) != 1) { ODP_DBG("segment alloc failed\n"); return ODP_PACKET_INVALID; } + ref_hdr = packet_hdr(ref); - link_hdr = packet_hdr(ref); - - seg_entry_find_offset(&hdr, &idx, &seg_offset, &seg_idx, offset); - num_copy = hdr->buf_hdr.num_seg - idx; - segcount = pkt_hdr->buf_hdr.segcount; - - /* In addition to segments, update reference count of - * an existing link header. */ - if (seg_is_link(hdr)) - buffer_ref_inc((odp_buffer_hdr_t *)hdr); - - seg = seg_entry_next(&hdr, &idx); - link_hdr->buf_hdr.num_seg = 1; - link_hdr->buf_hdr.seg[0].hdr = seg->hdr; - link_hdr->buf_hdr.seg[0].data = seg->data + seg_offset; - link_hdr->buf_hdr.seg[0].len = seg->len - seg_offset; - buffer_ref_inc(seg->hdr); - - /* The 'CONFIG_PACKET_SEGS_PER_HDR > 1' condition is required to fix an - * invalid error ('array subscript is above array bounds') thrown by - * gcc (5.4.0). */ - for (i = 1; CONFIG_PACKET_SEGS_PER_HDR > 1 && i < num_copy; i++) { - /* Update link header reference count */ - if (idx == 0 && seg_is_link(hdr)) - buffer_ref_inc((odp_buffer_hdr_t *)hdr); - - seg = seg_entry_next(&hdr, &idx); - - link_hdr->buf_hdr.num_seg++; - link_hdr->buf_hdr.seg[i].hdr = seg->hdr; - link_hdr->buf_hdr.seg[i].data = seg->data; - link_hdr->buf_hdr.seg[i].len = seg->len; - buffer_ref_inc(seg->hdr); - } + len = pkt_hdr->frame_len - offset; - next_hdr = hdr; + ref_hdr->buf_hdr.segcount = + 1 + (pkt_hdr->buf_hdr.segcount - segs_skipped); + ref_hdr->buf_hdr.next_seg = seg; - /* Increment ref count for remaining segments */ - for (i = seg_idx + num_copy; i < segcount; i++) { - /* Update link header reference count */ - if (idx == 0 && seg_is_link(hdr)) - buffer_ref_inc((odp_buffer_hdr_t *)hdr); + ref_hdr->frame_len = len; - seg = seg_entry_next(&hdr, &idx); - buffer_ref_inc(seg->hdr); - } + ref_hdr->tailroom = pkt_hdr->tailroom; + ref_hdr->headroom = 0; - len = pkt_hdr->frame_len - offset; - link_hdr->buf_hdr.next_seg = next_hdr; - link_hdr->buf_hdr.last_seg = pkt_hdr->buf_hdr.last_seg; - link_hdr->buf_hdr.segcount = segcount - seg_idx; - link_hdr->frame_len = len; - link_hdr->tailroom = pkt_hdr->tailroom; + /* Bump refcnt of trailing segments. */ + do { + buffer_ref_inc(&seg->buf_hdr); - /* Link header does not have headroom, it just points to other - * buffers. Zero length headroom ensures that head of the other buffer - * is not pushed through a reference. */ - link_hdr->headroom = 0; + seg = seg->buf_hdr.next_seg; + } while (seg); return ref; - } odp_packet_t odp_packet_ref_pkt(odp_packet_t pkt, uint32_t offset, @@ -2372,26 +1786,20 @@ odp_packet_t odp_packet_ref_pkt(odp_packet_t pkt, uint32_t offset, } return hdr; + } int odp_packet_has_ref(odp_packet_t pkt) { - odp_buffer_hdr_t *buf_hdr; - seg_entry_t *seg; - int i; - uint32_t ref_cnt; - odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt); - int seg_count = pkt_hdr->buf_hdr.segcount; - odp_packet_hdr_t *hdr = pkt_hdr; - uint8_t idx = 0; + odp_packet_hdr_t *pkt_hdr = (odp_packet_hdr_t *)(uintptr_t)pkt; - for (i = 0; i < seg_count; i++) { - seg = seg_entry_next(&hdr, &idx); - buf_hdr = seg->hdr; - ref_cnt = buffer_ref(buf_hdr); + while (pkt_hdr) { + uint32_t ref_cnt = buffer_ref(&pkt_hdr->buf_hdr); if (is_multi_ref(ref_cnt)) return 1; + + pkt_hdr = pkt_hdr->buf_hdr.next_seg; } return 0; diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index bdd12292f..42df14ddd 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -106,8 +106,7 @@ static unsigned cache_size(uint32_t num) static inline uint16_t mbuf_data_off(struct rte_mbuf *mbuf, odp_packet_hdr_t *pkt_hdr) { - return (uint64_t)pkt_hdr->buf_hdr.seg[0].data - - (uint64_t)mbuf->buf_addr; + return (uint64_t)pkt_hdr->buf_hdr.base_data - (uint64_t)mbuf->buf_addr; } /** @@ -122,8 +121,7 @@ static inline void mbuf_update(struct rte_mbuf *mbuf, odp_packet_hdr_t *pkt_hdr, mbuf->pkt_len = pkt_len; mbuf->refcnt = 1; - if (odp_unlikely(pkt_hdr->buf_hdr.base_data != - pkt_hdr->buf_hdr.seg[0].data)) + if (odp_unlikely(pkt_hdr->headroom != CONFIG_PACKET_HEADROOM)) mbuf->data_off = mbuf_data_off(mbuf, pkt_hdr); } @@ -647,7 +645,7 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry, /* Init buffer segments. Currently, only single segment packets * are supported. */ - pkt_hdr->buf_hdr.seg[0].data = data; + pkt_hdr->buf_hdr.base_data = data; packet_init(pkt_hdr, pkt_len); pkt_hdr->input = pktio_entry->s.handle; diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c index 64c7606df..66c3dfad6 100644 --- a/platform/linux-generic/pktio/ipc.c +++ b/platform/linux-generic/pktio/ipc.c @@ -658,7 +658,7 @@ static int ipc_pktio_send_lockless(pktio_entry_t *pktio_entry, offsets[i] = (uint8_t *)pkt_hdr - (uint8_t *)odp_shm_addr(pool->shm); - data_pool_off = (uint8_t *)pkt_hdr->buf_hdr.seg[0].data - + data_pool_off = (uint8_t *)pkt_hdr->buf_hdr.base_data - (uint8_t *)odp_shm_addr(pool->shm); /* compile all function code even if ipc disabled with config */ diff --git a/platform/linux-generic/pool/generic.c b/platform/linux-generic/pool/generic.c index 7a068472c..b16c7380a 100644 --- a/platform/linux-generic/pool/generic.c +++ b/platform/linux-generic/pool/generic.c @@ -207,7 +207,6 @@ static void init_buffers(pool_t *pool) ring_t *ring; uint32_t mask; int type; - uint32_t seg_size; uint64_t page_size; int skipped_blocks = 0; @@ -256,34 +255,26 @@ static void init_buffers(pool_t *pool) memset(buf_hdr, 0, (uintptr_t)data - (uintptr_t)buf_hdr); - seg_size = pool->headroom + pool->seg_len + pool->tailroom; - /* Initialize buffer metadata */ buf_hdr->index = i; - buf_hdr->size = seg_size; + buf_hdr->size = pool->seg_len; buf_hdr->type = type; buf_hdr->event_type = type; buf_hdr->event_subtype = ODP_EVENT_NO_SUBTYPE; buf_hdr->pool_hdl = pool->pool_hdl; buf_hdr->pool_ptr = pool; buf_hdr->uarea_addr = uarea; - /* Show user requested size through API */ - buf_hdr->segcount = 1; - buf_hdr->num_seg = 1; + buf_hdr->segcount = 0; buf_hdr->next_seg = NULL; - buf_hdr->last_seg = buf_hdr; - - /* Pointer to data start (of the first segment) */ - buf_hdr->seg[0].hdr = buf_hdr; - buf_hdr->seg[0].data = &data[offset]; - buf_hdr->seg[0].len = pool->seg_len; odp_atomic_init_u32(&buf_hdr->ref_cnt, 0); - /* Store base values for fast init */ - buf_hdr->base_data = buf_hdr->seg[0].data; - buf_hdr->buf_end = &data[offset + pool->seg_len + - pool->tailroom]; + ODP_ASSERT(offset <= 255); + buf_hdr->pristine_offset = offset; + + buf_hdr->base_data = &data[offset]; + buf_hdr->buf_end = + &data[offset + pool->seg_len + pool->tailroom]; /* Store buffer index into the global pool */ ring_enq(ring, mask, i); diff --git a/test/validation/api/packet/packet.c b/test/validation/api/packet/packet.c index 37550a2f5..6f1d10abf 100644 --- a/test/validation/api/packet/packet.c +++ b/test/validation/api/packet/packet.c @@ -2193,7 +2193,7 @@ void packet_test_ref(void) odp_packet_pool(segmented_test_packet)); CU_ASSERT_FATAL(hdr_pkt[1] != ODP_PACKET_INVALID); hdr_len[1] = odp_packet_len(hdr_pkt[1]); - offset[1] = 5; + offset[1] = 0; hdr_pkt[2] = odp_packet_copy_part(test_packet, 0, odp_packet_len(test_packet) / 4,