diff mbox

[[RFC] ] RFC for new buffer .h files

Message ID 1414983993-31343-1-git-send-email-bill.fischofer@linaro.org
State New
Headers show

Commit Message

Bill Fischofer Nov. 3, 2014, 3:06 a.m. UTC
RFC version of patches for new buffer .h files.  Includes all API changes from 
buffer design doc + extended notes.  Do not merge until corresponding code
changes are posted.

Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
---
 platform/linux-generic/include/api/odp_buffer.h    | 532 ++++++++++++++++++++-
 .../linux-generic/include/api/odp_buffer_pool.h    | 242 +++++++++-
 2 files changed, 740 insertions(+), 34 deletions(-)

Comments

Gilad Ben-Yossef Nov. 3, 2014, 8:54 a.m. UTC | #1
"ODP_BUFFER_TYPE_RAW<br>
+ * 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"
And odp_buffer_size says:
"The size returned by this rouine is the size of the application data contained within the buffer
Size of application data in a RAW buffer is not statically computable so does this mean RAW buffers don't support this function or that they report their fixed size?
I don't have problem either way, in fact I think it's great - I just want to understand.

Gilad Ben-Yossef
Software Architect
EZchip Technologies Ltd.
37 Israel Pollak Ave, Kiryat Gat 82025 ,Israel
Tel: +972-4-959-6666 ext. 576, Fax: +972-8-681-1483 
Mobile: +972-52-826-0388, US Mobile: +1-973-826-0388
Email: giladb@ezchip.com, Web: http://www.ezchip.com

"Ethernet always wins."
        — Andy Bechtolsheim


> -----Original Message-----

> From: lng-odp-bounces@lists.linaro.org [mailto:lng-odp-

> bounces@lists.linaro.org] On Behalf Of Bill Fischofer

> Sent: Monday, November 03, 2014 5:07 AM

> To: lng-odp@lists.linaro.org

> Subject: [lng-odp] [[RFC PATCH]] RFC for new buffer .h files

> 

> RFC version of patches for new buffer .h files.  Includes all API

> changes from

> buffer design doc + extended notes.  Do not merge until corresponding

> code

> changes are posted.

> 

> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>

> ---

>  platform/linux-generic/include/api/odp_buffer.h    | 532

> ++++++++++++++++++++-

>  .../linux-generic/include/api/odp_buffer_pool.h    | 242 +++++++++-

>  2 files changed, 740 insertions(+), 34 deletions(-)

> 

> diff --git a/platform/linux-generic/include/api/odp_buffer.h

> b/platform/linux-generic/include/api/odp_buffer.h

> index 289e0eb..9910d0e 100644

> --- a/platform/linux-generic/include/api/odp_buffer.h

> +++ b/platform/linux-generic/include/api/odp_buffer.h

> @@ -8,7 +8,88 @@

>  /**

>   * @file

>   *

> - * ODP buffer descriptor

> + * @par Buffer

> + * A buffer is an element of a buffer pool used for storing

> + * information.  Buffers are referenced by an abstract handle of type

> + * odp_buffer_t.  Buffers have associated buffer types that describe

> + * their intended use and the type of meta data that is associated

> + * with them.  Buffers of a specific type may be referenced for

> + * processing by cores or by offload engines.  Buffers are also

> + * transmitted via queues from one processing element to another.

> + *

> + * @par Buffer Types

> + * An ODP buffer type is identified by the

> + * odp_buffer_type_e enum.  It defines the semantics that are to be

> + * attached to the buffer and defines the type of meta data that is

> + * associated with it.  ODP implementations MUST support the following

> + * buffer types:<br><br>

> + *

> + * - ODP_BUFFER_TYPE_RAW<br>

> + * 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.<br><br>

> + *

> + * - ODP_BUFFER_TYPE_PACKET<br>

> + * This buffer type is suitable for receiving,

> + * processing, and transmitting network packet data.  Included in this

> + * type is a rich set of primitives for manipulating buffer aggregates

> + * and for storing system and user meta data.  APIs for this type of

> + * buffer are described here and in the ODP Packet Management Design

> + * document.<br><br>

> + *

> + * - ODP_BUFFER_TYPE_TIMEOUT<br>

> + * This buffer type is suitable for

> + * representing timer timeout events.  Does not support buffer

> + * aggregation but does support user meta data.  APIs for this type of

> + * buffer are described here and in the ODP Timer Management Design

> + * document.<br><br>

> + *

> + * - ODP_BUFFER_TYPE_ANY<br>

> + * A “universal” buffer type capable of

> + * storing information needed for any other buffer type.  It is not

> + * intended to be used directly, but exists for possible

> + * implementation convenience.

> + *

> + * @par Meta Data

> + * Meta Data is additional information relating to a

> + * buffer that is distinct from the application data normally held in

> + * the buffer.  Implementations MAY choose to implement meta data as

> + * contiguous with a buffer (e.g., in an implementation-managed prefix

> + * area of the buffer) or in a physically separate meta data area

> + * efficiently accessible by the implementation using the same

> + * identifier as the buffer itself.  ODP applications MUST NOT make

> + * assumptions about the addressability relationship between a buffer

> + * and its associated meta data, or between meta data items.

> + * Application use of meta data MUST only be via accessor functions.

> + *

> + * @par Note on OPTIONAL APIs

> + * Every conforming ODP implementation MUST

> + * provide implementations for each API described here.  if an API is

> + * designated as OPTIONAL, this means that it is acceptable for an

> + * implementation to do nothing except return

> + * ODP_FUNCTION_NOT_AVAILABLE in response to this call. Note that this

> + * may limit the range of ODP applications supported by a given

> + * implementation since applications needing the functionality of the

> + * optional API will likely choose to deploy on other ODP platforms.

> + *

> + * @par

> + * APIs are designated as OPTIONAL under two conditions:<br><br>

> + *

> + * -# The API is expected to be difficult to provide efficiently on all

> + *  platforms.<br><br>

> + * -# A significant number of ODP applications are expected to exist

> + *  that will not need or use this API.

> + *

> + * @par

> + * Under these circumstances, an API is designated as OPTIONAL to

> + * permit ODP implementations to be conformant while still expecting

> + * to be able to run a significant number of ODP applications.

> + *

>   */

> 

>  #ifndef ODP_BUFFER_H_

> @@ -21,10 +102,9 @@ extern "C" {

> 

>  #include <odp_std_types.h>

> 

> -

>  /** @defgroup odp_buffer ODP BUFFER

> - *  Operations on a buffer.

> - *  @{

> + *

> + * @{

>   */

> 

>  /**

> @@ -32,62 +112,476 @@ 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 pool

> + */

> +typedef uint32_t odp_buffer_pool_t;

> +

> +/**

> + * ODP buffer type

> + */

> +typedef enum odp_buffer_type {

> +	ODP_BUFER_TYPE_INVALID  = -1, /**< Buffer type invalid */

> +	ODP_BUFFER_TYPE_ANY     = 0,  /**< Buffer type 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

> + *

> + * @note 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.

> + *

> + * @par Segmented vs. Unsegmented Buffer Pools

> + * By default, the buffers

> + * in ODP buffer pools are logical buffers that support transparent

> + * segmentation managed by ODP on behalf of the application and have a

> + * rich set of associated semantics as described here.

> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified

> + * for the pool should be regarded as a fixed buffer size for all pool

> + * elements and that segmentation support is not needed for the pool.

> + * This MAY result in greater efficiency on some implementations.  For

> + * packet processing, a typical use of unsegmented pools would be in

> + * conjunction with classification rules that sort packets into

> + * different pools based on their lengths, thus ensuring that each

> + * packet occupies a single segment within an appropriately-sized

> + * buffer.

> + */

> + typedef enum odp_buffer_opts {

> +	 ODP_BUFFER_OPTS_NONE,        /**< Default, no buffer options */

> +	 ODP_BUFFER_OPTS_UNSEGMENTED, /**< Reqest this pool contain

> unsegmented

> +                                           buffers */

> + } odp_buffer_opts_e;

> +

> +/**

> + * Error returns

> + */

> +#define ODP_BUFFER_INVALID (odp_buffer_t)(-1)

> 

>  /**

>   * Buffer start address

>   *

> - * @param buf      Buffer handle

> + * @param[in] buf  Buffer handle

>   *

>   * @return Buffer start address

>   */

>  void *odp_buffer_addr(odp_buffer_t buf);

> 

>  /**

> - * Buffer maximum data size

> + * Buffer application data size

>   *

> - * @param buf      Buffer handle

> + * @param[in] buf  Buffer handle

>   *

> - * @return Buffer maximum data size

> + * @return Buffer application data size

> + *

> + * @note The size returned by this rouine is the size of the

> + * application data contained within the buffer and does not include

> + * any inplementation-defined overhead to support meta data, etc.  ODP

> + * does not define APIs for determining the amount of storage that is

> + * physically allocated by an implementation to support ODP buffers.

>   */

>  size_t odp_buffer_size(odp_buffer_t buf);

> 

>  /**

>   * Buffer type

>   *

> - * @param buf      Buffer handle

> + * @param[in] buf    Buffer handle

>   *

>   * @return Buffer type

>   */

> -int odp_buffer_type(odp_buffer_t buf);

> +odp_buffer_type_e 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 */

> +/**

> + * Get address and size of user meta data for 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 for 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.

> + *

> + * @note This is a "fastpath" version of odp_buffer_udata() since it

> + * omits returning the size of the user meta data area.  Callers are

> + * expected to know and honor this limit nonetheless.

> + */

> +void *odp_buffer_udata_addr(odp_buffer_t buf);

> 

>  /**

>   * Tests if buffer is valid

>   *

> - * @param buf      Buffer handle

> + * @param[in] buf    Buffer handle

>   *

>   * @return 1 if valid, otherwise 0

> + *

> + * @note Since buffer operations typically occur in fastpath sections

> + * of applications, by default most ODP APIs assume that valid buffer

> + * handles are passed to them and results are undefined if this

> + * assumption is not met.  This routine exists to enable an

> + * application to request explicit validation of a buffer handle. It

> + * is understood that the performance of this operation MAY vary

> + * considerably on a per-implementation basis.

>   */

>  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 then one segment, otherwise 0

> + *

> + * @note This routine behaves identically to the test

> + * odp_buffer_segment_count() > 1, but is potentially more efficient

> + * and represents the preferred method of determining a buffer's

> + * segmentation status.

> + */

> +int odp_buffer_is_segmented(odp_buffer_t buf);

> +

> +/**

>   * Print buffer metadata to STDOUT

>   *

> - * @param buf      Buffer handle

> + * @param[in] buf    Buffer handle

>   *

> + * @note This routine is intended for diagnostic use and prints

> + * implementation-defined information concerning the buffer to the ODP

> + * LOG.  It's provision is OPTIONAL.

>   */

>  void odp_buffer_print(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 handle 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 handle for a buffer segment

> + *

> + * @param[in] buf    Buffer handle

> + * @param[in] seg    Segment identifier of the previous segment

> + *

> + * @return           Segment identifier of next segment or

> ODP_SEGMENT_INVALID

> + *

> + * @note This routine returns the identifier (odp_buffer_segment_t) of

> + * the next buffer segment in a buffer aggregate.  The input

> + * specifies the buffer and the previous segment identifier.  There are

> + * three use cases for this routine:

> + * @par

> + * -# If the input seg is ODP_SEGMENT_START then the segment identifier

> returned

> + * is that of the first segment in the buffer.  ODP_SEGMENT_NULL MAY be

> used

> + * as a synonym for ODP_SEGMENT_START for symmetry if desired.<br><br>

> + * -# If the input seg is not the last segment in the buffer then the

> + * segment handle of the next segment following seg is

> returned.<br><br>

> + * -# If the input seg is the segment identifier of the last segment in

> + * the buffer then ODP_SEGMENT_NULL is returned.

> + *

> + */

> +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,

> +					     odp_buffer_segment_t seg);

> +

> +/**

> + * Get addressability for a specified buffer segment

> + *

> + * @param[in] buf     Buffer handle

> + * @param[in] seg     Segment handle of the segment to be mapped

> + * @param[in] seglen  Returned number of bytes in this buffer segment

> + *                    available at the returned address

> + *

> + * @return            Segment start address or NULL

> + *

> + * @note This routine is used to obtain addressability to a segment

> within

> + * a buffer aggregate at a specified segment identifier.  The returned

> seglen

> + * indicates the number of bytes addressable at the returned address.

> + */

> +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

> + *

> + * @note This routine is used to unmap a buffer segment previously

> + *  mapped by odp_buffer_segment_map().  Following this call,

> + *  applications MUST NOT attempt to reference the segment via any

> + *  pointer returned from a previous odp_buffer_segment_map() call

> + *  referring to it.  It is intended to allow certain NUMA

> + *  architectures to better manage the coherency of mapped segments.

> + *  For non-NUMA architectures this routine will be a no-op.  Note

> + *  that implementations SHOULD implicitly unmap all buffer segments

> + *  whenever a buffer is added to a queue as this indicates that the

> + *  caller is relinquishing control of the buffer.

> + */

> +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

> + *

> + * @note This routine is used to obtain addressability to a segment

> + * within a buffer at a specified byte offset.  Note that because the

> + * offset is independent of any implementation-defined physical

> + * segmentation the returned seglen may be “short” and will range from

> + * 1 to whatever physical segment size is used by the underlying

> + * implementation.

> + */

> +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

> + *

> + * @note This routine is used to unmap a buffer segment previously

> + * mapped by odp_buffer_offset_map(). Following this call

> + * the application MUST NOT attempt to reference the segment via any

> + * pointer returned by a prior odp_buffer_offset_map() call relating

> + * to this offset.  It is intended to allow certain NUMA architectures

> + * to better manage the coherency of mapped segments.  For non-NUMA

> + * architectures this routine will be a no-op.  Note that

> + * implementations SHOULD implicitly unmap all buffer segments

> + * whenever a buffer is added to a queue as this indicates that the

> + * caller is relinquishing control of the buffer.

> + */

> +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);

> +

> +/**

> + * 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

> + *

> + * @note This routine splits a buffer into two buffers at the

> + * specified byte offset.  The odp_buffer_t returned by the function

> + * is the handle of the new buffer created at the split point.  If the

> + * original buffer was allocated from a buffer pool then the split is

> + * allocated from the same pool.  If the original buffer was size

> + * bytes in length then upon return the original buffer is of size

> + * offset while the split buffer is of size (size-offset).

> + *

> + * @par

> + * This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a matching routine that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + *

> + * @par

> + * Upon return from this function, the system meta data for both

> + * buffers has been updated appropriately by the call since system

> + * meta data maintenance is the responsibility of the ODP

> + * implementation.  Any required updates to the user meta data is the

> + * responsibility of the caller.

> + */

> +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

> + *

> + * @note This routine joins two buffers into a single buffer.  Both

> + * buf1 and buf2 MUST be from the same buffer pool and the resulting

> + * joined buffer will be an element of that same pool.  The

> + * application MUST NOT assume that either buf1 or buf2 survive the

> + * join or that the returned joined buffer is contiguous with or

> + * otherwise related to the input buffers.  An implementation SHOULD

> + * free either or both input buffers if they are not reused as part of

> + * the construction of the returned joined buffer.  If the join cannot

> + * be performed (e.g., if the two input buffers are not from the same

> + * buffer pool, insufficient space in the target buffer pool, etc.)

> + * then ODP_BUFFER_INVALID SHOULD be returned to indicate that the

> + * operation could not be performed, and an appropriate errno set.  In

> + * such case the input buffers MUST NOT be freed as part of the failed

> + * join attempt and should be unchanged from their input values and

> + * content.

> + *

> + * @par The result of odp_buffer_join() is the logical concatenation

> + * of the two buffers using an implementation-defined buffer

> + * aggregation mechanism.  The application data contents of the

> + * returned buffer is identical to that of the two joined input

> + * buffers however certain associated meta data (e.g., information

> + * about the buffer size) will likely differ.

> + *

> + * @par If user meta data is present in the buffer pool containing the

> + * input buffers, then the user meta data associated with the returned

> + * buffer MUST be copied by this routine from the source buf1.

> + *

> + * @par This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a routine matching that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + */

> +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

> + *

> + * @note This routine discards bytes from the end of a buffer.  It is

> + * logically equivalent to a split followed by a free of the split

> + * portion of the input buffer.  The input offset must be less than or

> + * equal to the odp_buffer_size() of the input buffer.  Upon

> + * successful return the odp_buffer_size() routine would now return

> + * offset as the size of the trimmed buffer.  Note that the returned

> + * odp_buffer_t may not necessarily be the same as the input

> + * odp_buffer_t.  The caller should use the returned value when

> + * referencing the trimmed buffer instead of the original in case they

> + * are different.

> + *

> + * @par If the input buf contains user meta data, then this data MUST

> + * be copied to the returned buffer if needed by the API

> + * implementation.

> + *

> + * @par This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a matching routine that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + */

> +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

> + *

> + * @note This routine extends a buffer by increasing its size by ext

> + * bytes.  It is logically equivalent to an odp_buffer_join() of a

> + * buffer of size ext to the original buffer.  Upon successful return

> + * the odp_buffer_size() routine would now return size+ext as the size

> + * of the extended buffer.

> + *

> + * @par Note that the returned odp_buffer_t may not necessarily be the

> + * same as the input odp_buffer_t.  The caller should use the returned

> + * value when referencing the extended buffer instead of the original

> + * in case they are different.  If the input buf contains user meta

> + * data, then this data MUST be copied to the returned buffer if

> + * needed by the API implementation.

> + *

> + * @par This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a matching routine that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + */

> +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

> + *

> + * @note This routine allows an ODP buffer to be cloned in an

> + * implementation-defined manner.  The application data contents of

> + * the returned odp_buffer_t is an exact copy of the application data

> + * of the input buffer.  The implementation MAY perform this operation

> + * via reference counts, resegmentation, or any other technique it

> + * wishes to employ. The cloned buffer is an element of the same

> + * buffer pool as the input buf.  If the input buf contains user meta

> + * data, then this data MUST be copied to the returned buffer by the

> + * ODP implementation.

> + *

> + * @par This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a matching routine that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + */

> +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

> + * @param[in] pool buffer pool to contain the copied buffer

> + *

> + * @return         Handle of the copied buffer or ODP_BUFFER_INVALID

> + *                 if the operation was not performed

> + *

> + * @note This routine allows an ODP buffer to be copied in an

> + * implementation-defined manner to a specified buffer pool.  The

> + * specified pool may or may not be different from the source buffer’s

> + * pool.  The application data contents of the returned odp_buffer_t

> + * is an exact separate copy of the application data of the input

> + * buffer.  If the input buf contains user meta data, then this data

> + * MUST be copied to the returned buffer by the ODP implementation.

> + *

> + * @par This routine is OPTIONAL.  An implementation that does not

> + * support this function MUST provide a matching routine that simply

> + * returns ODP_BUFFER_INVALID with an errno of

> + * ODP_FUNCTION_NOT_AVAILABLE.

> + */

> +odp_buffer_t odp_buffer_copy(odp_buffer_t buf, odp_buffer_pool_t pool);

> +

> +

> +/**

>   * @}

>   */

> 

> diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h

> b/platform/linux-generic/include/api/odp_buffer_pool.h

> index d04abf0..cf67c2a 100644

> --- a/platform/linux-generic/include/api/odp_buffer_pool.h

> +++ b/platform/linux-generic/include/api/odp_buffer_pool.h

> @@ -8,7 +8,44 @@

>  /**

>   * @file

>   *

> - * ODP buffer pool

> + * @par Buffer Pools

> + * Buffers are elements of buffer pools that represent an equivalence

> + * class of buffer objects that are managed by a buffer pool manager.

> + * ODP implementations MAY support buffer pool managers implemented in

> + * hardware, software, or a combination of the two.  An ODP

> + * implementation MUST support at least one buffer pool and MAY

> + * support as many as it wishes.  The implementation MAY support one

> + * or more predefined buffer pools that are not explicitly allocated

> + * by an ODP application.  It SHOULD also support application creation

> + * of buffer pools via the odp_buffer_pool_create() API, however it

> + * MAY restrict the types of buffers that can be so created.

> + *

> + * @par

> + * Buffer pools are represented by the abstract type odp_buffer_pool_t

> + * that is returned by buffer pool creation and lookup/enumeration

> + * routines.  Applications refer to buffer pools via a name of

> + * implementation-defined maximum length that MUST be a minimummap of

> + * eight characters in length and MAY be longer.  It is RECOMMENDED

> + * that 32 character buffer pool names be supported to provide

> + * application naming flexibility.  The supported maximum length of

> + * buffer pool names is exposed via the ODP_BUFFER_POOL_NAME_LEN

> + * predefined implementation limit.

> + *

> + * @par Segmented vs. Unsegmented Buffer Pools

> + * By default, the buffers in

> + * ODP buffer pools are logical buffers that support transparent

> + * segmentation managed by ODP on behalf of the application and have a

> + * rich set of associated semantics as described here.

> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified

> + * for the pool should be regarded as a fixed buffer size for all pool

> + * elements and that segmentation support is not needed for the pool.

> + * This MAY result in greater efficiency on some implementations.  For

> + * packet processing, a typical use of unsegmented pools would be in

> + * conjunction with classification rules that sort packets into

> + * different pools based on their lengths, thus ensuring that each

> + * packet occupies a single segment within an appropriately-sized

> + * buffer.

> + *

>   */

> 

>  #ifndef ODP_BUFFER_POOL_H_

> @@ -35,42 +72,217 @@ extern "C" {

>  #define ODP_BUFFER_POOL_INVALID   0

> 

>  /** ODP buffer pool */

> -typedef uint32_t odp_buffer_pool_t;

> +// typedef uint32_t odp_buffer_pool_t;

> +

> +/**

> + * Buffer initialization routine prototype

> + *

> + * @note Routines of this type MAY be passed as part of the

> + * odp_buffer_pool_init_t structure to be called whenever a

> + * buffer is allocated to initialize the user meta data

> + * associated with that buffer.

> + */

> +typedef void (odp_buf_init_t)(odp_buffer_t buf, void *buf_init_arg);

> +

> +/**

> + * Buffer pool parameters

> + *

> + * @param[in] buf_num    Number of buffers that pool should contain

> + * @param[in] buf_size   Size of application data in each buffer

> + * @param[in] buf_type   Buffer type

> + * @param[in] buf_opts   Buffer options

> + */

> +typedef struct odp_buffer_pool_param_t {

> +        size_t buf_num;             /**< Number of buffers in this pool

> */

> +	size_t buf_size;            /**< Application data size of each

> buffer */

> +	odp_buffer_type_e buf_type; /**< Buffer type */

> +	odp_buffer_opts_e buf_opts; /**< Buffer options */

> +} odp_buffer_pool_param_t;          /**< Type of buffer pool parameter

> struct */

> 

> +/**

> + * Buffer pool initialization parameters

> + *

> + * @param[in] udata_size     Size of the user meta data for each buffer

> + * @param[in] buf_init       Function pointer to be called to

> initialize the

> + *                           user meta data for each buffer in the

> pool.

> + * @param[in] buf_init_arg   Argument to be passed to buf_init().

> + *

> + */

> +typedef struct odp_buffer_pool_init_t {

> +        size_t udata_size;         /**< Size of user meta dat for each

> buffer */

> +        odp_buf_init_t *buf_init;  /**< Buffer initialization routine

> to use */

> +        void *buf_init_arg;        /**< Argument to be passed to

> buf_init() */

> +} odp_buffer_pool_init_t;          /**< Type of buffer initialization

> struct */

> 

>  /**

>   * Create a buffer pool

>   *

> - * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1

> chars)

> - * @param base_addr Pool base address

> - * @param size      Pool size in bytes

> - * @param buf_size  Buffer size in bytes

> - * @param buf_align Minimum buffer alignment

> - * @param buf_type  Buffer type

> + * @param[in] name           Name of the pool

> + *                           (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)

> + *

> + * @param[in] params         Parameters controlling the creation of

> this

> + *                           buffer pool

> + *

> + * @param[in] init_params    Parameters controlling the initialization

> of

> + *                           this buffer pool

>   *

> - * @return Buffer pool handle

> + * @return Buffer pool handle or ODP_BUFFER_POOL_NULL with errno set

> + *

> + * @note This routine is used to create a buffer pool.  It takes three

> + * arguments: the name of the pool to be created, a parameter

> + * structure that controls the pool creation, and an optional

> + * parameter that controls pool initialization.  In the creation

> + * parameter structure, the application specifies the number of

> + * buffers that the pool should contain as well as the application

> + * data size for each buffer in the pool, the type of buffers it

> + * should contain, and their associated options.  In the

> + * initialization parameters, the application specifies the size of

> + * the user meta data that should be associated with each buffer in

> + * the pool.  If no user meta data is required, the init_params SHOULD

> + * be specified as NULL.  If user meta data is requested, then

> + * udata_size SHOULD be set to the requested size of the per-buffer

> + * user meta data.  Also specified is the address of an

> + * application-provided buffer initialization routine to be called for

> + * each buffer in the pool at the time the pool is initialized, or

> + * when the buffer is allocated.  If no application buffer

> + * initialization is needed, then buf_init and buf_init_arg SHOULD be

> + * set to NULL.

>   */

>  odp_buffer_pool_t odp_buffer_pool_create(const char *name,

> -					 void *base_addr, uint64_t size,

> -					 size_t buf_size, size_t buf_align,

> -					 int buf_type);

> -

> +                                         odp_buffer_pool_param_t

> *params,

> +                                         odp_buffer_pool_init_t

> *init_params);

> 

>  /**

>   * Find a buffer pool by name

>   *

> - * @param name      Name of the pool

> + * @param[in] name  Name of the pool

>   *

>   * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.

>   */

>  odp_buffer_pool_t odp_buffer_pool_lookup(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] params     Output structure for pool parameters

> + * @param[out] predef     Predefined (1) or Created (0).

> + *

> + * @return                Buffer pool handle

> + *

> + * @note This routine returns the abstract identifier

> + * (odp_buffer_pool_t) of a buffer pool and is used to obtain the list

> + * of all buffer pools.  In this manner an application can discover

> + * both application created and implementation predefined buffer pools

> + * and their characteristics.  The input specifies the previous buffer

> + * pool identifier.  There are three use cases for this

> + * routine:<br><br>

> + *

> + * -# If the input pool is ODP_BUFFER_POOL_START then the buffer pool

> handle

> + * returned is that of the first buffer pool in the list.

> + * ODP_BUFFER_POOL_NULL MAY be used as a synonym for

> ODP_BUFFER_POOL_START

> + * if desired.<br><br>

> + *

> + * -# If the input pool is not the last element in the buffer pool list

> + * then the buffer pool handle of the next buffer pool following  pool

> is

> + * returned.<br><br>

> + *

> + * -# If the input pool is the buffer pool handle of the last buffer

> pool

> + * in the list then ODP_BUFFER_POOL_NULL is returned.<br><br>

> + *

> + * Returned with the buffer pool handle is the name of the pool as

> + * well as its dimensions, type of buffers it contains, and a flag

> + * that says whether the pool is predefined or was created by the

> + * application.  Note that the buf_size reported for a buffer pool is

> + * simply the declared expected size of the buffers in the pool and

> + * serves only to estimate the total amount of application data that

> + * can be stored in the pool.  Actual sizes of individual buffers

> + * within the pool are dynamic and variable since physical buffer

> + * segments MAY be aggregated to create buffers of arbitrary size (up

> + * to the pool memory limits).  Note that for predefined buffer pools,

> + * some implementations MAY return the physical segment counts and

> + * sizes used to construct the pool as output of this routine.

> + */

> +odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,

> +                                       char *name, size_t *udata_size,

> +                                       odp_buffer_pool_param_t *params,

> +                                       int *predef);

