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 <[email protected]> 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: [email protected], Web: http://www.ezchip.com > > > > *"Ethernet always wins."* > > — Andy Bechtolsheim > > > > *From:* [email protected] [mailto: > [email protected]] *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 <[email protected]> > 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 <[email protected]> > --- > 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 > [email protected] > http://lists.linaro.org/mailman/listinfo/lng-odp > > > > > > -- > > *Mike Holmes* > > Linaro Sr Technical Manager > > LNG - ODP >
_______________________________________________ lng-odp mailing list [email protected] http://lists.linaro.org/mailman/listinfo/lng-odp
