From: Bill Fischofer <bill.fischo...@linaro.org>

Signed-off-by: Bill Fischofer <bill.fischo...@linaro.org>
---
/** Email created from pull request 82 (Bill-Fischofer-Linaro:pktrefs)
 ** https://github.com/Linaro/odp/pull/82
 ** Patch: https://github.com/Linaro/odp/pull/82.patch
 ** Base sha: 95ba4b394009d92c29c2e22f0776e90bb4c6edec
 ** Merge commit sha: 73cef9023221f7c5bc93e67cb57a9d07e8f1a113
 **/
 platform/linux-generic/odp_packet.c | 172 +++++++++++++++++++++---------------
 1 file changed, 103 insertions(+), 69 deletions(-)

diff --git a/platform/linux-generic/odp_packet.c 
b/platform/linux-generic/odp_packet.c
index a5abf1ba..35a8c645 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -1710,6 +1710,109 @@ int odp_packet_split(odp_packet_t *pkt, uint32_t len, 
odp_packet_t *tail)
 }
 
 /*
+ * References
+ */
+
+static inline void packet_ref(odp_packet_hdr_t *pkt_hdr)
+{
+       uint32_t i;
+       odp_packet_hdr_t *hdr;
+
+       do {
+               for (i = 0; i < pkt_hdr->buf_hdr.segcount; i++) {
+                       hdr = pkt_hdr->buf_hdr.seg[i].hdr;
+                       packet_ref_inc(hdr);
+               }
+
+               pkt_hdr = pkt_hdr->ref_hdr;
+       } while (pkt_hdr);
+}
+
+static inline odp_packet_t packet_splice(odp_packet_hdr_t *pkt_hdr,
+                                        uint32_t offset,
+                                        odp_packet_hdr_t *ref_hdr)
+{
+       /* Catch attempted references to stale handles in debug builds */
+       ODP_ASSERT(packet_ref_count(pkt_hdr) > 0);
+
+       /* Splicing is from the last section of src pkt */
+       while (ref_hdr->ref_hdr)
+               ref_hdr = ref_hdr->ref_hdr;
+
+       /* Find section where splice begins */
+       while (offset >= pkt_hdr->frame_len && pkt_hdr->ref_hdr) {
+               offset   -= (pkt_hdr->frame_len - pkt_hdr->ref_offset);
+               offset   += (pkt_hdr->ref_hdr->frame_len - pkt_hdr->ref_len);
+               pkt_hdr   = pkt_hdr->ref_hdr;
+       }
+
+       ref_hdr->ref_hdr    = pkt_hdr;
+       ref_hdr->ref_offset = offset;
+       ref_hdr->ref_len    = pkt_hdr->frame_len;
+
+       if (packet_ref_count(pkt_hdr) == 1 || offset < pkt_hdr->unshared_len)
+               pkt_hdr->unshared_len = offset;
+
+       packet_ref(pkt_hdr);
+       return packet_handle(ref_hdr);
+}
+
+odp_packet_t odp_packet_ref_static(odp_packet_t pkt)
+{
+       odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
+
+       packet_ref(pkt_hdr);
+       pkt_hdr->unshared_len = 0;
+       return pkt;
+}
+
+odp_packet_t odp_packet_ref(odp_packet_t pkt, uint32_t offset)
+{
+       odp_packet_t hdr;
+       odp_packet_hdr_t *pkt_hdr;
+
+       if (pkt == ODP_PACKET_INVALID)
+               return ODP_PACKET_INVALID;
+
+       pkt_hdr = packet_hdr(pkt);
+       if (offset >= packet_len(pkt_hdr))
+               return ODP_PACKET_INVALID;
+
+       hdr = odp_packet_alloc(odp_packet_pool(pkt), 0);
+
+       if (hdr == ODP_PACKET_INVALID)
+               return ODP_PACKET_INVALID;
+
+       return packet_splice(pkt_hdr, offset, packet_hdr(hdr));
+}
+
+odp_packet_t odp_packet_ref_pkt(odp_packet_t pkt, uint32_t offset,
+                               odp_packet_t hdr)
+{
+       odp_packet_hdr_t *pkt_hdr;
+
+       if (pkt == ODP_PACKET_INVALID ||
+           hdr == ODP_PACKET_INVALID ||
+           pkt == hdr)
+               return ODP_PACKET_INVALID;
+
+       ODP_ASSERT(odp_packet_has_ref(hdr) == 0);
+
+       pkt_hdr = packet_hdr(pkt);
+       if (offset >= packet_len(pkt_hdr))
+               return ODP_PACKET_INVALID;
+
+       return packet_splice(pkt_hdr, offset, packet_hdr(hdr));
+}
+
+int odp_packet_has_ref(odp_packet_t pkt)
+{
+       odp_packet_hdr_t *pkt_hdr = packet_hdr(pkt);
+
+       return pkt_hdr->ref_hdr != NULL || packet_ref_count(pkt_hdr) > 1;
+}
+
+/*
  *
  * Copy
  * ********************************************************
@@ -2353,75 +2456,6 @@ uint64_t odp_packet_seg_to_u64(odp_packet_seg_t hdl)
        return _odp_pri(hdl);
 }
 
-odp_packet_t odp_packet_ref_static(odp_packet_t pkt)
-{
-       return odp_packet_copy(pkt, odp_packet_pool(pkt));
-}
-
-odp_packet_t odp_packet_ref(odp_packet_t pkt, uint32_t offset)
-{
-       odp_packet_t new;
-       int ret;
-
-       new = odp_packet_copy(pkt, odp_packet_pool(pkt));
-
-       if (new == ODP_PACKET_INVALID) {
-               ODP_ERR("copy failed\n");
-               return ODP_PACKET_INVALID;
-       }
-
-       ret = odp_packet_trunc_head(&new, offset, NULL, NULL);
-
-       if (ret < 0) {
-               ODP_ERR("trunk_head failed\n");
-               odp_packet_free(new);
-               return ODP_PACKET_INVALID;
-       }
-
-       return new;
-}
-
-odp_packet_t odp_packet_ref_pkt(odp_packet_t pkt, uint32_t offset,
-                               odp_packet_t hdr)
-{
-       odp_packet_t new;
-       int ret;
-
-       new = odp_packet_copy(pkt, odp_packet_pool(pkt));
-
-       if (new == ODP_PACKET_INVALID) {
-               ODP_ERR("copy failed\n");
-               return ODP_PACKET_INVALID;
-       }
-
-       if (offset) {
-               ret = odp_packet_trunc_head(&new, offset, NULL, NULL);
-
-               if (ret < 0) {
-                       ODP_ERR("trunk_head failed\n");
-                       odp_packet_free(new);
-                       return ODP_PACKET_INVALID;
-               }
-       }
-
-       ret = odp_packet_concat(&hdr, new);
-
-       if (ret < 0) {
-               ODP_ERR("concat failed\n");
-               odp_packet_free(new);
-               return ODP_PACKET_INVALID;
-       }
-
-       return hdr;
-}
-
-int odp_packet_has_ref(odp_packet_t pkt)
-{
-       (void)pkt;
-
-       return 0;
-}
-
 /* Include non-inlined versions of API functions */
 #if ODP_ABI_COMPAT == 1
 #include <odp/api/plat/packet_inlines_api.h>

Reply via email to