> +

> +/**

> + * Get the high/low watermarks for a buffer pool

> + *

> + * @param[in]  pool     Handle of the buffer pool

> + * @param[out] high_wm  The high water mark of the designated buffer

> pool

> + * @param[out] low_wm   The low water mark of the designated buffer

> pool

> + *

> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown

> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks

> + *                 are associated with this buffer pool.

> + *

> + * @note This routine gets the high/low watermarks associated with a

> + * given buffer pool.  If the buffer pool does not have or support

> + * watermarks then an error will be returned and both high_wm and

> + * low_wm will be unchanged.

> + *

> + * @par

> + * It is RECOMMENDED that buffer pools of all types support the setting

> + * and getting of watermarks for use in flow control processing.

> + * Watermarks are designed to trigger flow control actions based on

> + * utilization levels of a buffer pool.  When the number of free

> + * buffers in the buffer pool hits the configured low watermark for

> + * the pool, the pool asserts a low watermark condition and an

> + * implementation-defined action in response to this condition is

> + * triggered.  Once in a low watermark state, the condition is

> + * maintained until the number of free buffers reaches the configured

> + * high watermark.  At this point the low watermark condition is

> + * deasserted and normal pool processing resumes.  Having separate

> + * high and low watermarks permits configurable hysteresis to avoid

> + * jitter in handling transient buffer shortages in the pool.

> + *

> + * @par

> + * In general, two types of actions are common.  The first is to

> + * control Random Early Detection (RED) or Weighted RED (WRED)

> + * processing for the pool, while the second is to control IEEE

> + * 802.1Qbb priority-based flow control (PFC) processing for so-called

> + * “lossless Ethernet” support.  The use of watermarks for flow

> + * control processing is most often used for pools containing packets

> + * and this is discussed in further detail in the Class of Service

> + * (CoS) ODP Classification APIs.

> + *

> + */

> +int odp_buffer_pool_watermarks(odp_buffer_pool_t pool,

> +                               size_t *high_wm, size_t *low_wm);

> +

> +/**

> + * Set the high/low watermarks for a buffer pool

> + *

> + * @param[in] pool      Handle of the buffer pool

> + * @param[in] high_wm   The high water mark of the designated buffer

> pool

> + * @param[in] low_wm    The low water mark of the designated buffer

> pool

> + *

> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown

> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks

> + *                 are associated with this buffer pool.

> + *

> + * @note This routine sets the high/low watermarks associated with a

> + * specified buffer pool.  If the buffer pool does not support

> + * watermarks then errno ODP_BUFFER_POOL_NO_WATERMARKS is set and no

> + * function is performed.

> + */

> +int odp_buffer_pool_set_watermarks(odp_buffer_pool_t pool,

> +                                   size_t high_wm, size_t low_wm);

> 

>  /**

>   * Print buffer pool info

>   *

> - * @param pool      Pool handle

> + * @param[in] pool   Pool handle

>   *

> + * @note This is a diagnostic routine that prints statistics regarding

> + * the specified buffer pool to the ODP LOG.  This routine is OPTIONAL

> + * and if present its output is implementation-defined.

>   */

>  void odp_buffer_pool_print(odp_buffer_pool_t pool);

> 

> --

> 1.8.3.2

> 

> 

> _______________________________________________

> lng-odp mailing list

> lng-odp@lists.linaro.org

> http://lists.linaro.org/mailman/listinfo/lng-odp
Bill Fischofer Nov. 3, 2014, 11:42 a.m. UTC | #2
The intent here is that they report their fixed size since RAW buffers are
just blocks without any structure.  It's not the intent for static to imply
compile-time since the caller specifies the size of the buffer block being
used.

The reality is I don't believe we have any actual uses of
ODP_BUFFER_TYPE_RAW at this point.  It was added for completeness.

Bill

On Mon, Nov 3, 2014 at 2:54 AM, Gilad Ben Yossef <giladb@ezchip.com> wrote:

