Hi,

1. The only segmentation use case is for segmented packet, not for segmented 
buffers.

2. Common case for packets is that everything application needs is in the first 
segment. Odp_packet_t could refer always into that “first segment”, so that 
application (in the common case) would not need to use odp_packet_seg_xxx() 
calls at all – only odp_packet_xxx() calls.

When buffer level features are minimized, the need for 
odp_buffer_xxx(odp_packet_to_buffer(pkt),...) is minimized. All packet 
manipulation should happen through odp_packet_xxx(pkt, …) calls.


-Petri


From: ext Bill Fischofer [mailto:[email protected]]
Sent: Friday, October 17, 2014 1:17 PM
To: Savolainen, Petri (NSN - FI/Espoo)
Cc: ext Jacob, Jerin; [email protected]
Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support API

I'm not sure how to understand these two statements:

1. There's no use case for segmented buffers
2. We should optimize for the common case (with segments)

These seem contradictory.

The use case for segmented buffers is that some platforms have a HW-defined and 
managed segmented buffer model. If we insist that the application be able to 
specify and control packet segment sizes we are making the decision to exclude 
such platforms from supporting ODP.  The optimization suggested is precisely 
what is being proposed here.  By default packets are assumed to be contained in 
implementation-managed segmented buffers and the first segment will be large 
enough to contain all packet headers for non-pathological cases.  The case 
where the application wishes to traverse the entire packet in SW is expected to 
be rare because in the data plane you simply do not have the cycles to do this 
at line rate for all packets.

As for having both odp_buffer_xxx() and odp_packet_xxx() APIs, this is simply 
syntax to avoid the constant need for explicit conversion functions since 
unlike C++, C does not support generic functions.  So you cannot pass an 
odp_packet_t to a function that expects an odp_buffer_t argument without a 
conversion call.  Do we really want to force applications to constantly be 
writing code like:

odp_buffer_xxx(odp_packet_to_buffer(pkt),...)

rather than

odp_packet_xxx(pkt,...)

Not only is this awkward, it is also inefficient.  By having the explicit 
odp_packet_xxx() calls, the implementation is free to optimize these references 
in whatever manner is appropriate to that implementation.  For some this may be 
a simple preprocessor-type expansion while for others there may be more 
sophisticated handling.  But the application should neither know nor care about 
how the implementation chooses to do this.

On Fri, Oct 17, 2014 at 2:27 AM, Savolainen, Petri (NSN - FI/Espoo) 
<[email protected]<mailto:[email protected]>> wrote:
Hi,

This is also my opinion. There’s no use case for segmented buffers in v1.0 - so 
let’s keep it simple and define that buffers (and thus buffer pools) are always 
unsegmented. Segmentation comes into play only with packets (and only with 
those packets that cannot fit into a single buffer). For example, if 
implementation has max buffer size 256, any packets larger than that are 
segmented and segments are handled with packet_seg_xxx calls.

Also, I’d propose that we optimize for the common case (with segments) - so 
that the odp_packet_t handle would refer always to the head of packet segment. 
If the first segment (data/data_len pointed by the odp_packet_t) carries all 
data application is interested in (=protocol headers), the application would 
not have to use the segment API at all. Most applications would not see any 
difference between small/large or segmented/unsegmented packets as long as all 
headers fit into the first segment.

-Petri


From: [email protected]<mailto:[email protected]> 
[mailto:[email protected]<mailto:[email protected]>]
 On Behalf Of ext Jacob, Jerin
Sent: Friday, October 17, 2014 9:34 AM
To: Bill Fischofer
Cc: [email protected]<mailto:[email protected]>
Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support API

The need for segment API infrastructure is very clear.The question is, Do we 
need separate APIs for
segment management at odp_buffer_segment* AND odp_packet_segment* levels ?
as ODP_BUFFER_TYPE_TIMEOUT and ODP_BUFFER_TYPE_RAW will be always unsegmented 
and if there is a
API for odp_packet_segement* then there will be not be any consumer for 
odp_buffer_segment* API for 1.0​



________________________________
From: Bill Fischofer 
<[email protected]<mailto:[email protected]>>
Sent: Thursday, October 16, 2014 9:08 PM
To: Jacob, Jerin
Cc: Ola Liljedahl; Balasubramanian Manoharan; 
[email protected]<mailto:[email protected]>
Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support API

From the buffer design doc (p. 8-9):
Buffer Pool Options

The odp_buffer_opts_e enum is used to specify additional options relating to 
the buffer pool.  Buffer pool options defined are:



