From patchwork Mon Nov 3 03:06:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Bill Fischofer X-Patchwork-Id: 39997 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f69.google.com (mail-la0-f69.google.com [209.85.215.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id CC7E52405B for ; Mon, 3 Nov 2014 03:07:03 +0000 (UTC) Received: by mail-la0-f69.google.com with SMTP id q1sf5744817lam.4 for ; Sun, 02 Nov 2014 19:07:02 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id :mime-version:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=LPDClmceaMt7h326P1QjU9ZvKi6pj79IAaLG39Dvw94=; b=AvJUKtbqy8EwmElMK/dh+oxbU4hmKDle1h61yfpGrd6ADABadFnRReukPT7XllTryE LVPj1UEqVHtFgkfoM7PTRzm8/QVVYQv3pq8qyclSnL/Yqx5BiP5zl6uWiu6zhPxR8J3Y Nos9s3X1VEAOYBxh5sMv24xVKPI+wCxnWHhjqzb5oUWpFrxvFwx1RbLnXLrBZYKUTKV9 000I6LcG6HhyA6NV1li0ciTdP+CcUuo1hiMlJhtWNMr4lkegR760Px6emNDkAMAj7nmi s6AR7XeOT3YHGJ4npWbdlEVUw1d9oRdr0jzLCVYsGWgCB9FIhBh9ZpJp4HJme9n4hrEG itnQ== X-Gm-Message-State: ALoCoQmFrAX5NRk9JR67/G0OPgizaY9MzjWqiZ2b9gj7mgvqTMHWgfVoZwSP5pB2S0e1RbIPuNHS X-Received: by 10.180.182.164 with SMTP id ef4mr2298475wic.0.1414984022680; Sun, 02 Nov 2014 19:07:02 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.37.226 with SMTP id b2ls645117lak.36.gmail; Sun, 02 Nov 2014 19:07:02 -0800 (PST) X-Received: by 10.112.52.37 with SMTP id q5mr11737202lbo.32.1414984022219; Sun, 02 Nov 2014 19:07:02 -0800 (PST) Received: from mail-lb0-f182.google.com (mail-lb0-f182.google.com. [209.85.217.182]) by mx.google.com with ESMTPS id jw6si30503773lbc.101.2014.11.02.19.07.02 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 02 Nov 2014 19:07:02 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.182 as permitted sender) client-ip=209.85.217.182; Received: by mail-lb0-f182.google.com with SMTP id f15so9365439lbj.41 for ; Sun, 02 Nov 2014 19:07:02 -0800 (PST) X-Received: by 10.112.77.74 with SMTP id q10mr46921261lbw.66.1414984022014; Sun, 02 Nov 2014 19:07:02 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.84.229 with SMTP id c5csp182452lbz; Sun, 2 Nov 2014 19:07:00 -0800 (PST) X-Received: by 10.224.23.67 with SMTP id q3mr59199671qab.92.1414984019777; Sun, 02 Nov 2014 19:06:59 -0800 (PST) Received: from ip-10-35-177-41.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id l5si1462757qat.15.2014.11.02.19.06.58 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 02 Nov 2014 19:06:59 -0800 (PST) Received-SPF: none (google.com: lng-odp-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-35-177-41.ec2.internal) by ip-10-35-177-41.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Xl7yq-00034T-DS; Mon, 03 Nov 2014 03:06:56 +0000 Received: from mail-oi0-f53.google.com ([209.85.218.53]) by ip-10-35-177-41.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Xl7yj-00034G-Dj for lng-odp@lists.linaro.org; Mon, 03 Nov 2014 03:06:49 +0000 Received: by mail-oi0-f53.google.com with SMTP id a141so6319465oig.26 for ; Sun, 02 Nov 2014 19:06:44 -0800 (PST) X-Received: by 10.202.206.69 with SMTP id e66mr132653oig.64.1414984004002; Sun, 02 Nov 2014 19:06:44 -0800 (PST) Received: from localhost.localdomain (cpe-24-28-70-239.austin.res.rr.com. [24.28.70.239]) by mx.google.com with ESMTPSA id c76sm7368895oih.28.2014.11.02.19.06.43 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 02 Nov 2014 19:06:43 -0800 (PST) From: Bill Fischofer To: lng-odp@lists.linaro.org Date: Sun, 2 Nov 2014 21:06:33 -0600 Message-Id: <1414983993-31343-1-git-send-email-bill.fischofer@linaro.org> X-Mailer: git-send-email 1.8.3.2 MIME-Version: 1.0 X-Topics: patch Subject: [lng-odp] [[RFC PATCH]] RFC for new buffer .h files X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: lng-odp-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: bill.fischofer@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.182 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 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 --- 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:

+ * + * - ODP_BUFFER_TYPE_RAW
+ * This is the “basic” buffer type + * which simply consists of a single fixed-sized block of contiguous + * memory. Buffers of this type do not support user meta data and the + * only built-in meta data supported for this type of buffer are those + * that are statically computable, such as pool and size. This type of + * buffer is entirely under application control and most of the buffer + * APIs defined in this document are not available. APIs for this + * type of buffer are described in this document.

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

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

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

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

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

+ * -# If the input seg is not the last segment in the buffer then the + * segment handle of the next segment following seg is returned.

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

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

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

+ * + * -# If the input pool is the buffer pool handle of the last buffer pool + * in the list then ODP_BUFFER_POOL_NULL is returned.

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