>
> "ODP_BUFFER_TYPE_RAW<br>
> + * 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"
> And odp_buffer_size says:
> "The size returned by this rouine is the size of the application data
> contained within the buffer
> Size of application data in a RAW buffer is not statically computable so
> does this mean RAW buffers don't support this function or that they report
> their fixed size?
> I don't have problem either way, in fact I think it's great - I just want
> to understand.
>
> Gilad Ben-Yossef
> Software Architect
> EZchip Technologies Ltd.
> 37 Israel Pollak Ave, Kiryat Gat 82025 ,Israel
> Tel: +972-4-959-6666 ext. 576, Fax: +972-8-681-1483
> Mobile: +972-52-826-0388, US Mobile: +1-973-826-0388
> Email: giladb@ezchip.com, Web: http://www.ezchip.com
>
> "Ethernet always wins."
>         — Andy Bechtolsheim
>
>
> > -----Original Message-----
> > From: lng-odp-bounces@lists.linaro.org [mailto:lng-odp-
> > bounces@lists.linaro.org] On Behalf Of Bill Fischofer
> > Sent: Monday, November 03, 2014 5:07 AM
> > To: lng-odp@lists.linaro.org
> > Subject: [lng-odp] [[RFC PATCH]] RFC for new buffer .h files
> >
> > RFC version of patches for new buffer .h files.  Includes all API
> > changes from
> > buffer design doc + extended notes.  Do not merge until corresponding
> > code
> > changes are posted.
> >
> > Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
> > ---
> >  platform/linux-generic/include/api/odp_buffer.h    | 532
> > ++++++++++++++++++++-
> >  .../linux-generic/include/api/odp_buffer_pool.h    | 242 +++++++++-
> >  2 files changed, 740 insertions(+), 34 deletions(-)
> >
> > diff --git a/platform/linux-generic/include/api/odp_buffer.h
> > b/platform/linux-generic/include/api/odp_buffer.h
> > index 289e0eb..9910d0e 100644
> > --- a/platform/linux-generic/include/api/odp_buffer.h
> > +++ b/platform/linux-generic/include/api/odp_buffer.h
> > @@ -8,7 +8,88 @@
> >  /**
> >   * @file
> >   *
> > - * ODP buffer descriptor
> > + * @par Buffer
> > + * A buffer is an element of a buffer pool used for storing
> > + * information.  Buffers are referenced by an abstract handle of type
> > + * odp_buffer_t.  Buffers have associated buffer types that describe
> > + * their intended use and the type of meta data that is associated
> > + * with them.  Buffers of a specific type may be referenced for
> > + * processing by cores or by offload engines.  Buffers are also
> > + * transmitted via queues from one processing element to another.
> > + *
> > + * @par Buffer Types
> > + * An ODP buffer type is identified by the
> > + * odp_buffer_type_e enum.  It defines the semantics that are to be
> > + * attached to the buffer and defines the type of meta data that is
> > + * associated with it.  ODP implementations MUST support the following
> > + * buffer types:<br><br>
> > + *
> > + * - ODP_BUFFER_TYPE_RAW<br>
> > + * 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.<br><br>
> > + *
> > + * - ODP_BUFFER_TYPE_PACKET<br>
> > + * This buffer type is suitable for receiving,
> > + * processing, and transmitting network packet data.  Included in this
> > + * type is a rich set of primitives for manipulating buffer aggregates
> > + * and for storing system and user meta data.  APIs for this type of
> > + * buffer are described here and in the ODP Packet Management Design
> > + * document.<br><br>
> > + *
> > + * - ODP_BUFFER_TYPE_TIMEOUT<br>
> > + * This buffer type is suitable for
> > + * representing timer timeout events.  Does not support buffer
> > + * aggregation but does support user meta data.  APIs for this type of
> > + * buffer are described here and in the ODP Timer Management Design
> > + * document.<br><br>
> > + *
> > + * - ODP_BUFFER_TYPE_ANY<br>
> > + * A “universal” buffer type capable of
> > + * storing information needed for any other buffer type.  It is not
> > + * intended to be used directly, but exists for possible
> > + * implementation convenience.
> > + *
> > + * @par Meta Data
> > + * Meta Data is additional information relating to a
> > + * buffer that is distinct from the application data normally held in
> > + * the buffer.  Implementations MAY choose to implement meta data as
> > + * contiguous with a buffer (e.g., in an implementation-managed prefix
> > + * area of the buffer) or in a physically separate meta data area
> > + * efficiently accessible by the implementation using the same
> > + * identifier as the buffer itself.  ODP applications MUST NOT make
> > + * assumptions about the addressability relationship between a buffer
> > + * and its associated meta data, or between meta data items.
> > + * Application use of meta data MUST only be via accessor functions.
> > + *
> > + * @par Note on OPTIONAL APIs
> > + * Every conforming ODP implementation MUST
> > + * provide implementations for each API described here.  if an API is
> > + * designated as OPTIONAL, this means that it is acceptable for an
> > + * implementation to do nothing except return
> > + * ODP_FUNCTION_NOT_AVAILABLE in response to this call. Note that this
> > + * may limit the range of ODP applications supported by a given
> > + * implementation since applications needing the functionality of the
> > + * optional API will likely choose to deploy on other ODP platforms.
> > + *
> > + * @par
> > + * APIs are designated as OPTIONAL under two conditions:<br><br>
> > + *
> > + * -# The API is expected to be difficult to provide efficiently on all
> > + *  platforms.<br><br>
> > + * -# A significant number of ODP applications are expected to exist
> > + *  that will not need or use this API.
> > + *
> > + * @par
> > + * Under these circumstances, an API is designated as OPTIONAL to
> > + * permit ODP implementations to be conformant while still expecting
> > + * to be able to run a significant number of ODP applications.
> > + *
> >   */
> >
> >  #ifndef ODP_BUFFER_H_
> > @@ -21,10 +102,9 @@ extern "C" {
> >
> >  #include <odp_std_types.h>
> >
> > -
> >  /** @defgroup odp_buffer ODP BUFFER
> > - *  Operations on a buffer.
> > - *  @{
> > + *
> > + * @{
> >   */
> >
> >  /**
> > @@ -32,62 +112,476 @@ 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 pool
> > + */
> > +typedef uint32_t odp_buffer_pool_t;
> > +
> > +/**
> > + * ODP buffer type
> > + */
> > +typedef enum odp_buffer_type {
> > +     ODP_BUFER_TYPE_INVALID  = -1, /**< Buffer type invalid */
> > +     ODP_BUFFER_TYPE_ANY     = 0,  /**< Buffer type 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
> > + *
> > + * @note 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.
> > + *
> > + * @par Segmented vs. Unsegmented Buffer Pools
> > + * By default, the buffers
> > + * in ODP buffer pools are logical buffers that support transparent
> > + * segmentation managed by ODP on behalf of the application and have a
> > + * rich set of associated semantics as described here.
> > + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> > + * for the pool should be regarded as a fixed buffer size for all pool
> > + * elements and that segmentation support is not needed for the pool.
> > + * This MAY result in greater efficiency on some implementations.  For
> > + * packet processing, a typical use of unsegmented pools would be in
> > + * conjunction with classification rules that sort packets into
> > + * different pools based on their lengths, thus ensuring that each
> > + * packet occupies a single segment within an appropriately-sized
> > + * buffer.
> > + */
> > + typedef enum odp_buffer_opts {
> > +      ODP_BUFFER_OPTS_NONE,        /**< Default, no buffer options */
> > +      ODP_BUFFER_OPTS_UNSEGMENTED, /**< Reqest this pool contain
> > unsegmented
> > +                                           buffers */
> > + } odp_buffer_opts_e;
> > +
> > +/**
> > + * Error returns
> > + */
> > +#define ODP_BUFFER_INVALID (odp_buffer_t)(-1)
> >
> >  /**
> >   * Buffer start address
> >   *
> > - * @param buf      Buffer handle
> > + * @param[in] buf  Buffer handle
> >   *
> >   * @return Buffer start address
> >   */
> >  void *odp_buffer_addr(odp_buffer_t buf);
> >
> >  /**
> > - * Buffer maximum data size
> > + * Buffer application data size
> >   *
> > - * @param buf      Buffer handle
> > + * @param[in] buf  Buffer handle
> >   *
> > - * @return Buffer maximum data size
> > + * @return Buffer application data size
> > + *
> > + * @note The size returned by this rouine is the size of the
> > + * application data contained within the buffer and does not include
> > + * any inplementation-defined overhead to support meta data, etc.  ODP
> > + * does not define APIs for determining the amount of storage that is
> > + * physically allocated by an implementation to support ODP buffers.
> >   */
> >  size_t odp_buffer_size(odp_buffer_t buf);
> >
> >  /**
> >   * Buffer type
> >   *
> > - * @param buf      Buffer handle
> > + * @param[in] buf    Buffer handle
> >   *
> >   * @return Buffer type
> >   */
> > -int odp_buffer_type(odp_buffer_t buf);
> > +odp_buffer_type_e 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 */
> > +/**
> > + * Get address and size of user meta data for 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 for 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.
> > + *
> > + * @note This is a "fastpath" version of odp_buffer_udata() since it
> > + * omits returning the size of the user meta data area.  Callers are
> > + * expected to know and honor this limit nonetheless.
> > + */
> > +void *odp_buffer_udata_addr(odp_buffer_t buf);
> >
> >  /**
> >   * Tests if buffer is valid
> >   *
> > - * @param buf      Buffer handle
> > + * @param[in] buf    Buffer handle
> >   *
> >   * @return 1 if valid, otherwise 0
> > + *
> > + * @note Since buffer operations typically occur in fastpath sections
> > + * of applications, by default most ODP APIs assume that valid buffer
> > + * handles are passed to them and results are undefined if this
> > + * assumption is not met.  This routine exists to enable an
> > + * application to request explicit validation of a buffer handle. It
> > + * is understood that the performance of this operation MAY vary
> > + * considerably on a per-implementation basis.
> >   */
> >  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 then one segment, otherwise 0
> > + *
> > + * @note This routine behaves identically to the test
> > + * odp_buffer_segment_count() > 1, but is potentially more efficient
> > + * and represents the preferred method of determining a buffer's
> > + * segmentation status.
> > + */
> > +int odp_buffer_is_segmented(odp_buffer_t buf);
> > +
> > +/**
> >   * Print buffer metadata to STDOUT
> >   *
> > - * @param buf      Buffer handle
> > + * @param[in] buf    Buffer handle
> >   *
> > + * @note This routine is intended for diagnostic use and prints
> > + * implementation-defined information concerning the buffer to the ODP
> > + * LOG.  It's provision is OPTIONAL.
> >   */
> >  void odp_buffer_print(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 handle 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 handle for a buffer segment
> > + *
> > + * @param[in] buf    Buffer handle
> > + * @param[in] seg    Segment identifier of the previous segment
> > + *
> > + * @return           Segment identifier of next segment or
> > ODP_SEGMENT_INVALID
> > + *
> > + * @note This routine returns the identifier (odp_buffer_segment_t) of
> > + * the next buffer segment in a buffer aggregate.  The input
> > + * specifies the buffer and the previous segment identifier.  There are
> > + * three use cases for this routine:
> > + * @par
> > + * -# If the input seg is ODP_SEGMENT_START then the segment identifier
> > returned
> > + * is that of the first segment in the buffer.  ODP_SEGMENT_NULL MAY be
> > used
> > + * as a synonym for ODP_SEGMENT_START for symmetry if desired.<br><br>
> > + * -# If the input seg is not the last segment in the buffer then the
> > + * segment handle of the next segment following seg is
> > returned.<br><br>
> > + * -# If the input seg is the segment identifier of the last segment in
> > + * the buffer then ODP_SEGMENT_NULL is returned.
> > + *
> > + */
> > +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
> > +                                          odp_buffer_segment_t seg);
> > +
> > +/**
> > + * Get addressability for a specified buffer segment
> > + *
> > + * @param[in] buf     Buffer handle
> > + * @param[in] seg     Segment handle of the segment to be mapped
> > + * @param[in] seglen  Returned number of bytes in this buffer segment
> > + *                    available at the returned address
> > + *
> > + * @return            Segment start address or NULL
> > + *
> > + * @note This routine is used to obtain addressability to a segment
> > within
> > + * a buffer aggregate at a specified segment identifier.  The returned
> > seglen
> > + * indicates the number of bytes addressable at the returned address.
> > + */
> > +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
> > + *
> > + * @note This routine is used to unmap a buffer segment previously
> > + *  mapped by odp_buffer_segment_map().  Following this call,
> > + *  applications MUST NOT attempt to reference the segment via any
> > + *  pointer returned from a previous odp_buffer_segment_map() call
> > + *  referring to it.  It is intended to allow certain NUMA
> > + *  architectures to better manage the coherency of mapped segments.
> > + *  For non-NUMA architectures this routine will be a no-op.  Note
> > + *  that implementations SHOULD implicitly unmap all buffer segments
> > + *  whenever a buffer is added to a queue as this indicates that the
> > + *  caller is relinquishing control of the buffer.
> > + */
> > +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
> > + *
> > + * @note This routine is used to obtain addressability to a segment
> > + * within a buffer at a specified byte offset.  Note that because the
> > + * offset is independent of any implementation-defined physical
> > + * segmentation the returned seglen may be “short” and will range from
> > + * 1 to whatever physical segment size is used by the underlying
> > + * implementation.
> > + */
> > +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
> > + *
> > + * @note This routine is used to unmap a buffer segment previously
> > + * mapped by odp_buffer_offset_map(). Following this call
> > + * the application MUST NOT attempt to reference the segment via any
> > + * pointer returned by a prior odp_buffer_offset_map() call relating
> > + * to this offset.  It is intended to allow certain NUMA architectures
> > + * to better manage the coherency of mapped segments.  For non-NUMA
> > + * architectures this routine will be a no-op.  Note that
> > + * implementations SHOULD implicitly unmap all buffer segments
> > + * whenever a buffer is added to a queue as this indicates that the
> > + * caller is relinquishing control of the buffer.
> > + */
> > +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);
> > +
> > +/**
> > + * 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
> > + *
> > + * @note This routine splits a buffer into two buffers at the
> > + * specified byte offset.  The odp_buffer_t returned by the function
> > + * is the handle of the new buffer created at the split point.  If the
> > + * original buffer was allocated from a buffer pool then the split is
> > + * allocated from the same pool.  If the original buffer was size
> > + * bytes in length then upon return the original buffer is of size
> > + * offset while the split buffer is of size (size-offset).
> > + *
> > + * @par
> > + * This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a matching routine that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + *
> > + * @par
> > + * Upon return from this function, the system meta data for both
> > + * buffers has been updated appropriately by the call since system
> > + * meta data maintenance is the responsibility of the ODP
> > + * implementation.  Any required updates to the user meta data is the
> > + * responsibility of the caller.
> > + */
> > +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
> > + *
> > + * @note This routine joins two buffers into a single buffer.  Both
> > + * buf1 and buf2 MUST be from the same buffer pool and the resulting
> > + * joined buffer will be an element of that same pool.  The
> > + * application MUST NOT assume that either buf1 or buf2 survive the
> > + * join or that the returned joined buffer is contiguous with or
> > + * otherwise related to the input buffers.  An implementation SHOULD
> > + * free either or both input buffers if they are not reused as part of
> > + * the construction of the returned joined buffer.  If the join cannot
> > + * be performed (e.g., if the two input buffers are not from the same
> > + * buffer pool, insufficient space in the target buffer pool, etc.)
> > + * then ODP_BUFFER_INVALID SHOULD be returned to indicate that the
> > + * operation could not be performed, and an appropriate errno set.  In
> > + * such case the input buffers MUST NOT be freed as part of the failed
> > + * join attempt and should be unchanged from their input values and
> > + * content.
> > + *
> > + * @par The result of odp_buffer_join() is the logical concatenation
> > + * of the two buffers using an implementation-defined buffer
> > + * aggregation mechanism.  The application data contents of the
> > + * returned buffer is identical to that of the two joined input
> > + * buffers however certain associated meta data (e.g., information
> > + * about the buffer size) will likely differ.
> > + *
> > + * @par If user meta data is present in the buffer pool containing the
> > + * input buffers, then the user meta data associated with the returned
> > + * buffer MUST be copied by this routine from the source buf1.
> > + *
> > + * @par This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a routine matching that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + */
> > +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
> > + *
> > + * @note This routine discards bytes from the end of a buffer.  It is
> > + * logically equivalent to a split followed by a free of the split
> > + * portion of the input buffer.  The input offset must be less than or
> > + * equal to the odp_buffer_size() of the input buffer.  Upon
> > + * successful return the odp_buffer_size() routine would now return
> > + * offset as the size of the trimmed buffer.  Note that the returned
> > + * odp_buffer_t may not necessarily be the same as the input
> > + * odp_buffer_t.  The caller should use the returned value when
> > + * referencing the trimmed buffer instead of the original in case they
> > + * are different.
> > + *
> > + * @par If the input buf contains user meta data, then this data MUST
> > + * be copied to the returned buffer if needed by the API
> > + * implementation.
> > + *
> > + * @par This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a matching routine that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + */
> > +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
> > + *
> > + * @note This routine extends a buffer by increasing its size by ext
> > + * bytes.  It is logically equivalent to an odp_buffer_join() of a
> > + * buffer of size ext to the original buffer.  Upon successful return
> > + * the odp_buffer_size() routine would now return size+ext as the size
> > + * of the extended buffer.
> > + *
> > + * @par Note that the returned odp_buffer_t may not necessarily be the
> > + * same as the input odp_buffer_t.  The caller should use the returned
> > + * value when referencing the extended buffer instead of the original
> > + * in case they are different.  If the input buf contains user meta
> > + * data, then this data MUST be copied to the returned buffer if
> > + * needed by the API implementation.
> > + *
> > + * @par This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a matching routine that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + */
> > +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
> > + *
> > + * @note This routine allows an ODP buffer to be cloned in an
> > + * implementation-defined manner.  The application data contents of
> > + * the returned odp_buffer_t is an exact copy of the application data
> > + * of the input buffer.  The implementation MAY perform this operation
> > + * via reference counts, resegmentation, or any other technique it
> > + * wishes to employ. The cloned buffer is an element of the same
> > + * buffer pool as the input buf.  If the input buf contains user meta
> > + * data, then this data MUST be copied to the returned buffer by the
> > + * ODP implementation.
> > + *
> > + * @par This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a matching routine that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + */
> > +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
> > + * @param[in] pool buffer pool to contain the copied buffer
> > + *
> > + * @return         Handle of the copied buffer or ODP_BUFFER_INVALID
> > + *                 if the operation was not performed
> > + *
> > + * @note This routine allows an ODP buffer to be copied in an
> > + * implementation-defined manner to a specified buffer pool.  The
> > + * specified pool may or may not be different from the source buffer’s
> > + * pool.  The application data contents of the returned odp_buffer_t
> > + * is an exact separate copy of the application data of the input
> > + * buffer.  If the input buf contains user meta data, then this data
> > + * MUST be copied to the returned buffer by the ODP implementation.
> > + *
> > + * @par This routine is OPTIONAL.  An implementation that does not
> > + * support this function MUST provide a matching routine that simply
> > + * returns ODP_BUFFER_INVALID with an errno of
> > + * ODP_FUNCTION_NOT_AVAILABLE.
> > + */
> > +odp_buffer_t odp_buffer_copy(odp_buffer_t buf, odp_buffer_pool_t pool);
> > +
> > +
> > +/**
> >   * @}
> >   */
> >
> > diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h
> > b/platform/linux-generic/include/api/odp_buffer_pool.h
> > index d04abf0..cf67c2a 100644
> > --- a/platform/linux-generic/include/api/odp_buffer_pool.h
> > +++ b/platform/linux-generic/include/api/odp_buffer_pool.h
> > @@ -8,7 +8,44 @@
> >  /**
> >   * @file
> >   *
> > - * ODP buffer pool
> > + * @par Buffer Pools
> > + * Buffers are elements of buffer pools that represent an equivalence
> > + * class of buffer objects that are managed by a buffer pool manager.
> > + * ODP implementations MAY support buffer pool managers implemented in
> > + * hardware, software, or a combination of the two.  An ODP
> > + * implementation MUST support at least one buffer pool and MAY
> > + * support as many as it wishes.  The implementation MAY support one
> > + * or more predefined buffer pools that are not explicitly allocated
> > + * by an ODP application.  It SHOULD also support application creation
> > + * of buffer pools via the odp_buffer_pool_create() API, however it
> > + * MAY restrict the types of buffers that can be so created.
> > + *
> > + * @par
> > + * Buffer pools are represented by the abstract type odp_buffer_pool_t
> > + * that is returned by buffer pool creation and lookup/enumeration
> > + * routines.  Applications refer to buffer pools via a name of
> > + * implementation-defined maximum length that MUST be a minimummap of
> > + * eight characters in length and MAY be longer.  It is RECOMMENDED
> > + * that 32 character buffer pool names be supported to provide
> > + * application naming flexibility.  The supported maximum length of
> > + * buffer pool names is exposed via the ODP_BUFFER_POOL_NAME_LEN
> > + * predefined implementation limit.
> > + *
> > + * @par Segmented vs. Unsegmented Buffer Pools
> > + * By default, the buffers in
> > + * ODP buffer pools are logical buffers that support transparent
> > + * segmentation managed by ODP on behalf of the application and have a
> > + * rich set of associated semantics as described here.
> > + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> > + * for the pool should be regarded as a fixed buffer size for all pool
> > + * elements and that segmentation support is not needed for the pool.
> > + * This MAY result in greater efficiency on some implementations.  For
> > + * packet processing, a typical use of unsegmented pools would be in
> > + * conjunction with classification rules that sort packets into
> > + * different pools based on their lengths, thus ensuring that each
> > + * packet occupies a single segment within an appropriately-sized
> > + * buffer.
> > + *
> >   */
> >
> >  #ifndef ODP_BUFFER_POOL_H_
> > @@ -35,42 +72,217 @@ extern "C" {
> >  #define ODP_BUFFER_POOL_INVALID   0
> >
> >  /** ODP buffer pool */
> > -typedef uint32_t odp_buffer_pool_t;
> > +// typedef uint32_t odp_buffer_pool_t;
> > +
> > +/**
> > + * Buffer initialization routine prototype
> > + *
> > + * @note Routines of this type MAY be passed as part of the
> > + * odp_buffer_pool_init_t structure to be called whenever a
> > + * buffer is allocated to initialize the user meta data
> > + * associated with that buffer.
> > + */
> > +typedef void (odp_buf_init_t)(odp_buffer_t buf, void *buf_init_arg);
> > +
> > +/**
> > + * Buffer pool parameters
> > + *
> > + * @param[in] buf_num    Number of buffers that pool should contain
> > + * @param[in] buf_size   Size of application data in each buffer
> > + * @param[in] buf_type   Buffer type
> > + * @param[in] buf_opts   Buffer options
> > + */
> > +typedef struct odp_buffer_pool_param_t {
> > +        size_t buf_num;             /**< Number of buffers in this pool
> > */
> > +     size_t buf_size;            /**< Application data size of each
> > buffer */
> > +     odp_buffer_type_e buf_type; /**< Buffer type */
> > +     odp_buffer_opts_e buf_opts; /**< Buffer options */
> > +} odp_buffer_pool_param_t;          /**< Type of buffer pool parameter
> > struct */
> >
> > +/**
> > + * Buffer pool initialization parameters
> > + *
> > + * @param[in] udata_size     Size of the user meta data for each buffer
> > + * @param[in] buf_init       Function pointer to be called to
> > initialize the
> > + *                           user meta data for each buffer in the
> > pool.
> > + * @param[in] buf_init_arg   Argument to be passed to buf_init().
> > + *
> > + */
> > +typedef struct odp_buffer_pool_init_t {
> > +        size_t udata_size;         /**< Size of user meta dat for each
> > buffer */
> > +        odp_buf_init_t *buf_init;  /**< Buffer initialization routine
> > to use */
> > +        void *buf_init_arg;        /**< Argument to be passed to
> > buf_init() */
> > +} odp_buffer_pool_init_t;          /**< Type of buffer initialization
> > struct */
> >
> >  /**
> >   * Create a buffer pool
> >   *
> > - * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
> > chars)
> > - * @param base_addr Pool base address
> > - * @param size      Pool size in bytes
> > - * @param buf_size  Buffer size in bytes
> > - * @param buf_align Minimum buffer alignment
> > - * @param buf_type  Buffer type
> > + * @param[in] name           Name of the pool
> > + *                           (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
> > + *
> > + * @param[in] params         Parameters controlling the creation of
> > this
> > + *                           buffer pool
> > + *
> > + * @param[in] init_params    Parameters controlling the initialization
> > of
> > + *                           this buffer pool
> >   *
> > - * @return Buffer pool handle
> > + * @return Buffer pool handle or ODP_BUFFER_POOL_NULL with errno set
> > + *
> > + * @note This routine is used to create a buffer pool.  It takes three
> > + * arguments: the name of the pool to be created, a parameter
> > + * structure that controls the pool creation, and an optional
> > + * parameter that controls pool initialization.  In the creation
> > + * parameter structure, the application specifies the number of
> > + * buffers that the pool should contain as well as the application
> > + * data size for each buffer in the pool, the type of buffers it
> > + * should contain, and their associated options.  In the
> > + * initialization parameters, the application specifies the size of
> > + * the user meta data that should be associated with each buffer in
> > + * the pool.  If no user meta data is required, the init_params SHOULD
> > + * be specified as NULL.  If user meta data is requested, then
> > + * udata_size SHOULD be set to the requested size of the per-buffer
> > + * user meta data.  Also specified is the address of an
> > + * application-provided buffer initialization routine to be called for
> > + * each buffer in the pool at the time the pool is initialized, or
> > + * when the buffer is allocated.  If no application buffer
> > + * initialization is needed, then buf_init and buf_init_arg SHOULD be
> > + * set to NULL.
> >   */
> >  odp_buffer_pool_t odp_buffer_pool_create(const char *name,
> > -                                      void *base_addr, uint64_t size,
> > -                                      size_t buf_size, size_t buf_align,
> > -                                      int buf_type);
> > -
> > +                                         odp_buffer_pool_param_t
> > *params,
> > +                                         odp_buffer_pool_init_t
> > *init_params);
> >
> >  /**
> >   * Find a buffer pool by name
> >   *
> > - * @param name      Name of the pool
> > + * @param[in] name  Name of the pool
> >   *
> >   * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
> >   */
> >  odp_buffer_pool_t odp_buffer_pool_lookup(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] params     Output structure for pool parameters
> > + * @param[out] predef     Predefined (1) or Created (0).
> > + *
> > + * @return                Buffer pool handle
> > + *
> > + * @note This routine returns the abstract identifier
> > + * (odp_buffer_pool_t) of a buffer pool and is used to obtain the list
> > + * of all buffer pools.  In this manner an application can discover
> > + * both application created and implementation predefined buffer pools
> > + * and their characteristics.  The input specifies the previous buffer
> > + * pool identifier.  There are three use cases for this
> > + * routine:<br><br>
> > + *
> > + * -# If the input pool is ODP_BUFFER_POOL_START then the buffer pool
> > handle
> > + * returned is that of the first buffer pool in the list.
> > + * ODP_BUFFER_POOL_NULL MAY be used as a synonym for
> > ODP_BUFFER_POOL_START
> > + * if desired.<br><br>
> > + *
> > + * -# If the input pool is not the last element in the buffer pool list
> > + * then the buffer pool handle of the next buffer pool following  pool
> > is
> > + * returned.<br><br>
> > + *
> > + * -# If the input pool is the buffer pool handle of the last buffer
> > pool
> > + * in the list then ODP_BUFFER_POOL_NULL is returned.<br><br>
> > + *
> > + * Returned with the buffer pool handle is the name of the pool as
> > + * well as its dimensions, type of buffers it contains, and a flag
> > + * that says whether the pool is predefined or was created by the
> > + * application.  Note that the buf_size reported for a buffer pool is
> > + * simply the declared expected size of the buffers in the pool and
> > + * serves only to estimate the total amount of application data that
> > + * can be stored in the pool.  Actual sizes of individual buffers
> > + * within the pool are dynamic and variable since physical buffer
> > + * segments MAY be aggregated to create buffers of arbitrary size (up
> > + * to the pool memory limits).  Note that for predefined buffer pools,
> > + * some implementations MAY return the physical segment counts and
> > + * sizes used to construct the pool as output of this routine.
> > + */
> > +odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,
> > +                                       char *name, size_t *udata_size,
> > +                                       odp_buffer_pool_param_t *params,
> > +                                       int *predef);
> > +
> > +/**
> > + * Get the high/low watermarks for a buffer pool
> > + *
> > + * @param[in]  pool     Handle of the buffer pool
> > + * @param[out] high_wm  The high water mark of the designated buffer
> > pool
> > + * @param[out] low_wm   The low water mark of the designated buffer
> > pool
> > + *
> > + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> > + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> > + *                 are associated with this buffer pool.
> > + *
> > + * @note This routine gets the high/low watermarks associated with a
> > + * given buffer pool.  If the buffer pool does not have or support
> > + * watermarks then an error will be returned and both high_wm and
> > + * low_wm will be unchanged.
> > + *
> > + * @par
> > + * It is RECOMMENDED that buffer pools of all types support the setting
> > + * and getting of watermarks for use in flow control processing.
> > + * Watermarks are designed to trigger flow control actions based on
> > + * utilization levels of a buffer pool.  When the number of free
> > + * buffers in the buffer pool hits the configured low watermark for
> > + * the pool, the pool asserts a low watermark condition and an
> > + * implementation-defined action in response to this condition is
> > + * triggered.  Once in a low watermark state, the condition is
> > + * maintained until the number of free buffers reaches the configured
> > + * high watermark.  At this point the low watermark condition is
> > + * deasserted and normal pool processing resumes.  Having separate
> > + * high and low watermarks permits configurable hysteresis to avoid
> > + * jitter in handling transient buffer shortages in the pool.
> > + *
> > + * @par
> > + * In general, two types of actions are common.  The first is to
> > + * control Random Early Detection (RED) or Weighted RED (WRED)
> > + * processing for the pool, while the second is to control IEEE
> > + * 802.1Qbb priority-based flow control (PFC) processing for so-called
> > + * “lossless Ethernet” support.  The use of watermarks for flow
> > + * control processing is most often used for pools containing packets
> > + * and this is discussed in further detail in the Class of Service
> > + * (CoS) ODP Classification APIs.
> > + *
> > + */
> > +int odp_buffer_pool_watermarks(odp_buffer_pool_t pool,
> > +                               size_t *high_wm, size_t *low_wm);
> > +
> > +/**
> > + * Set the high/low watermarks for a buffer pool
> > + *
> > + * @param[in] pool      Handle of the buffer pool
> > + * @param[in] high_wm   The high water mark of the designated buffer
> > pool
> > + * @param[in] low_wm    The low water mark of the designated buffer
> > pool
> > + *
> > + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> > + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> > + *                 are associated with this buffer pool.
> > + *
> > + * @note This routine sets the high/low watermarks associated with a
> > + * specified buffer pool.  If the buffer pool does not support
> > + * watermarks then errno ODP_BUFFER_POOL_NO_WATERMARKS is set and no
> > + * function is performed.
> > + */
> > +int odp_buffer_pool_set_watermarks(odp_buffer_pool_t pool,
> > +                                   size_t high_wm, size_t low_wm);
> >
> >  /**
> >   * Print buffer pool info
> >   *
> > - * @param pool      Pool handle
> > + * @param[in] pool   Pool handle
> >   *
> > + * @note This is a diagnostic routine that prints statistics regarding
> > + * the specified buffer pool to the ODP LOG.  This routine is OPTIONAL
> > + * and if present its output is implementation-defined.
> >   */
> >  void odp_buffer_pool_print(odp_buffer_pool_t pool);
> >
> > --
> > 1.8.3.2
> >
> >
> > _______________________________________________
> > lng-odp mailing list
> > lng-odp@lists.linaro.org
> > http://lists.linaro.org/mailman/listinfo/lng-odp
>
Shmulik Ladkani Nov. 3, 2014, 1:36 p.m. UTC | #3
On Mon, 3 Nov 2014 05:42:52 -0600 Bill Fischofer <bill.fischofer@linaro.org> wrote:
> The reality is I don't believe we have any actual uses of
> ODP_BUFFER_TYPE_RAW at this point.