•     ODP_BUFFER_OPTS_NONE

•     ODP_BUFFER_OPTS_UNSEGMENTED



These options are additive so an application can simply specify a buf_opts by 
ORing together the options needed.  Note that buffer pool options are 
themselves OPTIONAL and a given implementation MAY fail the buffer pool 
creation request with an appropriate errno if the requested option is not 
supported by the underlying ODP implementation, with the exception that 
UNSEGMENTED pools MUST be supported for non-packet types and for packet types 
as long as the requested size is less than the implementation-defined native 
packet segment size.



Use ODP_BUFFER_OPTS_NONE to specify default buffer pool options with no 
additions.  The ODP_BUFFER_OPTS_UNSEGMENTED option specifies that the buffer 
pool should be unsegmented.


So unsegmented buffer pool support is available.  As far as RAW buffers go, 
again from the doc (p. 14):
ODP_BUFFER_TYPE_RAW
This is the “basic” buffer type which simply consists of a single fixed-sized 
block of contiguous memory.  Buffers of this type do not support user meta data 
and the only built-in meta data supported for this type of buffer are those 
that are statically computable, such as pool and size. This type of buffer is 
entirely under application control and most of the buffer APIs defined in this 
document are not available.  APIs for this type of buffer are described in this 
document.

So RAW buffers are always unsegmented.  The intent is that Packets are by 
default segmented but can be unsegmented while the other buffer types are by 
default unsegmented but (with the exception of RAW buffers) can be made 
segmented.  This is because all buffers start out as a single segment and hence 
are unsegmented until they are expanded to overflow that single segment.

Hope that clarifies things.  Again, this is all very straightforward and only 
comes into play when actually needed.



On Wed, Oct 8, 2014 at 4:03 AM, Jacob, Jerin 
<[email protected]<mailto:[email protected]>> wrote:

If there is no valid use case for supporting segmentation for raw buffers then 
lets drop it. At least it will reduce the effort of

implementing and testing/verification buffer APIs on  different platforms.



________________________________
From: [email protected]<mailto:[email protected]> 
<[email protected]<mailto:[email protected]>> on 
behalf of Ola Liljedahl 
<[email protected]<mailto:[email protected]>>
Sent: Wednesday, October 8, 2014 1:37 PM
To: Balasubramanian Manoharan
Cc: [email protected]<mailto:[email protected]>
Subject: Re: [lng-odp] [ODP/PATCH v1] ODP Buffer Segment Support API

As I wrote in my comment to the architecture discussion yesterday, I am against 
segmentation for buffers. Or at least there must be the possibility to create a 
buffer pool with guaranteed non-segmented buffers. Segmented packets are OK but 
not all usages for buffers relate to packets. A lot of internal usages 
(timeouts, SW messages, internal data structures) will not be able to handle 
segmented buffers so you must be able to force the creation of buffer pools 
with non-segmented buffers.

-- Ola


On 8 October 2014 09:50, Balasubramanian Manoharan 
<[email protected]<mailto:[email protected]>> wrote:
This patch contains ODP Buffer Management missing APIs
The intent of this patch is to port the missing APIs from Buffer Management 
design document into Linux-generic repo.
The dummy functions will be replaced during linux-generic implementation.

Signed-off-by: Balasubramanian Manoharan 
<[email protected]<mailto:[email protected]>>
---
 platform/linux-generic/include/api/odp_buffer.h    | 203 ++++++++++++++++++++-
 .../linux-generic/include/api/odp_buffer_pool.h    |  30 +++
 platform/linux-generic/odp_buffer.c                | 120 ++++++++++++
 platform/linux-generic/odp_buffer_pool.c           |   7 +
 4 files changed, 351 insertions(+), 9 deletions(-)

