From: Bill Fischofer [mailto:bill.fischo...@linaro.org] 
Sent: Tuesday, November 15, 2016 3:03 PM
To: Savolainen, Petri (Nokia - FI/Espoo) <petri.savolai...@nokia-bell-labs.com>
Cc: lng-odp-forward <lng-odp@lists.linaro.org>
Subject: Re: [lng-odp] [API-NEXT PATCH v3 15/19] linux-gen: packet: added 
support for segmented packets



On Tue, Nov 15, 2016 at 6:20 AM, Savolainen, Petri (Nokia - FI/Espoo) 
<petri.savolai...@nokia-bell-labs.com> wrote:


From: Bill Fischofer [mailto:bill.fischo...@linaro.org]
Sent: Monday, November 14, 2016 3:37 AM
To: Savolainen, Petri (Nokia - FI/Espoo) <petri.savolai...@nokia-bell-labs.com>
Cc: lng-odp-forward <lng-odp@lists.linaro.org>
Subject: Re: [lng-odp] [API-NEXT PATCH v3 15/19] linux-gen: packet: added 
support for segmented packets



On Thu, Nov 10, 2016 at 5:07 AM, Petri Savolainen <petri.savolai...@nokia.com> 
wrote:
Added support for multi-segmented packets. The first segments
is the packet descriptor, which contains all metadata and
pointers to other segments.

Signed-off-by: Petri Savolainen <petri.savolai...@nokia.com>
---
 .../include/odp/api/plat/packet_types.h            |   6 +-
 .../linux-generic/include/odp_buffer_inlines.h     |  11 -
 .../linux-generic/include/odp_buffer_internal.h    |  23 +-
 .../linux-generic/include/odp_config_internal.h    |  39 +-
 .../linux-generic/include/odp_packet_internal.h    |  80 +--
 platform/linux-generic/include/odp_pool_internal.h |   3 -
 platform/linux-generic/odp_buffer.c                |   8 +-
 platform/linux-generic/odp_crypto.c                |   8 +-
 platform/linux-generic/odp_packet.c                | 712 +++++++++++++++++----
 platform/linux-generic/odp_pool.c                  | 123 ++--
 platform/linux-generic/pktio/netmap.c              |   4 +-
 platform/linux-generic/pktio/socket.c              |   3 +-
 12 files changed, 692 insertions(+), 328 deletions(-)




diff --git a/platform/linux-generic/odp_packet.c 
b/platform/linux-generic/odp_packet.c
index 2eee775..a5c6ff4 100644
--- a/platform/linux-generic/odp_packet.c
+++ b/platform/linux-generic/odp_packet.c
@@ -20,12 +20,155 @@
 #include <stdio.h>
 #include <inttypes.h>

-/*
- *
- * Alloc and free
- * ********************************************************
- *
- */
+static inline odp_packet_t packet_handle(odp_packet_hdr_t *pkt_hdr)
+{
+       return (odp_packet_t)pkt_hdr->buf_hdr.handle.handle;
+}
+
+static inline odp_buffer_t buffer_handle(odp_packet_hdr_t *pkt_hdr)
+{
+       return pkt_hdr->buf_hdr.handle.handle;
+}
+
+static inline uint32_t packet_seg_len(odp_packet_hdr_t *pkt_hdr,
+                                     uint32_t seg_idx)
+{
+       return pkt_hdr->buf_hdr.seg[seg_idx].len;
+}
+
+static inline void *packet_seg_data(odp_packet_hdr_t *pkt_hdr, uint32_t 
seg_idx)

This is more usefully typed as returning uint8_t * rather than void * to permit 
easy arithmetic on the result. The uint8_t * converts automatically to void * 
returns for the external API calls that use this.

<reply to HTML mail>

This is actually the only place packet_seg_data() is called. The API function 
returns (void *), so the inline function fits that.

void *odp_packet_seg_data(odp_packet_t pkt, odp_packet_seg_t seg)
{
        odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);

        if (odp_unlikely(seg >= pkt_hdr->buf_hdr.segcount))
                return NULL;

        return packet_seg_data(pkt_hdr, seg);
}

Also (void *) can be assigned to any pointer type without cast. For example:

uint8_t *data;
data = packet_seg_data(pkt_hdr, seg);