Well... it's part of the API... don't make such assumptions ;-)

(although I might just be mis-using it. I'll post a follow-up question)
Mike Holmes Nov. 3, 2014, 1:59 p.m. UTC | #4
On 2 November 2014 22:06, Bill Fischofer <bill.fischofer@linaro.org> wrote:

> RFC version of patches for new buffer .h files.  Includes all API changes
> from
> buffer design doc + extended notes.  Do not merge until corresponding code
> changes are posted.
>
> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
> ---
>  platform/linux-generic/include/api/odp_buffer.h    | 532
> ++++++++++++++++++++-
>  .../linux-generic/include/api/odp_buffer_pool.h    | 242 +++++++++-
>  2 files changed, 740 insertions(+), 34 deletions(-)
>
> diff --git a/platform/linux-generic/include/api/odp_buffer.h
> b/platform/linux-generic/include/api/odp_buffer.h
> index 289e0eb..9910d0e 100644
> --- a/platform/linux-generic/include/api/odp_buffer.h
> +++ b/platform/linux-generic/include/api/odp_buffer.h
> @@ -8,7 +8,88 @@
>  /**
>   * @file
>   *
> - * ODP buffer descriptor
> + * @par Buffer
> + * A buffer is an element of a buffer pool used for storing
> + * information.  Buffers are referenced by an abstract handle of type
>

You have two spaces after the full stop -multiple instance


> + * odp_buffer_t.  Buffers have associated buffer types that describe
> + * their intended use and the type of meta data that is associated
> + * with them.  Buffers of a specific type may be referenced for
> + * processing by cores or by offload engines.  Buffers are also
> + * transmitted via queues from one processing element to another.
> + *
> + * @par Buffer Types
> + * An ODP buffer type is identified by the
> + * odp_buffer_type_e enum.  It defines the semantics that are to be
> + * attached to the buffer and defines the type of meta data that is
> + * associated with it.  ODP implementations MUST support the following
> + * buffer types:<br><br>
> + *
> + * - ODP_BUFFER_TYPE_RAW<br>
>

Don't use raw HTML, use doxygen primitives, delete "<br>" multiple instances


> + * 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.<br><br>
>

One sentence per line as below for the paragraph above, this allow diff to
clearly show future updates cleanly - multiple instances

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.


> + *
> + * - ODP_BUFFER_TYPE_PACKET<br>
> + * This buffer type is suitable for receiving,
> + * processing, and transmitting network packet data.  Included in this
> + * type is a rich set of primitives for manipulating buffer aggregates
> + * and for storing system and user meta data.  APIs for this type of
> + * buffer are described here and in the ODP Packet Management Design
> + * document.<br><br>
> + *
> + * - ODP_BUFFER_TYPE_TIMEOUT<br>
> + * This buffer type is suitable for
> + * representing timer timeout events.  Does not support buffer
> + * aggregation but does support user meta data.  APIs for this type of
> + * buffer are described here and in the ODP Timer Management Design
> + * document.<br><br>
> + *
> + * - ODP_BUFFER_TYPE_ANY<br>
> + * A “universal” buffer type capable of
> + * storing information needed for any other buffer type.  It is not
> + * intended to be used directly, but exists for possible
> + * implementation convenience.
> + *
> + * @par Meta Data
> + * Meta Data is additional information relating to a
> + * buffer that is distinct from the application data normally held in
> + * the buffer.  Implementations MAY choose to implement meta data as
> + * contiguous with a buffer (e.g., in an implementation-managed prefix
> + * area of the buffer) or in a physically separate meta data area
> + * efficiently accessible by the implementation using the same
> + * identifier as the buffer itself.  ODP applications MUST NOT make
> + * assumptions about the addressability relationship between a buffer
> + * and its associated meta data, or between meta data items.
> + * Application use of meta data MUST only be via accessor functions.
> + *
> + * @par Note on OPTIONAL APIs
> + * Every conforming ODP implementation MUST
> + * provide implementations for each API described here.  if an API is
> + * designated as OPTIONAL, this means that it is acceptable for an
> + * implementation to do nothing except return
> + * ODP_FUNCTION_NOT_AVAILABLE in response to this call. Note that this
> + * may limit the range of ODP applications supported by a given
> + * implementation since applications needing the functionality of the
> + * optional API will likely choose to deploy on other ODP platforms.
> + *
> + * @par
> + * APIs are designated as OPTIONAL under two conditions:<br><br>
> + *
> + * -# The API is expected to be difficult to provide efficiently on all
> + *  platforms.<br><br>
> + * -# A significant number of ODP applications are expected to exist
> + *  that will not need or use this API.
> + *
> + * @par
> + * Under these circumstances, an API is designated as OPTIONAL to
> + * permit ODP implementations to be conformant while still expecting
> + * to be able to run a significant number of ODP applications.
> + *
>   */
>
>  #ifndef ODP_BUFFER_H_
> @@ -21,10 +102,9 @@ extern "C" {
>
>  #include <odp_std_types.h>
>
> -
>  /** @defgroup odp_buffer ODP BUFFER
> - *  Operations on a buffer.
> - *  @{
> + *
> + * @{
>   */
>
>  /**
> @@ -32,62 +112,476 @@ 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 pool
> + */
> +typedef uint32_t odp_buffer_pool_t;
> +
> +/**
> + * ODP buffer type
> + */
> +typedef enum odp_buffer_type {
> +       ODP_BUFER_TYPE_INVALID  = -1, /**< Buffer type invalid */
> +       ODP_BUFFER_TYPE_ANY     = 0,  /**< Buffer type 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
> + *
> + * @note 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.
> + *
> + * @par Segmented vs. Unsegmented Buffer Pools
> + * By default, the buffers
> + * in ODP buffer pools are logical buffers that support transparent
> + * segmentation managed by ODP on behalf of the application and have a
> + * rich set of associated semantics as described here.
> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> + * for the pool should be regarded as a fixed buffer size for all pool
> + * elements and that segmentation support is not needed for the pool.
> + * This MAY result in greater efficiency on some implementations.  For
> + * packet processing, a typical use of unsegmented pools would be in
> + * conjunction with classification rules that sort packets into
> + * different pools based on their lengths, thus ensuring that each
> + * packet occupies a single segment within an appropriately-sized
> + * buffer.
> + */
> + typedef enum odp_buffer_opts {
> +        ODP_BUFFER_OPTS_NONE,        /**< Default, no buffer options */
> +        ODP_BUFFER_OPTS_UNSEGMENTED, /**< Reqest this pool contain
> unsegmented
> +                                           buffers */
> + } odp_buffer_opts_e;
> +
> +/**
> + * Error returns
> + */
> +#define ODP_BUFFER_INVALID (odp_buffer_t)(-1)
>
>  /**
>   * Buffer start address
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf  Buffer handle
>   *
>   * @return Buffer start address
>   */
>  void *odp_buffer_addr(odp_buffer_t buf);
>

Can this return an error  ?


>  /**
> - * Buffer maximum data size
> + * Buffer application data size
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf  Buffer handle
>   *
> - * @return Buffer maximum data size
> + * @return Buffer application data size
> + *
> + * @note The size returned by this rouine is the size of the
> + * application data contained within the buffer and does not include
> + * any inplementation-defined overhead to support meta data, etc.  ODP
> + * does not define APIs for determining the amount of storage that is
> + * physically allocated by an implementation to support ODP buffers.
>   */
>  size_t odp_buffer_size(odp_buffer_t buf);
>
>
Can this return an error, also spelling int the note multiple instances



>  /**
>   * Buffer type
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
>   * @return Buffer type
>   */
> -int odp_buffer_type(odp_buffer_t buf);
> +odp_buffer_type_e odp_buffer_type(odp_buffer_t buf);
>

What if buf is invalid, error do we specify behaviour ?


>
> -#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 */
> +/**
> + * Get address and size of user meta data for 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);
>
>
Better to split the return - multiple instances
@retval Address of the user meta data for this buffer
@retval NULL if the buffer has no user meta data.


> +/**
> + * Get address of user meta data for 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.
> + *
> + * @note This is a "fastpath" version of odp_buffer_udata() since it
> + * omits returning the size of the user meta data area.  Callers are
> + * expected to know and honor this limit nonetheless.
> + */
> +void *odp_buffer_udata_addr(odp_buffer_t buf);
>
>  /**
>   * Tests if buffer is valid
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
>   * @return 1 if valid, otherwise 0
> + *
> + * @note Since buffer operations typically occur in fastpath sections
> + * of applications, by default most ODP APIs assume that valid buffer
> + * handles are passed to them and results are undefined if this
> + * assumption is not met.  This routine exists to enable an
> + * application to request explicit validation of a buffer handle. It
> + * is understood that the performance of this operation MAY vary
> + * considerably on a per-implementation basis.
>   */
>  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 then one segment, otherwise 0
> + *
> + * @note This routine behaves identically to the test
> + * odp_buffer_segment_count() > 1, but is potentially more efficient
> + * and represents the preferred method of determining a buffer's
> + * segmentation status.
> + */
> +int odp_buffer_is_segmented(odp_buffer_t buf);
> +
> +/**
>   * Print buffer metadata to STDOUT
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
> + * @note This routine is intended for diagnostic use and prints
> + * implementation-defined information concerning the buffer to the ODP
> + * LOG.  It's provision is OPTIONAL.
>   */
>  void odp_buffer_print(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);
>

What is buf id invalid ?


> +
> +/**
> + * 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 handle 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 handle for a buffer segment
> + *
> + * @param[in] buf    Buffer handle
> + * @param[in] seg    Segment identifier of the previous segment
> + *
> + * @return           Segment identifier of next segment or
> ODP_SEGMENT_INVALID
> + *
> + * @note This routine returns the identifier (odp_buffer_segment_t) of
> + * the next buffer segment in a buffer aggregate.  The input
> + * specifies the buffer and the previous segment identifier.  There are
> + * three use cases for this routine:
> + * @par
> + * -# If the input seg is ODP_SEGMENT_START then the segment identifier
> returned
> + * is that of the first segment in the buffer.  ODP_SEGMENT_NULL MAY be
> used
> + * as a synonym for ODP_SEGMENT_START for symmetry if desired.<br><br>
> + * -# If the input seg is not the last segment in the buffer then the
> + * segment handle of the next segment following seg is returned.<br><br>
> + * -# If the input seg is the segment identifier of the last segment in
> + * the buffer then ODP_SEGMENT_NULL is returned.
> + *
> + */
> +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
> +                                            odp_buffer_segment_t seg);
> +
> +/**
> + * Get addressability for a specified buffer segment
> + *
> + * @param[in] buf     Buffer handle
> + * @param[in] seg     Segment handle of the segment to be mapped
> + * @param[in] seglen  Returned number of bytes in this buffer segment
> + *                    available at the returned address
> + *
> + * @return            Segment start address or NULL
> + *
> + * @note This routine is used to obtain addressability to a segment within
> + * a buffer aggregate at a specified segment identifier.  The returned
> seglen
> + * indicates the number of bytes addressable at the returned address.
> + */
> +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
> + *
> + * @note This routine is used to unmap a buffer segment previously
> + *  mapped by odp_buffer_segment_map().  Following this call,
> + *  applications MUST NOT attempt to reference the segment via any
> + *  pointer returned from a previous odp_buffer_segment_map() call
> + *  referring to it.  It is intended to allow certain NUMA
> + *  architectures to better manage the coherency of mapped segments.
> + *  For non-NUMA architectures this routine will be a no-op.  Note
> + *  that implementations SHOULD implicitly unmap all buffer segments
> + *  whenever a buffer is added to a queue as this indicates that the
> + *  caller is relinquishing control of the buffer.
> + */
> +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
> + *
> + * @note This routine is used to obtain addressability to a segment
> + * within a buffer at a specified byte offset.  Note that because the
> + * offset is independent of any implementation-defined physical
> + * segmentation the returned seglen may be “short” and will range from
> + * 1 to whatever physical segment size is used by the underlying
> + * implementation.
> + */
> +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
> + *
> + * @note This routine is used to unmap a buffer segment previously
> + * mapped by odp_buffer_offset_map(). Following this call
> + * the application MUST NOT attempt to reference the segment via any
> + * pointer returned by a prior odp_buffer_offset_map() call relating
> + * to this offset.  It is intended to allow certain NUMA architectures
> + * to better manage the coherency of mapped segments.  For non-NUMA
> + * architectures this routine will be a no-op.  Note that
> + * implementations SHOULD implicitly unmap all buffer segments
> + * whenever a buffer is added to a queue as this indicates that the
> + * caller is relinquishing control of the buffer.
> + */
> +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);
> +
> +/**
> + * 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
> + *
> + * @note This routine splits a buffer into two buffers at the
> + * specified byte offset.  The odp_buffer_t returned by the function
> + * is the handle of the new buffer created at the split point.  If the
> + * original buffer was allocated from a buffer pool then the split is
> + * allocated from the same pool.  If the original buffer was size
> + * bytes in length then upon return the original buffer is of size
> + * offset while the split buffer is of size (size-offset).
> + *
> + * @par
> + * This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + *
> + * @par
> + * Upon return from this function, the system meta data for both
> + * buffers has been updated appropriately by the call since system
> + * meta data maintenance is the responsibility of the ODP
> + * implementation.  Any required updates to the user meta data is the
> + * responsibility of the caller.
> + */
> +odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset);
>