diff --git a/platform/linux-generic/include/api/odp_buffer.h 
b/platform/linux-generic/include/api/odp_buffer.h
index d8577fd..aeb75ed 100644
--- a/platform/linux-generic/include/api/odp_buffer.h
+++ b/platform/linux-generic/include/api/odp_buffer.h
@@ -28,8 +28,34 @@ extern "C" {
  */
 typedef uint32_t odp_buffer_t;

-#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
+/**
+* ODP buffer segment
+*/
+typedef uint32_t odp_buffer_segment_t;

+/**
+* ODP buffer type
+*/
+typedef enum odp_buffer_type {
+       ODP_BUFFER_TYPE_INVALID = -1,   /**< Buffer type invalid */
+       ODP_BUFFER_TYPE_ANY = 0,        /**< Buffer that can hold any other
+                                       buffer type */
+       ODP_BUFFER_TYPE_RAW = 1,        /**< Raw buffer,
+                                       no additional metadata */
+       ODP_BUFFER_TYPE_PACKET = 2,     /**< Packet buffer */
+       ODP_BUFFER_TYPE_TIMEOUT = 3     /**< Timeout buffer */
+} odp_buffer_type_e;
+
+/**
+* ODP buffer options
+*/
+typedef enum odp_buffer_opts {
+       ODP_BUFFER_OPTS_NONE,
+       ODP_BUFFER_OPTS_UNSEGMENTED
+} odp_buffer_opts_e;
+
+#define ODP_BUFFER_INVALID (0xffffffff) /**< Invalid buffer */
+#define ODP_SEGMENT_INVALID (0xffffffff) /**< Invalid segment */

 /**
  * Buffer start address
@@ -58,14 +84,6 @@ size_t odp_buffer_size(odp_buffer_t buf);
  */
 int odp_buffer_type(odp_buffer_t buf);

-#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
-#define ODP_BUFFER_TYPE_ANY       0  /**< Buffer that can hold any other
-                                         buffer type */
-#define ODP_BUFFER_TYPE_RAW       1  /**< Raw buffer, no additional metadata */
-#define ODP_BUFFER_TYPE_PACKET    2  /**< Packet buffer */
-#define ODP_BUFFER_TYPE_TIMEOUT   3  /**< Timeout buffer */
-
-
 /**
  * Tests if buffer is valid
  *
@@ -76,6 +94,110 @@ int odp_buffer_type(odp_buffer_t buf);
 int odp_buffer_is_valid(odp_buffer_t buf);

 /**
+ * Tests if buffer is segmented
+ *
+ * @param[in]  buf     Buffer handle
+ *
+ * @return             1 if buffer has more than one segment,
+ *                     otherwise 0
+ */
+
+int odp_buffer_is_segmented(odp_buffer_t buf);
+
+/**
+ * Get address and size of user meta data associated with a buffer
+ *
+ * @param[in]  buf             Buffer handle
+ * @param[out] udata_size      Number of bytes of user meta data available
+ *                             at the returned address
+ * @return                     Address of the user meta data for this buffer
+ *                             or NULL if the buffer has no user meta data.
+ */
+void *odp_buffer_udata(odp_buffer_t buf, size_t *udata_size);
+
+/**
+ * Get address of user meta data associated with a buffer
+ *
+ * @param[in]  buf     Buffer handle
+ *
+ * @return             Address of the user meta data for this buffer
+ *                     or NULL if the buffer has no user meta data.
+ */
+void *odp_buffer_udata_addr(odp_buffer_t buf);
+
+/**
+ * Get count of number of segments in a buffer
+ *
+ * @param[in]  buf     Buffer handle
+ *
+ * @return             Count of the number of segments in buf
+ */
+size_t odp_buffer_segment_count(odp_buffer_t buf);
+
+/**
+ * Get the segment identifier for a buffer segment by index
+ *
+ * @param[in]  buf     Buffer handle
+ * @param[in]  ndx     Segment index of segment of interest
+ *
+ * @return             Segment identifier or ODP_SEGMENT_INVALID if the
+ *                     supplied ndx is out of range.
+ */
+odp_buffer_segment_t odp_buffer_segment_by_index(odp_buffer_t buf, size_t ndx);
+
+/**
+ * Get the next segment identifier for a buffer segment
+ *
+ * @param[in]  buf     Buffer handle
+ * @param[in]  seg     Segment identifier of the previous segment
+ *
+ * @return             Segment identifier of the next segment,
+                       or ODP_SEGMENT_INVALID.
+ */
+odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
+                                            odp_buffer_segment_t seg);
+/**
+ * Get start address for a specified buffer segment
+ *
+ * @param[in]  buf     Buffer handle
+ * @param[in]  seg     Segment identifier of the buffer to be addressed
+ * @param[out] seglen  Returned number of bytes in this buffer
+ *                     segment available at returned address
+ *
+ * @return             Segment start address or NULL
+ */
+void *odp_buffer_segment_map(odp_buffer_t buf, odp_buffer_segment_t seg,
+size_t *seglen);
+
+/**
+ *Unmap a buffer segment
+ *
+ * @param[in]  seg     Buffer segment handle
+ */
+void odp_buffer_segment_unmap(odp_buffer_segment_t seg);
+
+/**
+* Get start address for a specified buffer offset
+*
+* @param[in]   buf     Buffer handle
+* @param[in]   offset  Byte offset within the buffer to be addressed
+* @param[out]  seglen  Returned number of bytes in this buffer
+*                      segment available at returned address
+*
+* @return              Offset start address or NULL
+*/
+void *odp_buffer_offset_map(odp_buffer_t buf, size_t offset,
+size_t *seglen);
+
+/**
+ * Unmap a buffer segment by offset
+ *
+ * @param[in]  buf     Buffer handle
+ * @param[in]  offset  Buffer offset
+ */
+void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);
+
+/**
  * Print buffer metadata to STDOUT
  *
  * @param buf      Buffer handle
@@ -83,6 +205,69 @@ int odp_buffer_is_valid(odp_buffer_t buf);
  */
 void odp_buffer_print(odp_buffer_t buf);

