Signed-off-by: Maxim Uvarov <maxim.uva...@linaro.org> --- .../linux-generic/include/odp_buffer_internal.h | 8 ++- .../linux-generic/include/odp_packet_internal.h | 18 ++++++ platform/linux-generic/odp_packet.c | 65 ++++++++++++++++++++-- 3 files changed, 85 insertions(+), 6 deletions(-)
diff --git a/platform/linux-generic/include/odp_buffer_internal.h b/platform/linux-generic/include/odp_buffer_internal.h index 4cacca1..7ab53c6 100644 --- a/platform/linux-generic/include/odp_buffer_internal.h +++ b/platform/linux-generic/include/odp_buffer_internal.h @@ -65,7 +65,11 @@ _ODP_STATIC_ASSERT((ODP_CONFIG_PACKET_BUF_LEN_MAX % #define ODP_BUFFER_POOL_BITS ODP_BITSIZE(ODP_CONFIG_POOLS) #define ODP_BUFFER_SEG_BITS ODP_BITSIZE(ODP_BUFFER_MAX_SEG) -#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS - ODP_BUFFER_SEG_BITS) +#define ODP_PACKET_REFS_BITS ODP_BITSIZE(ODP_CONFIG_PACKET_REFS) + +#define ODP_BUFFER_INDEX_BITS (32 - ODP_BUFFER_POOL_BITS - \ + ODP_BUFFER_SEG_BITS - \ + ODP_PACKET_REFS_BITS) #define ODP_BUFFER_PREFIX_BITS (ODP_BUFFER_POOL_BITS + ODP_BUFFER_INDEX_BITS) #define ODP_BUFFER_MAX_POOLS (1 << ODP_BUFFER_POOL_BITS) #define ODP_BUFFER_MAX_BUFFERS (1 << ODP_BUFFER_INDEX_BITS) @@ -79,6 +83,7 @@ typedef union odp_buffer_bits_t { uint32_t u32; struct { #if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + uint32_t ref:ODP_PACKET_REFS_BITS; uint32_t pool_id:ODP_BUFFER_POOL_BITS; uint32_t index:ODP_BUFFER_INDEX_BITS; uint32_t seg:ODP_BUFFER_SEG_BITS; @@ -86,6 +91,7 @@ typedef union odp_buffer_bits_t { uint32_t seg:ODP_BUFFER_SEG_BITS; uint32_t index:ODP_BUFFER_INDEX_BITS; uint32_t pool_id:ODP_BUFFER_POOL_BITS; + uint32_t ref:ODP_PACKET_REFS_BITS; #endif }; diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index ba2cd7e..2d6b58f 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -272,12 +272,30 @@ odp_packet_t _odp_packet_alloc(odp_pool_t pool_hdl); int _odp_packet_parse(odp_packet_hdr_t *pkt_hdr); +void _odp_packet_init(odp_packet_t pkt); +void _odp_packet_get(odp_packet_t pkt); +uint32_t _odp_packet_put(odp_packet_t pkt); + /* Convert a packet handle to a buffer handle */ odp_buffer_t _odp_packet_to_buffer(odp_packet_t pkt); /* Convert a buffer handle to a packet handle */ odp_packet_t _odp_packet_from_buffer(odp_buffer_t buf); +/* Internal debug function to check if packet has references + * + * @param pkt Packet handle + * @retval 0 Packet does not have references + * @retval 1 Packet has references +*/ +static inline int _odp_packet_refcheck(odp_packet_t pkt) +{ + odp_buffer_t buf = _odp_packet_to_buffer(pkt); + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + return odp_atomic_load_u32(&hdr->ref_count) - 1; +} + #ifdef __cplusplus } #endif diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index 209a6e6..f6c5509 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -28,28 +28,34 @@ odp_packet_t odp_packet_alloc(odp_pool_t pool_hdl, uint32_t len) { pool_entry_t *pool = odp_pool_to_entry(pool_hdl); + odp_packet_t pkt = ODP_PACKET_INVALID; if (pool->s.params.type != ODP_POOL_PACKET) return ODP_PACKET_INVALID; /* Handle special case for zero-length packets */ if (len == 0) { - odp_packet_t pkt = + pkt = (odp_packet_t)buffer_alloc(pool_hdl, pool->s.params.buf.size); - if (pkt != ODP_PACKET_INVALID) + if (pkt != ODP_PACKET_INVALID) { pull_tail(odp_packet_hdr(pkt), pool->s.params.buf.size); - + _odp_packet_init(pkt); + } return pkt; } - return (odp_packet_t)buffer_alloc(pool_hdl, len); + pkt = (odp_packet_t)buffer_alloc(pool_hdl, len); + if (pkt != ODP_PACKET_INVALID) + _odp_packet_init(pkt); + return pkt; } void odp_packet_free(odp_packet_t pkt) { - odp_buffer_free((odp_buffer_t)pkt); + if (!_odp_packet_put(pkt)) + odp_buffer_free((odp_buffer_t)pkt); } int odp_packet_reset(odp_packet_t pkt, uint32_t len) @@ -85,6 +91,46 @@ odp_event_t odp_packet_to_event(odp_packet_t pkt) return (odp_event_t)pkt; } +void _odp_packet_init(odp_packet_t pkt) +{ + odp_buffer_t buf = _odp_packet_to_buffer(pkt); + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + odp_atomic_store_u32(&hdr->ref_count, 1); +} + +void _odp_packet_get(odp_packet_t pkt) +{ + odp_buffer_t buf = _odp_packet_to_buffer(pkt); + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + odp_atomic_inc_u32(&hdr->ref_count); +} + +uint32_t _odp_packet_put(odp_packet_t pkt) +{ + odp_buffer_t buf = _odp_packet_to_buffer(pkt); + odp_buffer_hdr_t *hdr = odp_buf_to_hdr(buf); + + return odp_atomic_fetch_dec_u32(&hdr->ref_count) - 1; +} + +odp_packet_t odp_packet_create_ref(odp_packet_t pkt) +{ + odp_buffer_t buf = _odp_packet_to_buffer(pkt); + odp_buffer_bits_t handle; + + _odp_packet_get(pkt); + + handle.handle = buf; + if (handle.ref > ODP_CONFIG_PACKET_REFS) + ODP_ABORT("Maximum %d refs exceeded.\n", + ODP_CONFIG_PACKET_REFS); + handle.ref += 1; + + return _odp_packet_from_buffer(handle.handle); +} + /* * * Pointers and lengths @@ -472,6 +518,9 @@ odp_packet_t odp_packet_rem_data(odp_packet_t pkt, uint32_t offset, uint32_t pktlen = pkt_hdr->frame_len; odp_packet_t newpkt; + if (_odp_packet_refcheck(pkt)) + ODP_ABORT("modifying with refcounters is prohibited\n"); + if (offset > pktlen || offset + len > pktlen) return ODP_PACKET_INVALID; @@ -577,6 +626,9 @@ int odp_packet_copydata_in(odp_packet_t pkt, uint32_t offset, const uint8_t *srcaddr = (const uint8_t *)src; odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt); + if (_odp_packet_refcheck(pkt)) + ODP_ABORT("modifying with refcounters is prohibited\n"); + if (offset + len > pkt_hdr->frame_len) return -1; @@ -679,6 +731,9 @@ int _odp_packet_copy_to_packet(odp_packet_t srcpkt, uint32_t srcoffset, uint32_t srcseglen = 0; /* GCC */ uint32_t dstseglen = 0; /* GCC */ + if (_odp_packet_refcheck(dstpkt)) + ODP_ABORT("copiyng to packet with refcounters is prohibited\n"); + if (srcoffset + len > srchdr->frame_len || dstoffset + len > dsthdr->frame_len) return -1; -- 1.9.1 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org https://lists.linaro.org/mailman/listinfo/lng-odp