What about errors ?



> +
> +/**
> + * 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
> + *
> + * @note This routine joins two buffers into a single buffer.  Both
> + * buf1 and buf2 MUST be from the same buffer pool and the resulting
> + * joined buffer will be an element of that same pool.  The
> + * application MUST NOT assume that either buf1 or buf2 survive the
> + * join or that the returned joined buffer is contiguous with or
> + * otherwise related to the input buffers.  An implementation SHOULD
> + * free either or both input buffers if they are not reused as part of
> + * the construction of the returned joined buffer.  If the join cannot
> + * be performed (e.g., if the two input buffers are not from the same
> + * buffer pool, insufficient space in the target buffer pool, etc.)
> + * then ODP_BUFFER_INVALID SHOULD be returned to indicate that the
> + * operation could not be performed, and an appropriate errno set.  In
> + * such case the input buffers MUST NOT be freed as part of the failed
> + * join attempt and should be unchanged from their input values and
> + * content.
> + *
> + * @par The result of odp_buffer_join() is the logical concatenation
> + * of the two buffers using an implementation-defined buffer
> + * aggregation mechanism.  The application data contents of the
> + * returned buffer is identical to that of the two joined input
> + * buffers however certain associated meta data (e.g., information
> + * about the buffer size) will likely differ.
> + *
> + * @par If user meta data is present in the buffer pool containing the
> + * input buffers, then the user meta data associated with the returned
> + * buffer MUST be copied by this routine from the source buf1.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a routine matching that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t buf2);
>

@return text  != last text in this paragraph


> +
> +/**
> + * 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
> + *
> + * @note This routine discards bytes from the end of a buffer.  It is
> + * logically equivalent to a split followed by a free of the split
> + * portion of the input buffer.  The input offset must be less than or
> + * equal to the odp_buffer_size() of the input buffer.  Upon
> + * successful return the odp_buffer_size() routine would now return
> + * offset as the size of the trimmed buffer.  Note that the returned
> + * odp_buffer_t may not necessarily be the same as the input
> + * odp_buffer_t.  The caller should use the returned value when
> + * referencing the trimmed buffer instead of the original in case they
> + * are different.
> + *
> + * @par If the input buf contains user meta data, then this data MUST
> + * be copied to the returned buffer if needed by the API
> + * implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset);
>

@return text  != last text in this paragraph
errno should be its own @note ? - multiple instances


> +
> +/**
> + * 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
> + *
> + * @note This routine extends a buffer by increasing its size by ext
> + * bytes.  It is logically equivalent to an odp_buffer_join() of a
> + * buffer of size ext to the original buffer.  Upon successful return
> + * the odp_buffer_size() routine would now return size+ext as the size
> + * of the extended buffer.
> + *
> + * @par Note that the returned odp_buffer_t may not necessarily be the
> + * same as the input odp_buffer_t.  The caller should use the returned
> + * value when referencing the extended buffer instead of the original
> + * in case they are different.  If the input buf contains user meta
> + * data, then this data MUST be copied to the returned buffer if
> + * needed by the API implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +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
> + *
> + * @note This routine allows an ODP buffer to be cloned in an
> + * implementation-defined manner.  The application data contents of
> + * the returned odp_buffer_t is an exact copy of the application data
> + * of the input buffer.  The implementation MAY perform this operation
> + * via reference counts, resegmentation, or any other technique it
> + * wishes to employ. The cloned buffer is an element of the same
> + * buffer pool as the input buf.  If the input buf contains user meta
> + * data, then this data MUST be copied to the returned buffer by the
> + * ODP implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_clone(odp_buffer_t buf);
>

In general having looked at a few  I think the @return section needs to
hold all the possible return codes as ret vals with a description
@retval  needs to include   ODP_FUNCTION_NOT_AVAILABLE


> +
> +/**
> + * Copy a buffer, returning an exact copy of it
> + *
> + * @param[in] buf  buffer handle of buffer to copy
> + * @param[in] pool buffer pool to contain the copied buffer
> + *
> + * @return         Handle of the copied buffer or ODP_BUFFER_INVALID
> + *                 if the operation was not performed
> + *
> + * @note This routine allows an ODP buffer to be copied in an
> + * implementation-defined manner to a specified buffer pool.  The
> + * specified pool may or may not be different from the source buffer’s
> + * pool.  The application data contents of the returned odp_buffer_t
> + * is an exact separate copy of the application data of the input
> + * buffer.  If the input buf contains user meta data, then this data
> + * MUST be copied to the returned buffer by the ODP implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_copy(odp_buffer_t buf, odp_buffer_pool_t pool);
> +
> +
> +/**
>   * @}
>   */
>
> diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h
> b/platform/linux-generic/include/api/odp_buffer_pool.h
> index d04abf0..cf67c2a 100644
> --- a/platform/linux-generic/include/api/odp_buffer_pool.h
> +++ b/platform/linux-generic/include/api/odp_buffer_pool.h
> @@ -8,7 +8,44 @@
>  /**
>   * @file
>   *
> - * ODP buffer pool
> + * @par Buffer Pools
> + * Buffers are elements of buffer pools that represent an equivalence
> + * class of buffer objects that are managed by a buffer pool manager.
> + * ODP implementations MAY support buffer pool managers implemented in
> + * hardware, software, or a combination of the two.  An ODP
> + * implementation MUST support at least one buffer pool and MAY
> + * support as many as it wishes.  The implementation MAY support one
> + * or more predefined buffer pools that are not explicitly allocated
> + * by an ODP application.  It SHOULD also support application creation
> + * of buffer pools via the odp_buffer_pool_create() API, however it
> + * MAY restrict the types of buffers that can be so created.
> + *
> + * @par
> + * Buffer pools are represented by the abstract type odp_buffer_pool_t
> + * that is returned by buffer pool creation and lookup/enumeration
> + * routines.  Applications refer to buffer pools via a name of
> + * implementation-defined maximum length that MUST be a minimummap of
> + * eight characters in length and MAY be longer.  It is RECOMMENDED
> + * that 32 character buffer pool names be supported to provide
> + * application naming flexibility.  The supported maximum length of
> + * buffer pool names is exposed via the ODP_BUFFER_POOL_NAME_LEN
> + * predefined implementation limit.
> + *
> + * @par Segmented vs. Unsegmented Buffer Pools
> + * By default, the buffers in
> + * ODP buffer pools are logical buffers that support transparent
> + * segmentation managed by ODP on behalf of the application and have a
> + * rich set of associated semantics as described here.
> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> + * for the pool should be regarded as a fixed buffer size for all pool
> + * elements and that segmentation support is not needed for the pool.
> + * This MAY result in greater efficiency on some implementations.  For
> + * packet processing, a typical use of unsegmented pools would be in
> + * conjunction with classification rules that sort packets into
> + * different pools based on their lengths, thus ensuring that each
> + * packet occupies a single segment within an appropriately-sized
> + * buffer.
> + *
>   */
>
>  #ifndef ODP_BUFFER_POOL_H_
> @@ -35,42 +72,217 @@ extern "C" {
>  #define ODP_BUFFER_POOL_INVALID   0
>
>  /** ODP buffer pool */
> -typedef uint32_t odp_buffer_pool_t;
> +// typedef uint32_t odp_buffer_pool_t;
> +
> +/**
> + * Buffer initialization routine prototype
> + *
> + * @note Routines of this type MAY be passed as part of the
> + * odp_buffer_pool_init_t structure to be called whenever a
> + * buffer is allocated to initialize the user meta data
> + * associated with that buffer.
> + */
> +typedef void (odp_buf_init_t)(odp_buffer_t buf, void *buf_init_arg);
> +
> +/**
> + * Buffer pool parameters
> + *
> + * @param[in] buf_num    Number of buffers that pool should contain
> + * @param[in] buf_size   Size of application data in each buffer
> + * @param[in] buf_type   Buffer type
> + * @param[in] buf_opts   Buffer options
> + */
> +typedef struct odp_buffer_pool_param_t {
> +        size_t buf_num;             /**< Number of buffers in this pool */
> +       size_t buf_size;            /**< Application data size of each
> buffer */
> +       odp_buffer_type_e buf_type; /**< Buffer type */
> +       odp_buffer_opts_e buf_opts; /**< Buffer options */
> +} odp_buffer_pool_param_t;          /**< Type of buffer pool parameter
> struct */
>
> +/**
> + * Buffer pool initialization parameters
> + *
> + * @param[in] udata_size     Size of the user meta data for each buffer
> + * @param[in] buf_init       Function pointer to be called to initialize
> the
> + *                           user meta data for each buffer in the pool.
> + * @param[in] buf_init_arg   Argument to be passed to buf_init().
> + *
> + */
> +typedef struct odp_buffer_pool_init_t {
> +        size_t udata_size;         /**< Size of user meta dat for each
> buffer */
> +        odp_buf_init_t *buf_init;  /**< Buffer initialization routine to
> use */
> +        void *buf_init_arg;        /**< Argument to be passed to
> buf_init() */
> +} odp_buffer_pool_init_t;          /**< Type of buffer initialization
> struct */
>
>  /**
>   * Create a buffer pool
>   *
> - * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
> chars)
> - * @param base_addr Pool base address
> - * @param size      Pool size in bytes
> - * @param buf_size  Buffer size in bytes
> - * @param buf_align Minimum buffer alignment
> - * @param buf_type  Buffer type
> + * @param[in] name           Name of the pool
> + *                           (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
> + *
> + * @param[in] params         Parameters controlling the creation of this
> + *                           buffer pool
> + *
> + * @param[in] init_params    Parameters controlling the initialization of
> + *                           this buffer pool
>   *
> - * @return Buffer pool handle
> + * @return Buffer pool handle or ODP_BUFFER_POOL_NULL with errno set
> + *
> + * @note This routine is used to create a buffer pool.  It takes three
> + * arguments: the name of the pool to be created, a parameter
> + * structure that controls the pool creation, and an optional
> + * parameter that controls pool initialization.  In the creation
> + * parameter structure, the application specifies the number of
> + * buffers that the pool should contain as well as the application
> + * data size for each buffer in the pool, the type of buffers it
> + * should contain, and their associated options.  In the
> + * initialization parameters, the application specifies the size of
> + * the user meta data that should be associated with each buffer in
> + * the pool.  If no user meta data is required, the init_params SHOULD
> + * be specified as NULL.  If user meta data is requested, then
> + * udata_size SHOULD be set to the requested size of the per-buffer
> + * user meta data.  Also specified is the address of an
> + * application-provided buffer initialization routine to be called for
> + * each buffer in the pool at the time the pool is initialized, or
> + * when the buffer is allocated.  If no application buffer
> + * initialization is needed, then buf_init and buf_init_arg SHOULD be
> + * set to NULL.
>   */
>  odp_buffer_pool_t odp_buffer_pool_create(const char *name,
> -                                        void *base_addr, uint64_t size,
> -                                        size_t buf_size, size_t buf_align,
> -                                        int buf_type);
> -
> +                                         odp_buffer_pool_param_t *params,
> +                                         odp_buffer_pool_init_t
> *init_params);
>
>  /**
>   * Find a buffer pool by name
>   *
> - * @param name      Name of the pool
> + * @param[in] name  Name of the pool
>   *
>   * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
>   */
>  odp_buffer_pool_t odp_buffer_pool_lookup(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] params     Output structure for pool parameters
> + * @param[out] predef     Predefined (1) or Created (0).
> + *
> + * @return                Buffer pool handle
> + *
> + * @note This routine returns the abstract identifier
> + * (odp_buffer_pool_t) of a buffer pool and is used to obtain the list
> + * of all buffer pools.  In this manner an application can discover
> + * both application created and implementation predefined buffer pools
> + * and their characteristics.  The input specifies the previous buffer
> + * pool identifier.  There are three use cases for this
> + * routine:<br><br>
> + *
> + * -# If the input pool is ODP_BUFFER_POOL_START then the buffer pool
> handle
> + * returned is that of the first buffer pool in the list.
> + * ODP_BUFFER_POOL_NULL MAY be used as a synonym for ODP_BUFFER_POOL_START
> + * if desired.<br><br>
> + *
> + * -# If the input pool is not the last element in the buffer pool list
> + * then the buffer pool handle of the next buffer pool following  pool is
> + * returned.<br><br>
> + *
> + * -# If the input pool is the buffer pool handle of the last buffer pool
> + * in the list then ODP_BUFFER_POOL_NULL is returned.<br><br>
> + *
> + * Returned with the buffer pool handle is the name of the pool as
> + * well as its dimensions, type of buffers it contains, and a flag
> + * that says whether the pool is predefined or was created by the
> + * application.  Note that the buf_size reported for a buffer pool is
> + * simply the declared expected size of the buffers in the pool and
> + * serves only to estimate the total amount of application data that
> + * can be stored in the pool.  Actual sizes of individual buffers
> + * within the pool are dynamic and variable since physical buffer
> + * segments MAY be aggregated to create buffers of arbitrary size (up
> + * to the pool memory limits).  Note that for predefined buffer pools,
> + * some implementations MAY return the physical segment counts and
> + * sizes used to construct the pool as output of this routine.
> + */
> +odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,
> +                                       char *name, size_t *udata_size,
> +                                       odp_buffer_pool_param_t *params,
> +                                       int *predef);
> +
> +/**
> + * Get the high/low watermarks for a buffer pool
> + *
> + * @param[in]  pool     Handle of the buffer pool
> + * @param[out] high_wm  The high water mark of the designated buffer pool
> + * @param[out] low_wm   The low water mark of the designated buffer pool
> + *
> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> + *                 are associated with this buffer pool.
> + *
> + * @note This routine gets the high/low watermarks associated with a
> + * given buffer pool.  If the buffer pool does not have or support
> + * watermarks then an error will be returned and both high_wm and
> + * low_wm will be unchanged.
> + *
> + * @par
> + * It is RECOMMENDED that buffer pools of all types support the setting
> + * and getting of watermarks for use in flow control processing.
> + * Watermarks are designed to trigger flow control actions based on
> + * utilization levels of a buffer pool.  When the number of free
> + * buffers in the buffer pool hits the configured low watermark for
> + * the pool, the pool asserts a low watermark condition and an
> + * implementation-defined action in response to this condition is
> + * triggered.  Once in a low watermark state, the condition is
> + * maintained until the number of free buffers reaches the configured
> + * high watermark.  At this point the low watermark condition is
> + * deasserted and normal pool processing resumes.  Having separate
> + * high and low watermarks permits configurable hysteresis to avoid
> + * jitter in handling transient buffer shortages in the pool.
> + *
> + * @par
> + * In general, two types of actions are common.  The first is to
> + * control Random Early Detection (RED) or Weighted RED (WRED)
> + * processing for the pool, while the second is to control IEEE
> + * 802.1Qbb priority-based flow control (PFC) processing for so-called
> + * “lossless Ethernet” support.  The use of watermarks for flow
> + * control processing is most often used for pools containing packets
> + * and this is discussed in further detail in the Class of Service
> + * (CoS) ODP Classification APIs.
> + *
> + */
> +int odp_buffer_pool_watermarks(odp_buffer_pool_t pool,
> +                               size_t *high_wm, size_t *low_wm);
> +
> +/**
> + * Set the high/low watermarks for a buffer pool
> + *
> + * @param[in] pool      Handle of the buffer pool
> + * @param[in] high_wm   The high water mark of the designated buffer pool
> + * @param[in] low_wm    The low water mark of the designated buffer pool
> + *
> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> + *                 are associated with this buffer pool.
> + *
> + * @note This routine sets the high/low watermarks associated with a
> + * specified buffer pool.  If the buffer pool does not support
> + * watermarks then errno ODP_BUFFER_POOL_NO_WATERMARKS is set and no
> + * function is performed.
> + */
> +int odp_buffer_pool_set_watermarks(odp_buffer_pool_t pool,
> +                                   size_t high_wm, size_t low_wm);
>
>  /**
>   * Print buffer pool info
>   *
> - * @param pool      Pool handle
> + * @param[in] pool   Pool handle
>   *
> + * @note This is a diagnostic routine that prints statistics regarding
> + * the specified buffer pool to the ODP LOG.  This routine is OPTIONAL
> + * and if present its output is implementation-defined.
>   */
>  void odp_buffer_pool_print(odp_buffer_pool_t pool);
>
> --
> 1.8.3.2
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Bill Fischofer Nov. 3, 2014, 3:34 p.m. UTC | #5
That'a a reasonable suggestion.  The implementation can set errno to
indicate the specific reason for failure.

Bill

On Mon, Nov 3, 2014 at 9:30 AM, Gilad Ben Yossef <giladb@ezchip.com> wrote:

>
>
> A question regarding all the *_addr  type functions – since they may
> require a mapping to be put in place for some platforms, shouldn't all have
> some way to return an error indicating lack of resource to map - e.g.
> odp_buffer_addr() ?
>
>
>
> Specifically, for odp_buffer_udata(), odp_buffer_udata_addr() this means
> NULL may be return to indicate an error and not only that there is no user
> data.
>
>
>
> Gilad
>
>
>
>
>
> *Gilad Ben-Yossef*
>
> Software Architect
>
> EZchip Technologies Ltd.
>
> 37 Israel Pollak Ave, Kiryat Gat 82025 ,Israel
>
> Tel: +972-4-959-6666 ext. 576, Fax: +972-8-681-1483
> Mobile: +972-52-826-0388, US Mobile: +1-973-826-0388
>
> Email: giladb@ezchip.com, Web: http://www.ezchip.com
>
>
>
> *"Ethernet always wins."*
>
>         — Andy Bechtolsheim
>
>
>
> *From:* lng-odp-bounces@lists.linaro.org [mailto:
> lng-odp-bounces@lists.linaro.org] *On Behalf Of *Mike Holmes
> *Sent:* Monday, November 03, 2014 3:59 PM
> *To:* Bill Fischofer
> *Cc:* lng-odp
> *Subject:* Re: [lng-odp] [[RFC PATCH]] RFC for new buffer .h files
>
>
>
>
>
>
>
> On 2 November 2014 22:06, Bill Fischofer <bill.fischofer@linaro.org>
> wrote:
>
> RFC version of patches for new buffer .h files.  Includes all API changes
> from
> buffer design doc + extended notes.  Do not merge until corresponding code
> changes are posted.
>
> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
> ---
>  platform/linux-generic/include/api/odp_buffer.h    | 532
> ++++++++++++++++++++-
>  .../linux-generic/include/api/odp_buffer_pool.h    | 242 +++++++++-
>  2 files changed, 740 insertions(+), 34 deletions(-)
>
> diff --git a/platform/linux-generic/include/api/odp_buffer.h
> b/platform/linux-generic/include/api/odp_buffer.h
> index 289e0eb..9910d0e 100644
> --- a/platform/linux-generic/include/api/odp_buffer.h
> +++ b/platform/linux-generic/include/api/odp_buffer.h
> @@ -8,7 +8,88 @@
>  /**
>   * @file
>   *
> - * ODP buffer descriptor
> + * @par Buffer
> + * A buffer is an element of a buffer pool used for storing
> + * information.  Buffers are referenced by an abstract handle of type
>
>
>
> You have two spaces after the full stop -multiple instance
>
>
>
> + * odp_buffer_t.  Buffers have associated buffer types that describe
> + * their intended use and the type of meta data that is associated
> + * with them.  Buffers of a specific type may be referenced for
> + * processing by cores or by offload engines.  Buffers are also
> + * transmitted via queues from one processing element to another.
> + *
> + * @par Buffer Types
> + * An ODP buffer type is identified by the
> + * odp_buffer_type_e enum.  It defines the semantics that are to be
> + * attached to the buffer and defines the type of meta data that is
> + * associated with it.  ODP implementations MUST support the following
> + * buffer types:<br><br>
> + *
> + * - ODP_BUFFER_TYPE_RAW<br>
>
>
>
> Don't use raw HTML, use doxygen primitives, delete "<br>" multiple
> instances
>
>
>
> + * 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.<br><br>
>
>
>
> One sentence per line as below for the paragraph above, this allow diff to
> clearly show future updates cleanly - multiple instances
>
>
>
> 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.
>
>
>
> + *
> + * - ODP_BUFFER_TYPE_PACKET<br>
> + * This buffer type is suitable for receiving,
> + * processing, and transmitting network packet data.  Included in this
> + * type is a rich set of primitives for manipulating buffer aggregates
> + * and for storing system and user meta data.  APIs for this type of
> + * buffer are described here and in the ODP Packet Management Design
> + * document.<br><br>
> + *
> + * - ODP_BUFFER_TYPE_TIMEOUT<br>
> + * This buffer type is suitable for
> + * representing timer timeout events.  Does not support buffer
> + * aggregation but does support user meta data.  APIs for this type of
> + * buffer are described here and in the ODP Timer Management Design
> + * document.<br><br>
> + *
> + * - ODP_BUFFER_TYPE_ANY<br>
> + * A “universal” buffer type capable of
> + * storing information needed for any other buffer type.  It is not
> + * intended to be used directly, but exists for possible
> + * implementation convenience.
> + *
> + * @par Meta Data
> + * Meta Data is additional information relating to a
> + * buffer that is distinct from the application data normally held in
> + * the buffer.  Implementations MAY choose to implement meta data as
> + * contiguous with a buffer (e.g., in an implementation-managed prefix
> + * area of the buffer) or in a physically separate meta data area
> + * efficiently accessible by the implementation using the same
> + * identifier as the buffer itself.  ODP applications MUST NOT make
> + * assumptions about the addressability relationship between a buffer
> + * and its associated meta data, or between meta data items.
> + * Application use of meta data MUST only be via accessor functions.
> + *
> + * @par Note on OPTIONAL APIs
> + * Every conforming ODP implementation MUST
> + * provide implementations for each API described here.  if an API is
> + * designated as OPTIONAL, this means that it is acceptable for an
> + * implementation to do nothing except return
> + * ODP_FUNCTION_NOT_AVAILABLE in response to this call. Note that this
> + * may limit the range of ODP applications supported by a given
> + * implementation since applications needing the functionality of the
> + * optional API will likely choose to deploy on other ODP platforms.
> + *
> + * @par
> + * APIs are designated as OPTIONAL under two conditions:<br><br>
> + *
> + * -# The API is expected to be difficult to provide efficiently on all
> + *  platforms.<br><br>
> + * -# A significant number of ODP applications are expected to exist
> + *  that will not need or use this API.
> + *
> + * @par
> + * Under these circumstances, an API is designated as OPTIONAL to
> + * permit ODP implementations to be conformant while still expecting
> + * to be able to run a significant number of ODP applications.
> + *
>   */
>
>  #ifndef ODP_BUFFER_H_
> @@ -21,10 +102,9 @@ extern "C" {
>
>  #include <odp_std_types.h>
>
> -
>  /** @defgroup odp_buffer ODP BUFFER
> - *  Operations on a buffer.
> - *  @{
> + *
> + * @{
>   */
>
>  /**
> @@ -32,62 +112,476 @@ 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 pool
> + */
> +typedef uint32_t odp_buffer_pool_t;
> +
> +/**
> + * ODP buffer type
> + */
> +typedef enum odp_buffer_type {
> +       ODP_BUFER_TYPE_INVALID  = -1, /**< Buffer type invalid */
> +       ODP_BUFFER_TYPE_ANY     = 0,  /**< Buffer type 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
> + *
> + * @note 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.
> + *
> + * @par Segmented vs. Unsegmented Buffer Pools
> + * By default, the buffers
> + * in ODP buffer pools are logical buffers that support transparent
> + * segmentation managed by ODP on behalf of the application and have a
> + * rich set of associated semantics as described here.
> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> + * for the pool should be regarded as a fixed buffer size for all pool
> + * elements and that segmentation support is not needed for the pool.
> + * This MAY result in greater efficiency on some implementations.  For
> + * packet processing, a typical use of unsegmented pools would be in
> + * conjunction with classification rules that sort packets into
> + * different pools based on their lengths, thus ensuring that each
> + * packet occupies a single segment within an appropriately-sized
> + * buffer.
> + */
> + typedef enum odp_buffer_opts {
> +        ODP_BUFFER_OPTS_NONE,        /**< Default, no buffer options */
> +        ODP_BUFFER_OPTS_UNSEGMENTED, /**< Reqest this pool contain
> unsegmented
> +                                           buffers */
> + } odp_buffer_opts_e;
> +
> +/**
> + * Error returns
> + */
> +#define ODP_BUFFER_INVALID (odp_buffer_t)(-1)
>
>  /**
>   * Buffer start address
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf  Buffer handle
>   *
>   * @return Buffer start address
>   */
>  void *odp_buffer_addr(odp_buffer_t buf);
>
>
>
> Can this return an error  ?
>
>
>
>
>  /**
> - * Buffer maximum data size
> + * Buffer application data size
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf  Buffer handle
>   *
> - * @return Buffer maximum data size
> + * @return Buffer application data size
> + *
> + * @note The size returned by this rouine is the size of the
> + * application data contained within the buffer and does not include
> + * any inplementation-defined overhead to support meta data, etc.  ODP
> + * does not define APIs for determining the amount of storage that is
> + * physically allocated by an implementation to support ODP buffers.
>   */
>  size_t odp_buffer_size(odp_buffer_t buf);
>
>
>
> Can this return an error, also spelling int the note multiple instances
>
>
>
>
>
>  /**
>   * Buffer type
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
>   * @return Buffer type
>   */
> -int odp_buffer_type(odp_buffer_t buf);
> +odp_buffer_type_e odp_buffer_type(odp_buffer_t buf);
>
>
>
> What if buf is invalid, error do we specify behaviour ?
>
>
>
>
> -#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 */
> +/**
> + * Get address and size of user meta data for 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);
>
>
>
> Better to split the return - multiple instances
>
> @retval Address of the user meta data for this buffer
>
> @retval NULL if the buffer has no user meta data.
>
>
>
> +/**
> + * Get address of user meta data for 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.
> + *
> + * @note This is a "fastpath" version of odp_buffer_udata() since it
> + * omits returning the size of the user meta data area.  Callers are
> + * expected to know and honor this limit nonetheless.
> + */
> +void *odp_buffer_udata_addr(odp_buffer_t buf);
>
>  /**
>   * Tests if buffer is valid
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
>   * @return 1 if valid, otherwise 0
> + *
> + * @note Since buffer operations typically occur in fastpath sections
> + * of applications, by default most ODP APIs assume that valid buffer
> + * handles are passed to them and results are undefined if this
> + * assumption is not met.  This routine exists to enable an
> + * application to request explicit validation of a buffer handle. It
> + * is understood that the performance of this operation MAY vary
> + * considerably on a per-implementation basis.
>   */
>  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 then one segment, otherwise 0
> + *
> + * @note This routine behaves identically to the test
> + * odp_buffer_segment_count() > 1, but is potentially more efficient
> + * and represents the preferred method of determining a buffer's
> + * segmentation status.
> + */
> +int odp_buffer_is_segmented(odp_buffer_t buf);
> +
> +/**
>   * Print buffer metadata to STDOUT
>   *
> - * @param buf      Buffer handle
> + * @param[in] buf    Buffer handle
>   *
> + * @note This routine is intended for diagnostic use and prints
> + * implementation-defined information concerning the buffer to the ODP
> + * LOG.  It's provision is OPTIONAL.
>   */
>  void odp_buffer_print(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);
>
>
>
> What is buf id invalid ?
>
>
>
> +
> +/**
> + * 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 handle 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 handle for a buffer segment
> + *
> + * @param[in] buf    Buffer handle
> + * @param[in] seg    Segment identifier of the previous segment
> + *
> + * @return           Segment identifier of next segment or
> ODP_SEGMENT_INVALID
> + *
> + * @note This routine returns the identifier (odp_buffer_segment_t) of
> + * the next buffer segment in a buffer aggregate.  The input
> + * specifies the buffer and the previous segment identifier.  There are
> + * three use cases for this routine:
> + * @par
> + * -# If the input seg is ODP_SEGMENT_START then the segment identifier
> returned
> + * is that of the first segment in the buffer.  ODP_SEGMENT_NULL MAY be
> used
> + * as a synonym for ODP_SEGMENT_START for symmetry if desired.<br><br>
> + * -# If the input seg is not the last segment in the buffer then the
> + * segment handle of the next segment following seg is returned.<br><br>
> + * -# If the input seg is the segment identifier of the last segment in
> + * the buffer then ODP_SEGMENT_NULL is returned.
> + *
> + */
> +odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
> +                                            odp_buffer_segment_t seg);
> +
> +/**
> + * Get addressability for a specified buffer segment
> + *
> + * @param[in] buf     Buffer handle
> + * @param[in] seg     Segment handle of the segment to be mapped
> + * @param[in] seglen  Returned number of bytes in this buffer segment
> + *                    available at the returned address
> + *
> + * @return            Segment start address or NULL
> + *
> + * @note This routine is used to obtain addressability to a segment within
> + * a buffer aggregate at a specified segment identifier.  The returned
> seglen
> + * indicates the number of bytes addressable at the returned address.
> + */
> +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
> + *
> + * @note This routine is used to unmap a buffer segment previously
> + *  mapped by odp_buffer_segment_map().  Following this call,
> + *  applications MUST NOT attempt to reference the segment via any
> + *  pointer returned from a previous odp_buffer_segment_map() call
> + *  referring to it.  It is intended to allow certain NUMA
> + *  architectures to better manage the coherency of mapped segments.
> + *  For non-NUMA architectures this routine will be a no-op.  Note
> + *  that implementations SHOULD implicitly unmap all buffer segments
> + *  whenever a buffer is added to a queue as this indicates that the
> + *  caller is relinquishing control of the buffer.
> + */
> +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
> + *
> + * @note This routine is used to obtain addressability to a segment
> + * within a buffer at a specified byte offset.  Note that because the
> + * offset is independent of any implementation-defined physical
> + * segmentation the returned seglen may be “short” and will range from
> + * 1 to whatever physical segment size is used by the underlying
> + * implementation.
> + */
> +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
> + *
> + * @note This routine is used to unmap a buffer segment previously
> + * mapped by odp_buffer_offset_map(). Following this call
> + * the application MUST NOT attempt to reference the segment via any
> + * pointer returned by a prior odp_buffer_offset_map() call relating
> + * to this offset.  It is intended to allow certain NUMA architectures
> + * to better manage the coherency of mapped segments.  For non-NUMA
> + * architectures this routine will be a no-op.  Note that
> + * implementations SHOULD implicitly unmap all buffer segments
> + * whenever a buffer is added to a queue as this indicates that the
> + * caller is relinquishing control of the buffer.
> + */
> +void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);
> +
> +/**
> + * 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
> + *
> + * @note This routine splits a buffer into two buffers at the
> + * specified byte offset.  The odp_buffer_t returned by the function
> + * is the handle of the new buffer created at the split point.  If the
> + * original buffer was allocated from a buffer pool then the split is
> + * allocated from the same pool.  If the original buffer was size
> + * bytes in length then upon return the original buffer is of size
> + * offset while the split buffer is of size (size-offset).
> + *
> + * @par
> + * This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + *
> + * @par
> + * Upon return from this function, the system meta data for both
> + * buffers has been updated appropriately by the call since system
> + * meta data maintenance is the responsibility of the ODP
> + * implementation.  Any required updates to the user meta data is the
> + * responsibility of the caller.
> + */
> +odp_buffer_t odp_buffer_split(odp_buffer_t buf, size_t offset);
>
>
>
> What about errors ?
>
>
>
>
>
> +
> +/**
> + * 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
> + *
> + * @note This routine joins two buffers into a single buffer.  Both
> + * buf1 and buf2 MUST be from the same buffer pool and the resulting
> + * joined buffer will be an element of that same pool.  The
> + * application MUST NOT assume that either buf1 or buf2 survive the
> + * join or that the returned joined buffer is contiguous with or
> + * otherwise related to the input buffers.  An implementation SHOULD
> + * free either or both input buffers if they are not reused as part of
> + * the construction of the returned joined buffer.  If the join cannot
> + * be performed (e.g., if the two input buffers are not from the same
> + * buffer pool, insufficient space in the target buffer pool, etc.)
> + * then ODP_BUFFER_INVALID SHOULD be returned to indicate that the
> + * operation could not be performed, and an appropriate errno set.  In
> + * such case the input buffers MUST NOT be freed as part of the failed
> + * join attempt and should be unchanged from their input values and
> + * content.
> + *
> + * @par The result of odp_buffer_join() is the logical concatenation
> + * of the two buffers using an implementation-defined buffer
> + * aggregation mechanism.  The application data contents of the
> + * returned buffer is identical to that of the two joined input
> + * buffers however certain associated meta data (e.g., information
> + * about the buffer size) will likely differ.
> + *
> + * @par If user meta data is present in the buffer pool containing the
> + * input buffers, then the user meta data associated with the returned
> + * buffer MUST be copied by this routine from the source buf1.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a routine matching that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_join(odp_buffer_t buf1, odp_buffer_t buf2);
>
>
>
> @return text  != last text in this paragraph
>
>
>
> +
> +/**
> + * 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
> + *
> + * @note This routine discards bytes from the end of a buffer.  It is
> + * logically equivalent to a split followed by a free of the split
> + * portion of the input buffer.  The input offset must be less than or
> + * equal to the odp_buffer_size() of the input buffer.  Upon
> + * successful return the odp_buffer_size() routine would now return
> + * offset as the size of the trimmed buffer.  Note that the returned
> + * odp_buffer_t may not necessarily be the same as the input
> + * odp_buffer_t.  The caller should use the returned value when
> + * referencing the trimmed buffer instead of the original in case they
> + * are different.
> + *
> + * @par If the input buf contains user meta data, then this data MUST
> + * be copied to the returned buffer if needed by the API
> + * implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_trim(odp_buffer_t buf, size_t offset);
>
>
>
> @return text  != last text in this paragraph
>
> errno should be its own @note ? - multiple instances
>
>
>
> +
> +/**
> + * 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
> + *
> + * @note This routine extends a buffer by increasing its size by ext
> + * bytes.  It is logically equivalent to an odp_buffer_join() of a
> + * buffer of size ext to the original buffer.  Upon successful return
> + * the odp_buffer_size() routine would now return size+ext as the size
> + * of the extended buffer.
> + *
> + * @par Note that the returned odp_buffer_t may not necessarily be the
> + * same as the input odp_buffer_t.  The caller should use the returned
> + * value when referencing the extended buffer instead of the original
> + * in case they are different.  If the input buf contains user meta
> + * data, then this data MUST be copied to the returned buffer if
> + * needed by the API implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +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
> + *
> + * @note This routine allows an ODP buffer to be cloned in an
> + * implementation-defined manner.  The application data contents of
> + * the returned odp_buffer_t is an exact copy of the application data
> + * of the input buffer.  The implementation MAY perform this operation
> + * via reference counts, resegmentation, or any other technique it
> + * wishes to employ. The cloned buffer is an element of the same
> + * buffer pool as the input buf.  If the input buf contains user meta
> + * data, then this data MUST be copied to the returned buffer by the
> + * ODP implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_clone(odp_buffer_t buf);
>
>
>
> In general having looked at a few  I think the @return section needs to
> hold all the possible return codes as ret vals with a description
>
> @retval  needs to include   ODP_FUNCTION_NOT_AVAILABLE
>
>
>
> +
> +/**
> + * Copy a buffer, returning an exact copy of it
> + *
> + * @param[in] buf  buffer handle of buffer to copy
> + * @param[in] pool buffer pool to contain the copied buffer
> + *
> + * @return         Handle of the copied buffer or ODP_BUFFER_INVALID
> + *                 if the operation was not performed
> + *
> + * @note This routine allows an ODP buffer to be copied in an
> + * implementation-defined manner to a specified buffer pool.  The
> + * specified pool may or may not be different from the source buffer’s
> + * pool.  The application data contents of the returned odp_buffer_t
> + * is an exact separate copy of the application data of the input
> + * buffer.  If the input buf contains user meta data, then this data
> + * MUST be copied to the returned buffer by the ODP implementation.
> + *
> + * @par This routine is OPTIONAL.  An implementation that does not
> + * support this function MUST provide a matching routine that simply
> + * returns ODP_BUFFER_INVALID with an errno of
> + * ODP_FUNCTION_NOT_AVAILABLE.
> + */
> +odp_buffer_t odp_buffer_copy(odp_buffer_t buf, odp_buffer_pool_t pool);
> +
> +
> +/**
>   * @}
>   */
>
> diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h
> b/platform/linux-generic/include/api/odp_buffer_pool.h
> index d04abf0..cf67c2a 100644
> --- a/platform/linux-generic/include/api/odp_buffer_pool.h
> +++ b/platform/linux-generic/include/api/odp_buffer_pool.h
> @@ -8,7 +8,44 @@
>  /**
>   * @file
>   *
> - * ODP buffer pool
> + * @par Buffer Pools
> + * Buffers are elements of buffer pools that represent an equivalence
> + * class of buffer objects that are managed by a buffer pool manager.
> + * ODP implementations MAY support buffer pool managers implemented in
> + * hardware, software, or a combination of the two.  An ODP
> + * implementation MUST support at least one buffer pool and MAY
> + * support as many as it wishes.  The implementation MAY support one
> + * or more predefined buffer pools that are not explicitly allocated
> + * by an ODP application.  It SHOULD also support application creation
> + * of buffer pools via the odp_buffer_pool_create() API, however it
> + * MAY restrict the types of buffers that can be so created.
> + *
> + * @par
> + * Buffer pools are represented by the abstract type odp_buffer_pool_t
> + * that is returned by buffer pool creation and lookup/enumeration
> + * routines.  Applications refer to buffer pools via a name of
> + * implementation-defined maximum length that MUST be a minimummap of
> + * eight characters in length and MAY be longer.  It is RECOMMENDED
> + * that 32 character buffer pool names be supported to provide
> + * application naming flexibility.  The supported maximum length of
> + * buffer pool names is exposed via the ODP_BUFFER_POOL_NAME_LEN
> + * predefined implementation limit.
> + *
> + * @par Segmented vs. Unsegmented Buffer Pools
> + * By default, the buffers in
> + * ODP buffer pools are logical buffers that support transparent
> + * segmentation managed by ODP on behalf of the application and have a
> + * rich set of associated semantics as described here.
> + * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
> + * for the pool should be regarded as a fixed buffer size for all pool
> + * elements and that segmentation support is not needed for the pool.
> + * This MAY result in greater efficiency on some implementations.  For
> + * packet processing, a typical use of unsegmented pools would be in
> + * conjunction with classification rules that sort packets into
> + * different pools based on their lengths, thus ensuring that each
> + * packet occupies a single segment within an appropriately-sized
> + * buffer.
> + *
>   */
>
>  #ifndef ODP_BUFFER_POOL_H_
> @@ -35,42 +72,217 @@ extern "C" {
>  #define ODP_BUFFER_POOL_INVALID   0
>
>  /** ODP buffer pool */
> -typedef uint32_t odp_buffer_pool_t;
> +// typedef uint32_t odp_buffer_pool_t;
> +
> +/**
> + * Buffer initialization routine prototype
> + *
> + * @note Routines of this type MAY be passed as part of the
> + * odp_buffer_pool_init_t structure to be called whenever a
> + * buffer is allocated to initialize the user meta data
> + * associated with that buffer.
> + */
> +typedef void (odp_buf_init_t)(odp_buffer_t buf, void *buf_init_arg);
> +
> +/**
> + * Buffer pool parameters
> + *
> + * @param[in] buf_num    Number of buffers that pool should contain
> + * @param[in] buf_size   Size of application data in each buffer
> + * @param[in] buf_type   Buffer type
> + * @param[in] buf_opts   Buffer options
> + */
> +typedef struct odp_buffer_pool_param_t {
> +        size_t buf_num;             /**< Number of buffers in this pool */
> +       size_t buf_size;            /**< Application data size of each
> buffer */
> +       odp_buffer_type_e buf_type; /**< Buffer type */
> +       odp_buffer_opts_e buf_opts; /**< Buffer options */
> +} odp_buffer_pool_param_t;          /**< Type of buffer pool parameter
> struct */
>
> +/**
> + * Buffer pool initialization parameters
> + *
> + * @param[in] udata_size     Size of the user meta data for each buffer
> + * @param[in] buf_init       Function pointer to be called to initialize
> the
> + *                           user meta data for each buffer in the pool.
> + * @param[in] buf_init_arg   Argument to be passed to buf_init().
> + *
> + */
> +typedef struct odp_buffer_pool_init_t {
> +        size_t udata_size;         /**< Size of user meta dat for each
> buffer */
> +        odp_buf_init_t *buf_init;  /**< Buffer initialization routine to
> use */
> +        void *buf_init_arg;        /**< Argument to be passed to
> buf_init() */
> +} odp_buffer_pool_init_t;          /**< Type of buffer initialization
> struct */
>
>  /**
>   * Create a buffer pool
>   *
> - * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1
> chars)
> - * @param base_addr Pool base address
> - * @param size      Pool size in bytes
> - * @param buf_size  Buffer size in bytes
> - * @param buf_align Minimum buffer alignment
> - * @param buf_type  Buffer type
> + * @param[in] name           Name of the pool
> + *                           (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
> + *
> + * @param[in] params         Parameters controlling the creation of this
> + *                           buffer pool
> + *
> + * @param[in] init_params    Parameters controlling the initialization of
> + *                           this buffer pool
>   *
> - * @return Buffer pool handle
> + * @return Buffer pool handle or ODP_BUFFER_POOL_NULL with errno set
> + *
> + * @note This routine is used to create a buffer pool.  It takes three
> + * arguments: the name of the pool to be created, a parameter
> + * structure that controls the pool creation, and an optional
> + * parameter that controls pool initialization.  In the creation
> + * parameter structure, the application specifies the number of
> + * buffers that the pool should contain as well as the application
> + * data size for each buffer in the pool, the type of buffers it
> + * should contain, and their associated options.  In the
> + * initialization parameters, the application specifies the size of
> + * the user meta data that should be associated with each buffer in
> + * the pool.  If no user meta data is required, the init_params SHOULD
> + * be specified as NULL.  If user meta data is requested, then
> + * udata_size SHOULD be set to the requested size of the per-buffer
> + * user meta data.  Also specified is the address of an
> + * application-provided buffer initialization routine to be called for
> + * each buffer in the pool at the time the pool is initialized, or
> + * when the buffer is allocated.  If no application buffer
> + * initialization is needed, then buf_init and buf_init_arg SHOULD be
> + * set to NULL.
>   */
>  odp_buffer_pool_t odp_buffer_pool_create(const char *name,
> -                                        void *base_addr, uint64_t size,
> -                                        size_t buf_size, size_t buf_align,
> -                                        int buf_type);
> -
> +                                         odp_buffer_pool_param_t *params,
> +                                         odp_buffer_pool_init_t
> *init_params);
>
>  /**
>   * Find a buffer pool by name
>   *
> - * @param name      Name of the pool
> + * @param[in] name  Name of the pool
>   *
>   * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
>   */
>  odp_buffer_pool_t odp_buffer_pool_lookup(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] params     Output structure for pool parameters
> + * @param[out] predef     Predefined (1) or Created (0).
> + *
> + * @return                Buffer pool handle
> + *
> + * @note This routine returns the abstract identifier
> + * (odp_buffer_pool_t) of a buffer pool and is used to obtain the list
> + * of all buffer pools.  In this manner an application can discover
> + * both application created and implementation predefined buffer pools
> + * and their characteristics.  The input specifies the previous buffer
> + * pool identifier.  There are three use cases for this
> + * routine:<br><br>
> + *
> + * -# If the input pool is ODP_BUFFER_POOL_START then the buffer pool
> handle
> + * returned is that of the first buffer pool in the list.
> + * ODP_BUFFER_POOL_NULL MAY be used as a synonym for ODP_BUFFER_POOL_START
> + * if desired.<br><br>
> + *
> + * -# If the input pool is not the last element in the buffer pool list
> + * then the buffer pool handle of the next buffer pool following  pool is
> + * returned.<br><br>
> + *
> + * -# If the input pool is the buffer pool handle of the last buffer pool
> + * in the list then ODP_BUFFER_POOL_NULL is returned.<br><br>
> + *
> + * Returned with the buffer pool handle is the name of the pool as
> + * well as its dimensions, type of buffers it contains, and a flag
> + * that says whether the pool is predefined or was created by the
> + * application.  Note that the buf_size reported for a buffer pool is
> + * simply the declared expected size of the buffers in the pool and
> + * serves only to estimate the total amount of application data that
> + * can be stored in the pool.  Actual sizes of individual buffers
> + * within the pool are dynamic and variable since physical buffer
> + * segments MAY be aggregated to create buffers of arbitrary size (up
> + * to the pool memory limits).  Note that for predefined buffer pools,
> + * some implementations MAY return the physical segment counts and
> + * sizes used to construct the pool as output of this routine.
> + */
> +odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,
> +                                       char *name, size_t *udata_size,
> +                                       odp_buffer_pool_param_t *params,
> +                                       int *predef);
> +
> +/**
> + * Get the high/low watermarks for a buffer pool
> + *
> + * @param[in]  pool     Handle of the buffer pool
> + * @param[out] high_wm  The high water mark of the designated buffer pool
> + * @param[out] low_wm   The low water mark of the designated buffer pool
> + *
> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> + *                 are associated with this buffer pool.
> + *
> + * @note This routine gets the high/low watermarks associated with a
> + * given buffer pool.  If the buffer pool does not have or support
> + * watermarks then an error will be returned and both high_wm and
> + * low_wm will be unchanged.
> + *
> + * @par
> + * It is RECOMMENDED that buffer pools of all types support the setting
> + * and getting of watermarks for use in flow control processing.
> + * Watermarks are designed to trigger flow control actions based on
> + * utilization levels of a buffer pool.  When the number of free
> + * buffers in the buffer pool hits the configured low watermark for
> + * the pool, the pool asserts a low watermark condition and an
> + * implementation-defined action in response to this condition is
> + * triggered.  Once in a low watermark state, the condition is
> + * maintained until the number of free buffers reaches the configured
> + * high watermark.  At this point the low watermark condition is
> + * deasserted and normal pool processing resumes.  Having separate
> + * high and low watermarks permits configurable hysteresis to avoid
> + * jitter in handling transient buffer shortages in the pool.
> + *
> + * @par
> + * In general, two types of actions are common.  The first is to
> + * control Random Early Detection (RED) or Weighted RED (WRED)
> + * processing for the pool, while the second is to control IEEE
> + * 802.1Qbb priority-based flow control (PFC) processing for so-called
> + * “lossless Ethernet” support.  The use of watermarks for flow
> + * control processing is most often used for pools containing packets
> + * and this is discussed in further detail in the Class of Service
> + * (CoS) ODP Classification APIs.
> + *
> + */
> +int odp_buffer_pool_watermarks(odp_buffer_pool_t pool,
> +                               size_t *high_wm, size_t *low_wm);
> +
> +/**
> + * Set the high/low watermarks for a buffer pool
> + *
> + * @param[in] pool      Handle of the buffer pool
> + * @param[in] high_wm   The high water mark of the designated buffer pool
> + * @param[in] low_wm    The low water mark of the designated buffer pool
> + *
> + * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
> + *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
> + *                 are associated with this buffer pool.
> + *
> + * @note This routine sets the high/low watermarks associated with a
> + * specified buffer pool.  If the buffer pool does not support
> + * watermarks then errno ODP_BUFFER_POOL_NO_WATERMARKS is set and no
> + * function is performed.
> + */
> +int odp_buffer_pool_set_watermarks(odp_buffer_pool_t pool,
> +                                   size_t high_wm, size_t low_wm);
>
>  /**
>   * Print buffer pool info
>   *
> - * @param pool      Pool handle
> + * @param[in] pool   Pool handle
>   *
> + * @note This is a diagnostic routine that prints statistics regarding
> + * the specified buffer pool to the ODP LOG.  This routine is OPTIONAL
> + * and if present its output is implementation-defined.
>   */
>  void odp_buffer_pool_print(odp_buffer_pool_t pool);
>
> --
> 1.8.3.2
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
>
>
>
>
> --
>
> *Mike Holmes*
>
> Linaro  Sr Technical Manager
>
> LNG - ODP
>
diff mbox