+/**
+ * Split a buffer into two buffers at a specified split point
+ *
+ * @param[in]  buf     Handle of buffer to split
+ * @param[in]  offset  Byte offset within buf to split buffer
+ *
+ * @return             Buffer handle of the created split buffer
+ */
+odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset);
+
+/**
+ * Join two buffers into a single buffer
+ *
+ * @param[in]  buf1    Buffer handle of first buffer to join
+ * @param[in]  buf2    Buffer handle of second buffer to join
+ *
+ * @return             Buffer handle of the joined buffer
+ */
+odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t buf2);
+
+/**
+ * Trim a buffer at a specified trim point
+ *
+ * @param[in]  buf     Buffer handle of buffer to trim
+ * @param[in]  offset  byte offset within buf to trim
+ *
+ * @return             Handle of the trimmed buffer or
+ *                     ODP_BUFFER_INVALID if the operation was not performed
+ */
+odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset);
+/**
+ * Extend a buffer for a specified number of bytes
+ *
+ * @param[in]  buf     Buffer handle of buffer to expand
+ * @param[in]  ext     size, in bytes, of the extent to add to the
+ *                     existing buffer.
+ *
+ * @return             Handle of the extended buffer or ODP_BUFFER_INVALID
+ *                     if the operation was not performed
+ */
+odp_buffer_t odp_buffer_extend(odp_buffer_t buf, size_t ext);
+
+/**
+ * Clone a buffer, returning an exact copy of it
+ *
+ * @param[in]  buf     Buffer handle of buffer to duplicate
+ *
+ * @return             Handle of the duplicated buffer or ODP_BUFFER_INVALID
+ *                     if the operation was not performed
+ */
+odp_buffer_t odp_buffer_clone(odp_buffer_t buf);
+
+/**
+ * Copy a buffer, returning an exact copy of it
+ *
+ * @param[in]  buf     Buffer handle of buffer to copy
+ *
+ * @return             Handle of the copied buffer or ODP_BUFFER_INVALID
+ *                     if the operation was not performed
+ */
+odp_buffer_t odp_buffer_copy(odp_buffer_t buf);
+
+

 #ifdef __cplusplus
 }
diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h 
b/platform/linux-generic/include/api/odp_buffer_pool.h
index fe88898..f85d96c 100644
--- a/platform/linux-generic/include/api/odp_buffer_pool.h
+++ b/platform/linux-generic/include/api/odp_buffer_pool.h
@@ -52,6 +52,27 @@ odp_buffer_pool_t odp_buffer_pool_create(const char *name,


 /**
+ * Get the next buffer pool from its predecessor
+ *
+ * @param[in]  pool            Buffer pool handle
+ * @param[out] name            Name of the pool
+ *                             (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
+ * @param[out] udata_size      Size of user meta data used by this pool.
+ * @param[out] buf_num         Number of buffers contained in this pool
+ * @param[out] buf_size        Default size of application data in each buffer
+ * @param[out] buf_type        Buffer type of the pool
+ * @param[out] buf_opts        Buffer options for this pool
+ * @param[out] predef          Predefined (1) or Created (0).
+ *
+ * @return                     Buffer pool handle
+ */
+odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,
+                                      char *name, size_t *udata_size,
+                                      size_t *buf_num, size_t *buf_size,
+                                      enum odp_buffer_type *buf_type,
+                                      enum odp_buffer_opts *buf_opts,
+                                      uint32_t *predef);
+/**
  * Find a buffer pool by name
  *
  * @param name      Name of the pool
@@ -80,6 +101,15 @@ void odp_buffer_pool_print(odp_buffer_pool_t pool);
  */
 odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);