So, I think there's no benefit to change.

</reply to HTML mail>

I do use this function in the packet reference extensions, and need to perform 
arithmetic on the return, which is why having it return uint8_t * rather than 
void * is more useful. I can include this change as part of my patch series if 
you don't want to make it part of this base patch.
 
<2nd reply to HTML mail>

It's better to change it on a future patch that actually needs the change.

</2nd reply to HTML mail>




+{
+       return pkt_hdr->buf_hdr.seg[seg_idx].data;
+}
+
+static inline int packet_last_seg(odp_packet_hdr_t *pkt_hdr)
+{
+       if (CONFIG_PACKET_MAX_SEGS == 1)
+               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 packet_seg_len(pkt_hdr, 0);
+}
+
+static inline uint32_t packet_last_seg_len(odp_packet_hdr_t *pkt_hdr)
+{
+       int last = packet_last_seg(pkt_hdr);
+
+       return packet_seg_len(pkt_hdr, last);
+}
+
+static inline void *packet_data(odp_packet_hdr_t *pkt_hdr)
+{
+       return pkt_hdr->buf_hdr.seg[0].data;


Given the earlier definition of the packet_seg_data helper this would more 
consistently be:

        return packet_seg_data(pkt_hdr, 0);
 

<reply to HTML mail>

There's no need to change the return type of packet_seg_data() to be able to 
use it here.

Anyway, I decided not to hide buf_hdr.seg[0].data reads behind a function call, 
since this way it's easy to find all reads and *writes* of it throughout the 
file.

</reply to HTML mail>


Then I'd question why have this function at all if the intent is not to help 
hide the particulars of the seg structure contained in the buf_hdr? I thought 
this was a useful abstraction so it's use as an internal API should be 
encouraged.
 
<2nd reply to HTML mail>

I didn't end up using it due to the reason above. It's internal to the file and 
used only once, so I could remove it. Do you want it to be removed ?

</2nd reply to HTML mail>


+}
+
+static inline void *packet_tail(odp_packet_hdr_t *pkt_hdr)
+{
+       int last = packet_last_seg(pkt_hdr);
+       uint32_t seg_len = pkt_hdr->buf_hdr.seg[last].len;
+
+       return pkt_hdr->buf_hdr.seg[last].data + seg_len;
+}
+
+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;
+}




 int odp_packet_num_segs(odp_packet_t pkt)
 {
-       return odp_packet_hdr(pkt)->buf_hdr.segcount;
+       odp_packet_hdr_t *pkt_hdr = odp_packet_hdr(pkt);
+
+       return pkt_hdr->buf_hdr.segcount;
 }

 odp_packet_seg_t odp_packet_first_seg(odp_packet_t pkt)
 {
-       return (odp_packet_seg_t)pkt;
+       (void)pkt;
+
+       return 0;
 }

This should be written as:

odp_packet_seg_t odp_packet_first_seg(odp_packet_t pkt ODP_UNUSED)
{
        return 0;
}
 

<reply to HTML mail>

This is mostly matter of taste. We use cast to (void) in many places already. 
Also (void) is part of C language (I believe), whereas ODP_UNUSED rely on an 
__attribute__ that all compilers might not implement (on function prototype at 
least). So, actually  (void) seems to me more portable than ODP_UNUSED.

Maybe API definition of ODP_UNUSED should be changed to ODP_UNUSED(x), which 
would not be defined on function prototype but on function body and would be 
implemented like this,

#define ODP_UNUSED(x) (void)(x)

</reply to HTML mail>

These discussions were held and settled quite some time ago, which is why we 
defined the ODP_UNUSED idiom. Since we have a well-defined and established 
mechanism for handling unused parameters, we should use it consistently.

<2nd reply to HTML mail>

Actually, the definition of '#define ODP_UNUSED(x) (void)(x)' implementation 
was never discussed. We just wrapped "__attribute__((__unused__))" of GCC. 
That's why I'm questioning it here now. What if your compiler X checks for 
unused params but does not support the same or similar attribute *inside* 
function prototype ?

We could also remove ODP_UNUSED from the API if cast to (void) is a valid C 
language feature.

Anyway, for this series I'll send a v4 with ODP_UNUSED.

</2nd reply to HTML mail>


-Petri

Reply via email to