Patch

diff --git a/platform/linux-generic/include/api/odp_buffer.h b/platform/linux-generic/include/api/odp_buffer.h
index 289e0eb..9910d0e 100644
--- a/platform/linux-generic/include/api/odp_buffer.h
+++ b/platform/linux-generic/include/api/odp_buffer.h
@@ -8,7 +8,88 @@ 
 /**
  * @file
  *
- * ODP buffer descriptor
+ * @par Buffer
+ * A buffer is an element of a buffer pool used for storing
+ * information.  Buffers are referenced by an abstract handle of type
+ * odp_buffer_t.  Buffers have associated buffer types that describe
+ * their intended use and the type of meta data that is associated
+ * with them.  Buffers of a specific type may be referenced for
+ * processing by cores or by offload engines.  Buffers are also
+ * transmitted via queues from one processing element to another.
+ *
+ * @par Buffer Types
+ * An ODP buffer type is identified by the
+ * odp_buffer_type_e enum.  It defines the semantics that are to be
+ * attached to the buffer and defines the type of meta data that is
+ * associated with it.  ODP implementations MUST support the following
+ * buffer types:<br><br>
+ *
+ * - ODP_BUFFER_TYPE_RAW<br>
+ * 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.<br><br>
+ *
+ * - ODP_BUFFER_TYPE_PACKET<br>
+ * This buffer type is suitable for receiving,
+ * processing, and transmitting network packet data.  Included in this
+ * type is a rich set of primitives for manipulating buffer aggregates
+ * and for storing system and user meta data.  APIs for this type of
+ * buffer are described here and in the ODP Packet Management Design
+ * document.<br><br>
+ *
+ * - ODP_BUFFER_TYPE_TIMEOUT<br>
+ * This buffer type is suitable for
+ * representing timer timeout events.  Does not support buffer
+ * aggregation but does support user meta data.  APIs for this type of
+ * buffer are described here and in the ODP Timer Management Design
+ * document.<br><br>
+ *
+ * - ODP_BUFFER_TYPE_ANY<br>
+ * A “universal” buffer type capable of
+ * storing information needed for any other buffer type.  It is not
+ * intended to be used directly, but exists for possible
+ * implementation convenience.
+ *
+ * @par Meta Data
+ * Meta Data is additional information relating to a
+ * buffer that is distinct from the application data normally held in
+ * the buffer.  Implementations MAY choose to implement meta data as
+ * contiguous with a buffer (e.g., in an implementation-managed prefix
+ * area of the buffer) or in a physically separate meta data area
+ * efficiently accessible by the implementation using the same
+ * identifier as the buffer itself.  ODP applications MUST NOT make
+ * assumptions about the addressability relationship between a buffer
+ * and its associated meta data, or between meta data items.
+ * Application use of meta data MUST only be via accessor functions.
+ *
+ * @par Note on OPTIONAL APIs
+ * Every conforming ODP implementation MUST
+ * provide implementations for each API described here.  if an API is
+ * designated as OPTIONAL, this means that it is acceptable for an
+ * implementation to do nothing except return
+ * ODP_FUNCTION_NOT_AVAILABLE in response to this call. Note that this
+ * may limit the range of ODP applications supported by a given
+ * implementation since applications needing the functionality of the
+ * optional API will likely choose to deploy on other ODP platforms.
+ *
+ * @par
+ * APIs are designated as OPTIONAL under two conditions:<br><br>
+ *
+ * -# The API is expected to be difficult to provide efficiently on all
+ *  platforms.<br><br>
+ * -# A significant number of ODP applications are expected to exist
+ *  that will not need or use this API.
+ *
+ * @par
+ * Under these circumstances, an API is designated as OPTIONAL to
+ * permit ODP implementations to be conformant while still expecting
+ * to be able to run a significant number of ODP applications.
+ *
  */
 
 #ifndef ODP_BUFFER_H_