+/**
+* Allocate a buffer from a buffer pool
+*
+* @param[in]   pool    Pool handle
+* @param[in]   size    Size of object to store in buffer
+*
+* @return              Buffer handle or ODP_BUFFER_INVALID
+*/
+odp_buffer_t odp_buffer_alloc_size(odp_buffer_pool_t pool, size_t size);

 /**
  * Buffer free
diff --git a/platform/linux-generic/odp_buffer.c 
b/platform/linux-generic/odp_buffer.c
index e54e0e7..7f4b4f0 100644
--- a/platform/linux-generic/odp_buffer.c
+++ b/platform/linux-generic/odp_buffer.c
@@ -45,6 +45,21 @@ int odp_buffer_is_valid(odp_buffer_t buf)
        return (handle.index != ODP_BUFFER_INVALID_INDEX);
 }

+int odp_buffer_is_segmented(odp_buffer_t buf)
+{
+       odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(buf);
+
+       if (buf_hdr->scatter.num_bufs == 0)
+               return 0;
+       else
+               return 1;
+}
+
+size_t odp_buffer_segment_count(odp_buffer_t buf)
+{
+       odp_buffer_hdr_t *buf_hdr = odp_buf_to_hdr(buf);
+       return (size_t)buf_hdr->scatter.num_bufs + 1;
+}

 int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
 {
@@ -101,8 +116,113 @@ void odp_buffer_print(odp_buffer_t buf)
        printf("\n%s\n", str);
 }

+void *odp_buffer_udata(odp_buffer_t buf, size_t *udata_size)
+{
+       (void)buf;
+       (void)udata_size;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+void *odp_buffer_udata_addr(odp_buffer_t buf)
+{
+       (void)buf;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_segment_t odp_buffer_segment_by_index(odp_buffer_t buf,
+                                                size_t ndx)
+{
+       (void)buf;
+       (void)ndx;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
+                                            odp_buffer_segment_t seg)
+{
+       (void)buf;
+       (void)seg;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+void *odp_buffer_segment_map(odp_buffer_t buf, odp_buffer_segment_t seg,
+                            size_t *seglen)
+{
+       (void)buf;
+       (void)seg;
+       (void)seglen;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+void *odp_buffer_offset_map(odp_buffer_t buf, size_t offset,
+size_t *seglen)
+{
+       (void)buf;
+       (void)offset;
+       (void)seglen;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset)
+{
+       (void)buf;
+       (void)offset;
+       ODP_UNIMPLEMENTED();
+       return;
+}
+
 void odp_buffer_copy_scatter(odp_buffer_t buf_dst, odp_buffer_t buf_src)
 {
        (void)buf_dst;
        (void)buf_src;
 }
+
+odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset)
+{
+       (void)buf;
+       (void)offset;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t buf2)
+{
+       (void)buf1;
+       (void)buf2;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset)
+{
+       (void)buf;
+       (void)offset;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+odp_buffer_t odp_buffer_extend(odp_buffer_t buf, size_t ext)
+{
+       (void)buf;
+       (void)ext;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_t odp_buffer_clone(odp_buffer_t buf)
+{
+       (void)buf;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
+odp_buffer_t odp_buffer_copy(odp_buffer_t buf)
+{
+       (void)buf;
+       ODP_UNIMPLEMENTED();
+       return 0;
+}
+
diff --git a/platform/linux-generic/odp_buffer_pool.c 
b/platform/linux-generic/odp_buffer_pool.c
index a48d7d6..bff4db5 100644
--- a/platform/linux-generic/odp_buffer_pool.c
+++ b/platform/linux-generic/odp_buffer_pool.c
@@ -471,6 +471,13 @@ odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_hdl)
        return handle.u32;
 }

+odp_buffer_t odp_buffer_alloc_size(odp_buffer_pool_t pool, size_t size)
+{
+       (void)pool;
+       (void) size;
+       ODP_ERR("%s function is yet to be implemented", __func__);
+       return 0;
+}

 void odp_buffer_free(odp_buffer_t buf)
 {
--
2.0.1.472.g6f92e5f


_______________________________________________
lng-odp mailing list
[email protected]<mailto:[email protected]>
http://lists.linaro.org/mailman/listinfo/lng-odp


_______________________________________________
lng-odp mailing list
[email protected]<mailto:[email protected]>
http://lists.linaro.org/mailman/listinfo/lng-odp


_______________________________________________
lng-odp mailing list
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to