@@ -21,10 +102,9 @@  extern "C" {
 
 #include <odp_std_types.h>
 
-
 /** @defgroup odp_buffer ODP BUFFER
- *  Operations on a buffer.
- *  @{
+ *
+ * @{
  */
 
 /**
@@ -32,62 +112,476 @@  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 pool
+ */
+typedef uint32_t odp_buffer_pool_t;
+
+/**
+ * ODP buffer type
+ */
+typedef enum odp_buffer_type {
+	ODP_BUFER_TYPE_INVALID  = -1, /**< Buffer type invalid */
+	ODP_BUFFER_TYPE_ANY     = 0,  /**< Buffer type 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
+ *
+ * @note 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.
+ *
+ * @par Segmented vs. Unsegmented Buffer Pools
+ * By default, the buffers
+ * in ODP buffer pools are logical buffers that support transparent
+ * segmentation managed by ODP on behalf of the application and have a
+ * rich set of associated semantics as described here.
+ * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
+ * for the pool should be regarded as a fixed buffer size for all pool
+ * elements and that segmentation support is not needed for the pool.
+ * This MAY result in greater efficiency on some implementations.  For
+ * packet processing, a typical use of unsegmented pools would be in
+ * conjunction with classification rules that sort packets into
+ * different pools based on their lengths, thus ensuring that each
+ * packet occupies a single segment within an appropriately-sized
+ * buffer.
+ */
+ typedef enum odp_buffer_opts {
+	 ODP_BUFFER_OPTS_NONE,        /**< Default, no buffer options */
+	 ODP_BUFFER_OPTS_UNSEGMENTED, /**< Reqest this pool contain unsegmented
+                                           buffers */
+ } odp_buffer_opts_e;
+
+/**
+ * Error returns
+ */
+#define ODP_BUFFER_INVALID (odp_buffer_t)(-1)
 
 /**
  * Buffer start address
  *
- * @param buf      Buffer handle
+ * @param[in] buf  Buffer handle
  *
  * @return Buffer start address
  */
 void *odp_buffer_addr(odp_buffer_t buf);
 
 /**
- * Buffer maximum data size
+ * Buffer application data size
  *
- * @param buf      Buffer handle
+ * @param[in] buf  Buffer handle
  *
- * @return Buffer maximum data size
+ * @return Buffer application data size
+ *
+ * @note The size returned by this rouine is the size of the
+ * application data contained within the buffer and does not include
+ * any inplementation-defined overhead to support meta data, etc.  ODP
+ * does not define APIs for determining the amount of storage that is
+ * physically allocated by an implementation to support ODP buffers.
  */
 size_t odp_buffer_size(odp_buffer_t buf);
 
 /**
  * Buffer type
  *
- * @param buf      Buffer handle
+ * @param[in] buf    Buffer handle
  *
  * @return Buffer type
  */
-int odp_buffer_type(odp_buffer_t buf);
+odp_buffer_type_e 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 */
+/**
+ * Get address and size of user meta data for 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 for 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.
+ *
+ * @note This is a "fastpath" version of odp_buffer_udata() since it
+ * omits returning the size of the user meta data area.  Callers are
+ * expected to know and honor this limit nonetheless.
+ */
+void *odp_buffer_udata_addr(odp_buffer_t buf);
 
 /**
  * Tests if buffer is valid
  *
- * @param buf      Buffer handle
+ * @param[in] buf    Buffer handle
  *
  * @return 1 if valid, otherwise 0
+ *
+ * @note Since buffer operations typically occur in fastpath sections
+ * of applications, by default most ODP APIs assume that valid buffer
+ * handles are passed to them and results are undefined if this
+ * assumption is not met.  This routine exists to enable an
+ * application to request explicit validation of a buffer handle. It
+ * is understood that the performance of this operation MAY vary
+ * considerably on a per-implementation basis.
  */
 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 then one segment, otherwise 0
+ *
+ * @note This routine behaves identically to the test
+ * odp_buffer_segment_count() > 1, but is potentially more efficient
+ * and represents the preferred method of determining a buffer's
+ * segmentation status.
+ */
+int odp_buffer_is_segmented(odp_buffer_t buf);
+
+/**
  * Print buffer metadata to STDOUT
  *
- * @param buf      Buffer handle
+ * @param[in] buf    Buffer handle
  *
+ * @note This routine is intended for diagnostic use and prints
+ * implementation-defined information concerning the buffer to the ODP
+ * LOG.  It's provision is OPTIONAL.
  */
 void odp_buffer_print(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 handle 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 handle for a buffer segment
+ *
+ * @param[in] buf    Buffer handle
+ * @param[in] seg    Segment identifier of the previous segment
+ *
+ * @return           Segment identifier of next segment or ODP_SEGMENT_INVALID
+ *
+ * @note This routine returns the identifier (odp_buffer_segment_t) of
+ * the next buffer segment in a buffer aggregate.  The input
+ * specifies the buffer and the previous segment identifier.  There are
+ * three use cases for this routine:
+ * @par
+ * -# If the input seg is ODP_SEGMENT_START then the segment identifier returned
+ * is that of the first segment in the buffer.  ODP_SEGMENT_NULL MAY be used
+ * as a synonym for ODP_SEGMENT_START for symmetry if desired.<br><br>
+ * -# If the input seg is not the last segment in the buffer then the
+ * segment handle of the next segment following seg is returned.<br><br>
+ * -# If the input seg is the segment identifier of the last segment in
+ * the buffer then ODP_SEGMENT_NULL is returned.
+ *
+ */
+odp_buffer_segment_t odp_buffer_segment_next(odp_buffer_t buf,
+					     odp_buffer_segment_t seg);
+
+/**
+ * Get addressability for a specified buffer segment
+ *
+ * @param[in] buf     Buffer handle
+ * @param[in] seg     Segment handle of the segment to be mapped
+ * @param[in] seglen  Returned number of bytes in this buffer segment
+ *                    available at the returned address
+ *
+ * @return            Segment start address or NULL
+ *
+ * @note This routine is used to obtain addressability to a segment within
+ * a buffer aggregate at a specified segment identifier.  The returned seglen
+ * indicates the number of bytes addressable at the returned address.
+ */
+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
+ *
+ * @note This routine is used to unmap a buffer segment previously
+ *  mapped by odp_buffer_segment_map().  Following this call,
+ *  applications MUST NOT attempt to reference the segment via any
+ *  pointer returned from a previous odp_buffer_segment_map() call
+ *  referring to it.  It is intended to allow certain NUMA
+ *  architectures to better manage the coherency of mapped segments.
+ *  For non-NUMA architectures this routine will be a no-op.  Note
+ *  that implementations SHOULD implicitly unmap all buffer segments
+ *  whenever a buffer is added to a queue as this indicates that the
+ *  caller is relinquishing control of the buffer.
+ */
+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
+ *
+ * @note This routine is used to obtain addressability to a segment
+ * within a buffer at a specified byte offset.  Note that because the
+ * offset is independent of any implementation-defined physical
+ * segmentation the returned seglen may be “short” and will range from
+ * 1 to whatever physical segment size is used by the underlying
+ * implementation.
+ */
+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
+ *
+ * @note This routine is used to unmap a buffer segment previously
+ * mapped by odp_buffer_offset_map(). Following this call
+ * the application MUST NOT attempt to reference the segment via any
+ * pointer returned by a prior odp_buffer_offset_map() call relating
+ * to this offset.  It is intended to allow certain NUMA architectures
+ * to better manage the coherency of mapped segments.  For non-NUMA
+ * architectures this routine will be a no-op.  Note that
+ * implementations SHOULD implicitly unmap all buffer segments
+ * whenever a buffer is added to a queue as this indicates that the
+ * caller is relinquishing control of the buffer.
+ */
+void odp_buffer_offset_unmap(odp_buffer_t buf, size_t offset);
+
+/**
+ * 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
+ *
+ * @note This routine splits a buffer into two buffers at the
+ * specified byte offset.  The odp_buffer_t returned by the function
+ * is the handle of the new buffer created at the split point.  If the
+ * original buffer was allocated from a buffer pool then the split is
+ * allocated from the same pool.  If the original buffer was size
+ * bytes in length then upon return the original buffer is of size
+ * offset while the split buffer is of size (size-offset).
+ *
+ * @par
+ * This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a matching routine that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ *
+ * @par
+ * Upon return from this function, the system meta data for both
+ * buffers has been updated appropriately by the call since system
+ * meta data maintenance is the responsibility of the ODP
+ * implementation.  Any required updates to the user meta data is the
+ * responsibility of the caller.
+ */
+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
+ *
+ * @note This routine joins two buffers into a single buffer.  Both
+ * buf1 and buf2 MUST be from the same buffer pool and the resulting
+ * joined buffer will be an element of that same pool.  The
+ * application MUST NOT assume that either buf1 or buf2 survive the
+ * join or that the returned joined buffer is contiguous with or
+ * otherwise related to the input buffers.  An implementation SHOULD
+ * free either or both input buffers if they are not reused as part of
+ * the construction of the returned joined buffer.  If the join cannot
+ * be performed (e.g., if the two input buffers are not from the same
+ * buffer pool, insufficient space in the target buffer pool, etc.)
+ * then ODP_BUFFER_INVALID SHOULD be returned to indicate that the
+ * operation could not be performed, and an appropriate errno set.  In
+ * such case the input buffers MUST NOT be freed as part of the failed
+ * join attempt and should be unchanged from their input values and
+ * content.
+ *
+ * @par The result of odp_buffer_join() is the logical concatenation
+ * of the two buffers using an implementation-defined buffer
+ * aggregation mechanism.  The application data contents of the
+ * returned buffer is identical to that of the two joined input
+ * buffers however certain associated meta data (e.g., information
+ * about the buffer size) will likely differ.
+ *
+ * @par If user meta data is present in the buffer pool containing the
+ * input buffers, then the user meta data associated with the returned
+ * buffer MUST be copied by this routine from the source buf1.
+ *
+ * @par This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a routine matching that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ */
+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
+ *
+ * @note This routine discards bytes from the end of a buffer.  It is
+ * logically equivalent to a split followed by a free of the split
+ * portion of the input buffer.  The input offset must be less than or
+ * equal to the odp_buffer_size() of the input buffer.  Upon
+ * successful return the odp_buffer_size() routine would now return
+ * offset as the size of the trimmed buffer.  Note that the returned
+ * odp_buffer_t may not necessarily be the same as the input
+ * odp_buffer_t.  The caller should use the returned value when
+ * referencing the trimmed buffer instead of the original in case they
+ * are different.
+ *
+ * @par If the input buf contains user meta data, then this data MUST
+ * be copied to the returned buffer if needed by the API
+ * implementation.
+ *
+ * @par This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a matching routine that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ */
+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
+ *
+ * @note This routine extends a buffer by increasing its size by ext
+ * bytes.  It is logically equivalent to an odp_buffer_join() of a
+ * buffer of size ext to the original buffer.  Upon successful return
+ * the odp_buffer_size() routine would now return size+ext as the size
+ * of the extended buffer.
+ *
+ * @par Note that the returned odp_buffer_t may not necessarily be the
+ * same as the input odp_buffer_t.  The caller should use the returned
+ * value when referencing the extended buffer instead of the original
+ * in case they are different.  If the input buf contains user meta
+ * data, then this data MUST be copied to the returned buffer if
+ * needed by the API implementation.
+ *
+ * @par This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a matching routine that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ */
+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
+ *
+ * @note This routine allows an ODP buffer to be cloned in an
+ * implementation-defined manner.  The application data contents of
+ * the returned odp_buffer_t is an exact copy of the application data
+ * of the input buffer.  The implementation MAY perform this operation
+ * via reference counts, resegmentation, or any other technique it
+ * wishes to employ. The cloned buffer is an element of the same
+ * buffer pool as the input buf.  If the input buf contains user meta
+ * data, then this data MUST be copied to the returned buffer by the
+ * ODP implementation.
+ *
+ * @par This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a matching routine that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ */
+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
+ * @param[in] pool buffer pool to contain the copied buffer
+ *
+ * @return         Handle of the copied buffer or ODP_BUFFER_INVALID
+ *                 if the operation was not performed
+ *
+ * @note This routine allows an ODP buffer to be copied in an
+ * implementation-defined manner to a specified buffer pool.  The
+ * specified pool may or may not be different from the source buffer’s
+ * pool.  The application data contents of the returned odp_buffer_t
+ * is an exact separate copy of the application data of the input
+ * buffer.  If the input buf contains user meta data, then this data
+ * MUST be copied to the returned buffer by the ODP implementation.
+ *
+ * @par This routine is OPTIONAL.  An implementation that does not
+ * support this function MUST provide a matching routine that simply
+ * returns ODP_BUFFER_INVALID with an errno of
+ * ODP_FUNCTION_NOT_AVAILABLE.
+ */
+odp_buffer_t odp_buffer_copy(odp_buffer_t buf, odp_buffer_pool_t pool);
+
+
+/**
  * @}
  */
 
diff --git a/platform/linux-generic/include/api/odp_buffer_pool.h b/platform/linux-generic/include/api/odp_buffer_pool.h
index d04abf0..cf67c2a 100644
--- a/platform/linux-generic/include/api/odp_buffer_pool.h
+++ b/platform/linux-generic/include/api/odp_buffer_pool.h
@@ -8,7 +8,44 @@ 
 /**
  * @file
  *
- * ODP buffer pool
+ * @par Buffer Pools
+ * Buffers are elements of buffer pools that represent an equivalence
+ * class of buffer objects that are managed by a buffer pool manager.
+ * ODP implementations MAY support buffer pool managers implemented in
+ * hardware, software, or a combination of the two.  An ODP
+ * implementation MUST support at least one buffer pool and MAY
+ * support as many as it wishes.  The implementation MAY support one
+ * or more predefined buffer pools that are not explicitly allocated
+ * by an ODP application.  It SHOULD also support application creation
+ * of buffer pools via the odp_buffer_pool_create() API, however it
+ * MAY restrict the types of buffers that can be so created.
+ *
+ * @par
+ * Buffer pools are represented by the abstract type odp_buffer_pool_t
+ * that is returned by buffer pool creation and lookup/enumeration
+ * routines.  Applications refer to buffer pools via a name of
+ * implementation-defined maximum length that MUST be a minimummap of
+ * eight characters in length and MAY be longer.  It is RECOMMENDED
+ * that 32 character buffer pool names be supported to provide
+ * application naming flexibility.  The supported maximum length of
+ * buffer pool names is exposed via the ODP_BUFFER_POOL_NAME_LEN
+ * predefined implementation limit.
+ *
+ * @par Segmented vs. Unsegmented Buffer Pools
+ * By default, the buffers in
+ * ODP buffer pools are logical buffers that support transparent
+ * segmentation managed by ODP on behalf of the application and have a
+ * rich set of associated semantics as described here.
+ * ODP_BUFFER_OPTS_UNSEGMENTED indicates that the buf_size specified
+ * for the pool should be regarded as a fixed buffer size for all pool
+ * elements and that segmentation support is not needed for the pool.
+ * This MAY result in greater efficiency on some implementations.  For
+ * packet processing, a typical use of unsegmented pools would be in
+ * conjunction with classification rules that sort packets into
+ * different pools based on their lengths, thus ensuring that each
+ * packet occupies a single segment within an appropriately-sized
+ * buffer.
+ *
  */
 
 #ifndef ODP_BUFFER_POOL_H_
@@ -35,42 +72,217 @@  extern "C" {
 #define ODP_BUFFER_POOL_INVALID   0
 
 /** ODP buffer pool */
-typedef uint32_t odp_buffer_pool_t;
+// typedef uint32_t odp_buffer_pool_t;
+
+/**
+ * Buffer initialization routine prototype
+ *
+ * @note Routines of this type MAY be passed as part of the
+ * odp_buffer_pool_init_t structure to be called whenever a
+ * buffer is allocated to initialize the user meta data
+ * associated with that buffer.
+ */
+typedef void (odp_buf_init_t)(odp_buffer_t buf, void *buf_init_arg);
+
+/**
+ * Buffer pool parameters
+ *
+ * @param[in] buf_num    Number of buffers that pool should contain
+ * @param[in] buf_size   Size of application data in each buffer
+ * @param[in] buf_type   Buffer type
+ * @param[in] buf_opts   Buffer options
+ */
+typedef struct odp_buffer_pool_param_t {
+        size_t buf_num;             /**< Number of buffers in this pool */
+	size_t buf_size;            /**< Application data size of each buffer */
+	odp_buffer_type_e buf_type; /**< Buffer type */
+	odp_buffer_opts_e buf_opts; /**< Buffer options */
+} odp_buffer_pool_param_t;          /**< Type of buffer pool parameter struct */
 
+/**
+ * Buffer pool initialization parameters
+ *
+ * @param[in] udata_size     Size of the user meta data for each buffer
+ * @param[in] buf_init       Function pointer to be called to initialize the
+ *                           user meta data for each buffer in the pool.
+ * @param[in] buf_init_arg   Argument to be passed to buf_init().
+ *
+ */
+typedef struct odp_buffer_pool_init_t {
+        size_t udata_size;         /**< Size of user meta dat for each buffer */
+        odp_buf_init_t *buf_init;  /**< Buffer initialization routine to use */
+        void *buf_init_arg;        /**< Argument to be passed to buf_init() */
+} odp_buffer_pool_init_t;          /**< Type of buffer initialization struct */
 
 /**
  * Create a buffer pool
  *
- * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
- * @param base_addr Pool base address
- * @param size      Pool size in bytes
- * @param buf_size  Buffer size in bytes
- * @param buf_align Minimum buffer alignment
- * @param buf_type  Buffer type
+ * @param[in] name           Name of the pool
+ *                           (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
+ *
+ * @param[in] params         Parameters controlling the creation of this
+ *                           buffer pool
+ *
+ * @param[in] init_params    Parameters controlling the initialization of
+ *                           this buffer pool
  *
- * @return Buffer pool handle
+ * @return Buffer pool handle or ODP_BUFFER_POOL_NULL with errno set
+ *
+ * @note This routine is used to create a buffer pool.  It takes three
+ * arguments: the name of the pool to be created, a parameter
+ * structure that controls the pool creation, and an optional
+ * parameter that controls pool initialization.  In the creation
+ * parameter structure, the application specifies the number of
+ * buffers that the pool should contain as well as the application
+ * data size for each buffer in the pool, the type of buffers it
+ * should contain, and their associated options.  In the
+ * initialization parameters, the application specifies the size of
+ * the user meta data that should be associated with each buffer in
+ * the pool.  If no user meta data is required, the init_params SHOULD
+ * be specified as NULL.  If user meta data is requested, then
+ * udata_size SHOULD be set to the requested size of the per-buffer
+ * user meta data.  Also specified is the address of an
+ * application-provided buffer initialization routine to be called for
+ * each buffer in the pool at the time the pool is initialized, or
+ * when the buffer is allocated.  If no application buffer
+ * initialization is needed, then buf_init and buf_init_arg SHOULD be
+ * set to NULL.
  */
 odp_buffer_pool_t odp_buffer_pool_create(const char *name,
-					 void *base_addr, uint64_t size,
-					 size_t buf_size, size_t buf_align,
-					 int buf_type);
-
+                                         odp_buffer_pool_param_t *params,
+                                         odp_buffer_pool_init_t *init_params);
 
 /**
  * Find a buffer pool by name
  *
- * @param name      Name of the pool
+ * @param[in] name  Name of the pool
  *
  * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
  */
 odp_buffer_pool_t odp_buffer_pool_lookup(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] params     Output structure for pool parameters
+ * @param[out] predef     Predefined (1) or Created (0).
+ *
+ * @return                Buffer pool handle
+ *
+ * @note This routine returns the abstract identifier
+ * (odp_buffer_pool_t) of a buffer pool and is used to obtain the list
+ * of all buffer pools.  In this manner an application can discover
+ * both application created and implementation predefined buffer pools
+ * and their characteristics.  The input specifies the previous buffer
+ * pool identifier.  There are three use cases for this
+ * routine:<br><br>
+ *
+ * -# If the input pool is ODP_BUFFER_POOL_START then the buffer pool handle
+ * returned is that of the first buffer pool in the list.
+ * ODP_BUFFER_POOL_NULL MAY be used as a synonym for ODP_BUFFER_POOL_START
+ * if desired.<br><br>
+ *
+ * -# If the input pool is not the last element in the buffer pool list
+ * then the buffer pool handle of the next buffer pool following  pool is
+ * returned.<br><br>
+ *
+ * -# If the input pool is the buffer pool handle of the last buffer pool
+ * in the list then ODP_BUFFER_POOL_NULL is returned.<br><br>
+ *
+ * Returned with the buffer pool handle is the name of the pool as
+ * well as its dimensions, type of buffers it contains, and a flag
+ * that says whether the pool is predefined or was created by the
+ * application.  Note that the buf_size reported for a buffer pool is
+ * simply the declared expected size of the buffers in the pool and
+ * serves only to estimate the total amount of application data that
+ * can be stored in the pool.  Actual sizes of individual buffers
+ * within the pool are dynamic and variable since physical buffer
+ * segments MAY be aggregated to create buffers of arbitrary size (up
+ * to the pool memory limits).  Note that for predefined buffer pools,
+ * some implementations MAY return the physical segment counts and
+ * sizes used to construct the pool as output of this routine.
+ */
+odp_buffer_pool_t odp_buffer_pool_next(odp_buffer_pool_t pool,
+                                       char *name, size_t *udata_size,
+                                       odp_buffer_pool_param_t *params,
+                                       int *predef);
+
+/**
+ * Get the high/low watermarks for a buffer pool
+ *
+ * @param[in]  pool     Handle of the buffer pool
+ * @param[out] high_wm  The high water mark of the designated buffer pool
+ * @param[out] low_wm   The low water mark of the designated buffer pool
+ *
+ * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
+ *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
+ *                 are associated with this buffer pool.
+ *
+ * @note This routine gets the high/low watermarks associated with a
+ * given buffer pool.  If the buffer pool does not have or support
+ * watermarks then an error will be returned and both high_wm and
+ * low_wm will be unchanged.
+ *
+ * @par
+ * It is RECOMMENDED that buffer pools of all types support the setting
+ * and getting of watermarks for use in flow control processing.
+ * Watermarks are designed to trigger flow control actions based on
+ * utilization levels of a buffer pool.  When the number of free
+ * buffers in the buffer pool hits the configured low watermark for
+ * the pool, the pool asserts a low watermark condition and an
+ * implementation-defined action in response to this condition is
+ * triggered.  Once in a low watermark state, the condition is
+ * maintained until the number of free buffers reaches the configured
+ * high watermark.  At this point the low watermark condition is
+ * deasserted and normal pool processing resumes.  Having separate
+ * high and low watermarks permits configurable hysteresis to avoid
+ * jitter in handling transient buffer shortages in the pool.
+ *
+ * @par
+ * In general, two types of actions are common.  The first is to
+ * control Random Early Detection (RED) or Weighted RED (WRED)
+ * processing for the pool, while the second is to control IEEE
+ * 802.1Qbb priority-based flow control (PFC) processing for so-called
+ * “lossless Ethernet” support.  The use of watermarks for flow
+ * control processing is most often used for pools containing packets
+ * and this is discussed in further detail in the Class of Service
+ * (CoS) ODP Classification APIs.
+ *
+ */
+int odp_buffer_pool_watermarks(odp_buffer_pool_t pool,
+                               size_t *high_wm, size_t *low_wm);
+
+/**
+ * Set the high/low watermarks for a buffer pool
+ *
+ * @param[in] pool      Handle of the buffer pool
+ * @param[in] high_wm   The high water mark of the designated buffer pool
+ * @param[in] low_wm    The low water mark of the designated buffer pool
+ *
+ * @return Success or ODP_BUFFER_POOL_INVALID if pool is unknown
+ *                 or ODP_BUFFER_POOL_NO_WATERMARKS if no watermarks
+ *                 are associated with this buffer pool.
+ *
+ * @note This routine sets the high/low watermarks associated with a
+ * specified buffer pool.  If the buffer pool does not support
+ * watermarks then errno ODP_BUFFER_POOL_NO_WATERMARKS is set and no
+ * function is performed.
+ */
+int odp_buffer_pool_set_watermarks(odp_buffer_pool_t pool,
+                                   size_t high_wm, size_t low_wm);
 
 /**
  * Print buffer pool info
  *
- * @param pool      Pool handle
+ * @param[in] pool   Pool handle
  *
+ * @note This is a diagnostic routine that prints statistics regarding
+ * the specified buffer pool to the ODP LOG.  This routine is OPTIONAL
+ * and if present its output is implementation-defined.
  */
 void odp_buffer_pool_print(odp_buffer_pool_t pool);